线性反馈移位寄存器LFSR verilog实现
一、什么是LFSR?
线性反馈移位寄存器(linear feedback shift register, LFSR)是指,给定前一状态的输出,将该输出的线性函数再用作输入的移位寄存器。异或运算是最常见的单比特线性函数:对寄存器的某些位进行异或操作后作为输入,再对寄存器中的各比特进行整体移位(百度百科定义)。
线性反馈移位寄存器反馈分为两种,一种是IE型的LFSR
,即异或门内接的线性反馈移位寄存器:
另一种是异或门外接的线性反馈移位寄存器,简称EE型LFSR
:
gi
表示接不接入反馈,只能为0或1,为1即为接入,为0不接入。
关于线性反馈移位寄存器(LFSR)数学原理更加详细的介绍,可以参考下面这篇文章。
本文主要是介绍如果使用verilog来实现LFSR电路的编写。
需要注意的是,LFSR是伪随机的,这意味着它只是接近随机,并不是完全随机的。这是因为其实从LFSR的任何状态,你都可以预测下一个状态。 有一些重要的移位寄存器属性需要注意:
-
LFSR是伪随机的,从LFSR的任何状态,都可以预测下一个状态。
-
影响下一个状态的比特位叫做抽头。当抽头使用
XOR门
时,全0状态不会出现,这是因为0与0异或将始终产生0,此时LFSR将停止运行。当抽头使用XNOR门
时,全1状态不会出现,这是因为1与1同或(异或非)将始终产生1,此时LFSR将停止运行。 -
任何LFSR的最大可能迭代次数 =
2^N-1
,N为级数,也就是寄存器bit位的个数。
那么怎样的LFSR才能遍历2^N-1
个状态,产生最大的迭代次数呢?也就是到底寄存器的哪些位去组合然后反馈到输入端,才能使该LFSR的所有2^N-1
个状态都出现呢?这里官方给了一个表,我们可以根据这个表来确定LFSR的结构:
需要注意的是LFSR的每一位的索引是从1开始,然后到N,一共 2^N-1
个状态(因为使用异或反馈时要除去全0状态,使用异或非反馈时要除去全1状态)。表中使用的是异或非XNOR。
二、代码设计
代码设计部分没有什么难点,主要是会移位寄存器的写法就可以。然后初始值seed_data
在使用XNOR
时,不要给全1就可以。
`timescale 1ns / 1ps
module lfsr #(parameter Bits_Num = 5)(
input clk,
input rst_n,
// data valid
input seed_valid,
// Optional Seed Value
input [Bits_Num-1:0] seed_data,
output [Bits_Num-1:0] o_LFSR_data
);
reg [Bits_Num:1] LFSR_reg = 0;//保存移位寄存器的状态
reg XNOR_reg;
always @(posedge clk)
begin
if (rst_n != 1'b0)
begin
if (seed_valid == 1'b1)
LFSR_reg <= seed_data;
else
LFSR_reg <= {LFSR_reg[Bits_Num-1:1],XNOR_reg}; //left right
end
end
always @(*)
begin
case (Bits_Num)
3: begin
XNOR_reg = LFSR_reg[3] ^~ LFSR_reg[2];
end
4: begin
XNOR_reg = LFSR_reg[4] ^~ LFSR_reg[3];
end
5: begin
XNOR_reg = LFSR_reg[5] ^~ LFSR_reg[3];
end
6: begin
XNOR_reg = LFSR_reg[6] ^~ LFSR_reg[5];
end
7: begin
XNOR_reg = LFSR_reg[7] ^~ LFSR_reg[6];
end
8: begin
XNOR_reg = LFSR_reg[8] ^~ LFSR_reg[6] ^~ LFSR_reg[5] ^~ LFSR_reg[4];
end
9: begin
XNOR_reg = LFSR_reg[9] ^~ LFSR_reg[5];
end
10: begin
XNOR_reg = LFSR_reg[10] ^~ LFSR_reg[7];
end
11: begin
XNOR_reg = LFSR_reg[11] ^~ LFSR_reg[9];
end
12: begin
XNOR_reg = LFSR_reg[12] ^~ LFSR_reg[6] ^~ LFSR_reg[4] ^~ LFSR_reg[1];
end
13: begin
XNOR_reg = LFSR_reg[13] ^~ LFSR_reg[4] ^~ LFSR_reg[3] ^~ LFSR_reg[1];
end
14: begin
XNOR_reg = LFSR_reg[14] ^~ LFSR_reg[5] ^~ LFSR_reg[3] ^~ LFSR_reg[1];
end
15: begin
XNOR_reg = LFSR_reg[15] ^~ LFSR_reg[14];
end
16: begin
XNOR_reg = LFSR_reg[16] ^~ LFSR_reg[15] ^~ LFSR_reg[13] ^~ LFSR_reg[4];
end
17: begin
XNOR_reg = LFSR_reg[17] ^~ LFSR_reg[14];
end
18: begin
XNOR_reg = LFSR_reg[18] ^~ LFSR_reg[11];
end
19: begin
XNOR_reg = LFSR_reg[19] ^~ LFSR_reg[6] ^~ LFSR_reg[2] ^~ LFSR_reg[1];
end
20: begin
XNOR_reg = LFSR_reg[20] ^~ LFSR_reg[17];
end
21: begin
XNOR_reg = LFSR_reg[21] ^~ LFSR_reg[19];
end
22: begin
XNOR_reg = LFSR_reg[22] ^~ LFSR_reg[21];
end
23: begin
XNOR_reg = LFSR_reg[23] ^~ LFSR_reg[18];
end
24: begin
XNOR_reg = LFSR_reg[24] ^~ LFSR_reg[23] ^~ LFSR_reg[22] ^~ LFSR_reg[17];
end
25: begin
XNOR_reg = LFSR_reg[25] ^~ LFSR_reg[22];
end
26: begin
XNOR_reg = LFSR_reg[26] ^~ LFSR_reg[6] ^~ LFSR_reg[2] ^~ LFSR_reg[1];
end
27: begin
XNOR_reg = LFSR_reg[27] ^~ LFSR_reg[5] ^~ LFSR_reg[2] ^~ LFSR_reg[1];
end
28: begin
XNOR_reg = LFSR_reg[28] ^~ LFSR_reg[25];
end
29: begin
XNOR_reg = LFSR_reg[29] ^~ LFSR_reg[27];
end
30: begin
XNOR_reg = LFSR_reg[30] ^~ LFSR_reg[6] ^~ LFSR_reg[4] ^~ LFSR_reg[1];
end
31: begin
XNOR_reg = LFSR_reg[31] ^~ LFSR_reg[28];
end
32: begin
XNOR_reg = LFSR_reg[32] ^~ LFSR_reg[22] ^~ LFSR_reg[2] ^~ LFSR_reg[1];
end
endcase // case (Bits_Num)
end // always @ (*)
assign o_LFSR_data = LFSR_reg;
endmodule
仿真程序:
`timescale 1ns / 1ps
module lfsr_tb ();
parameter Bits_Num = 5;
//input
reg clk = 1'b0;
reg rst_n = 1'b0;
reg seed_valid = 1'b0;
reg [Bits_Num-1:0]seed_data = 1'b0;
//output
wire [Bits_Num-1:0] o_LFSR_data;
lfsr #(.Bits_Num(Bits_Num)) u_lfsr
(.clk(clk),
.rst_n(rst_n),
.seed_valid(seed_valid),
.seed_data(seed_data),
.o_LFSR_data(o_LFSR_data)
);
always @(*)
#5 clk <= ~clk;
initial
begin
#20 rst_n = 1;
end
initial
begin
#15 seed_valid = 1;
seed_data = 5;
#10 seed_valid = 0;
end
initial
begin
#100 $finish;
end
endmodule
在25ns时采样到seed_data = 5
,LFSR_reg
初始值被置为了00101,然后通过:
LFSR_reg <= {LFSR_reg[Bits_Num-1:1],XNOR_reg}; //left right
XNOR_reg = LFSR_reg[5] ^~ LFSR_reg[3];
计算得到00001也即1,然后后面依次按照算法计算即可。