[lc_ctrl] Switch to sparse fsm primitive
Signed-off-by: Michael Schaffner <msf@opentitan.org>
diff --git a/hw/ip/lc_ctrl/dv/env/lc_ctrl_if.sv b/hw/ip/lc_ctrl/dv/env/lc_ctrl_if.sv
index cb0e1de..d237af5 100644
--- a/hw/ip/lc_ctrl/dv/env/lc_ctrl_if.sv
+++ b/hw/ip/lc_ctrl/dv/env/lc_ctrl_if.sv
@@ -6,7 +6,7 @@
`ifndef LC_CTRL_FSM_STATE_REGS_PATH
`define LC_CTRL_FSM_STATE_REGS_PATH \
- tb.dut.u_lc_ctrl_fsm.u_fsm_state_regs.gen_generic.u_impl_generic.d_i
+ tb.dut.u_lc_ctrl_fsm.u_fsm_state_regs.u_state_flop.gen_generic.u_impl_generic.d_i
`endif
`ifndef LC_CTRL_FSM_COUNT_REGS_PATH
diff --git a/hw/ip/lc_ctrl/lc_ctrl.core b/hw/ip/lc_ctrl/lc_ctrl.core
index e15ef19..27833e9 100644
--- a/hw/ip/lc_ctrl/lc_ctrl.core
+++ b/hw/ip/lc_ctrl/lc_ctrl.core
@@ -14,6 +14,7 @@
- lowrisc:prim:lc_sync
- lowrisc:prim:lc_sender
- lowrisc:prim:mubi
+ - lowrisc:prim:sparse_fsm
- lowrisc:ip:lc_ctrl_pkg
- lowrisc:ip:tlul
- lowrisc:ip:pwrmgr_pkg
diff --git a/hw/ip/lc_ctrl/rtl/lc_ctrl.sv b/hw/ip/lc_ctrl/rtl/lc_ctrl.sv
index 0502576..0b60236 100644
--- a/hw/ip/lc_ctrl/rtl/lc_ctrl.sv
+++ b/hw/ip/lc_ctrl/rtl/lc_ctrl.sv
@@ -581,7 +581,7 @@
// KMAC Interface //
////////////////////
- logic token_hash_req, token_hash_req_chk, token_hash_ack, token_hash_err;
+ logic token_hash_req, token_hash_req_chk, token_hash_ack, token_hash_err, token_if_fsm_err;
lc_token_t hashed_token;
lc_ctrl_kmac_if u_lc_ctrl_kmac_if (
.clk_i,
@@ -595,6 +595,7 @@
.token_hash_req_chk_i ( token_hash_req_chk ),
.token_hash_ack_o ( token_hash_ack ),
.token_hash_err_o ( token_hash_err ),
+ .token_if_fsm_err_o ( token_if_fsm_err ),
.hashed_token_o ( hashed_token )
);
@@ -633,6 +634,7 @@
.token_hash_req_chk_o ( token_hash_req_chk ),
.token_hash_ack_i ( token_hash_ack ),
.token_hash_err_i ( token_hash_err ),
+ .token_if_fsm_err_i ( token_if_fsm_err ),
.hashed_token_i ( hashed_token ),
.otp_prog_req_o ( lc_otp_program_o.req ),
.otp_prog_lc_state_o ( lc_otp_program_o.state ),
@@ -692,4 +694,10 @@
`ASSERT_KNOWN(LcFlashRmaReqKnown_A, lc_flash_rma_req_o )
`ASSERT_KNOWN(LcKeymgrDiv_A, lc_keymgr_div_o )
+ // Alert assertions for sparse FSMs.
+ `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(CtrlLcFsmCheck_A,
+ u_lc_ctrl_fsm.u_fsm_state_regs, alert_tx_o[1])
+ `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(CtrlKmacIfFsmCheck_A,
+ u_lc_ctrl_kmac_if.u_state_regs, alert_tx_o[1])
+
endmodule : lc_ctrl
diff --git a/hw/ip/lc_ctrl/rtl/lc_ctrl_fsm.sv b/hw/ip/lc_ctrl/rtl/lc_ctrl_fsm.sv
index 7e82f07..eea2de2 100644
--- a/hw/ip/lc_ctrl/rtl/lc_ctrl_fsm.sv
+++ b/hw/ip/lc_ctrl/rtl/lc_ctrl_fsm.sv
@@ -48,6 +48,7 @@
output logic token_hash_req_chk_o,
input token_hash_ack_i,
input token_hash_err_i,
+ input token_if_fsm_err_i,
input lc_token_t hashed_token_i,
// OTP programming interface
output logic otp_prog_req_o,
@@ -416,11 +417,11 @@
///////////////////////////////////////////////////////////////////
endcase
- // If at any time the life cycle state encoding is not valid,
- // we jump into the terminal error state right away.
+ // If at any time the life cycle state encoding or any other FSM state within this module
+ // is not valid, we jump into the terminal error state right away.
// Note that state_invalid_error is a multibit error signal
// with different error sources - need to reduce this to one bit here.
- if (|state_invalid_error) begin
+ if (|state_invalid_error | token_if_fsm_err_i) begin
fsm_state_d = InvalidSt;
state_invalid_error_o = 1'b1;
end else if (esc_scrap_state0_i || esc_scrap_state1_i) begin
@@ -436,14 +437,15 @@
// flops in order to prevent FSM state encoding optimizations.
logic [FsmStateWidth-1:0] fsm_state_raw_q;
assign fsm_state_q = fsm_state_e'(fsm_state_raw_q);
- prim_flop #(
+ prim_sparse_fsm_flop #(
+ .StateEnumT(fsm_state_e),
.Width(FsmStateWidth),
.ResetValue(FsmStateWidth'(ResetSt))
) u_fsm_state_regs (
.clk_i,
.rst_ni,
- .d_i ( fsm_state_d ),
- .q_o ( fsm_state_raw_q )
+ .state_i ( fsm_state_d ),
+ .state_o ( fsm_state_raw_q )
);
logic [LcStateWidth-1:0] lc_state_raw_q;
diff --git a/hw/ip/lc_ctrl/rtl/lc_ctrl_kmac_if.sv b/hw/ip/lc_ctrl/rtl/lc_ctrl_kmac_if.sv
index 6949d55..00b7202 100644
--- a/hw/ip/lc_ctrl/rtl/lc_ctrl_kmac_if.sv
+++ b/hw/ip/lc_ctrl/rtl/lc_ctrl_kmac_if.sv
@@ -26,8 +26,9 @@
input token_hash_req_i,
// Used for gating assertions inside CDC primitives.
input token_hash_req_chk_i,
- output token_hash_ack_o,
- output token_hash_err_o,
+ output logic token_hash_ack_o,
+ output logic token_hash_err_o,
+ output logic token_if_fsm_err_o,
output lc_token_t hashed_token_o
);
@@ -141,15 +142,15 @@
//
// Minimum Hamming distance: 5
// Maximum Hamming distance: 6
- // Minimum Hamming weight: 1
+ // Minimum Hamming weight: 2
// Maximum Hamming weight: 6
//
localparam int StateWidth = 8;
typedef enum logic [StateWidth-1:0] {
- FirstSt = 8'b00000001,
- SecondSt = 8'b11110011,
- WaitSt = 8'b10111100,
- DoneSt = 8'b01001110
+ FirstSt = 8'b01011011,
+ SecondSt = 8'b10010100,
+ WaitSt = 8'b11100111,
+ DoneSt = 8'b00101000
} state_e;
state_e state_d, state_q;
@@ -159,6 +160,7 @@
state_d = state_q;
kmac_data_o = '0;
kmac_ack = 1'b0;
+ token_if_fsm_err_o = 1'b0;
unique case (state_q)
// Wait for request and transfer first half of
@@ -193,7 +195,9 @@
// Terminal state (by design we can only perform
// one token hashing operation per reset cycle).
DoneSt: ;
- default: state_d = DoneSt;
+ default: begin
+ token_if_fsm_err_o = 1'b1;
+ end
endcase // state_q
end
@@ -201,14 +205,15 @@
// flops in order to prevent FSM state encoding optimizations.
logic [StateWidth-1:0] state_raw_q;
assign state_q = state_e'(state_raw_q);
- prim_flop #(
+ prim_sparse_fsm_flop #(
+ .StateEnumT(state_e),
.Width(StateWidth),
.ResetValue(StateWidth'(FirstSt))
) u_state_regs (
- .clk_i ( clk_kmac_i ),
- .rst_ni ( rst_kmac_ni ),
- .d_i ( state_d ),
- .q_o ( state_raw_q )
+ .clk_i ( clk_kmac_i ),
+ .rst_ni ( rst_kmac_ni ),
+ .state_i ( state_d ),
+ .state_o ( state_raw_q )
);
endmodule : lc_ctrl_kmac_if
diff --git a/hw/ip/lc_ctrl/rtl/lc_ctrl_pkg.sv b/hw/ip/lc_ctrl/rtl/lc_ctrl_pkg.sv
index 98cd875..2545145 100644
--- a/hw/ip/lc_ctrl/rtl/lc_ctrl_pkg.sv
+++ b/hw/ip/lc_ctrl/rtl/lc_ctrl_pkg.sv
@@ -62,14 +62,14 @@
// 3: --
// 4: --
// 5: ||||||| (7.62%)
- // 6: |||||||||| (10.48%)
- // 7: ||||||||||||||||| (17.14%)
- // 8: |||||||||||||||||||| (20.00%)
- // 9: ||||||||||||||||||| (19.05%)
- // 10: |||||||||||||| (14.29%)
+ // 6: ||||||||| (9.52%)
+ // 7: |||||||||||||||| (17.14%)
+ // 8: |||||||||||||||||||| (20.95%)
+ // 9: ||||||||||||||||| (18.10%)
+ // 10: ||||||||||||| (14.29%)
// 11: |||||| (6.67%)
// 12: ||| (3.81%)
- // 13: (0.95%)
+ // 13: | (1.90%)
// 14: --
// 15: --
// 16: --
@@ -81,13 +81,13 @@
//
localparam int FsmStateWidth = 16;
typedef enum logic [FsmStateWidth-1:0] {
- ResetSt = 16'b1100000001111011,
- IdleSt = 16'b1111011010111100,
- ClkMuxSt = 16'b0000011110101101,
- CntIncrSt = 16'b1100111011001001,
- CntProgSt = 16'b0011001111000111,
- TransCheckSt = 16'b0000110001010100,
- TokenHashSt = 16'b0110111010110000,
+ ResetSt = 16'b1111011010111100,
+ IdleSt = 16'b0000011110101101,
+ ClkMuxSt = 16'b1100111011001001,
+ CntIncrSt = 16'b0011001111000111,
+ CntProgSt = 16'b0000110001010100,
+ TransCheckSt = 16'b0110111010110000,
+ TokenHashSt = 16'b1101001000111111,
FlashRmaSt = 16'b1110100010001111,
TokenCheck0St = 16'b0010000011000000,
TokenCheck1St = 16'b1101010101101111,