常用的时序电路介绍

在电平敏感的锁存器时钟信号有效期(高电平)期间,锁存器的状态随着输入信号的变化而变化。有时候,我们需要存储器的状态在一个时钟周期只改变一次,这个时候就用到了触发器。触发器(flipflop)这个术语表示在时钟的边沿时刻改变状态的存储元件。下面分别是D锁存器,D触发器(正边沿,上升沿触发),D触发器(负边沿,下降沿触发)的图形符号。图中用>表示边沿触发,小圆圈表示该触发器在负边沿触发。

Load_n和Rst_n连线上的小圆圈表示这两个信号时低电平有效。Rst_n将置Q=0,Load_n将置Q=1。

注意:通常在verilog中,我们定义变量名字,如果里面带有_n,就表示该信号是在时钟下降沿触发,n就是negative的意思,这是verilog程序代码中大家默认的一个约定。

主从D触发器

把两个D锁存器串联起来,可以组成主从D触发器,如下图所示。

对于第一个图:clk=1时候,Qm的值随着D变化而变化,Qs保持不变,当clk=0时候,Qm不在变化,Qs=Qm,所以在一个时钟周期内Qs只变化一次。从外部观察者角度,Q在时钟的下降沿改变状态Q=D。

对于第二个图:clk=0时候,Qm的值随着D变化而变化,Qs保持不变,当clk=1时候,Qm不在变化,Qs=Qm,所以在一个时钟周期内Qs只变化一次。从外部观察者角度,Q在时钟的上升沿改变状态Q=D。

D触发器其它实现方式

相同的逻辑功能,可以有不同的电路实现方式。上面的主从D触发器,共有4+4=8个与非门,还有3个反相器,总共11个逻辑门(假设用与非门实现D锁存器,电路图参照前面一篇文章)。我们可以考虑下面的电路,它也可以实现上升沿触发的D触发器。它只有6个与非门,相比主从触发器,更有效率。

Clk=0时,P1=1,P2=1,所以5,6与非门组成的锁存器保持Q当前值。同时P4=~D(这是因为clk=0,所以P2=1,P4=~(P2&D)=~D), P3= ~(P4&P1)=~(P4)=~(~D)=D。

Clk=1时,P1=~(P3&clk)=~D,P2=~(P1&clk&P4)=~(~D&~D)=D,所以Q=D

所以该电路实现了一个上升沿触发的D触发器。

为了使电路保持稳定,Clk信号从0变为1时候,P3和P4必须保持稳定。因此触发器的建立时间为信号D通过门4和门1到P3点的延时时间。触发器的保持时间为门3的延时时间,因为一旦信号P2保持稳定后,D再变化也没有关系了。为了保证电路可靠工作,有必要说明在Clk变为1之后,只要clk=1,信号D的任何后续变化都不会对锁存器的输出产生任何影响。这分为两种情况,第一种情况,假设时钟上升沿时候D=0,则p2=0,因而在clk=1期间,门4的输出保持为1(不管D后续如何变化)。第二种情况,如果时钟上升沿D=1,则P1=0,从而使得门1和门3输出都为1,而与输入信号D无关。所以在clk=1期间,触发器不会理会输入端D的变化。

用或非门构成的类似的电路,可以实现下降沿触发的D触发器。

如下图所示电路,若clk=1, 则P1=0,P2=0,所以5,6或非门组成的锁存器保持Q当前值。同时P4=~D(这是因为clk=1,所以P2=0,P4=~(P2|D)=~D), P3= ~(P4|P1)=~(P4)=~(~D)=D。

Clk=0时,P1=~(P3|clk)=~D,P2=~(P1|clk|P4)=~(~D&~D)=D,所以Q=D

所以该电路实现了一个下降沿触发的D触发器。

D触发器verilog实现

