1功能概述
按键开关是各种电子设备不可或缺的人机接口,如电脑的键盘等。实际应用中,按键开关通常为机械式弹性开关。当机械点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定接通,断开时也不会马上断开,在闭合和断开的瞬间均伴随有一连串的抖动。为保证系统及时正确识别,必须对这种情况作出相应处理。我们称之为按键消抖。
按键消抖可分为硬件消抖和软件消抖。硬件消抖的原理是在信号输入系统之前消除抖动干扰,在按键较少的情况下比较适宜。如果按键较多,则使用软件消抖。软件消抖的实质在于降低键盘输入端口的采样频率,将高频抖动略去。需要注意的是,软件消抖需要占据一定的系统资源。
尽管硬件消抖和软件消抖能实现按键消抖功能,串行处理的方式都存在一定的局限性,显得不那么完美。而硬件资源丰富的FPGA系统采用并行处理的模式,利用硬件来减轻软件工作量,通过硬件加速软件消抖处理,即可做到软件消抖并行化,因而在按键消抖处理方面具备非常明显的优势。
优秀的设计程序应该是用最简单的代码(架构、信号)实现功能。在本例中,我们的只需要用4个信号界定,并用很短的代码即可。下面我们先来看看功能要求:
在系统设计中,消除按键抖动的方法五花八门,无论是硬件电路和软件设计都十分成熟。在本项目中,我们将用Verilog语言给出具体实现过程,设计一个程序来检查键值,有效滤除按键抖动区间20 ms的毛刺脉冲。
2 设计思路
一般按键所用开关为机械弹性开关,由于机械触点的弹性作用,每个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,如下图。抖动时间的长短由按键的机械特性决定,一般为5 ms~10 ms。
图xx 按键抖动过程示意
当系统检测出按键闭合后,执行一个延时程序,产生5ms~10ms的延时;前沿抖动消失后,再一次检测键的状态;如果仍保持闭合状态电平,则确认为真正有键按下。当检测到按键释放后,也要给5ms~10ms的延时,待后沿抖动消失后才能转入该键的处理程序。本案例我们设置经过20 ms后的高电平才是真正的按键功能。
根据上述思路并使用下面列表中的信号即可进行代码设计。
信号列表
顶层模块信号列表
信号名 |
I/O |
位宽 |
说明 |
clk |
I |
1 |
系统工作时钟50MHz。 |
rst_n |
I |
1 |
系统复位信号,低电平有效。 |
key_in |
I |
4 |
按键输入信号,按下高电平。 |
key_vld |
O |
4 |
按键有效信号,高电平有效。 |
3 程序设计
顶层模块代码
2 clk ,
3 rst_n ,
4 key_in ,
5 key_vld
6 );
7 parameter DATA_W = 20 ;
8 parameter KEY_W = 4 ;
9 parameter TIME_20MS = 1_000_000 ;
10
11 input clk ;
12 input rst_n ;
13 input [KEY_W-1 :0] key_in ;
14 output [KEY_W-1 :0] key_vld ;
15 reg [KEY_W-1 :0] key_vld ;
16 reg [DATA_W-1:0] cnt ;
17 wire add_cnt ;
18 wire end_cnt ;
19 reg flag ;
20 reg [KEY_W-1 :0] key_in_ff1 ;
21 reg [KEY_W-1 :0] key_in_ff0 ;
22
23 always @(posedge clk or negedge rst_n)begin
24 if(rst_n==1'b0)begin
25 cnt <= 20'b0;
26 end
27 else if(add_cnt)begin
28 if(end_cnt)
29 cnt <= 20'b0;
30 else
31 cnt <= cnt + 1'b1;
32 end
33 else begin
34 cnt <= 0;
35 end
36 end
37
38 assign add_cnt = flag==1'b0 && (key_in_ff1!=0);
39 assign end_cnt = add_cnt && cnt == TIME_20MS - 1;
40
41 always @(posedge clk or negedge rst_n)begin
42 if(rst_n==1'b0)begin
43 flag <= 1'b0;
44 end
45 else if(end_cnt)begin
46 flag <= 1'b1;
47 end
48 else if(key_in_ff1==0)begin
49 flag <= 1'b0;
50 end
51 end
52
53 always @(posedge clk or negedge rst_n)begin
54 if(rst_n==1'b0)begin
55 key_in_ff0 <= 0;
56 key_in_ff1 <= 0;
57 end
58 else begin
59 key_in_ff0 <= key_in ;
60 key_in_ff1 <= key_in_ff0;
61 end
62 end
63
64 always @(posedge clk or negedge rst_n)begin
65 if(rst_n==1'b0)begin
66 key_vld <= 0;
67 end
68 else if(end_cnt)begin
69 key_vld <= key_in_ff1;
70 end
71 else begin
72 key_vld <= 0;
73 end
74 end
75 endmodule
76
77
78
更多资讯请关注微信公众号:fpga520