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