FPGA功能模块---边沿检测edge_detector
1、 边沿检测介绍
1.1 目的
检测信号的跳变,即上升沿(0→1)或下降沿(1→0)。
1.2 应用
常用于检测1bit信号的电平跳变,例如光耦、按键、微动开关等器件在正常工作时会产生由0到1或者由1到0的跳变,检测到边沿的跳变后就能知道这些器件在什么时候被触发,方便进行其它的逻辑判断。
1.3 检测方法
设置两个寄存器A和B,分别寄存当前状态和后一状态,若当前状态和后一状态不同,则表示信号有跳变。具体判断逻辑如下:
(1)若A为High,而B为Low,则检测到上升沿;
(2)若A为Low,而B为High,则检测到下降沿;
(3)若A≠B,则检测到双边沿。
1.4 代码实现方式
上升沿 posedge = (A) & (~B)
下降沿 negedge = (~ A) & (B)
双边沿 bothedge= (A) ^ (B)
2、 Verilog代码
2.1 功能描述
(1)用于检测信号上升沿或者下降沿的模块。
(2)可以输出时钟同步后的信号,以及该信号的上升沿、下降沿、双边沿。
(3)边沿信号都是即时反馈的。
(4)模块输出的边沿信号与检测信号是同步的,没有延时。
2.2 输入输出信号
该模块的输出信号不仅包括了传统的上升沿信号和下降沿信号,还一并输出了同步后的检测信号以及双边沿信号,基本可以应对各种各样的应用场景。
module edge_detector
(
input clk ,//系统时钟
input rst_n ,//复位信号,低电平有效
input signal ,//待检测信号
output wire sig_sync ,//时钟同步后的检测信号
output wire sig_posedge ,//sig_sync信号的上升沿标志
output wire sig_negedge ,//sig_sync信号的下降沿标志
output wire sig_bothedge //sig_sync信号的上升沿和下降沿标志
);
2.2 处理输入信号的亚稳态问题
(1)因为检测信号signal与系统时钟信号clk可能会不同步,所以在边沿检测的过程中需要处理亚稳态问题,即对输入信号多寄存一次。
(2)由于signal信号的上电初始值未知,将3个输入信号寄存器signal_temp赋值为1’bx可以避免生成多余的上升沿或者下降沿(详见时序图)。
reg signal_temp1 ;//待检测信号寄存1拍
reg signal_temp2 ;//待检测信号寄存2拍
reg signal_temp3 ;//待检测信号寄存3拍
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
signal_temp1 <= 1'bx ;//(1)signal信号的初始值未知,此处赋值1'bx可以避免生成多余的上升沿或者下降沿
signal_temp2 <= 1'bx ;//(2)若此处为1'b0且signal复位前为1'b1,则进行边沿检测时,会多检测到1个上升沿
signal_temp3 <= 1'bx ;//(3)若此处为1'b1且signal复位前为1'b0,则进行边沿检测时,会多检测到1个下降沿
end
else begin
signal_temp1 <= signal ;
signal_temp2 <= signal_temp1 ;
signal_temp3 <= signal_temp2 ;
end
end
2.3 时序图
2.3.1 正常状态
2.3.2 误判上升沿
若signal_temp复位之前为1’b0且signal复位前为1’b1,则进行边沿检测时,就会多检测到1个上升沿,如下图红色区域所示。
2.3.3 误判下降沿
若signal_temp复位之前为1’b1且signal复位前为1’b0,则进行边沿检测时,就会多检测到1个下降沿,如下图红色区域所示。
2.5 源代码及TestBench仿真文件
源代码:
// ***************************************************************************************************
// 作者 :DingXY的硬件笔记本**************************************************************************
// 邮箱 :1324830818@qq.com **************************************************************************
// 版本 :V1.0 **************************************************************************
// 日期 :2023/12/15 **************************************************************************
// 功能 :********************************************************************************************
// 1、用于检测信号上升沿或者下降沿的模块*************************************************************
// 2、可以输出时钟同步后的信号,以及该信号的上升沿、下降沿、双边沿***********************************
// 3、边沿信号都是即时反馈的*************************************************************************
// ***************************************************************************************************
module edge_detector
(
input clk ,//系统时钟
input rst_n ,//复位信号,低电平有效
input signal ,//待检测信号
output wire sig_sync ,//时钟同步后的检测信号
output wire sig_posedge ,//sig_sync信号的上升沿标志
output wire sig_negedge ,//sig_sync信号的下降沿标志
output wire sig_bothedge //sig_sync信号的上升沿和下降沿标志
);
// ***************************************************************************************************
// 同步不同时钟域的信号,防止亚稳态*******************************************************************
// ***************************************************************************************************
reg signal_temp1 ;//待检测信号寄存1拍
reg signal_temp2 ;//待检测信号寄存2拍
reg signal_temp3 ;//待检测信号寄存3拍
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0) begin
signal_temp1 <= 1'bx ;//(1)signal信号的初始值未知,此处赋值1'bx可以避免生成多余的上升沿或者下降沿
signal_temp2 <= 1'bx ;//(2)若此处为1'b0且signal复位前为1'b1,则进行边沿检测时,会多检测到1个上升沿
signal_temp3 <= 1'bx ;//(3)若此处为1'b1且signal复位前为1'b0,则进行边沿检测时,会多检测到1个下降沿
end
else begin
signal_temp1 <= signal ;
signal_temp2 <= signal_temp1 ;
signal_temp3 <= signal_temp2 ;
end
end
// ***************************************************************************************************
// 时钟同步后的检测信号及其边沿标志*******************************************************************
// ***************************************************************************************************
assign sig_sync = signal_temp2 ;
assign sig_posedge = signal_temp2 & (~ signal_temp3) ;
assign sig_negedge = (~signal_temp2) & ( signal_temp3) ;
assign sig_bothedge = signal_temp2 ^ signal_temp3 ;
endmodule
TestBench仿真文件:
`timescale 1ns/1ns //定义时间刻度
module edge_detector_tb();
reg clk ;//系统时钟
reg rst_n ;//复位信号,低电平有效
reg signal ;//待检测信号
wire sig_sync ;//时钟同步后的检测信号
wire sig_posedge ;//sig_sync信号的上升沿标志
wire sig_negedge ;//sig_sync信号的下降沿标志
wire sig_bothedge;//sig_sync信号的上升沿和下降沿标志
always #10 clk = ~ clk ;//定义主时钟,周期20ns,频率50MHz
initial begin
clk <= 1'b0 ;
rst_n <= 1'b0 ;
signal <= 1'b1 ;
#20 //系统开始工作
rst_n <= 1'b1 ;
#80
signal <= 1'b0 ;
#70
signal <= 1'b1 ;
#90
signal <= 1'b0 ;
#50
signal <= 1'b1 ;
#30
signal <= 1'b1 ;
#80
$finish ;//结束仿真
end
// 例化edge_detector模块
// 用于读取传感器信号时,要求待检测信号:触发时低电平
edge_detector
edge_detector_inst0(
.clk (clk ),//系统时钟
.rst_n (rst_n ),//复位信号,低电平有效
.signal (signal ),//待检测信号
.sig_sync (sig_sync ),//时钟同步后的检测信号
.sig_posedge (sig_posedge ),//sig_sync信号的上升沿标志
.sig_negedge (sig_negedge ),//sig_sync信号的下降沿标志
.sig_bothedge(sig_bothedge ) //sig_sync信号的上升沿和下降沿标志
);
endmodule
2.6 仿真结果
更多内容请关注微信公众号: