Verilog 之 LFSR僞隨機數

The linear feedback shift register is implemented as a series of Flip-Flops inside of an FPGA that are wired together as a shift register. Several taps off of the shift register chain are used as inputs to either an XOR or XNOR gate. The output of this gate is then used as feedback to the beginning of the shift register chain, hence the Feedback in LFSR.


  • LFSR patterns are pseudo-random.
  • Output patterns are deterministic. You can figure out the next state by knowing the position of the XOR gates as well as the current pattern.
  • A pattern of all 0's cannot appear when the taps use XOR gates. Since 0 XORed with 0 will always produce 0, the LFSR will stop running.注意初始化種子
  • A pattern of all 1's cannot appear when the taps use XNOR gates. Since 1 XNORed with 1 will always produce 1, the LFSR will stop running.
  • The maximum possible number of iterations of any LFSR = 2Bits-1

產生僞隨機數的方法最常見的是利用一種線性反饋移位寄存器(LFSR)。它是由n個D觸發器和若干個異或門組成的,如圖:


其中,gn爲反饋係數,取值只能爲0或1,取爲0時表明不存在該反饋之路,取爲1時表明存在該反饋之路;n個D觸發器最多可以提供2^n-1個狀態(不包括全0的狀態),爲了保證這些狀態沒有重複,gn的選擇必須滿足一定的條件。下面以n=3,g0=1,g1=1,g2=0,g3=1爲例,說明LFSR的特性,具有該參數的LFSR結構如下圖:


假設在開始時,D2D1D0=111(seed),那麼,當時鍾到來時,有:

  D2=D1_OUT=1;

  D1=D0_OUT^D2_OUT=0;

  D0=D2_OUT=1;

即D2D1D0=101;同理,又一個時鐘到來時,可得D2D1D0=001. ………………

畫出狀態轉移圖如下:

從圖可以看出,正好有2^3-1=7個狀態,不包括全0;

  如果您理解了上圖,至少可以得到三條結論:

  1)初始狀態是由SEED提供的;

  2)當反饋係數不同時,得到的狀態轉移圖也不同;必須保證gn===1。

  3)D觸發器的個數越多,產生的狀態就越多,也就越“隨機”;

verilog實現

<pre name="code" class="plain">//文章地址:http://www.nandland.com/vhdl/modules/lfsr-linear-feedback-shift-register.html
//程序地址:http://www.nandland.com/verilog/modules/code/LFSR.v


