数字电路基础---寄存器

目录

数字电路基础---寄存器

1、寄存器简介

1.1、寄存器是如何工作的

2、实验任务

3、程序设计

3.1、模块设计

3.2、绘制波形图

4、编写代码

5、仿真验证

5.1、编写 TB 文件

5.2、仿真验证

6、总结

7、拓展训练


数字电路基础---寄存器

       寄存器是构成时序逻辑最重要的一个单元,可以说没有寄存器就没有时序逻辑。寄存器是由触发器组成的,一个触发器可以组成一个一位的寄存器,多个触发器可以组成一个多位的寄存器。

1、寄存器简介

寄存器一般是由多个触发器构成的,所以在学习寄存器之前,我们先来了解一下触发器。

       从 D 触发器的电路图中我们可以看出,该电路是由两个相同的 D 锁存器以及两个非门连接而成的,图中的 F1 F2 就是 D 锁存器的电路符号,F1 为主锁存器,F2 为从锁存器,由于主锁存器的输出信号 Q0 就是从锁存器的输入信号,因而造成了两个锁存器的主从关系,这两个锁存器的控制信号都由外部时钟信号 CLK 提供。

1.1、寄存器是如何工作的

        首先当 CLK=0 时,CLK 经过非门后直接作为 F1 的控制信号,那么此时 F1 的控制信号为 1F1 被选通,F1 处于工作状态。如果现在输入信号 D 1 的话,它经过 F1F1 的输出 Q0 就为 1,这里的 Q0 不仅是 F1 的输出信号,同时也是 F2 的输入信号。不过现在 F2 的控制信号为 0,因此 F2 现在被锁存了,处于保持状态。输入信号 D 没有办法直接改变输出 Q1 的状态,这是前半拍的工作情况,也就是说,输入信号先存入主锁存器中,但不直接影响输出 Q1 的状态。

       接下来我们再来看后半拍,当外部的控制信号 CLK 0 变为 1 时,经过第一个作为 F1 控制信号的非门后,此时 F1 的控制信号将变为 0。主锁存器 F1 就被封锁了,它的输出 Q0 将保持在当前的状态,即使现在输入信号 D 再发生改变,Q0 的值也不再受影响了。经过两个非门后,F2 的控制信号 CLK 此时为 1,那么 F2 将处于工作状态。Q0 将会作为 F2 这个从锁存器的输入信号,直接影响到输出信号 Q1 的状态。当 Q0 为 1 时,那么根据 D 锁存器的逻辑规律,输出的 Q1 就为 1F2 Q 非为 0,这就是后半拍的工作情况。在后半拍中我们才能实现整个电路状态的改变,因此从上面的分析中我们就可以看出,在 CLK 信号由 0 变为 1 这样的一个变化周期内,触发器的输出状态只可能改变一次。

       在了解完触发器之后,我们再来看一下寄存器。一个触发器可以组成一个一位的寄存器(一个触发器其实可以看作一个寄存器),多个触发器可以组成一个多位的寄存器,多位的寄存器可以存储多 bit 的二进制数据。

       如果多个触发器组成的寄存器输入都是相同信号,那么寄存器的输出也都是相同的信号,这种属于触发器并联如果多个触发器组成的寄存器输入是互相传递的(下一个触发器的输入是上一个触发器的输出),那么寄存器的输出也都是不相同的信号,这种属于触发器串联

       下面我们先来看下触发器的并联,我们以 2bit 的寄存器为例子说明,如下图所示:

       通过上图,我们可以看到,每个触发器的输入都是 D0F1 触发器的 D0 经过时钟上升沿采样后输出是 Q0F2 触发器的 D0 经过时钟上升沿采样后输出是 Q1。由于两个触发器的 D0 是来自同一个信号,所以每个触发器的 Q 端输出也是相同的。

下面我们来看下这并联下的 2bit 寄存器的状态表格。

       由上表格我们可以看出,只有时钟上升沿,数据采样变化,其他时候数据是保持锁存状态。看完触发器的并联后,接下来我们再来看下触发器的串联,我们还是以 2bit 寄存器为例子说明, 如下图所示:

       通过上图,我们可以看到,第一个触发器的输入是 D0F1 触发器的 D0 经过时钟上升沿采样后输出是 Q0,输出的 Q0 F2 的输入。由于 F2 的输入来自于上一个触发器的输出 Q0,因此 F2 的输出比 F1 的输出要晚一个时钟周期,这个地方也就是通常所说的延迟一拍的概念,在逻辑电路设计里面,俗称“打一拍”,或者寄存一拍。

       下面我们来看下这串联下的 2bit 寄存器的状态表格:

       由寄存器的状态表可以看出,当 F1 的输入为 1 时,在时钟上升沿采样后,F1 的输出是 1,此时 F2 的输出还是 0,当下一个上升沿过去之后,F2 的输出才为 1。同理,如果更多的触发器依次串联,其实完成的是一个多级打拍的功能,也是逻辑电路里面移位的功能,就是一个信号在时钟上升沿跳变的时候依次传递到下一个寄存器中。

2、实验任务

本节的实验任务是设计一个 4 级串联寄存器电路。

