[all] Introduce sparse FSM macro

Signed-off-by: Michael Schaffner <msf@opentitan.org>
diff --git a/hw/ip/aes/rtl/aes_cipher_control_fsm.sv b/hw/ip/aes/rtl/aes_cipher_control_fsm.sv
index ad9ebe8..feceee5 100644
--- a/hw/ip/aes/rtl/aes_cipher_control_fsm.sv
+++ b/hw/ip/aes/rtl/aes_cipher_control_fsm.sv
@@ -476,20 +476,8 @@
   end
 
   // SEC_CM: CIPHER.FSM.SPARSE
-  // 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] aes_cipher_ctrl_cs_raw;
-  assign aes_cipher_ctrl_cs = aes_cipher_ctrl_e'(aes_cipher_ctrl_cs_raw);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(aes_cipher_ctrl_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(IDLE))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( aes_cipher_ctrl_ns     ),
-    .state_o ( aes_cipher_ctrl_cs_raw )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, aes_cipher_ctrl_ns,
+      aes_cipher_ctrl_cs, aes_cipher_ctrl_e, IDLE)
 
   always_ff @(posedge clk_i or negedge rst_ni) begin : reg_fsm
     if (!rst_ni) begin
diff --git a/hw/ip/aes/rtl/aes_control_fsm.sv b/hw/ip/aes/rtl/aes_control_fsm.sv
index 2cc7279..e6b9171 100644
--- a/hw/ip/aes/rtl/aes_control_fsm.sv
+++ b/hw/ip/aes/rtl/aes_control_fsm.sv
@@ -651,20 +651,7 @@
   end
 
   // SEC_CM: MAIN.FSM.SPARSE
-  // 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] aes_ctrl_cs_raw;
-  assign aes_ctrl_cs = aes_ctrl_e'(aes_ctrl_cs_raw);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(aes_ctrl_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(IDLE))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( aes_ctrl_ns     ),
-    .state_o ( aes_ctrl_cs_raw )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, aes_ctrl_ns, aes_ctrl_cs, aes_ctrl_e, IDLE)
 
   always_ff @(posedge clk_i or negedge rst_ni) begin : reg_fsm
     if (!rst_ni) begin
diff --git a/hw/ip/aes/rtl/aes_ctr_fsm.sv b/hw/ip/aes/rtl/aes_ctr_fsm.sv
index 23f6648..65d1ec6 100644
--- a/hw/ip/aes/rtl/aes_ctr_fsm.sv
+++ b/hw/ip/aes/rtl/aes_ctr_fsm.sv
@@ -131,20 +131,7 @@
   end
 
   // SEC_CM: CTR.FSM.SPARSE
-  // 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] aes_ctr_cs_raw;
-  assign aes_ctr_cs = aes_ctr_e'(aes_ctr_cs_raw);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(aes_ctr_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(IDLE))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( aes_ctr_ns     ),
-    .state_o ( aes_ctr_cs_raw )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, aes_ctr_ns, aes_ctr_cs, aes_ctr_e, IDLE)
 
   // Forward slice index.
   assign ctr_slice_idx_o = ctr_slice_idx_q;
diff --git a/hw/ip/csrng/rtl/csrng_cmd_stage.sv b/hw/ip/csrng/rtl/csrng_cmd_stage.sv
index 1417a06..281c58a 100644
--- a/hw/ip/csrng/rtl/csrng_cmd_stage.sv
+++ b/hw/ip/csrng/rtl/csrng_cmd_stage.sv
@@ -234,23 +234,7 @@
   } state_e;
 
   state_e state_d, state_q;
-
-  logic [StateWidth-1:0] state_raw_q;
-
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(Idle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d ),
-    .state_o ( state_raw_q )
-  );
-
-  assign state_q = state_e'(state_raw_q);
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, Idle)
 
   always_comb begin
     state_d = state_q;
diff --git a/hw/ip/csrng/rtl/csrng_ctr_drbg_gen.sv b/hw/ip/csrng/rtl/csrng_ctr_drbg_gen.sv
index d8d870e..b8f2163 100644
--- a/hw/ip/csrng/rtl/csrng_ctr_drbg_gen.sv
+++ b/hw/ip/csrng/rtl/csrng_ctr_drbg_gen.sv
@@ -215,24 +215,8 @@
 
   state_e state_d, state_q;
 
-  logic [StateWidth-1:0] state_raw_q;
-
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
-
   // SEC_CM: UPDATE.FSM.SPARSE
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(ReqIdle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d ),
-    .state_o ( state_raw_q )
-  );
-
-  assign state_q = state_e'(state_raw_q);
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ReqIdle)
 
   always_ff @(posedge clk_i or negedge rst_ni)
     if (!rst_ni) begin
diff --git a/hw/ip/csrng/rtl/csrng_ctr_drbg_upd.sv b/hw/ip/csrng/rtl/csrng_ctr_drbg_upd.sv
index 7131e41..a1aebaa 100644
--- a/hw/ip/csrng/rtl/csrng_ctr_drbg_upd.sv
+++ b/hw/ip/csrng/rtl/csrng_ctr_drbg_upd.sv
@@ -183,24 +183,9 @@
 
   blk_enc_state_e blk_enc_state_d, blk_enc_state_q;
 
-  logic [BlkEncStateWidth-1:0] blk_enc_state_raw_q;
-
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
-
   // SEC_CM: BLK_ENC.FSM.SPARSE
