实验要求
生活中很多时候都会用到按键,但按键并不是按下,抬起那么的简单,机器在检测按键按下时,也会进行一系列的判断。但在按下时不可避免的会出现按键抖动,也就是产生多个按下信号,又比如按下过后又再次快速的松开按下,这就使得机器检测到了多个按下信号脉冲,它不知道哪一个是有效的。所以此次实验就是为了消除按键抖动。
设计思路
在检测到按键按下时给它延迟20ms(因为绝大多数按键抖动都在这个时间左右)。也就是检测第一个上升沿来后延时20ms,那怎么检测到他是第一个上升沿呢?后面抖动还有抖动那么多个上升沿。这个时候就得产生一个计数器,检测到上升沿就开始计数,假如这里是计20个数,当计数满20就等于0了,那么我们只需要检测计数等于1时判断有没有上升沿的到来,其他时候一律按照无效信号处理,这样就避免了按键抖动。按键松开后的设计也是同理,详细见代码。
代码设计
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 15:10:33 04/15/2020
// Design Name:
// Module Name: key_shake_disappear
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module key_shake_disappear(
input clk,
input key_in,//按键输入
output key_out//消抖后的按键输出
);
reg kt=0; //寄存器,记录按键的前一态
reg key_r=0; //上升沿检测
reg key_f=0; //下降沿检测
always@(posedge clk)
kt<=key_in;
always@(posedge clk)
begin
key_r<=key_in & (!kt);
key_f<=(!key_in) & kt;
end
//wire[27:0] TIME_20ms=28'd1000;
reg[27:0] cn_begin=0; //上升沿计数
reg[27:0] cn_end=0; //下降沿计数
always@(posedge clk) //按键第一次松开后20ms清零
if((cn_begin==20) & (cn_end==20))
cn_begin<=0;
//当检测到按键动作,且未计满20ms时计数
else if((key_r) &(cn_begin<=19))
cn_begin<=cn_begin+1;
//当已开始计数,但未计满20ms时
else if(cn_begin>0 & (cn_begin<=19))
cn_begin<=cn_begin+1;
//松开后的延时
always@(posedge clk)
if(cn_end>19)
cn_end<=0;
else if(key_f&(cn_begin==20))
cn_end<=cn_end+1;
else if(cn_end>0)
cn_end<=cn_end+1;
//输出消抖后的按键信号
assign key_out=(cn_begin==1)?1:0;
endmodule
rtl原理图
激励文件
`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 09:42:21 04/16/2020
// Design Name: key_shake_disappear
// Module Name: D:/FPGA_project/work_13/D_N_T_Display/tst_shake.v
// Project Name: D_N_T_Display
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: key_shake_disappear
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
module tst_shake;
// Inputs
reg clk;
reg key_in;
// Outputs
wire key_out;
// Instantiate the Unit Under Test (UUT)
key_shake_disappear uut (
.clk(clk),
.key_in(key_in),
.key_out(key_out)
);
initial begin
// Initialize Inputs
clk = 0;
key_in = 0;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
end
always #10 clk<=!clk;
reg clkt=0;
always #400 clkt<=!clkt; //产生一个测试信号
reg[5:0] cn100=0;
always@(posedge clkt)
cn100<=cn100+1;
always@(posedge clkt)
case(cn100)
0:key_in<=1;
3:key_in<=1;
6:key_in<=1;
12:key_in<=1;
14:key_in<=1;
19:key_in<=1;
default:key_in<=0;
endcase
endmodule
仿真波形
可以看到当按键按下,上升沿产生,按键输出信号key_out产生,然后计数20,下降沿时,也是计数延时20。这里没有测时当按键按下后在计数20之内再次按下键的情况,照理说应该不会产升按键输出信号了。各位可以自行测试一下。