常用的时序电路介绍

flipflop)这个术语表示在时钟的边沿时刻改变状态的存储元件。下面分别是D锁存器,D触发器(正边沿,上升沿触发),D触发器(负边沿,下降沿触发)的图形符号。图中用>表示边沿触发,小圆圈表示该触发器在负边沿触发。

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

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


vfp中触发器有哪些 触发器的verilog代码_P4

vfp中触发器有哪些 触发器的verilog代码_vfp中触发器有哪些_02

主从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。


vfp中触发器有哪些 触发器的verilog代码_P4_03

D触发器其它实现方式

假设用与非门实现D锁存器,电路图参照前面一篇文章)。我们可以考虑下面的电路,它也可以实现上升沿触发的D触发器。它只有6个与非门,相比主从触发器,更有效率。

同时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的变化。


vfp中触发器有哪些 触发器的verilog代码_vfp中触发器有哪些_04

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

同时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触发器。

    

vfp中触发器有哪些 触发器的verilog代码_触发器_05

D触发器verilog实现

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

module flipflop(D,clk,Q);
  input D;
  input clk;
  output reg Q;

  always @(posedge clk)
    Q <=D;

endmodule
`timescale 1ns/1ns
`define clock_period 20

module flipflop_tb;
  reg D;
  wire Q;
  reg clk;

  flipflop flipflop0(.D(D),.clk(clk),.Q(Q));
  always # (`clock_period/2) clk = ~clk;

  initial
  begin
    D = 1'b0;
	 clk = 1'b0;
	 #(`clock_period)
	 D = 1'b1;
	 #(`clock_period*2)
	 D = 1'b0;
	 #(`clock_period*4)
	 D = 1'b1;
	 #(`clock_period*10)
    $stop;
  end

endmodule

vfp中触发器有哪些 触发器的verilog代码_P4_06



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

      把上面与非门实现的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。


vfp中触发器有哪些 触发器的verilog代码_P4_07



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

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

vfp中触发器有哪些 触发器的verilog代码_vfp中触发器有哪些_08

也可以在时钟的有效沿实现触发器复位清零,这种方式称为同步复位。比如下图中我们把D和Rst_n用一个与门连接起来,Rst_n=1对电路没有影响,Rst_n=0,则在下一个时钟上升沿到来时,触发器清零。

vfp中触发器有哪些 触发器的verilog代码_vfp中触发器有哪些_09


含复位端的触发器

信号名字后面加一个n,通常表示低电平触发信号)。

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

module flipflop_ar(D,clk,Rst_n,Q);
  input D;
  input clk;
  input Rst_n; //复位信号

  output reg Q;

  always @(posedge clk, negedge Rst_n)
    if(Rst_n==0)
	   Q <= 1'b0;
	 else
	   Q <= D ;


endmodule
`timescale 1ns/1ns
`define clock_period 20

module flipflop_ar_tb;
  reg D;
  wire Q;
  reg clk;
  reg Rst_n;

  flipflop_ar flipflop_ar0(.D(D),.clk(clk),.Rst_n(Rst_n),.Q(Q));
  always # (`clock_period/2) clk = ~clk;

  initial
  begin
    D = 1'b0;
	 clk = 1'b0;
	 Rst_n = 1'b1;
	 #(`clock_period)
	 Rst_n = 1'b0;
	 D = 1'b1;
	 #(`clock_period)
	 Rst_n = 1'b1;
	 #(`clock_period*2)
	 D = 1'b0;
	 #(`clock_period*4)
	 D = 1'b1;
	 #(`clock_period*10)
    $stop;
  end

endmodule


vfp中触发器有哪些 触发器的verilog代码_P4_10


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

下面是同步复位的代码:

module flipflop_sr(D,clk,Rst_n,Q);
  input D;
  input clk;
  input Rst_n; //复位信号

  output reg Q;

  always @(posedge clk)
    if(Rst_n==0)
	   Q <= 1'b0;
	 else
	   Q <= D ;


endmodule
`timescale 1ns/1ns
`define clock_period 20

module flipflop_sr_tb;
  reg D;
  wire Q;
  reg clk;
  reg Rst_n;

  flipflop_sr flipflop_sr0(.D(D),.clk(clk),.Rst_n(Rst_n),.Q(Q));
  always # (`clock_period/2) clk = ~clk;

  initial
  begin
    D = 1'b0;
	 clk = 1'b0;
	 Rst_n = 1'b0;
	 #(`clock_period)
	 Rst_n = 1'b1;
	 D = 1'b1;
	 #(`clock_period*2)
	 D = 1'b0;
	 #(`clock_period*4)
	 D = 1'b1;
	 #(`clock_period*10)
    $stop;
  end

endmodule


vfp中触发器有哪些 触发器的verilog代码_vfp中触发器有哪些_11

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

module flipflop_srl(D,clk,Rst_n,Load_n,Q);
  input D;
  input clk;
  input Rst_n; //复位信号
  input Load_n; //置位信号,也是低电平有效

  output reg Q;

  always @(posedge clk)
    if(Rst_n==0)
	   Q <= 1'b0;
	 else if(Load_n==0)
	   Q <= 1'b1;
	 else
	   Q <= D ;


endmodule
`timescale 1ns/1ns
`define clock_period 20

module flipflop_srl_tb;
  reg D;
  wire Q;
  reg clk;
  reg Rst_n;
  reg Load_n;

  flipflop_srl flipflop_srl0(.D(D),.clk(clk),.Rst_n(Rst_n),.Load_n(Load_n),.Q(Q));
  always # (`clock_period/2) clk = ~clk;

  initial
  begin
    D = 1'b0;
	 clk = 1'b0;
	 Rst_n = 1'b0;
	 Load_n = 1'b1;
	 #(`clock_period)
	 Rst_n = 1'b1;
	 D = 1'b1;
	 #(`clock_period*2)
	 D = 1'b0;
	 #(`clock_period*2)
	 Load_n = 1'b0;
	 #(`clock_period*4)
	 Load_n = 1'b1;
	 D = 1'b1;
	 #(`clock_period*10)
    $stop;
  end

endmodule



vfp中触发器有哪些 触发器的verilog代码_上升沿_12