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

举报
李锐博恩 发表于 2021/07/15 01:29:06 2021/07/15
【摘要】 博文目录 写在前面正文原理Verilog实现仿真测试代码提示 参考资料交个朋友 写在前面 相关博文 博客首页 注:学习交流使用! 正文 原理 线性反馈移位寄存器(LFSR)的英文全称为:Linear Feedback Shift Register。 赛灵思公司的高速串口IP核示例程序经常以LFSR为例,例如Aurora IP的例子程序: /...

写在前面

相关博文
博客首页
注:学习交流使用!

正文

原理

线性反馈移位寄存器(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}};


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

相关博客链接


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

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

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


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153

仿真测试

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

`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

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

仿真结果:

在这里插入图片描述

代码提示

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

  reg [NUM_BITS:1] r_LFSR = 0;

  
 
  • 1

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

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

  
 
  • 1

也就是低位往高位移,也即左移。
这是根据这张图来的:
在这里插入图片描述
至于仿真文件中对仿真输入设计的也十分简单,就是单纯让种子为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) );

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

关于反馈多项式是如何确定的呢?
正是上面提供的文档:
抽头确定
在这里插入图片描述

此表列出了最大长度为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

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/106473130

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。