[sram_ctrl] Harden initialization counter
Signed-off-by: Michael Schaffner <msf@google.com>
diff --git a/hw/ip/prim/rtl/prim_ram_1p_scr.sv b/hw/ip/prim/rtl/prim_ram_1p_scr.sv
index 103edfc..8e3fe19 100644
--- a/hw/ip/prim/rtl/prim_ram_1p_scr.sv
+++ b/hw/ip/prim/rtl/prim_ram_1p_scr.sv
@@ -337,16 +337,18 @@
logic rvalid_q;
assign rvalid_o = rvalid_q;
+ logic intg_error_q;
logic [Width-1:0] wmask_q;
always_comb begin : p_forward_mux
rdata_o = '0;
- // regular reads
- if (rvalid_q) begin
+ // regular reads. note that we just return zero in case
+ // an integrity error was signalled.
+ if (rvalid_q && !intg_error_q) begin
rdata_o = rdata;
end
// In case of a collision, we forward the valid bytes of the write data from the unscrambled
// holding register.
- if (addr_collision_q) begin
+ if (addr_collision_q && !intg_error_q) begin
for (int k = 0; k < Width; k++) begin
if (wmask_q[k]) begin
rdata_o[k] = wdata_q[k];
@@ -365,6 +367,7 @@
addr_collision_q <= 1'b0;
rvalid_q <= 1'b0;
write_en_q <= 1'b0;
+ intg_error_q <= 1'b0;
raddr_q <= '0;
waddr_q <= '0;
wmask_q <= '0;
@@ -375,6 +378,7 @@
addr_collision_q <= addr_collision_d;
rvalid_q <= read_en;
write_en_q <= write_en_d;
+ intg_error_q <= intg_error_i;
if (read_en) begin
raddr_q <= addr_i;
diff --git a/hw/ip/sram_ctrl/data/sram_ctrl.hjson b/hw/ip/sram_ctrl/data/sram_ctrl.hjson
index 2edd01b..57e49fd 100644
--- a/hw/ip/sram_ctrl/data/sram_ctrl.hjson
+++ b/hw/ip/sram_ctrl/data/sram_ctrl.hjson
@@ -17,8 +17,11 @@
///////////////////////////
alert_list: [
- { name: "fatal_bus_integ_error",
- desc: "This fatal alert is triggered when a fatal TL-UL bus integrity fault is detected."
+ { name: "fatal_error",
+ desc: '''
+ This fatal alert is triggered when a fatal TL-UL bus integrity fault is detected,
+ or if the initialization mechanism has reached an invalid state.
+ '''
}
],
@@ -126,11 +129,21 @@
name: "BUS_INTEG_ERROR"
desc: '''
This bit is set to 1 if a fatal bus integrity fault is detected.
- This error triggers a fatal_bus_integ_error alert.
+ This error triggers a fatal_error alert.
+ This condition is terminal.
''',
resval: 0,
}
{ bits: "1"
+ name: "INIT_ERROR"
+ desc: '''
+ This bit is set to 1 if a the initialization counter has reached an invalid state.
+ This error triggers a fatal_error alert.
+ This condition is terminal.
+ ''',
+ resval: 0,
+ }
+ { bits: "2"
name: "ESCALATED"
desc: '''
Set to 1 if the sram controller has received an escalate request.
@@ -140,7 +153,7 @@
''',
resval: 0,
}
- { bits: "2"
+ { bits: "3"
name: "SCR_KEY_VALID"
desc: '''
Set to 1 if a new scrambling key has been successfully obtained from OTP.
@@ -149,7 +162,7 @@
''',
resval: 0,
}
- { bits: "3"
+ { bits: "4"
name: "SCR_KEY_SEED_VALID"
desc: '''
Set to 1 if the scrambling key has been derived from a valid key seed in OTP.
@@ -160,7 +173,7 @@
''',
resval: 0,
}
- { bits: "4"
+ { bits: "5"
name: "INIT_DONE"
desc: '''
Set to 1 if the hardware initialization triggered via !!CTRL.INIT has completed.
diff --git a/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_base_vseq.sv b/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_base_vseq.sv
index 8ca50c2..47e9c63 100644
--- a/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_base_vseq.sv
+++ b/hw/ip/sram_ctrl/dv/env/seq_lib/sram_ctrl_base_vseq.sv
@@ -49,7 +49,7 @@
//
virtual task req_mem_init();
csr_wr(.ptr(ral.ctrl), .value(3));
- csr_spinwait(.ptr(ral.ctrl.init), .exp_data(0));
+ csr_spinwait(.ptr(ral.status.init_done), .exp_data(1));
endtask
// Request a new scrambling key from the OTP interface.
diff --git a/hw/ip/sram_ctrl/dv/env/sram_ctrl_env_cfg.sv b/hw/ip/sram_ctrl/dv/env/sram_ctrl_env_cfg.sv
index 6b11603..b12c9c5 100644
--- a/hw/ip/sram_ctrl/dv/env/sram_ctrl_env_cfg.sv
+++ b/hw/ip/sram_ctrl/dv/env/sram_ctrl_env_cfg.sv
@@ -24,7 +24,7 @@
virtual function void initialize(bit [31:0] csr_base_addr = '1);
list_of_alerts = sram_ctrl_env_pkg::LIST_OF_ALERTS;
- tl_intg_alert_name = "fatal_intg_error";
+ tl_intg_alert_name = "fatal_error";
super.initialize(csr_base_addr);
// Build KDI cfg object and configure
diff --git a/hw/ip/sram_ctrl/dv/env/sram_ctrl_env_pkg.sv b/hw/ip/sram_ctrl/dv/env/sram_ctrl_env_pkg.sv
index 6b4e18e..86186f7 100644
--- a/hw/ip/sram_ctrl/dv/env/sram_ctrl_env_pkg.sv
+++ b/hw/ip/sram_ctrl/dv/env/sram_ctrl_env_pkg.sv
@@ -24,7 +24,7 @@
`include "dv_macros.svh"
// parameters
- parameter string LIST_OF_ALERTS[] = { "fatal_bus_integ_error"};
+ parameter string LIST_OF_ALERTS[] = { "fatal_error"};
parameter uint NUM_ALERTS = 1;
// Number of bits in the otp_ctrl_pkg::sram_otp_key_rsp_t struct:
@@ -48,11 +48,12 @@
} sram_ctrl_e;
typedef enum bit [2:0] {
- SramCtrlError = 0,
- SramCtrlEscalated = 1,
- SramCtrlScrKeyValid = 2,
- SramCtrlScrKeySeedValid = 3,
- SramCtrlInitDone = 4
+ SramCtrlBusIntegError = 0,
+ SramCtrlInitError = 1,
+ SramCtrlEscalated = 2,
+ SramCtrlScrKeyValid = 3,
+ SramCtrlScrKeySeedValid = 4,
+ SramCtrlInitDone = 5
} sram_ctrl_status_e;
// package sources
diff --git a/hw/ip/sram_ctrl/dv/env/sram_ctrl_scoreboard.sv b/hw/ip/sram_ctrl/dv/env/sram_ctrl_scoreboard.sv
index 5b38e92..2e546ae 100644
--- a/hw/ip/sram_ctrl/dv/env/sram_ctrl_scoreboard.sv
+++ b/hw/ip/sram_ctrl/dv/env/sram_ctrl_scoreboard.sv
@@ -326,6 +326,7 @@
exp_status[SramCtrlEscalated] = 1;
exp_status[SramCtrlScrKeySeedValid] = 0;
+ exp_status[SramCtrlScrKeyValid] = 0;
exp_status[SramCtrlInitDone] = 0;
// escalation resets the key and nonce back to defaults
diff --git a/hw/ip/sram_ctrl/rtl/sram_ctrl.sv b/hw/ip/sram_ctrl/rtl/sram_ctrl.sv
index 98504be..54b94c4 100644
--- a/hw/ip/sram_ctrl/rtl/sram_ctrl.sv
+++ b/hw/ip/sram_ctrl/rtl/sram_ctrl.sv
@@ -51,8 +51,8 @@
);
// This is later on pruned to the correct width at the SRAM wrapper interface.
- parameter int Depth = MemSizeRam >> 2;
- parameter int AddrWidth = prim_util_pkg::vbits(Depth);
+ parameter int unsigned Depth = MemSizeRam >> 2;
+ parameter int unsigned AddrWidth = prim_util_pkg::vbits(Depth);
`ASSERT_INIT(NonceWidthsLessThanSource_A, NonceWidth + LfsrWidth <= otp_ctrl_pkg::SramNonceWidth)
@@ -91,10 +91,13 @@
logic alert_test;
assign alert_test = reg2hw.alert_test.q & reg2hw.alert_test.qe;
- logic bus_integ_error, bus_integ_error_q;
- assign bus_integ_error_q = reg2hw.status.bus_integ_error.q;
+ logic bus_integ_error;
assign hw2reg.status.bus_integ_error.d = 1'b1;
- assign hw2reg.status.bus_integ_error.de = bus_integ_error | bus_integ_error_q;
+ assign hw2reg.status.bus_integ_error.de = bus_integ_error;
+
+ logic init_error;
+ assign hw2reg.status.init_error.d = 1'b1;
+ assign hw2reg.status.init_error.de = init_error;
prim_alert_sender #(
.AsyncOn(AlertAsyncOn[0]),
@@ -102,17 +105,17 @@
) u_prim_alert_sender_parity (
.clk_i,
.rst_ni,
- .alert_test_i ( alert_test ),
- .alert_req_i ( bus_integ_error ),
- .alert_ack_o ( ),
- .alert_state_o ( ),
- .alert_rx_i ( alert_rx_i[0] ),
- .alert_tx_o ( alert_tx_o[0] )
+ .alert_test_i ( alert_test ),
+ .alert_req_i ( bus_integ_error | init_error ),
+ .alert_ack_o ( ),
+ .alert_state_o ( ),
+ .alert_rx_i ( alert_rx_i[0] ),
+ .alert_tx_o ( alert_tx_o[0] )
);
- //////////////////////////////////////////
- // Lifecycle Escalation Synchronization //
- //////////////////////////////////////////
+ /////////////////////////
+ // Escalation Triggers //
+ /////////////////////////
lc_ctrl_pkg::lc_tx_t escalate_en;
prim_lc_sync #(
@@ -124,6 +127,76 @@
.lc_en_o (escalate_en)
);
+ logic escalate;
+ assign escalate = (escalate_en != lc_ctrl_pkg::Off);
+ assign hw2reg.status.escalated.d = 1'b1;
+ assign hw2reg.status.escalated.de = escalate;
+
+ // Aggregate external and internal escalation sources. This is used on countermeasures further
+ // below (key reset, transaction blocking and scrambling nonce reversal).
+ logic local_esc;
+ assign local_esc = escalate |
+ init_error |
+ bus_integ_error |
+ reg2hw.status.escalated.q |
+ reg2hw.status.init_error.q |
+ reg2hw.status.bus_integ_error.q;
+
+ ///////////////////////
+ // HW Initialization //
+ ///////////////////////
+
+ // A write to the init register reloads the LFSR seed, resets the init counter and
+ // sets init_q to flag a pending initialization request.
+ logic init_trig;
+ assign init_trig = reg2hw.ctrl.init.q & reg2hw.ctrl.init.qe;
+
+ // We employ two redundant counters to guard against FI attacks.
+ // If any of the two is glitched and the two counter states do not agree,
+ // we trigger an alert.
+ logic [1:0] init_req, init_done, init_q;
+ logic [1:0][AddrWidth-1:0] init_cnt_q;
+ for (genvar k = 0; k < 2; k++) begin : gen_double_cnt
+
+ // These size_only buffers are instantiated in order to prevent
+ // optimization / merging of the two counters.
+ logic init_trig_buf;
+ prim_buf u_prim_buf_trig (
+ .in_i(init_trig),
+ .out_o(init_trig_buf)
+ );
+
+ // This waits until the scrambling keys are actually valid (this allows the SW to trigger
+ // key renewal and initialization at the same time).
+ assign init_req[k] = init_q[k] & reg2hw.status.scr_key_valid.q;
+ assign init_done[k] = (init_cnt_q[k] == AddrWidth'(Depth - 1)) & init_req[k];
+
+ logic init_d;
+ assign init_d = (init_done[k]) ? 1'b0 :
+ (init_trig_buf) ? 1'b1 : init_q[k];
+
+ logic [AddrWidth-1:0] init_cnt_d;
+ assign init_cnt_d = (init_trig_buf) ? '0 :
+ (init_req[k]) ? init_cnt_q[k] + 1'b1 : init_cnt_q[k];
+
+ prim_flop #(
+ .Width(1+AddrWidth)
+ ) u_prim_flop_cnt (
+ .clk_i,
+ .rst_ni,
+ .d_i({init_d, init_cnt_d}),
+ .q_o({init_q[k], init_cnt_q[k]})
+ );
+ end
+
+ // Clear this bit on local escalation.
+ assign hw2reg.status.init_done.d = init_done[0] & ~init_trig & ~local_esc;
+ assign hw2reg.status.init_done.de = init_done[0] | init_trig | local_esc;
+
+ // Check whether counter is glitched into an invalid state
+ assign init_error = {init_q[0], init_cnt_q[0]} !=
+ {init_q[1], init_cnt_q[1]};
+
////////////////////////////
// Scrambling Key Request //
////////////////////////////
@@ -138,33 +211,6 @@
assign key_req_pending_d = (key_req) ? 1'b1 :
(key_ack) ? 1'b0 : key_req_pending_q;
- logic init_q, init_d;
- logic init_trig, init_req, init_done;
- logic [AddrWidth-1:0] init_cnt_d, init_cnt_q;
- // A write to the init register reloads the LFSR seed, resets the init counter and
- // sets init_q to flag a pending initialization request.
- assign init_trig = reg2hw.ctrl.init.q & reg2hw.ctrl.init.qe;
- // This waits until the scrambling keys are actually valid (this allows the SW to trigger
- // key renewal and initialization at the same time).
- assign init_req = init_q & reg2hw.status.scr_key_valid.q;
- assign init_done = (init_cnt_q == Depth - 1) & init_req;
-
- assign init_d = (init_done) ? 1'b0 :
- (init_trig) ? 1'b1 : init_q;
-
- // TODO: Do we need to harden this counter long term?
- assign init_cnt_d = (init_trig) ? '0 :
- (init_req) ? init_cnt_q + 1'b1 : init_cnt_q;
-
- assign hw2reg.status.init_done.d = init_done & ~init_trig;
- assign hw2reg.status.init_done.de = init_done | init_trig;
-
- // Trigger escalation
- logic escalate;
- assign escalate = (escalate_en != lc_ctrl_pkg::Off) | reg2hw.status.escalated.q;
- assign hw2reg.status.escalated.d = 1'b1;
- assign hw2reg.status.escalated.de = escalate;
-
// The SRAM scrambling wrapper will not accept any transactions while
// the key req is pending or if we have escalated.
// Note that we're not using key_valid_q here, such that the SRAM can be used
@@ -172,30 +218,28 @@
logic key_valid;
assign key_valid = ~(key_req_pending_q | reg2hw.status.escalated.q);
- assign hw2reg.status.scr_key_valid.d = key_ack & ~key_req;
- assign hw2reg.status.scr_key_valid.de = key_req | key_ack;
+ // Clear this bit on local escalation.
+ assign hw2reg.status.scr_key_valid.d = key_ack & ~key_req & ~local_esc;
+ assign hw2reg.status.scr_key_valid.de = key_req | key_ack | local_esc;
+ // Clear this bit on local escalation.
logic key_seed_valid;
- assign hw2reg.status.scr_key_seed_valid.d = key_seed_valid & ~escalate;
- assign hw2reg.status.scr_key_seed_valid.de = key_ack | escalate;
+ assign hw2reg.status.scr_key_seed_valid.d = key_seed_valid & ~local_esc;
+ assign hw2reg.status.scr_key_seed_valid.de = key_ack | local_esc;
always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
if (!rst_ni) begin
- init_q <= '0;
- init_cnt_q <= '0;
key_req_pending_q <= 1'b0;
key_q <= RndCnstSramKey;
nonce_q <= RndCnstSramNonce;
end else begin
- init_q <= init_d;
- init_cnt_q <= init_cnt_d;
key_req_pending_q <= key_req_pending_d;
if (key_ack) begin
key_q <= key_d;
nonce_q <= nonce_d;
end
// This scraps the keys.
- if (escalate) begin
+ if (local_esc) begin
key_q <= RndCnstSramKey;
nonce_q <= RndCnstSramNonce;
end
@@ -264,7 +308,7 @@
) u_lfsr (
.clk_i,
.rst_ni,
- .lfsr_en_i(init_req),
+ .lfsr_en_i(init_req[0]),
.seed_en_i(init_trig),
.seed_i(nonce_q[NonceWidth +: LfsrWidth]),
.entropy_i('0),
@@ -319,13 +363,13 @@
);
// Interposing mux logic for initialization with pseudo random data.
- assign sram_req = tlul_req | init_req;
- assign tlul_gnt = sram_gnt & ~init_req;
- assign sram_we = tlul_we | init_req;
- assign sram_intg_error = bus_integ_error_q & ~init_req;
- assign sram_addr = (init_req) ? init_cnt_q : tlul_addr;
- assign sram_wdata = (init_req) ? lfsr_out_integ : tlul_wdata;
- assign sram_wmask = (init_req) ? {DataWidth{1'b1}} : tlul_wmask;
+ assign sram_req = tlul_req | init_req[0];
+ assign tlul_gnt = sram_gnt & ~init_req[0];
+ assign sram_we = tlul_we | init_req[0];
+ assign sram_intg_error = local_esc & ~init_req[0];
+ assign sram_addr = (init_req[0]) ? init_cnt_q[0] : tlul_addr;
+ assign sram_wdata = (init_req[0]) ? lfsr_out_integ : tlul_wdata;
+ assign sram_wmask = (init_req[0]) ? {DataWidth{1'b1}} : tlul_wmask;
prim_ram_1p_scr #(
.Width(DataWidth),
diff --git a/hw/ip/sram_ctrl/rtl/sram_ctrl_reg_pkg.sv b/hw/ip/sram_ctrl/rtl/sram_ctrl_reg_pkg.sv
index 514d5b7..f8a3f29 100644
--- a/hw/ip/sram_ctrl/rtl/sram_ctrl_reg_pkg.sv
+++ b/hw/ip/sram_ctrl/rtl/sram_ctrl_reg_pkg.sv
@@ -28,6 +28,9 @@
} bus_integ_error;
struct packed {
logic q;
+ } init_error;
+ struct packed {
+ logic q;
} escalated;
struct packed {
logic q;
@@ -63,6 +66,10 @@
struct packed {
logic d;
logic de;
+ } init_error;
+ struct packed {
+ logic d;
+ logic de;
} escalated;
struct packed {
logic d;
@@ -80,15 +87,15 @@
// Register -> HW type for regs interface
typedef struct packed {
- sram_ctrl_reg2hw_alert_test_reg_t alert_test; // [13:12]
- sram_ctrl_reg2hw_status_reg_t status; // [11:7]
+ sram_ctrl_reg2hw_alert_test_reg_t alert_test; // [14:13]
+ sram_ctrl_reg2hw_status_reg_t status; // [12:7]
sram_ctrl_reg2hw_exec_reg_t exec; // [6:4]
sram_ctrl_reg2hw_ctrl_reg_t ctrl; // [3:0]
} sram_ctrl_regs_reg2hw_t;
// HW -> register type for regs interface
typedef struct packed {
- sram_ctrl_hw2reg_status_reg_t status; // [9:0]
+ sram_ctrl_hw2reg_status_reg_t status; // [11:0]
} sram_ctrl_regs_hw2reg_t;
// Register offsets for regs interface
@@ -101,7 +108,7 @@
// Reset values for hwext registers and their fields for regs interface
parameter logic [0:0] SRAM_CTRL_ALERT_TEST_RESVAL = 1'h 0;
- parameter logic [0:0] SRAM_CTRL_ALERT_TEST_FATAL_BUS_INTEG_ERROR_RESVAL = 1'h 0;
+ parameter logic [0:0] SRAM_CTRL_ALERT_TEST_FATAL_ERROR_RESVAL = 1'h 0;
// Register index for regs interface
typedef enum int {
diff --git a/hw/ip/sram_ctrl/rtl/sram_ctrl_regs_reg_top.sv b/hw/ip/sram_ctrl/rtl/sram_ctrl_regs_reg_top.sv
index 42f0932..6506427 100644
--- a/hw/ip/sram_ctrl/rtl/sram_ctrl_regs_reg_top.sv
+++ b/hw/ip/sram_ctrl/rtl/sram_ctrl_regs_reg_top.sv
@@ -112,6 +112,7 @@
logic alert_test_we;
logic alert_test_wd;
logic status_bus_integ_error_qs;
+ logic status_init_error_qs;
logic status_escalated_qs;
logic status_scr_key_valid_qs;
logic status_scr_key_seed_valid_qs;
@@ -174,7 +175,33 @@
);
- // F[escalated]: 1:1
+ // F[init_error]: 1:1
+ prim_subreg #(
+ .DW (1),
+ .SwAccess(prim_subreg_pkg::SwAccessRO),
+ .RESVAL (1'h0)
+ ) u_status_init_error (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+
+ // from register interface
+ .we (1'b0),
+ .wd ('0),
+
+ // from internal hardware
+ .de (hw2reg.status.init_error.de),
+ .d (hw2reg.status.init_error.d),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.status.init_error.q),
+
+ // to register interface (read)
+ .qs (status_init_error_qs)
+ );
+
+
+ // F[escalated]: 2:2
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessRO),
@@ -200,7 +227,7 @@
);
- // F[scr_key_valid]: 2:2
+ // F[scr_key_valid]: 3:3
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessRO),
@@ -226,7 +253,7 @@
);
- // F[scr_key_seed_valid]: 3:3
+ // F[scr_key_seed_valid]: 4:4
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessRO),
@@ -252,7 +279,7 @@
);
- // F[init_done]: 4:4
+ // F[init_done]: 5:5
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessRO),
@@ -466,10 +493,11 @@
addr_hit[1]: begin
reg_rdata_next[0] = status_bus_integ_error_qs;
- reg_rdata_next[1] = status_escalated_qs;
- reg_rdata_next[2] = status_scr_key_valid_qs;
- reg_rdata_next[3] = status_scr_key_seed_valid_qs;
- reg_rdata_next[4] = status_init_done_qs;
+ reg_rdata_next[1] = status_init_error_qs;
+ reg_rdata_next[2] = status_escalated_qs;
+ reg_rdata_next[3] = status_scr_key_valid_qs;
+ reg_rdata_next[4] = status_scr_key_seed_valid_qs;
+ reg_rdata_next[5] = status_init_done_qs;
end
addr_hit[2]: begin
diff --git a/hw/ip/tlul/rtl/tlul_sram_byte.sv b/hw/ip/tlul/rtl/tlul_sram_byte.sv
index 89e07ec..d865e96 100644
--- a/hw/ip/tlul/rtl/tlul_sram_byte.sv
+++ b/hw/ip/tlul/rtl/tlul_sram_byte.sv
@@ -69,6 +69,7 @@
logic wr_txn;
logic byte_wr_txn;
logic byte_req_ack;
+ logic a_ack_q, a_ack_d;
assign a_ack = tl_i.a_valid & tl_o.a_ready;
assign sram_a_ack = tl_sram_o.a_valid & tl_sram_i.a_ready;
@@ -80,9 +81,12 @@
if (EnableIntg) begin : gen_dyn_sel
assign byte_wr_txn = tl_i.a_valid & ~&tl_i.a_mask & wr_txn;
assign sel_int = byte_wr_txn | stall_host ? SelInt : SelPassThru;
+ // TODO(#7461): remove this register, once this issue has been addressed.
+ assign a_ack_d = a_ack;
end else begin : gen_static_sel
assign byte_wr_txn = '0;
assign sel_int = SelPassThru;
+ assign a_ack_d = 1'b0;
end
// state machine handling
@@ -94,8 +98,13 @@
unique case (state_q)
StPassThru: begin
-
- if (byte_req_ack) begin
+ // TODO(#7461): remove the first if condition once all RAW corner cases are handled in DV.
+ // This introduces an artificial bubble before entering a read modify write operation
+ // in case there was another transaction right before this one. This ensures that the
+ // previous operation can complete.
+ if (byte_wr_txn && a_ack_q) begin
+ stall_host = 1'b1;
+ end else if (byte_req_ack) begin
state_d = StWaitRd;
end
end
@@ -119,6 +128,8 @@
end
// TODO(#7461): remove this once all RAW corner cases are handled in DV.
+ // This state artificially introduces a bubble after each read modify write
+ // operation such that it can complete.
StWait: begin
stall_host = 1'b1;
state_d = StPassThru;
@@ -130,6 +141,14 @@
end
+ always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
+ if (!rst_ni) begin
+ a_ack_q <= 1'b0;
+ end else begin
+ a_ack_q <= a_ack_d;
+ end
+ end
+
// prim fifo for capturing info
typedef struct packed {
logic [2:0] a_param;
diff --git a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
index 25c084d..46b3a95 100644
--- a/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
+++ b/hw/top_earlgrey/data/autogen/top_earlgrey.gen.hjson
@@ -12801,7 +12801,7 @@
module_name: sensor_ctrl_aon
}
{
- name: sram_ctrl_ret_aon_fatal_bus_integ_error
+ name: sram_ctrl_ret_aon_fatal_error
width: 1
type: alert
async: "1"
@@ -12927,7 +12927,7 @@
module_name: edn1
}
{
- name: sram_ctrl_main_fatal_bus_integ_error
+ name: sram_ctrl_main_fatal_error
width: 1
type: alert
async: "1"
diff --git a/hw/top_earlgrey/dv/env/autogen/chip_env_pkg__params.sv b/hw/top_earlgrey/dv/env/autogen/chip_env_pkg__params.sv
index d2e7bb9..e2aeb1b 100644
--- a/hw/top_earlgrey/dv/env/autogen/chip_env_pkg__params.sv
+++ b/hw/top_earlgrey/dv/env/autogen/chip_env_pkg__params.sv
@@ -46,7 +46,7 @@
"sensor_ctrl_aon_recov_ot3",
"sensor_ctrl_aon_recov_ot4",
"sensor_ctrl_aon_recov_ot5",
- "sram_ctrl_ret_aon_fatal_bus_integ_error",
+ "sram_ctrl_ret_aon_fatal_error",
"flash_ctrl_recov_err",
"flash_ctrl_recov_mp_err",
"flash_ctrl_recov_ecc_err",
@@ -64,7 +64,7 @@
"entropy_src_fatal_alert",
"edn0_fatal_alert",
"edn1_fatal_alert",
- "sram_ctrl_main_fatal_bus_integ_error",
+ "sram_ctrl_main_fatal_error",
"otbn_fatal",
"otbn_recov",
"rom_ctrl_fatal",
diff --git a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
index 2075a37..0a21d99 100644
--- a/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
+++ b/hw/top_earlgrey/rtl/autogen/top_earlgrey.sv
@@ -1890,7 +1890,7 @@
.MemSizeRam(4096),
.InstrExec(SramCtrlRetAonInstrExec)
) u_sram_ctrl_ret_aon (
- // [41]: fatal_bus_integ_error
+ // [41]: fatal_error
.alert_tx_o ( alert_tx[41:41] ),
.alert_rx_i ( alert_rx[41:41] ),
@@ -2286,7 +2286,7 @@
.MemSizeRam(131072),
.InstrExec(SramCtrlMainInstrExec)
) u_sram_ctrl_main (
- // [59]: fatal_bus_integ_error
+ // [59]: fatal_error
.alert_tx_o ( alert_tx[59:59] ),
.alert_rx_i ( alert_rx[59:59] ),
diff --git a/hw/top_earlgrey/sw/autogen/top_earlgrey.c b/hw/top_earlgrey/sw/autogen/top_earlgrey.c
index f5fb4e0..baa4da7 100644
--- a/hw/top_earlgrey/sw/autogen/top_earlgrey.c
+++ b/hw/top_earlgrey/sw/autogen/top_earlgrey.c
@@ -244,7 +244,7 @@
[kTopEarlgreyAlertIdSensorCtrlAonRecovOt3] = kTopEarlgreyAlertPeripheralSensorCtrlAon,
[kTopEarlgreyAlertIdSensorCtrlAonRecovOt4] = kTopEarlgreyAlertPeripheralSensorCtrlAon,
[kTopEarlgreyAlertIdSensorCtrlAonRecovOt5] = kTopEarlgreyAlertPeripheralSensorCtrlAon,
- [kTopEarlgreyAlertIdSramCtrlRetAonFatalBusIntegError] = kTopEarlgreyAlertPeripheralSramCtrlRetAon,
+ [kTopEarlgreyAlertIdSramCtrlRetAonFatalError] = kTopEarlgreyAlertPeripheralSramCtrlRetAon,
[kTopEarlgreyAlertIdFlashCtrlRecovErr] = kTopEarlgreyAlertPeripheralFlashCtrl,
[kTopEarlgreyAlertIdFlashCtrlRecovMpErr] = kTopEarlgreyAlertPeripheralFlashCtrl,
[kTopEarlgreyAlertIdFlashCtrlRecovEccErr] = kTopEarlgreyAlertPeripheralFlashCtrl,
@@ -262,7 +262,7 @@
[kTopEarlgreyAlertIdEntropySrcFatalAlert] = kTopEarlgreyAlertPeripheralEntropySrc,
[kTopEarlgreyAlertIdEdn0FatalAlert] = kTopEarlgreyAlertPeripheralEdn0,
[kTopEarlgreyAlertIdEdn1FatalAlert] = kTopEarlgreyAlertPeripheralEdn1,
- [kTopEarlgreyAlertIdSramCtrlMainFatalBusIntegError] = kTopEarlgreyAlertPeripheralSramCtrlMain,
+ [kTopEarlgreyAlertIdSramCtrlMainFatalError] = kTopEarlgreyAlertPeripheralSramCtrlMain,
[kTopEarlgreyAlertIdOtbnFatal] = kTopEarlgreyAlertPeripheralOtbn,
[kTopEarlgreyAlertIdOtbnRecov] = kTopEarlgreyAlertPeripheralOtbn,
[kTopEarlgreyAlertIdRomCtrlFatal] = kTopEarlgreyAlertPeripheralRomCtrl,
diff --git a/hw/top_earlgrey/sw/autogen/top_earlgrey.h b/hw/top_earlgrey/sw/autogen/top_earlgrey.h
index 554e57f..62926be 100644
--- a/hw/top_earlgrey/sw/autogen/top_earlgrey.h
+++ b/hw/top_earlgrey/sw/autogen/top_earlgrey.h
@@ -1298,7 +1298,7 @@
kTopEarlgreyAlertIdSensorCtrlAonRecovOt3 = 38, /**< sensor_ctrl_aon_recov_ot3 */
kTopEarlgreyAlertIdSensorCtrlAonRecovOt4 = 39, /**< sensor_ctrl_aon_recov_ot4 */
kTopEarlgreyAlertIdSensorCtrlAonRecovOt5 = 40, /**< sensor_ctrl_aon_recov_ot5 */
- kTopEarlgreyAlertIdSramCtrlRetAonFatalBusIntegError = 41, /**< sram_ctrl_ret_aon_fatal_bus_integ_error */
+ kTopEarlgreyAlertIdSramCtrlRetAonFatalError = 41, /**< sram_ctrl_ret_aon_fatal_error */
kTopEarlgreyAlertIdFlashCtrlRecovErr = 42, /**< flash_ctrl_recov_err */
kTopEarlgreyAlertIdFlashCtrlRecovMpErr = 43, /**< flash_ctrl_recov_mp_err */
kTopEarlgreyAlertIdFlashCtrlRecovEccErr = 44, /**< flash_ctrl_recov_ecc_err */
@@ -1316,7 +1316,7 @@
kTopEarlgreyAlertIdEntropySrcFatalAlert = 56, /**< entropy_src_fatal_alert */
kTopEarlgreyAlertIdEdn0FatalAlert = 57, /**< edn0_fatal_alert */
kTopEarlgreyAlertIdEdn1FatalAlert = 58, /**< edn1_fatal_alert */
- kTopEarlgreyAlertIdSramCtrlMainFatalBusIntegError = 59, /**< sram_ctrl_main_fatal_bus_integ_error */
+ kTopEarlgreyAlertIdSramCtrlMainFatalError = 59, /**< sram_ctrl_main_fatal_error */
kTopEarlgreyAlertIdOtbnFatal = 60, /**< otbn_fatal */
kTopEarlgreyAlertIdOtbnRecov = 61, /**< otbn_recov */
kTopEarlgreyAlertIdRomCtrlFatal = 62, /**< rom_ctrl_fatal */