///////////////////////////////////////////////////////////////////////////////
// File downloaded from http://www.nandland.com
///////////////////////////////////////////////////////////////////////////////
// Description: 
// A LFSR or Linear Feedback Shift Register is a quick and easy way to generate
// pseudo-random data inside of an FPGA.  The LFSR can be used for things like
// counters, test patterns, scrambling of data, and others.  This module
// creates an LFSR whose width gets set by a parameter.  The o_LFSR_Done will
// pulse once all combinations of the LFSR are complete.  The number of clock
// cycles that it takes o_LFSR_Done to pulse is equal to 2^g_Num_Bits-1.  For
// example setting g_Num_Bits to 5 means that o_LFSR_Done will pulse every
// 2^5-1 = 31 clock cycles.  o_LFSR_Data will change on each clock cycle that
// the module is enabled, which can be used if desired.
//
// Parameters:
// NUM_BITS - Set to the integer number of bits wide to create your LFSR.
///////////////////////////////////////////////////////////////////////////////
module LFSR #(parameter NUM_BITS)
  (
   input i_Clk,
   input i_Enable,

   // Optional Seed Value
   input i_Seed_DV,
   input [NUM_BITS-1:0] i_Seed_Data,

   output [NUM_BITS-1:0] o_LFSR_Data,
   output o_LFSR_Done
   );

  reg [NUM_BITS:1] r_LFSR = 0;
  reg              r_XNOR;


  // Purpose: Load up LFSR with Seed if Data Valid (DV) pulse is detected.
  // Othewise just run LFSR when enabled.
  // 初始化seed值可以選擇載入,
  always @(posedge i_Clk)
    begin
      if (i_Enable == 1'b1)
        begin
          if (i_Seed_DV == 1'b1)
            r_LFSR <= i_Seed_Data;
          else
            r_LFSR <= {r_LFSR[NUM_BITS-1:1], r_XNOR};
        end
    end

  // Create Feedback Polynomials.  Based on Application Note:
  // http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf
  //使用同或運算,初始化種子不能全1
  
  
  always @(*)
    begin
      case (NUM_BITS)
        3: begin
          r_XNOR = r_LFSR[3] ^~ r_LFSR[2];
        end
        4: begin
          r_XNOR = r_LFSR[4] ^~ r_LFSR[3];
        end
        5: begin
          r_XNOR = r_LFSR[5] ^~ r_LFSR[3];
        end
        6: begin
          r_XNOR = r_LFSR[6] ^~ r_LFSR[5];
        end
        7: begin
          r_XNOR = r_LFSR[7] ^~ r_LFSR[6];
        end
        8: begin
          r_XNOR = r_LFSR[8] ^~ r_LFSR[6] ^~ r_LFSR[5] ^~ r_LFSR[4];
        end
        9: begin
          r_XNOR = r_LFSR[9] ^~ r_LFSR[5];
        end
        10: begin
          r_XNOR = r_LFSR[10] ^~ r_LFSR[7];
        end
        11: begin
          r_XNOR = r_LFSR[11] ^~ r_LFSR[9];
        end
        12: begin
          r_XNOR = r_LFSR[12] ^~ r_LFSR[6] ^~ r_LFSR[4] ^~ r_LFSR[1];
        end
        13: begin
          r_XNOR = r_LFSR[13] ^~ r_LFSR[4] ^~ r_LFSR[3] ^~ r_LFSR[1];
        end
        14: begin
          r_XNOR = r_LFSR[14] ^~ r_LFSR[5] ^~ r_LFSR[3] ^~ r_LFSR[1];
        end
        15: begin
          r_XNOR = r_LFSR[15] ^~ r_LFSR[14];
        end
        16: begin
          r_XNOR = r_LFSR[16] ^~ r_LFSR[15] ^~ r_LFSR[13] ^~ r_LFSR[4];
          end
        17: begin
          r_XNOR = r_LFSR[17] ^~ r_LFSR[14];
        end
        18: begin
          r_XNOR = r_LFSR[18] ^~ r_LFSR[11];
        end
        19: begin
          r_XNOR = r_LFSR[19] ^~ r_LFSR[6] ^~ r_LFSR[2] ^~ r_LFSR[1];
        end
        20: begin
          r_XNOR = r_LFSR[20] ^~ r_LFSR[17];
        end
        21: begin
          r_XNOR = r_LFSR[21] ^~ r_LFSR[19];
        end
        22: begin
          r_XNOR = r_LFSR[22] ^~ r_LFSR[21];
        end
        23: begin
          r_XNOR = r_LFSR[23] ^~ r_LFSR[18];
        end
        24: begin
          r_XNOR = r_LFSR[24] ^~ r_LFSR[23] ^~ r_LFSR[22] ^~ r_LFSR[17];
        end
        25: begin
          r_XNOR = r_LFSR[25] ^~ r_LFSR[22];
        end
        26: begin
          r_XNOR = r_LFSR[26] ^~ r_LFSR[6] ^~ r_LFSR[2] ^~ r_LFSR[1];
        end
        27: begin
          r_XNOR = r_LFSR[27] ^~ r_LFSR[5] ^~ r_LFSR[2] ^~ r_LFSR[1];
        end
        28: begin
          r_XNOR = r_LFSR[28] ^~ r_LFSR[25];
        end
        29: begin
          r_XNOR = r_LFSR[29] ^~ r_LFSR[27];
        end
        30: begin
          r_XNOR = r_LFSR[30] ^~ r_LFSR[6] ^~ r_LFSR[4] ^~ r_LFSR[1];
        end
        31: begin
          r_XNOR = r_LFSR[31] ^~ r_LFSR[28];
        end
        32: begin
          r_XNOR = r_LFSR[32] ^~ r_LFSR[22] ^~ r_LFSR[2] ^~ r_LFSR[1];
        end

      endcase // case (NUM_BITS)
    end // always @ (*)


  assign o_LFSR_Data = r_LFSR[NUM_BITS:1];

  // Conditional Assignment (?)
  //一個循壞結束,數據個數2^NUM_BITS -1 
  assign o_LFSR_Done = (r_LFSR[NUM_BITS:1] == i_Seed_Data) ? 1'b1 : 1'b0;

endmodule // LFSR



testbench程序:
`timescale 1ns / 100ps

`define N_BITS 4
module tb_lfsr;

	reg i_Clk;
	reg i_Enable;

	// Optional Seed Value
	reg i_Seed_DV;
	reg [`N_BITS-1:0] i_Seed_Data;

	wire [`N_BITS-1:0] o_LFSR_Data;
	wire o_LFSR_Done;
	
	LFSR #(.NUM_BITS(`N_BITS)) dut(	.i_Clk(i_Clk),
									.i_Enable(i_Enable),
									.i_Seed_DV(i_Seed_DV),
									.i_Seed_Data(i_Seed_Data),
									.o_LFSR_Data(o_LFSR_Data),
									.o_LFSR_Done(o_LFSR_Done));
	
	always #10 i_Clk = ~i_Clk;
	
	initial begin
		i_Clk = 0;
		i_Enable = 0;
		i_Seed_DV = 0;
		i_Seed_Data = 0;
		
		#15;
		i_Enable = 1;
		i_Seed_DV = 1;
		@(posedge i_Clk);
		#5;
		i_Seed_DV = 0;
	end
	
endmodule


Modelsim仿真結果:





//參考文章地址:http://www.nandland.com/vhdl/modules/lfsr-linear-feedback-shift-register.html
//參考程序地址:http://www.nandland.com/verilog/modules/code/LFSR.v
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章