D触发器类似锁存器,区别是它在时钟边沿触发,比如下面的代码在时钟上升沿触发Q=D。

  1. module flipflop(D,clk,Q);
  2. input D;
  3. input clk;
  4. output reg Q;
  5.  
  6. always @(posedge clk)
  7. Q <=D;
  8.  
  9. endmodule
  1. `timescale 1ns/1ns
  2. `define clock_period 20
  3.  
  4. module flipflop_tb;
  5. reg D;
  6. wire Q;
  7. reg clk;
  8.  
  9. flipflop flipflop0(.D(D),.clk(clk),.Q(Q));
  10. always # (`clock_period/2) clk = ~clk;
  11.  
  12. initial
  13. begin
  14. D = 1'b0;
  15. clk = 1'b0;
  16. #(`clock_period)
  17. D = 1'b1;
  18. #(`clock_period*2)
  19. D = 1'b0;
  20. #(`clock_period*4)
  21. D = 1'b1;
  22. #(`clock_period*10)
  23. $stop;
  24. end
  25.  
  26. endmodule

含复位端和预置信号触发器的电路

把上面与非门实现的D触发器中的电路图进行修改,加入预置信号Load_n和复位信号Rst_n。如下图虚线所示,在交叉耦合的锁存器的每个与非门输入端增加一个输入信号。Rst_n =0 会迫使触发器进入Q=0的状态,Rst_n=1对与非门的输出没有任何影响。同理,Load_n=0,会使出使触发器进入Q=1的状态,而Load_n=1,对触发器没有任何影响。注意:不能使Rst_n和Load_n同时为0。

下面把主从D触发器的电路,进行一点修改,并加入预置信号Load_n和复位信号Rst_n。注意:从级没有采用标准的D锁存器,而使用了简单的SR锁存器,可以减少一个非门。如下图虚线所示,在交叉耦合的锁存器的每个与非门输入端增加一个输入信号。Rst_n =0 会迫使触发器进入Q=0的状态,Rst_n=1该输入对与非门的输出没有任何影响。同理,Load_n=0,会使出使触发器进入Q=1的状态,而Load_n=1,对触发器没有任何影响。

注意:不能使Rst_n和Load_n同时为0。

上面这两个图中的Rst_n和Load_n都是在低电平时候起作用。比如Rst_n,一旦其为0,则Q立即为0,而与时钟信号没有关系,这种清零复位方式称为异步复位。也可以在时钟的有效沿实现触发器复位清零,这种方式称为同步复位。比如下图中我们把D和Rst_n用一个与门连接起来,Rst_n=1对电路没有影响,Rst_n=0,则在下一个时钟上升沿到来时,触发器清零。

含复位端的触发器

下面的代码实现了一个含异步复位的D触发器。我们增加了一个异步复位信号Rst_n(信号名字后面加一个n,通常表示低电平触发信号)。

低电平有效的复位信号是下降沿触发,高电平有效的复位信号是上升沿触发。(从高变到低,此时是低电平,一定是下降沿,反之一定是上升沿)。所以在代码中,我们通过判断Rst_n==0来复位Q。

  1. module flipflop_ar(D,clk,Rst_n,Q);
  2. input D;
  3. input clk;
  4. input Rst_n; //复位信号
  5.  
  6. output reg Q;
  7.  
  8. always @(posedge clk, negedge Rst_n)
  9. if(Rst_n==0)
  10. Q <= 1'b0;
  11. else
  12. Q <= D ;
  13.  
  14. endmodule

  1. `timescale 1ns/1ns
  2. `define clock_period 20
  3.  
  4. module flipflop_ar_tb;
  5. reg D;
  6. wire Q;
  7. reg clk;
  8. reg Rst_n;
  9.  
  10. flipflop_ar flipflop_ar0(.D(D),.clk(clk),.Rst_n(Rst_n),.Q(Q));
  11. always # (`clock_period/2) clk = ~clk;
  12.  
  13. initial
  14. begin
  15. D = 1'b0;
  16. clk = 1'b0;
  17. Rst_n = 1'b1;
  18. #(`clock_period)
  19. Rst_n = 1'b0;
  20. D = 1'b1;
  21. #(`clock_period)
  22. Rst_n = 1'b1;
  23. #(`clock_period*2)
  24. D = 1'b0;
  25. #(`clock_period*4)
  26. D = 1'b1;
  27. #(`clock_period*10)
  28. $stop;
  29. end
  30.  
  31. endmodule

