Module prim_lfsr
Block Diagram of prim_lfsr
Name |
Default |
Description |
---|---|---|
LfsrType |
"GAL_XOR" |
Lfsr Type, can be FIB_XNOR or GAL_XOR |
LfsrDw |
32 |
Lfsr width |
EntropyDw |
8 |
Width of the entropy input to be XOR'd into state (lfsr_q[EntropyDw-1:0]) |
StateOutDw |
8 |
Width of output tap (from lfsr_q[StateOutDw-1:0]) |
DefaultSeed |
LfsrDw'(1) |
Lfsr reset state, must be nonzero! |
CustomCoeffs |
'0 |
Custom polynomial coeffs |
StatePermEn |
1'b0 |
If StatePermEn is set to 1, the custom permutation specified via StatePerm is applied to the state output, in order to break linear shifting patterns of the LFSR. Note that this permutation represents a way of customizing the LFSR via a random netlist constant. This is different from the NonLinearOut feature below which just transforms the output non-linearly with a fixed function. In most cases, designers should consider enabling StatePermEn as it comes basically "for free" in terms of area and timing impact. NonLinearOut on the other hand has area and timing implications and designers should consider whether the use of that feature is justified. |
StatePerm |
'0 |
|
MaxLenSVA |
1'b1 |
Enable this for DV, disable this for long LFSRs in FPV |
LockupSVA |
1'b1 |
Can be disabled in cases where seed and entropy inputs are unused in order to not distort coverage (the SVA will be unreachable in such cases) |
ExtSeedSVA |
1'b1 |
|
NonLinearOut |
1'b0 |
Introduce non-linearity to lfsr output. Note, unlike StatePermEn, this feature is not "for free". Please double check that this feature is indeed required. Also note that this feature is only available for LFSRs that have a power-of-two width greater or equal 16bit. |
Name |
Type |
Direction |
Description |
---|---|---|---|
clk_i |
wire logic |
input |
|
rst_ni |
wire logic |
input |
|
seed_en_i |
wire logic |
input |
load external seed into the state (takes precedence) |
seed_i |
wire logic [LfsrDw - 1 : 0] |
input |
external seed input |
lfsr_en_i |
wire logic |
input |
enables the LFSR |
entropy_i |
wire logic [EntropyDw - 1 : 0] |
input |
additional entropy to be XOR'ed into the state |
state_o |
var logic [StateOutDw - 1 : 0] |
output |
(partial) LFSR state output |
Name |
Kind |
Description |
---|---|---|
prim_lfsr.MinLfsrWidth_A |
immediate assert |
(LfsrDw >= ($low(LFSR_COEFFS) + LUT_OFF))
|
prim_lfsr.MaxLfsrWidth_A |
immediate assert |
(LfsrDw <= ($high(LFSR_COEFFS) + LUT_OFF))
|
prim_lfsr.DefaultSeedNzCheck_A |
immediate assert |
| DefaultSeedLocal
|
prim_lfsr.MinLfsrWidth_A |
immediate assert |
(LfsrDw >= ($low(LFSR_COEFFS) + LUT_OFF))
|
prim_lfsr.MaxLfsrWidth_A |
immediate assert |
(LfsrDw <= ($high(LFSR_COEFFS) + LUT_OFF))
|
prim_lfsr.DefaultSeedNzCheck_A |
immediate assert |
! & DefaultSeedLocal
|
prim_lfsr.UnknownLfsrType_A |
immediate assert |
0
|
prim_lfsr.SboxPermutationCheck_A |
concurent assert |
disable iff((!rst_ni)!=='0)& sbox_perm_test
|
prim_lfsr.DataKnownO_A |
concurent assert |
disable iff((!rst_ni)!=='0)! $isunknown(state_o)
|
prim_lfsr.NextStateCheck_A |
concurent assert |
disable iff((!rst_ni)!=='0)(## 1 ((lfsr_en_i && ! seed_en_i) |=> (lfsr_q == compute_next_state(coeffs, $past(entropy_i), $past(lfsr_q)))))
|
prim_lfsr.PermutationCheck_A |
immediate assert |
& lfsr_perm_test
|
prim_lfsr.InputWidth_A |
immediate assert |
(LfsrDw >= EntropyDw)
|
prim_lfsr.OutputWidth_A |
immediate assert |
(LfsrDw >= StateOutDw)
|
prim_lfsr.CoeffCheck_A |
concurent assert |
disable iff((!rst_ni)!=='0)coeffs[LfsrDw - 1]
|
prim_lfsr.OutputKnown_A |
concurent assert |
disable iff((!rst_ni)!=='0)! $isunknown(state_o)
|
prim_lfsr.OutputCheck_A |
concurent assert |
disable iff((!rst_ni)!=='0)(state_o == (StateOutDw ' lfsr_q))
|
prim_lfsr.NoLockups_A |
concurent assert |
disable iff((!rst_ni)!=='0)(((lfsr_en_i && ! entropy_i) && ! seed_en_i) |=> ! lockup)
|
prim_lfsr.ExtDefaultSeedInputCheck_A |
concurent assert |
disable iff((!rst_ni)!=='0)((seed_en_i && rst_ni) |=> (lfsr_q == $past(seed_i)))
|
prim_lfsr.LfsrLockupCheck_A |
concurent assert |
disable iff((!rst_ni)!=='0)(((lfsr_en_i && lockup) && ! seed_en_i) |=> ! lockup)
|
prim_lfsr.SboxByteAlign_A |
immediate assert |
(((2 ** $clog2(LfsrDw)) == LfsrDw) && (LfsrDw >= 16))
|
prim_lfsr.MaximalLengthCheck0_A |
concurent assert |
disable iff((!rst_ni||perturbed_q)!=='0)((cnt_q == 0) |-> (lfsr_q == DefaultSeedLocal))
|
prim_lfsr.MaximalLengthCheck1_A |
concurent assert |
disable iff((!rst_ni||perturbed_q)!=='0)((cnt_q != 0) |-> (lfsr_q != DefaultSeedLocal))
|
Functions
- compute_next_state(logic[LfsrDw-1:0] lfsrcoeffs, logic[EntropyDw-1:0] entropy, logic[LfsrDw-1:0] current_state)
- Parameters:
lfsrcoeffs (logic[LfsrDw-1:0])
entropy (logic[EntropyDw-1:0])
current_state (logic[LfsrDw-1:0])
This module implements different LFSR types
All flavors have an additional entropy input and lockup protection, which reseeds the state once it has accidentally fallen into the all-zero (XOR) or all-one (XNOR) state. Further, an external seed can be loaded into the LFSR state at runtime. If that seed is all-zero (XOR case) or all-one (XNOR case), the state will be reseeded in the next cycle using the lockup protection mechanism. Note that the external seed input takes precedence over internal state updates.
All polynomials up to 34 bit in length have been verified in simulation.
Refs
[1] https://en.wikipedia.org/wiki/Linear-feedback_shift_register
[2] https://users.ece.cmu.edu/~koopman/lfsr/ [3] https://www.xilinx.com/support/documentation/application_notes/xapp052.pdf