Lattice Diamond中VerilogHDL按键延时消抖

2023-10-22 15:20

本文主要是介绍Lattice Diamond中VerilogHDL按键延时消抖,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在之前的实验中我们学习了如何用按键作为FPGA的输入控制,在本实验中将学习如何进行按键消抖,用按键完成更多的功能。 

硬件说明


按键是一种常用的电子开关,电子设计中不可缺少的输入设备。当按下时使开关导通,松开时则开关断开,内部结构是靠金属弹片来实现通断。 

按键抖动的原理 
抖动原理

  1. 抖动的产生 :通常的按键所用的开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。
  2. 消除抖动的措施:一般我们采用软件方法消抖。即检测到按键按下动作之后进行10ms~20ms左右的延时,当前沿的抖动消失之后再一次检测按键的状态。如果仍然是按下的电平状态,则认为这是一次真正的按键按下;同样检测到按键释放,也要做10ms~20ms延时,检测到后沿抖动消失后认为是一个完整的按键弹起过程。
  3. 消抖的好处:执行按键消抖有两个好处,
    1. 消除误触发:我们想通过按键来翻转信号(例如按下一次led亮,在按一次led灭),如果没有进行消抖,则会产生很多误触发造成不必要的翻转。
    2. 记录按键次数:执行按键消抖可以让我们记录按键动作的次数,在很多应用里这非常有用。


在点亮LED实验中我们知道了小脚丫板子上按键的设计,当按键未被按下时,连接到FPGA管脚认为是高电平;当按键被按下时,连接到FPGA管脚认为是低电平。


要消除按键的抖动,我们需要去扫描按键,也就是不断的去采集按键的状态。软件消抖时我们一般只考虑按键按下时的抖动,而放弃对释放时抖动的消除。用系统时钟(频率较高)去采集按键状态,当检测到按下时用计数器延时20ms,再去检测按键状态,如果这时仍为按下状态,确认是一次按下动作,否侧的话认为无按键按下。如何检测按键状态变化就需要用到脉冲边沿检测的方法。


脉冲边沿检测


检测按键按下时要用到脉冲边沿检测的方法,捕捉信号的突变、捕捉时钟的上升下降沿等经常会用到这种方法。简单地说就是用一个频率更高的时钟去触发要检测的信号,用两个寄存器去储存相邻两个时钟采集到的值,然后进行异或运算,如果不为零,代表发生了上升沿或者下降沿。


在按键消抖的过程中,同样运用了脉冲边沿检测。用两个寄存器储存相邻时钟采集的值(例如data_pre,data),然后将data取反与前一个值相与(state=data_pre&(~data)),如果为1,则判断有下降沿既按键按下由高到低;否则无变化。 
将一个信号由连续时钟采集,相邻两个钟触发的值存入两个寄存器。理解verilog实现这个过程要充分了解其中的非阻塞赋值。


Verilog代码


本实验主要通过按键来控制led的翻转,当按下一次led变亮,再按下一次led变暗。首先我们做个试验,对按键不做处理通过按键来控制led翻转。

// ********************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// ********************************************************************
// File name    : top.v
// Module name  : top
// Author       : STEP
// Description  : control led through the button
// Web          : www.stepfpga.com
// 
// --------------------------------------------------------------------
// Code Revision History : 
// --------------------------------------------------------------------
// Version: |Mod. Date:   |Changes Made:
// V1.0     |2017/03/02   |Initial ver
// --------------------------------------------------------------------
// Module Function:按键控制led翻转,未做消抖module top(key,          //按键输入rst,          //复位输入led           //led输出);input key,rst;output reg led;always @(key or rst)if (!rst)             //复位时led熄灭led = 1;else if(key == 0)     led = ~led;   //按键按下时led翻转elseled = led;
endmodule


未经过消抖的程序下载到小脚丫上会发现按键有时不能够控制led翻转,这是因为按键的抖动造成了led状态变化不可控,所以我们必须将抖动消除。下面是一种延时去抖的程序

