小梅哥课程学习——基于状态机的按键消抖(A)

发布时间 2023-03-27 22:23:45作者: 无情的造轮子
  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:19:22