Skip to content

Commit

Permalink
Merged PR 118379: More RDC clean up and fuse valid pauser fix
Browse files Browse the repository at this point in the history
- Made the fuse valid pauser registers sticky, allowing them to be used during fuse download instead of held under reset.
- Updated the fuse pauser test in soc ifc tb
- Appropriately staged the reset window logic so it doesn't create it's own RDC issue.
- Forced more logic IDLE in the 2:1 ahb mux during fw update reset.
- Provided RDC only gated clock to veer core to resolve the RDC crosses into debug logic.

Related work items: #518239, #518350
  • Loading branch information
Nitsirks authored and Anjana Parthasarathy committed Aug 14, 2023
1 parent 3c8ae28 commit 896ef91
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 38 deletions.
28 changes: 18 additions & 10 deletions src/ahb_lite_bus/rtl/ahb_lite_2to1_mux.sv
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ module ahb_lite_2to1_mux #(
// ---------------------------------------
input logic hclk,
input logic hreset_n,
input logic force_bus_idle,

// ---------------------------------------
// From Initiator 0
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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;
Expand Down
4 changes: 1 addition & 3 deletions src/ahb_lite_bus/rtl/ahb_lite_address_decoder.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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
// ---------------------------------------
Expand Down Expand Up @@ -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
// ----------------------------------------------
Expand Down
9 changes: 5 additions & 4 deletions src/integration/rtl/caliptra_top.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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]),
Expand Down Expand Up @@ -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),
Expand All @@ -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 ),
Expand Down Expand Up @@ -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),
Expand Down
35 changes: 26 additions & 9 deletions src/soc_ifc/rtl/soc_ifc_boot_fsm.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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

Expand All @@ -200,29 +212,34 @@ 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;
synch_noncore_rst_b <= fsm_synch_noncore_rst_b;
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

//uC reset generation
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 :
Expand Down
4 changes: 2 additions & 2 deletions src/soc_ifc/rtl/soc_ifc_external_reg.rdl
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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;
8 changes: 4 additions & 4 deletions src/soc_ifc/rtl/soc_ifc_reg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions src/soc_ifc/tb/fuse_reg_pauser_test.svh
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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();
Expand All @@ -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);


Expand Down
2 changes: 2 additions & 0 deletions src/soc_ifc/tb/soc_ifc_tb_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 896ef91

Please sign in to comment.