lab03 消抖模块之一
![image [笔记]再笔记--边干边学Verilog HDL --003_第1张图片](http://img.e-com-net.com/image/product/f74b26cd98344e2ea9acce4a2235e624.jpg)
本实验是一个简单的按键消抖。主要由电平检测和10ms延时2个模块组成。
以前,知道按键要消抖,但一直没做过。究其原因,可能是觉得麻烦,效果不炫,悲哀。无论如何,“出来混,总要还的”。咋消抖呢?大大们说,先检测电平变化,再将确定的变化延时输出。说起来简单,其中还有些小九九:
1> 消的是什么抖?
首先,要搞清楚,“抖”(跳变)是从哪里来的,最开始,我们的常识:按下按键,电平就变了。假设是由高变低。事实上,在按下的过程中,由于,按键大多是机械结构,就会产生轻微的跳变,瞬间(us级)跳变n次。也就是说这个瞬间,电平不是那么“干净”,所以就有了消抖的需求:期颐得到“干净”、确定的电平。这要求真不高,只是,俺以前直接无视了。
2> 咋消?
接着上面的按键的动作说,既然电平瞬间就由高变为我们要的低,那么,消抖就要在这个瞬间完成。首先,要知道按键想得到一个什么样的电平,就需要检测电平,而前面说了,电平有段时间是抖动的,干脆从100us之后开始检测,这样就忽略了抖动,(至于这100us是咋来的,科学吗?不晓得,做实验测试,还OK)。检测电平之后,判断出是高变低还是低变高,这个判断有需要很短的时间(ns级),然后,就是稳定的电平了,至此,我们得到了电平的确切变化动作,再加上一个延时模块,包含判断电平变化的时间,也就是akuei2说的“过滤”。这里用的10ms,够吗,当然够,为啥是10ms,不晓得,不过同样,实验可以验证。
3> 设计思路
(1)一旦检测到按键按下(高电平到低电平变化),“电平检查模块”就会拉高H2L_sig电平,然后拉低。
(2)“10ms延迟模块”,检测到H2L_sig高电平,就会利用10ms过滤H2L_sig, 拉高输出。
(3)当按键释放,“电平检测模块”会拉高L2H_sig电平,然后拉低。
(4)“10ms延迟模块”检查到L2H_sig就会利用10ms过滤L2H_sig,然后拉低输出。
代码
detect_module.v
1
/*
*
2
* File name: detect_mocule.v
3
*
4
*/
5
6
module
detect_module
7
(
8
clk, rst_n, pin_in, H2L_sig, L2H_sig
9
);
10
11
input
clk;
12
input
rst_n;
13
input
pin_in;
14
output
H2L_sig;
15
output
L2H_sig;
16
17
parameter
T100US
=
13
'
d5000-1;
18
19
reg
[
12
:
0
] count;
20
reg
isEn;
21
22
always
@(
posedge
clk
or
negedge
rst_n)
23
if
(
!
rst_n)
24
begin
25
count
<=
13
'
d0;
26
isEn
<=
1
'
b0;
27
end
28
else
if
(count
==
T100US)
29
isEn
<=
1
'
b1;
30
else
31
count
<=
count
+
1
'
b1;
32
33
reg
H2L_F1;
34
reg
H2L_F2;
35
reg
L2H_F1;
36
reg
L2H_F2;
37
38
always
@(
posedge
clk
or
negedge
rst_n)
39
if
(
!
rst_n)
40
begin
41
H2L_F1
<=
1
'
b1;
42
H2L_F2
<=
1
'
b1;
43
L2H_F1
<=
1
'
b0;
44
L2H_F2
<=
1
'
b0;
45
end
46
else
47
begin
48
H2L_F1
<=
pin_in;
49
H2L_F2
<=
H2L_F1;
50
L2H_F1
<=
pin_in;
51
L2H_F2
<=
L2H_F1;
52
end
53
54
assign
H2L_sig
=
isEn
?
(H2L_F2
&
!
H2L_F1) :
1
'
b0;
55
assign
L2H_sig
=
isEn
?
(
!
L2H_F2
&
L2H_F1) :
1
'
b0;
56
57
endmodule
58
这里isEn = 1寄存器是表示100us的延迟完成。电平检测模块的有效是发生在100us之后。
delay_module.v
1
/*
*
2
* File name: delay_mocule.v
3
*
4
*/
5
6
module
delay_module
7
(
8
clk, rst_n, H2L_sig, L2H_sig, pin_out
9
);
10
11
input
clk;
12
input
rst_n;
13
input
H2L_sig;
14
input
L2H_sig;
15
output
pin_out;
16
17
parameter
T1MS
=
16
'
d50_000 - 1;
18
19
reg
[
15
:
0
] count;
20
21
always
@(
posedge
clk
or
negedge
rst_n)
22
if
(
!
rst_n)
23
count
<=
16
'
d0;
24
else
if
(isCount
&&
count
==
T1MS)
25
count
<=
16
'
d0;
26
else
if
(isCount)
27
count
<=
count
+
1
'
b1;
28
else
if
(
!
isCount)
29
count
<=
16
'
d0;
30
31
reg
[
3
:
0
] count_ms;
32
33
always
@(
posedge
clk
or
negedge
rst_n)
34
if
(
!
rst_n)
35
count_ms
<=
4
'
d0;
36
else
if
(isCount
&&
count
==
T1MS)
37
count_ms
<=
count_ms
+
1
'
b1;
38
else
if
(
!
isCount)
39
count_ms
<=
4
'
d0;
40
41
reg
isCount;
42
reg
rpin_out;
43
reg
[
1
:
0
] i;
44
45
always
@(
posedge
clk
or
negedge
rst_n)
46
if
(
!
rst_n)
47
begin
48
isCount
<=
1
'
b0;
49
rpin_out
<=
1
'
b0;
50
i
<=
2
'
d0;
51
end
52
else
53
case
(i)
54
55
2
'
d0:
56
if
(H2L_sig) i
<=
2
'
d1;
57
else
if
(L2H_sig) i
<=
2
'
d2;
58
59
2
'
d1:
60
if
(count_ms
==
4
'
d10) begin
61
isCount
<=
1
'
b0;
62
rpin_out
<=
1
'
b1;
63
i
<=
2
'
d0;
64
end
65
else
66
isCount
<=
1
'
b1;
67
68
2
'
d2:
69
if
(count_ms
==
4
'
d10) begin
70
isCount
<=
1
'
b0;
71
rpin_out
<=
1
'
b0;
72
i
<=
2
'
d0;
73
end
74
else
75
isCount
<=
1
'
b1;
76
77
endcase
78
79
assign
pin_out
=
rpin_out;
80
81
endmodule
82
这里isCount是定时器和计数器的使能。由其控制10ms延时的开始。
debounce_module.v
1
/*
*
2
* File name: debounce_mocule.v
3
* Function: debounce module.
4
* ------------------------------
5
* Pins: KEY0-rst_n, KEY1-pin_in, LEDG8-pin_out
6
*
7
* Target board: DE2.
8
* Software: Quartus II 9.1 sp1
9
* ----------------------------
10
* yf.x
11
* 7-12-2011
12
*
13
*/
14
15
module
debounce_module
16
(
17
CLOCK_50, KEY, LEDG
18
);
19
20
input
CLOCK_50;
21
input
[
1
:
0
] KEY;
22
output
[
8
:
8
] LEDG;
23
24
wire
H2L_sig;
25
wire
L2H_sig;
26
27
detect_module U1
28
(
29
.clk (CLOCK_50),
30
.rst_n (KEY[
0
]),
31
.pin_in (KEY[
1
]),
32
.H2L_sig (H2L_sig),
33
.L2H_sig (L2H_sig)
34
);
35
36
delay_module U2
37
(
38
.clk (CLOCK_50),
39
.rst_n (KEY[
0
]),
40
.H2L_sig (H2L_sig),
41
.L2H_sig (L2H_sig),
42
.pin_out (LEDG[
8
])
43
);
44
45
endmodule
46
47
RTL图
![image [笔记]再笔记--边干边学Verilog HDL --003_第2张图片](http://img.e-com-net.com/image/product/29de3522f1a947e0a28a2a0fec1dd31c.png)
小结
本实验的目的是体验“低级建模”里的单模块单功能的建模准则。直观,方便人读。