1 //课程重点:学会分析状态
2 //没有被按下,空闲静止态,高电平。
3 //按下过程中,抖动过程,会高低电平多次变化。
4 //按下以后,抖动结束,处于按下静止态,输出低电平。
5 //释放过程中,抖动过程,会高低电平多次变化,最终稳定在高电平。
6 //工程师经验,按下过程中抖动不会超过20ms。
7 //按下过后开始计时,如果没有达到20ms的情况下,出现了上升沿/高电平,就认为这是一次抖动直到低电平持续时间超过20ms,才认为按键稳定下来了,此时的状态才是有效的。
8
9 //空闲态,等待按键按下(等待下降沿),就开始20ms的计时。
10 //消抖状态:20ms的计时状态,在这个状态里,一边计时,一边检测有没有出现上升沿,如果有出现上升沿,回到空闲态,如果计满20ms,没有出现上升沿,发出按键按下的通知信号。
11 // 等待释放:等待按键释放(等待上升沿),一旦出现上升沿,就开始20ms的计时
12 //释放消抖状态:20ms的计时状态,在这个状态里,一边计时,一边检测按键有没有出现下降沿,如果出现下降沿,则回到等待释放状态;如果计时满20ms没有出现下降沿,发出按键释放的通知信号。
13
14 //源代码
15
16 // Company:
17 // Engineer:
18 // Create Date: 2023/03/27 20:23:15
19 // Design Name: key_filter
20 // Module Name: key_filter
21 // Project Name:
22 // Tool Versions: 2018.3
23 // Description: 按键消抖
24
25 module key_filter(
26 clk,
27 reset_n,
28 key,
29 // key_p_flag,
30 // key_r_flag,
31 key_flag,
32 key_state
33 );
34 input clk;
35 input reset_n;
36 input key;
37 // output reg key_p_flag;
38 // output reg key_r_flag;
39 output key_flag;
40 output reg key_state;
41
42 reg key_p_flag;
43 reg key_r_flag;
44 assign key_flag = (key_p_flag | key_r_flag);
45
46 //定义两个寄存器来产生上升沿和下降沿。
47
48 reg [1:0] r_key;
49 always@(posedge clk)//利用位拼接来完成。
50 r_key <= {r_key[0],key};
51 // always@(posedge clk)begin
52 // r_key[0] <= key;
53 // r_key[1] <= r_key[0];
54 // end
55
56 //上升沿
57 wire pedge_key;
58 assign pedge_key = (r_key == 2'b01);
59
60 //下降沿
61 wire nedge_key;
62 assign nedge_key = (r_key == 2'b10);
63
64 //定义计数器
65 reg [19:0] cnt;
66
67
68 reg [1:0] state;
69 always@(posedge clk or negedge reset_n)
70 if(!reset_n)begin
71 state <= 0;
72 key_r_flag <= 0;
73 key_p_flag <= 0;
74 cnt <= 0;
75 key_state <= 1;
76 end
77 else begin
78 case(state)
79 0:
80 begin
81 key_r_flag <= 0;
82 if(nedge_key)
83 state <= 1;
84 else
85 state <= 0;
86 end
87 1:
88 if((pedge_key) &&(cnt < 1000000-1))
89 state <= 0;
90 else if(cnt >= 1000000-1)begin
91 state <= 2;
92 cnt<=0;
93 key_p_flag <= 1;
94 key_state <= 0;
95 end
96 else begin
97 cnt <= cnt +1'b1;
98 state <= 1;
99 end
100 2:
101 begin
102 key_p_flag <= 0;
103 if(pedge_key)
104 state <= 3;
105 else
106 state <= 2;
107 end
108 3:
109 if((nedge_key) &&(cnt < 1000000-1))
110 state <= 2;
111 else if(cnt >= 1000000-1)begin
112 state <= 0;
113 cnt <= 0;
114 key_r_flag <= 1;
115 key_state <= 1;
116 end
117 else begin
118 cnt <= cnt +1'b1;
119 state <= 3;
120 end
121 default:;
122 endcase
123 end
124
125 endmodule
126 //仿真代码
127 `timescale 1ns / 1ps
128 module key_filter_tb();
129 reg clk;
130 reg reset_n;
131 reg key;
132 // wire key_p_flag;
133 // wire key_r_flag;
134 wire key_flag;
135 wire key_state;
136 key_filter key_filter_inst0(
137 clk,
138 reset_n,
139 key,
140 // key_p_flag,
141 // key_r_flag,
142 key_flag,
143 key_state
144 );
145
146 initial clk = 1;
147 always #10 clk =! clk;
148
149 initial begin
150 reset_n = 0;
151 key = 1;
152 #201;
153 reset_n =1;
154 #3000;
155
156 //模拟抖动
157 key = 0;
158 #20000;
159 key = 1;
160 #30000;
161 key = 0;
162 #20000;
163 key = 1;
164 #30000;
165 key = 0;
166 #50000000;
167
168 key = 1;
169 #30000;
170 key = 0;
171 #20000;
172 key = 1;
173 #30000;
174 key = 0;
175 #20000;
176 key = 1;
177 #50000000;
178 end
179 endmodule
2023-03-27 22:12:31