Parametrizing a hardcoded target table in a pacing FSM (SV)
A transmitter FSM had a hardcoded 6-entry (addr, sub) lookup table driving per-target pacing state (stop_c, pace_count). Making it parameterizable required:
1. Convert module to ANSI #() style; expose NUM_TGT, TGT_ADDR[NUM_TGT], TGT_SUB[NUM_TGT], TGT_ANYSUB, FIFO_TGT_MASK[NUM_FIFO], and single-target FIFO indices (FIFO1_TGT, FIFO3_TGT) as parameters.
2. Derive width and sentinel as localparams: localparam int TGT_W = $clog2(NUM_TGT + 1); localparam logic [TGT_W-1:0] UNKNOWN = TGT_W'(NUM_TGT); This keeps the sentinel and all index widths consistent regardless of NUM_TGT.
3. Replace every hardcoded 3'd6 sentinel with UNKNOWN and every 3'd4 target-index literal with TGT_W'(FIFO1_TGT) / TGT_W'(FIFO3_TGT). Update automatic variable declarations (pt, idx) inside the always block to [TGT_W-1:0].
4. The tgt_idx function return type changes from [2:0] to [TGT_W-1:0].
SV allows unpacked array parameters with size driven by an earlier parameter in the same list; works in Vivado, VCS, ModelSim. FIFO_TGT_MASK and FIFO count remain architecture constants - the FSM case arms are still per-FIFO, so NUM_FIFO is not truly variable without generating the case arms too.