博文目录


写在前面正文
  • 原理
  • Verilog实现
  • 仿真测试
  • 代码提示
  • 参考资料
  • 交个朋友

写在前面


博客首页

注:学习交流使用!

正文

原理

线性反馈移位寄存器(LFSR)的英文全称为:Linear Feedback Shift Register。

赛灵思公司的高速串口IP核示例程序经常以LFSR为例,例如Aurora IP的例子程序:

//______________________________ Transmit Data  __________________________________   
//Transmit data when TX_DST_RDY_N is asserted.
//Random data is generated using XNOR feedback LFSR
//TX_SRC_RDY_N is asserted on every cycle with data
always @(posedge USER_CLK)
if(reset_c)
begin
data_lfsr_r <= `DLY 16'hABCD; //random seed value
TX_SRC_RDY_N <= `DLY 1'b1;
end
else if(!TX_DST_RDY_N)
begin
data_lfsr_r <= `DLY {!{data_lfsr_r[3]^data_lfsr_r[12]^data_lfsr_r[14]^data_lfsr_r[15]},
data_lfsr_r[0:14]};
TX_SRC_RDY_N <= `DLY 1'b0;
end

//Connect TX_D to the DATA LFSR register
assign TX_D = {1{data_lfsr_r}};

​相关博客链接​


LFSR代表线性反馈移位寄存器,它是一种在FPGA内部有用的设计。 LFSR易于合成,这意味着它们占用的资源相对较少,并且可以在FPGA内部以很高的时钟速率运行。 使用LFSR可以使许多应用受益,包括:


  • 计数器(Counters)
  • 测试码型发生器(Test Pattern Generators)
  • 数据加扰(Data Scrambling)
  • 密码学(Cryptography)

线性反馈移位寄存器实现为FPGA内部的一系列触发器,这些触发器连接在一起作为移位寄存器。 移位寄存器链的多个抽头用作XOR或XNOR门的输入。 然后,此门的输出用作对移位寄存器链开始的反馈,因此用作LFSR中的反馈。

例如5bit的LFSR的一种形式:

Verilog设计实例(1)线性反馈移位寄存器(LFSR)_LFSR

运行LFSR时,由各个触发器生成的模式是伪随机的,这意味着它接近随机。 它不是完全随机的,因为从LFSR模式的任何状态,您都可以预测下一个状态。 有一些重要的移位寄存器属性需要注意:


  • LFSR模式是伪随机的。
  • 输出模式是确定性的。 您可以通过了解XOR门的位置以及当前模式来确定下一个状态。
    当抽头使用XOR门时,全0的模式不会出现。 由于0与0异或将始终产生0,因此LFSR将停止运行。
  • 当抽头使用XNOR门时,全1的模式将不会出现。 由于将1与1进行异或运算将始终产生1,因此LFSR将停止运行。
  • 任何LFSR的最大可能迭代次数= 2^Bits-1

更长的LFSR将花费更长的时间来运行所有迭代。 N位LFSR的最大可能迭代次数为2^N-1。

如果您考虑一下,所有N位长的东西的所有可能模式都是2^N。 因此,只有一种模式无法使用LFSR表示。 当使用XOR门时,该模式全为0,而使用XNOR门作为您的反馈门时全为1。

VHDL和Verilog代码创建所需的任何N位宽的LFSR。 它使用多项式(这是LFSR背后的数学方法)为每个位宽创建最大可能的LFSR长度。

因此,对于3位,需要2^3-1 = 7个时钟来运行所有可能的组合;

对于4位:2^4-1 = 15;

对于5位:2^5-1 = 31,依此类推。

我基于XNOR实现 以允许FPGA在LFSR上以全零状态启动。 这是Xilinx发布的所有LFSR模式的​​完整表​​。

Verilog实现

下面给出Verilog实现代码:

