本文参考小梅哥的独立按键消抖视频

1,实验原理:

这里是黑金开发板教程中的图,可以看出,按键未按下时的状态是高电平,按下为低电平。下边是小梅哥画的图解。

因为是机械按键,按下时候有一个不稳定的抖动期,这个时间大概在20ms以内。

2,设计思路:利用状态机实现独立按键的消抖

  1. 未按下时空闲状态
  2. 按下抖动滤除状态
  3. 按下稳定状态
  4. 释放抖动滤除状态

在第一个状态时,等待按键按下,一旦有按键按下(按键下降沿到来),便跳转到第二个状态,抖动滤除状态。在第二个状态,有检测到高电平(上升沿),就会被认为是毛刺,进而返回第一个状态继续等待下降沿。等毛刺被滤除后(计数满)则进入按下稳定状态。在按下稳定状态,等待释放(上升沿),同按键按下的状态,再次滤除释放按键的抖动。等抖动滤除后,恢复到第一个状态。

配个图吧。聊胜于无。

这段话可能有些啰嗦,结合代码看会比较清楚。当然这段话并没有牵扯到计数器的关闭与开启,会在后面代码注释中详细说明。

3,仿真图

注意看state的第一个状态,是0001,这个是第一个下降沿等待状态。后面才开始有了状态的跳变。每一个计数满就意味着一次滤波的完成。第一次代表按下抖动释放,第二次代表松开抖动释放。

仿真图很重要!!!可以帮助理解

RTL图可以自己去看,对应代码还是很清楚的。

4,代码

module filter(clk,rst_n,key_in,key_flag,key_state);
//端口声明
input clk;        //时钟50MHz
input rst_n;      //复位信号
input key_in;     //按键输入output key_state;    //按键状态,高电平为未按下,低电平为按下状态
output key_flag;       /*完成滤波信号(消抖后的按键),这里有很有趣的一件事,我们在生活中发现,有些按键是按下时产生效果的,有些是按下松开后起作用的,在这段代码中,依据这个信号来产生*///定义
parameter   IDLE    = 4'b0001,FILTER0 = 4'b0010,DOWN    = 4'b0100,FILTER1 = 4'b1000;
//内部信号声明
reg [3:0] state;
reg key_flag;
reg key_state;
reg cnt_full;
reg [19:0] cnt;
reg en_counter;
//边沿检测模块,将输入信号寄存一个节拍,分别按键上升沿和下降沿的产生
reg key_tmp0,key_tmp1;
always@(posedge clk or negedge rst_n)
beginif(!rst_n)beginkey_tmp0 <= 1'b1;key_tmp1 <= 1'b1;endelse beginkey_tmp0 <= key_in;key_tmp1 <= key_tmp0;end
end
wire pedge,nedge;
assign nedge = (!key_tmp0) &  key_tmp1;        //下降沿
assign pedge = key_tmp0  & (!key_tmp1);        //上升沿//状态机模块
always@(posedge clk or negedge rst_n)
beginif(!rst_n)beginstate <= IDLE;en_counter <= 1'b0;key_state <= 1'b1;key_flag <= 1'b0;endelse begincase(state)IDLE:beginkey_flag <= 1'b0;key_state <= 1'b1;en_counter <= 1'b0;if(nedge)        //检测到下降沿,进入下一个状态同时打开计数器beginstate <= FILTER0;en_counter <= 1'b1;endelse state <= state;    endFILTER0:if(cnt_full)        //计数满,说明达到稳定状态,关闭计数器beginstate <= DOWN;en_counter <= 1'b0;key_flag <= 1'b1;key_state <= 1'b0;endelse if(pedge)        //检测到上升沿(毛刺),跳回idle状态同时关闭计数器beginen_counter <= 1'b0;state <= IDLE;endelse state <= state;DOWN:beginkey_flag <= 1'b0;if(pedge)beginstate <= FILTER1;en_counter <= 1'b1;endelse state <= DOWN;endFILTER1:if(cnt_full)beginstate <= IDLE;//key_flag <= 1'b1;key_state <= 1'b0;endelse if(nedge)beginen_counter <= 1'b0;state <= DOWN;                           end else state <= state;default:state <= IDLE;endcaseend
end//20ms计数器
//这里有一个计数使能信号,只有当计数使能为高电平的时候,计数器才会计数,数数到999_999计数满时间到
always@(posedge clk or negedge rst_n)
beginif(!rst_n)cnt <= 20'd0;else if(en_counter)cnt <= cnt + 1'b1;else cnt <= 20'd0;
end
//计数满信号
always@(posedge clk or negedge rst_n)
beginif(!rst_n)cnt_full <= 1'b0;else if(cnt == 20'd999_999)cnt_full <= 1'b1;else cnt_full <= 1'b0;
endendmodule

5,仿真代码

代码就直接贴上来了,理解应该没什么问题,这里的毛刺产生笔者随便模拟产生,没有用视频中讲的随机数产生函数。仿真时间比较长,不要着急。

module tb_filter;// Inputsreg clk;reg rst_n;reg key_in;// Outputswire key_flag;wire key_state;// Instantiate the Unit Under Test (UUT)filter uut (.clk(clk), .rst_n(rst_n), .key_in(key_in), .key_flag(key_flag), .key_state(key_state));
always #10 clk = ~clk;initial begin// Initialize Inputsclk = 1'b0;rst_n = 1'b0;key_in = 1'b1;// Wait 100 ns for global reset to finish#200;rst_n = 1'b1;#(20*10);key_in = 1'b0;#1000;key_in = 1'b1;#140;key_in = 1'b0;#2000;key_in = 1'b1;#3000;key_in = 1'b0;#100;key_in = 1'b1;#20;key_in = 1'b0;#(20*10000000);key_in = 1'b1;#1000;key_in = 1'b0;#140;key_in = 1'b1;#2000;key_in = 1'b0;#3000;key_in = 1'b1;#100;key_in = 1'b0;#20;key_in = 1'b1;// Add stimulus hereendendmodule