// ********************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// ********************************************************************
// File name    : debounce.v
// Module name  : debounce
// Author       : STEP
// Description  : 
// Web          : www.stepfpga.com
// 
// --------------------------------------------------------------------
// Code Revision History : 
// --------------------------------------------------------------------
// Version: |Mod. Date:   |Changes Made:
// V1.0     |2017/03/02   |Initial ver
// --------------------------------------------------------------------
// Module Function:按键消抖module debounce (clk,rst,key,key_pulse);parameter       N  =  1;                      //要消除的按键的数量input             clk;input             rst;input 	[N-1:0]   key;                        //输入的按键					output  [N-1:0]   key_pulse;                  //按键动作产生的脉冲	reg     [N-1:0]   key_rst_pre;                //定义一个寄存器型变量存储上一个触发时的按键值reg     [N-1:0]   key_rst;                    //定义一个寄存器变量储存储当前时刻触发的按键值wire    [N-1:0]   key_edge;                   //检测到按键由高到低变化是产生一个高脉冲//利用非阻塞赋值特点,将两个时钟触发时按键状态存储在两个寄存器变量中always @(posedge clk  or  negedge rst)beginif (!rst) beginkey_rst <= {N{1'b1}};                //初始化时给key_rst赋值全为1,{}中表示N个1key_rst_pre <= {N{1'b1}};endelse beginkey_rst <= key;                     //第一个时钟上升沿触发之后key的值赋给key_rst,同时key_rst的值赋给key_rst_prekey_rst_pre <= key_rst;             //非阻塞赋值。相当于经过两个时钟触发,key_rst存储的是当前时刻key的值,key_rst_pre存储的是前一个时钟的key的值end    endassign  key_edge = key_rst_pre & (~key_rst);//脉冲边沿检测。当key检测到下降沿时,key_edge产生一个时钟周期的高电平reg	[17:0]	  cnt;                       //产生延时所用的计数器,系统时钟12MHz,要延时20ms左右时间,至少需要18位计数器     //产生20ms延时,当检测到key_edge有效是计数器清零开始计数always @(posedge clk or negedge rst)beginif(!rst)cnt <= 18'h0;else if(key_edge)cnt <= 18'h0;elsecnt <= cnt + 1'h1;end  reg     [N-1:0]   key_sec_pre;                //延时后检测电平寄存器变量reg     [N-1:0]   key_sec;                    //延时后检测key,如果按键状态变低产生一个时钟的高脉冲。如果按键状态是高的话说明按键无效always @(posedge clk  or  negedge rst)beginif (!rst) key_sec <= {N{1'b1}};                else if (cnt==18'h3ffff)key_sec <= key;  endalways @(posedge clk  or  negedge rst)beginif (!rst)key_sec_pre <= {N{1'b1}};else                   key_sec_pre <= key_sec;             end      assign  key_pulse = key_sec_pre & (~key_sec);     endmodule


以上就是一个N位按键的消抖程序,如果有按键按下会输出一个时钟周期的高脉冲。下面我们可以试试用这个按键消抖的输出来触发LED的显示,既按键一次LED翻转。你也可以不加按键消抖试试用按键来控制LED(按一次变亮,再按一次灭掉)。


下面的程序是例化调用debounce模块来控制LED 

// ********************************************************************
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// ********************************************************************
// File name    : top.v
// Module name  : top
// Author       : STEP
// Description  : 
// Web          : www.stepfpga.com
// 
// --------------------------------------------------------------------
// Code Revision History : 
// --------------------------------------------------------------------
// Version: |Mod. Date:   |Changes Made:
// V1.0     |2017/03/02   |Initial ver
// --------------------------------------------------------------------
// Module Function:进过按键消抖后控制led显示翻转module top (clk,rst,key,led);input             clk;input             rst;input 	          key;                      				output   reg      led;        wire              key_pulse;//当按键按下时产生一个高脉冲,翻转一次ledalways @(posedge clk  or  negedge rst)beginif (!rst) led <= 1'b1;else if (key_pulse)led <= ~led;elseled <= led;end    //例化消抖module,这里没有传递参数N,采用了默认的N=1     debounce  u1 (                               .clk (clk),.rst (rst),.key (key),.key_pulse (key_pulse));endmodule


引脚分配


设置好复位键可消抖的按键,编译完成后下载,通过按键就可以翻转LED。你也可以定义多个按键控制多个LED,还可以比较不加按键消抖情况下实际的效果对比如何。 

信号 引脚
clk C1
rst L14
key N14
led N13

这篇关于Lattice Diamond中VerilogHDL按键延时消抖的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/262262

相关文章

独立按键单击检测(延时消抖+定时器扫描)

