FPGA按键消抖实验(源码)
- 格式:docx
- 大小:15.65 KB
- 文档页数:4
按键消抖1功能概述按键开关是各种电子设备不可或缺的人机接口,如电脑的键盘等。
实际应用中,按键开关通常为机械式弹性开关。
当机械点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定接通,断开时也不会马上断开,在闭合和断开的瞬间均伴随有一连串的抖动。
为保证系统及时正确识别,必须对这种情况作出相应处理。
我们称之为按键消抖。
按键消抖可分为硬件消抖和软件消抖。
硬件消抖的原理是在信号输入系统之前消除抖动干扰,在按键较少的情况下比较适宜。
如果按键较多,则使用软件消抖。
软件消抖的实质在于降低键盘输入端口的采样频率,将高频抖动略去。
需要注意的是,软件消抖需要占据一定的系统资源。
尽管硬件消抖和软件消抖能实现按键消抖功能,串行处理的方式都存在一定的局限性,显得不那么完美。
而硬件资源丰富的FPGA系统采用并行处理的模式,利用硬件来减轻软件工作量,通过硬件加速软件消抖处理,即可做到软件消抖并行化,因而在按键消抖处理方面具备非常明显的优势。
优秀的设计程序应该是用最简单的代码(架构、信号)实现功能。
在本例中,我们的只需要用4个信号界定,并用很短的代码即可。
下面我们先来看看功能要求:在系统设计中,消除按键抖动的方法五花八门,无论是硬件电路和软件设计都十分成熟。
在本项目中,我们将用Verilog语言给出具体实现过程,设计一个程序来检查键值,有效滤除按键抖动区间20 ms的毛刺脉冲。
2 设计思路一般按键所用开关为机械弹性开关,由于机械触点的弹性作用,每个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。
因而在闭合及断开的瞬间均伴随有一连串的抖动,如下图。
抖动时间的长短由按键的机械特性决定,一般为5 ms~10 ms。
1图1 按键抖动过程示意当系统检测出按键闭合后,执行一个延时程序,产生5ms~10ms的延时;前沿抖动消失后,再一次检测键的状态;如果仍保持闭合状态电平,则确认为真正有键按下。
当检测到按键释放后,也要给5ms~10ms的延时,待后沿抖动消失后才能转入该键的处理程序。
FPGA按键去抖程序代码是特权同学的,我将其理解后加上了注释。
去抖的原理和单片机是一样的,即通过延时来过滤掉按键抖动产生的毛刺信号。
不同的是判断按键按下的条件不同,单片机通常是已知按键不按时IO口的电平(如高电平),当IO口电平发生改变时(如低电平),则开启定时器进行延时,延时20ms后再次读取IO口的电平,若仍为低电平,则说明有按键按下;若为高电平,则说明是按键抖动,没有按键按下。
FPGA的采样频率很高,它可以在每个时钟周期的上升沿到来时对IO口的电平进行一次读取。
通过读取相邻2个时钟周期内IO口的电平值并进行比较,若电平值发生改变(此代码中是判断电平从0变为1),则计数器清零,若持续20ms后电平值没有发生改变,则读取按键的键值,同时将这一键值存储起来,当下一个20ms后再次读取键值,将2次键值进行比较,若键值发生改变,则说明按键有动作(要么按下,要么松手)。
此代码中是判断键值从0变为1,即松手检测。
// 按键去抖// 实现一个简单的三个按键分别控制三个发光二极管亮或暗的控制。
// 例如,按键1控制发光二极管1。
上电初始发光二极管1不亮,// 当检测到按键1被按下后,发光二极管1则点亮,// 按键1再次被按下时,发光二极管1则不亮,如此反复。
// 该实验需要把握好按键消抖检测的设计技巧。
// 注:此代码的按键操作是包括松手检测的,// 即按键按下后要等到松手才算一次按键操作module key_debounce(clk,rst_n,key1_n,key2_n,key3_n,led1_n,led2_n,led3_n);input clk;input rst_n;input key1_n,key2_n,key3_n;output led1_n,led2_n,led3_n;reg [2:0] key_rst;always @(posedge clk or negedge rst_n)beginif(!rst_n)key_rst <= 3'b111;elsekey_rst <= {key3_n,key2_n,key1_n}; // 读取当前时刻的按键值endreg [2:0] key_rst_r;always @(posedge clk or negedge rst_n)beginif(!rst_n)key_rst_r <= 3'b111;elsekey_rst_r <= key_rst; // 将上一时刻的按键值进行存储endwire [2:0]key_an = key_rst_r & (~key_rst); // 当键值从0到1时key_an改变//wire [2:0]key_an = key_rst_r ^ key_rst; // 注:也可以这样写reg [19:0] cnt; // 延时用计数器always @(posedge clk or negedge rst_n)beginif(!rst_n)cnt <= 20'd0;else if(key_an)cnt <= 20'd0;elsecnt <= cnt + 20'd1;endreg [2:0] key_value;always @(posedge clk or negedge rst_n)beginif(!rst_n)key_value <= 3'b111;else if(cnt == 20'hfffff) // 2^20*1/(50MHZ)=20ms key_value <= {key3_n,key2_n,key1_n}; // 去抖20ms 后读取当前时刻的按键值endreg [2:0] key_value_r;always @(posedge clk or negedge rst_n)beginif(!rst_n)key_value_r <= 3'b111;elsekey_value_r <= key_value; // 将去抖前一时刻的按键值进行存储endwire [2:0] key_ctrl = key_value_r & (~key_value); // 当键值从0到1时key_ctrl改变reg d1;reg d2;reg d3;always @(posedge clk or negedge rst_n)beginif(!rst_n)begin // 一个if内有多条语句时不要忘了begin end d1 <= 0;d2 <= 0;d3 <= 0;endelsebeginif(key_ctrl[0]) d1 <= ~d1;if(key_ctrl[1]) d2 <= ~d2;if(key_ctrl[2]) d3 <= ~d3;endendassign led1_n = d1? 1'b1:1'b0; // 此处只是为了将LED输出进行翻转,RTL级与下面注释代码无差别assign led2_n = d2? 1'b1:1'b0; assign led3_n = d3? 1'b1:1'b0; endmodule。
基于FPGA的LED流水灯与按键消抖实验1.实验目的(1)通过实验进一步学习Quartus II软件的使用方法。
(2)通过实验学习流水灯的设计原理。
(3)通过实验学习按键消抖(边沿检测法)的基本原理。
2.实验仪器设备(1)FPGA开发实验箱。
(2)数字万用表。
(3)电脑。
3.预习(1)复习FPGA开发有关的流程。
(2)复习Verilog HDL语言语法。
(3)复习实验所用的相关原理。
(4)按要求编写实验中要求的硬件描述语言程序。
4.实验原理(1)LED流水灯。
流水灯是一个典型的FPGA程序设计,通过控制8位led向左依次循环点亮,达到对硬件语言、软件开发平台等的初步认识。
①if语句的使用。
Verilog HDL语言中的if语句与C语言中的十分相似,其使用方法有以下三种:a.if(条件1)语句块1;b.if(条件1)语句块1;else 语句块2;c.if(条件1)语句块1;else if(条件2)语句块2;……else if(条件n)语句块n;else 语句块n+1。
在上述三种方式中,“条件”一般为逻辑表达式或关系表达式,也可以是一位的变量。
如果表达式的值出现0(假),x(未知),z(高阻),则全部按“假”来处理;若为“1”,则按“真”来处理。
语句块若为单句,直接书写即可;若为多句,则需要用“begin end”块括起来。
建议无论多句还是单句都用“begin end”括起来。
②case语句的使用。
case语句是一个多路条件分支语句,常用于多路译码、状态机和微处理机的指令译码等场合。
case语句的语法格式为:case(条件表达式)分支1:语句块1;分支2:语句块2;……default:语句块nendcase其中,“分支n”通常都是一些常量表达式。
case语句先对“条件表达式”求值,然后同时并行对各分支项求值并进行比较,这是与if语句最大不同。
比较完成后,与条件表达式值相匹配的分支中的语句被执行。
分支项需要互斥,否则会出现逻辑矛盾。
2009年11月吉林师范大学学报(自然科学版)№.4第4期Journal of Jilin Normal University (Natural Science Edition )Nov.2009收稿日期:2009209222 基金项目:吉林省信息产业厅专项发展基金项目(2007042)作者简介:许德成(19772),男,吉林省辽源市人,现为吉林师范大学信息技术学院讲师,硕士.研究方向:基础电子技术,单片机及可编程逻辑器件技术.基于FPG A 的按键消抖动设计许德成(吉林师范大学信息技术学院,吉林四平136000)摘 要:在研制测量仪表、电子仪器及电子设计的过程中,按键是常用器件,而按键的弹跳现象是数字系统设计中存在的客观问题.这就要求电路具有消抖措施,即对于由于机械弹跳产生的噪声信号经过消抖电路滤除,保证电路能够正确的响应.本文介绍了基于FPG A 的两种消除按键抖动的方法,并给出了相应的VH D L 代码以及仿真图形,从而解决了按键的机械抖动影响,保证电路稳定工作.关键词:机械抖动;仿真图形;电路中图分类号:T N912 文献标识码:A 文章编号:1674238732(2009)04201542030 引言我们通常所用的按键都为机械触点开关.由于机械触点存在弹性作用,当我们按下按键或松开按键时,都不可避免的要在触点闭合及断开的瞬间产生有一连串的键抖动.其按键信号的实际波形如图1所示.图1 按键信号的实际波形 由图1可见,在按键闭合和断开时产生了多个边沿.而在实际中每按一次键,我们只需要一组稳定的上升或下降边沿.所以对于电路中的按键信号,如果我们不滤除抖动的话,还是简单的读取信号的边沿,会引起一次按键被误读多次.这样就会引起电路的误动作.为了保证按一次键电路只有一次正确的响应,即在键闭合稳定时读取键的状态,就要求电路中必须采取滤除抖动的措施.消除案件抖动的方法一般有硬件和软件两种方式.对于硬件方式一般可用RS 触发器作为常用的消抖电路,从根本上解决按键抖动问题.但对于按键较多且从节省硬件资源和易于修改的角度考虑,我们常应用软件滤抖.1 基于计数器模式消抖电路的设计方法应用计数器实现,即采用延时的方法.先正确设定计数的时钟脉冲.当判断到按键按下时计数器开始计数,等计数器计满后再一次判断键的状态.如果仍为按下状态,则认为是按键稳定闭合.这时再针对具体按键信号做相应的处理,否则认为是抖动信号,电路不做任何处理.应用这种方法消除按键抖动,其计数器模值的确定和计数时钟的频率是按键抖动消除的关键问题,因为它们共同决定了延时的时间.如果延时时间过长,就会使正确的按键信号得不到处理;如果延时时间过短,则会将抖动误认为是输入信号,从而导致后电路做出错误处理.一般人按键的时间大于100ms ,抖动时间一般·451·为5ms ~10ms.按这种常规处理,我们一般认为接收到的按键信号持续时间如果小于40ms 则其为抖动信号,如果时间大于40ms 则为正确的按键信号.即让计数器的模值和计数时钟周期的乘积略大于40ms 即可.这样就可以把按下的时间小于40ms 的抖动信号滤掉.其VH D L 代码为:library ieee ;use ieee.std -logic -1164.all ;entity anjian is port (clk ,input :in std -logic ;output :out std -logic );end anjian ;architecture one of anjian is signal a :std -logic ;signal count :integer range 0to 9;beginprocess (clk )beginif input =′0′then count <=0;elsif clk ’event and clk =′1′thenif count =9then count <=count ;else count <=count +1;end if ;end if ;if count =8then a <=′1′;else a <=′0′;end if ;end process ;output <=a ;end one; 由上仿真图可以看出:当信号维持时间小于八个计数时钟周期的时候,认为这时的信号是短时间的抖动信号,所以电路输出不做任何反应.保持原电平不变,后续电路也无需处理.当信号维持时间超过八个计数时钟周期,认为这时定稳定的按键信号,即键稳定的闭合.所以输出一个按键脉冲,以供后续电路处理.2 基于RS 触发器模式的消抖动电路设计在设计中用时钟信号进行采样.对于按键输入信号,当两次采样信号相同时,这是判定已经稳定的按下或放开了按键.触发器相应的被置成0态或1态.如两次采样结果不相同.则触发器维持原输出信号不变.由于直接由触发器输出的信号时间宽度可能过长,所以在触发器后再接一级同步化电路,保证每次输出的信号只占有一个时钟周期的宽度.应用这种方法去滤除抖动,关键是确定采样时钟的频率.保证两次采样的时间间隔能够大于按键的抖动时间,且小于正常按键时的按键稳定闭合时间.其VH D L 代码和仿真如下:library ieee ;use ieee.std -logic -1164.all ;entity dou is port (din ,clk :in std -logic ;dout :out std -logic );end entity dou ;architecture one of dou issignal clr0,clr1,q0,q1,d1,d0:std -logic ;beginclr0<=din ;clr1<=q0;process (clk ,clr0,clr1)beginif clr0=′0′then q0<=′0′;elsif clk ′event and clk =′1′thenq0<=′1′;end if ;if clr1=′0′then q1<=′0′;elsif clk ′event and clk =′1′thenq1<=′1′;end if ;end process ;process (clk )beginif clk ′event and clk =′1′thend0<=q1;d1<=d0;end if ;end process ;dout <=d0and (not d1);end ;·551· 由上仿真图形可以看出:当两次的采样信号结果相同时,这时输出信号才可能发生变化,对应的按键的稳定闭合或断开,当两次的采样信号结果不同时,认为输入的信号定抖动信号.这时电路输出维持原状态不变,同时由于有同步化的处理,输出信号的高电平宽度只为采样时钟的一个周期.3 结束语通过以上的仿真图形可以看出,对于带有机械抖动的按键信号,当它经过消抖电路处理后其输出信号已经将抖动滤除,且输出信号只占有一个时钟信号的周期,从而能使后续电路能够正确的读取键值,做相应的响应,有效的避免了误动作.因此该设计有很大的实际应用意义.参 考 文 献[1]潘 松,黄继业.E DA 技术实用教程[M].北京:科学出版社,20051[2]谭会生,瞿遂春.E DA 技术综合应用实例与分析[M].西安:西安电子科技大学出版社,2004.[3]林明权等.VH D L 数字控制系统设计范例[M].北京:电子工业出版社,2003.[4]方 龙,肖献保,李 威.关于消除按键机械抖动的研究[J ].广西轻工业,2008,1:92.[5]潘永雄,泌河,刘向阳.电子线路CAD 实用教程[M].西安:西安电子科技大学出版社,2004.[6]杨 恒,李爱国,王辉,王新安.FPG A/CP LD 最新实用技术指南[M].北京:清华大学出版社,2005.[7][美]沃尔夫(W olr.w )基于FPG A 的系统设计(英语版)[M].北京:机械工业出版社,2005.[8]王强,曾繁泰,励娜.EPA 工程的理论与实践—S OC 系统蕊片设计[M].北京:电子工业出版社,2004.[9]李国洪,胡辉,沈阳山等.E DA 技术与实验[M].北京:电子工业出版社,2005.Shaking R elease Design on the K eys of FPGAXU De 2cheng(C ollege of In formation T echnology ,Jilin N ormal University ,S iping 136000,China )Abstract :K eys were the comm on elements during the research of measure instrument ,electronic apparatus ,and design of the electronic.The bounce phenomenon of keys was the objective problem in the digital system design.Therefore ,the shaking release measurement was necessary.That is to rem ove the noise signal at the engine bounce through the elimi 2nating the shaking circuit in order to ensure the right response of the circuit.The paper introduced tw o methods of elim 2inating shaking on FPG A and gave the relative VH D L code and the imitating picture.It res olved the in fluence of engine shaking on keys and ensurd the steady w orking of the circuit.K ey w ords :engine shaking ;imitating picture ;circuit·651·。
笔记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这个实验主要有计数器和边缘检查来实现按键消抖,按键功能。
基于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);。
下面是转的一个源码,俺没有细看,有兴趣的看看,讲讲如何// author: Dandy Nee// mail: dandynee@// module: HW KeyScan Module// version:0.1// **************************// all functions are provided as if okay// run at your own risk// **************************//// problem: there is one keyvalue valid// indicator signal needed////------------------------------------------------//// ^ ^ ^ ^ Pull Up// | | | |// x0 >--|--|--|--|-// x1 >--|--|--|--|-// x2 >--|--|--|--|-// x3 >--|--|--|--|-// y0 <--+ | | |// y1 <-----+ | |// y2 <--------+ |// y3 <-----------+//module m_keyscan(clk, //system clkrstb, //system a-rst, low active//clkdiv, //clock divide coef//keyvalue, //returned key//x, //x-row scan outy //y-col scan in);input clk, rstb;input [19:0] clkdiv;output [15:0] keyvalue;output [3:0] x;input [3:0] y;reg [19:0] cnt;always @(posedge clk or negedge rstb) if(~rstb)cnt<=0;elsecnt <= cnt==clkdiv ? 0 : cnt+1;reg clken;always @(posedge clk or negedge rstb) if(~rstb)clken <= 0;elseclken <= cnt==clkdiv;reg [2:0] fsm;always @(posedge clk or negedge rstb) if(~rstb)fsm <= 0;else if(clken)fsm <= fsm+1; //8 statesreg [15:0] keyvalue;reg [3:0] x;always @(posedge clk or negedge rstb) if(~rstb)keyvalue <= 0;else if(clken)case(fsm)0: beginx <= 4'b1110;end1: beginkeyvalue[3:0] <= ~y;end2: beginx <= 4'b1101;end3: beginkeyvalue[7:4] <= ~y;end4: beginx <= 4'b1011;end5: beginkeyvalue[11:8] <= ~y;end6: beginx <= 4'b0111;end7: beginkeyvalue[15:12] <= ~y;endendcaseendmodule本程序做的只是按键单纯挂在IO上,并不是行列扫描的。
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。
10_基于FPGA进⾏按键消抖10_基于FPGA进⾏按键消抖实验原理计数器型消抖电路:计数器型消抖电路(⼀) 计数器型消抖电路(⼀)是设置⼀个模值为(N+1)的控制计数器,clk在上升沿时,如果按键开关key_in='1',计数器加1,key_in='0'时,计数器清零。
当计数器值为2时,key_out输出才为1,其他值为0时。
计数器值为N时处于保持状态。
因此按键key_in持续时间⼤于N个clk时钟周期时,计数器输出⼀个单脉冲,否则没有脉冲输出。
如果按键开关抖动产⽣的⽑刺宽度⼩于N个时钟周期,因⽽⽑刺作⽤不可能使计数器有输出,防抖动⽬的得以实现。
clk的时钟周期与N的值可以根据按键抖动时间由设计者⾃⾏设定。
下图为N为3的波形仿真图,当按键持续时间⼤于3个时钟周期,计数器输出⼀个单脉冲,其宽度为1个时钟周期,⼩于3个时钟周期的窄脉冲⽤作模拟抖动⼲扰,从图1可以看出,抖动不能⼲扰正常的单脉冲输出。
该⽅法的特点是能很好消除按键抖动产⽣的窄脉冲,还可以滤去⼲扰、噪⾳等其他尖峰波,但遇到脉宽⼤于N个Tclk时钟周期的⼲扰、噪⾳等时会有输出从⽽产⽣误操作,⽽对于按键操作要求按键时间必须⼤于N个Tclk时钟周期,否则按键操作也没有输出。
计数器型消抖电路(⼆) 计数器型消抖电路(⼆)是控制计数器⼯作⼀个循环周期(N+1个状态),且仅在计数器为0时输出为"1"。
电路设计了连锁控制设施。
在计数器处于状态0时,此时若有按键操作,则计数器进⼊状态1,同时输出单脉冲(其宽度等于时钟周期)。
计数器处于其他状态,都没有单脉冲输出。
计数器处于状态N时,控制en='0',导致计数器退出状态N,进⼊状态0。
计数器能否保持状态0,取决于⼈⼯按键操作,若按键key_in='1',控制en='1'(计数器能正常⼯作),key_in='0',计数器状态保持。
实验5 按键消抖1. 实验目的1. 掌握QuartusII的硬件描述语言设计方法2. 了解同步计数器的原理及应用3. 设计一个带使能输入、进位输出及同步清零的增1四位N (N<16)进制同步计数器2. 准备知识在按键使用的过程中,常常遇到按键抖动的问题,开关在闭合(断开)的瞬间,不能一接触就一直保持导通(断开),因为开关的机械特性,重要经历接触-断开-再接触-再断开,最终稳定在接触位置,这就是开关的抖动,即虽然只是按下按键一次然后放掉,结果在按键信号稳定前后,竟出现了一些不该存在的噪声,这样就会引起电路的误动作。
在很多应用按键的场合,要求具有消抖措施。
按键抖动与开关的机械特性有关,其抖动期一般为5-10ms。
图5.1 按键电平抖动示意图按键的消除抖动分为硬件消除抖动和软件消除抖动。
硬件消除抖动一般采用滤波的方法,通常在按键两端并联一个1~10u左右的电容,有时这样也不能完全消除按键的抖动。
软件消除抖动的方法有多种,常用的是延时扫描和定时器扫描。
延时扫描其原理为:检测到按键操作后延时一端时间(如10ms)后,再检测是否为仍然为同样的按键操作状态,如果相同,就认为是进行了按键操作,然后对该操作进行相应的处理。
定时器扫描的原理是:每隔一端时间(几毫秒)扫描一次键盘,如果连续两次(或3次)的所获得的按键状态相同,就输出按键状态,然后再对这种按键状态进行处理,这里的扫描时间间隔和连续判断按键状态的次数是有关系的,一般总时间要大于按键的抖动期。
如果总时间太长,则感觉按键迟钝,太短可能不能完全消除抖动,要根据实际的情况合适的选择。
在实际电路设计中,经常采用的是软硬件相结合对按键进行消除抖动的处理方法。
本实验采用的方法:实验箱按键的硬件电路是共阳极电路,按下按键时输出到FPGA管脚的电平为低电平,松开按键时为高电平。
我们采用5ms的定时器扫描FPGA管脚电平,如果连续3次为低电平时,存储连续按键状态的次数CNT的值加1,直到该计数值等于10(或再大一些),就不再累加(防止长按该值溢出而重新计数),此时认为按键已稳定,输出按键操作标志;在该过程中,一旦FPGA管脚电平为低电平就对CNT复位清零并同时对按键操作标志位复位,即一个异步复位。
第23卷第3期2006年6月吉林化工学院学报JOURNALOFJILlNlNSTlTUTE0FCHEMICALTECHNOLOGYV01.23No.3Jun.2006文章编号:1007.2853(2006)03—0053一03基于FPGA器件的消除按键抖动方法研究谷长龙,李小英(湖南大学计算机与通信学院,湖南长沙4lOOl2)摘要:按键在数字电路设计中经常用到,但是按键是机械触点,当机械触点断开、闭合时会有抖动,为使每一次按键只做一次响应.就必须考虑去除抖动.本文介绍了数字电路设计中的按键抖动信号以及进行消除的三种常用方法,并用vHDL编程,用MAxPLusⅡ10.1仿真,用Alter公司的Flexl0K芯片EPFlOK20TLl44。
4来实现.关键词:按键抖动;VHDL;FPGA;MAxPLusⅡlO.1;仿真中图分类号:TN79文献标识码:A在数字电路设计中,经常遇到抖动信号的处理问题.抖动信号可以分为两种:一种是时间很短的干扰信号,如高频毛刺;另一种是时间较长的干扰信号.如按键抖动.对于高频毛刺,由于时间很短,只有几个纳秒,不能满足触发器的建立与保持时间,可以用一个D触发器去读带毛刺的信号,利用D触发器对输人信号的毛刺不敏感的特点,去除信号中的毛刺.消除高频毛刺还有很多别的方法,这里不做讨论.本文主要说明按键抖动及其消除.由于按键是机械触点,当机械触点断开、闭合时会有抖动,为使每一次按键只做一次响应,就必须考虑去除抖动.在按键按下或松开时存在抖动.根据一般人按键的速度小于10Hz(每秒小于10次),所以按键时间大于100ms,按占空比50%计算,按下的时间大于50nm按这种约定,笔者认为按下的时间小于50ms的为抖动信号,按下的时间大于50ms的是按键信号.对于延迟时间较长的抖动信号,电路设计中可以在输出端用积分电路(如Rc滤波器)滤波实现.在纯数字电路设计中,可以用类似的方法来消除按键抖动.下面介绍几种常用的实现方法.1用计数器实现设计一个增减计数器,引入一个采样脉冲信号(cLK),对输入信号D进行采样并且对clk进行计数:若D=l作加法计数,直到输出达到全部为1停止计数,并且使消抖信号(OuTcLK)输出l;若D=0作减法计数,直到输出达到全部为O停止计数,并且使消抖信号(OuTcLK)输出o.也就是说,如果连续采样到N(计数器的模值)个或N个以上的1时,OuTCLK输出1;如果连续采样到N(计数器的模值)个或N个以上的0时,OuTcLK输出0.依据上面的约定,按下的时间大于50ms的是按键信号,采样脉冲信号周期(CLK)若取12.5ms,N取4,就可以把按下的时间小于50ms的抖动信号滤波去触掉.显然,抖动信号的脉冲宽度和采样脉冲信号周期的大小决定计数器的模值.省略具体的VHDL语言描述实现,在MAx—PLuSⅡ10.1下仿真的结果如图1所示.图1用计数器实现按键抖动的仿真波形收稿日期:2006一05—22作者简介:谷长龙(1973一),男,湖南长沙人,湖南大学讲师,主要从事数字电路与EDA设计方面的研究 万方数据吉林化工学院学报2用移位寄存器实现通过采样脉冲信号(cLK)把输人信号D送人移位寄存器,检查寄存器的内容:如果全为l,消抖信号(OuTcLK)输出1;如果全为o,消抖信号(OUTCLK)输出0.同样的,若CLK取12.5ms,采用4位的移位寄存器,就可以把按下的时问小于50ms的抖动信号滤波去触掉.如果clk频率固定,抖动信号脉冲宽度增大,就必须增加移位寄存器的位数,这将增加系统的开销.省略具体的VHDL语言描述实现,在MAXPLUSⅡ10.1下仿真的结果如图2所示.图2用移位寄存器实现按键抖动的仿真波形3用D触发器延时实现为便于分析,这种方法用原理图实现,具体电路如图3所示.^HD±学型芷—三≥叫T£m图3用D触发器延时实现按键抖动的原理图这种方法的基本原理是用CLK对D采样,再送入RS触发器,利用RS触发器的置l、置O功能达到消抖目的.从图中可以看出:在CLK作用下,如果连续两次采样到的D值都是1,将使s=l、R=o,触发器置1,消抖信号OuTcLK输出l;在cLK作用下,如果连续两次采样到的D值都是o,将使s=o,R=1,触发器置0,消抖信号0uTCLK输出o.对于周期大于50ms的按键信号,只要合理选择CLK的周期,能够达到消抖目的.例如,cLK周期取6ms,可以对按键信号采样8次以上,而对于4ms以下的不稳定干扰,最多只采样一次.在MAxPLuSⅡ10.1下仿真的结果如图4所示.图4用D触发器延时实现按键抖动的仿真波形从波形图上可以清楚的看到三种方法都可以将抖动信号消除.但是消抖信号输出OuTcLK时间宽度较大,如果要把它作为计数器的脉冲输入将可能导致超过1次以上的计数错误.为了得到输出脉宽相当于CLK一个时钟周期宽度的输出信号,可以在输出端串接一个微分环节(WEIFEN.GDF).微分(上升沿微分)环节的原理图如图5所示.图5微分(上升沿微分)环节的原理图将xIAOD0u1的输出信号ouTcLK经过微分环节(wEIFEN.GDF)微分处理,如图6所示.图6将消抖信号进行微分处理的原理图得到的仿真波行如图7所示.图7将消抖信号进行微分处理的仿真波形从波行图可以看到,抖动信号D的抖动已被消除,消抖输出0uTcLK经过微分后,输出wFOUT的高电平脉宽与CLK一个时钟周期相等,可以满足准确计数的要求.4结论本文介绍了基于FPGA的三种按键抖动的消除方法,有详细的实现过程,每种方法都用MAxPLusⅡ10.1进行了仿真验证.但是消抖信号输出OUTCLK时间宽度较大,为了得到输出脉宽相当于CLK一个时钟周期宽度的输出信号, 万方数据 万方数据。
FPGA按键防抖动,最精简的写法只有10行
最近学了FPGA 一段时间,想自己做个真实的东西,笔者也是务实求真的人,呵呵。
首先就选择了一个数字钟,当我昨晚了计数器模块,做按键校准的时候,就发现按键抖动的很厉害,没有C 语言做防抖动那么简单,因此我参考了网上很多博主的观点,总结了自己认为最简单,最精简的一个写法,如下:进程模块内代码只有10行。
哈哈
reg key_reg1,key_reg2,key_out;
always @( posedge clk)//CLK 50M
begin
count2<=count2+1;
if(count2==500000)
begin
key_reg1<=key1;
count2<=0;
end
key_reg2<=key_reg1;
key_out<=key_reg2&(!key_reg1);
end
意思为定义2个寄存器,存储按键在2个周期内的数据,计数器是决定按键的采样频率,如果我们把按键的采样频率调高,那么按键就会有2次相应,我试过吧计数器去掉,但是一直都是双数增加,很让我费解,在苦思冥想之际,悟出了可以通过延时,吧后面松手的一个电平跳变滤掉,哈哈!!顿时给大家分享下最简单的防抖动,
key1 是低电平按下,当按下的时候, key_out输出的是一个高电平。
这个需要大家注意。
如有bug 希望大家抛砖。
阐述基于FPGA的按键抖动的消除方法我们在进行数字电路的设计的过程中,经常会碰到信号抖动相关的问题。
抖动信号大致分为两类:一类是时间极短的干扰信号(比如毛刺);另一类是时间较长的干扰信号(如本文所研究的按键抖动问题)。
对于第一类干扰信号——毛刺,它的时间极短,通常只有几纳秒,不能满足触发器的建立时间与保持时间,因此我们可以用一个D触发器去读带毛刺的信号,由于D触发器具有对毛刺不敏感的特点,可以去除信号中的毛刺,达到消除抖动的效果(消除毛刺的方法很多,在这里不做讨论,本文重点说明按键抖动的消除及其代码设计)。
在数字电路设计中,按键通常为一个个具有弹性的机械触点开关,其开启或者闭合的瞬间都会产生按键抖动,实际波形如图1所示:由图1可知,在按键闭合和断开的瞬间,我们往往只需要一组稳定的上升边沿和下降边沿,但实际上却产生了若干个边沿。
所以,在实际电路中,我们仅仅按动按键,简单地读取信号的边沿,却不滤除抖动,会导致一次按键操作被误读多次,从而引起电路的误动作。
为了达到一次按键操作得到一次正确的响应的目的(在按键闭合或者断开),信号稳定的状态下读取此时按键的状态,就必须在电路中采取消除抖动的措施。
在纯数字电路设计中,下面介绍几种消除按键抖动的常用实现方法。
1 设计硬件消抖电路(硬件方法)设计一个具有延时作用的滤波电路或者经常用到的单稳态电路等硬件电路,来消除按键的抖动(避免抖动时间)。
图2所示的电路,即为典型的滤波延时消抖电路,S为按键,Di为CPU数据线。
当按键S未闭合时,与非门的输入电压Vi(即电容的端电压)为0,从而输出电压Vo为1。
我们按下按键S,电容C的端电压不会发生突变,充电延迟时间取决于R1、R2和C值的大小,当电容端电压在充电时间内未达到与非门的开启电压,将不会改变门的输出电压;当电容端电压大于门的开启电压时,与非门的输出Vo发生改变,即输出为0(我们在数字电路的设计过程中,为了避开按键抖动的影响,需要使充电延时大于或等于100ms)。
【⿊⾦原创教程】【FPGA那些事⼉-驱动篇I】实验⼆:按键模块①-消抖实验⼆:按键模块① - 消抖按键消抖实验可谓是经典中的经典,按键消抖实验虽曾在《建模篇》出现过,⽽且还惹来⼀堆⿇烦。
事实上,笔者这是在刁难各位同学,好让对⽅的惯性思维短路⼀下,但是惨遭⼝⽔攻击 ... ⾯对它,笔者宛如被甩的男⼈,对它⼜爱⼜恨。
不管怎么样,如今 I’ll be back,笔者再也不会重复⼀样的悲剧。
按键消抖说傻不傻说难不难。
所谓傻,它因为原理不仅简单(就是延迟⼏下下⽽已),⽽且顺序语⾔(C语⾔)也有⽆数不尽的例⼦。
所谓难,那是因为⼈们很难从单⽚机的思维跳出来 ... 此外,按键消抖也有许多细节未曾被⼈重视,真是让⼈伤⼼。
按键消抖⼀般有3段操作:l 检测电平变化;l 过滤抖动(延迟);l 产⽣有效按键。
假设C语⾔与单⽚机的组合想要检测电平变化,它们⼀般是利⽤if查询或者外部中断。
事后,如果这对组合想要过滤抖动,那么可以借⽤for 延迟的⼒量,⼜或者依赖定时中断产⽣精明的延迟效果。
反观有效案件的产⽣,这对组合视乎⽽外钟情“按下有效”似的 ... 不管怎么样,C语⾔与单⽚机这对组合在处理按键的时候,它们往往会错过⼀些黄⾦。
“黄⾦?”,读者震撼道。
所谓黄⾦时间就是电平发⽣变化那⼀瞬间,还有消抖(延迟)以后那⼀瞬间。
按键按下期间,按键的输⼊电平故会发⽣变化,如果使⽤if查询去检测,结果很容易浪费单⽚机的处理资源,因为单⽚机必须⼀直等待 ... 换之,如果反⽤外部中断,中断寻址也会耽误诺⼲时间。
假设C语⾔与单⽚机这对组合挨过电平检测这起难关,余下的困难却是消抖动作。
如果利⽤for循环实现去消抖,例如 Delay_ms(10) 之类的函数。
For循环不仅计数不紧密,⽽且还会⽩⽩浪费单⽚机的处理资源。
定时中断虽然计数紧密,但是中断触发依然也会产⽣诺⼲的寻址延迟。
补上,所谓寻址延迟是处理器处理中断触发的时候,它要事先保护现场之余,也要寻址中断处理⼊⼝,然后执⾏中断函数,完后回复现场,最后再返回当前的⼯作。
FPGA学习按键消抖实验Verilog代码modulesw_de(clk,rst_n,sw1_n,sw2_n,sw3_n,led_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<=3'b111;else key_rst <= {sw3_n ,sw2_n ,sw1_n};reg[2:0] key_rst_r;//每个时钟周期的上升沿将low_sw信号锁存到low_sw_r中always @ (posedge clk or negedge rst_n)if(!rst_n) key_rst_r<=3'b111;else key_rst_r<=key_rst;//当寄存器key_rst由1变为0时,led_an的值变为高,维持一个时钟周期wire[2:0]key_an=key_rst_r&(~key_rst);//-----------------------------------------------------reg[19:0] cnt;//计数寄存器always @ (posedge clk or negedge rst_n)/*always块clk时钟的上升沿和rst_n复位信号的下降沿触发执行*/if (!rst_n) cnt<=20'd0;else if (key_an) cnt<=20'd0;else cnt<=cnt+1'b1;reg[2:0] low_sw;always @ (posedge clk or negedge rst_n)if (!rst_n) low_sw<=3'b111;else if(cnt==20'hfffff)/*满20ms,将按键值锁存到寄存器low_sw中20'hfffff='d1048575 t=1/48000000*1048575=0.021s*/ low_sw<={sw3_n,sw2_n,sw1_n};/*将按键sw3_n,sw2_n,sw1_n,用位拼接符{}拼接为一个三位的数传给low_sw*///-----------------------------------------------------------reg[2:0] low_sw_r; //每个时钟周期的上升沿将low_sw信号锁存到low_sw_ralways @ (posedge clk or negedge rst_n)if (!rst_n) low_sw_r<=3'b111;else low_sw_r<=low_sw;//当寄存器low_sw由1变为0时,led_ctr1的值变为高,维持一个时钟周期wire[2:0] led_ctr1=low_sw_r[2:0]&(~low_sw[2:0]);//找出变化的键存到led_ctr1中reg d1;reg d2;reg d3;always @ (posedge clk or negedge rst_n)if (!rst_n)begind1<=1'b0;d2<=1'b0;d3<=1'b0;endelse begin //某个按键值变化时,LED将亮灭翻转 if (led_ctrl[0]) d1<=~d1;if (led_ctrl[1]) d2<=~d2;if (led_ctrl[2]) d3<=~d3;endassign led_d3=d1?1'b1:1'b0; assign led_d2=d2?1'b1:1'b0; assign led_d1=d3?1'b1:1'b0; endmodule。
基于FPGA的按键消抖电路设计方法的研究于晶;杨晓慧;黄勇【摘要】采用了VHDL语言编程的设计方法,通过FPGA来实现按键消抖的硬件电路。
论述了基于计数器、RS触发器和状态机3种方法来实现按键消抖电路,并给出仿真结果。
通过下载到CycloneEP1C6T144芯片中进行验证,表明这3种方法设计的消抖电路都能够实现电路功能,其中有限状态机的方法更能确保每一次按键操作后准确输出按键确认信号,且性能稳定。
%In order to solve key jitter of FPGA system,use the design method of VHDL language programming to realize key-jitter.Discusses three methods base on counter,RS flip-flop and state machine with simulation and analysis.Being verified by theCycloneEP1C6T144,the three methods all able to achieve the circuit function,can guarantee a quick keypress once every time the response,and have stable property.The main innovation is using the most simple programming to realize key-jitter.【期刊名称】《电子设计工程》【年(卷),期】2011(019)022【总页数】3页(P1-3)【关键词】按键消抖;计数器;RS触发器;状态机【作者】于晶;杨晓慧;黄勇【作者单位】长春理工大学,吉林长春130000;长春理工大学,吉林长春130000;吉林博安消防设备有限公司,吉林长春130000【正文语种】中文【中图分类】TP274通常所用的按键都为机械触点开关,由于机械触点存在弹性作用,当按下按键或松开按键时,都不可避免地要在触点闭合及断开的瞬间产生一连串的键抖动。
modulekey_scan(
inputclk,
inputrst_n,
input [3:0] row, // 矩阵键盘行
output reg [3:0] col, // 矩阵键盘列
output reg [7:0] key_val // 键盘值
);
//++++++++++++++++++++++++++++++++++++++
// 分频部分开始
//++++++++++++++++++++++++++++++++++++++
reg [19:0] cnt; // 计数子
always @ (posedgeclk, negedgerst_n)
if (!rst_n)
cnt<= 0;
else
cnt<= cnt + 1'b1;
wirekey_clk = cnt[19]; // (2^20/50M = 21)ms //--------------------------------------
// 分频部分结束
//--------------------------------------
//++++++++++++++++++++++++++++++++++++++
// 状态机部分开始
//++++++++++++++++++++++++++++++++++++++
// 状态数较少,独热码编码
parameter NO_KEY_PRESSED = 6'b000_001; // 没有按键按下parameter SCAN_COL0 = 6'b000_010; // 扫描第0列parameter SCAN_COL1 = 6'b000_100; // 扫描第1列parameter SCAN_COL2 = 6'b001_000; // 扫描第2列parameter SCAN_COL3 = 6'b010_000; // 扫描第3列parameter KEY_PRESSED = 6'b100_000; // 有按键按下
reg [5:0] current_state, next_state; // 现态、次态
always @ (posedgekey_clk, negedgerst_n)
if (!rst_n)
current_state<= NO_KEY_PRESSED;
else
current_state<= next_state;
// 根据条件转移状态
always @ *
case (current_state)
NO_KEY_PRESSED : // 没有按键按下if (row != 4'hF)
next_state = SCAN_COL0;
else
next_state = NO_KEY_PRESSED;
SCAN_COL0 : // 扫描第0列if (row != 4'hF)
next_state = KEY_PRESSED;
else
next_state = SCAN_COL1;
SCAN_COL1 : // 扫描第1列if (row != 4'hF)
next_state = KEY_PRESSED;
else
next_state = SCAN_COL2;
SCAN_COL2 : // 扫描第2列if (row != 4'hF)
next_state = KEY_PRESSED;
else
next_state = SCAN_COL3;
SCAN_COL3 : // 扫描第3列if (row != 4'hF)
next_state = KEY_PRESSED;
else
next_state = NO_KEY_PRESSED;
KEY_PRESSED : // 有按键按下
if (row != 4'hF)
next_state = KEY_PRESSED;
else
next_state = NO_KEY_PRESSED;
endcase
regkey_pressed_flag; // 键盘按下标志
reg [3:0] col_val, row_val; // 列值、行值
// 根据次态,给相应寄存器赋值
always @ (posedgekey_clk, negedgerst_n)
if (!rst_n)
begin
col<= 4'h0;
key_pressed_flag<= 0;
end
else
case (next_state)
NO_KEY_PRESSED : // 没有按键按下begin
col<= 4'h0;
key_pressed_flag<= 0; // 清键盘按下标志
end
SCAN_COL0 : // 扫描第0列col<= 4'b1110;
SCAN_COL1 : // 扫描第1列col<= 4'b1101;
SCAN_COL2 : // 扫描第2列col<= 4'b1011;
SCAN_COL3 : // 扫描第3列col<= 4'b0111;
KEY_PRESSED : // 有按键按下begin
col_val<= col; // 锁存列值
row_val<= row; // 锁存行值
key_pressed_flag<= 1; // 置键盘按下标志
end
endcase
//--------------------------------------
// 状态机部分结束
//--------------------------------------
//++++++++++++++++++++++++++++++++++++++
// 扫描行列值部分开始
//++++++++++++++++++++++++++++++++++++++
always @ (posedgekey_clk, negedgerst_n)
if (!rst_n)
key_val<= 4'h0;
else
if (key_pressed_flag)
case ({col_val, row_val})
8'b1110_1110 :key_val<= 8'h01;
8'b1110_1101 :key_val<= 8'h02;
8'b1110_1011 :key_val<= 8'h03;
8'b1110_0111 :key_val<= 8'h04;
8'b1101_1110 :key_val<= 8'h05;
8'b1101_1101 :key_val<= 8'h06;
8'b1101_1011 :key_val<= 8'h07;
8'b1101_0111 :key_val<= 8'h08;
8'b1011_1110 :key_val<= 8'h09;
8'b1011_1101 :key_val<= 8'h10;
8'b1011_1011 :key_val<= 8'h11;
8'b1011_0111 :key_val<= 8'h12;
8'b0111_1110 :key_val<= 8'h13;
8'b0111_1101 :key_val<= 8'h14;
8'b0111_1011 :key_val<= 8'h15;
8'b0111_0111 :key_val<= 8'h16; default: key_val=8'h00;
endcase
endmodule。