6,小总结

这里的按键消抖其实更多的是用来理解运用状态机的,具体个人感觉并不实用。要是多个按键就必须每一个按键分别调用模块,资源多,小点的还好,一旦太多,实例化就很麻烦了。所以真正可以用的代码我将在下一篇博客里分享。其次就是这里key_flag信号很有意思。仿真图很重要!!!可以帮助理解!仿真图很重要!!!可以帮助理解!仿真图很重要!!!可以帮助理解!

Verilog实现独立按键消抖(状态机)相关推荐

  1. FPGA学习-Verilog实现独立按键消抖

    文章目录 前言 一.独立按键消抖原理 二.按键消抖程序实现(Verilog) 1.按键触发判断 2.计数器模块实现 3.按键状态更新 4.按键控制led亮灭 三.仿真测试文件编写 四.编译结果 前言 ...

  2. verilog基础-状态机之FPGA独立按键消抖设计与验证(熟练testbench的写法)

    独立按键消抖设计与验证 本实验主要是为了锻炼状态机的思维模式以及熟练掌握TB的写法 本节主要收获了:define的用法,另外就是,顶层的input在TB中是reg的真正含义,其实就是把激励当做寄存器来 ...

  3. Verilog功能模块 —— 按键消抖

    一. 什么是按键消抖 按键消抖_百度百科 (baidu.com) 按键消抖通常的按键所用开关为机械弹性开关,当机械触点断开.闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断 ...

  4. 【Verilog HDL 训练】第 09 天(按键消抖)

    5月7日 按键防抖 1. 用verilog实现按键抖动消除电路,抖动小于15ms,输入时钟12MHz. 在编写Verilog代码之前,先分析下一些前提问题,首先是几个按键(1个,多个),我们以1个和三 ...

  5. 基于verilog按键消抖设计

    关于键盘的基础知识,我就以下面的一点资料带过,因为这个实在是再基础不过的东西了.然后我引两篇我自己的博文,都是关于按键消抖的,代码也正是同目录下project里的.这两篇博文都是ednchina的博客 ...

  6. 三行代码按键消抖 独立按键 矩阵按键 长按 短按 双击

    九层妖塔 起于垒土 直接跳转到三行代码 三行代码按键消抖 独立按键 矩阵按键 长按 短按 双击 一.基本理论 0.按键的常见名词:  ①按键抖动  ②按键稳定闭合时间 1.按键的扫描: 2.按键的消抖 ...

  7. Verilog中按键消抖检测的实现

    Verilog按键消抖是FPGA学习时的一个入门教程,为避免眼高手低,还是再次分析与记录一下.此处着重介绍按键消抖的基本原理,对按键消抖与检测的关键技术进行分析,并进行功能仿真. 一.按键消抖基本原理 ...

  8. c语言实现按键的抖动与消除,【Verilog HDL 训练】第 09 天(按键消抖)

    5月7日 按键防抖 1. 用verilog实现按键抖动消除电路,抖动小于15ms,输入时钟12MHz. 在编写Verilog代码之前,先分析下一些前提问题,首先是几个按键(1个,多个),我们以1个和三 ...

  9. 小梅哥三段式状态机按键消抖改写

    小梅哥三段式状态机按键消抖改写 小梅哥资料中按键消抖部分是用一段式.二段式状态机写的.我用三段式状态机改写了一下,仿真和板载测试通过. 代码记录如下: module key_filter1(input ...

最新文章

  1. 2018机器阅读理解技术竞赛,奇点机智获第一名
  2. 解读:MR多路径输入
  3. 组合数 com(n,r)
  4. [BEC][hujiang] Lesson02 Unit1:Working life ---Reading
  5. 苹果开发者修改团队名称_鼓励您的团队对项目进行更改的5步计划
  6. apache 启用 gzip压缩
  7. mysql elt interval_mysql 区间分组 interval,elt 的运用
  8. 语音机器人究竟能做些什么?
  9. 通读5G 半导体产业有新商机
  10. HbuilderX启动 微信开发者工具
  11. 模拟狗狗的“魔鬼步伐”,比更真还更真
  12. 畜牧业适宜性评价算法
  13. JSP中session的简单应用——以购物车为例
  14. might和could的区别用法_地道的英语口语:Might、 may、could用法区分
  15. 电子电路硬件学习目标
  16. IPv6- TC实现IPv6流量限速测试详情
  17. 简单使用OnlyOffice
  18. 矢量科研数据质量检查方法
  19. 计算机可以玩电子游戏吗?
  20. linux架设DNF服务器,使用linux的dnf命令新一代的RPM软件包管理器

热门文章

  1. zookeeper 异常 :stat is not executed because it is not in the whitelist. Connection closed b
  2. android发布新版忘记keystore(jks)密码终极解决方案
  3. Spring MVC异常处理详解 ExceptionHandler good
  4. 我应该如何验证电子邮件地址?
  5. 如何取消选中单选按钮?
  6. 枚举的字符串表示形式
  7. HTML+CSS详解
  8. BootStrap的介绍与案例使用
  9. 系统对接方案_一个呼叫中心系统组建的案例
  10. 问答 | 为什么car-like robot转向机构需要使用等腰梯形?