信号边沿检测总结

 在FPGA逻辑电路中,输入信号的边缘检测是一个常用的操作,这算是FPGA的基本功之一。

  信号边缘检测应用十分广泛,例如:通信协议的时序操作,按键的检测等,都应用到按键的检测。按键的检测分为上升沿和下降沿两种,基本的检测思想是一致的。

     在博客园里,大家也都讨论到了信号的边沿检测,这里我只是做个总结而已!

情形一 :如果需要检测信号的上升沿或者下降沿,一般的处理方法就是 延时取反。     

我们姑且这么叫:b<=in; status<=b 称为 in到status的一次延迟赋值(延迟时间为一个时钟),in到status的n次延迟就以此类推。

输入      in:     1 1 1 1 1 0 0 0 0 0 0 0 1 1 1

一次延迟   delay1: x 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1

输入取反     ~in:    0 0 0 0 0 1 1 1 1 1 1 1 0 0 0

一次延迟取反 ~delay1:x 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0  

上升沿检测:(~delay1)&in --in bit13

下降沿检测:(~in)&delay1 --in bit6

说明:针对边缘毛刺多的地方,比如按键的消除抖动,这里面的延迟需要设定够大(比较好的按键消抖时间20ms左右),通过对时钟的分频进行一次延迟赋值,这样子就能够消除延迟中的抖动,并且能够很好的检测出来按键的边缘。

给出一个简单的边缘检测程序:

复制代码
module prj1(clk,rst_n,in,pos_edge,neg_edge);

input clk,rst_n,in;
output pos_edge,neg_edge;
    
reg delay1;    
reg pos_edge,neg_edge;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        delay1<=0;
        pos_edge<=0;
        neg_edge<=0;
        end
    else begin
        delay1<=in;
        pos_edge <=(~delay1)&in;
        neg_edge <=(~in)&delay1;
    end
end

endmodule

或者进程为:
always@(posedge clk or negedge rst_n)begin
if(!rst_n) begin
H2L_F1 <= 1'b1;
H2L_F2 <= 1'b1;
L2H_F1 <= 1'b0;
L2H_F2 <= 1'b0;
end
else
begin
H2L_F1 <= Pin_In; //Pin_In表示为按键输入
H2L_F2 <= H2L_F1;
L2H_F1 <= Pin_In;
L2H_F2 <= L2H_F1;
end
end

assign H2L_sig = H2L_F2 & !H2L_F1; //H2L表示下降沿
assign L2H_sig = !L2H_F2 & L2H_F1; //L2H表示上升沿
复制代码

仿真结果如图:

情形二 :按键抖动下的边沿检测

  • 抖动的产生:

  通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。

  • 抖动时间

  抖动时间的长短由按键的机械特性决定,一般为5ms~10ms。这是一个很重要的时间参数,在很多场合都要用到按键稳定闭合时间的长短则是由操作人员的按键动作决定的,一般为零点几秒至数秒。键抖动会引起一次按键被误读多次。为确保FPGA对键的一次闭合仅作一次处理,必须去除键抖动。在键闭合稳定时读取键的状态,并且必须判别到键释放稳定后再作处理。

图1  按键抖动

  • FPGA内实现消抖的方法

  在FPGA内实现按键消抖的方法多种多样,但是最简单的是采用移位寄存器的方法进行消抖。因为移位寄存器的方法不需要对时钟进行分频,也不需要进行延时等复杂操作,即可实现对按键边沿的检测。假设未按下时键值=1.

    1、在无键按下时,移位寄存器samp[7:0]始终采集到高电平,即samp[7:0]=8'b1111_1111;

    2、当键按下时,samp[7:0]将采集到低电平,数据的变化方式为samp[7:0]=8'b1111_1110-->8'b1111_1100-->8'b1111_1000-->  ........——>8'b0000_0000;samp[7:0]=8'b1111_1110即为按键下降沿。

    3、当松开按键时,samp[7:0]将重新采集到高电平,数据变化方式为samp[7:0]=8'b0000_0001-->8'b0000_0011--> ........-->8'b1111_1111;当samp[7:0]=8'b0111_1111时,即为按键上升沿。

图2 移位寄存器消抖原理图

  •  参考Verilog代码

 

复制代码
//模块名:EdgeDetect,边沿检测
//button:按键,无键按下时为高电平//clk:10M时钟 //rst:复位按钮,低电平有效 //rise:检测到上升沿,高电平有效,宽度为1个clk //fall:检测到下降沿,高电平有效,宽度为1个clk module EdgeDetect( input clk, input rst, input button, output reg rise, output reg fall );

reg[7:0] samp;//移位寄存器采集button键值 //移位寄存器采集button信息 always@(posedge clk or negedge rst) begin if(!rst) samp<=8'b1111_1111; else samp<={samp[7:1],button}; end //产生上升沿信息 always@(posedge clk or negedge rst) begin if(!rst) rise<=1'b0; else if(samp==8'b1111_1110) rise<=1'b1; else rise<=1'b0; end //产生下降沿信息 always@(posedge clk or negedge rst) begin if(!rst) fall<=1'b0; else if(samp==8'b0111_1111) fall<=1'b1; else fall<=1'b0; end endmodule
复制代码
原文地址:https://www.cnblogs.com/xd-elegant/p/3982310.html