-  prim_sparse_fsm_flop #(
-    .StateEnumT(blk_enc_state_e),
-    .Width(BlkEncStateWidth),
-    .ResetValue(BlkEncStateWidth'(ReqIdle))
-  ) u_blk_enc_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( blk_enc_state_d ),
-    .state_o ( blk_enc_state_raw_q )
-  );
-
-  assign blk_enc_state_q = blk_enc_state_e'(blk_enc_state_raw_q);
+  `PRIM_FLOP_SPARSE_FSM(u_blk_enc_state_regs, blk_enc_state_d,
+      blk_enc_state_q, blk_enc_state_e, ReqIdle)
 
 // Encoding generated with:
 // $ ./util/design/sparse-fsm-encode.py -d 3 -m 4 -n 6 \
@@ -232,24 +217,9 @@
 
   outblk_state_e outblk_state_d, outblk_state_q;
 
-  logic [OutBlkStateWidth-1:0] outblk_state_raw_q;
-
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
-
   // SEC_CM: OUTBLK.FSM.SPARSE
-  prim_sparse_fsm_flop #(
-    .StateEnumT(outblk_state_e),
-    .Width(OutBlkStateWidth),
-    .ResetValue(OutBlkStateWidth'(AckIdle))
-  ) u_outblk_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( outblk_state_d ),
-    .state_o ( outblk_state_raw_q )
-  );
-
-  assign outblk_state_q = outblk_state_e'(outblk_state_raw_q);
+  `PRIM_FLOP_SPARSE_FSM(u_outblk_state_regs, outblk_state_d,
+      outblk_state_q, outblk_state_e, AckIdle)
 
   always_ff @(posedge clk_i or negedge rst_ni)
     if (!rst_ni) begin
diff --git a/hw/ip/csrng/rtl/csrng_main_sm.sv b/hw/ip/csrng/rtl/csrng_main_sm.sv
index 19020b6..21f25e4 100644
--- a/hw/ip/csrng/rtl/csrng_main_sm.sv
+++ b/hw/ip/csrng/rtl/csrng_main_sm.sv
@@ -73,25 +73,9 @@
   } state_e;
 
   state_e state_d, state_q;
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, Idle)
 
-  logic [StateWidth-1:0] state_raw_q;
-
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
-
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(Idle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d ),
-    .state_o ( state_raw_q )
-  );
-
-  assign state_q = state_e'(state_raw_q);
-  assign main_sm_state_o = state_raw_q;
+  assign main_sm_state_o = {state_q};
 
   always_comb begin
     state_d = state_q;
diff --git a/hw/ip/edn/rtl/edn_ack_sm.sv b/hw/ip/edn/rtl/edn_ack_sm.sv
index 9ac94b3..143ac75 100644
--- a/hw/ip/edn/rtl/edn_ack_sm.sv
+++ b/hw/ip/edn/rtl/edn_ack_sm.sv
@@ -47,24 +47,7 @@
 
   state_e state_d, state_q;
 
-  logic [StateWidth-1:0] state_raw_q;
-
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
-
-
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(Idle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d ),
-    .state_o ( state_raw_q )
-  );
-
-  assign state_q = state_e'(state_raw_q);
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, Idle)
 
   always_comb begin
     state_d = state_q;
diff --git a/hw/ip/edn/rtl/edn_main_sm.sv b/hw/ip/edn/rtl/edn_main_sm.sv
index a46d95d..cebbc08 100644
--- a/hw/ip/edn/rtl/edn_main_sm.sv
+++ b/hw/ip/edn/rtl/edn_main_sm.sv
@@ -80,25 +80,9 @@
 
   state_e state_d, state_q;
 
-  logic [StateWidth-1:0] state_raw_q;
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, Idle)
 
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
-
-
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(Idle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d ),
-    .state_o ( state_raw_q )
-  );
-
-  assign state_q = state_e'(state_raw_q);
-  assign main_sm_state_o = state_raw_q;
+  assign main_sm_state_o = state_q;
 
   assign main_sm_busy_o = (state_q != Idle) && (state_q != BootPulse) &&
          (state_q != BootDone) && (state_q != SWPortMode);
diff --git a/hw/ip/entropy_src/rtl/entropy_src_ack_sm.sv b/hw/ip/entropy_src/rtl/entropy_src_ack_sm.sv
index b0ca079..b4d0e17 100644
--- a/hw/ip/entropy_src/rtl/entropy_src_ack_sm.sv
+++ b/hw/ip/entropy_src/rtl/entropy_src_ack_sm.sv
@@ -48,23 +48,7 @@
 
   state_e state_d, state_q;
 
-  logic [StateWidth-1:0] state_raw_q;
-
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
-
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(Idle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d ),
-    .state_o ( state_raw_q )
-  );
-
-  assign state_q = state_e'(state_raw_q);
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, Idle)
 
   always_comb begin
     state_d = state_q;
diff --git a/hw/ip/entropy_src/rtl/entropy_src_main_sm.sv b/hw/ip/entropy_src/rtl/entropy_src_main_sm.sv
index c7a874c..e449044 100644
--- a/hw/ip/entropy_src/rtl/entropy_src_main_sm.sv
+++ b/hw/ip/entropy_src/rtl/entropy_src_main_sm.sv
@@ -88,24 +88,9 @@
 
   state_e state_d, state_q;
 
-  logic [StateWidth-1:0] state_raw_q;
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, Idle)
 
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
-
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(Idle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d ),
-    .state_o ( state_raw_q )
-  );
-
-  assign state_q = state_e'(state_raw_q);
-  assign main_sm_state_o = state_raw_q;
+  assign main_sm_state_o = state_q;
 
   always_comb begin
     state_d = state_q;
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv
index 4ddd3c0..4fb9ec4 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv
@@ -129,21 +129,8 @@
   logic sw_req;
   assign sw_req = sw_ctrl_i.start.q;
 
-  // 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);
   // SEC_CM: FSM.SPARSE
-  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 )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, arb_state_e, StReset)
 
   always_comb begin
 
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_lcmgr.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_lcmgr.sv
index 9ce2d09..4960252 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_lcmgr.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_lcmgr.sv
@@ -132,21 +132,8 @@
   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 )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, lcmgr_state_e, StIdle)
 
   lc_ctrl_pkg::lc_tx_t err_sts_d, err_sts_q;
   logic err_sts_set;
@@ -546,21 +533,8 @@
                     RmaWipeEntries[rma_wipe_idx].num_pages;
 
   rma_state_e rma_state_d, rma_state_q;
