厚街网站建设,网站的icp备案信息是什么,织梦dedecms网站更换域名后文章图片路径批量修改,wordpress主题商城主题什么是移位寄存器
移位寄存器#xff1a;是指多个寄存器并排相连#xff0c;前一个寄存器的输出作为下一个寄存器的输入#xff0c;寄存器中存放的数据在每个时钟周期向左或向右移动一位。
下面的右移移位寄存器因为左侧没有有效输入#xff0c;所以在第4个时钟周期…什么是移位寄存器
移位寄存器是指多个寄存器并排相连前一个寄存器的输出作为下一个寄存器的输入寄存器中存放的数据在每个时钟周期向左或向右移动一位。
下面的右移移位寄存器因为左侧没有有效输入所以在第4个时钟周期寄存器内就已经没有有效数据了。
反馈移位寄存器寄存器被移出的数据后又通过某种方式或函数重新连接到了移位寄存器的输入端从而使得移位寄存器有不断的输出。
线性反馈移位寄存器Linear-Feedback Shift RegisterLFSR当反馈移位寄存器的反馈函数为线性函数时就称这个移位寄存器是反馈移位寄存器。LFSR所用的线性反馈函数一般为 异或 或者 同或。
在每个时钟周期LFSR的新的输入值会被反馈到内部各个寄存器的输入端输入值中的一部分来源于LFSR的输出端另一部分来源于LFSR各输出端进行异或运算得到。
什么是LFSR
LFSR的初始值被称为种子Seed。由异或门构成的LFSR的种子不能为全0因为0与0异或永远为0所以移位寄存器的输出永远都不会变化。同理由同或门构成的LFSR的种子则不能为全1。
LFSR中的寄存器的个数被称为LFSR的级数。一个3级的LFSR最多同时存放3bit数据。一个n级的LFSR最多只有2^n - 1个状态因为要排除全0状态 或 全1状态比如3级的LFSR就只有7个状态。
LFSR的有些位参与反馈有些位不参与反馈其中参与的位被称为抽头。因为触发器编号从1开始因此抽头的取值范围是1~(2^n-1)。
如果设计得当与抽头有关那么LFSR产生的状态可以是周期性的。只要选择合适的反馈函数便可使序列的周期达到最大值(2^n-1)周期达到最大值的序列称为m序列 m-sequence 。比如下面的LFSR假设种子为111会依次产生 111110100001010101011 这7个状态然后又重新从111开始循环。 不同的级数如何选取正确的抽头可以参考下面这个表表内的抽头选取都是可以保证LFSR能运转到最多状态的。
LFSR的两种分类
目前有两类常用的LFSR斐波那契LFSR 和 伽罗瓦LFSR下面分别就进行介绍。
斐波那契LFSRFibonacci LFSRs又被称为多到一型LFSR即多个触发器的输出通过反馈来驱动一个触发器的输入。下图是一个典型的斐波那契LFSR反馈抽头为3和2。 伽罗瓦LFSRFibonacci LFSRs又被称为一到多型LFSR即以个触发器的输出通过反馈来驱动多个触发器的输入。下图是一个典型的伽罗瓦LFSR反馈抽头同样为3和2。这个伽罗瓦LFSR同样可以产生7级序列但是序列的排序与斐波那契LFSR产生的序列是不同的。 斐波那契LFSR和伽罗瓦LFSR有同样的功能但是伽罗瓦LFSR的电路性能要由于斐波那契LFSR因为它在两个触发器之间只使用了一个异或门或者同或门。
Verilog实现与仿真
下面用Verilog分别实现抽头为8.6.5.4的8级斐波那契LFSR和伽罗瓦LFSR8级LFSR的状态数为2^8-1255个。 . 这个网站LFSR自动工具有一个很好用的LFSR工具可以自定义抽头、级数反馈方式和LFSR种类它可以自动生成Verilog代码和穷举所有的LFSR状态。
斐波那契LFSR
用同或门作为反馈函数生成抽头为8.6.5.4的8级斐波那契LFSRVerilog代码如下
//8级斐波那契LFSR多到1型LFSR设计
//同或门作为反馈函数反馈多项式为 f(x)x^8 x^6 x^5 x^4 1
module LFSR8_Fib(input clk,input rst, output reg [7:0] lfsr
);always (posedge clk) beginif(rst)//同或门种子可以选取全0同时FPGA复位后也会复位到0比较方便lfsr 8h0; else begin//抽头从1开始为8、6、5、4lfsr[0] ~(lfsr[3] ^ lfsr[4] ^ lfsr[5] ^ lfsr[7]);//低位移动到高位lfsr[7:1] lfsr[6:0];end
end生成的LFSR示意图如下 为了验证生成电路的正确性需要编写TB文件进行验证。对于这种简单的模块只有255个状态最简单的验证办法就是穷举所有状态与正确状态进行对比即可。方法有几种
方法1手动对比 移位LFSR软件提供了所有正确的输出所以我们只需要将正确的向量与仿真出来的波形结果一一对比即可这种方法简单但是效率较低且容易出错。编写的TB文件如下
timescale 1ns/1ns
module tb_LFSR8_Fib();
//信号声明
reg clk;
reg rst;
reg [7:0] cnt; //记录状态个数一共255个没有全1状态
wire [7:0] lfsr;//模块实例化
LFSR8_Fib inst_LFSR8_Fib(.clk (clk),.rst (rst), .lfsr (lfsr)
); //生成时钟信号
initial beginclk 1b1;forever #5 clk ~clk;
end//生成复位信号
initial beginrst 1b1; //复位#45 rst 1b0; //取消复位
end//仿真过程
initial beginwait(cnt 255); //所有状态都仿真结束#10 $stop; //关闭仿真
end//记录状态个数每个有效时钟周期加1
always(posedge clk)beginif(rst)cnt 8d0;else begincnt cnt 1d1;end
endendmodule仿真结果如下 与正确向量一一对比即可发现仿真结果无误。
方法2将仿真结果打印到Tcl窗口然后复制到文件再与正确向量对比。对比方式可以是手动对比也可以是用插件自动进行对比。
这种方法只需要部分修改TB文件
//记录状态个数每个有效时钟周期加1
always(posedge clk)beginif(rst)cnt 8d0;else begincnt cnt 1d1;$display(%h,lfsr); //打印每一个状态到窗口end
end然后Tcl窗口就打印出了仿真结果 方法3基本与方法2类似只不过将将仿真结果直接打印到文件再与正确向量对比。对比方式可以是手动对比也可以是用插件自动进行对比。TB文件如下
timescale 1ns/1ns
module tb_LFSR8_Fib();
//信号声明
reg clk;
reg rst;
reg [7:0] cnt; //记录状态个数一共255个没有全1状态
wire [7:0] lfsr;//定义文件句柄
integer handle_file_out; //模块实例化
LFSR8_Fib inst_LFSR8_Fib(.clk (clk),.rst (rst), .lfsr (lfsr)
); //生成时钟信号
initial beginclk 1b1;forever #5 clk ~clk;
end//生成复位信号
initial beginrst 1b1; //复位#45 rst 1b0; //取消复位
end//仿真过程
initial beginwait(cnt 255); //所有状态都仿真结束#10 $fclose(handle_file_out); //关闭文件$stop; //关闭仿真
end//打开文件file_out相对路径需要与TB文件在同一目录下
initial begin//handle_file_out $fopen(file_out.txt,w);//相对路径handle_file_out $fopen(G:/file_out.txt,w);//绝对路径
end//记录状态个数每个有效时钟周期加1
always(posedge clk)beginif(rst)cnt 8d0;else begincnt cnt 1d1;//$display(%h,lfsr); //打印每一个状态到窗口//打印每一个状态到文件$fdisplay(handle_file_out,%h,lfsr); end
endendmodule打开file_out文件可以看到数据都已经被保存好了 方法4在TB文件中读取正确向量并自动与仿真结果一一对比若对比有误则输出某个标志信号。TB文件如下
timescale 1ns/1ns
module tb_LFSR8_Fib();
//信号声明
reg clk;
reg rst;
wire [7:0] lfsr;reg [7:0] cnt; //记录状态个数一共255个没有全1状态
reg [7:0] lfsr_gold [0:254]; //构建一个数组来存储正确向量位宽为8个数为255个
reg flag; //错误标志1表示对比错误0表示对比正确
reg [7:0] cnt_error; //错误计数器//模块实例化
LFSR8_Fib inst_LFSR8_Fib(.clk (clk),.rst (rst), .lfsr (lfsr)
); //生成时钟信号
initial beginclk 1b1;forever #5 clk ~clk;
end//生成复位信号
initial beginrst 1b1; //复位#45 rst 1b0; //取消复位
end//读取正确向量
initial begin$readmemh(G:/file_in.txt,lfsr_gold); //绝对路径
end//仿真过程
initial beginwait(cnt 255); //所有状态都仿真结束if (cnt_error 0)//打印仿真成功信息$display(simulation succeed!);else//打印仿真错误信号$display(simulation failed,there is %d errors!,cnt_error);#10 $stop; //关闭仿真
end//记录状态个数每个有效时钟周期加1
always(posedge clk)beginif(rst)begincnt 8d0;flag 1b0;cnt_error 8d0;end else begincnt cnt 1d1;if(lfsr_gold[cnt] ! lfsr)begin //如果对比有误//$display(cnt%d is wrong,cnt); //打印错误的地方flag 1b1; //拉高错误标志cnt_error cnt_error 1; //错误计数器加1endelse beginflag 1b0;cnt_error cnt_error;end end
endendmodule为了对比仿真结果我故意把正确向量的第2个数据改成错误数据仿真结果如下 Tcl窗口也打印了错误 把正确向量的错误修正后再仿真仿真无误打印的信息如下 这种方式可以自动对比正确向量与仿真结果大大提高了效率。
伽罗瓦LFSR
用同或门作为反馈函数生成抽头为8.6.5.4的8级伽罗瓦LFSRVerilog代码如下
//8级伽罗瓦LFSR1到多型LFSR设计
//同或门作为反馈函数反馈多项式为 f(x)x^8 x^6 x^5 x^4 1
module LFSR8_Gal(input clk,input rst, output reg [7:0] lfsr
);wire feedback;;assign feedback lfsr[7];always (posedge clk)beginif(rst)//同或门种子可以选取全0同时FPGA复位后也会复位到0比较方便lfsr 8h0;else begin//抽头从1开始为8、6、5、4lfsr[0] feedback;lfsr[1] lfsr[0];lfsr[2] lfsr[1];lfsr[3] lfsr[2];lfsr[4] lfsr[3] ~^ feedback;lfsr[5] lfsr[4] ~^ feedback;lfsr[6] lfsr[5] ~^ feedback; lfsr[7] lfsr[6];end
endendmodule电路示意图如下 仿真脚本依然用上面的即可这里就不啰嗦了。
禁止状态的处理
用同或门作为反馈函数的LFSR是禁止使用全1状态的因为全1的同或还是1会导致移位寄存器一直处于全1状态出不来。这是的n级的LFSR只有2^n - 1 个状态比一般的计数器状态少1个。如果需要完善这种禁止状态的处理可以增加一部分电路来改变。
斐波那契LFSR可以增加一个判断寄存器是否为全1的电路并将其输出连接到同或门示意图如下 如果不为全1状态则全1判断电路输出为00异或任何数都等于该数本身即不会对原有电路造成影响。如果为全1状态则全1判断电路输出为1此时同或门的输出为0所以下一个状态的最低位即为0也就是说跳出了全1状态。
这部分的Verilog代码如下
//8级斐波那契LFSR多到1型LFSR设计
//同或门作为反馈函数反馈多项式为 f(x)x^8 x^6 x^5 x^4 1
module LFSR8_Fib(input clk,input rst, output reg [7:0] lfsr
);always (posedge clk) beginif(rst)//同或门种子可以选取全0同时FPGA复位后也会复位到0比较方便lfsr 8h0; else begin//抽头从1开始为8、6、5、4增加全1状态的跳出lfsr[0] ~(lfsr[3] ^ lfsr[4] ^ lfsr[5] ^ lfsr[7] ^ (lfsr[6:0]7b1111111));//低位移动到高位lfsr[7:1] lfsr[6:0];end
endendmodule仿真也没问题能从全1状态跳出 同理伽罗瓦LFSR也可以增加一个判断寄存器是否为全1的电路并将其输出连接到同或门示意图如下 如果不为全1状态则全1判断电路输出为00异或任何数都等于该数本身即不会对原有电路造成影响。如果为全1状态则全1判断电路输出为1此时异或门的输出为0所以下一个状态的抽头位全变为0也就是说跳出了全1状态。
这部分的Verilog代码如下
//8级伽罗瓦LFSR1到多型LFSR设计
//同或门作为反馈函数反馈多项式为 f(x)x^8 x^6 x^5 x^4 1
module LFSR8_Gal(input clk,input rst, output reg [7:0] lfsr
);wire feedback;;//增加全1状态的跳出
assign feedback lfsr[7] ^ (lfsr[6:0]7b1111111);;always (posedge clk)beginif(rst)//同或门种子可以选取全0同时FPGA复位后也会复位到0比较方便lfsr 8h0;else begin//抽头从1开始为8、6、5、4lfsr[0] feedback;lfsr[1] lfsr[0];lfsr[2] lfsr[1];lfsr[3] lfsr[2];lfsr[4] lfsr[3] ~^ feedback;lfsr[5] lfsr[4] ~^ feedback;lfsr[6] lfsr[5] ~^ feedback; lfsr[7] lfsr[6];end
endendmodule仿真也没问题能从全1状态跳出 您有任何问题都可以在评论区和我交流本文由 孤独的单刀 原创首发于CSDN平台博客主页wuzhikai.blog.csdn.net您的支持是我持续创作的最大动力如果本文对您有帮助还请多多点赞、评论和收藏⭐