[笔记].一种独立键盘消抖的Verilog写法.[Verilog]
0赞
发表于 2010/6/10 16:12:27
阅读(9720)
图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 |