-  // This primitive is used to place a size-only constraint on the
-  // 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);
   // SEC_CM: FSM.SPARSE
-  prim_sparse_fsm_flop #(
-    .StateEnumT(rma_state_e),
-    .Width(RmaStateWidth),
-    .ResetValue(RmaStateWidth'(StRmaIdle))
-  ) u_rma_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( rma_state_d ),
-    .state_o ( rma_state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_rma_state_regs, rma_state_d, rma_state_q, rma_state_e, StRmaIdle)
 
   // SEC_CM: CTR.SPARSE
   logic page_err_q, page_err_d;
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_core.sv b/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
index cd2659b..23b6952 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
@@ -159,21 +159,8 @@
   import prim_mubi_pkg::mubi4_test_false_strict;
   import prim_mubi_pkg::mubi4_test_true_loose;
 
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
   // SEC_CM: PHY.FSM.SPARSE
-  logic [StateWidth-1:0] state_raw_q;
-  assign state_q = state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(StIdle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, StIdle)
 
   typedef enum logic [2:0] {
     HostDisableIdx,
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv b/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv
index b6f8f5e..420e139 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv
@@ -157,21 +157,8 @@
     end
   end
 
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
   // SEC_CM: PHY.FSM.SPARSE
-  logic [StateWidth-1:0] state_raw_q;
-  assign state_q = state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(StIdle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, StIdle)
 
   // If the first beat of an incoming transaction is not aligned to word boundary (for example
   // if each flash word is 4 bus words wide, and the first word to program starts at index 1),
diff --git a/hw/ip/keymgr/dv/env/keymgr_if.sv b/hw/ip/keymgr/dv/env/keymgr_if.sv
index e4d717e..2a426e8 100644
--- a/hw/ip/keymgr/dv/env/keymgr_if.sv
+++ b/hw/ip/keymgr/dv/env/keymgr_if.sv
@@ -379,19 +379,19 @@
       end
       1: begin
         `uvm_info(msg_id, "Force KMC_IF FSM", UVM_LOW)
-        prev_state = tb.dut.u_kmac_if.state_raw_q;
+        prev_state = tb.dut.u_kmac_if.u_state_regs.state_raw;
         `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(invalid_state,
             !(invalid_state inside {KmacIfValidStates});,
             , msg_id)
 
-        force tb.dut.u_kmac_if.state_raw_q = invalid_state;
+        force tb.dut.u_kmac_if.u_state_regs.state_raw = invalid_state;
         @(posedge clk);
 
         if ($urandom_range(0, 1)) begin
-          force tb.dut.u_kmac_if.state_raw_q = prev_state;
+          force tb.dut.u_kmac_if.u_state_regs.state_raw = prev_state;
           @(posedge clk);
         end
-        release tb.dut.u_kmac_if.state_raw_q;
+        release tb.dut.u_kmac_if.u_state_regs.state_raw;
         is_kmac_if_fsm_err = 1;
       end
       1: begin
@@ -426,19 +426,19 @@
       end
       1: begin
         `uvm_info(msg_id, "Force ctrl FSM", UVM_LOW)
-        prev_state = tb.dut.u_ctrl.state_raw_q;
+        prev_state = tb.dut.u_ctrl.u_state_regs.state_raw;
         `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(invalid_state,
             !(invalid_state inside {CtrlValidStates});,
             , msg_id)
 
-        force tb.dut.u_ctrl.state_raw_q = invalid_state;
+        force tb.dut.u_ctrl.u_state_regs.state_raw = invalid_state;
         @(posedge clk);
 
         if ($urandom_range(0, 1)) begin
-          force tb.dut.u_ctrl.state_raw_q = prev_state;
+          force tb.dut.u_ctrl.u_state_regs.state_raw = prev_state;
           @(posedge clk);
         end
-        release tb.dut.u_ctrl.state_raw_q;
+        release tb.dut.u_ctrl.u_state_regs.state_raw;
         is_ctrl_fsm_err = 1;
       end
       1: begin
diff --git a/hw/ip/keymgr/rtl/keymgr_ctrl.sv b/hw/ip/keymgr/rtl/keymgr_ctrl.sv
index 4a0b4e8..a65dd5e 100644
--- a/hw/ip/keymgr/rtl/keymgr_ctrl.sv
+++ b/hw/ip/keymgr/rtl/keymgr_ctrl.sv
@@ -237,19 +237,8 @@
   //////////////////////////
   // Main Control FSM
   //////////////////////////
-  logic [StateWidth-1:0] state_raw_q;
-  assign state_q = state_e'(state_raw_q);
   // SEC_CM: CTRL.FSM.SPARSE
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(StCtrlReset))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, StCtrlReset)
 
   always_ff @(posedge clk_i or negedge rst_ni) begin
     if (!rst_ni) begin
