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

2022-09-13 10:04:26 浏览数 (1)

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

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


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


文章目录

  • 一、Overview
  • (1)Theory
  • (2)Demand
  • 二、Interface
  • 三、Timeing
  • 四、Design and Functional Verification
  • (1)RTL
  • (2)Test Bench
  • 五、Result
  • (1)行为级描述测试结果
  • (2)结构级描述测试结果
  • (3)bug分析

一、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

代码语言:javascript复制
//行为级描述
//-- 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
代码语言:javascript复制
//结构级描述
//-- 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

代码语言:javascript复制
//行为级描述测试平台
//-- 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
代码语言:javascript复制
//结构描述测试平台
//-- 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 版权:本文是作者原创,版权归作者所有。 转载:未经作者允许,禁止转载,转载必须保留此段声明,必须在文章中给出原文连接。

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

0 人点赞