基于状态机的按键消抖

 按键产生的抖动原理

空闲态 (IDLE)》:等待按键按下(等待下降沿),-旦出现下降沿,就开始 20ms 的计时
按下消抖状态:20ms 的计时状态,在这个状态里,一边计时,一边检测有没有出现上升沿,
如果有出现上升沿,回到空闲态;如果计时满 20ms,没有出现上升沿,发出按键按下的通
知信号。
等待释放:等待按键释放(等待上升沿),一旦出现上升沿,就开始 20ms 的计时~
释放消抖状态:20ms 的计时状态,在这个状态里,一边计时,一边检测按键有没有出现下
降沿,如果出现下降沿,则回到等待释放状态,如果计时满 20ms 没有出现下降沿,发出
按键释放的通知信号。

利用状态机消抖的状态转移图

按键消抖:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/06/29 17:14:51
// Design Name: czy
// Module Name: key_filter
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module key_filter(
Clk,
Reset_n,
key,
key_flag,
key_state
   );
   
   input Clk;
   input Reset_n;
   input key;
   output key_flag;
   output reg key_state;
   
   
 reg press_flag;
 reg release_flag;
   //定义状态机 4个状态 2位
   localparam IDLE=0;
   localparam Pr_f=1;
   localparam WAIT=2;
   localparam Re_f=3;
  //key_flag
  assign key_flag = press_flag|release_flag;
   
   reg [1:0] state; 
   //定义上升沿 、下降沿
   wire key_pedge;  
   wire key_nedge;
   //检验上升沿or下降沿
   reg [1:0] key_edge;//移位寄存器
   reg [19:0] cnt;
   always@(posedge Clk)
   key_edge <= {key_edge[0],key};

   assign key_pedge=key_edge==2'b01;
  
   assign key_nedge=key_edge==2'b10;
   //定义计数器 20 000 000(20ms)/20(20ns时钟周期)=1 000 000周期  20'b 1111 0100 0010 0100 0000
   
   

   
   always@(posedge Clk or negedge Reset_n )
      if(!Reset_n)begin
           state <= IDLE;
           release_flag <= 0;
           press_flag <= 0; 
           cnt <= 1'b0;
           key_state<=1;
           end
       else  begin
   case(state)
   IDLE:
   begin
    release_flag<=0;
        if(key_nedge)
            state <= Pr_f;
        else 
            state <= IDLE;
    end
    Pr_f:
    begin
        if((key_pedge)&&(cnt<1_000_000-1))
            state <= IDLE;
        else if(cnt>=1_000_000-1)begin
           
            press_flag<=1;
            key_state<=0;
            state <= WAIT;
            cnt<=0;
        end
        else begin 
            cnt<=cnt+1'b1;
            state <= Pr_f;
              end
     end         
    WAIT:begin
         press_flag<=0;
        if(key_pedge)
            state <= Re_f;
        else 
            state <= WAIT;
        end        
    Re_f:
    begin
              if((key_nedge)&&(cnt<1_000_000-1))
                   state <= WAIT;
                else if(cnt>1_000_000-1)begin
                    state <= IDLE;
                    release_flag<=1;
                    key_state<=1;
                    cnt<=0;
                    end
                    else begin
                    cnt<=cnt+1'b1;
                    state <= Re_f;
                    end
   end         
   endcase
end
endmodule

测试文件:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2023/07/06 16:45:46
// Design Name: czy
// Module Name: key_filter_tb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module key_filter_tb();
    
reg Clk;
reg Reset_n;
reg key;

wire key_flag;
wire key_state;
    
key_filter key_filter(
Clk,
Reset_n,
key,
key_flag,
key_state
   );
      
//产生时钟

initial Clk=1;
always#10 Clk=~Clk;

initial begin
Reset_n = 0;
key=1;//按键正常情况高电平
#201;//避开时钟的上升沿
Reset_n = 1;//释放复位
#30000;
key = 0;
#20000;
key = 1;
#30000;
key = 0;
#20000;
key = 1;
#30000;
key=0;
#50_000_000;
key = 1;
#30000;
key = 0;
#20000;
key = 1;
#30000;
key=0;
#20000;
key = 1;
#50_000_000;
$stop;

end


endmodule

仿真波形

放大看...

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值