diff --git a/hw/ip/keymgr/rtl/keymgr_data_en_state.sv b/hw/ip/keymgr/rtl/keymgr_data_en_state.sv
index d2157b5..3b1cd5c 100644
--- a/hw/ip/keymgr/rtl/keymgr_data_en_state.sv
+++ b/hw/ip/keymgr/rtl/keymgr_data_en_state.sv
@@ -54,21 +54,8 @@
 
   state_e state_d, state_q;
 
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
-  logic [DataStateWidth-1:0] state_raw_q;
-  assign state_q = state_e'(state_raw_q);
   // SEC_CM: DATA.FSM.SPARSE
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(DataStateWidth),
-    .ResetValue(DataStateWidth'(StCtrlDataIdle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, StCtrlDataIdle)
 
   // The below control path is used for modulating the datapath to sideload and sw keys.
   // This path is separate from the data_valid_o path, thus creating two separate attack points.
diff --git a/hw/ip/keymgr/rtl/keymgr_kmac_if.sv b/hw/ip/keymgr/rtl/keymgr_kmac_if.sv
index d6993a9..5ed3fd3 100644
--- a/hw/ip/keymgr/rtl/keymgr_kmac_if.sv
+++ b/hw/ip/keymgr/rtl/keymgr_kmac_if.sv
@@ -159,22 +159,8 @@
     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 = data_state_e'(state_raw_q);
-
   // SEC_CM: KMAC_IF.FSM.SPARSE
-  prim_sparse_fsm_flop #(
-    .StateEnumT(data_state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(StIdle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, data_state_e, StIdle)
 
   always_comb begin
     cnt_clr = 1'b0;
diff --git a/hw/ip/keymgr/rtl/keymgr_op_state_ctrl.sv b/hw/ip/keymgr/rtl/keymgr_op_state_ctrl.sv
index cab586d..635ee0d 100644
--- a/hw/ip/keymgr/rtl/keymgr_op_state_ctrl.sv
+++ b/hw/ip/keymgr/rtl/keymgr_op_state_ctrl.sv
@@ -41,19 +41,7 @@
   } state_e;
 
   state_e state_q, state_d;
-  logic [OpStateWidth-1:0] state_raw_q;
-
-  assign state_q = state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(OpStateWidth),
-    .ResetValue(OpStateWidth'(StIdle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, StIdle)
 
   logic gen_en;
   assign id_en_o = gen_en & id_req_i;
diff --git a/hw/ip/kmac/rtl/keccak_round.sv b/hw/ip/kmac/rtl/keccak_round.sv
index e91a6d9..7c63d19 100644
--- a/hw/ip/kmac/rtl/keccak_round.sv
+++ b/hw/ip/kmac/rtl/keccak_round.sv
@@ -189,21 +189,7 @@
       StTerminalError = 6'b110110
   } keccak_st_e;
   keccak_st_e keccak_st, keccak_st_d;
-
-  // 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 keccak_st = keccak_st_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(keccak_st_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(StIdle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( keccak_st_d ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, keccak_st_d, keccak_st, keccak_st_e, StIdle)
 
   // Next state logic and output logic
   // SEC_CM: FSM.SPARSE
diff --git a/hw/ip/kmac/rtl/kmac.sv b/hw/ip/kmac/rtl/kmac.sv
index 574fad9..39f02c2 100644
--- a/hw/ip/kmac/rtl/kmac.sv
+++ b/hw/ip/kmac/rtl/kmac.sv
@@ -129,8 +129,7 @@
 
   } kmac_st_e;
 
-  logic [StateWidth-1:0] kmac_st_raw;
-  kmac_st_e              kmac_st, kmac_st_d;
+  kmac_st_e kmac_st, kmac_st_d;
 
   /////////////
   // Signals //
@@ -677,19 +676,7 @@
   ///////////////////
 
   // State FF
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
-  prim_sparse_fsm_flop #(
-    .StateEnumT(kmac_st_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(KmacIdle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i (kmac_st_d),
-    .state_o (kmac_st_raw)
-  );
-  assign kmac_st = kmac_st_e'(kmac_st_raw);
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, kmac_st_d, kmac_st, kmac_st_e, KmacIdle)
 
   always_comb begin
     // Default value
diff --git a/hw/ip/kmac/rtl/kmac_app.sv b/hw/ip/kmac/rtl/kmac_app.sv
index aef4234..24e22d8 100644
--- a/hw/ip/kmac/rtl/kmac_app.sv
+++ b/hw/ip/kmac/rtl/kmac_app.sv
@@ -353,20 +353,7 @@
   /////////
 
   // State register
-  // 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] st_raw;
-  assign st = st_e'(st_raw);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(st_e),
-    .Width      (StateWidth),
-    .ResetValue (StateWidth'(StIdle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( st_d   ),
-    .state_o ( st_raw )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, st_d, st, st_e, StIdle)
 
   // Create a lint error to reduce the risk of accidentally enabling this feature.
   `ASSERT_STATIC_LINT_ERROR(KmacSecIdleAcceptSwMsgNonDefault, SecIdleAcceptSwMsg == 0)
diff --git a/hw/ip/kmac/rtl/kmac_core.sv b/hw/ip/kmac/rtl/kmac_core.sv
index dbba58a..77c2990 100644
--- a/hw/ip/kmac/rtl/kmac_core.sv
+++ b/hw/ip/kmac/rtl/kmac_core.sv
@@ -156,20 +156,7 @@
   kmac_st_e st, st_d;
 
   // State register
-  // 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 st = kmac_st_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(kmac_st_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(StKmacIdle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( st_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, st_d, st, kmac_st_e, StKmacIdle)
 
   // Next state and output logic
   // SEC_CM: FSM.SPARSE
diff --git a/hw/ip/kmac/rtl/kmac_entropy.sv b/hw/ip/kmac/rtl/kmac_entropy.sv
index 841c9aa..4a8dc4d 100644
--- a/hw/ip/kmac/rtl/kmac_entropy.sv
+++ b/hw/ip/kmac/rtl/kmac_entropy.sv
@@ -419,22 +419,9 @@
   ///////////////////
 
   rand_st_e st, st_d;
-  logic [StateWidth-1:0] st_raw_q;
-  assign st = rand_st_e'(st_raw_q);
 
   // State FF
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
-  prim_sparse_fsm_flop #(
-    .StateEnumT(rand_st_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(StRandReset))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( st_d     ),
-    .state_o ( st_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, st_d, st, rand_st_e, StRandReset)
 
   // State: Next State and Output Logic
   // SEC_CM: FSM.SPARSE
diff --git a/hw/ip/kmac/rtl/kmac_errchk.sv b/hw/ip/kmac/rtl/kmac_errchk.sv
index 977816b..791e221 100644
--- a/hw/ip/kmac/rtl/kmac_errchk.sv
+++ b/hw/ip/kmac/rtl/kmac_errchk.sv
@@ -322,20 +322,7 @@
   ///////////////////
   // State Machine //
   ///////////////////
-  // 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 st = st_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(st_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(StIdle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( st_d        ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, st_d, st, st_e, StIdle)
 
   always_comb begin : next_state
     st_d = st;
diff --git a/hw/ip/kmac/rtl/sha3.sv b/hw/ip/kmac/rtl/sha3.sv
index c3dd82e..c8ec19c 100644
--- a/hw/ip/kmac/rtl/sha3.sv
+++ b/hw/ip/kmac/rtl/sha3.sv
@@ -185,20 +185,7 @@
   ///////////////////
 
   // State Register
-  // 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 st = sha3_st_sparse_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(sha3_st_sparse_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(StIdle_sparse))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( st_d        ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, st_d, st, sha3_st_sparse_e, StIdle_sparse)
 
 
   // Next State and Output Logic
diff --git a/hw/ip/kmac/rtl/sha3pad.sv b/hw/ip/kmac/rtl/sha3pad.sv
index 3ed1025..7ccf824 100644
--- a/hw/ip/kmac/rtl/sha3pad.sv
+++ b/hw/ip/kmac/rtl/sha3pad.sv
@@ -275,20 +275,7 @@
   // State Register ===========================================================
   pad_st_e st, st_d;
 
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
-  logic [StateWidthPad-1:0] state_raw_q;
-  assign st = pad_st_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(pad_st_e),
-    .Width(StateWidthPad),
-    .ResetValue(StateWidthPad'(StPadIdle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( st_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, st_d, st, pad_st_e, StPadIdle)
 
   // `end_of_block` indicates current beat is end of the block
   // It shall set when the address reaches to the end of the block. End address
diff --git a/hw/ip/lc_ctrl/rtl/lc_ctrl_fsm.sv b/hw/ip/lc_ctrl/rtl/lc_ctrl_fsm.sv
index dac04bd..2c0b0e9 100644
--- a/hw/ip/lc_ctrl/rtl/lc_ctrl_fsm.sv
+++ b/hw/ip/lc_ctrl/rtl/lc_ctrl_fsm.sv
@@ -4,6 +4,8 @@
 //
 // Main Life Cycle Controller FSM.
 
+`include "prim_assert.sv"
+
 module lc_ctrl_fsm
   import lc_ctrl_pkg::*;
   import lc_ctrl_state_pkg::*;
