首先把系统框图和时序图画出来: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