机械按键在按下和松开有一个抖动的过程,这个过程大概在10ms到15ms之间,具体取决于实际情况。如果不消除这个抖动,那么我们想要的效果将会得到一个很不确定的值,比如我想要的是按一下数码管显示1,再按一下数码管管显示2,依次显示3,4,5,6;如果不消抖,我按键按一下上面的每一个值都可能显示,所以无法达到我想要的目的。
信号1就是按键按下产生抖动然后平稳,释放再次抖动到平稳的整个过程
信号2就是理想中按键得到的信号,只有一个时钟的高脉冲
之前有讲解按键消抖的思路是检测按键按下和释放动作,进行20ms计数延时,状态机结束表示我们的按键结束,然后得到消抖信号
现在换一种思路,按键按下和未按下的电平是不一样的,当我们检测到代表按下的电平时表示有按键的可能,如果这个电平保持时间大于按下抖动的时间那么证明是按键按下,也就是说当按下电平达到20ms左右时就是按键发生,这个时候输出一个脉冲信号代表按键信号。
module shake(
input clk ,
input rstn ,
input key ,
output shape
);
reg [25:0] cnt_20ms;
parameter num_20ms = 30;//仿真使用
//parameter num_20ms = 1000000;//下开发板使用
always@(posedge clk or negedge rstn)
begin
if(!rstn)begin
cnt_20ms <= 0;
end else if(key == 0)begin
if(cnt_20ms == num_20ms-1)begin
cnt_20ms <= num_20ms;
end else begin
cnt_20ms <= cnt_20ms+1;
end
end else begin
cnt_20ms <= 0;
end
end
assign shape = (cnt_20ms == num_20ms-1) ? 1 : 0;
endmodule
仿真代码如下:
`timescale 1ns / 1ps
module tb_top();
reg clk ;
reg rstn ;
reg key ;
wire shape;
shake shake_u(
.clk (clk ), //input clk ,
.rstn (rstn ), //input rstn ,
.key (key ), //input key ,
.shape (shape) //output shape
);
always#10 clk <= !clk;
initial begin
clk = 0;
rstn = 0;
key = 1;
#100;
rstn = 1;
#500;
repeat(20)begin
key = 0;#20;
key = 1;#20;
end
key = 0;
#1000;
repeat(20)begin
key = 0;#20;
key = 1;#20;
end
end
endmodule