@@ -440,46 +442,9 @@
   // State Flops //
   /////////////////
 
-  // This primitive is used to place a size-only constraint on the
-  // 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_sparse_fsm_flop #(
-    .StateEnumT(fsm_state_e),
-    .Width(FsmStateWidth),
-    .ResetValue(FsmStateWidth'(ResetSt))
-  ) u_fsm_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( fsm_state_d     ),
-    .state_o ( fsm_state_raw_q )
-  );
-
-  logic [LcStateWidth-1:0] lc_state_raw_q;
-  assign lc_state_q = lc_state_e'(lc_state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(lc_state_e),
-    .Width(LcStateWidth),
-    .ResetValue(LcStateWidth'(LcStScrap))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( lc_state_d     ),
-    .state_o ( lc_state_raw_q )
-  );
-
-  logic [LcCountWidth-1:0] lc_cnt_raw_q;
-  assign lc_cnt_q = lc_cnt_e'(lc_cnt_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(lc_cnt_e),
-    .Width(LcCountWidth),
-    .ResetValue(LcCountWidth'(LcCnt24))
-  ) u_cnt_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( lc_cnt_d     ),
-    .state_o ( lc_cnt_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_fsm_state_regs, fsm_state_d, fsm_state_q, fsm_state_e, ResetSt)
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, lc_state_d, lc_state_q, lc_state_e, LcStScrap)
+  `PRIM_FLOP_SPARSE_FSM(u_cnt_regs, lc_cnt_d, lc_cnt_q, lc_cnt_e, LcCnt24)
 
   always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
     if (!rst_ni) begin
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 43c651a..1fb4ca9 100644
--- a/hw/ip/lc_ctrl/rtl/lc_ctrl_kmac_if.sv
+++ b/hw/ip/lc_ctrl/rtl/lc_ctrl_kmac_if.sv
@@ -202,19 +202,6 @@
     endcase // state_q
   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 = state_e'(state_raw_q);
-  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 ),
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, FirstSt, clk_kmac_i, rst_kmac_ni)
 
 endmodule : lc_ctrl_kmac_if
diff --git a/hw/ip/otbn/rtl/otbn_controller.sv b/hw/ip/otbn/rtl/otbn_controller.sv
index e14dffe..35ebc21c 100644
--- a/hw/ip/otbn/rtl/otbn_controller.sv
+++ b/hw/ip/otbn/rtl/otbn_controller.sv
@@ -533,20 +533,7 @@
   `ASSERT(NoStallOnBranch,
       insn_valid_i & insn_dec_shared_i.branch_insn |-> state_q != OtbnStateStall)
 
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
-  logic [StateControllerWidth-1:0] state_raw_q;
-  assign state_q = otbn_state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(otbn_state_e),
-    .Width(StateControllerWidth),
-    .ResetValue(StateControllerWidth'(OtbnStateHalt))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, otbn_state_e, OtbnStateHalt)
 
   assign insn_cnt_clear = state_reset_i | (state_q == OtbnStateLocked) | insn_cnt_clear_i;
 
diff --git a/hw/ip/otbn/rtl/otbn_scramble_ctrl.sv b/hw/ip/otbn/rtl/otbn_scramble_ctrl.sv
index bff7788..8d0cb05 100644
--- a/hw/ip/otbn/rtl/otbn_scramble_ctrl.sv
+++ b/hw/ip/otbn/rtl/otbn_scramble_ctrl.sv
@@ -132,20 +132,7 @@
     end
   end
 
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
-  logic [StateScrambleCtrlWidth-1:0] state_raw_q;
-  assign state_q = scramble_ctrl_state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(scramble_ctrl_state_e),
-    .Width(StateScrambleCtrlWidth),
-    .ResetValue(StateScrambleCtrlWidth'(ScrambleCtrlIdle))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, scramble_ctrl_state_e, ScrambleCtrlIdle)
 
   always_comb begin
     dmem_key_valid_d            = dmem_key_valid_q;
diff --git a/hw/ip/otbn/rtl/otbn_start_stop_control.sv b/hw/ip/otbn/rtl/otbn_start_stop_control.sv
index afde96d..11900d4 100644
--- a/hw/ip/otbn/rtl/otbn_start_stop_control.sv
+++ b/hw/ip/otbn/rtl/otbn_start_stop_control.sv
@@ -62,20 +62,8 @@
   logic addr_cnt_inc;
   logic [4:0] addr_cnt_q, addr_cnt_d;
 
-  // This primitive is used to place a size-only constraint on the
-  // flops in order to prevent FSM state encoding optimizations.
-  logic [StateStartStopWidth-1:0] state_raw_q;
-  assign state_q = otbn_start_stop_state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(otbn_start_stop_state_e),
-    .Width(StateStartStopWidth),
-    .ResetValue(StateStartStopWidth'(OtbnStartStopStateHalt))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q,
+      otbn_start_stop_state_e, OtbnStartStopStateHalt)
 
   always_comb begin
     urnd_reseed_req_o      = 1'b0;
diff --git a/hw/ip/otp_ctrl/rtl/otp_ctrl_dai.sv b/hw/ip/otp_ctrl/rtl/otp_ctrl_dai.sv
index 5dd82c1..05bd56a 100644
--- a/hw/ip/otp_ctrl/rtl/otp_ctrl_dai.sv
+++ b/hw/ip/otp_ctrl/rtl/otp_ctrl_dai.sv
@@ -5,7 +5,7 @@
 // Direct access interface for OTP controller.
 //
 
-`include "prim_assert.sv"
+`include "prim_flop_macros.sv"
 
 module otp_ctrl_dai
   import otp_ctrl_pkg::*;
@@ -765,20 +765,7 @@
   // Registers //
   ///////////////
 
-  // 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 = state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(ResetSt))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt)
 
   always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
     if (!rst_ni) begin
diff --git a/hw/ip/otp_ctrl/rtl/otp_ctrl_kdi.sv b/hw/ip/otp_ctrl/rtl/otp_ctrl_kdi.sv
index 35b3b0f..f04fd18 100644
--- a/hw/ip/otp_ctrl/rtl/otp_ctrl_kdi.sv
+++ b/hw/ip/otp_ctrl/rtl/otp_ctrl_kdi.sv
@@ -5,7 +5,7 @@
 // Scrambling key derivation module for OTP.
 //
 
-`include "prim_assert.sv"
+`include "prim_flop_macros.sv"
 
 module otp_ctrl_kdi
   import otp_ctrl_pkg::*;
@@ -348,7 +348,6 @@
   } state_e;
 
   state_e state_d, state_q;
-
   logic edn_req_d, edn_req_q;
   assign edn_req_o = edn_req_q;
 
@@ -568,20 +567,7 @@
   // Registers //
   ///////////////
 
-  // 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 = state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(ResetSt))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt)
 
   always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
     if (!rst_ni) begin
diff --git a/hw/ip/otp_ctrl/rtl/otp_ctrl_lci.sv b/hw/ip/otp_ctrl/rtl/otp_ctrl_lci.sv
index 9caf2ac..a0599f4 100644
--- a/hw/ip/otp_ctrl/rtl/otp_ctrl_lci.sv
+++ b/hw/ip/otp_ctrl/rtl/otp_ctrl_lci.sv
@@ -5,7 +5,7 @@
 // Life cycle interface for performing life cycle transitions in OTP.
 //
 
-`include "prim_assert.sv"
+`include "prim_flop_macros.sv"
 
 module otp_ctrl_lci
   import otp_ctrl_pkg::*;
@@ -105,10 +105,10 @@
     ErrorSt     = 9'b011111101
   } state_e;
 
