2
module LSFR_counter 
#(parameter BITS = 5)
(
  input             clk,
  input             rst_n,

  output reg [4:0] data
);
reg [4:0] data_next;

always @* begin
  data_next[4] = data[4]^data[1];
  data_next[3] = data[3]^data[0];
  data_next[2] = data[2]^data_next[4];
  data_next[1] = data[1]^data_next[3];
  data_next[0] = data[0]^data_next[2];
end

always_ff @(posedge clk or negedge rst_n) begin
  if(!rst_n)
    data <= 5'h1f;
  else
    data <= data_next;
end
endmodule

This is code for LSFR for 4 bit number. I want to implement N bit Random number generator for an FPGA board.

Greg
  • 18,111
  • 5
  • 46
  • 68
Misal313
  • 169
  • 2
  • 8
  • 23
  • It would be good if you could have linked to [the question/answer this came from](http://stackoverflow.com/questions/14497877/how-to-implement-a-pseudo-hardware-random-number-generator), as the answer that contains your example answers your question in the second example. – Morgan Feb 18 '15 at 16:28

3 Answers3

2

N is normally reserved for the state of the LFSR, M would be good to use for the number of random bits we wish to generate.

A standard LFSR generates 1 bit of random data, if consecutive bits of the LFSR are used they can be highly correlated, especially if taking a multi-bit value every clock cycle. To remove this correlation we can overclock the lfsr, say 4 times to generate 4 bits. The alternative to the this is to calculate the equations (feedback polynomials) that you would get for each bit. For every clock its internal state (as represented by the N-bits of the LFSR) would move forward 4 steps. Both techniques for over clocking or creating the feedback taps to move the state forward more than 1 step are known as leap-forward.

The code example in the question has been taken from a previous question and answer, this is an example of manually creating the extra feedback for a leap-forward lfsr.

The maths to do this can be done by generating the transition matrix and raising to the power of the number of steps we wish to move forward.

Quick 4-bit LFRS example: with transition matrix a:

a =

     0     1     0     0
     0     0     1     0
     0     0     0     1
     1     0     0     1

Feedback is XOR of the first and last bit, seen on last row of the matrix. All other rows are just a single shift. The output of this LFSR is good for one bit. Two bits would suffer from a high correlation, unless it was overclocked.

>> a^2

ans =

     0     0     1     0
     0     0     0     1
     1     0     0     1
     1     1     0     1

If we want two bits we need to square the transition matrix. It can be seen that the first two rows are a shift of two places and we require feedback for two places, ie we are moving the LFSR forward two states for every clock.

Just for confirmation if we wanted three bits:

a^3

ans =

     0     0     0     1
     1     0     0     1
     1     1     0     1
     1     1     1     1

The second code example in the previous question went on to parameterise the code so the leap forward calculations did not have to be manually created, skipping all of that lovely maths! However the approach used meant it could not be fully parameterised. Therefore I would like to revisit the example I gave for that question:

module fibonacci_lfsr(
  input  clk,
  input  rst_n,

  output [4:0] data
);

wire feedback = data[4] ^ data[1] ;

always @(posedge clk or negedge rst_n)
  if (~rst_n) 
    data <= 4'hf;
  else
    data <= {data[3:0], feedback} ;

endmodule

Now we want to parameterise it:

module fibonacci_lfsr#(
  parameter POLYNOMIAL = 4'h9
)(
  input  clk,
  input  rst_n,

  output [4:0] data
);

//AND data with POLYNOMIAL this 
// selects only the taps in the polynomial to be used.
// ^(  ) performs a XOR reduction to 1 bit
always @* begin
  feedback  = ^( POLYNOMIAL & data);
end

//Reseting to 0 is easier
// Invert feedback, all 1's state is banned instead of all 0's
always @(posedge clk or negedge rst_n)
  if (~rst_n) 
    data <= 'b0;
  else
    data <= {data[3:0], ~feedback};

endmodule

A small step now, Just bring the shift outside of the synchronous loop to help with the step after.

always @* begin
  data_next = data;
  feedback  = ^( POLYNOMIAL & data);
  data_next = {data_next[3:0], ~feedback} ; //<- Shift and feedback
end

