[flash_ctrl] D2 preparation steps
- fully covnert to new sparse fsm
- add additional fsms as needed
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl.hjson b/hw/ip/flash_ctrl/data/flash_ctrl.hjson
index 1f9fc41..32068de 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl.hjson
+++ b/hw/ip/flash_ctrl/data/flash_ctrl.hjson
@@ -177,6 +177,10 @@
{ name: "BUS.INTEGRITY",
desc: "End-to-end bus integrity scheme."
}
+
+ { name: "FSM.SPARSE",
+ desc: "sparse fsm encoding in life cycle interface."
+ }
]
scan: "true", // Enable `scanmode_i` port
@@ -1568,6 +1572,12 @@
'''
},
{ bits: "9",
+ name: "arb_fsm_err",
+ desc: '''
+ The software / hardware interface has encountered a fatal error.
+ '''
+ },
+ { bits: "10",
name: "storage_err",
desc: '''
A shadow register encountered a storage fault.
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl.hjson.tpl b/hw/ip/flash_ctrl/data/flash_ctrl.hjson.tpl
index aa2d601..e7a6b10 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl.hjson.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl.hjson.tpl
@@ -184,6 +184,10 @@
{ name: "BUS.INTEGRITY",
desc: "End-to-end bus integrity scheme."
}
+
+ { name: "FSM.SPARSE",
+ desc: "sparse fsm encoding in life cycle interface."
+ }
]
scan: "true", // Enable `scanmode_i` port
@@ -1069,6 +1073,12 @@
'''
},
{ bits: "9",
+ name: "arb_fsm_err",
+ desc: '''
+ The software / hardware interface has encountered a fatal error.
+ '''
+ },
+ { bits: "10",
name: "storage_err",
desc: '''
A shadow register encountered a storage fault.
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl b/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
index 1495297..1a2dc46 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
@@ -216,6 +216,7 @@
logic sw_sel;
flash_lcmgr_phase_e hw_phase;
logic lcmgr_err;
+ logic arb_fsm_err;
// Flash control arbitration connections to software interface
logic sw_ctrl_done;
@@ -360,7 +361,8 @@
.phase_o(phase),
// indication that sw has been selected
- .sel_o(if_sel)
+ .sel_o(if_sel),
+ .fsm_err_o(arb_fsm_err)
);
assign op_start = muxed_ctrl.start.q;
@@ -915,6 +917,7 @@
assign hw2reg.fault_status.reg_intg_err.d = 1'b1;
assign hw2reg.fault_status.phy_intg_err.d = 1'b1;
assign hw2reg.fault_status.lcmgr_err.d = 1'b1;
+ assign hw2reg.fault_status.arb_fsm_err.d = 1'b1;
assign hw2reg.fault_status.storage_err.d = 1'b1;
assign hw2reg.fault_status.mp_err.de = hw_err.mp_err;
assign hw2reg.fault_status.rd_err.de = hw_err.rd_err;
@@ -924,6 +927,7 @@
assign hw2reg.fault_status.reg_intg_err.de = intg_err;
assign hw2reg.fault_status.phy_intg_err.de = flash_phy_rsp.intg_err;
assign hw2reg.fault_status.lcmgr_err.de = lcmgr_err;
+ assign hw2reg.fault_status.arb_fsm_err.de = arb_fsm_err;
assign hw2reg.fault_status.storage_err.de = storage_err;
// Correctable ECC count / address
@@ -1176,4 +1180,11 @@
alert_tx_o[0])
`ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(WordCntAlertCheck_A, u_flash_hw_if.u_word_cnt,
alert_tx_o[0])
+
+ `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(LcCtrlFsmCheck_A,
+ u_flash_hw_if.u_state_regs, alert_tx_o[0])
+ `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(LcCtrlRmaFsmCheck_A,
+ u_flash_hw_if.u_rma_state_regs, alert_tx_o[0])
+ `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(ArbFsmCheck_A,
+ u_ctrl_arb.u_state_regs, alert_tx_o[0])
endmodule
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl b/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl
index 63a7926..70e8d4d 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl
@@ -586,13 +586,14 @@
//
localparam int RmaStateWidth = 10;
typedef enum logic [RmaStateWidth-1:0] {
- StRmaIdle = 10'b1000000111,
- StRmaPageSel = 10'b0110100101,
- StRmaErase = 10'b0100011100,
- StRmaWordSel = 10'b1011110010,
- StRmaProgram = 10'b0000111011,
- StRmaProgramWait = 10'b0011001000,
- StRmaRdVerify = 10'b1101101001
+ StRmaIdle = 10'b1101000011,
+ StRmaPageSel = 10'b0010111001,
+ StRmaErase = 10'b1111010100,
+ StRmaWordSel = 10'b0001011111,
+ StRmaProgram = 10'b0110001110,
+ StRmaProgramWait = 10'b1000110110,
+ StRmaRdVerify = 10'b1011101010,
+ StRmaInvalid = 10'b1100101101
} rma_state_e;
endpackage : flash_ctrl_pkg
diff --git a/hw/ip/flash_ctrl/flash_ctrl.core b/hw/ip/flash_ctrl/flash_ctrl.core
index 1a52ede..bcd5f35 100644
--- a/hw/ip/flash_ctrl/flash_ctrl.core
+++ b/hw/ip/flash_ctrl/flash_ctrl.core
@@ -12,11 +12,12 @@
- lowrisc:prim:all
- lowrisc:prim:count
- lowrisc:prim:edge_detector
- - lowrisc:prim:secded
- - lowrisc:prim:lfsr
- lowrisc:prim:flash
- lowrisc:prim:gf_mult
- lowrisc:prim:lc_sync
+ - lowrisc:prim:lfsr
+ - lowrisc:prim:secded
+ - lowrisc:prim:sparse_fsm
- lowrisc:ip:otp_ctrl_pkg
- lowrisc:ip:flash_ctrl_pkg
- lowrisc:ip:jtag_pkg
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl.sv
index 226e044..7868578 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl.sv
@@ -217,6 +217,7 @@
logic sw_sel;
flash_lcmgr_phase_e hw_phase;
logic lcmgr_err;
+ logic arb_fsm_err;
// Flash control arbitration connections to software interface
logic sw_ctrl_done;
@@ -361,7 +362,8 @@
.phase_o(phase),
// indication that sw has been selected
- .sel_o(if_sel)
+ .sel_o(if_sel),
+ .fsm_err_o(arb_fsm_err)
);
assign op_start = muxed_ctrl.start.q;
@@ -916,6 +918,7 @@
assign hw2reg.fault_status.reg_intg_err.d = 1'b1;
assign hw2reg.fault_status.phy_intg_err.d = 1'b1;
assign hw2reg.fault_status.lcmgr_err.d = 1'b1;
+ assign hw2reg.fault_status.arb_fsm_err.d = 1'b1;
assign hw2reg.fault_status.storage_err.d = 1'b1;
assign hw2reg.fault_status.mp_err.de = hw_err.mp_err;
assign hw2reg.fault_status.rd_err.de = hw_err.rd_err;
@@ -925,6 +928,7 @@
assign hw2reg.fault_status.reg_intg_err.de = intg_err;
assign hw2reg.fault_status.phy_intg_err.de = flash_phy_rsp.intg_err;
assign hw2reg.fault_status.lcmgr_err.de = lcmgr_err;
+ assign hw2reg.fault_status.arb_fsm_err.de = arb_fsm_err;
assign hw2reg.fault_status.storage_err.de = storage_err;
// Correctable ECC count / address
@@ -1177,4 +1181,11 @@
alert_tx_o[0])
`ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(WordCntAlertCheck_A, u_flash_hw_if.u_word_cnt,
alert_tx_o[0])
+
+ `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(LcCtrlFsmCheck_A,
+ u_flash_hw_if.u_state_regs, alert_tx_o[0])
+ `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(LcCtrlRmaFsmCheck_A,
+ u_flash_hw_if.u_rma_state_regs, alert_tx_o[0])
+ `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(ArbFsmCheck_A,
+ u_ctrl_arb.u_state_regs, alert_tx_o[0])
endmodule
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv
index a5a1fd6..9e14caf 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv
@@ -83,37 +83,73 @@
output flash_lcmgr_phase_e phase_o,
// indication that sw has been selected
- output flash_sel_e sel_o
+ output flash_sel_e sel_o,
+
+ // fsm sparse error
+ output logic fsm_err_o
);
// arbitration FSM
- typedef enum logic [1:0] {
- StReset, // at reset wait for flash phy to be ready
- StHw,
- StSwActive,
- StSwIdle
- } state_e;
+ // Encoding generated with:
+ // $ ./util/design/sparse-fsm-encode.py -d 5 -m 5 -n 10 \
+ // -s 1044018132 --language=sv --avoid-zero
+ //
+ // Hamming distance histogram:
+ //
+ // 0: --
+ // 1: --
+ // 2: --
+ // 3: --
+ // 4: --
+ // 5: |||||||||||||||||||| (50.00%)
+ // 6: |||||||||||||||| (40.00%)
+ // 7: |||| (10.00%)
+ // 8: --
+ // 9: --
+ // 10: --
+ //
+ // Minimum Hamming distance: 5
+ // Maximum Hamming distance: 7
+ // Minimum Hamming weight: 5
+ // Maximum Hamming weight: 7
+ //
+ localparam int StateWidth = 10;
+ typedef enum logic [StateWidth-1:0] {
+ StReset = 10'b1010101011,
+ StHw = 10'b1111010001,
+ StSwActive = 10'b1011001100,
+ StSwIdle = 10'b0101100111,
+ StInvalid = 10'b0111111010
+ } arb_state_e;
flash_sel_e func_sel;
- state_e state_q, state_d;
+ arb_state_e state_q, state_d;
logic sw_req;
assign sw_req = sw_ctrl_i.start.q;
- always_ff @(posedge clk_i or negedge rst_ni) begin
- if (!rst_ni) begin
- state_q <= StReset;
- end else begin
- state_q <= state_d;
- end
- end
+ // This primitive is used to place a size-only constraint on the
+ // flops in order to prevent FSM state encoding optimizations.
+ logic [StateWidth-1:0] state_raw_q;
+ assign state_q = arb_state_e'(state_raw_q);
+ prim_sparse_fsm_flop #(
+ .StateEnumT(arb_state_e),
+ .Width(StateWidth),
+ .ResetValue(StateWidth'(StReset))
+ ) u_state_regs (
+ .clk_i,
+ .rst_ni,
+ .state_i ( state_d ),
+ .state_o ( state_raw_q )
+ );
always_comb begin
func_sel = NoneSel;
fifo_clr_o = 1'b0;
state_d = state_q;
+ fsm_err_o = 1'b0;
unique case (state_q)
StReset: begin
@@ -158,7 +194,15 @@
end
end
- default:;
+ StInvalid: begin
+ fsm_err_o = 1'b1;
+ end
+
+ default: begin
+ state_d = StInvalid;
+ end
+
+
endcase // unique case (state_q)
end // always_comb
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_core_reg_top.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_core_reg_top.sv
index e7e2f79..510c7cc 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_core_reg_top.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_core_reg_top.sv
@@ -973,6 +973,7 @@
logic fault_status_reg_intg_err_qs;
logic fault_status_phy_intg_err_qs;
logic fault_status_lcmgr_err_qs;
+ logic fault_status_arb_fsm_err_qs;
logic fault_status_storage_err_qs;
logic [19:0] err_addr_qs;
logic ecc_single_err_cnt_we;
@@ -11508,7 +11509,32 @@
.qs (fault_status_lcmgr_err_qs)
);
- // F[storage_err]: 9:9
+ // F[arb_fsm_err]: 9:9
+ prim_subreg #(
+ .DW (1),
+ .SwAccess(prim_subreg_pkg::SwAccessRO),
+ .RESVAL (1'h0)
+ ) u_fault_status_arb_fsm_err (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+
+ // from register interface
+ .we (1'b0),
+ .wd ('0),
+
+ // from internal hardware
+ .de (hw2reg.fault_status.arb_fsm_err.de),
+ .d (hw2reg.fault_status.arb_fsm_err.d),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.fault_status.arb_fsm_err.q),
+
+ // to register interface (read)
+ .qs (fault_status_arb_fsm_err_qs)
+ );
+
+ // F[storage_err]: 10:10
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessRO),
@@ -13603,7 +13629,8 @@
reg_rdata_next[6] = fault_status_reg_intg_err_qs;
reg_rdata_next[7] = fault_status_phy_intg_err_qs;
reg_rdata_next[8] = fault_status_lcmgr_err_qs;
- reg_rdata_next[9] = fault_status_storage_err_qs;
+ reg_rdata_next[9] = fault_status_arb_fsm_err_qs;
+ reg_rdata_next[10] = fault_status_storage_err_qs;
end
addr_hit[87]: begin
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_lcmgr.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_lcmgr.sv
index 2ee60d4..3a3ccd4 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_lcmgr.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_lcmgr.sv
@@ -90,21 +90,60 @@
// the various seed outputs
logic [NumSeeds-1:0][SeedReads-1:0][BusWidth-1:0] seeds_q;
+ // Hamming distance histogram:
+ //
+ // 0: --
+ // 1: --
+ // 2: --
+ // 3: --
+ // 4: --
+ // 5: |||||||||||||||||||| (55.56%)
+ // 6: |||||||||||||||| (44.44%)
+ // 7: --
+ // 8: --
+ // 9: --
+ // 10: --
+ //
+ // Minimum Hamming distance: 5
+ // Maximum Hamming distance: 6
+ // Minimum Hamming weight: 5
+ // Maximum Hamming weight: 6
+ //
+ localparam int StateWidth = 10;
+
// progress through and read out the various pieces of content
// This FSM should become sparse, especially for StRmaRsp
- typedef enum logic [3:0] {
- StIdle,
- StReqAddrKey,
- StReqDataKey,
- StReadSeeds,
- StWait,
- StEntropyReseed,
- StRmaWipe,
- StRmaRsp,
- StInvalid
- } state_e;
+ typedef enum logic [StateWidth-1:0] {
+ StIdle = 10'b1001100110,
+ StReqAddrKey = 10'b1010101101,
+ StReqDataKey = 10'b0100110101,
+ StReadSeeds = 10'b1110010110,
+ StWait = 10'b1111000001,
+ StEntropyReseed = 10'b0011110011,
+ StRmaWipe = 10'b0011011100,
+ StRmaRsp = 10'b0101001111,
+ StInvalid = 10'b0110101010
+ } lcmgr_state_e;
- state_e state_q, state_d;
+ lcmgr_state_e state_q, state_d;
+ logic state_err;
+
+ // This primitive is used to place a size-only constraint on the
+ // flops in order to prevent FSM state encoding optimizations.
+ logic [StateWidth-1:0] state_raw_q;
+ assign state_q = lcmgr_state_e'(state_raw_q);
+ //SEC_CM: FSM.SPARSE
+ prim_sparse_fsm_flop #(
+ .StateEnumT(lcmgr_state_e),
+ .Width(StateWidth),
+ .ResetValue(StateWidth'(StIdle))
+ ) u_state_regs (
+ .clk_i,
+ .rst_ni,
+ .state_i ( state_d ),
+ .state_o ( state_raw_q )
+ );
+
lc_ctrl_pkg::lc_tx_t err_sts;
logic err_sts_set;
lc_ctrl_pkg::lc_tx_t rma_ack_d, rma_ack_q;
@@ -125,11 +164,9 @@
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
- state_q <= StIdle;
rma_ack_q <= lc_ctrl_pkg::Off;
validate_q <= 1'b0;
end else begin
- state_q <= state_d;
rma_ack_q <= rma_ack_d;
validate_q <= validate_d;
end
@@ -315,6 +352,8 @@
rma_wipe_req = 1'b0;
rma_wipe_idx_incr = 1'b0;
+ state_err = 1'b0;
+
unique case (state_q)
// If rma request is seen, directly transition to wipe.
@@ -433,10 +472,14 @@
end
end
- // Invalid catch-all state
- default: begin
+ StInvalid: begin
+ state_err = 1'b1;
phase = PhaseInvalid;
rma_ack_d = lc_ctrl_pkg::Off;
+ end
+
+ // Invalid catch-all state
+ default: begin
state_d = StInvalid;
end
@@ -474,14 +517,15 @@
// flops in order to prevent FSM state encoding optimizations.
logic [RmaStateWidth-1:0] rma_state_raw_q;
assign rma_state_q = rma_state_e'(rma_state_raw_q);
- prim_flop #(
+ prim_sparse_fsm_flop #(
+ .StateEnumT(rma_state_e),
.Width(RmaStateWidth),
.ResetValue(RmaStateWidth'(StRmaIdle))
- ) u_state_regs (
+ ) u_rma_state_regs (
.clk_i,
.rst_ni,
- .d_i ( rma_state_d ),
- .q_o ( rma_state_raw_q )
+ .state_i ( rma_state_d ),
+ .state_o ( rma_state_raw_q )
);
logic page_err_q, page_err_d;
@@ -691,11 +735,15 @@
end
end
- default: begin
+ StRmaInvalid: begin
err_sts_set = 1'b1;
fsm_err = 1'b1;
end
+ default: begin
+ rma_state_d = StRmaInvalid;
+ end
+
endcase // unique case (rma_state_q)
end // always_comb
@@ -720,7 +768,7 @@
assign rma_ack_o = rma_ack_q;
// all of these are considered fatal errors
- assign fatal_err_o = page_err_q | word_err_q | fsm_err;
+ assign fatal_err_o = page_err_q | word_err_q | fsm_err | state_err;
logic unused_seed_valid;
assign unused_seed_valid = otp_key_rsp_i.seed_valid;
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv
index 9a2684f..62a4b65 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv
@@ -585,13 +585,14 @@
//
localparam int RmaStateWidth = 10;
typedef enum logic [RmaStateWidth-1:0] {
- StRmaIdle = 10'b1000000111,
- StRmaPageSel = 10'b0110100101,
- StRmaErase = 10'b0100011100,
- StRmaWordSel = 10'b1011110010,
- StRmaProgram = 10'b0000111011,
- StRmaProgramWait = 10'b0011001000,
- StRmaRdVerify = 10'b1101101001
+ StRmaIdle = 10'b1101000011,
+ StRmaPageSel = 10'b0010111001,
+ StRmaErase = 10'b1111010100,
+ StRmaWordSel = 10'b0001011111,
+ StRmaProgram = 10'b0110001110,
+ StRmaProgramWait = 10'b1000110110,
+ StRmaRdVerify = 10'b1011101010,
+ StRmaInvalid = 10'b1100101101
} rma_state_e;
endpackage : flash_ctrl_pkg
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_reg_pkg.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_reg_pkg.sv
index 20747d3..bcc27c3 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_reg_pkg.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_reg_pkg.sv
@@ -507,6 +507,9 @@
} lcmgr_err;
struct packed {
logic q;
+ } arb_fsm_err;
+ struct packed {
+ logic q;
} storage_err;
} flash_ctrl_reg2hw_fault_status_reg_t;
@@ -684,6 +687,10 @@
struct packed {
logic d;
logic de;
+ } arb_fsm_err;
+ struct packed {
+ logic d;
+ logic de;
} storage_err;
} flash_ctrl_hw2reg_fault_status_reg_t;
@@ -719,33 +726,33 @@
// Register -> HW type for core interface
typedef struct packed {
- flash_ctrl_reg2hw_intr_state_reg_t intr_state; // [576:571]
- flash_ctrl_reg2hw_intr_enable_reg_t intr_enable; // [570:565]
- flash_ctrl_reg2hw_intr_test_reg_t intr_test; // [564:553]
- flash_ctrl_reg2hw_alert_test_reg_t alert_test; // [552:549]
- flash_ctrl_reg2hw_dis_reg_t dis; // [548:545]
- flash_ctrl_reg2hw_exec_reg_t exec; // [544:513]
- flash_ctrl_reg2hw_init_reg_t init; // [512:512]
- flash_ctrl_reg2hw_control_reg_t control; // [511:492]
- flash_ctrl_reg2hw_addr_reg_t addr; // [491:472]
- flash_ctrl_reg2hw_prog_type_en_reg_t prog_type_en; // [471:470]
- flash_ctrl_reg2hw_erase_suspend_reg_t erase_suspend; // [469:469]
- flash_ctrl_reg2hw_mp_region_cfg_shadowed_mreg_t [7:0] mp_region_cfg_shadowed; // [468:261]
- flash_ctrl_reg2hw_default_region_shadowed_reg_t default_region_shadowed; // [260:255]
+ flash_ctrl_reg2hw_intr_state_reg_t intr_state; // [577:572]
+ flash_ctrl_reg2hw_intr_enable_reg_t intr_enable; // [571:566]
+ flash_ctrl_reg2hw_intr_test_reg_t intr_test; // [565:554]
+ flash_ctrl_reg2hw_alert_test_reg_t alert_test; // [553:550]
+ flash_ctrl_reg2hw_dis_reg_t dis; // [549:546]
+ flash_ctrl_reg2hw_exec_reg_t exec; // [545:514]
+ flash_ctrl_reg2hw_init_reg_t init; // [513:513]
+ flash_ctrl_reg2hw_control_reg_t control; // [512:493]
+ flash_ctrl_reg2hw_addr_reg_t addr; // [492:473]
+ flash_ctrl_reg2hw_prog_type_en_reg_t prog_type_en; // [472:471]
+ flash_ctrl_reg2hw_erase_suspend_reg_t erase_suspend; // [470:470]
+ flash_ctrl_reg2hw_mp_region_cfg_shadowed_mreg_t [7:0] mp_region_cfg_shadowed; // [469:262]
+ flash_ctrl_reg2hw_default_region_shadowed_reg_t default_region_shadowed; // [261:256]
flash_ctrl_reg2hw_bank0_info0_page_cfg_shadowed_mreg_t [9:0]
- bank0_info0_page_cfg_shadowed; // [254:185]
+ bank0_info0_page_cfg_shadowed; // [255:186]
flash_ctrl_reg2hw_bank0_info1_page_cfg_shadowed_mreg_t [0:0]
- bank0_info1_page_cfg_shadowed; // [184:178]
+ bank0_info1_page_cfg_shadowed; // [185:179]
flash_ctrl_reg2hw_bank0_info2_page_cfg_shadowed_mreg_t [1:0]
- bank0_info2_page_cfg_shadowed; // [177:164]
+ bank0_info2_page_cfg_shadowed; // [178:165]
flash_ctrl_reg2hw_bank1_info0_page_cfg_shadowed_mreg_t [9:0]
- bank1_info0_page_cfg_shadowed; // [163:94]
+ bank1_info0_page_cfg_shadowed; // [164:95]
flash_ctrl_reg2hw_bank1_info1_page_cfg_shadowed_mreg_t [0:0]
- bank1_info1_page_cfg_shadowed; // [93:87]
+ bank1_info1_page_cfg_shadowed; // [94:88]
flash_ctrl_reg2hw_bank1_info2_page_cfg_shadowed_mreg_t [1:0]
- bank1_info2_page_cfg_shadowed; // [86:73]
- flash_ctrl_reg2hw_mp_bank_cfg_shadowed_mreg_t [1:0] mp_bank_cfg_shadowed; // [72:71]
- flash_ctrl_reg2hw_fault_status_reg_t fault_status; // [70:62]
+ bank1_info2_page_cfg_shadowed; // [87:74]
+ flash_ctrl_reg2hw_mp_bank_cfg_shadowed_mreg_t [1:0] mp_bank_cfg_shadowed; // [73:72]
+ flash_ctrl_reg2hw_fault_status_reg_t fault_status; // [71:62]
flash_ctrl_reg2hw_ecc_single_err_cnt_mreg_t [1:0] ecc_single_err_cnt; // [61:46]
flash_ctrl_reg2hw_phy_err_cfg_reg_t phy_err_cfg; // [45:45]
flash_ctrl_reg2hw_phy_alert_cfg_reg_t phy_alert_cfg; // [44:43]
@@ -756,14 +763,14 @@
// HW -> register type for core interface
typedef struct packed {
- flash_ctrl_hw2reg_intr_state_reg_t intr_state; // [147:136]
- flash_ctrl_hw2reg_ctrl_regwen_reg_t ctrl_regwen; // [135:135]
- flash_ctrl_hw2reg_control_reg_t control; // [134:133]
- flash_ctrl_hw2reg_erase_suspend_reg_t erase_suspend; // [132:131]
- flash_ctrl_hw2reg_op_status_reg_t op_status; // [130:127]
- flash_ctrl_hw2reg_status_reg_t status; // [126:117]
- flash_ctrl_hw2reg_err_code_reg_t err_code; // [116:105]
- flash_ctrl_hw2reg_fault_status_reg_t fault_status; // [104:87]
+ flash_ctrl_hw2reg_intr_state_reg_t intr_state; // [149:138]
+ flash_ctrl_hw2reg_ctrl_regwen_reg_t ctrl_regwen; // [137:137]
+ flash_ctrl_hw2reg_control_reg_t control; // [136:135]
+ flash_ctrl_hw2reg_erase_suspend_reg_t erase_suspend; // [134:133]
+ flash_ctrl_hw2reg_op_status_reg_t op_status; // [132:129]
+ flash_ctrl_hw2reg_status_reg_t status; // [128:119]
+ flash_ctrl_hw2reg_err_code_reg_t err_code; // [118:107]
+ flash_ctrl_hw2reg_fault_status_reg_t fault_status; // [106:87]
flash_ctrl_hw2reg_err_addr_reg_t err_addr; // [86:66]
flash_ctrl_hw2reg_ecc_single_err_cnt_mreg_t [1:0] ecc_single_err_cnt; // [65:48]
flash_ctrl_hw2reg_ecc_single_err_addr_mreg_t [1:0] ecc_single_err_addr; // [47:6]
diff --git a/hw/top_earlgrey/ip/flash_ctrl/data/autogen/flash_ctrl.hjson b/hw/top_earlgrey/ip/flash_ctrl/data/autogen/flash_ctrl.hjson
index ab4ac75..cb0939f 100644
--- a/hw/top_earlgrey/ip/flash_ctrl/data/autogen/flash_ctrl.hjson
+++ b/hw/top_earlgrey/ip/flash_ctrl/data/autogen/flash_ctrl.hjson
@@ -183,6 +183,10 @@
{ name: "BUS.INTEGRITY",
desc: "End-to-end bus integrity scheme."
}
+
+ { name: "FSM.SPARSE",
+ desc: "sparse fsm encoding in life cycle interface."
+ }
]
scan: "true", // Enable `scanmode_i` port
@@ -1574,6 +1578,12 @@
'''
},
{ bits: "9",
+ name: "arb_fsm_err",
+ desc: '''
+ The software / hardware interface has encountered a fatal error.
+ '''
+ },
+ { bits: "10",
name: "storage_err",
desc: '''
A shadow register encountered a storage fault.
diff --git a/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl.sv b/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl.sv
index 663aa25..d6d0659 100644
--- a/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl.sv
+++ b/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl.sv
@@ -223,6 +223,7 @@
logic sw_sel;
flash_lcmgr_phase_e hw_phase;
logic lcmgr_err;
+ logic arb_fsm_err;
// Flash control arbitration connections to software interface
logic sw_ctrl_done;
@@ -367,7 +368,8 @@
.phase_o(phase),
// indication that sw has been selected
- .sel_o(if_sel)
+ .sel_o(if_sel),
+ .fsm_err_o(arb_fsm_err)
);
assign op_start = muxed_ctrl.start.q;
@@ -922,6 +924,7 @@
assign hw2reg.fault_status.reg_intg_err.d = 1'b1;
assign hw2reg.fault_status.phy_intg_err.d = 1'b1;
assign hw2reg.fault_status.lcmgr_err.d = 1'b1;
+ assign hw2reg.fault_status.arb_fsm_err.d = 1'b1;
assign hw2reg.fault_status.storage_err.d = 1'b1;
assign hw2reg.fault_status.mp_err.de = hw_err.mp_err;
assign hw2reg.fault_status.rd_err.de = hw_err.rd_err;
@@ -931,6 +934,7 @@
assign hw2reg.fault_status.reg_intg_err.de = intg_err;
assign hw2reg.fault_status.phy_intg_err.de = flash_phy_rsp.intg_err;
assign hw2reg.fault_status.lcmgr_err.de = lcmgr_err;
+ assign hw2reg.fault_status.arb_fsm_err.de = arb_fsm_err;
assign hw2reg.fault_status.storage_err.de = storage_err;
// Correctable ECC count / address
@@ -1183,4 +1187,11 @@
alert_tx_o[0])
`ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(WordCntAlertCheck_A, u_flash_hw_if.u_word_cnt,
alert_tx_o[0])
+
+ `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(LcCtrlFsmCheck_A,
+ u_flash_hw_if.u_state_regs, alert_tx_o[0])
+ `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(LcCtrlRmaFsmCheck_A,
+ u_flash_hw_if.u_rma_state_regs, alert_tx_o[0])
+ `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(ArbFsmCheck_A,
+ u_ctrl_arb.u_state_regs, alert_tx_o[0])
endmodule
diff --git a/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl_core_reg_top.sv b/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl_core_reg_top.sv
index e7e2f79..510c7cc 100644
--- a/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl_core_reg_top.sv
+++ b/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl_core_reg_top.sv
@@ -973,6 +973,7 @@
logic fault_status_reg_intg_err_qs;
logic fault_status_phy_intg_err_qs;
logic fault_status_lcmgr_err_qs;
+ logic fault_status_arb_fsm_err_qs;
logic fault_status_storage_err_qs;
logic [19:0] err_addr_qs;
logic ecc_single_err_cnt_we;
@@ -11508,7 +11509,32 @@
.qs (fault_status_lcmgr_err_qs)
);
- // F[storage_err]: 9:9
+ // F[arb_fsm_err]: 9:9
+ prim_subreg #(
+ .DW (1),
+ .SwAccess(prim_subreg_pkg::SwAccessRO),
+ .RESVAL (1'h0)
+ ) u_fault_status_arb_fsm_err (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+
+ // from register interface
+ .we (1'b0),
+ .wd ('0),
+
+ // from internal hardware
+ .de (hw2reg.fault_status.arb_fsm_err.de),
+ .d (hw2reg.fault_status.arb_fsm_err.d),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.fault_status.arb_fsm_err.q),
+
+ // to register interface (read)
+ .qs (fault_status_arb_fsm_err_qs)
+ );
+
+ // F[storage_err]: 10:10
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessRO),
@@ -13603,7 +13629,8 @@
reg_rdata_next[6] = fault_status_reg_intg_err_qs;
reg_rdata_next[7] = fault_status_phy_intg_err_qs;
reg_rdata_next[8] = fault_status_lcmgr_err_qs;
- reg_rdata_next[9] = fault_status_storage_err_qs;
+ reg_rdata_next[9] = fault_status_arb_fsm_err_qs;
+ reg_rdata_next[10] = fault_status_storage_err_qs;
end
addr_hit[87]: begin
diff --git a/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl_pkg.sv b/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl_pkg.sv
index 035bf72..5adbe31 100644
--- a/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl_pkg.sv
+++ b/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl_pkg.sv
@@ -591,13 +591,14 @@
//
localparam int RmaStateWidth = 10;
typedef enum logic [RmaStateWidth-1:0] {
- StRmaIdle = 10'b1000000111,
- StRmaPageSel = 10'b0110100101,
- StRmaErase = 10'b0100011100,
- StRmaWordSel = 10'b1011110010,
- StRmaProgram = 10'b0000111011,
- StRmaProgramWait = 10'b0011001000,
- StRmaRdVerify = 10'b1101101001
+ StRmaIdle = 10'b1101000011,
+ StRmaPageSel = 10'b0010111001,
+ StRmaErase = 10'b1111010100,
+ StRmaWordSel = 10'b0001011111,
+ StRmaProgram = 10'b0110001110,
+ StRmaProgramWait = 10'b1000110110,
+ StRmaRdVerify = 10'b1011101010,
+ StRmaInvalid = 10'b1100101101
} rma_state_e;
endpackage : flash_ctrl_pkg
diff --git a/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl_reg_pkg.sv b/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl_reg_pkg.sv
index df55426..03f3024 100644
--- a/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl_reg_pkg.sv
+++ b/hw/top_earlgrey/ip/flash_ctrl/rtl/autogen/flash_ctrl_reg_pkg.sv
@@ -507,6 +507,9 @@
} lcmgr_err;
struct packed {
logic q;
+ } arb_fsm_err;
+ struct packed {
+ logic q;
} storage_err;
} flash_ctrl_reg2hw_fault_status_reg_t;
@@ -684,6 +687,10 @@
struct packed {
logic d;
logic de;
+ } arb_fsm_err;
+ struct packed {
+ logic d;
+ logic de;
} storage_err;
} flash_ctrl_hw2reg_fault_status_reg_t;
@@ -719,33 +726,33 @@
// Register -> HW type for core interface
typedef struct packed {
- flash_ctrl_reg2hw_intr_state_reg_t intr_state; // [576:571]
- flash_ctrl_reg2hw_intr_enable_reg_t intr_enable; // [570:565]
- flash_ctrl_reg2hw_intr_test_reg_t intr_test; // [564:553]
- flash_ctrl_reg2hw_alert_test_reg_t alert_test; // [552:549]
- flash_ctrl_reg2hw_dis_reg_t dis; // [548:545]
- flash_ctrl_reg2hw_exec_reg_t exec; // [544:513]
- flash_ctrl_reg2hw_init_reg_t init; // [512:512]
- flash_ctrl_reg2hw_control_reg_t control; // [511:492]
- flash_ctrl_reg2hw_addr_reg_t addr; // [491:472]
- flash_ctrl_reg2hw_prog_type_en_reg_t prog_type_en; // [471:470]
- flash_ctrl_reg2hw_erase_suspend_reg_t erase_suspend; // [469:469]
- flash_ctrl_reg2hw_mp_region_cfg_shadowed_mreg_t [7:0] mp_region_cfg_shadowed; // [468:261]
- flash_ctrl_reg2hw_default_region_shadowed_reg_t default_region_shadowed; // [260:255]
+ flash_ctrl_reg2hw_intr_state_reg_t intr_state; // [577:572]
+ flash_ctrl_reg2hw_intr_enable_reg_t intr_enable; // [571:566]
+ flash_ctrl_reg2hw_intr_test_reg_t intr_test; // [565:554]
+ flash_ctrl_reg2hw_alert_test_reg_t alert_test; // [553:550]
+ flash_ctrl_reg2hw_dis_reg_t dis; // [549:546]
+ flash_ctrl_reg2hw_exec_reg_t exec; // [545:514]
+ flash_ctrl_reg2hw_init_reg_t init; // [513:513]
+ flash_ctrl_reg2hw_control_reg_t control; // [512:493]
+ flash_ctrl_reg2hw_addr_reg_t addr; // [492:473]
+ flash_ctrl_reg2hw_prog_type_en_reg_t prog_type_en; // [472:471]
+ flash_ctrl_reg2hw_erase_suspend_reg_t erase_suspend; // [470:470]
+ flash_ctrl_reg2hw_mp_region_cfg_shadowed_mreg_t [7:0] mp_region_cfg_shadowed; // [469:262]
+ flash_ctrl_reg2hw_default_region_shadowed_reg_t default_region_shadowed; // [261:256]
flash_ctrl_reg2hw_bank0_info0_page_cfg_shadowed_mreg_t [9:0]
- bank0_info0_page_cfg_shadowed; // [254:185]
+ bank0_info0_page_cfg_shadowed; // [255:186]
flash_ctrl_reg2hw_bank0_info1_page_cfg_shadowed_mreg_t [0:0]
- bank0_info1_page_cfg_shadowed; // [184:178]
+ bank0_info1_page_cfg_shadowed; // [185:179]
flash_ctrl_reg2hw_bank0_info2_page_cfg_shadowed_mreg_t [1:0]
- bank0_info2_page_cfg_shadowed; // [177:164]
+ bank0_info2_page_cfg_shadowed; // [178:165]
flash_ctrl_reg2hw_bank1_info0_page_cfg_shadowed_mreg_t [9:0]
- bank1_info0_page_cfg_shadowed; // [163:94]
+ bank1_info0_page_cfg_shadowed; // [164:95]
flash_ctrl_reg2hw_bank1_info1_page_cfg_shadowed_mreg_t [0:0]
- bank1_info1_page_cfg_shadowed; // [93:87]
+ bank1_info1_page_cfg_shadowed; // [94:88]
flash_ctrl_reg2hw_bank1_info2_page_cfg_shadowed_mreg_t [1:0]
- bank1_info2_page_cfg_shadowed; // [86:73]
- flash_ctrl_reg2hw_mp_bank_cfg_shadowed_mreg_t [1:0] mp_bank_cfg_shadowed; // [72:71]
- flash_ctrl_reg2hw_fault_status_reg_t fault_status; // [70:62]
+ bank1_info2_page_cfg_shadowed; // [87:74]
+ flash_ctrl_reg2hw_mp_bank_cfg_shadowed_mreg_t [1:0] mp_bank_cfg_shadowed; // [73:72]
+ flash_ctrl_reg2hw_fault_status_reg_t fault_status; // [71:62]
flash_ctrl_reg2hw_ecc_single_err_cnt_mreg_t [1:0] ecc_single_err_cnt; // [61:46]
flash_ctrl_reg2hw_phy_err_cfg_reg_t phy_err_cfg; // [45:45]
flash_ctrl_reg2hw_phy_alert_cfg_reg_t phy_alert_cfg; // [44:43]
@@ -756,14 +763,14 @@
// HW -> register type for core interface
typedef struct packed {
- flash_ctrl_hw2reg_intr_state_reg_t intr_state; // [147:136]
- flash_ctrl_hw2reg_ctrl_regwen_reg_t ctrl_regwen; // [135:135]
- flash_ctrl_hw2reg_control_reg_t control; // [134:133]
- flash_ctrl_hw2reg_erase_suspend_reg_t erase_suspend; // [132:131]
- flash_ctrl_hw2reg_op_status_reg_t op_status; // [130:127]
- flash_ctrl_hw2reg_status_reg_t status; // [126:117]
- flash_ctrl_hw2reg_err_code_reg_t err_code; // [116:105]
- flash_ctrl_hw2reg_fault_status_reg_t fault_status; // [104:87]
+ flash_ctrl_hw2reg_intr_state_reg_t intr_state; // [149:138]
+ flash_ctrl_hw2reg_ctrl_regwen_reg_t ctrl_regwen; // [137:137]
+ flash_ctrl_hw2reg_control_reg_t control; // [136:135]
+ flash_ctrl_hw2reg_erase_suspend_reg_t erase_suspend; // [134:133]
+ flash_ctrl_hw2reg_op_status_reg_t op_status; // [132:129]
+ flash_ctrl_hw2reg_status_reg_t status; // [128:119]
+ flash_ctrl_hw2reg_err_code_reg_t err_code; // [118:107]
+ flash_ctrl_hw2reg_fault_status_reg_t fault_status; // [106:87]
flash_ctrl_hw2reg_err_addr_reg_t err_addr; // [86:66]
flash_ctrl_hw2reg_ecc_single_err_cnt_mreg_t [1:0] ecc_single_err_cnt; // [65:48]
flash_ctrl_hw2reg_ecc_single_err_addr_mreg_t [1:0] ecc_single_err_addr; // [47:6]