+  state_e state_d, state_q;
   logic cnt_clr, cnt_en, cnt_err;
   logic [CntWidth-1:0] cnt;
   otp_err_e error_d, error_q;
-  state_e state_d, state_q;
 
   // Output LCI errors
   assign error_o = error_q;
@@ -270,20 +270,7 @@
   // Registers //
   ///////////////
 
-  // 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 = state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(ResetSt))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt)
 
   always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
     if (!rst_ni) begin
diff --git a/hw/ip/otp_ctrl/rtl/otp_ctrl_lfsr_timer.sv b/hw/ip/otp_ctrl/rtl/otp_ctrl_lfsr_timer.sv
index 5774365..4dd6bb9 100644
--- a/hw/ip/otp_ctrl/rtl/otp_ctrl_lfsr_timer.sv
+++ b/hw/ip/otp_ctrl/rtl/otp_ctrl_lfsr_timer.sv
@@ -26,7 +26,7 @@
 // This can be useful if SW chooses to leave the periodic checks disabled.
 //
 
-`include "prim_assert.sv"
+`include "prim_flop_macros.sv"
 
 module otp_ctrl_lfsr_timer
   import otp_ctrl_pkg::*;
@@ -241,7 +241,7 @@
   assign chk_timeout_o = chk_timeout_q;
 
   always_comb begin : p_fsm
-    state_d = state_e'(state_q);
+    state_d = state_q;
 
     // LFSR and counter signals
     lfsr_en = 1'b0;
@@ -361,20 +361,7 @@
   // Registers //
   ///////////////
 
-  // 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 = state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(ResetSt))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt)
 
   always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
     if (!rst_ni) begin
diff --git a/hw/ip/otp_ctrl/rtl/otp_ctrl_part_buf.sv b/hw/ip/otp_ctrl/rtl/otp_ctrl_part_buf.sv
index 2f49ca3..ea9397d 100644
--- a/hw/ip/otp_ctrl/rtl/otp_ctrl_part_buf.sv
+++ b/hw/ip/otp_ctrl/rtl/otp_ctrl_part_buf.sv
@@ -5,7 +5,7 @@
 // Buffered partition for OTP controller.
 //
 
