基于FPGA的按键消抖

文章目录

  • 基于FPGA的按键消抖
  • 前言
  • 一、按键状态机
  • 二、按键消抖模块
    • 1.模块框图
    • 2.模块代码
    • 2.模块仿真代码
  • 三、总结(含文件)

前言

按键消抖属于一个经典问题了,放一张图

大概就是根据经验,如果按键在20ms内没有变化则判定为按下。


一、按键状态机

本次是参考小梅哥的文档使用状态机写的按键消抖,状态转移图如下

二、按键消抖模块

1.模块框图


其中 :key_pose是在按键按下时刻产生一个时钟周期的高电平。
key_nege是在按键抬起时刻产生一个时钟周期的高电平。
key_out 是在按键消抖后的实际状态。

2.模块代码

开发平台:Vivado 2018.3
仿真平台:Modusim SE-64 10.5
开发平台:ALINX AX7Z020

代码如下:状态机的是按照野火的新式两段式状态机格式编写的

`timescale 1ns / 1nsmodule key
#(parameter   CNT_20MS_MAX = 1_000_000
)
(input       wire        sys_clk     ,input       wire        sys_rst_n   ,input       wire        key_in      ,output      reg         key_pose    ,   output      reg         key_nege    ,   output      reg         key_out
);reg     key_in_reg1;
reg     key_in_reg2;wire     key_in_pose;
wire     key_in_nege;reg     key_out_reg;reg                 cnt_en;
reg                 cnt_20ms_full;
reg     [19:0]      cnt_20ms;reg     [3:0]       state;
localparam          IDLE        = 4'b0001,DOWN_FILTER = 4'b0010,DOWN        = 4'b0100,UP_FILTER   = 4'b1000;
//将按键信号同步至系统时钟地域,同时打拍缓解亚稳态
always@(posedge sys_clk or  negedge  sys_rst_n) if(sys_rst_n == 1'b0)key_in_reg1 <= 1'b1;elsekey_in_reg1 <= key_in;always@(posedge sys_clk or  negedge  sys_rst_n) if(sys_rst_n == 1'b0)key_in_reg2 <= 1'b1;elsekey_in_reg2 <= key_in_reg1;
//捕获按键按下的上升沿,下降沿
assign  key_in_nege = (~key_in_reg1)&&(key_in_reg2);
assign  key_in_pose = (key_in_reg1)&&(~key_in_reg2);always@(posedge sys_clk or  negedge  sys_rst_n) if(sys_rst_n == 1'b0)cnt_20ms <= 20'd0;else    if((cnt_20ms == CNT_20MS_MAX - 1'b1) && (cnt_en == 1'b1))cnt_20ms <= cnt_20ms;else    if((cnt_20ms != CNT_20MS_MAX - 1'b1) && (cnt_en == 1'b1))cnt_20ms <= cnt_20ms + 1'b1;elsecnt_20ms <= 20'd0;    //按键处于状态2、4时开启20ms定时器
always@(posedge sys_clk or  negedge  sys_rst_n) if(sys_rst_n == 1'b0)cnt_en <= 1'b0;else    if((state == DOWN_FILTER) || (state == UP_FILTER))cnt_en <= 1'b1;elsecnt_en <= 1'b0;//按键记满将标志置1
always@(posedge sys_clk or  negedge  sys_rst_n) if(sys_rst_n == 1'b0)cnt_20ms_full <= 1'b0;else    if(cnt_20ms == CNT_20MS_MAX - 2'd2)    cnt_20ms_full <= 1'b1;elsecnt_20ms_full <= 1'b0;always@(posedge sys_clk or  negedge  sys_rst_n) if(sys_rst_n == 1'b0)state <= IDLE;else    case(state)IDLE        :   if(key_in_nege == 1'b1)state <= DOWN_FILTER;elsestate <= IDLE;    DOWN_FILTER :   if(cnt_20ms_full == 1'b1)state <= DOWN;else  if(key_in_pose == 1'b1)state <= IDLE;   elsestate <= DOWN_FILTER;      DOWN        :   if(key_in_pose == 1'b1)state <= UP_FILTER;elsestate <= DOWN;  UP_FILTER   :   if(cnt_20ms_full == 1'b1)  state <= IDLE;          else    if(key_in_nege == 1'b1)  state <= DOWN;     else    state <= UP_FILTER;   default     :       state <= IDLE;                   endcase                    always@(posedge sys_clk or  negedge  sys_rst_n) if(sys_rst_n == 1'b0)key_out <= 1'b1;else    if(state == DOWN)key_out <= 1'b0;else    if(state == IDLE)key_out <= 1'b1;    elsekey_out <= key_out;always@(posedge sys_clk or  negedge  sys_rst_n) if(sys_rst_n == 1'b0)key_out_reg <= 1'b1;elsekey_out_reg <= key_out;    always@(posedge sys_clk or  negedge  sys_rst_n) if(sys_rst_n == 1'b0)key_pose <= 1'b0;else    key_pose <= ~key_out_reg & key_out;always@(posedge sys_clk or  negedge  sys_rst_n) if(sys_rst_n == 1'b0)key_nege <= 1'b0;else    key_nege <= key_out_reg & ~key_out;endmodule

2.模块仿真代码

参考了野火的代码

`timescale 1ns / 1nsmodule tb_key();parameter   CNT_1MS = 20'd19    , CNT_11MS = 21'd69   , CNT_41MS = 22'd149  , CNT_51MS = 22'd199  , CNT_60MS = 22'd249  ;reg     sys_clk;
reg     sys_rst_n;
reg     key_in;wire    key_pose;
wire    key_nege;
wire    key_out;  key
#(.CNT_20MS_MAX(20'd25)
)
key_inst
(.sys_clk    (sys_clk  ) ,.sys_rst_n  (sys_rst_n) ,.key_in     (key_in   ) ,.key_pose   (key_pose ) ,  .key_nege   (key_nege ) ,  .key_out    (key_out  ) );reg     [21:0]    tb_cnt;initial beginsys_clk = 1'b1;sys_rst_n <= 1'b0;key_in <= 1'b0;#20sys_rst_n <= 1'b1;      endalways #10 sys_clk =~ sys_clk;always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) tb_cnt <= 22'b0; else if(tb_cnt == CNT_60MS) tb_cnt <= 22'b0; else tb_cnt <= tb_cnt + 1'b1;always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1'b0) key_in <= 1'b1; else if((tb_cnt >= CNT_1MS && tb_cnt <= CNT_11MS) || (tb_cnt >= CNT_41MS && tb_cnt <= CNT_51MS)) key_in <= {$random} % 2; else if(tb_cnt >= CNT_11MS && tb_cnt <= CNT_41MS) key_in <= 1'b0; else key_in <= 1'b1;endmodule

