08【Verilog实战】4bit移位寄存器设计与功能验证(附源码)[通俗易懂]

08【Verilog实战】4bit移位寄存器设计与功能验证(附源码)[通俗易懂]一、Overview(1)Theory(2)Demand二、Interface三、Timeing四、DesignandFunctionalVerification(1)RTL(2)TestBench五、Result(1)行为级描述测试结果(2)结构级描述测试结果

大家好,又见面了,我是你们的朋友全栈君。

写在前面,4位右移移位寄存器,顾名思义使用四个触发器级联,从一次输入到输出,只移动了3位,而不是4位。比如输入是1101,输出时为0001,而不是0000。


虚拟机:VMware -14.0.0.24051
环 境:ubuntu 18.04.1
脚 本:makefile(点击直达
应用工具:vcs 和 verdi



一、Overview

(1)Theory

  • 行为级描述
    在这里插入图片描述

  • 结构级描述

在这里插入图片描述

  移位寄存器可以存储数据,还可以用来实现数据的串并转换、分频,构成序列码发生器、序列码检测器等;上图是4位右移寄存器原理图,依据移位寄存器的特点,移位寄存器在时钟的控制下,可将输入数据依次往后移动,N个寄存器级联,最后输出的数据是输入数据的右移N-1位。其中,左边的空位会被补0。其中QD是串行输出端,{QA,QB,QC,QD}可实现并行输出,如果将输出端QD接到输入端QI,则可以实现自循环移位寄存器。

(2)Demand

  1. 当复位信号为0时,输出端全为0;在每个时钟的上升沿时刻,输出端的4位数据向右移一位。
  2. 使用行为级描述和结构建模方式描述。

二、Interface

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

三、Timeing

在这里插入图片描述


四、Design and Functional Verification

(1)RTL

//行为级描述
//-- 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

(2)Test Bench

//行为级描述测试平台
//-- 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

五、Result

(1)行为级描述测试结果

在这里插入图片描述

(2)结构级描述测试结果

在这里插入图片描述
分析
  在行为级描述过程中,输出只与输入有关,每次只会操作就近的四位数据,之外的数据会被丢弃掉,四位内左侧补0,因为每次只有四位数据被赋值到中间变量out_s造成下一次的时候,四位以外的数据丢失了,数据不符合实际电路产生的值bug)。
  在结构级描述过程中,输出与result_o是4位寄存器的并输出端,out_o是移位后数据的输出端,其中输出的值需要看该时刻前面的完整的输入值。比如刚开始的时候,串行输入值为0110时,移位输出值为0000;串行输入值为01101时,移位输出值为0001;串行输入值为0110111时,移位输出值为0110,,依次类推,每来一个时钟,数据右移一位输出。

(3)bug分析

  针对上述情况,分析产生数据丢失的是因为中间的缓存变量每次只缓存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
版权:本文是作者原创,版权归作者所有。
转载:未经作者允许,禁止转载,转载必须保留此段声明,必须在文章中给出原文连接。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/160267.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • gbdt算法_dlt算法

    gbdt算法_dlt算法GBDT算法参数详解

    2022年10月11日
  • python中延时函数_python延时函数

    python中延时函数_python延时函数广告关闭腾讯云11.11云上盛惠,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元!可以使用python的time模块来实现类似于c中的sleep函数作用代码如下:importtimedefsleep(mytime=‘’):time.sleep(mytime)printcallsleepsleep(5)#sleep5sprint‘sleepen…

  • 无法解析类型java.lang.Object_java类型转换异常

    无法解析类型java.lang.Object_java类型转换异常问题场景:1、前端传一个数组,2、后台Controller用map接收。如下@PostMapping(“add/xxxx”)publicResponseObjaddXXXX(@RequestBodyMap<String,Object>map){}3、Service业务类方法中,直接获取数组并转化为实体的集合:List<XXXX&g…

  • java.lang包中不能被继承的类

    java.lang包中不能被继承的类public final class Bytepublic final class Characterpublic static final class Character.UnicodeBlockpublic final class Class&lt;T&gt;public final class Compiler //编译器public final class Doublepub…

  • Git配置账号信息

    Git配置账号信息在前面我们已经简单的说了一下Git是什么,用来干嘛什么,他与SVN的区别,以及它的安装。今天我们接着讲,当第一次下载后我们如何配置自己Git账号信息(这里可以是Github也可以是国内的码云账号等等),下面我们开始主题:这里大概有两种方式一种是通过全局配置信息让所有的项目都使用这个账号,另一种是在指定项目下配置单独的信息默认在我们第一次下载后Git后我们最好是配置到自己…

  • MyEclipse 快捷键

    MyEclipse快捷键1(CTRL)Ctrl+1快速修复Ctrl+D:删除当前行 Ctrl+Q定位到最后编辑的地方 Ctrl+L定位在某行Ctrl+O快速显示O

    2021年12月25日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号