异步复位这儿指的是通过复位信号的边沿触发复位。如果在时钟信号的边沿触发复位,则是同步复位。

下面是同步复位的代码:

  1. module flipflop_sr(D,clk,Rst_n,Q);
  2. input D;
  3. input clk;
  4. input Rst_n; //复位信号
  5.  
  6. output reg Q;
  7.  
  8. always @(posedge clk)
  9. if(Rst_n==0)
  10. Q <= 1'b0;
  11. else
  12. Q <= D ;
  13.  
  14. endmodule
  1. `timescale 1ns/1ns
  2. `define clock_period 20
  3.  
  4. module flipflop_sr_tb;
  5. reg D;
  6. wire Q;
  7. reg clk;
  8. reg Rst_n;
  9.  
  10. flipflop_sr flipflop_sr0(.D(D),.clk(clk),.Rst_n(Rst_n),.Q(Q));
  11. always # (`clock_period/2) clk = ~clk;
  12.  
  13. initial
  14. begin
  15. D = 1'b0;
  16. clk = 1'b0;
  17. Rst_n = 1'b0;
  18. #(`clock_period)
  19. Rst_n = 1'b1;
  20. D = 1'b1;
  21. #(`clock_period*2)
  22. D = 1'b0;
  23. #(`clock_period*4)
  24. D = 1'b1;
  25. #(`clock_period*10)
  26. $stop;
  27. end
  28.  
  29. endmodule

带置位和复位的同步D触发器代码:

  1. module flipflop_srl(D,clk,Rst_n,Load_n,Q);
  2. input D;
  3. input clk;
  4. input Rst_n; //复位信号
  5. input Load_n; //置位信号,也是低电平有效
  6.  
  7. output reg Q;
  8.  
  9. always @(posedge clk)
  10. if(Rst_n==0)
  11. Q <= 1'b0;
  12. else if(Load_n==0)
  13. Q <= 1'b1;
  14. else
  15. Q <= D ;
  16.  
  17. endmodule
  1. `timescale 1ns/1ns
  2. `define clock_period 20
  3.  
  4. module flipflop_srl_tb;
  5. reg D;
  6. wire Q;
  7. reg clk;
  8. reg Rst_n;
  9. reg Load_n;
  10.  
  11. flipflop_srl flipflop_srl0(.D(D),.clk(clk),.Rst_n(Rst_n),.Load_n(Load_n),.Q(Q));
  12. always # (`clock_period/2) clk = ~clk;
  13.  
  14. initial
  15. begin
  16. D = 1'b0;
  17. clk = 1'b0;
  18. Rst_n = 1'b0;
  19. Load_n = 1'b1;
  20. #(`clock_period)
  21. Rst_n = 1'b1;
  22. D = 1'b1;
  23. #(`clock_period*2)
  24. D = 1'b0;
  25. #(`clock_period*2)
  26. Load_n = 1'b0;
  27. #(`clock_period*4)
  28. Load_n = 1'b1;
  29. D = 1'b1;
  30. #(`clock_period*10)
  31. $stop;
  32. end
  33.  
  34. endmodule

