边沿检测指令的作用_一种相对高效的按键消抖方法[通俗易懂]

边沿检测指令的作用_一种相对高效的按键消抖方法[通俗易懂]边沿检测、按键消抖的Verilog实现边沿检测和按键消抖是FPGA设计中比较经常用到的小模块,本篇介绍一下这两个部分的简单实现

边沿检测、按键消抖的Verilog实现
边沿检测和按键消抖是FPGA设计中比较经常用到的小模块,本篇介绍一下这两个部分的简单实现。
1.边沿检测
边沿检测技术在项目应用中,非常广泛。如要有效捕获信号跳变沿,边沿检测技术的应用是必不可少的。其中有如下几个方面
(1)将时钟边沿使能转换为边沿检测使能,使时钟同步化。
(2)捕获信号的突变(UART,SPI 等信号使能突变)
(3)逻辑分析仪中信号的边沿检测。
(4)按键消抖中也可以使用
在这里插入图片描述
就如上图所示,边沿检测就是清楚边沿0和1的变化顺序,时间一般都是从左往右进行,那么对于下降沿会首先检测一个1随后检测到0说明是下降沿,反之首先检测一个0随后检测到1是上升沿。这一点首先要清楚。
其次如何利用0和1来说明是哪个沿,此时我们先把0和1用寄存器寄存,利用(~0)&&1=1。有时综合后是RTL视图是一个两位的寄存器,实际原理电路如下:
在这里插入图片描述
右边寄存器寄存先来的值,左边的寄存后来的,检测到0的取反与1相与。
module byjc(
clk,
rst,
din,
posedge_d,
negedge_d
);
input clk,rst;
input din;
output posedge_d,negedge_d;

reg reg1,reg2;

always@(posedge clk or negedge rst)
begin
	if(!rst)
	begin
		reg1<=1'b0;
		reg2<=1'b0;
	end
	else
		{reg2,reg1}<={reg1,din};
		/*reg1<=din;
		reg2<=reg1;*/
end

assign posedge_d=reg1&&(~reg2);
assign negedge_d=(~reg1)&&reg2;

endmodule
在这里插入图片描述
仿真视图,延后一拍
边沿检测有如下缺陷:
(1)增大 CLK 信号可以增强边沿检测的效率,但不能滤去跳变的杂波。
(2)减少 CLK 可以有效滤去跳变的杂波,但不能及时检测到边沿跳变。
(3)增加 DFF 能更好的滤除杂波,寄存信号,但同时检测延时大。
2.按键消抖
在这里先介绍一下按键消抖的原理。通常我们所使用的开关为机械弹性开关,当我们按下或松开按键时,由于弹片的物理特性,不能立即闭合或断开,往往会在断开或闭合的短时间内产生机械抖动,消除这种抖动的过程即称为按键消抖。按键消抖可分为硬件消抖和软件消抖。硬件消抖主要使用RS触发器或电容等方法实现消抖,一般在按键较少时使用。软件消抖的原理主要为按键按下或松开后延时5ms—20ms采样,也可以在检测到按键状态稳定后采样,即避开抖动区域后再采样,如图 所示
在这里插入图片描述
设计思想就是不断对按键输入值比较,如果发生变化开始计数,一般需要20ms,然后取稳定值。对于50M时钟,20ms需要计数1000000次。在代码中为了说明问题暂时用1000.
module debounce(
input wire clk, rst,
input wire key_in,
output reg key_out,
output reg done
);

//    
localparam TIME_20MS = 1000;       
reg [20:0] cnt;
reg en_cnt;

//按键输入
always @(posedge clk or negedge rst) begin
    if(rst == 0)
        key_out <= 0;
    else 
        key_out <= key_in;
end

//计数器
always @(posedge clk or negedge rst) begin
    if(rst == 0)
        cnt <= 0;
    else if(en_cnt)
        cnt <= cnt + 1'b1;
    else
        cnt <= 0; 
end
 
 //判断按键值是否变化产生使能计数
 always @(posedge clk or negedge rst) begin
        if(rst == 0)
			begin
            en_cnt <= 0;
			done<=0;
			end
        else if(key_in != key_out)
			begin
            en_cnt <= 1;
			done<=0;
			cnt<=0;
			end
        else if(cnt == TIME_20MS - 1)      //计数满产生完成标志
			begin
            en_cnt <= 0;
			cnt<=0;
			done<=1;
			end
 end

endmodule
在这里插入图片描述
仿真结果图
测试:
timescale 1ns/1nsdefine clk_period 20
module debounce_tb;

 reg clk,rst,key_in;
 wire done;
 wire key_out;
 reg [15:0] myrand;
 
  debounce u0(
   .clk(clk),
    .rst(rst),
    .key_in(key_in),
    .done(done),
    .key_out(key_out)

);

initial clk=1;
 always #(`clk_period/2)clk=~clk;
 
 task press_key_in;
   begin
	repeat(20)begin
	  myrand={$random}%65535;
	  #myrand key_in=~key_in;
	  end
	  key_in=0;
	  #20_000_000;
	  
	  repeat(20)begin
	  myrand={$random}%65535;
	  #myrand key_in=~key_in;
	  end
	  key_in=1;
	  #20_000_000;	  
	end
 endtask
 
 initial begin
   rst=0;
   key_in=1;
	#(`clk_period*5)rst=1;
	press_key_in;#100;
   press_key_in;#100;
	$stop;
 end

endmodule

今天的文章边沿检测指令的作用_一种相对高效的按键消抖方法[通俗易懂]分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/88310.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注