3、程序设计

3.1、模块设计

       根据实验任务可知,我们需要设计一个 4 级串联寄存器的电路模块。它的输入端口为 a,输出端口为 y,在输入到输出之间使用 4 个触发器进行串联。而每个触发器都是需要时钟信号以及复位信号,所以我们还需要一个时钟端口以及一个复位端口。

模块端口与功能描述如下表所示:

3.2、绘制波形图

根据模块框图以及端口功能的描述列表可以画出该模块的波形,波形如下图所示:

       从绘制的波形图我们可以看出,因为是时序逻辑电路,所以输入 a 的值会延迟一个时钟周期赋值给 a_reg1。以此类推,每个寄存器的值都会延迟一个时钟周期赋值给下一个寄存器。

4、编写代码

       4 级的串联寄存器需要 4 个寄存器,每个寄存器都是需要有时钟,复位信号,输入和输出,根据波形图我们可以写出如下代码:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/06/19 11:56:45
// Design Name: 
// Module Name: shfit_reg4
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
//实验任务
//本节的实验任务是设计一个 4 级串联寄存器电路。

//4 级的串联寄存器需要 4 个寄存器,每个寄存器都是需要有时钟,复位信号,输入和输出
module shfit_reg4(
    input               sys_clk,      //50MHz系统时钟(一个周期是20ns:1/50MHz=0.02us=20ns)
    input               sys_rst_n,    //全局复位
    input               a,            //输入a
    
    output               y             //输出y
    );

reg         a_reg1;      //寄存器1
reg         a_reg2;      //寄存器2
reg         a_reg3;      //寄存器3
reg         a_reg4;      //寄存器4

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        a_reg1 <= 1'b0;
        a_reg2 <= 1'b0;
        a_reg3 <= 1'b0;
        a_reg4 <= 1'b0;
     end
     else begin
         a_reg1 <= a;
         a_reg2 <= a_reg1;
         a_reg3 <= a_reg2;
         a_reg4 <= a_reg3;
     end
end

assign y = a_reg4;

endmodule

       程序中第 33 行到第 36 行定义了 4 个寄存器,代码第 38 行到第 51 行将 4 个寄存器串联起来,第 53 行将 a_reg4 的值赋给输出 y

       我们可以使用 VIVADO RTL ANALYSlS 来看一下 RTL 电路。

       从上图可以看出,每个触发器都有 sys_clk 输入信号端口、一个异步清零端口、一个输出端口以及一个输出端口。我们代码中的输入 a 通过 a_reg1a_reg2a_reg3 以及 a_reg4 的串联输出到 y,从图中可以看出这个电路就是一个 4 级寄存器组成的移位寄存器。

5、仿真验证

5.1、编写 TB 文件

下面我们编写一个 testbech 激励文件,通过仿真来看下移位寄存器的波形。仿真代码如下:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/06/19 14:15:30
// Design Name: 
// Module Name: tb_shfit_reg4
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tb_shfit_reg4();

reg             sys_clk;
reg             sys_rst_n;
reg             a;

wire           y;

initial  begin
    sys_clk = 1'b1;
    sys_rst_n <= 1'b0;
    a <= 1'b0;
    #201
    sys_rst_n <= 1'b1;
    #100
    a <= 1'b1;
    #100
    a <= 1'b0;
end

always #10 sys_clk <= ~sys_clk;

shfit_reg4 u_shfit_reg4(
    .sys_clk        (sys_clk      ),
    .sys_rst_n      (sys_rst_n    ),
    .a              (a            ),
    
    .y              (y            )
    );

endmodule

编写完我们的仿真代码,就可以对仿真代码进行仿真的验证了。

5.2、仿真验证

我们打开 Modelsim 软件对代码进行仿真,在运行仿真 1us 后,仿真的波形如下图所示:

       由上图可知,当输入信号 a 1 之后,在下一个时钟上升沿到来时,a_reg1 拉高,经过一个时钟后,a_reg2 拉高,再经过一个时钟后,a_reg3 拉高,在 a 拉高之后的第 4 个时钟,a_reg4 也由低变为了高,然后 a_reg4 的值是通过组合逻辑直接赋值给了 y 信号,因此 y 的波形和 a_reg4 也是完全一样的。可以看出触发器的采样都是在时钟上升沿进行的,其他时候触发器是保持之前采样的信号。另外从波形中,我们也能看到一个移位的效果,就是数据 1 依次移动到下一个触发器中。

6、总结

       本章主要为大家介绍了寄存器的相关概念,并且通过一个时序逻辑电路设计了一个移位寄存器。通过代码的编写以及仿真波形的观察,我们知道了带有时序逻辑的 always 语句块都具有延迟一拍的效果。在后续的学习与设计中我们要养成一个思维,看到 always 语句块下的时序逻辑电路,自然的想到会产生延迟一拍的现象,这个也就是人们常说的“打拍”操作。

7、拓展训练

       我们学习并了解了锁存器和寄存器。可以对比一下锁存器以及寄存器到底有什么区别?锁存器最大的危害是什么?可以画一下寄存器和锁存器的波形图进行对比。

  • 14
    点赞
  • 115
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值