verilog语法实例学习(8)的更多相关文章

  1. verilog语法实例学习(4)

    Verilog模块 Verilog中代码描述的电路叫模块,模块具有以下的结构: module module_name[ (portname {, portname})]; //端口列表 [parame ...

  2. verilog语法实例学习(1)

    本文档中通过verilog实例来学习verilog语法.Verilog是一种硬件描述语言,它具有并发性和时序性.并发性是指不同硬件模块的同时操作,时序性是指信号的赋值或操作在时钟的边沿进行.由于作者本 ...

  3. verilog语法实例学习(12)

    verilog中的综合和不可综合总结 Verilog中综合的概念 综合就是EDA工具或者说综合工具把我们编写的verilog代码转化成具体电路的过程.Verilog中有很多语法,结构,过程,语句,有些 ...

  4. verilog语法实例学习(6)

    函数和任务 函数 https://wenku.baidu.com/view/d31d1ba8dd3383c4bb4cd283.html verilog中函数的目的是允许代码写成模块的方式而不是定义独立 ...

  5. verilog语法实例学习(5)

    子电路模块 子电路模块的使用 一个verilog模块能够作为一个子电路包含在另一个模块中.采用这种方式,所有的模块都必须定义在一个文件中,那么verilog编译器就必须被告知每个模块的所属.模块例化的 ...

  6. verilog语法实例学习(2)

    Verilog中的信号类型 线网类型 线网类型表示一个或多个门或者其它类型的信号源驱动的硬件连线.如果没有驱动源,则线网的默认值为z.verilog中定义的线网类型有以下几种:     wire,tr ...

  7. verilog语法实例学习(13)

    verilog代码编写指南 变量及信号命名规范  1. 系统级信号的命名.  系统级信号指复位信号,置位信号,时钟信号等需要输送到各个模块的全局信号:系统信号以字符串Sys开头.  2. 低电平有效的 ...

  8. verilog语法实例学习(11)

    同步时序电路的一般形式 时序电路由组合逻辑以及一个或多个触发器实现.一般的架构如下图所示:W为输入,Z为输出,触发器中存储的状态为Q.在时钟信号的控制下,触发器通过加在其输入端的组合逻辑输入,使得电路 ...

  9. verilog语法实例学习(10)

    常用的时序电路介绍 T触发器和JK触发器 在D触发器输入端添加一些简单的逻辑电路,可以生成另一种类型的存储元件.比如下图所示的T触发器.该电路有一个上升沿触发的触发器和两个与门,一个或门,以及一个反相 ...

  10. verilog语法实例学习(9)

    常用的时序电路介绍 寄存器 一个触发器可以存储一位数据,由n个触发器组成的电路可以存储n位数据,我们把这一组触发器叫做寄存器.寄存器中每个触发器共用同一个时钟. 下面是n位寄存器的代码,我们通过一个参 ...

随机推荐

  1. 反射调用 java bean的set和get方法

    一.使用java.beans.PropertyDescriptor import java.beans.IntrospectionException; import java.beans.Proper ...

  2. 利用transform的bug使fixed相对于父级定位

    首先,大家都清楚,元素使用fixed之后,若不设置top与left则会相对于最近的使用定位的父元素,并位于父元素的原点位置设置top与left值时,则会相对于窗口定位.但无论如何,此时仍相对于窗口定位 ...

  3. css样式大全整理

    字体属性:(font) 大小 {font-size: x-large;}(特大) xx-small;(极小) 一般中文用不到,只要用数值就可以,单位:PX.PD 样式 {font-style: obl ...

  4. 初识thinkphp(2)

    thinkphp的url路径的表示格式为 http://ip/tp/public/index.php/模块/控制器/操作 这里url最后的操作就是类里面的函数. 0x01:url访问格式 官方文档中有 ...

  5. win7 配置DNS

    Network 右键 properties

  6. C#开发Unity游戏教程之使用脚本变量

    C#开发Unity游戏教程之使用脚本变量 使用脚本变量 本章前面说了那么多关于变量的知识,那么在脚本中要如何编写关于变量的代码,有规章可循吗?答案是有的.本节会依次讲解变量的声明.初始化.赋值和运算. ...

  7. Fisher–Yates shuffle 洗牌算法(zz)

    1,缘起 最近工作上遇到一个问题,即将一组数据,比如[A,B,C,D,E]其中的两个B,E按随机排列,其他的仍在原来的位置: 原始数组:[A,B,C,D,E] 随机字母:[B,D] 可能结果:[A,B ...

  8. Android Native层异步消息处理框架

     *本文系作者工作学习总结,尚有不完善及理解不恰当之处,欢迎批评指正* 一.前言 在NuPlayer中,可以发现许多类似于下面的代码: //============================== ...

  9. 【原】使用Eclipse远程Debug测试环境

    [环境参数] Eclipse:Version: Mars.2 Release (4.5.2) Linux:centOS 6.5 [简述] Java自身支持调试功能,并提供了一个简单的调试工具--JDB ...

  10. Linux kernel AIO

    http://blog.csdn.net/abcd1f2/article/details/47440087