diff --git a/src/ahb_lite_bus/rtl/ahb_lite_2to1_mux.sv b/src/ahb_lite_bus/rtl/ahb_lite_2to1_mux.sv index b5963adcf..7330bef19 100644 --- a/src/ahb_lite_bus/rtl/ahb_lite_2to1_mux.sv +++ b/src/ahb_lite_bus/rtl/ahb_lite_2to1_mux.sv @@ -29,6 +29,7 @@ module ahb_lite_2to1_mux #( // --------------------------------------- input logic hclk, input logic hreset_n, + input logic force_bus_idle, // --------------------------------------- // From Initiator 0 @@ -81,7 +82,9 @@ module ahb_lite_2to1_mux #( //Initiator 0 always takes priority logic initiator0_address_ph, initiator1_address_ph; +logic initiator0_data_ph_nq, initiator1_data_ph_nq; logic initiator0_data_ph, initiator1_data_ph; +logic initiator0_pend_addr_ph_nq, initiator1_pend_addr_ph_nq; logic initiator0_pend_addr_ph, initiator1_pend_addr_ph; logic initiator0_gnt, initiator1_gnt; logic [AHB_LITE_ADDR_WIDTH-1:0] initiator0_pend_haddr, initiator1_pend_haddr; @@ -94,8 +97,8 @@ logic initiator0_pend_hwrite, initiator1_pend_hwrite; logic initiator0_hwrite, initiator1_hwrite; //Detect address phase -always_comb initiator0_address_ph = hsel_i_0 & hready_i_0 & htrans_i_0 inside {2'b10, 2'b11}; -always_comb initiator1_address_ph = hsel_i_1 & hready_i_1 & htrans_i_1 inside {2'b10, 2'b11}; +always_comb initiator0_address_ph = hsel_i_0 & hready_i_0 & htrans_i_0 inside {2'b10, 2'b11} & ~force_bus_idle; +always_comb initiator1_address_ph = hsel_i_1 & hready_i_1 & htrans_i_1 inside {2'b10, 2'b11} & ~force_bus_idle; always_ff @(posedge hclk or negedge hreset_n) begin if (~hreset_n) begin @@ -107,10 +110,10 @@ always_ff @(posedge hclk or negedge hreset_n) begin initiator1_pend_hsize <= '0; initiator0_pend_hwrite <= '0; initiator1_pend_hwrite <= '0; - initiator0_pend_addr_ph <= '0; - initiator1_pend_addr_ph <= '0; - initiator0_data_ph <= '0; - initiator1_data_ph <= '0; + initiator0_pend_addr_ph_nq <= '0; + initiator1_pend_addr_ph_nq <= '0; + initiator0_data_ph_nq <= '0; + initiator1_data_ph_nq <= '0; end else begin //Capture the address during the address phase for each initiator @@ -124,15 +127,20 @@ always_ff @(posedge hclk or negedge hreset_n) begin initiator1_pend_hwrite <= initiator1_address_ph & ~initiator1_pend_addr_ph ? hwrite_i_1 : initiator1_pend_hwrite; //Capture pending address phase when initiators collide - initiator0_pend_addr_ph <= (initiator0_address_ph | initiator0_pend_addr_ph) & ~(hreadyout_i & initiator0_gnt); - initiator1_pend_addr_ph <= (initiator1_address_ph | initiator1_pend_addr_ph) & ~(hreadyout_i & initiator1_gnt); + initiator0_pend_addr_ph_nq <= (initiator0_address_ph | initiator0_pend_addr_ph) & ~(hreadyout_i & initiator0_gnt); + initiator1_pend_addr_ph_nq <= (initiator1_address_ph | initiator1_pend_addr_ph) & ~(hreadyout_i & initiator1_gnt); //Transition to data phase when endpoint accepts address phase, hold when not ready - initiator0_data_ph <= (initiator0_gnt) | (initiator0_data_ph & ~hreadyout_i); - initiator1_data_ph <= (initiator1_gnt) | (initiator1_data_ph & ~hreadyout_i); + initiator0_data_ph_nq <= (initiator0_gnt) | (initiator0_data_ph & ~hreadyout_i); + initiator1_data_ph_nq <= (initiator1_gnt) | (initiator1_data_ph & ~hreadyout_i); end end +always_comb initiator0_data_ph = initiator0_data_ph_nq & ~force_bus_idle; +always_comb initiator1_data_ph = initiator1_data_ph_nq & ~force_bus_idle; +always_comb initiator0_pend_addr_ph = initiator0_pend_addr_ph_nq & ~force_bus_idle; +always_comb initiator1_pend_addr_ph = initiator1_pend_addr_ph_nq & ~force_bus_idle; + always_comb initiator0_haddr = initiator0_pend_addr_ph ? initiator0_pend_haddr : haddr_i_0; always_comb initiator0_htrans = initiator0_pend_addr_ph ? initiator0_pend_htrans : htrans_i_0; always_comb initiator0_hsize = initiator0_pend_addr_ph ? initiator0_pend_hsize : hsize_i_0; diff --git a/src/ahb_lite_bus/rtl/ahb_lite_address_decoder.sv b/src/ahb_lite_bus/rtl/ahb_lite_address_decoder.sv index 4a1128e3f..918529300 100644 --- a/src/ahb_lite_bus/rtl/ahb_lite_address_decoder.sv +++ b/src/ahb_lite_bus/rtl/ahb_lite_address_decoder.sv @@ -27,7 +27,7 @@ module ahb_lite_address_decoder #( // --------------------------------------- input logic hclk, input logic hreset_n, - + input logic force_bus_idle, // --------------------------------------- // From Initiator Interface Port // --------------------------------------- @@ -56,8 +56,6 @@ module ahb_lite_address_decoder #( output logic [NUM_RESPONDERS-1:0][1:0] htrans_o, output logic [NUM_RESPONDERS-1:0][2:0] hsize_o, - input logic force_bus_idle, - // ---------------------------------------------- // Responder Disable // ---------------------------------------------- diff --git a/src/integration/rtl/caliptra_top.sv b/src/integration/rtl/caliptra_top.sv index b100bcb39..83aab863c 100755 --- a/src/integration/rtl/caliptra_top.sv +++ b/src/integration/rtl/caliptra_top.sv @@ -407,7 +407,7 @@ el2_veer_wrapper rvtop ( .rst_l ( cptra_uc_rst_b), `endif .dbg_rst_l ( cptra_pwrgood), - .clk ( clk ), + .clk ( rdc_clk_cg ), .rst_vec ( reset_vector[31:1]), .nmi_int ( nmi_int ), .nmi_vec ( nmi_vector[31:1]), @@ -553,9 +553,9 @@ el2_veer_wrapper rvtop ( ) u_sb_lsu_ahb_mux ( .hclk (clk_cg), .hreset_n (cptra_noncore_rst_b), - + .force_bus_idle (fw_update_rst_window), // Initiator 0 - .hsel_i_0 (~fw_update_rst_window), + .hsel_i_0 (1'b1 ), .haddr_i_0 (lsu_ahb.haddr ), .hwdata_i_0 (lsu_ahb.hwdata), .hwrite_i_0 (lsu_ahb.hwrite), @@ -567,7 +567,7 @@ el2_veer_wrapper rvtop ( .hrdata_o_0 (lsu_ahb.hrdata), // Initiator 1 - .hsel_i_1 (~fw_update_rst_window), + .hsel_i_1 (1'b1 ), .haddr_i_1 (sb_ahb.haddr ), .hwdata_i_1 (sb_ahb.hwdata ), .hwrite_i_1 (sb_ahb.hwrite ), @@ -653,6 +653,7 @@ ahb_lite_2to1_mux #( ) u_ahb_lite_2to1_mux ( .hclk (clk_cg), .hreset_n (cptra_uc_rst_b), + .force_bus_idle (fw_update_rst_window), // From Initiator 0 // Inputs .hsel_i_0 (responder_inst[`CALIPTRA_SLAVE_SEL_IMEM].hsel), diff --git a/src/soc_ifc/rtl/soc_ifc_boot_fsm.sv b/src/soc_ifc/rtl/soc_ifc_boot_fsm.sv index eee1cbdbe..70442363a 100644 --- a/src/soc_ifc/rtl/soc_ifc_boot_fsm.sv +++ b/src/soc_ifc/rtl/soc_ifc_boot_fsm.sv @@ -65,10 +65,11 @@ logic [7:0] wait_count; logic wait_count_rst; logic wait_count_decr; -logic cptra_rst_window,cptra_rst_window_f,cptra_rst_window_ff; +logic cptra_rst_window,cptra_rst_window_f; +logic cptra_rst_window_2f, cptra_rst_window_3f, cptra_rst_window_4f; //move to fuse state when SoC de-asserts reset -always_comb arc_BOOT_IDLE_BOOT_FUSE = (boot_fsm_ps == BOOT_IDLE) & ~cptra_rst_window; +always_comb arc_BOOT_IDLE_BOOT_FUSE = (boot_fsm_ps == BOOT_IDLE) & ~cptra_rst_window_f; //move from fuse state to done when fuse done register is set OR //if it was already set (since its locked across warm reset), that the write was observed from SOC always_comb arc_BOOT_FUSE_BOOT_DONE = fuse_done & fuse_wr_done_observed; @@ -79,12 +80,13 @@ always_comb arc_BOOT_FUSE_BOOT_WAIT = BootFSM_BrkPoint; //dummy arc for terminal state lint check always_comb arc_BOOT_DONE_BOOT_IDLE = '0; -always_comb arc_IDLE = cptra_rst_window; +always_comb arc_IDLE = cptra_rst_window_2f; //Masks combo paths from uc reset flops into other reset domains always_comb fw_update_rst_window = boot_fsm_ps inside {BOOT_FW_RST,BOOT_WAIT}; //clock gate all flops on warm reset to prevent RDC metastability issues -always_comb rdc_clk_dis = cptra_rst_window | cptra_rst_window_f | cptra_rst_window_ff; +//cover 2 clocks after synchronized reset assertion (cptra_rst_window_2f) to handle bootfsm transitions +always_comb rdc_clk_dis = cptra_rst_window_2f | cptra_rst_window_3f | cptra_rst_window_4f; //move to rst state when reg bit is set to 1. This state will assert fw_rst to uc always_comb arc_BOOT_DONE_BOOT_FWRST = (boot_fsm_ps == BOOT_DONE) & fw_update_rst; @@ -108,7 +110,7 @@ always_comb begin wait_count_decr = 0; wait_count_rst = 0; - unique casez (boot_fsm_ps) + unique case (boot_fsm_ps) inside BOOT_IDLE: begin if (arc_BOOT_IDLE_BOOT_FUSE) begin boot_fsm_ns = BOOT_FUSE; @@ -188,6 +190,16 @@ always_comb begin wait_count_rst = 0; wait_count_decr = 0; end + default: begin + boot_fsm_ns = boot_fsm_ps; + ready_for_fuses = '0; + fw_upd_rst_executed = '0; + fsm_synch_noncore_rst_b = '0; + fsm_iccm_unlock = '0; + fsm_synch_uc_rst_b = '0; + wait_count_decr = 0; + wait_count_rst = 0; + end endcase end @@ -200,6 +212,10 @@ always_ff @(posedge clk or negedge cptra_pwrgood) begin synch_uc_rst_b <= 0; cptra_noncore_rst_b <= '0; cptra_uc_rst_b <= '0; + cptra_rst_window_f <= '1; + cptra_rst_window_2f <= '1; + cptra_rst_window_3f <= '1; + cptra_rst_window_4f <= '1; end else begin boot_fsm_ps <= arc_IDLE ? BOOT_IDLE : boot_fsm_ns; @@ -207,6 +223,11 @@ always_ff @(posedge clk or negedge cptra_pwrgood) begin synch_uc_rst_b <= fsm_synch_uc_rst_b; cptra_noncore_rst_b <= synch_noncore_rst_b; cptra_uc_rst_b <= synch_noncore_rst_b && synch_uc_rst_b; //uc comes out of rst only when both global and fw rsts are deasserted (through 2FF sync) + + cptra_rst_window_f <= cptra_rst_window; + cptra_rst_window_2f <= cptra_rst_window_f; + cptra_rst_window_3f <= cptra_rst_window_2f; + cptra_rst_window_4f <= cptra_rst_window_3f; end end @@ -214,15 +235,11 @@ end always_ff @(posedge clk or negedge cptra_rst_b) begin if (~cptra_rst_b) begin cptra_rst_window <= '1; - cptra_rst_window_f <= '1; - cptra_rst_window_ff <= '1; wait_count <= '0; iccm_unlock <= 0; end else begin cptra_rst_window <= 0; - cptra_rst_window_f <= cptra_rst_window; - cptra_rst_window_ff <= cptra_rst_window_f; wait_count <= (wait_count_decr && (wait_count != '0)) ? wait_count - 1 : wait_count_rst ? fw_update_rst_wait_cycles : diff --git a/src/soc_ifc/rtl/soc_ifc_external_reg.rdl b/src/soc_ifc/rtl/soc_ifc_external_reg.rdl index ca0529e0f..2fec0e008 100644 --- a/src/soc_ifc/rtl/soc_ifc_external_reg.rdl +++ b/src/soc_ifc/rtl/soc_ifc_external_reg.rdl @@ -348,7 +348,7 @@ reg { [br]Caliptra Access: RW [br]SOC Access: RW [br]Read-Only once locked by FUSE_PAUSER_LOCK."; - field {sw=rw; hw=r; swwel; resetsignal = cptra_rst_b;} PAUSER[32]=0xFFFF_FFFF; + field {sw=rw; hw=r; swwel; resetsignal = cptra_pwrgood;} PAUSER[32]=0xFFFF_FFFF; } CPTRA_FUSE_VALID_PAUSER; reg { @@ -360,5 +360,5 @@ reg { [br]Caliptra Access: RW [br]SOC Access: RW [br]Read-Only once locked."; - field {sw=rw; hw=r; swwel; resetsignal=cptra_rst_b;} LOCK=0; + field {sw=rw; hw=r; swwel; resetsignal=cptra_pwrgood;} LOCK=0; } CPTRA_FUSE_PAUSER_LOCK; diff --git a/src/soc_ifc/rtl/soc_ifc_reg.sv b/src/soc_ifc/rtl/soc_ifc_reg.sv index fb6f0a13a..99780787f 100644 --- a/src/soc_ifc/rtl/soc_ifc_reg.sv +++ b/src/soc_ifc/rtl/soc_ifc_reg.sv @@ -2736,8 +2736,8 @@ module soc_ifc_reg ( field_combo.CPTRA_FUSE_VALID_PAUSER.PAUSER.next = next_c; field_combo.CPTRA_FUSE_VALID_PAUSER.PAUSER.load_next = load_next_c; end - always_ff @(posedge clk or negedge hwif_in.cptra_rst_b) begin - if(~hwif_in.cptra_rst_b) begin + always_ff @(posedge clk or negedge hwif_in.cptra_pwrgood) begin + if(~hwif_in.cptra_pwrgood) begin field_storage.CPTRA_FUSE_VALID_PAUSER.PAUSER.value <= 'hffffffff; end else if(field_combo.CPTRA_FUSE_VALID_PAUSER.PAUSER.load_next) begin field_storage.CPTRA_FUSE_VALID_PAUSER.PAUSER.value <= field_combo.CPTRA_FUSE_VALID_PAUSER.PAUSER.next; @@ -2755,8 +2755,8 @@ module soc_ifc_reg ( field_combo.CPTRA_FUSE_PAUSER_LOCK.LOCK.next = next_c; field_combo.CPTRA_FUSE_PAUSER_LOCK.LOCK.load_next = load_next_c; end - always_ff @(posedge clk or negedge hwif_in.cptra_rst_b) begin - if(~hwif_in.cptra_rst_b) begin + always_ff @(posedge clk or negedge hwif_in.cptra_pwrgood) begin + if(~hwif_in.cptra_pwrgood) begin field_storage.CPTRA_FUSE_PAUSER_LOCK.LOCK.value <= 'h0; end else if(field_combo.CPTRA_FUSE_PAUSER_LOCK.LOCK.load_next) begin field_storage.CPTRA_FUSE_PAUSER_LOCK.LOCK.value <= field_combo.CPTRA_FUSE_PAUSER_LOCK.LOCK.next; diff --git a/src/soc_ifc/tb/fuse_reg_pauser_test.svh b/src/soc_ifc/tb/fuse_reg_pauser_test.svh index 093fb401f..d8714de07 100644 --- a/src/soc_ifc/tb/fuse_reg_pauser_test.svh +++ b/src/soc_ifc/tb/fuse_reg_pauser_test.svh @@ -96,8 +96,8 @@ task fuse_reg_pauser_test; tphase = "1b"; // NOTE. simulate_caliptra_boot() is necessary for noncore_rst_b to be deasserted - simulate_caliptra_boot(); - wait (cptra_noncore_rst_b_tb == 1'b1); + //simulate_caliptra_boot(); + //wait (cptra_noncore_rst_b_tb == 1'b1); // Set pauser valid to non-default wrtrans.update_byname("CPTRA_FUSE_VALID_PAUSER", 0, tid); @@ -217,7 +217,7 @@ task fuse_reg_pauser_test; tphase = "2b"; warm_reset_dut(); - reset_exp_data(); + warm_reset_exp_data(); sb.del_all(); simulate_caliptra_boot(); @@ -229,7 +229,7 @@ task fuse_reg_pauser_test; // $display("TB. DEBUG if status of cptra_noncore_rst_b_tb = 1'b%b", cptra_noncore_rst_b_tb); // end - read_reg_chk_inrange(GET_APB, "CPTRA_FUSE_PAUSER_LOCK", tid, '0, '0); + read_reg_chk_inrange(GET_APB, "CPTRA_FUSE_PAUSER_LOCK", tid, 'd1, 'd1); @(posedge clk_tb); diff --git a/src/soc_ifc/tb/soc_ifc_tb_pkg.sv b/src/soc_ifc/tb/soc_ifc_tb_pkg.sv index 866528805..0f39263a0 100644 --- a/src/soc_ifc/tb/soc_ifc_tb_pkg.sv +++ b/src/soc_ifc/tb/soc_ifc_tb_pkg.sv @@ -282,6 +282,8 @@ package soc_ifc_tb_pkg; "CPTRA_FW_EXTENDED_ERROR_INFO": 32'hffff_ffff, "CPTRA_RESET_REASON": 32'h2, // field WARM_RESET "CPTRA_FUSE_WR_DONE": 32'h1, // field 0 + "CPTRA_FUSE_VALID_PAUSER": 32'hffff_ffff, + "CPTRA_FUSE_PAUSER_LOCK": 32'h1, "CPTRA_TIMER_CONFIG": 32'hffff_ffff, "INTERNAL_RV_MTIME_L": 32'hffff_ffff, "INTERNAL_RV_MTIME_H": 32'hffff_ffff, diff --git a/src/soc_ifc/uvmf_soc_ifc/uvmf_template_output/verification_ip/environment_packages/soc_ifc_env_pkg/registers/soc_ifc_reg_model_top_pkg.sv b/src/soc_ifc/uvmf_soc_ifc/uvmf_template_output/verification_ip/environment_packages/soc_ifc_env_pkg/registers/soc_ifc_reg_model_top_pkg.sv index 442be3e18..d2293a905 100644 --- a/src/soc_ifc/uvmf_soc_ifc/uvmf_template_output/verification_ip/environment_packages/soc_ifc_env_pkg/registers/soc_ifc_reg_model_top_pkg.sv +++ b/src/soc_ifc/uvmf_soc_ifc/uvmf_template_output/verification_ip/environment_packages/soc_ifc_env_pkg/registers/soc_ifc_reg_model_top_pkg.sv @@ -206,8 +206,8 @@ package soc_ifc_reg_model_top_pkg; for (ii=0; ii<$size(this.CPTRA_GENERIC_OUTPUT_WIRES); ii++) begin if ( this.CPTRA_GENERIC_OUTPUT_WIRES[ii]. has_reset("HARD" )) this.CPTRA_GENERIC_OUTPUT_WIRES[ii]. set_reset(this.CPTRA_GENERIC_OUTPUT_WIRES[ii]. get_reset("HARD"), "SOFT"); end - if ( this.CPTRA_FUSE_VALID_PAUSER. has_reset("HARD" )) this.CPTRA_FUSE_VALID_PAUSER. set_reset(this.CPTRA_FUSE_VALID_PAUSER. get_reset("HARD"), "SOFT"); - if ( this.CPTRA_FUSE_PAUSER_LOCK. has_reset("HARD" )) this.CPTRA_FUSE_PAUSER_LOCK. set_reset(this.CPTRA_FUSE_PAUSER_LOCK. get_reset("HARD"), "SOFT"); +// if ( this.CPTRA_FUSE_VALID_PAUSER. has_reset("HARD" )) this.CPTRA_FUSE_VALID_PAUSER. set_reset(this.CPTRA_FUSE_VALID_PAUSER. get_reset("HARD"), "SOFT"); +// if ( this.CPTRA_FUSE_PAUSER_LOCK. has_reset("HARD" )) this.CPTRA_FUSE_PAUSER_LOCK. set_reset(this.CPTRA_FUSE_PAUSER_LOCK. get_reset("HARD"), "SOFT"); if ( this.CPTRA_HW_REV_ID.CPTRA_GENERATION. has_reset("HARD" )) this.CPTRA_HW_REV_ID.CPTRA_GENERATION. set_reset(this.CPTRA_HW_REV_ID.CPTRA_GENERATION. get_reset("HARD"), "SOFT"); if ( this.CPTRA_HW_REV_ID.SOC_STEPPING_ID. has_reset("HARD" )) this.CPTRA_HW_REV_ID.SOC_STEPPING_ID. set_reset(this.CPTRA_HW_REV_ID.SOC_STEPPING_ID. get_reset("HARD"), "SOFT"); for (ii=0; ii<$size(this.CPTRA_FW_REV_ID); ii++) begin