按键消抖模块的状态机实现

一. 设计思路

按键通常采用机械弹性开关,当机械触点闭合/断开时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定的接通,在断开时也不会马上断开。而是会在闭合/断开的瞬间伴随一连串的抖动,为避免这种现象带来的问题,需要进行按键消抖。
按键波形

使用状态机来描述按键按下时电路的状态。

按键未被按下时,电路处于IDLE状态;按键按下后,电路检测到按键被按下的状态,即key_in = 0,此时进入滤波状态,开始进行计数。计数过程中,如果检测到key_in = 1,则再次回到IDLE状态,直到再次检测到key_in = 0. 如果在滤波状态FILTER_DOWN中检测到key_in稳定在低电平,则持续进行计数,直到达到我们制定的时间标准,此时说明按键状态稳定,产生一个周期的高电平握手信号,状态机检测到握手信号,进入DOWN状态,输出key_out = 0. 按键松开时的状态转移也是类似的。

二. Verilog代码

本次设计使用三段式状态机,第一段使用时序电路实现状态切换,第二段使用组合电路描述状态转移,第三段使用时序电路描述电路输出,以避免常规的两段式状态机组合电路输出时可能带来的竞争与冒险(虽然这个按键消抖电路不可能产生冒险就是了)。

代码里的end_cnt_down和end_cnt_idle的值是随便设置的,为的是仿真时方便看波形。实际设计中我们应根据电路的时钟频率确定具体的计数数值。当我们的电路使用的时钟频率为50MHz时,由于通常电路产生的抖动为10ms左右,我们就把10ms作为我们计数的目标,即:

assign end_cnt_down = cnt_down == 19'd499_999

在按键消抖模块中,使用输入直接做状态转移的条件可能并非完全正确,实际可以在输入加两级寄存器来消除亚稳态的影响,然后用两级寄存器之间产生的脉冲来做状态转移的条件。但是在我们的设计中,输入信号key_in并不直接作为数据进行转移,因此我觉得直接使用这个信号也不会产生亚稳态,就没有进行修改。

下面来看具体代码。

`timescale 1ns / 1ps

module Debounce
 #(
   parameter IDLE        =  4'b0001,
   parameter FILTER_DOWN =  4'b0010,
   parameter DOWN        =  4'b0100,
   parameter FILTER_IDLE =  4'b1000
  )
  (
//-------------<输入信号>-----------------------------
    input      clk,
    input      rst,
    input      key_in,
//-------------<输出信号>-----------------------------
    output reg key_out,
//-------------<用于测试的临时输出信号>-----------------
    output     current_state,
    output     cnt_down
  );
  reg [4 : 0] current_state,
              next_state;
  reg [3 : 0] cnt_down,
              cnt_idle;
  
  wire end_cnt_down, end_cnt_idle;

  always@(posedge clk
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值