FPGA搭积木之按键消抖

目录

1.前言

2.原理

3.verilog代码

4.按键消抖模块IP核调用


1.前言

  由于机械按键的物理特性,按键被按下的过程中,存在一段时间的抖动,同 时在释放按键的过程中也存在抖动,这就导致在识别的时候可能检测为多次的按键按下,而通常检测到一次按键输入信号的状态为低电平,就可以确认按键被按下了,所以我们在使用按键时往往需要消抖,以确保按键被按下一次只检测到一次低电平。

我们理想中的按键是下面这样:

但是实际中的按键是这样的:

实际中的按键

2.原理

  一般开发板上的按键都是机械按键,所以在按下的时候,会产生回弹的时刻,称为机械的弹性开关。机械按键在按下和松开有一个抖动的过程,这个过程大概在10ms到15ms之间,具体取决于实际情况。这导致你按键按下但不一定真的按下了,按键弹起来了但不一定真的弹起来了。 如果不消除这个抖动,那么我们想要的效果将会得到一个很不确定的值。

机械按键

  为了能够得到准确的按键信号,我们需要在检测到按键抖动时,延迟20ms再进行采样,即可得到稳定的按键信号。

延迟采样消抖

3.verilog代码

设计思路如下:
(1)使用一个寄存器,将按键信号打一拍,将按键信号打一拍后的值与当前按键信号进行比较,来检测按键是否稳定。
(2)只要检测到按键不稳定,即还在抖动,就清零计数器,重新开始计数。
(3)只有当按键稳定后才启动计数器进行20ms的计数。
(4)如果按键信号未能稳定20ms时,key_flag <= 1'b0;认为按键值无效。
(5)只有当按键信号稳定20ms时,key_flag <= 1'b1;此按键值有效。

按键消抖过程

module key_debounce 
#(parameter DELAY_CNT = 'd1_000_000)//50M时钟时的20ms计数值
(    //防抖模块端口声明
      input clk      ,//50M
      input rst_n    ,
      input key      ,//定义按键输入
      
      output key_out//定义按键输出
);
reg         key_value ;//用于反馈key的值
reg        key_flag ;//按键标志
reg  [$clog2(DELAY_CNT) - 1:0]  delay_cnt ;//用于延时计数
reg                             key_reg  ;//用于记住上一刻key的值

assign key_out = key_flag & ~key_value;

always @ (posedge clk or negedge rst_n) begin
      if (!rst_n) begin //复位,key_reg置1,即未按下,延时计数清0
            key_reg <= 1'b1;
            delay_cnt <= 'd0;
      end
      else begin
            key_reg <= key; //key_reg记下此时key的值
            if (key_reg != key)  //若按键不稳定
                  delay_cnt <= DELAY_CNT;  //延时计数置满
            else if (key_reg == key) begin
                  if (delay_cnt > 0)
                        delay_cnt <= delay_cnt - 1'd1; 
                        //若20ms延时没结束,每次延时计数减1
                 else
                        delay_cnt <= delay_cnt;
            end
      end   
end                  
             
always @ (posedge clk or negedge rst_n) begin
      if (!rst_n) begin
            key_flag <= 1'b0;       //复位时按键标志置0
            key_value <= 1'b1;    //按键值置1
      end
      else begin
            if (delay_cnt == 'd1) begin 
                  //20ms延时结束,按键标志置1,反馈值记下此时key的值
                  key_flag <= 1'b1;
                  key_value <= key;
           end
            else begin //20ms延时未到按键标志置0
                  key_flag <= 1'b0;
                  key_value <= key_value;
             end
        end
 end

endmodule 
            

4.按键消抖模块IP核调用

  该模块可以当成IP核使用,根据自己的FPGA时钟频率,计算出20ms需要的计数值,调用模块时,在顶层修改参数即可使用。如100M时钟时的调用如下所示:

key_debounce #(.DELAY_CNT('d2_000_000))//100M时钟的计数值
u_key_debounce(
.clk    (clk    ), 
.rst_n  (rst_n  ),
.key    (key    ), 
.key_out(key_out) 
);

  将设计参数化,放入自己的代码库,供有需要时直接使用。相比于官方提供的封闭的IP核,自己设计的IP核虽然性能比不过,但是更灵活,方便进行个性化修改。FPGA其实就像搭积木一样,只要自己的代码库够丰富,设计只会越来越轻松! 此合集持续分享一些笔者自己设计的可复用硬件模块:FPGA搭积木

  • 25
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值