FPGA入门实验之按键消抖

实验要求

生活中很多时候都会用到按键,但按键并不是按下,抬起那么的简单,机器在检测按键按下时,也会进行一系列的判断。但在按下时不可避免的会出现按键抖动,也就是产生多个按下信号,又比如按下过后又再次快速的松开按下,这就使得机器检测到了多个按下信号脉冲,它不知道哪一个是有效的。所以此次实验就是为了消除按键抖动。

设计思路

在检测到按键按下时给它延迟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之内再次按下键的情况,照理说应该不会产升按键输出信号了。各位可以自行测试一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值