FPGA搭积木之按键消抖

news/2024/7/5 6:24:14

目录

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搭积木


http://lihuaxi.xjx100.cn/news/2165407.html

相关文章

力扣刷题---返回word中所有不重复的单词

当需要从一个数据集合中去除重复元素时&#xff0c;set是一个很好的选择。由于其不允许存储重复的元素&#xff0c;因此可以很容易地实现去重功能。这在处理原始数据或进行数据分析时特别有用。 题目&#xff1a; 给定一个字符串数组 words&#xff0c;请返回一个由 words 中所…

Mac OS制作Ubuntu的U盘启动盘

1. 下载Ubuntu的iso镜像文件 地址为&#xff1a;https://ubuntu.com/download/desktop 2. 把iso镜像文件转换成dmg文件 cd Downloads/ hdiutil convert -format UDRW -o ubuntu.iso ubuntu-18.04.2-desktop-amd64.iso-format为生成文件的权限&#xff1b;UDRW :表示转换成有…

【运维】笔记本电脑风扇清洁

笔记本电脑是我们不可或缺的工具&#xff0c;无论是工作、学习还是娱乐。然而&#xff0c;随着时间的推移&#xff0c;笔记本电脑的性能可能会因为各种原因受到影响&#xff0c;尤其是散热问题。过热不仅会降低性能&#xff0c;还可能缩短硬件的寿命。最近&#xff0c;在使用我…

深入浅出递归算法

文章目录 递归思想递归的题目1.汉诺塔问题问题分析代码展示 2.合并两个有序链表问题分析代码展示 3.反转链表问题分析代码展示 4.两两交换 链表中的节点问题分析代码展示 总结 递归思想 递归就是将一个很大的问题拆分成子问题&#xff0c;然后再将子问题继续拆分&#xff0c;拆…

HarmonyOS之ArkUI布局设计常见细节

这里写目录标题 1. Button设置带有渐变色的背景图片无效1.1 问题分析1.2 成功案例 2. 路由跳转失败2.1 问题分析 1. Button设置带有渐变色的背景图片无效 1.1 问题分析 说明&#xff1a;设置颜色渐变需先设置backgroundColor为透明色。 Button($r(app.string.login), { type…

FunSound: 基于FunASR-onnx 的高精度离线转写

​ 基于funasr的高精度离线语音转写网页 www.funsound.cn 精度和速度表现不错&#xff0c;提供给大家免费测试 ​

BeanDefinition作用

BeanDefinition接口 BeanDefinition 描述一个 Bean 实例&#xff0c;这个实例有哪些属性值、构造函数以及一些其他信息&#xff0c;就是描述Bean实例的信息。 BeanDefinition是一个接口&#xff0c;允许BeanFactoryPostProcessor 内省和修改属性值和其他 Bean 元数据。 点击了…

React开发必须掌握这些es6语法-03

箭头函数 其实就是java的lamda编程&#xff0c;它的特点是单向无环流&#xff0c;没有变量&#xff0c;源数据状态不能被改变。 基本语法 ()> {} //表示一个空函数&#xff0c;和function(){}功能一样&#xff0c;如果只有一行语句则&#xff0c;{}可省略 lef fn arg &g…