FPGA学习专题-对异步信号的处理(边沿检测)

“众所周知”,FPGA中的操作,很多都是依靠参考时钟来进行的,最简单的

always@(posedge clk or negedge rst)

这条语句在always的敏感信号中,是基于clk的上升沿进行判断,然后再进行接下来的处理的。而实际上你的程序中会出现很多这样的always。
很经典的一个问题就是边沿检测!
按键的信号输入是在任意时刻都有可能发生的,这样的一个随机发生的信号,和系统时钟clk是没有可对照性的,因此会觉得很难处理这玩意儿。
下面来分析一下常用的处理方式

1.一级寄存

下面是主程序的代码,对一个输入信号in_signal进行判断,如果输入出现一个上升沿,则产生一个out_signal的输出高脉冲信号。

1.1主程序代码

module posedge_detect(

	clk,
	rst,
	in_signal,
	out_signal
);

input clk;
input rst;
input in_signal;
output  out_signal;

reg in_signal_buf1;

/*****************寄存一次******************/
always@(posedge clk or negedge rst)
if(!rst)
in_signal_buf1<=1'b0;
else
in_signal_buf1<=in_signal;

assign out_signal = (!in_signal_buf1)&in_signal;

endmodule

1.2RTL视图

在这里插入图片描述

上面的RTL是在对主程序进行分析综合后得到的,可以看出,in_signal信号输入进D触发器进行了一次寄存,然后将D触发器的输出再和in_signal信号进行比较判断。以此来判断两次的输入信号值,通过与门判断是否出现了上升沿。
这里需要注意D触发器,在CLK的上升沿采样D端口的数据,然后输出到Q。通常我们看到的是,如果在CLK的上升沿,D上有个高电平信号,那么会立刻出现在Q端。但是实际情况不是这么理想的,D端数据需要提前保持稳定,然后CLK的上升沿才能采到数据(这个叫建立时间);同时,D的数据还要在CLK上升沿后一段时间继续保持稳定(这个叫保持时间);同时,Q端的数据是延迟D端数据一个时间Tco,这个就是输出延迟。这里写这些只是帮助自己记忆理解,不做分析了。

1.3TestBench

`timescale 1ns/1ns
`define clock_period 20

module posedge_detect_tb;

reg clk;
reg rst;
reg in_signal;
wire out_signal;


posedge_detect posedge_detect1(

	.clk(clk),
	.rst(rst),
	.in_signal(in_signal),
	.out_signal(out_signal)

);

initial clk = 1;
always #(`clock_period/2) clk = ~clk;

initial begin
rst = 1'b0;
in_signal = 1'b0;
#(`clock_period*200)
rst = 1'b1;
#(`clock_period*200)//在clk的上升沿处产生输入信号上升沿  					#1
in_signal = 1'b1;
#(`clock_period*200)//在clk的上升沿处把输入信号拉低,这个输入的高脉冲信号时间足够长,大于一个clk时钟周期
in_signal = 1'b0;
#(`clock_period*200)//clk的上升沿拉高信号								#2
in_signal = 1'b1;
#5					//高电平持续5ns,注意这里是小于一个clk时钟周期了
in_signal = 1'b0;
#(`clock_period*200-10)//拉高输入信号,此时出现在clk的低电平处,不是边沿喽  #3								
in_signal = 1'b1;
#5					//同样持续5ns,小于一个时钟周期
in_signal = 1'b0;
#(`clock_period*200+10)//拉高输入信号,此时出现在clk的高电平处				#4
in_signal = 1'b1;
#2000000000;
$stop;
end

endmodule

注意testbench中的4个输入模拟信号 分别标注了#1、#2、#3、#4;代码中给了明确注释

1.4仿真波形

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
根据上面的4幅图,可以看出,指示上升沿的脉冲信号out_signal,它的脉冲宽度是很难确定的。这个脉冲信号的下降沿是和后面的clk的上升沿对齐的;脉冲信号的上升沿是和输入信号in_signal的上升沿对齐的;这个out_signal的脉冲宽度很难被clk采样到,正常来说,要能被clk采样到,那么它的脉宽起码是一个clk的时钟周期。

2.二级寄存

接来下对信号进行二级寄存

2.1主程序代码

module posedge_detect(

	clk,
	rst,
	in_signal,
	out_signal


);

input clk;
input rst;
input in_signal;
output  out_signal;

reg in_signal_buf1;
reg in_signal_buf2;

/*****************寄存两次******************/
always@(posedge clk or negedge rst)
if(!rst) begin
in_signal_buf1 <=1'b0;
in_signal_buf2 <=1'b0;
end
else begin
in_signal_buf1 <=in_signal;
in_signal_buf2 <=in_signal_buf1;
end

assign out_signal = (!in_signal_buf2)&in_signal_buf1;

endmodule


2.2RTL视图

在这里插入图片描述

2.3TestBench

仿真文件同上

2.4仿真波形

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
具体的分析都备注在图片中了。可见,当将异步输入信号进行两级寄存后,只要这个输入信号的脉宽足够,那么无论如何都能采到这个异步信号。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值