always @(posedge clk or negedge rst_n)
  if (~rst_n) 
    data <= 'b0;
  else
    data <= data_next;

TL;DR

Now to control the leap-forward iterations, let the tools do the heavy lifting of multiplying the transition matrix.

module fibonacci_lfsr#(
  parameter POLYNOMIAL = 4'h9,
  parameter N = 4,
  parameter BITS = 2
)(
  input  clk,
  input  rst_n,

  output [BITS-1:0] random
);
reg [N-1:0] data;
reg [N-1:0] data_next;
reg feedback;

assign random = data[N-1:N-BITS];

always @* begin
  data_next = data;
  // Compiler unrolls the loop, calculating the transition matrix
  for (int i=0; i<BITS; i++) begin
    feedback  = ^( POLYNOMIAL & data_next);
    data_next = {data_next[N-2:0], ~feedback} ; 
  end
end

always @(posedge clk or negedge rst_n)
  if (~rst_n) 
    data <= 'b0;
  else
    data <= data_next;
endmodule

Example on EDA Playground.

i++ is part of SystemVerilog. If you can only synthesis plain (pre-2009) Verilog then you will need to declare i as an integer and use i =i+1 in the for loop.

Community
  • 1
  • 1
Morgan
  • 19,934
  • 8
  • 58
  • 84
1

If you want to implement an N-bit LFSR, then because each length of LFSR has a different polynomial, and hence a difference set of taps to XOR to produce the next LFSR value, you will need to have constants or a lookup table describing the different tap points, which the design could then could use, based on 'BITS'.

A simpler way to do it might be to implement say a 32-bit LFSR, then use the least significant N bits of this as your output. This has the added benefit of increasing the repetition period for anything but the maximum length LFSR, giving better randomness in these cases.

If you're going for the first option, look at whether using the Fibonacci form instead of the Galois form will make the design more conducive to parametrization in this way. I can't quite work out which form you are using in your 5-bit example.

I'm a VHDL guy*, so I can't give Verilog code, but VHDL-like-pseudocode (untested) might look like this:

constant TAPS_TABLE : TAPS_TABLE_type := (
    "00000011",
    "00000110",
    ...
);

for i in 0 to BITS-2 loop
    if (TAPS_TABLE(BITS-2)(i) = '1') then
        data_next(i) <= data(0) xor data(i+1)
    else
        data_next(i) <= data(i+1)
    end if;
end for;

This would support BITS being between 2 and 8 inclusive, assuming the table was completed. The constant TAPS_TABLE would be optimised away during synthesis, leaving you with something no less resource-hungry than a manually coded LFSR.

* This question originally had a 'VHDL' tag.

scary_jeff
  • 4,314
  • 13
  • 27
  • "N-bit LFSR, then because each LFSR has a different polynomial" ... "you will need to have constants or a lookup table which describe the different tap points". I do not understand the logic behind this. Why do we different polynomials for a single LFSR? – Morgan Feb 18 '15 at 16:18
  • "for anything but the maximum length LFSR", any reason why we would not build a maximal length LFSR? – Morgan Feb 18 '15 at 16:21
  • If you were going to simply implement a 32-bit LFSR, then create different size outputs simply by taking the least significant N bits of the 32-bit register, any value for 'N' other than 32 (the maximum length in this case) would give a random sequence longer than it would have been had an LFSR of length N been implemented. This is what I mean by this comment. – scary_jeff Feb 18 '15 at 16:54
  • If you take the other alternative I present, which is to have an LFSR generated that has the specified number of bits in the LFSR (not just the output), then of course the differently sized LFSRs that the code could produce, would each require different taps. – scary_jeff Feb 18 '15 at 16:56
0

In Addition to the previous answers:

Years ago, Xilinx wrote a good AppNote on how to implement 'pseudo random number generators' (PRNGs). The AppNote has a TAP table for n = 3..168. The TAP table is optimized to allow the usage of shift registers. So a PRNG with n=32 does not use 32 single FFs.

Efficient Shift Registers, LFSR Counters, and Long PseudoRandom Sequence GeneratorsXilinx [XAPP 052][1996.07.07]

Paebbels
  • 15,573
  • 13
  • 70
  • 139