[source]

Module prim_lfsr

LfsrTypeLfsrDwEntropyDwStateOutDwDefaultSeedCustomCoeffsStatePermEnStatePermMaxLenSVALockupSVAExtSeedSVANonLinearOutclk_ilogicrst_nilogicseed_en_ilogicseed_i[LfsrDw-1:0]logiclfsr_en_ilogicentropy_i[EntropyDw-1:0]logicstate_ologic[StateOutDw-1:0]

Block Diagram of prim_lfsr

This module implements different LFSR types

0) Galois XOR type LFSR ([1], internal XOR gates, very fast). Parameterizable width from 3 to 168 bits. Coefficients obtained from [3].

  1. Fibonacci XNOR type LFSR, parameterizable from 3 to 168 bits. Coefficients obtained from [3].

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

[2] https://users.ece.cmu.edu/~koopman/lfsr/ [3] https://www.xilinx.com/support/documentation/application_notes/xapp052.pdf

Parameters

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.

Ports

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

Assertions

Name

Kind

Description

prim_lfsr.MinLfsrWidth_A

immediate assert

check that the most significant bit of polynomial is 1

(LfsrDw >= ($low(LFSR_COEFFS) + LUT_OFF))

prim_lfsr.MaxLfsrWidth_A

immediate assert

(LfsrDw <= ($high(LFSR_COEFFS) + LUT_OFF))

prim_lfsr.DefaultSeedNzCheck_A

immediate assert

check that seed is not all-zero

| DefaultSeedLocal

prim_lfsr.MinLfsrWidth_A

immediate assert

check that the most significant bit of polynomial is 1

(LfsrDw >= ($low(LFSR_COEFFS) + LUT_OFF))

prim_lfsr.MaxLfsrWidth_A

immediate assert

(LfsrDw <= ($high(LFSR_COEFFS) + LUT_OFF))

prim_lfsr.DefaultSeedNzCheck_A

immediate assert

check that seed is not all-ones

! & DefaultSeedLocal

prim_lfsr.UnknownLfsrType_A

immediate assert

0

prim_lfsr.SboxPermutationCheck_A

concurent assert

All bit positions must be marked with 1.

disable iff((!rst_ni)!=='0)& sbox_perm_test

prim_lfsr.DataKnownO_A

concurent assert

///////////////////// shared assertions // /////////////////////

disable iff((!rst_ni)!=='0)! $isunknown(state_o)

prim_lfsr.NextStateCheck_A

concurent assert

check whether next state is computed correctly we shift the assertion by one clock cycle (##1) in order to avoid erroneous SVA triggers right after reset deassertion in cases where the precondition is true throughout the reset. this can happen since the disable_iff evaluates using unsampled values, meaning that the assertion may already read rst_ni == 1 on an active clock edge while the flops in the design have not yet changed state.

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

All bit positions must be marked with 1.

& 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

MSB must be one in any case

disable iff((!rst_ni)!=='0)coeffs[LfsrDw - 1]

prim_lfsr.OutputKnown_A

concurent assert

output check

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

if no external input changes the lfsr state, a lockup must not occur (by design) `ASSERT(NoLockups_A, (!entropy_i) && (!seed_en_i) |=> !lockup, clk_i, !rst_ni)

disable iff((!rst_ni)!=='0)(((lfsr_en_i && ! entropy_i) && ! seed_en_i) |=> ! lockup)

prim_lfsr.ExtDefaultSeedInputCheck_A

concurent assert

check that external seed is correctly loaded into the state rst_ni is used directly as part of the pre-condition since the usage of rst_ni in disable_iff is unsampled. See #1985 for more details

disable iff((!rst_ni)!=='0)((seed_en_i && rst_ni) |=> (lfsr_q == $past(seed_i)))

prim_lfsr.LfsrLockupCheck_A

concurent assert

check that a stuck LFSR is correctly reseeded

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])