[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]