FPGA——按键消抖

按键消抖
按键消抖主要针对的是机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了保证系统能正确识别按键的开关,就必须对按键的抖动进行处理,这就是按键消抖。
按键抖动
开始时的回弹时间和结束时的回弹时间一般为5~10ms,稳定时间一般为20ms,这里采用一个计数器,计数最大时间的为20ms,系统的晶振为50Mhz(换算成时间为20ns),20ms/20ns=1000000,所以计数器计数最大值为999999(从0开始计数)。当是系统检测到按键为低电平时,计数器开始计数,当系统检测到高电平时,对计数器清零。当计数到最大值时,让计数器保持值不变
在这里插入图片描述
然后再定义一个标志信号对按键消抖的稳定状态进行采集。当是计数器计数到最大值时,说明按键已经处于稳定状态。

RTL代码

module	key_shake
#(
	parameter		CNT_MAX = 20'd999_999//计数最大值,20ms
)
(
		input	wire			sys_clk		,
		input	wire			sys_rst_n	,
		input	wire			key_in		,
		
		output	reg				key_flag
);



reg	[19:0]		cnt;

always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		cnt <= 20'd0;
	else	if(key_in == 1'b1)
		cnt <= 20'd0;
	else	if(cnt == CNT_MAX)
		cnt <= CNT_MAX;
	else
		cnt <= cnt + 1'b1;
		
always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		key_flag <= 1'b0;
	else	if(cnt == CNT_MAX)
		key_flag <= 1'b1;
	else
		key_flag <= 1'b0;


endmodule

testbench

`timescale	1ns/1ns 
module	tb_key_shake();

reg			sys_clk;
reg			sys_rst_n;
reg			key_in;
reg	[7:0]	tb_cnt; 
wire		key_flag;

initial	
	begin
		sys_clk = 1'b0;
		sys_rst_n <= 1'b0;
		key_in	<= 1'b1;
		#20
		sys_rst_n <= 1'b1;
	end
	
always	#10 sys_clk = ~sys_clk;

//把按键消抖过程压缩至250个系统周期
always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		tb_cnt <= 8'd0;
	else	if(tb_cnt == 8'd249)
		tb_cnt <= 8'd0;
	else
		tb_cnt <= tb_cnt + 1'b1;

//模拟按键抖动
always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		tb_cnt <= 8'd0;
	else	if(tb_cnt <= 8'd24 || tb_cnt >= 8'd224)
		key_in <= 1'b1;
	else	if((tb_cnt <= 8'd74 && tb_cnt > 8'd24)||(tb_cnt <= 8'd224 && tb_cnt >= 8'd174))
		key_in <= {$random}%2;
	else
		key_in <= 1'b0;
		
key_shake
#(
	.CNT_MAX(70)
)
key_shake_inst
(
		.sys_clk		(sys_clk),
		.sys_rst_n		(sys_rst_n),
		.key_in			(key_in),

		.key_flag       (key_flag)
);

endmodule


仿真结果把按键按下时长缩短到250个系统时钟周期。定义一个计数器tb_cnt,计数最大值为249,然后模拟按键被按下的过程。过程如下图所示
在这里插入图片描述

modelsim仿真结果
在这里插入图片描述
由仿真结果得,每一次模拟按键的稳定状态都被标志信号key_flag采集到。
ps:(部分图片和学习教程由野火提供)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值