-`include "prim_assert.sv"
+`include "prim_flop_macros.sv"
 
 module otp_ctrl_part_buf
   import otp_ctrl_pkg::*;
@@ -744,20 +744,7 @@
   // Registers //
   ///////////////
 
-  // 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 = state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(ResetSt))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt)
 
   always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
     if (!rst_ni) begin
diff --git a/hw/ip/otp_ctrl/rtl/otp_ctrl_part_unbuf.sv b/hw/ip/otp_ctrl/rtl/otp_ctrl_part_unbuf.sv
index 69ef1f4..3552d6b 100644
--- a/hw/ip/otp_ctrl/rtl/otp_ctrl_part_unbuf.sv
+++ b/hw/ip/otp_ctrl/rtl/otp_ctrl_part_unbuf.sv
@@ -5,7 +5,7 @@
 // Unbuffered partition for OTP controller.
 //
 
-`include "prim_assert.sv"
+`include "prim_flop_macros.sv"
 
 module otp_ctrl_part_unbuf
   import otp_ctrl_pkg::*;
@@ -434,20 +434,7 @@
   // Registers //
   ///////////////
 
-  // 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 = state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(ResetSt))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt)
 
   always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
     if (!rst_ni) begin
diff --git a/hw/ip/otp_ctrl/rtl/otp_ctrl_scrmbl.sv b/hw/ip/otp_ctrl/rtl/otp_ctrl_scrmbl.sv
index e74ec58..e52d03c 100644
--- a/hw/ip/otp_ctrl/rtl/otp_ctrl_scrmbl.sv
+++ b/hw/ip/otp_ctrl/rtl/otp_ctrl_scrmbl.sv
@@ -68,6 +68,8 @@
 //             - http://www.lightweightcrypto.org/present/present_ches2007.pdf
 //
 
