本文主要是介绍Lattice Diamond中VerilogHDL按键延时消抖,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
按键消抖
在之前的实验中我们学习了如何用按键作为FPGA的输入控制,在本实验中将学习如何进行按键消抖,用按键完成更多的功能。
硬件说明
按键是一种常用的电子开关,电子设计中不可缺少的输入设备。当按下时使开关导通,松开时则开关断开,内部结构是靠金属弹片来实现通断。
按键抖动的原理
在点亮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按键延时消抖的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!