赞
踩
写在前面,4位右移移位寄存器,顾名思义使用四个触发器级联,从一次输入到输出,只移动了3位,而不是4位。比如输入是1101,输出时为0001,而不是0000。
虚拟机:VMware -14.0.0.24051
环 境:ubuntu 18.04.1
脚 本:makefile(点击直达)
应用工具:vcs 和 verdi
行为级描述
结构级描述
移位寄存器可以存储数据,还可以用来实现数据的串并转换、分频,构成序列码发生器、序列码检测器等;上图是4位右移寄存器原理图,依据移位寄存器的特点,移位寄存器在时钟的控制下,可将输入数据依次往后移动,N个寄存器级联,最后输出的数据是输入数据的右移N-1
位。其中,左边的空位会被补0。其中QD是串行输出端,{QA,QB,QC,QD}可实现并行输出,如果将输出端QD接到输入端QI,则可以实现自循环移位寄存器。
Signal Name | Width | Direction | Description |
---|---|---|---|
clk | 1 | input | System clk signal, xxMhz |
rst | 1 | input | System reset signal |
data | 1 | input | Detected data |
result | 1 | output | Detection result signal |
//行为级描述 //-- modified by xlinxdu, 2022/04/27 module shift( input clk_i , input rst_n_i, input data_i , output reg [3:0] out_o ); reg [3:0] out_s; always @ (posedge clk_i or negedge rst_n_i)begin if(!rst_n_i)begin out_s <= 4'b0; end else begin out_s <= {out_s[2:0],data_i}; end end always @ (posedge clk_i or negedge rst_n_i)begin if(!rst_n_i)begin out_o <= 4'b0; end else begin out_o <= (out_s >> 3); end end endmodule
//结构级描述 //-- modified by xlinxdu, 2022/04/27 module shift( input clk_i , input rst_n_i , input data_i , output reg [3:0] result_o, output reg [3:0] out_o ); reg [2:0] cnt; reg QA,QB,QC,QD; always @ (posedge clk_i or negedge rst_n_i)begin if(!rst_n_i) begin cnt <= 2'b0; QA <= 1'b0; QB <= 1'b0; QC <= 1'b0; QD <= 1'b0; result_o <= 4'b0; end else begin QA <= data_i; QB <= QA; QC <= QB; QD <= QC; result_o <= {QD,QC,QB,QA}; end end always @ (posedge clk_i or negedge rst_n_i)begin if(!rst_n_i) begin out_o <= 4'b0; end else begin out_o <= {out_o[2:0],QD}; end end endmodule
//行为级描述测试平台 //-- modified by xlinxdu, 2022/04/27 module tb_shift; reg clk_i; reg rst_n_i; reg data_i; // wire [3:0] result_o; wire [3:0] out_o; initial begin clk_i = 0; rst_n_i = 1; data_i = 0; #10 rst_n_i = 0; #10; rst_n_i = 1; end always #50 clk_i = ~clk_i; always begin #100 data_i = 1; #100 data_i = 1; #100 data_i = 0; #100 data_i = 1; #100; end shift tb_shift( .clk_i(clk_i), .rst_n_i(rst_n_i), .data_i(data_i), // .result_o(result_o), .out_o(out_o) ); initial begin $fsdbDumpfile("shift.fsdb"); $fsdbDumpvars ; $fsdbDumpMDA ; #1000 $finish ; end endmodule
//结构描述测试平台 //-- modified by xlinxdu, 2022/04/27 module tb_shift; reg clk_i; reg rst_n_i; reg data_i; wire [3:0] result_o; wire [3:0] out_o; initial begin clk_i = 0; rst_n_i = 1; data_i = 0; #10 rst_n_i = 0; #10; rst_n_i = 1; end always #50 clk_i = ~clk_i; always begin #100 data_i = 1; #100 data_i = 1; #100 data_i = 0; #100 data_i = 1; #100; end shift tb_shift( .clk_i(clk_i), .rst_n_i(rst_n_i), .data_i(data_i), .result_o(result_o), .out_o(out_o) ); initial begin $fsdbDumpfile("shift.fsdb"); $fsdbDumpvars ; $fsdbDumpMDA ; #1000 $finish ; end endmodule
分析:
在行为级描述过程中,输出只与输入有关,每次只会操作就近的四位数据,之外的数据会被丢弃掉,四位内左侧补0,因为每次只有四位数据被赋值到中间变量out_s造成下一次的时候,四位以外的数据丢失了,数据不符合实际电路产生的值(bug)。
在结构级描述过程中,输出与result_o是4位寄存器的并输出端,out_o是移位后数据的输出端,其中输出的值需要看该时刻前面的完整的输入值。比如刚开始的时候,串行输入值为0110时,移位输出值为0000;串行输入值为01101时,移位输出值为0001;串行输入值为0110111时,移位输出值为0110,,依次类推,每来一个时钟,数据右移一位输出。
针对上述情况,分析产生数据丢失的是因为中间的缓存变量每次只缓存4bit数据,而在四位移位寄存器中,要保证数据不被截取掉,至少保证数据位宽为7(移动的3bit+4bit数据)。见下表:
输入 | 累计数据(4bit) | 移位后的数据(>>3) | 累计数据(7bit) | 移位后的数据(>>3) | |
---|---|---|---|---|---|
a | 000a | 0000 | 000_000a | 0000 | |
b | 00ab | 0000 | 000_00ab | 0000 | |
c | 0abc | 0000 | 000_0abc | 0000 | |
d | abcd | 000a | 000_abcd | 000a | |
e | bcde | 000b | 00a_bcde | 00ab | |
f | cdef | 000c | 0ab_cdef | 0abc | |
g | defg | 000d | abc_defg | abcd | |
h | efgh | 000h | bcd_efgh | bcde |
作者:xlinxdu
版权:本文是作者原创,版权归作者所有。
转载:未经作者允许,禁止转载,转载必须保留此段声明,必须在文章中给出原文连接。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。