+`include "prim_flop_macros.sv"
+
 module otp_ctrl_scrmbl
   import otp_ctrl_pkg::*;
   import otp_ctrl_part_pkg::*;
@@ -468,20 +470,7 @@
   // Registers //
   ///////////////
 
-  // 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 = state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(IdleSt))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, IdleSt)
 
   always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
     if (!rst_ni) begin
diff --git a/hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv b/hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv
index 5e21d7d..9c3f596 100644
--- a/hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv
+++ b/hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv
@@ -155,19 +155,8 @@
     end
   end
 
-  logic [FastPwrStateWidth-1:0] state_raw_q;
-  assign state_q = fast_pwr_state_e'(state_raw_q);
   // SEC_CM: FSM.SPARSE
-  prim_sparse_fsm_flop #(
-    .StateEnumT(fast_pwr_state_e),
-    .Width(FastPwrStateWidth),
-    .ResetValue(FastPwrStateWidth'(FastPwrStateLowPower))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, fast_pwr_state_e, FastPwrStateLowPower)
 
   always_ff @(posedge clk_i or negedge rst_ni) begin
     if (!rst_ni) begin
diff --git a/hw/ip/pwrmgr/rtl/pwrmgr_slow_fsm.sv b/hw/ip/pwrmgr/rtl/pwrmgr_slow_fsm.sv
index 4ebda38..4c15b96 100644
--- a/hw/ip/pwrmgr/rtl/pwrmgr_slow_fsm.sv
+++ b/hw/ip/pwrmgr/rtl/pwrmgr_slow_fsm.sv
@@ -130,19 +130,8 @@
     end
   end
 
-  logic [SlowPwrStateWidth-1:0] state_raw_q;
-  assign state_q = slow_pwr_state_e'(state_raw_q);
   // SEC_CM: FSM.SPARSE
-  prim_sparse_fsm_flop #(
-    .StateEnumT(slow_pwr_state_e),
-    .Width(SlowPwrStateWidth),
-    .ResetValue(SlowPwrStateWidth'(SlowPwrStateReset))
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, slow_pwr_state_e, SlowPwrStateReset)
 
   always_comb begin
     state_d        = state_q;
diff --git a/hw/ip/rom_ctrl/rtl/rom_ctrl_compare.sv b/hw/ip/rom_ctrl/rtl/rom_ctrl_compare.sv
index 82ad743..8aa81b1 100644
--- a/hw/ip/rom_ctrl/rtl/rom_ctrl_compare.sv
+++ b/hw/ip/rom_ctrl/rtl/rom_ctrl_compare.sv
@@ -88,20 +88,11 @@
     Done     = 5'b11001
   } state_e;
 
-  logic [4:0]  state_q, state_d;
-  logic        matches_q, matches_d;
-  logic        fsm_alert;
+  state_e state_q, state_d;
+  logic   matches_q, matches_d;
+  logic   fsm_alert;
 
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(5),
-    .ResetValue({Waiting})
-  ) u_state_regs (
-    .clk_i   (clk_i),
-    .rst_ni  (rst_ni),
-    .state_i (state_d),
-    .state_o (state_q)
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, Waiting)
 
   always_comb begin
     state_d = state_q;
diff --git a/hw/ip/rom_ctrl/rtl/rom_ctrl_fsm.sv b/hw/ip/rom_ctrl/rtl/rom_ctrl_fsm.sv
index f9013c9..845ee24 100644
--- a/hw/ip/rom_ctrl/rtl/rom_ctrl_fsm.sv
+++ b/hw/ip/rom_ctrl/rtl/rom_ctrl_fsm.sv
@@ -132,19 +132,12 @@
   // SEC_CM: FSM.SPARSE
   // SEC_CM: INTERSIG.MUBI
 
-  logic [9:0]  state_q, state_d;
-  logic        fsm_alert;
+  fsm_state_e state_d, state_q;
+  logic [9:0] logic_state_q;
+  logic       fsm_alert;
 
-  prim_sparse_fsm_flop #(
-    .StateEnumT(fsm_state_e),
-    .Width(10),
-    .ResetValue({ReadingLow})
-  ) u_state_regs (
-    .clk_i   (clk_i),
-    .rst_ni  (rst_ni),
-    .state_i (state_d),
-    .state_o (state_q)
-  );
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, fsm_state_e, ReadingLow)
+  assign logic_state_q = {state_q};
 
   always_comb begin
     state_d = state_q;
@@ -218,7 +211,7 @@
   // bottom 4 bits of state_q is equivalent to "mubi4_bool_to_mubi(state_q == Done)" except that it
   // doesn't have a 1-bit signal on the way.
   mubi4_t in_state_done;
-  assign in_state_done = mubi4_t'(state_q[3:0]);
+  assign in_state_done = mubi4_t'(logic_state_q[3:0]);
 
   // Route digest signals coming back from KMAC straight to the CSRs
   assign digest_o     = kmac_digest_i;
diff --git a/hw/ip/rstmgr/rtl/rstmgr_cnsty_chk.sv b/hw/ip/rstmgr/rtl/rstmgr_cnsty_chk.sv
index 1655716..f1358e9 100644
--- a/hw/ip/rstmgr/rtl/rstmgr_cnsty_chk.sv
+++ b/hw/ip/rstmgr/rtl/rstmgr_cnsty_chk.sv
@@ -108,22 +108,9 @@
 
   state_e state_q, state_d;
 
-  // 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 = state_e'(state_raw_q);
-  //SEC_CM: LEAF.FSM.SPARSE
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(Reset)),
-    .EnableAlertTriggerSVA(0)
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  // SEC_CM: LEAF.FSM.SPARSE
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, Reset,
+      clk_i, rst_ni, 0)
 
   logic timeout;
   logic cnt_inc;
diff --git a/hw/ip_templates/alert_handler/rtl/alert_handler_esc_timer.sv b/hw/ip_templates/alert_handler/rtl/alert_handler_esc_timer.sv
index e12bb77..0059a54 100644
--- a/hw/ip_templates/alert_handler/rtl/alert_handler_esc_timer.sv
+++ b/hw/ip_templates/alert_handler/rtl/alert_handler_esc_timer.sv
@@ -291,23 +291,10 @@
   // FSM Registers //
   ///////////////////
 
-  // 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 = state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(IdleSt)),
-    // The alert handler behaves differently than other comportable IP. I.e., instead of sending out
-    // an alert signal, this condition is handled internally in the alert handler.
-    .EnableAlertTriggerSVA(0)
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  // The alert handler behaves differently than other comportable IP. I.e., instead of sending out
+  // an alert signal, this condition is handled internally in the alert handler. The
+  // EnableAlertTriggerSVA parameter is therefore set to 0.
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, IdleSt, clk_i, rst_ni, 0)
 
   ////////////////
   // Assertions //
diff --git a/hw/ip_templates/alert_handler/rtl/alert_handler_ping_timer.sv b/hw/ip_templates/alert_handler/rtl/alert_handler_ping_timer.sv
index c82d957..1f1a152 100644
--- a/hw/ip_templates/alert_handler/rtl/alert_handler_ping_timer.sv
+++ b/hw/ip_templates/alert_handler/rtl/alert_handler_ping_timer.sv
@@ -377,23 +377,10 @@
   // FSM Registers //
   ///////////////////
 
-  // 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 = state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(InitSt)),
-    // The alert handler behaves differently than other comportable IP. I.e., instead of sending out
-    // an alert signal, this condition is handled internally in the alert handler.
-    .EnableAlertTriggerSVA(0)
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  // The alert handler behaves differently than other comportable IP. I.e., instead of sending out
+  // an alert signal, this condition is handled internally in the alert handler. The
+  // EnableAlertTriggerSVA parameter is therefore set to 0.
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, InitSt, clk_i, rst_ni, 0)
 
   ////////////////
   // Assertions //
diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_esc_timer.sv b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_esc_timer.sv
index e12bb77..0059a54 100644
--- a/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_esc_timer.sv
+++ b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_esc_timer.sv
@@ -291,23 +291,10 @@
   // FSM Registers //
   ///////////////////
 
-  // 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 = state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(IdleSt)),
-    // The alert handler behaves differently than other comportable IP. I.e., instead of sending out
-    // an alert signal, this condition is handled internally in the alert handler.
-    .EnableAlertTriggerSVA(0)
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  // The alert handler behaves differently than other comportable IP. I.e., instead of sending out
+  // an alert signal, this condition is handled internally in the alert handler. The
+  // EnableAlertTriggerSVA parameter is therefore set to 0.
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, IdleSt, clk_i, rst_ni, 0)
 
   ////////////////
   // Assertions //
diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_ping_timer.sv b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_ping_timer.sv
index c82d957..1f1a152 100644
--- a/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_ping_timer.sv
+++ b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler_ping_timer.sv
@@ -377,23 +377,10 @@
   // FSM Registers //
   ///////////////////
 
-  // 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 = state_e'(state_raw_q);
-  prim_sparse_fsm_flop #(
-    .StateEnumT(state_e),
-    .Width(StateWidth),
-    .ResetValue(StateWidth'(InitSt)),
-    // The alert handler behaves differently than other comportable IP. I.e., instead of sending out
-    // an alert signal, this condition is handled internally in the alert handler.
-    .EnableAlertTriggerSVA(0)
-  ) u_state_regs (
-    .clk_i,
-    .rst_ni,
-    .state_i ( state_d     ),
-    .state_o ( state_raw_q )
-  );
+  // The alert handler behaves differently than other comportable IP. I.e., instead of sending out
+  // an alert signal, this condition is handled internally in the alert handler. The
+  // EnableAlertTriggerSVA parameter is therefore set to 0.
+  `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, InitSt, clk_i, rst_ni, 0)
 
   ////////////////
   // Assertions //