安德鲁

[笔记].一种独立键盘消抖的Verilog写法.[Verilog]

0
阅读(9859)

图1 KEY原理图

 


图2 LED原理图

key_led.v

01 module key_led(
02   input            CLOCK_50,
03   input            Q_KEY,
04   input      [4:1] KEY,
05   output reg [4:1] LED
06 ); 
07  
08 //++++++++++++++++++++++++++++++++++++++
09 // 获取键值 开始
10 //++++++++++++++++++++++++++++++++++++++
11 wire [4:1] key_val;                     // 键值
12  
13 key_debounce u0(
14   .i_clk            (CLOCK_50),
15   .i_rst_n          (Q_KEY),
16   .i_key            (KEY),
17   .o_key_val        (key_val)           // 按下为0,松开为1
18 ); 
19 //--------------------------------------
20 // 获取键值 结束
21 //--------------------------------------
22  
23  
24 //++++++++++++++++++++++++++++++++++++++
25 // 按下键后开关LED 开始
26 //++++++++++++++++++++++++++++++++++++++
27 always @ (posedge CLOCK_50, negedge Q_KEY)
28   if (!Q_KEY)
29     LED <= 4'hF;                        // 0灭1亮
30   else
31     case (1'b0)
32       key_val[1] : LED[1] <= ~LED[1];
33       key_val[2] : LED[2] <= ~LED[2];
34       key_val[3] : LED[3] <= ~LED[3];
35       key_val[4] : LED[4] <= ~LED[4];
36       default    : LED    <=  LED   ;   // 缺省亮灭情况不变
37     endcase
38 //--------------------------------------
39 // 按下键后开关LED 结束
40 //--------------------------------------
41  
42 endmodule

key_debounce.v

01 module key_debounce(
02   input            i_clk,
03   input            i_rst_n,
04   input      [4:1] i_key,               // 按下为0,松开为1
05   output reg [4:1] o_key_val            // 键值
06 ); 
07  
08 //++++++++++++++++++++++++++++++++++++++
09 reg [4:1] key_samp1, key_samp1_locked;
10  
11 // 将i_key采集至key_samp1
12 always @ (posedge i_clk, negedge i_rst_n)
13   if(!i_rst_n)
14     key_samp1 <= 4'hF;
15   else        
16     key_samp1 <= i_key;
17  
18 // 将key_samp1锁存至key_samp1_locked
19 always @ (posedge i_clk, negedge i_rst_n)
20   if(!i_rst_n)
21     key_samp1_locked <= 4'hF;
22   else        
23     key_samp1_locked <= key_samp1;
24 //--------------------------------------
25  
26 //++++++++++++++++++++++++++++++++++++++
27 wire [4:1] key_changed1;
28  
29 // 当key_samp1由1变为0时
30 // key_changed1由0变为1,只维持一个时钟周期
31 assign key_changed1 = key_samp1_locked & (~key_samp1);
32 //--------------------------------------
33  
34  
35 //++++++++++++++++++++++++++++++++++++++
36 reg [19:0] cnt;
37  
38 // 一旦有按键按下,cnt立即被清零
39 always @ (posedge i_clk, negedge i_rst_n)
40   if(!i_rst_n)
41     cnt <= 20'h0;
42   else if(key_changed1)
43     cnt <= 20'h0;
44   else
45     cnt <= cnt + 1'b1;
46 //--------------------------------------
47  
48  
49 //++++++++++++++++++++++++++++++++++++++
50 reg [4:1] key_samp2, key_samp2_locked;
51  
52 // 只有当按键不变化(不抖动),且维持20ms以上时
53 // 才将i_key采集至key_samp2
54 always @ (posedge i_clk, negedge i_rst_n)
55   if(!i_rst_n)
56     key_samp2 <= 4'hF;
57   else if(cnt == 20'hF_FFFF)            // 0xFFFFF/50M = 20.9715ms
58     key_samp2 <= i_key;
59  
60 // 将key_samp2锁存至key_samp2_locked
61 always @ (posedge i_clk, negedge i_rst_n)
62   if(!i_rst_n)
63     key_samp2_locked <= 4'hF;
64   else
65     key_samp2_locked <= key_samp2;
66 //--------------------------------------
67  
68 //++++++++++++++++++++++++++++++++++++++
69 wire [4:1] key_changed2;
70  
71 // 当key_samp2由1变为0时
72 // key_changed2由0变为1,只维持一个时钟周期
73 assign key_changed2 = key_samp2_locked & (~key_samp2);
74 //--------------------------------------
75  
76  
77 //++++++++++++++++++++++++++++++++++++++
78 // 每次按键稳定后,输出键值
79 // 按下为0,松开为1
80 always @ (posedge i_clk, negedge i_rst_n)
81   if(!i_rst_n)
82     o_key_val <= 4'hF;
83   else
84     o_key_val <= ~key_changed2;
85 //--------------------------------------
86  
87 endmodule