三、总结(含文件)

工程文件点这里~~
提取码:bemh

黑金的板子到了,真滴帅,赶紧点个灯试试手。
打算基于黑金的板子,将以前做的仿真都重构下下。
但是最近事情有点多,进度缓慢,呜呜呜 >o<

此工程可以应用于实际项目,如果认为文章写的不错请点赞支持。
FPGA初学者,欢迎交流鸭。

基于FPGA的按键消抖相关推荐

  1. 【按键消抖】基于FPGA的按键消抖模块开发

    1.软件版本 QUARTUSII8.1 Modelsim6.5d 2.系统源码 module tops(i_clk, //100Mi_rst, //系统复位功能,高电平复位,如果不使用这个角,那么一直 ...

  2. 【 FPGA 】按键消抖与LED灯流动小实验

    记录一个小实验吧,实验的目的是仅仅是塞塞牙缝而已,没其他意思,很简单. 功能:拨码开关控制led灯工作与否,拨码开关为on,led灯工作,否则不工作:导航按键up和down,也就是独立按键而已,控制l ...

  3. FPGA编程按键消抖

    FPGA按键消抖 编写思路 1.按键消抖的基本原理 2.代码原理 3.代码部分 4.仿真代码编写 5.仿真 6.总结 一.按键消抖的基本原理 按键消抖,按下,松开存在毛刺,主要为了消除毛刺.通过稳定后 ...

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

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

  5. FPGA实现按键消抖及短时间按键和长时间按键不同动作

    module key_test2(clk, //时钟信号:50Mhzrst, //按键复位key, //用户按键led //LED0~LED2);//端口定义input clk;input rst;i ...

  6. [FPGA入门笔记](十):按键消抖实验

    简介 今天购买了AXLINX AX7020的开发板,从今天开始每一个例程都要做文档记录,为自己加油. 本实验,基于ALINX AX7020开发板,芯片为xc7z020clg400-2.开发板输入时钟为 ...

  7. FPGA VerilogHDL语言 数字钟 按键消抖

    1.描述 一个简单的基于FPGA的数字钟,语言用的是VerilogHDL,可以实现以下功能: 1. 数码管显示0-59(秒表) 2. 数码管显示:时-分-秒 3. 数码管显示时分秒并且可以设置时间(小 ...

  8. 基于verilog按键消抖设计

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

  9. FPGA学习笔记---利用连续赋值语句延时功能实现按键消抖

    最近一直在学习FPGA,今天在学习延时语句时,发现了连续赋值的一个特点.在连续赋值语句中添加延时时,任何小于延迟值的输入变化都会被滤除而不会体现在输出上.比如  #10 B = A; 当A的变化小于1 ...

  10. stm32 工业按键检测_STM32单片机按键消抖和FPGA按键消抖大全

    写在前面: 物联网STM32入门 - 直播课程 - 创客学院​www.makeru.com.cn 按键去抖:由上图可以看出理想波形与实际波形之间是有区别的,实际波形在按下和释放的瞬间都有抖动的现象,抖 ...

最新文章

  1. JZOJ 5473. 【NOIP2017提高组正式赛】小凯的疑惑
  2. QT Media Error: DirectShowPlayerService::doRender: Unresolved error code 0x80040266
  3. redis安装与基本配置
  4. Pro*C/C++简单介绍
  5. jquery实现app开发闹钟功能_一款让你真正摆脱懒觉的“闹钟APP软件”
  6. cmd 批处理文件(.bat)文件的编写
  7. 如何查看电脑ip地址
  8. 机器学习sklearn-线性回归
  9. python中tmp什么意思_python中tmp
  10. 【异常】git提示Ask a project Owner or Maintainer to create a default branch
  11. php访问微信云数据库,第三方服务器php获取微信小程序云开发access_token和云数据库...
  12. 小程序设置整个页面的背景颜色
  13. Kafka offset 偏移量详解
  14. 图像处理基础和OpenCV常用接口
  15. 【小5聊】本地IP地址设置为任意域名访问
  16. 【机器学习算法面试题】四.深度神经网络中激活函数有哪些?
  17. 交换内存SWAP使用率90%
  18. mpv播放器 —— 一个免费的、开源的、跨平台的媒体播放器
  19. 使用keytool和openssl生成RSA公钥私钥和证书,
  20. 受控电源(SOC PWM调压SVB)计算工具CVC使用说明

热门文章

  1. SOUI使用总结知识汇总.
  2. 17SWFObject使用
  3. JDK10 新特性详解
  4. docker介绍与应用
  5. 资讯美国悬赏1000万美元追捕勒索黑客、能源行业成为网络钓鱼攻击“重灾区”|11月8日全球网络安全热点
  6. matlab有限元分析程序,matlab有限元分析与应用(书及源程序)
  7. linux git difftool,git difftool 详解
  8. 混合储能系统能量管理simulink仿真模型。 蓄电池和超级电容构成的混合储能系统能量管理控制策略
  9. Max Script|修改器篇
  10. obj 格式3D模型转 gltf 格式