目录 独立按键简介 按键抖动 模块接线 延时消抖 Key.h Key.c 定时器扫描按键代码 Key.h Key.c main.c 思考  MultiButton按键驱动 独立按键简介 ​ 轻触按键相当于一种电子开关,按下时开关接通,松开时开关断开,实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通与断开。  ​ 按键抖动 由于按键内部使用的是机

3.门锁_STM32_矩阵按键设备实现

概述 需求来源: 门锁肯定是要输入密码,这个门锁提供了两个输入密码的方式:一个是蓝牙输入,一个是按键输入。对于按键输入,采用矩阵按键来实现。矩阵按键是为了模拟触摸屏的按键输入,后续如果项目结束前还有时间就更新为触摸屏按键输入。 矩阵按键开发整体思路: 由于矩阵按键就是GPIO的控制,所以不进行芯片和设备的分层编写,控制写在同一个文件中,最终向应用层提供一个接口。 代码层级关系:

STM32F4按键状态机--单击、双击、长按

STM32F4按键状态机--单击、双击、长按 一、状态机的三要素二、使用状态机原因2.1资源占用方面2.2 执行效率方面:2.3 按键抖动方面: 三、状态机实现3.1 状态机分析3.1 程序实现 百度解析的状态机概念如下 状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作、完成特定操作的控制中心。有限状态机简写为FSM(

JS触发按键事件

<script type="text/javascript" language=JavaScript charset="UTF-8">document.onkeydown=function(event){var e = event || window.event || arguments.callee.caller.arguments[0];if(e && e.keyCode==27){ // 按

阿里中间件——diamond

一、前言        最近工作不忙闲来无事,仔细分析了公司整个项目架构,发现用到了很多阿里巴巴集团开源的框架,今天要介绍的是中间件diamond. 二、diamond学习笔记       1、diamond简介       diamond是一个管理持久配置(持久配置是指配置数据会持久化到磁盘和数据库中)的系统。无可厚非,淘宝内部正在使用diamond,在淘宝内部的绝大多数系统的配置都是由

学习记录-Qt按键单击后延迟一段时间触发下一个函数执行

<span style="font-family: Arial, Helvetica, sans-serif;">QTimer::singleShot(1000, this, SLOT(on_pushButton_pcba_readfilename_clicked()));</span>项目中,需要按键单击后发送一条指令,等待一段时间后在发另一条指令,看文档发现使用如上方式可以实现

linux--按键重映射问题

第一:按键重映射可以解决的问题是 ①键盘的某些按键不灵敏,需要把这个坏键重新映射到好的按键上。比如:如果Up按键不灵敏,把Esc按键重新映射成Up按键,这样就可以使用Esc按键代替Up按键。 ②经常使用的按键比较远,需要把常用的较远的按键重映射到距离手指比较近的地方,这样方便使用。 -------------------------------------------------

gt9xx系列------实现实体按键的unpin解锁

由于gt的虚拟按键的上报不是上报坐标而是类似电源按键的实体按键所以需要修改之前的unpin步骤 if ((( rawEvent->code==139)&&(rawEvent->value==1))||((rawEvent->code==158)&&(rawEvent->value==1)))  //有按键按下 { if( unpinkey[0]==0)     //第一次数组0肯定为空

嵌入式开发与应用按键外部中断实验二

一、实验目的 1. 通过实验掌握中断式键盘控制与设计方法; 2. 熟悉编写中断服务程序; 3. 掌握中断系统相关知识,掌握外部中断应用方法和处理过程; 4. 掌握实验处理器中断处理的软件编程方法; 5. 从按键程序的设计对系统的编程进行深入了解,与单片机裸机编程进行区分; 6. 掌握基于固件库编程控制GPIO端口的输出,进而控制LED灯的显示状态。 二、实验内容   根据实验要

ZET6程序换成VCT6程序,延时不对的解决办法

前言 已经写好了ZET6的程序,因为改板了,同一系列的芯片,程序也就改个芯片选项吗,可发现延时不准 提示:以下是本篇文章正文内容,下面案例可供参考 一、原因 启动文件注释了时钟初始化,ZET6使用是没有问题的,但是VCT6就会出错 二、解决办法 103VCT6是256K的FLASH所以,C++里还是用HD,所以其实大致不用改,就在Deveice选VCT6,程序基本能够编译通过