D型触发器的verilog代码和Testbench的编写

September 14, 2016
作者:dengshuai_super
出处:http://blog.csdn.net/dengshuai_super/article/details/52540819
声明:转载请注明作者及出处。


时序逻辑中为了响应不同的状态,需要对信号进行记忆。存储信号的电路常用的有锁存器(Latches)和D触发器(D-type Flip-Flop),前者使用时钟电平捕获信号,后者使用时钟沿捕获信号。对于使用时钟沿捕获数据的电路结构,同步系统中用Register表示,中文译为寄存器。因此,D触发器是寄存器的一种。

在下面的例子中,用Verilog进行一个D-Latch的RTL的建模示例和一个寄存器(D flip-Flop)的RTL建模示例。最后描绘一个计数器。

锁存器(D-Latch)的RTL的建模

D型触发器的verilog代码和Testbench的编写_第1张图片

module d_latch(d,clk,q);
    input d;
    input clk;
    output q;

    reg q;

    always @ (d,clk)
        if(clk)
            q <= d;
endmodule
`timescale 1ns / 1ns

module d_latch_tb;
    reg clk,d;
    wire q;

    d_latch u1(.d(d),.clk(clk),.q(q));

    initial
    begin
        clk = 1;
        d <= 0;
        forever
        begin
            #60 d <= 1;//人为生成毛刺 
            #22 d <= 0;
            #2  d <= 1;
            #2  d <= 0;
            #16 d <= 0;//维持16ns的低电平,然后让它做周期性的循环
        end
    end

    always #20 clk <= ~clk;//半周期为20ns,全周期为40ns的一个信号
endmodule

在它的Testbench中,其中特别设计了一段毛刺,当clk为高时,d信号被捕获,但同时d信号的变化也反映在输出q中,电平敏感锁存器的透明性质,使得组合电路的毛刺(glitches)被输出,导致一些问题。因此一些FPGA手册强调对锁存器的慎用。(类似于软件编程里慎用goto语句)


D型触发器(D flip-Flop)的RTL建模

D型触发器的verilog代码和Testbench的编写_第2张图片

上图中的小三角代表沿敏感


module d_flip_flop(d,clk,q);
    input d;
    input clk;
    output q;

    reg q;

    always @ (posedge clk)//我们用正的时钟沿做它的敏感信号
    begin
        q <= d;//上升沿有效的时候,把d捕获到q
    end


endmodule
`timescale 1ns / 1ns

module d_flip_flop_tb;
    reg clk,d;
    wire q;

    d_flip_flop u1(.d(d),.clk(clk),.q(q));

    initial
    begin
        clk = 1;
        d <= 0;
        forever
        begin
            #60 d <= 1;//人为生成毛刺 
            #22 d <= 0;
            #2  d <= 1;
            #2  d <= 0;
            #16 d <= 0;//维持16ns的低电平,然后让它做周期性的循环
        end
    end

    always #20 clk <= ~clk;//半周期为20ns,全周期为40ns的一个信号
endmodule

加入复位信号之后:


module d_flip_flop_rst(clk,d,rst,q);
    input d;
    input clk;
    input rst;
    output q;

    reg q;//上电以后,在时钟没有工作之前,这个寄存器应该是个什么信号呢,就是初始化的信号
          //通常上电初始化我们用复位信号来做,用复位信号来指定复位以后的状态
//    always @ (posedge clk)//我们用正的时钟沿做它的敏感信号
//    begin
//        if(rst)//同步复位信号
//            q <=0;
//        else
//            q <= d;//上升沿有效的时候,把d捕获到q
//    end

    always @ (posedge clk,posedge rst)//我们用正的时钟沿做它的敏感信号
    begin
        if(rst)//异步复位信号,跟时钟沿无关,只要复位是高电平就会复位
            q <=0;
        else
            q <= d;//上升沿有效的时候,把d捕获到q
    end    

endmodule

32位计数器

插入图片

module counter(clk,reset,q);

    input clk;
    input reset;
    output [31:0] q;

    reg [31:0] q;//上电以后,在时钟没有工作之前,这个寄存器应该是个什么信号呢,就是初始化的信号
          //通常上电初始化我们用复位信号来做,用复位信号来指定复位以后的状态

    always @ (posedge clk)//在同步复位的情况下,不需要把复位信号放到敏感表里面
    begin
        if(reset)//复位高电平的时候做初始化
            q <= 32'h0000_0000;
        else//复位结束以后让它捕获信号
            q <= q + 1;
    end
endmodule

来源:
https://ke.qq.com/user/tasks/index.html?cid=117307#tid=100127911&fr=2

你可能感兴趣的:(FPGA)