hdk/common/lib/aws_clk_regs.sv (269 lines of code) (raw):

// ============================================================================ // Amazon FPGA Hardware Development Kit // // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. // // Licensed under the Amazon Software License (the "License"). You may not use // this file except in compliance with the License. A copy of the License is // located at // // http://aws.amazon.com/asl/ // // or in the "license" file accompanying this file. This file is distributed on // an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or // implied. See the License for the specific language governing permissions and // limitations under the License. // ============================================================================ // Module // ------- // AWS_CLK_REGS // // Description // ----------- // * Houses all the Control/Status Regs for AWS_CLK_GEN design // /////////////////////////////////////////////////////////////////////////////////// module aws_clk_regs #( parameter CLK_GRP_A_EN = 1, parameter CLK_GRP_B_EN = 1, parameter CLK_GRP_C_EN = 1, parameter CLK_HBM_EN = 1, parameter MAX_NUM_CLKS = 10 //Max number of clocks supported ) ( input logic i_clk, input logic i_rst_n, input logic [31:0] s_axil_awaddr, input logic s_axil_awvalid, output logic s_axil_awready, input logic [31:0] s_axil_wdata, input logic [3:0] s_axil_wstrb, input logic s_axil_wvalid, output logic s_axil_wready, output logic [1:0] s_axil_bresp, output logic s_axil_bvalid, input logic s_axil_bready, input logic [31:0] s_axil_araddr, input logic s_axil_arvalid, output logic s_axil_arready, output logic [31:0] s_axil_rdata, output logic [1:0] s_axil_rresp, output logic s_axil_rvalid, input logic s_axil_rready, input logic i_mmcm_a_lock, input logic i_mmcm_b_lock, input logic i_mmcm_c_lock, input logic i_mmcm_hbm_lock, output logic o_glbl_rst = '0, output logic o_cl_rst_hbm_axi_n = '0, output logic o_cl_rst_hbm_ref_n = '0, output logic o_cl_rst_c1_n = '0, output logic o_cl_rst_c0_n = '0, output logic o_cl_rst_b1_n = '0, output logic o_cl_rst_b0_n = '0, output logic o_cl_rst_a3_n = '0, output logic o_cl_rst_a2_n = '0, output logic o_cl_rst_a1_n = '0, output logic o_cl_rst_main_n = '0 ); //=================================================================== // AXI-L to CFG convert //=================================================================== axil_bus_t s_axil_bus(); cfg_bus_t cfg_bus(); always_comb begin //{ s_axil_bus.awaddr = s_axil_awaddr; s_axil_bus.awvalid = s_axil_awvalid; s_axil_awready = s_axil_bus.awready; s_axil_bus.wdata = s_axil_wdata; s_axil_bus.wstrb = s_axil_wstrb; s_axil_bus.wvalid = s_axil_wvalid; s_axil_wready = s_axil_bus.wready; s_axil_bresp = s_axil_bus.bresp; s_axil_bvalid = s_axil_bus.bvalid; s_axil_bus.bready = s_axil_bready; s_axil_bus.araddr = s_axil_araddr; s_axil_bus.arvalid = s_axil_arvalid; s_axil_arready = s_axil_bus.arready; s_axil_rdata = s_axil_bus.rdata; s_axil_rresp = s_axil_bus.rresp; s_axil_rvalid = s_axil_bus.rvalid; s_axil_bus.rready = s_axil_rready; end //} // AXIL to CFG convertor axil_to_cfg_cnv #( .ADDR_WIDTH (32), .DATA_WIDTH (32) ) AXIL_TO_CFG_CNV_I ( .clk (i_clk ), .rst_n (i_rst_n ), .s_axil_bus (s_axil_bus ), .m_cfg_bus (cfg_bus ), .o_fsm_busy ( ) ); //=================================================================== // CFG WR/RD reqs //=================================================================== logic [7:0] cfg_addr_q = '0; logic cfg_wr_q = '0; logic cfg_rd_q = '0; logic cfg_wr_pulse_q = '0; logic cfg_rd_pulse_q = '0; logic [31:0] cfg_rdata_q = '0; logic [31:0] cfg_wdata_q = '0; always_ff @(posedge i_clk) if (!i_rst_n) begin //{ cfg_wr_q <= '0; cfg_rd_q <= '0; end //} else begin //{ cfg_wr_q <= cfg_bus.wr; cfg_rd_q <= cfg_bus.rd; cfg_addr_q <= cfg_bus.addr[0+:$bits(cfg_addr_q)]; cfg_wdata_q <= cfg_bus.wdata; cfg_wr_pulse_q <= ~cfg_wr_q & cfg_bus.wr; cfg_rd_pulse_q <= ~cfg_rd_q & cfg_bus.rd; end //} always_ff @(posedge i_clk) if (!i_rst_n) cfg_bus.ack <= '0; else cfg_bus.ack <= cfg_wr_pulse_q | cfg_rd_pulse_q; assign cfg_bus.rdata = cfg_rdata_q; //=================================================================== // CSRs //=================================================================== localparam ID_REG = 8'h00; localparam VER_REG = 8'h04; localparam BUILD_REG = 8'h08; localparam CLKS_AVAIL_REG = 8'h0C; localparam G_RST_REG = 8'h10; localparam SYS_RST_REG = 8'h14; localparam DIS_RST_MAIN_REG = 8'h18; localparam MMCM_LOCK_REG = 8'h20; localparam MMCM_LOCK_ERR_REG = 8'h24; logic [31:0] id_reg = '0; logic [31:0] ver_reg = '0; logic [31:0] build_reg = '0; logic [31:0] clks_avail_reg = '0; logic [31:0] g_rst_reg = '0; logic [31:0] sys_rst_reg = 32'hFFFF_FFFE; logic dis_rst_main_reg = '0; logic [31:0] mmcm_lock_reg = '0; logic [31:0] mmcm_lock_err_reg = '0; //=================================================================== // Read Datapath //=================================================================== always_ff @(posedge i_clk) unique case (cfg_addr_q) //{ ID_REG : cfg_rdata_q <= id_reg; VER_REG : cfg_rdata_q <= ver_reg; BUILD_REG : cfg_rdata_q <= build_reg; CLKS_AVAIL_REG : cfg_rdata_q <= clks_avail_reg; G_RST_REG : cfg_rdata_q <= g_rst_reg; SYS_RST_REG : cfg_rdata_q <= sys_rst_reg; DIS_RST_MAIN_REG : cfg_rdata_q <= 32'(dis_rst_main_reg); MMCM_LOCK_REG : cfg_rdata_q <= mmcm_lock_reg; MMCM_LOCK_ERR_REG : cfg_rdata_q <= mmcm_lock_err_reg; default : cfg_rdata_q <= 32'hBAAD_DEC0; endcase // unique case (cfg_addr_q) } always_comb begin //{ id_reg = 32'h9048_1D0F; // AWS unique ID ver_reg = 32'h02_01_00_00; // Arch, Major, Minor, Maintenance version build_reg = 32'h09_23_22_23; clks_avail_reg = { 23'd0, // Reserved 1'(CLK_HBM_EN), // 1 = clk_hbm_axi available | 0 = clock unavilable 1'(CLK_GRP_C_EN), // 1 = clk_extra_c1 available | 0 = clock unavilable 1'(CLK_GRP_C_EN), // 1 = clk_extra_c0 available | 0 = clock unavilable 1'(CLK_GRP_B_EN), // 1 = clk_extra_b1 available | 0 = clock unavilable 1'(CLK_GRP_B_EN), // 1 = clk_extra_b0 available | 0 = clock unavilable 1'(CLK_GRP_A_EN), // 1 = clk_extra_a3 available | 0 = clock unavilable 1'(CLK_GRP_A_EN), // 1 = clk_extra_a2 available | 0 = clock unavilable 1'(CLK_GRP_A_EN), // 1 = clk_extra_a1 available | 0 = clock unavilable 1'b1 }; // 1 = clk_main_a0 available | 0 = clock unavilable end //} //=================================================================== // Writes //=================================================================== always_ff @(posedge i_clk) begin //{ if ((cfg_addr_q == G_RST_REG) && cfg_wr_pulse_q) g_rst_reg <= cfg_wdata_q; if ((cfg_addr_q == SYS_RST_REG) && cfg_wr_pulse_q) sys_rst_reg <= cfg_wdata_q; if ((cfg_addr_q == DIS_RST_MAIN_REG) && cfg_wr_pulse_q) dis_rst_main_reg <= cfg_wdata_q[0]; if ((cfg_addr_q == MMCM_LOCK_ERR_REG) && cfg_wr_pulse_q) mmcm_lock_err_reg <= mmcm_lock_err_reg & ~cfg_wdata_q; // Write 1 to Clear end //} //=================================================================== // Reset Outputs //=================================================================== always_ff @(posedge i_clk) o_glbl_rst <= (g_rst_reg == '1); logic [31:0] rst_out_n = '0; //=================================================================== // Reset truth table // ----------------- // o_glbl_rst | sys_rst_reg | dis_rst_main_reg | i_rst_n | Output // --------------------------------------------------------------- // 1 | X | X | X | 0 // 0 | 1 | X | X | 0 // 0 | 0 | 0 | 0 | 0 // 0 | 0 | 0 | 1 | 1 // 0 | 0 | 1 | X | 1 // 0 | 0 | 1 | X | 1 //=================================================================== always_ff @(posedge i_clk) for (int gg = 0; gg < MAX_NUM_CLKS; gg++) rst_out_n[gg] <= ~o_glbl_rst & ~sys_rst_reg[gg] & (dis_rst_main_reg | i_rst_n); always_comb begin : RST_OUT_I //{ o_cl_rst_hbm_axi_n = rst_out_n[9]; o_cl_rst_hbm_ref_n = rst_out_n[8]; o_cl_rst_c1_n = rst_out_n[7]; o_cl_rst_c0_n = rst_out_n[6]; o_cl_rst_b1_n = rst_out_n[5]; o_cl_rst_b0_n = rst_out_n[4]; o_cl_rst_a3_n = rst_out_n[3]; o_cl_rst_a2_n = rst_out_n[2]; o_cl_rst_a1_n = rst_out_n[1]; o_cl_rst_main_n = rst_out_n[0]; end : RST_OUT_I //} //========================================================================== // MMCM Lock //========================================================================== logic [3:0] mmcm_lock_in; logic [3:0] mmcm_lock_syncd; assign mmcm_lock_in = {i_mmcm_hbm_lock, i_mmcm_c_lock, i_mmcm_b_lock, i_mmcm_a_lock}; generate //{ for (genvar jj = 0; jj < $bits(mmcm_lock_in); jj++) begin : MMCM_LOCK_SYNC_I //{ xpm_cdc_single #( .DEST_SYNC_FF (2), .INIT_SYNC_FF (0), .SIM_ASSERT_CHK (0), .SRC_INPUT_REG (0) ) CDC_XPM_SINGLE ( .src_clk (i_clk ), .src_in (mmcm_lock_in[jj] ), .dest_clk (i_clk ), .dest_out (mmcm_lock_syncd[jj] ) ); end : MMCM_LOCK_SYNC_I//} endgenerate //} // // MMCM_LOCK_REG // always_comb begin //{ mmcm_lock_reg = '0; mmcm_lock_reg[0] = mmcm_lock_syncd[0]; // MMCM-A locked mmcm_lock_reg[4] = mmcm_lock_syncd[1]; // MMCM-B locked mmcm_lock_reg[6] = mmcm_lock_syncd[2]; // MMCM-C locked mmcm_lock_reg[8] = mmcm_lock_syncd[3]; // MMCM-HBM locked end //} endmodule // aws_clk_regs