线性反馈移位寄存器LFSR,是移位寄存器的一种,通常用于在数字电路中产生伪随机数。寄存器中的初始值叫做种子,种子应该是非零的。LFSR的下一时刻输入为是由整个移位寄存器值的某些位做异或运算的结果。选取哪些位置 用于移位,是需要进行预先设计好的,目的是要产生一个伪随机并且尽可能长周期的数字序列。
n位LFSR,最多产生2^(n-1)种序列(全零或全一被排除,因为全零异或nor结果为0,不会产生新序列,全1同或xnor也是)。
影响下一个状态的比特位叫做抽头。移位寄存器链的多个抽头用作XOR或XNOR门的输入。 然后,此门的输出用作对移位寄存器链开始的反馈,因此用作LFSR中的反馈。
注意:当抽头使用XOR门时,全0的模式不会出现。 当抽头使用XNOR门时,全1的模式将不会出现。 此两种情况LFSR将停止运行。LFSR是伪随机的。输出模式是确定性,可以通过了解XOR门的位置以及当前模式来确定下一个状态。
怎样选取抽头可以产生最大长度的随机序列,可以参考下表;
LFSR的特征方程根据抽头位置来定:
这里可以表示为f(x)=1+c1x+c2x^(2)+c3x^(3)+...+cnx^(n)
比如,如果n=3,f(x)=1+c1x+c2x^(2)+c3x^(3),其中c1和c3为1,那么f(x)=1+x+x^3,抽头对应为a3,a2。
如果初始序列是101,
则输出为:101001110100111010011……
`timescale 1ns/1ps
module top_module ();
reg clk=0;
always #5 clk = ~clk; // Create clock with period=10
initial `probe_start; // Start the timing diagram
`probe(clk); // Probe signal "clk"
// A testbench
reg set_seed;
reg [2:0] seed_data;
reg enable;
parameter bits_num=3;
initial begin
set_seed=1;
enable=1;
seed_data=3'b101;
#10 set_seed=0;
#60 $finish; // Quit the simulation
end
LFSR #(.bits_num(bits_num)) inst1( .clk(clk),.enable(enable),.set_seed(set_seed),.seed_data(seed_data)); // Sub-modules work too.
endmodule
module LFSR #(parameter bits_num=3)(
input clk,
input enable,
input set_seed,
input [bits_num-1:0] seed_data,
output [bits_num-1:0] lfsr_data,
output lfsr_done//cycle done
);
`probe(clk);
`probe(enable);
`probe(set_seed);
`probe(seed_data);
`probe(lfsr_data);
`probe(r_lfsr);
reg [bits_num:1] r_lfsr;
reg r_xnor;
always @(posedge clk)
begin
if (enable == 1'b1)
begin
if (set_seed == 1'b1)
r_lfsr <= seed_data;
else begin
$display("1.r_lfsr=%b,time=%g",r_lfsr,$time);
r_lfsr <= {r_lfsr[bits_num-1:1],r_xnor};
$display("2.r_lfsr=%b,r_xnor=%b,time=%g",r_lfsr,r_xnor,$time);
end
end
end
always @(*)//一开始就要有变化,所以不设置为posedge clk。
begin
case (bits_num)//3-32
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
end
assign lfsr_data = r_lfsr[bits_num:1];
assign lfsr_done = (r_lfsr[bits_num:1] == seed_data) ? 1'b1 : 1'b0;
endmodule
结果:
LFSR分为两种:一种是IE型的LFSR,即异或门内接的线性反馈移位寄存器,如下图第一张。另一种是异或门外接的线性反馈移位寄存器,简称EE型LFSR,如第二张。这两种类型在代码表现上是不一样的。第一种LFSR的任何一位,如果g=1,其下一时刻值就是输出位以及其前一位的异或。
第二种LFSR的任何一位,如果g=1,其下一时刻值就是其前一位的值,但是输入位的值,就需要其参与异或得到。