`timescale 1ns / 1ps
//
// Company:
// Engineer: Reborn Lee
// Create Date: 2020/06/01 12:50:38
// Design Name:
// Module Name: lfsr
// Revision 0.01 - File Created
// Additional Comments:
//
//


module lfsr #(parameter NUM_BITS = 3)(
input i_Clk,
input i_Enable,

// data valid
input i_Seed_DV,

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

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

);

// internal variables
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.
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}; //left right
end
end

// Create Feedback Polynomials. Based on Application Note:
// http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf
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 (?)
assign o_LFSR_Done = (r_LFSR[NUM_BITS:1] == i_Seed_Data) ? 1'b1 : 1'b0;


endmodule

仿真测试

给出一个简单的仿真测试:

`timescale 1ns / 1ps
module lfsr_tb ();

parameter c_NUM_BITS = 4;

reg r_Clk = 1'b0;

wire [c_NUM_BITS-1:0] w_LFSR_Data;
wire w_LFSR_Done;

lfsr #(.NUM_BITS(c_NUM_BITS)) LFSR_inst
(.i_Clk(r_Clk),
.i_Enable(1'b1),
.i_Seed_DV(1'b0),
.i_Seed_Data({c_NUM_BITS{1'b0}}), // Replication
.o_LFSR_Data(w_LFSR_Data),
.o_LFSR_Done(w_LFSR_Done)
);

always @(*)
#10 r_Clk <= ~r_Clk;

endmodule // LFSR_TB

仿真结果:

Verilog设计实例(1)线性反馈移位寄存器(LFSR)_参考资料_02

代码提示

值得注意的是r_LFSR的定义,内部位从1到NUM_BITS,而非0到NUM_BITS -1;

reg [NUM_BITS:1] r_LFSR = 0;

这就意味着移位代码这样写:

r_LFSR <= {r_LFSR[NUM_BITS-1:1],r_XNOR}; //left right

也就是低位往高位移,也即左移。

这是根据这张图来的:

Verilog设计实例(1)线性反馈移位寄存器(LFSR)_LFSR

至于仿真文件中对仿真输入设计的也十分简单,就是单纯让种子为0,也即初始值为0,之后进行反馈移位操作。

lfsr #(.NUM_BITS(c_NUM_BITS)) LFSR_inst
(.i_Clk(r_Clk),
.i_Enable(1'b1),
.i_Seed_DV(1'b0),
.i_Seed_Data({c_NUM_BITS{1'b0}}), // Replication
.o_LFSR_Data(w_LFSR_Data),
.o_LFSR_Done(w_LFSR_Done)
);

在设计文件内部,r_LFSR初始值就是为0,因此,不给种子也可以,反正i_Seed_DV本身在测试文件中就无效。

关于反馈多项式是如何确定的呢?

正是上面提供的文档:

抽头确定

Verilog设计实例(1)线性反馈移位寄存器(LFSR)_触发器_04

此表列出了最大长度为168位的LFSR计数器的相应抽头。前40位的基本描述和表最初在XCELL中发布,并在1993年和1994年Xilinx数据手册的第9-24页上重印。


  • n位LFSR计数器的最大序列长度可以是2^n-1。在这种情况下,它会经历所有可能的代码排列,除了一个锁定状态。
  • 最大长度的n位LFSR计数器由一个n位移位寄存器组成,该移位寄存器在从最后输出Qn到第一输入D1的反馈路径中具有XNOR。XNOR将锁定状态设为all-one状态,也就是说如果种子为全1,则LFSR将锁定,其最终移位结果永远为1;XOR将锁定状态设为all-zeros状态。
  • 对于普通的Xilinx应用程序,全1的触发器都更容易避免,因为“默认情况下”触发器在全零状态下唤醒。
  • Table3描述了必须用作XNOR输入的输出。LFSR输出通常标记为1到n,1是移位寄存器的第一级,n是最后一级。这与二进制计数器的传统0到(n-1)表示法不同。多输入XNOR也称为均匀奇偶校验电路。
  • 请注意,此表中描述的连接不一定唯一;某些其他连接也可能导致最大长度序列。

参考资料

​参考资料1​

​参考资料2​

交个朋友

FPGA/IC技术交流2020