用Verilog HDL实现按键消抖
VHDL语言按键去抖动电路的设计
--状态机复位,dout输出信 状态机复位, 状态机复位 输出信 号复位。 号复位。
--按键按下 按键按下
--按键按下 按键按下
--按键释放 按键释放
仿真结果
S0
S1
S0
S0
S1
S2
S2
S0
维持3个周期的低电平时 变成低电平, 当din维持 个周期的低电平时,dout变成低电平,表示有 维持 个周期的低电平时, 变成低电平 按键按下。 按键按下。
c lk res et key 1 key 2 key 3 key 4
ins t
led1 led2 led3 led4
clk:时钟,50MHz; :时钟, ; reset:复位信号; :复位信号; key1, key2, key3, key4:按键信号 : 输入; 输入; 输出信号: 输出信号: led1, led2, led3, led4:发光二极管 : 信号输出。 信号输出。
--key2按下 按下
--key3按下 按下
--key4按下 按下
--没有键被按下 没有键被按下
仿真结果
clk reset key 3
INPUT VCC
dout
din inst9 debounce clk reset dout
该设计包含分频模块、 该设计包含分频模块、去抖 动模块和按键扫描模块组成。 动模块和按键扫描模块组成。
key 4
INPUT VCC
din inst10
按键扫描程序
--key1按下 按下
50MHz
clk
INPUT VCC
Parameter Value Type n 250000 Signed Integer
f div 200hz clkin clkout
按键消抖实验
基于verilog按键消抖设计Aaron malone关于键盘的基础知识,我就以下面的一点资料带过,因为这个实在是再基础不过的东西了。
然后我引两篇我自己的博文,都是关于按键消抖的,代码也正是同目录下project里的。
这两篇博文都是ednchina的博客精华,并且在其blog 首页置顶多日,我想对大家会很有帮助的。
键盘的分类键盘分编码键盘和非编码键盘。
键盘上闭合键的识别由专用的硬件编码器实现,并产生键编码号或键值的称为编码键盘,如计算机键盘。
而靠软件编程来识别的称为非编码键盘。
在单片机组成的各种系统中,用的最多的是非编码键盘。
也有用到编码键盘的。
非编码键盘有分为:独立键盘和行列式(又称为矩阵式)键盘。
按键在闭合和断开时,触点会存在抖动现象:从上面的图形我们知道,在按键按下或者是释放的时候都会出现一个不稳定的抖动时间的,那么如果不处理好这个抖动时间,我们就无法处理好按键编码,所以如何才能有效的消除按键抖动呢?让下面的两篇博文日志给你答案吧。
经典的verilog键盘扫描程序从最基础的分频程序开始,但看到这个键盘扫描程序后,直呼经典,有相见恨晚的感觉,还想说一句:威百仕( VibesIC ),我很看好你!WHY?待我慢慢道来,这个程序的综合后是0error,0warning。
想想自己编码的时候那个warning是满天飞,现在才明白HDL设计有那么讲究了,代码所设计的不仅仅是简单的逻辑以及时序的关系,更重要的是你要在代码中不仅要表现出每一个寄存器,甚至每一个走线。
想想我写过的代码,只注意到了前者,从没有注意过后者,还洋洋自得以为自己也算是个高手了,现在想来,实在惭愧啊!学习学习在学习,这也重新激发了我对HDL设计的激情,威百仕给了我一个方向,那我可要开始努力喽!废话说了一大堆,看程序吧:(本代码经过ise7.1i综合并下载到SP306板上验证通过)//当三个独立按键的某一个被按下后,相应的LED被点亮;再次按下后,LED 熄灭,按键控制LED亮灭经过一次20ms的采样后判定为键盘按下。
VHDL入门:关于按键消抖的那个process
这学期的EDA课程设计有涉及到一个按键信号稳定的问题,虽然就算没有这块处理,最后成绩只会扣3分,但自己觉得像LED亮度变化,数字钟设置这些功能,如果没有加进一个稳定按键信号的模块,根本不能算是已实现的功能。
按键消抖的程序在网上有几种可供选择,但这里只讨论一种,本人觉得简单得来又比较强大的一种。
其实消抖的原理就是把一个按键周期内所输入的所有有效信号,包括那些毛刺,处理成一个脉冲输入。
能达到这点,就可以实现消抖功能了。
功能的源代码:代码中的 key 是按键输入,count 是自定义的计数器,N的值可以根据需要结合时钟频率设置,如果只是想达到按键一次输入一个脉冲的效果,建议 count 的时长设为 5ms,key_en 是处理完后输出的单个脉冲,至于有效信号是 '0' 还是'1' ,这要看板上的电路设计了。
此代码中是 '0' 为有效信号。
不要怀疑这段代码有错,理清逻辑后再套用,如果弄不明白什么原理,建议还是别用,用了可能会更糟糕。
要注意的是一个 process 中只能有一个时钟信号,否则很容易出错,就算编译通过,实际操作还是不行。
所以如果要对多个按键消抖,一定要在 "if clk'event and clk='1' then" 语句的内部增加,别重新设置一个 clk'event 。
还有就是按键的消抖功能块最好用单独的 process 运行,将 key_en 设置成新的按键输入信号,而实际的输入信号 key 只在按键消抖的process 中读入。
之所以说这种消抖方法简单得来又比较强大,是因为这方法不需要用到什么状态机、component 之类较高级点的东西,只需要多个 process 即可;另外这种方法还有其他的拓展用途,比如可以利用这个 count 延时周期设置一个短按键和长按键的识别,实现长按此键切换或者 reset 等等的功能,这里不详细解释。
vivado按键消抖原理
vivado按键消抖原理按键消抖是指在数字电路中,当按键按下或释放时,由于按键机械开关的特性,会导致电路出现不稳定的信号状态。
这种不稳定状态可能会导致错误的触发,例如出现多次触发或漏触发。
因此,为了确保按键信号的稳定性和可靠性,需要进行按键消抖处理。
按键消抖的原因主要有两个方面。
首先,按键机械开关的接触面存在微小的弹跳现象,当按键按下或释放时,接触面会在短时间内反复接触和分离,导致电路信号出现多次变化。
其次,由于电路中存在的噪声干扰,也会使得按键信号产生抖动。
为了解决按键消抖问题,可以采用硬件和软件两种方法。
硬件方法主要通过添加滤波电路或使用稳定的按键开关来消除按键弹跳现象。
滤波电路可以通过RC电路或者使用专用的按键消抖芯片来实现。
而软件方法主要通过在数字电路中添加按键消抖算法来处理按键信号。
在Vivado中,按键消抖可以通过使用状态机来实现。
状态机是一种用于描述系统行为的模型,可以根据输入信号的状态变化来改变系统的状态和输出。
在按键消抖中,可以使用状态机来检测按键信号的变化,并根据一定的状态转换规则来消除按键弹跳现象。
具体实现时,可以将按键信号作为输入,将按键状态和输出作为状态机的状态和输出。
当按键信号发生变化时,状态机会根据一定的状态转换规则进行状态转换,并输出消抖后的按键信号。
常用的状态转换规则包括按键按下时状态转换为按下状态,按键释放时状态转换为释放状态,以及连续按键时状态不变。
在Vivado中,可以使用Verilog或VHDL等硬件描述语言来编写状态机代码。
首先,需要定义状态机的输入、输出和状态变量,并初始化各个变量的初始值。
然后,需要编写状态转换规则和输出逻辑,根据输入信号的状态变化来改变状态和输出。
最后,需要将状态机代码综合生成对应的逻辑电路,并进行仿真和验证。
总结起来,按键消抖是数字电路设计中常见的问题,为了确保按键信号的稳定性和可靠性,需要进行按键消抖处理。
在Vivado中,可以使用状态机来实现按键消抖,通过定义状态转换规则和输出逻辑,消除按键弹跳现象。
键盘消抖原理代码说明(Verilog)
笔记2 键盘消抖(别人的笔记)老实说,这个实验的开始之前和之后,都给我蛋疼了。
时钟了解不到源码的思路,边看源码边睡着。
醒来的时候既然“惊”一下,相通了......module lesson02(CLK, RST,SW0, SW1, SW2,LED0, LED1, LED2);input CLK;input RST;input SW0, SW1, SW2;output LED0, LED1, LED2;//---------------------------------------------------------------------------//Detect the switch pressingreg [2:0] Press0;reg [2:0] Press1;wire [2:0] isPress;always @ (posedge CLK or negedge RST)if(!RST)Press0 <= 3'b111;elsePress0 <= {SW0, SW1, SW2}; //read the pin result;always @ (posedge CLK or negedge RST)if(!RST)Press1 <= 3'b111;elsePress1 <= Press0; //read the previous Press0 resultassign isPress=Press1 & (~Press0); //detect the logic with bit is changed from logic 1 to 0 //---------------------------------------------------------------------------//if pressing, counter start counting for 20msreg [19:0] Counter; //计数寄存器always @ (posedge CLK or negedge RST)if(!RST)Counter <= 20'd0;else if(isPress)Counter <= 20'd0;elseCounter <= Counter + 1'b1; //increment for counter//------------------------------------------------------------------------//After 20ms read the key pin resultreg [2:0] Press2;reg [2:0] Press3;wire [2:0] Result;always @ (posedge CLK or negedge RST)if(!RST)beginPress2 <= 3'b111;Press3 <= 3'b111;endelse if(Counter == 20'hfffff)Press2 <= {SW0, SW1, SW2}; //read the pin result after 20mselsealways @ (posedge CLK or negedge RST)if(!RST)elsePress3 <= Press2; //read the previous pin resultassign Result = Press3 & (~Press2); //detect the changing bit from logic 1 to 0//------------------------------------------------------------------------//turn on led with pin resultreg D1;reg D2;reg D3;always @ (posedge CLK or negedge RST)if(!RST)beginD1 <= 1'b0;D2 <= 1'b0;D3 <= 1'b0;endelsebeginif( Result[0] ) D1 <= ~D1;if( Result[1] ) D2 <= ~D2;if( Result[2] ) D3 <= ~D3;endassign LED0 = D1 ? 1'b1 : 1'b0;assign LED1 = D2 ? 1'b1 : 1'b0;assign LED2 = D3 ? 1'b1 : 1'b0;endmodule这个实验主要有计数器和边缘检查来实现按键消抖,按键功能。
Verilog写的按键消抖程序
前几天看了特权同学用Verilog写的按键消抖程序,感觉很经典。
在这里将程序贴出来分享一下。
module lcd_button2(clk,rst,seg,wei,sw1,sw2,sw3,sw4);//按键按下,数码管依次显示0-9input clk;input rst;input sw1,sw2,sw3,sw4;output [3:0] wei;output[7:0] seg;reg [7:0] seg;reg [3:0] wei;integer num;initial beginnum = 0;endreg[3:0] key_rst;always @(posedge clk or negedge rst)if(!rst)key_rst <= 4'b1111;elsekey_rst <= {sw4,sw3,sw2,sw1};reg[3:0] key_rst_r;always @(posedge clk or negedge rst)if(!rst)key_rst_r <= 4'b111;elsekey_rst_r <= key_rst;wire[3:0] key_an = key_rst_r & (~key_rst);reg[19:0] cnt;always @(posedge clk or negedge rst)if(!rst)cnt <= 0;else if(key_an) cnt <= 0;else cnt <= cnt+1'b1;reg [3:0] low_sw;always @(posedge clk or negedge rst)if(!rst)low_sw <= 4'b1111;else if(cnt==10'hfffff)low_sw <= {sw4,sw3,sw2,sw1};reg[3:0] low_sw_r;always @(posedge clk or negedge rst)if(!rst)low_sw_r <= 4'b1111;elselow_sw_r <= low_sw;wire [3:0] led_ctrl = low_sw_r[3:0] & (~low_sw[3:0]);reg d1,d2,d3,d4;always @(posedge clk or negedge rst)if(!rst) begind1 <= 0;d2 <= 0;d3 <= 0;d4 <= 0;endelse beginif(led_ctrl[0]) beginnum <= num+1;if(num==9)num <= 0;endendalways @(posedge clk ) beginwei <= 4'b1111;case(num)0: seg <= 8'hfc;1: seg <= 8'h60;2: seg <= 8'hda;3: seg <= 8'hf2;4: seg <= 8'h66;5: seg <= 8'hb6;6: seg <= 8'hbe;7: seg <= 8'he0;8: seg <= 8'hfe;9: seg <= 8'hf6;default: seg <= 8'h02;endcaseendendmodule参考了特权的代码。
防抖动Verilog HDL代码
cnt<=0;
led<=key;
end
else
cnt<=cnt+1;
key_last<=key;
end
endmodule
module stable_key(led,clk,key);
input key,clk;
output led;
reg key_last;
reg led;
reg[31:0] cnt;
always @ (posedge clk)
begin
if(key!=key_last)
cnt<=0;
else
if(cnt==1000000)
防抖动Verilog HDL代码:
module stable_key(key,led,clk );
input ;
reg [31:0] cnt;
reg led;
always @(posedge clk)
begin
if (key!=key_last)
防抖动verilog hdl代码 防抖动veriloghdl代码: module stable_key(key,led,clk inputkey,clk; output led; reg key_last; reg [31:0] cnt; reg led; always @(posedge clk) begin (key!=key_last)cnt<=0; else (cnt==50000000)//stable length begin cnt<=0; led<=key; end else cnt<=cnt+1; key_last<=key; end endmodule modulestable_key(led,clk,key); input key,clk; output led; reg key_last; reg led; reg[31:0] cnt; always (posedgeclk) begin if(key!=key_last) cnt<=0; else if(cnt==1000000) begin cnt<=0; led<=key; end else cnt<=cnt+1; key_last<=key; end endmodule fuke1236910 分享于 2013-01-15 05:47:9.8 暂无简介 文档格式: .doc 文档页数: 3页 文档大小: 22.0k 文档热度: 文档分类: 待分类 文档标签: 专业资料
Verilog按键消抖的理解
Verilog按键消抖的理解按键在按下时会产生抖动,释放时也会产生抖动,所以在设计键盘扫描程序时必须考虑按键的消抖,我们一般只考虑按下时的抖动,而放弃对释放时抖动的消抖。
抖动时间一般为20ms左右。
按下的最终结果是低电平'在单片机设计的的按键去抖思路是:检测到按下时延时20ms,再检测,如果状态仍为按下,贝U确认是按下的;如果状态为弹起的,则确认是干扰,无按键按下。
图1 按键抖动特性有一个概念要理一下,按键按下时会有抖动,也就是说我们其实只按一次,但是实际产生的“ 按下” 却是许多次的,这些许多次集中在这20ms 里。
我们按的只是一次,而实际却产生了许多次,那么就必须滤除其他的次数。
单片机为了得到真正的“ 按下”,通过延时20ms,把其他的“按下” (也就是抖动)给滤除了。
然后再次判断是否有按下,因为有的时候干扰很大。
而在FPGA中,基于下面的程序,理解如下:在这个程序里检测按键是否按下的方法是脉冲边沿检法。
而在单片机里是判断是否为低电平的方法(那么在FPGA中可不可以也用这个方法呢?)第一次检测到后,启动20ms 计数器,时间到后再检测。
这里的检测方法跟脉冲边沿检测法有异曲同工之处,FPGA过20ms检测按键是否按下,存储检测到的值,并且按位取反与前一个20ms检测的值相与,得到一个值,如果为1,则判断按键按下,否则则无按下。
所以跟单片机按键扫描的原理是一样的,不同的是检测方法不一样。
图2 FPGA 按键的理解示意图其中key_an 寄存器的功能是检测第一次的 “按 下”,是ent 的启动标志位。
通过也能滤除干扰信 号。
led_etrl是确实有按键按下的信号,维持一个时钟周期。
特权同学的Verilog 键盘扫描程序// 说明:当三个独立按键的某一个被按下后,相应的LED 被点亮;//再次按下后,LED 熄灭,按键控制 LED 亮灭 modulesw_debounce( clk,rst_n, sw1_n,sw2_n,sw3_n,下的JS生 谨产汞 按时彼伺隔勿吧时间轴110 UCi 111] 边沿唸迴注检测到"m 零汁数器并启动⑷矶的 时间计数 tn in no 110led_d1,led_d2,led_d3);input clk; // 主时钟信号,50MHzinput rst_n; // 复位信号,低有效input sw1_n,sw2_n,sw3_n; // 三个独立按键,低表示按下output led_d1,led_d2,led_d3; // 发光二极管,分别由按键控制// ----------------------------------------------reg[2:0] key_rst;always @(posedge clk or negedge rst_n)if (!rst_n) key_rst。
按键消抖的原理和基于verilog的消抖设计
按键消抖的原理和基于verilog的消抖设计按键开关是各种电子设备不可或缺的人机接口。
在实际应用中,很大一部分的按键是机械按键。
在机械按键的触点闭合和断开时,都会产生抖动,为了保证系统能正确识别按键的开关,就必须对按键的抖动进行处理。
在系统设计中,有各种各样的消除按键抖动的设计方法,硬件电路和软件设计都很成熟。
不过我们这里要从另外一个角度来讨论按键的消抖,并给出一个用verilog给出一个具体的实现。
首先,看一个普通的机械按键的触点在闭合与断开时的波形(用示波器抓取)。
下面的四张图都是按键在闭合的时候抓到的波形。
可以看到两个明显的趋势:1. 按键在几个us之内就可以达到稳定状态,从高电平转换到底电平;2. 在高电平转换到低电平的过程中,触点有非常明显的抖动。
下面的两张图是按键在断开的时候抓到的波形。
也可以看到两个明显的趋势:1. 按键的变化趋势比较缓慢,从低电平变为高电平需要大概10~20ms的时间;2. 按键断开时没有闭合时那么大的抖动下面两张图是用手迅速闭合按键然后就断开时,按键的输出波形。
在处理按键抖动的程序中,必须同时考虑消除闭合和断开两种情况下的抖动。
所以,对于按键消抖的处理,必须按最差的情况来考虑。
我们从上面的图上可以看到,按键输出的信号的跳变时间(上升沿和下降沿)最大是在20ms左右。
按键一次闭合最短的时间大概是120ms 左右。
如果我们把按键的输出做为一个时钟域(时钟频率未知,但信号的slow rate是已知的,既最大20ms左右)的信号,用另外一个时钟来采集这个按键的输出,则就可以把按键的消抖归结为一个最基本的CDC问题来处理。
而问题的核心是如何确定采集时钟的频率。
假设采集时钟的周期小于20ms,那么,采集时钟就有可能两次采到按键断开时的不。
基于FPGA的抖动及消抖的方法
基于FPGA的抖动及消抖的方法抖动的产生通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。
因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。
抖动时间抖动时间的长短由按键的机械特性决定,一般为5ms~10ms。
这是一个很重要的时间参数,在很多场合都要用到按键稳定闭合时间的长短则是由操作人员的按键动作决定的,一般为零点几秒至数秒。
键抖动会引起一次按键被误读多次。
为确保FPGA对键的一次闭合仅作一次处理,必须去除键抖动。
在键闭合稳定时读取键的状态,并且必须判别到键释放稳定后再作处理。
FPGA内实现消抖的方法在FPGA内实现按键消抖的方法多种多样,但是最简单的是采用移位寄存器的方法进行消抖。
因为移位寄存器的方法不需要对时钟进行分频,也不需要进行延时等复杂操作,即可实现对按键边沿的检测。
假设未按下时键值=1.1、在无键按下时,移位寄存器samp[7:0]始终采集到高电平,即samp[7:0]=8b1111_1111;2、当键按下时,samp[7:0]将采集到低电平,数据的变化方式为samp[7:0]=8b1111_1110--8b1111_1100--8b1111_1000-- ........8b0000_0000;samp[7:0]=8b1111_ 1110即为按键下降沿。
3、当松开按键时,samp[7:0]将重新采集到高电平,数据变化方式为samp[7:0]=8b0000_0001--8b0000_0011-- ........--8b1111_1111;当samp[7:0]=8b0111_1111时,即为按键上升沿。
参考Verilog代码//模块名:EdgeDetect,边沿检测//button:按键,无键按下时为高电平//clk:10M时钟//rst:复位按钮,低电平有效//rise:检测到上升沿,高电平有效,宽度为1个clk//fall:检测到下降沿,高电平有效,宽度为1个clkmodule EdgeDetect(input clk,input rst,input button,output reg rise,output reg fall);。
verilog按键消抖原理
verilog按键消抖原理(原创版)目录1.Verilog 简介2.按键消抖的概念3.按键消抖的实现原理4.实际应用中的按键消抖设计5.总结正文【1.Verilog 简介】Verilog 是一种硬件描述语言,主要用于数字系统硬件的描述、模拟和验证。
在数字电路设计和 FPGA 开发领域,Verilog 被广泛应用。
通过Verilog,设计人员可以对硬件电路进行建模、模拟和验证,以确保设计满足性能要求。
【2.按键消抖的概念】按键消抖,又称按键去抖,是一种在按键输入过程中消除误触发的技术。
在实际应用中,按键输入可能会受到噪声、抖动等因素的影响,导致误触发。
按键消抖的目的就是消除这些干扰,确保按键输入的准确性。
【3.按键消抖的实现原理】按键消抖的实现原理主要有两种:软件消抖和硬件消抖。
(1)软件消抖:软件消抖是通过程序算法实现的。
在按键触发时,程序会检测按键触发信号是否满足一定的条件,例如连续触发次数、触发时间间隔等。
如果满足条件,则认为这是一个有效的按键触发,否则不予响应。
(2)硬件消抖:硬件消抖是通过硬件电路实现的。
硬件消抖电路通常包括滤波器、延迟器等组件。
当按键触发信号输入时,滤波器会滤除噪声,延迟器会消除触发信号的抖动,从而保证输出信号的稳定性。
【4.实际应用中的按键消抖设计】在实际应用中,按键消抖设计需要考虑多种因素,如按键触发信号的噪声、抖动特性,系统的响应速度等。
为了实现高效、可靠的按键消抖,设计人员需要对这些因素进行综合考虑,选择合适的消抖方案。
【5.总结】按键消抖是一种重要的技术,可以有效消除按键输入中的误触发,提高系统的稳定性和可靠性。
消抖电路
基于VHDL语言的按键消抖电路设计及仿真按键开关是电子设备实现人机对话的重要器件之一。
由于大部分按键是机械触点,在触点闭合和断开时都会产生抖动。
为避免抖动引起误动作造成系统的不稳定,就要求消除按键的抖动,确保按键每按一次只做一次响应。
随着可编程逻辑器件的综合性能的不断提高,它已经象单片机一样。
广泛应用在各种数字逻辑领域。
用可编程逻辑器件直接获取键盘信息也得到广泛的应用。
这里提出用VHDL 语言编程的有限状态机的设计方法来实现按键的消抖,经仿真分析和下载实现,这种方法设计的消抖电路能够很好地实现电路功能,进行快速按键时都能保证每按一次做一次的响应,且性能稳定。
1 按键抖动产生原因分析绝大多数按键都是机械式开关结构,由于机械式开关的核心部件为弹性金属簧片,因而在开关切换的瞬间会在接触点出现来回弹跳的现象。
虽然只是进行了一次按键,结果在按键信号稳定的前后出现了多个脉冲,如图1所示。
如果将这样的信号直接送给微处理器扫描采集的话,将可能把按键稳定前后出现的脉冲信号当作按键信号,这就出现人为的一次按键但微处理器以为多次按键现象。
为了确保按键识别的准确性,在按键信号抖动的情况下不能进入状态输入,为此就必须对按键进行消抖处理,消除抖动时不稳定、随机的电压信号。
机械式按键的抖动次数、抖动时间、抖动波形都是随机的。
不同类型的按键其最长抖动时间也有差别,抖动时间的长短和按键的机械特性有关,一般为5~10 ms,但是,有些按键的抖动时间可达到20 ms,甚至更长。
所以,在具体设计中要具体分析,根据实际情况来调整设计。
2 按键消抖电路的设计按键消抖一般采用硬件和软件消抖两种方法。
硬件消抖是利用电路滤波的原理实现,软件消抖是通过按键延时来实现。
在微机系统中一般都采用软件延时的消抖方法。
在用可编程逻辑器件FPGA/CPLD设计数字系统中,也可以用VHDL语言设计相应的时序和逻辑电路,对按键信号进行处理,同样可以达到消抖目的。
EDA实验五报告
实验五按键消抖和分频器电路设计一、实验目的学习和掌握使用Verilog语言设计按键去抖动电路和分频器的方法二、实验原理分频器就是简单的加法计数器,对于偶数分频和奇数分频应注意其占空比的问题。
当按一次按健时,由于按健有反应时间、有大量的毛刺产生(抖动),可能按一次机器感应到几次。
消抖就是让在按键正常反应时间内机器只感应一次按键效果,防止误操作。
消抖的原理是:当检测到有键按下时,并不认为有键按下,而是等待20ms后,再次判断是否有键按下,若有则认为确实有键按下;若没有则认为上次的按键是误操作。
三、实验内容1.分频器设计:使用实验箱左下角的时钟频率源,编写一段Verilog程序,使led发光管,每隔1S闪烁一次。
程序设计:module clk5M_1s(clk5M,clk1s);input clk5M;output clk1s;parameter i1=4999;parameter i2=999;reg [12:0]t1,t2;reg k;reg clk1s;always @(posedge clk5M)begin //进行5000分频if(t1<=i1) t1<=t1+1'b1; else t1<=1'b0;if(t1==i1) k<=k+1'b1;endalways @(posedge k)begin //进行1000分频if(t2<=i2) t2<=t2+1'b1; else t2<=1'b0;if(t2==i2) clk1s<=clk1s+1'b1;endendmodule分析:选用的时钟频率源为5M,如果产生频率为1Hz的脉冲使led发光管每隔1s亮一次,则共需分频5000000次,因此分频次数超过内部芯片1个计数器所能承受的范围,故需用两个计数器进行两次分频,即程序中所指出的第一次5000分频,第二次1000分频。
FPGA入门系列实验教程——按键消抖控制LED亮灭
FPGA入门系列实验教程——按键消抖控制LED亮灭1.实验任务实现按键控制LED亮灭。
通过这个实验,掌握采用Verilog HDL语言编程实现按键控制LED亮灭及按键消抖方法。
2.实验环境硬件实验环境为艾米电子工作室型号EP2C8Q208C8增强版开发套件。
软件实验环境为Quartus II8.1开发软件。
3.实验原理当独立按键key1按下后,相应的LED被点亮;再次按下后,LED做翻转输出,即LED熄灭,从而实现按键控制LED亮灭。
本实验对按键进行了消抖处理。
作为机械开关的按键,操作时,机械触点的弹性及电压突跳等原因,在触点闭合或开启的瞬间会出现电压抖动,实际应用中如果不进行处理将会造成误触发。
按键去抖动的关键在于提取稳定的低电平状态,滤除前沿、后沿抖动毛刺。
按键消抖处理一般有硬件和软件两种方法。
软件消抖是检测到有触发后,延时一段时间后再检测触发状态,如果与之前检测到的状态相同,则认为有按键按下;如果没有则认为是误触发。
硬件就是加去抖电路。
4.实验程序module key_debounce(rst_n,clk,key,led);input rst_n;input clk;input key;output led;//通过降采样对key的输入做低通滤波,将其高频分量滤除,得到low_sw值reg[17:0]cnt;always@(posedge clk)if(!rst_n)cnt<=18'd0;elsecnt<=cnt+1'b1;wire sample_pulse=cnt==18'h3ffff;reg low_sw;always@(posedge clk)if(!rst_n)low_sw<=1'b1;else if(sample_pulse)low_sw<=key;//在整个low_sw(active_low)有效过程中取一个控制量作为led的控制信号//本实例中使用low_sw的下降沿reg low_sw_r;//将low_sw信号锁存一个时钟周期,延时不是真的“锁存”always@(posedge clk)low_sw_r<=low_sw;wire led_ctrl=low_sw_r&(!low_sw);reg led;always@(posedge clk or negedge rst_n)if(!rst_n)led<=1'b0;else if(led_ctrl)led<=~led;endmodule5.实验步骤(1)建立新工程项目:打开Quartus II软件,进入集成开发环境,点击File→New project wizard建立一个工程项目key_debounce。
详解MCU独立按键消抖:原因、方法统统都有
详解MCU独立按键消抖:原因、方法统统都有简单的说,进入了电子,不管是学纯模拟,还是学单片机,像DSP、ARM等处理器,或者是我们的FPGA,一般没有不用到按键的地方(按键:人机交互控制,主要用于对系统的控制,信号的释放等)。
因此在这里,FPGA上应用的按键消抖动,也不得不讲!一、为什么要消抖动在按键被按下的短暂一瞬间,由于硬件上的抖动,往往会产生几毫秒的抖动,在这时候若采集信号,势必导致误操作,甚至系统崩溃;同样,在释放按键的那一刻,硬件上会相应的产生抖动,会产生同样的后果。
因此,在模拟或者数字电路中,我们要避免在最不稳定的时候采集信号进行操作。
对此,一般产用消抖动的原理,其可分为以下三种:(1)延时(2)N次低电平计数(3)低通滤波在数字电路中,一般采用第1、2种方法(后文中将详细介绍)。
二、各种消抖动1、模拟电路按键消抖动对于模拟电路中,一般消抖动用的是电容消抖动或者施密特触发等电路,再次不做具体介绍。
图片2、单片机中按键消抖动对于单片机中的按键消抖动,本节Bingo根据自己当年写过的单片机其中的一个代码来讲解,代码如下所示:unsigned char key_sCAN(void){if(key == 0) //检测到被按下{delay(5); //延时5ms,消抖if(key != 0)retrurn 0; //是抖动,返回退出while(!key1); // 确认被按下,等下释放delay(5); //延时5ms,消抖while(!key1); //确认被释放return 1; //返回按下信号}return 0; //没信号}针对以上代码,消抖动的顺序如下所示:(1)检测到信号(2)延时5ms,消抖动(3)继续检测信号,确认是否被按下a. 是,则开始等待释放b. 否,则返回0,退出(4)延时5ms,消抖动(5)确认,返回按下信号,退出当然,在单片机中也可以循环计数来确认是否被按下。
Bingo认为如此,太耗MCU资源,因此再次不做讲述。
阐述基于FPGA的按键抖动的消除方法
阐述基于FPGA的按键抖动的消除方法我们在进行数字电路的设计的过程中,经常会碰到信号抖动相关的问题。
抖动信号大致分为两类:一类是时间极短的干扰信号(比如毛刺);另一类是时间较长的干扰信号(如本文所研究的按键抖动问题)。
对于第一类干扰信号——毛刺,它的时间极短,通常只有几纳秒,不能满足触发器的建立时间与保持时间,因此我们可以用一个D触发器去读带毛刺的信号,由于D触发器具有对毛刺不敏感的特点,可以去除信号中的毛刺,达到消除抖动的效果(消除毛刺的方法很多,在这里不做讨论,本文重点说明按键抖动的消除及其代码设计)。
在数字电路设计中,按键通常为一个个具有弹性的机械触点开关,其开启或者闭合的瞬间都会产生按键抖动,实际波形如图1所示:由图1可知,在按键闭合和断开的瞬间,我们往往只需要一组稳定的上升边沿和下降边沿,但实际上却产生了若干个边沿。
所以,在实际电路中,我们仅仅按动按键,简单地读取信号的边沿,却不滤除抖动,会导致一次按键操作被误读多次,从而引起电路的误动作。
为了达到一次按键操作得到一次正确的响应的目的(在按键闭合或者断开),信号稳定的状态下读取此时按键的状态,就必须在电路中采取消除抖动的措施。
在纯数字电路设计中,下面介绍几种消除按键抖动的常用实现方法。
1 设计硬件消抖电路(硬件方法)设计一个具有延时作用的滤波电路或者经常用到的单稳态电路等硬件电路,来消除按键的抖动(避免抖动时间)。
图2所示的电路,即为典型的滤波延时消抖电路,S为按键,Di为CPU数据线。
当按键S未闭合时,与非门的输入电压Vi(即电容的端电压)为0,从而输出电压Vo为1。
我们按下按键S,电容C的端电压不会发生突变,充电延迟时间取决于R1、R2和C值的大小,当电容端电压在充电时间内未达到与非门的开启电压,将不会改变门的输出电压;当电容端电压大于门的开启电压时,与非门的输出Vo发生改变,即输出为0(我们在数字电路的设计过程中,为了避开按键抖动的影响,需要使充电延时大于或等于100ms)。
如何设计按键消抖
在使用单片机搭建有人机交互的系统时需要用到键盘,因为单片机工作时间都是纳秒与毫秒级别,但是我们人体的反应时间最少要0.2秒,之间差距很大,现实过程中也会不小心碰到按键,正常的按下按键应该是持续数十秒的稳定。
一、按键电路常用的非编码键盘,每个在使用单片机搭建有人机交互的系统时需要用到键盘,因为单片机工作时间都是纳秒与毫秒级别,但是我们人体的反应时间最少要0.2秒,之间差距很大,现实过程中也会不小心碰到按键,正常的按下按键应该是持续数十秒的稳定。
一、按键电路常用的非编码键盘,每个键都是一个常开开关电路。
计数器输入脉冲最好不要直接接普通的按键开关,因为记数器的记数速度非常快,按键、触点等接触时会有多次接通和断开的现象。
我们感觉不到,可是记数器却都记录了下来。
例如,虽然只按了1下,记数器可能记了3下。
因此,使用按键的记数电路都会增加单稳态电路避免记数错误。
二、按键消抖通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,电压信号小型如下图。
由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。
因而在闭合与断开的瞬间均伴随有一连串的抖动,如下图。
抖动时间的长短由按键的机械特性决定,一般为5ms~10ms。
这是一个很重要的时间参数,在很多场合都要用到。
按键稳定闭合时间的长短则是由操作人员的按键动作决定的,一般为零点几秒至数秒。
键抖动会引起一次按键被误读多次。
为确保CPU对键的一次闭合仅作一次处理,必须去除键抖动。
在键闭合稳定时读取键的状态,并且必须判别到键释放稳定后再作处理。
按键的抖动,可用硬件或软件两种方法。
三、硬件消抖在键数较少时可用硬件方法消除键抖动。
下图所示的RS触发器为常用的硬件去抖。
消抖电路如下图中两个“与非”门构成一个RS触发器。
当按键未按下时,输出为1;当键按下时,输出为0。
此时即使用按键的机械性能,使按键因弹性抖动而产生瞬时断开(抖动跳开B),中要按键不返回原始状态A,双稳态电路的状态不改变,输出保持为0,不会产生抖动的波形。
verilog按键消抖原理
verilog按键消抖原理
摘要:
1.按键消抖的原理
2.按键消抖的方法
3.基于Verilog 的按键消抖设计
4.结论
正文:
一、按键消抖的原理
按键消抖是指在按键输入过程中,由于按键机械特性和电路特性的影响,导致按键在按下或松开时,信号电平会在一段时间内发生抖动。
为了消除这种抖动,需要采用一定的方法来确认按键输入的稳定性,这就是按键消抖。
二、按键消抖的方法
常见的按键消抖方法有以下几种:
1.硬件消抖:通过硬件电路实现消抖,如使用滤波器、RC 电路等。
2.软件消抖:通过软件算法实现消抖,如使用计数器、计时器等。
3.结合硬件和软件消抖:既使用硬件电路,也使用软件算法来实现消抖。
三、基于Verilog 的按键消抖设计
基于Verilog 的按键消抖设计可以分为以下几个步骤:
1.输入信号处理:对输入的按键信号进行采样,并转化为数字信号。
2.计数器:使用计数器来统计按键信号的持续时间,以判断按键是否稳定。
3.状态判断:根据计数器的计数值来判断按键是按下还是松开。
4.输出信号处理:将判断结果输出,以控制其他电路或设备。
四、结论
按键消抖是电子设备中常见的一种技术,它可以有效地消除按键输入过程中的抖动,提高系统的稳定性和可靠性。
【黑金原创教程】【FPGA那些事儿-驱动篇I】实验二:按键模块①-消抖
【⿊⾦原创教程】【FPGA那些事⼉-驱动篇I】实验⼆:按键模块①-消抖实验⼆:按键模块① - 消抖按键消抖实验可谓是经典中的经典,按键消抖实验虽曾在《建模篇》出现过,⽽且还惹来⼀堆⿇烦。
事实上,笔者这是在刁难各位同学,好让对⽅的惯性思维短路⼀下,但是惨遭⼝⽔攻击 ... ⾯对它,笔者宛如被甩的男⼈,对它⼜爱⼜恨。
不管怎么样,如今 I’ll be back,笔者再也不会重复⼀样的悲剧。
按键消抖说傻不傻说难不难。
所谓傻,它因为原理不仅简单(就是延迟⼏下下⽽已),⽽且顺序语⾔(C语⾔)也有⽆数不尽的例⼦。
所谓难,那是因为⼈们很难从单⽚机的思维跳出来 ... 此外,按键消抖也有许多细节未曾被⼈重视,真是让⼈伤⼼。
按键消抖⼀般有3段操作:l 检测电平变化;l 过滤抖动(延迟);l 产⽣有效按键。
假设C语⾔与单⽚机的组合想要检测电平变化,它们⼀般是利⽤if查询或者外部中断。
事后,如果这对组合想要过滤抖动,那么可以借⽤for 延迟的⼒量,⼜或者依赖定时中断产⽣精明的延迟效果。
反观有效案件的产⽣,这对组合视乎⽽外钟情“按下有效”似的 ... 不管怎么样,C语⾔与单⽚机这对组合在处理按键的时候,它们往往会错过⼀些黄⾦。
“黄⾦?”,读者震撼道。
所谓黄⾦时间就是电平发⽣变化那⼀瞬间,还有消抖(延迟)以后那⼀瞬间。
按键按下期间,按键的输⼊电平故会发⽣变化,如果使⽤if查询去检测,结果很容易浪费单⽚机的处理资源,因为单⽚机必须⼀直等待 ... 换之,如果反⽤外部中断,中断寻址也会耽误诺⼲时间。
假设C语⾔与单⽚机这对组合挨过电平检测这起难关,余下的困难却是消抖动作。
如果利⽤for循环实现去消抖,例如 Delay_ms(10) 之类的函数。
For循环不仅计数不紧密,⽽且还会⽩⽩浪费单⽚机的处理资源。
定时中断虽然计数紧密,但是中断触发依然也会产⽣诺⼲的寻址延迟。
补上,所谓寻址延迟是处理器处理中断触发的时候,它要事先保护现场之余,也要寻址中断处理⼊⼝,然后执⾏中断函数,完后回复现场,最后再返回当前的⼯作。
Verilog-按键消抖程序
按键消抖一、程序(50mhz)modulexiaodou(clk,clr,key1,key2,key3,key4,key5,key_out1,key_out2,key_out3,key_out4,key_ out5);input clk,clr;input key1,key2,key3,key4,key5;output key_out1,key_out2,key_out3,key_out4,key_out5;//-------------------------------------------------reg [4:0] key_rst;reg [4:0] key_rst_n;reg [19:0] cnt;reg [4:0] key_next;reg [4:0] key_next_n;reg d1,d2,d3,d4,d5;wire[4:0] key_flag;wire [4:0] key_out_n;reg [23:0] count1;reg count_flag;always @(posedge clk or negedge clr) //get the fist valuebeginif(!clr)begin key_rst<=5'b11111;endelsebegin key_rst<={key5,key4,key3,key2,key1};endend//---------------------------------------always @(posedge clk or negedge clr) beginif(!clr)begin key_rst_n<=5'b11111;endelsebegin key_rst_n<=key_rst;endend//---------------------------------------- assign key_flag=key_rst_n&(~key_rst); //--------------jishu------------------- always @(posedge clk or negedge clr) beginif(!clr)begin cnt<=20'd0;endelse if(key_flag)begin cnt<=20'b0;endelsebegin cnt<=cnt+1'b1;endend//-----------------20ms after ------------- always @(posedge clk or negedge clr) beginif(!clr)begin key_next<=5'b11111;endelse if(cnt==20'hfffff)beginkey_next<={key5,key4,key3,key2,key1};endend//----------------------------------always @(posedge clk or negedge clr)beginif(!clr)begin key_next_n<=5'b11111;endelsebegin key_next_n<=key_next;endend//-------------------------------------------assign key_out_n=key_next_n&(~key_next);//--------------------------------------always @(posedge clk or negedge clr)beginif(!clr)begin d1<=1'b1;d2<=1'b1;d3<=1'b1;d4<=1'b1;d5<=1'b1;count_flag<=1;endelse //应led止显示一个时钟周期,我们观测不到,begin //此处有个计数延时,目的是led灯显示能够持续一段时间if(key_out_n[0])begin d1<=1'b0;count_flag<=1'b0;endelseif(count1==24'hffffff)begin d1<=1'b1;count_flag<=1;endif(key_out_n[1])begin d2<=1'b0;count_flag<=1'b0;endelseif(count1==24'hffffff)begin d2<=1'b1;count_flag<=1;endif(key_out_n[2])begin d3<=1'b0;count_flag<=1'b0;endelseif(count1==24'hffffff)begin d3<=1'b1;count_flag<=1;endif(key_out_n[3])begin d4<=1'b0;count_flag<=1'b0;endelseif(count1==24'hffffff)begin d4<=1'b1;count_flag<=1;endif(key_out_n[4])begin d5<=1'b0;count_flag<=1'b0;endelseif(count1==24'hffffff)begin d5<=1'b1;count_flag<=1;endendendassign key_out1=d1?1'b1:1'b0;assign key_out2=d2?1'b1:1'b0;assign key_out3=d3?1'b1:1'b0;assign key_out4=d4?1'b1:1'b0;assign key_out5=d5?1'b1:1'b0;always @(posedge clk or negedge clr) //计数延时,具体时间没有计算beginif(!clr)begin count1<=0;endelseif(count_flag==1'b0)begin count1<=count1+1'b1;endelsebegincount1<=0;endendendmodule二、框图。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
按键消抖
用按键控制一个数字,按键每按一次,这个数字加1,并通过数码管将这个数字显示出来(以16进制)。
可能是悟性比较低,按键消抖都搞了1天才搞出来,下面这个程序是我经过参考别人的(有些地方没想明白),然后自己领会,写的一个程序,经过在开发板上实验,还是有一点小问题,但是我觉得,按键消抖的原理应该是这样的。
希望本文能帮到需要的人,我也是一个初学者,可能程序中也有很多不足,还请能提出来,相互交流。
QQ:1664619265
module SW_debounce(rst_n,sy_clk,key,HEX0_D);
input rst_n;/低电平复位
input sy_clk;//系统时钟50Mhz
input key; 按键
output [6:0]HEX0_D;数码管
//*************************/
reg key_rst;
always@(posedge sy_clk or negedge rst_n) begin
if(!rst_n)
key_rst<=1'b1;
else每个时钟周期读一次按键的值
key_rst<=key;
end 将按键的值存在key_rst中
//*************************/
reg key_rst_r;
always@(posedge sy_clk or negedge rst_n) begin
if(!rst_n)
key_rst_r<=1'b1;
else 每个时钟周期将key_rst中的值存入key_rst_r中。
key_rst_r<=key_rst;这样key_rst和key_rst_r中存放的是前后两个
时钟周期,按键的值
end
//*************************/
wire key_en,key_an;重点1:抖动时期的标志量,这两个标志
量是用来给后面的计数器清零的assign key_en=key_rst&(~key_rst_r);当按键由0变1时,key_en为1 assign key_an=key_rst_r&(~key_rst);当按键由1变0时,key_an为1;
看下面的按键波形,俺觉得,抖动
期间,这两个标志量都有可能为1 //**************************/
reg[18:0] count; 计数,是为了延时10ms左右
always@(posedge sy_clk or negedge rst_n) begin
if(!rst_n)
count<=19'd0;
else if(key_en | key_an)
count<=19'd0;出现抖动就将count
清零,使其计不满,因为后面是每10ms读一次按键的
值
else if(count==19'h7ffff)//10ms
count<=19'd0;
else
count<=count+1'b1;
end
//************************/
reg low_sw;
always@(posedge sy_clk or negedge rst_n) begin
if(!rst_n)
low_sw<=1'b1;
else if(count==19'h7ffff)
low_sw<=key;每10ms读一次按键的值,因为抖动期间,count的值是
到不了7ffff的,所以抖动期间是不会读按键的值的,因
此能消除抖动。
end
//*********************/
reg low_sw_r;
always@(posedge sy_clk or negedge rst_n) begin
if(!rst_n)
low_sw_r<=1'b1;
else
low_sw_r<=low_sw;low_sw和low_sw_r存放的是前后10ms,按键的
值,这个值中,是按键稳定时的值end
//*************************/
wire ctr;
assign ctr=low_sw&(~low_sw_r);按键松手时,ctr会出现一个系统周期的高电平
//
reg[3:0]control;
always@(posedge sy_clk or negedge rst_n) begin
if(!rst_n)
control<=4'b0;
else if(ctr) 如何用通过按键产生的这个信号ctr control<=control+1'b1;
end
display dis1(control,HEX0_D);
endmodule
module display(d,dis_data);
input[3:0]d;
output[6:0]dis_data;
reg[6:0]dis_data;
always@(d) begin
case(d)
4'b0000: dis_data=7'b1000000;//display 0
4'b0001: dis_data=7'b1111001;//display 1
4'b0010: dis_data=7'b0100100;//display 2
4'b0011: dis_data=7'b0110000;//display 3
4'b0100: dis_data=7'b0011001;//display 4
4'b0101: dis_data=7'b0010010;//display 5
4'b0110: dis_data=7'b0000010;//display 6
4'b0111: dis_data=7'b1111000;//display 7
4'b1000: dis_data=7'b0000000;//display 8
4'b1001: dis_data=7'b0011000;//display 9
4'b1010: dis_data=7'b0100011; //display a;
4'b1011: dis_data=7'b0000011;//display b;
4'b1100: dis_data=7'b1000110;//display c;
4'b1101: dis_data=7'b0011100;//display d;
4'b1110: dis_data=7'b0000110;//display E;
4'B1111: dis_data=7'b0001110;//display F;
endcase
end
endmodule。