FPGA的学习:D触发器

首先把系统框图和时序图画出来:dom

同步复位:只在时钟上升沿发生信号的变化异步

异步复位:在时钟的上升沿和复位信号的降低沿发生信号的变化orm

接着编写程序来实现:blog

`timescale  1ns/1nsip

module  flip_flop
(
    input   wire    sys_clk     ,   //系统时钟
    input   wire    sys_rst_n   ,   //全局复位
    input   wire    key_in      ,   //输入按键input

    output  reg     led_out         //输出
);同步

//同步复位,注意always中的语句与下面异步的不同,并且一次只能运行一个alwaysit

always@(posedge sys_clk)    
    if(sys_rst_n == 1'b0)   
        led_out <= 1'b0;    
    else
        led_out <= key_in;form

 

always@(posedge sys_clk or negedge sys_rst_n) //当always块中的敏感列表为检测到sys_clk上升沿或sys_rst_n降低沿时执行下面的语句
    if(sys_rst_n == 1'b0)                     
        led_out <= 1'b0;
    else
        led_out <= key_in;module

endmodule

 

实现了波形的实现后,进行仿真文件的编写:

`timescale  1ns/1ns

module  tb_flip_flop();

wire            led_out     ;

reg             sys_clk     ;
reg             sys_rst_n   ;
reg             key_in      ;

//初始化系统时钟、全局复位和输入信号
initial begin
    sys_clk    = 1'b1;  //时钟信号的初始化为1,且使用“=”赋值,其余信号的赋值都是用“<=”
    sys_rst_n <= 1'b0;  //由于低电平复位,因此复位信号的初始化为0
    key_in    <= 1'b0;  //输入信号按键的初始化,为0和1都可
    #20
    sys_rst_n <= 1'b1;  //初始化20ns后,复位释放,由于是低电平复位,所示释放时,把信号拉高,电路开始工做
    #210
    sys_rst_n <= 1'b0;  //为了观察同步复位和异步复位的区别,在复位释放后电路工做210ns后再让复位有效。之因此选择延时210ns而不是200ns或220ns,是由于可以使复位信号在时钟降低沿时复位,可以清晰的看出同步复位和异步复位的差异
    #40
    sys_rst_n <= 1'b1;  //复位40ns后再次让复位释放掉
end

always #10 sys_clk = ~sys_clk; //使用always产生时钟信号,让时钟每隔10ns反转一次,即一个时钟周期为20ns,换算为频率为50Mhz

always #20 key_in <= {$random} % 2; //取模求余数,产生非负随机数0、1,每隔20ns产生一次随机数(之因此每20ns产生一次随机数而不是以前的每10ns产生一次随机数,是为了在时序逻辑中可以保证key_in信号的变化的时间小于等于时钟的周期,这样就不会产生相似毛刺的变化信号,虽然产生的毛刺在时序电路中也能被滤除掉,可是不便于咱们观察波形)

initial begin
    $timeformat(-9, 0, "ns", 6);
    $monitor("@time %t: key_in=%b led_out=%b", $time, key_in, led_out);
end

//实例化

flip_flop   flip_flop_inst
(
    .sys_clk    (sys_clk    ),  //input     sys_clk
    .sys_rst_n  (sys_rst_n  ),  //input     sys_rst_n
    .key_in     (key_in     ),  //input     key_in

    .led_out    (led_out    )   //output    led_out
);

endmodule