[prim] Add flop wrapper for sparse fsm
- Implements proposal from #9043
- The flop module used for anchoring the sparse state is
now wrapped another layer for streamlining DV.
- This follows the prim_count scheme very closely and should
standardize the alert hook-up testing for all modules.
- Once this PR is approved, similar changes will be made to all
blocks that utilize sparse FSM.
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/keymgr/keymgr.core b/hw/ip/keymgr/keymgr.core
index c1a0a4f..358b6cc 100644
--- a/hw/ip/keymgr/keymgr.core
+++ b/hw/ip/keymgr/keymgr.core
@@ -8,17 +8,18 @@
filesets:
files_rtl:
depend:
- - lowrisc:ip:tlul
- lowrisc:prim:all
- lowrisc:prim:count
- - lowrisc:prim:lfsr
- lowrisc:prim:lc_sync
+ - lowrisc:prim:lfsr
- lowrisc:prim:msb_extend
+ - lowrisc:prim:sparse_fsm
- lowrisc:ip:flash_ctrl_pkg
- lowrisc:ip:keymgr_pkg
- lowrisc:ip:kmac_pkg
- lowrisc:ip:otp_ctrl_pkg
- lowrisc:ip:rom_ctrl_pkg
+ - lowrisc:ip:tlul
files:
- rtl/keymgr_reg_top.sv
- rtl/keymgr_sideload_key_ctrl.sv
diff --git a/hw/ip/keymgr/rtl/keymgr.sv b/hw/ip/keymgr/rtl/keymgr.sv
index bb83ec1..0598965 100644
--- a/hw/ip/keymgr/rtl/keymgr.sv
+++ b/hw/ip/keymgr/rtl/keymgr.sv
@@ -657,4 +657,5 @@
`ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(KmacIfCntAlertCheck_A, u_kmac_if.u_cnt, alert_tx_o[0])
`ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(ReseedCtrlCntAlertCheck_A, u_reseed_ctrl.u_reseed_cnt,
alert_tx_o[0])
+ `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(CtrlMainFsmCheck_A, u_ctrl.u_state_regs, alert_tx_o[0])
endmodule // keymgr
diff --git a/hw/ip/keymgr/rtl/keymgr_ctrl.sv b/hw/ip/keymgr/rtl/keymgr_ctrl.sv
index a1af5c8..abf4bbd 100644
--- a/hw/ip/keymgr/rtl/keymgr_ctrl.sv
+++ b/hw/ip/keymgr/rtl/keymgr_ctrl.sv
@@ -236,17 +236,17 @@
//////////////////////////
// Main Control FSM
//////////////////////////
-
logic [StateWidth-1:0] state_raw_q;
assign state_q = keymgr_ctrl_state_e'(state_raw_q);
- prim_flop #(
+ prim_sparse_fsm_flop #(
+ .StateEnumT(keymgr_ctrl_state_e),
.Width(StateWidth),
.ResetValue(StateWidth'(StCtrlReset))
) u_state_regs (
.clk_i,
.rst_ni,
- .d_i ( state_d ),
- .q_o ( state_raw_q )
+ .state_i ( state_d ),
+ .state_o ( state_raw_q )
);
always_ff @(posedge clk_i or negedge rst_ni) begin
diff --git a/hw/ip/prim/prim_sparse_fsm.core b/hw/ip/prim/prim_sparse_fsm.core
new file mode 100644
index 0000000..5367085
--- /dev/null
+++ b/hw/ip/prim/prim_sparse_fsm.core
@@ -0,0 +1,37 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+
+name: "lowrisc:prim:sparse_fsm"
+description: ""
+filesets:
+ files_rtl:
+ depend:
+ - lowrisc:prim:assert
+ files:
+ - rtl/prim_sparse_fsm_flop.sv
+ file_type: systemVerilogSource
+
+ files_verilator_waiver:
+ depend:
+ # common waivers
+ - lowrisc:lint:common
+
+ files_ascentlint_waiver:
+ depend:
+ # common waivers
+ - lowrisc:lint:common
+
+ files_veriblelint_waiver:
+ depend:
+ # common waivers
+ - lowrisc:lint:common
+
+targets:
+ default:
+ filesets:
+ - tool_verilator ? (files_verilator_waiver)
+ - tool_ascentlint ? (files_ascentlint_waiver)
+ - tool_veriblelint ? (files_veriblelint_waiver)
+ - files_rtl
diff --git a/hw/ip/prim/rtl/prim_lc_sync.sv b/hw/ip/prim/rtl/prim_lc_sync.sv
index d575674..b61343c 100644
--- a/hw/ip/prim/rtl/prim_lc_sync.sv
+++ b/hw/ip/prim/rtl/prim_lc_sync.sv
@@ -30,7 +30,7 @@
output lc_ctrl_pkg::lc_tx_t [NumCopies-1:0] lc_en_o
);
- localparam lc_ctrl_pkg::lc_tx_t ResetValue = (ResetValueIsOn) ? lc_ctrl_pkg::On :
+ localparam lc_ctrl_pkg::lc_tx_t LcResetValue = (ResetValueIsOn) ? lc_ctrl_pkg::On :
lc_ctrl_pkg::Off;
`ASSERT_INIT(NumCopiesMustBeGreaterZero_A, NumCopies > 0)
@@ -39,7 +39,7 @@
if (AsyncOn) begin : gen_flops
prim_flop_2sync #(
.Width(lc_ctrl_pkg::TxWidth),
- .ResetValue(lc_ctrl_pkg::TxWidth'(ResetValue))
+ .ResetValue(lc_ctrl_pkg::TxWidth'(LcResetValue))
) u_prim_flop_2sync (
.clk_i,
.rst_ni,
diff --git a/hw/ip/prim/rtl/prim_sparse_fsm_flop.sv b/hw/ip/prim/rtl/prim_sparse_fsm_flop.sv
new file mode 100644
index 0000000..ab29d7c
--- /dev/null
+++ b/hw/ip/prim/rtl/prim_sparse_fsm_flop.sv
@@ -0,0 +1,55 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+`include "prim_assert.sv"
+
+module prim_sparse_fsm_flop #(
+ parameter type StateEnumT = logic,
+ parameter int Width = 1,
+ parameter logic [Width-1:0] ResetValue = 0
+) (
+ input clk_i,
+ input rst_ni,
+ input [Width-1:0] state_i,
+ output logic [Width-1:0] state_o
+);
+
+ logic unused_valid_st;
+
+ prim_flop #(
+ .Width(Width),
+ .ResetValue(ResetValue)
+ ) u_state_flop (
+ .clk_i,
+ .rst_ni,
+ .d_i(state_i),
+ .q_o(state_o)
+ );
+
+ `ifdef INC_ASSERT
+ StateEnumT tmp;
+ assign unused_valid_st = $cast(tmp, state_o);
+ `else
+ assign unused_valid_st = 1'b1;
+ `endif
+
+ // If ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT is declared, the unused_assert_connected signal will
+ // be set to 1 and the below check will pass.
+ // If the assertion is not declared however, the statement below will fail.
+ `ifdef INC_ASSERT
+ logic unused_assert_connected;
+
+ // ASSERT_INIT can only be used for paramters/constants in FPV.
+ `ifdef SIMULATION
+ `ASSERT_INIT(AssertConnected_A, unused_assert_connected === 1'b1)
+ `endif
+ `endif
+
+endmodule
+
+`define ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(NAME_, PRIM_HIER_, ALERT_, MAX_CYCLES_ = 5) \
+ `ASSERT(NAME_, $fell(PRIM_HIER_.unused_valid_st) |-> ##[1:MAX_CYCLES_] $rose(ALERT_.alert_p)) \
+ `ifdef INC_ASSERT \
+ assign PRIM_HIER_.unused_assert_connected = 1'b1; \
+ `endif
diff --git a/util/design/sparse-fsm-encode.py b/util/design/sparse-fsm-encode.py
index 22f31c5..fc7817f 100755
--- a/util/design/sparse-fsm-encode.py
+++ b/util/design/sparse-fsm-encode.py
@@ -239,14 +239,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'(State0))
) u_state_regs (
.clk_i,
.rst_ni,
- .d_i ( state_d ),
- .q_o ( state_raw_q )
+ .state_i ( state_d ),
+ .state_o ( state_raw_q )
);
'''.format(state_str))