FPGA学习按键消抖实验Verilog代码

合集下载

按键消抖实验

按键消抖实验

基于verilog按键消抖设计Aaron malone关于键盘的基础知识,我就以下面的一点资料带过,因为这个实在是再基础不过的东西了。

然后我引两篇我自己的博文,都是关于按键消抖的,代码也正是同目录下project里的。

这两篇博文都是ednchina的博客精华,并且在其blog 首页置顶多日,我想对大家会很有帮助的。

键盘的分类键盘分编码键盘和非编码键盘。

键盘上闭合键的识别由专用的硬件编码器实现,并产生键编码号或键值的称为编码键盘,如计算机键盘。

而靠软件编程来识别的称为非编码键盘。

在单片机组成的各种系统中,用的最多的是非编码键盘。

也有用到编码键盘的。

非编码键盘有分为:独立键盘和行列式(又称为矩阵式)键盘。

按键在闭合和断开时,触点会存在抖动现象:从上面的图形我们知道,在按键按下或者是释放的时候都会出现一个不稳定的抖动时间的,那么如果不处理好这个抖动时间,我们就无法处理好按键编码,所以如何才能有效的消除按键抖动呢?让下面的两篇博文日志给你答案吧。

经典的verilog键盘扫描程序从最基础的分频程序开始,但看到这个键盘扫描程序后,直呼经典,有相见恨晚的感觉,还想说一句:威百仕( VibesIC ),我很看好你!WHY?待我慢慢道来,这个程序的综合后是0error,0warning。

想想自己编码的时候那个warning是满天飞,现在才明白HDL设计有那么讲究了,代码所设计的不仅仅是简单的逻辑以及时序的关系,更重要的是你要在代码中不仅要表现出每一个寄存器,甚至每一个走线。

想想我写过的代码,只注意到了前者,从没有注意过后者,还洋洋自得以为自己也算是个高手了,现在想来,实在惭愧啊!学习学习在学习,这也重新激发了我对HDL设计的激情,威百仕给了我一个方向,那我可要开始努力喽!废话说了一大堆,看程序吧:(本代码经过ise7.1i综合并下载到SP306板上验证通过)//当三个独立按键的某一个被按下后,相应的LED被点亮;再次按下后,LED 熄灭,按键控制LED亮灭经过一次20ms的采样后判定为键盘按下。

verilog按键消抖原理

verilog按键消抖原理

verilog按键消抖原理(原创实用版)目录1.按键消抖的原理2.Verilog 实现按键消抖的方法3.按键消抖的具体设计4.总结正文一、按键消抖的原理按键消抖是指在按键输入过程中,由于机械特性的影响,导致按键在按下或松开的瞬间会产生抖动,即电平从一个状态转换到另一个状态时,会在短时间内出现多次变化。

为了消除这种抖动,需要设计一种按键消抖电路或算法,确保输入信号的稳定性。

二、Verilog 实现按键消抖的方法Verilog 是一种硬件描述语言,可以用来设计和验证数字电路。

在Verilog 中实现按键消抖,主要可以通过计数器和寄存器来完成。

当按键输入发生变化时,计数器清零;当按键输入稳定时,计数器累加到一定值,此时输出稳定信号。

三、按键消抖的具体设计以下是一个基于 Verilog 的按键消抖设计示例:```verilogmodule keyjitter(clk, keyin, keyout);input clk; // 50MHz clock ininput keyin;output keyout;reg [22:0] counthigh;reg [22:0] countlow;reg keyreg;always @(posedge clk) beginif (keyin == 1"b0) begincountlow <= countlow - 1;end else begincountlow <= 23"h000000;endendalways @(posedge clk) beginif (keyin == 1"b1) begincounthigh <= counthigh + 1;end else begincounthigh <= 23"h000000;endendalways @(posedge clk) beginif (counthigh == 23"h250000) beginkeyreg <= 1"b1;end else if (countlow == 23"h250000) beginkeyreg <= 1"b0;end else beginkeyreg <= keyreg;endendendmodule```在这个设计中,我们使用了两个计数器,分别记录按键输入的高电平和低电平。

vivado按键消抖原理

vivado按键消抖原理

vivado按键消抖原理按键消抖是指在数字电路中,当按键按下或释放时,由于按键机械开关的特性,会导致电路出现不稳定的信号状态。

这种不稳定状态可能会导致错误的触发,例如出现多次触发或漏触发。

因此,为了确保按键信号的稳定性和可靠性,需要进行按键消抖处理。

按键消抖的原因主要有两个方面。

首先,按键机械开关的接触面存在微小的弹跳现象,当按键按下或释放时,接触面会在短时间内反复接触和分离,导致电路信号出现多次变化。

其次,由于电路中存在的噪声干扰,也会使得按键信号产生抖动。

为了解决按键消抖问题,可以采用硬件和软件两种方法。

硬件方法主要通过添加滤波电路或使用稳定的按键开关来消除按键弹跳现象。

滤波电路可以通过RC电路或者使用专用的按键消抖芯片来实现。

而软件方法主要通过在数字电路中添加按键消抖算法来处理按键信号。

在Vivado中,按键消抖可以通过使用状态机来实现。

状态机是一种用于描述系统行为的模型,可以根据输入信号的状态变化来改变系统的状态和输出。

在按键消抖中,可以使用状态机来检测按键信号的变化,并根据一定的状态转换规则来消除按键弹跳现象。

具体实现时,可以将按键信号作为输入,将按键状态和输出作为状态机的状态和输出。

当按键信号发生变化时,状态机会根据一定的状态转换规则进行状态转换,并输出消抖后的按键信号。

常用的状态转换规则包括按键按下时状态转换为按下状态,按键释放时状态转换为释放状态,以及连续按键时状态不变。

在Vivado中,可以使用Verilog或VHDL等硬件描述语言来编写状态机代码。

首先,需要定义状态机的输入、输出和状态变量,并初始化各个变量的初始值。

然后,需要编写状态转换规则和输出逻辑,根据输入信号的状态变化来改变状态和输出。

最后,需要将状态机代码综合生成对应的逻辑电路,并进行仿真和验证。

总结起来,按键消抖是数字电路设计中常见的问题,为了确保按键信号的稳定性和可靠性,需要进行按键消抖处理。

在Vivado中,可以使用状态机来实现按键消抖,通过定义状态转换规则和输出逻辑,消除按键弹跳现象。

Verilog写的按键消抖程序

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按键消抖的理解

Verilog按键消抖的理解

Verilog按键消抖的理解按键在按下时会产生抖动,释放时也会产生抖动,所以在设计键盘扫描程序时必须考虑按键的消抖,我们一般只考虑按下时的抖动,而放弃对释放时抖动的消抖。

抖动时间一般为20ms左右。

按下的最终结果是低电平'在单片机设计的的按键去抖思路是:检测到按下时延时20ms,再检测,如果状态仍为按下,贝U确认是按下的;如果状态为弹起的,则确认是干扰,无按键按下。

图1 按键抖动特性有一个概念要理一下,按键按下时会有抖动,也就是说我们其实只按一次,但是实际产生的&ldquo; 按下&rdquo; 却是许多次的,这些许多次集中在这20ms 里。

我们按的只是一次,而实际却产生了许多次,那么就必须滤除其他的次数。

单片机为了得到真正的&ldquo; 按下&rdquo;,通过延时20ms,把其他的&ldquo;按下&rdquo; (也就是抖动)给滤除了。

然后再次判断是否有按下,因为有的时候干扰很大。

而在FPGA中,基于下面的程序,理解如下:在这个程序里检测按键是否按下的方法是脉冲边沿检法。

而在单片机里是判断是否为低电平的方法(那么在FPGA中可不可以也用这个方法呢?)第一次检测到后,启动20ms 计数器,时间到后再检测。

这里的检测方法跟脉冲边沿检测法有异曲同工之处,FPGA过20ms检测按键是否按下,存储检测到的值,并且按位取反与前一个20ms检测的值相与,得到一个值,如果为1,则判断按键按下,否则则无按下。

所以跟单片机按键扫描的原理是一样的,不同的是检测方法不一样。

图2 FPGA 按键的理解示意图其中key_an 寄存器的功能是检测第一次的 &ldquo;按 下&rdquo;,是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的消抖设计按键开关是各种电子设备不可或缺的人机接口。

在实际应用中,很大一部分的按键是机械按键。

在机械按键的触点闭合和断开时,都会产生抖动,为了保证系统能正确识别按键的开关,就必须对按键的抖动进行处理。

在系统设计中,有各种各样的消除按键抖动的设计方法,硬件电路和软件设计都很成熟。

不过我们这里要从另外一个角度来讨论按键的消抖,并给出一个用verilog给出一个具体的实现。

首先,看一个普通的机械按键的触点在闭合与断开时的波形(用示波器抓取)。

下面的四张图都是按键在闭合的时候抓到的波形。

可以看到两个明显的趋势:1. 按键在几个us之内就可以达到稳定状态,从高电平转换到底电平;2. 在高电平转换到低电平的过程中,触点有非常明显的抖动。

下面的两张图是按键在断开的时候抓到的波形。

也可以看到两个明显的趋势:1. 按键的变化趋势比较缓慢,从低电平变为高电平需要大概10~20ms的时间;2. 按键断开时没有闭合时那么大的抖动下面两张图是用手迅速闭合按键然后就断开时,按键的输出波形。

在处理按键抖动的程序中,必须同时考虑消除闭合和断开两种情况下的抖动。

所以,对于按键消抖的处理,必须按最差的情况来考虑。

我们从上面的图上可以看到,按键输出的信号的跳变时间(上升沿和下降沿)最大是在20ms左右。

按键一次闭合最短的时间大概是120ms 左右。

如果我们把按键的输出做为一个时钟域(时钟频率未知,但信号的slow rate是已知的,既最大20ms左右)的信号,用另外一个时钟来采集这个按键的输出,则就可以把按键的消抖归结为一个最基本的CDC问题来处理。

而问题的核心是如何确定采集时钟的频率。

假设采集时钟的周期小于20ms,那么,采集时钟就有可能两次采到按键断开时的不。

基于FPGA的抖动及消抖的方法

基于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);。

自动售货机fpga与verilog代码

自动售货机fpga与verilog代码

深圳大学课程论文题目设计一个自动售货机成绩专业课程名称、代码年级姓名学号时间年月设计一个自动售货机基本要求:可以对3种不同种类的货物进行自动售货,价格分别为A=1.00, B=1.50, C=1.60。

售货机可以接受1元,5角,1角三种硬币(即有三种输入信号IY,IWJ,IYJ),并且在7段数码管(二位代表元,一位代表角)显示已投入的总钱数,选择货物的输入信号Ia,Ib,Ic,输出指示信号为Sa, Sb ,Sc 分别表示售出相应的货物,同时输出的信号yuan, jiao代表找零,并显示在7段数码管上。

规格说明:1.按一下button1按钮,表示购买货物A,第一个LED灯亮;按两下button1按钮,表示购买货物B,第二个LED灯亮;按三下button1按钮,表示购买货物C,第三个LED灯亮。

2.LED灯亮后,开始输入硬币。

button2按一下,输入1元,按两下,输入两元,以此类推;Button3按一下输入5角,按两下代表1元,以此类推;button4按一下输入1角,按两下输入2角,以此类推。

7段数码管显示已投入的总钱数,再次按下button1键,7段数码管显示找零数目,同时指示货物的LED灯熄灭。

3.本实验使用FPGA板:Sparant6XC6SLX16CSG324C(建project时,需要选择该芯片的型号)。

论文要求:1.论文的格式采用标准的深圳大学以论文、报告等形式考核专用答题纸;2.论文中应完包括ASM图, 以及VerilogHDL代码,并且代码应该与ASM图相一致.3.论文应包括该电路的VerilogHDL仿真.4.论文应该有FPGA开发的布局布线后结果.5.报告应该有实验成功的开发板截图.1.状态图售货机FSM本设计需要2个状态机,一个是售货机工作状态机,一个是按键消抖用的FSM2. Verilog 代码:`timescale 1ns / 1psmodule automat(clk_in,reset,cs,Led,seg,button1_in,button2_in,button3_in,button4_in );input clk_in,reset;input button1_in,button2_in,button3_in,button4_in;output [2:0] Led;output [3:0] cs;output [7:0] seg;reg [7:0] seg;reg [3:0] cs;reg [2:0] Led;reg [6:0] total;reg [4:0] state;reg [2:0] state1,state2,state3,state4;reg [4:0] cnt1,cnt2,cnt3,cnt4;reg button1,button2,button3,button4;reg [6:0] ones,tens;reg clk;reg [23:0] divcnt;parameter wait0 = 3'b001;parameter delay = 3'b010;parameter wait1 = 3'b100;parameter idle = 5'b00001;parameter selA = 5'b00010;parameter selB = 5'b00100;parameter selC = 5'b01000;parameter count = 5'b10000;always @ (posedge clk_in or negedge reset) /// clk_dividerbeginif (!reset)beginclk <= 1'b0;divcnt <= 0;endelse if (divcnt == 99999)beginclk <= 1'b1;divcnt <= 0;endelse if (divcnt == 49999)beginclk <= 1'b0;divcnt <= divcnt + 1;endelsedivcnt <= divcnt + 1;endalways @ (posedge clk or negedge reset) // 7seg scan clk=1Khz beginif (!reset)begincs <= 4'b1101;seg <= 8'b00111000;endelse if (cs == 4'b1101)begincs <= 4'b1110;case(ones)0: seg <= 8'b10000001;1: seg <= 8'b11001111;2: seg <= 8'b10010010;3: seg <= 8'b10000110;4: seg <= 8'b11001100;5: seg <= 8'b10100100;6: seg <= 8'b10100000;7: seg <= 8'b10001111;8: seg <= 8'b10000000;9: seg <= 8'b10000100;default: seg <= 8'b01110000;endcaseendelse if (cs == 4'b1110)begincs <= 4'b1101;case(tens)0: seg <= 8'b00000001;1: seg <= 8'b01001111;2: seg <= 8'b00010010;3: seg <= 8'b00000110;4: seg <= 8'b01001100;5: seg <= 8'b00100100;6: seg <= 8'b00100000;7: seg <= 8'b00001111;8: seg <= 8'b00000000;9: seg <= 8'b00000100;default: seg <= 8'b01110000;endcaseendendalways @ (total) //total decode beginif (total < 10 && total >= 0)begintens = 0;ones = total;endelse if (total < 20 && total >= 10)begintens = 1;ones = total - 10;endelse if (total < 30 && total >= 20) begintens = 2;ones = total - 20;endelse if (total < 40 && total >= 30) begintens = 3;ones = total - 30;endelse if (total < 50 && total >= 40) begintens = 4;ones = total - 40;endelse if (total < 60 && total >= 50) begintens = 5;ones = total - 50;endelse if (total < 70 && total >= 60) begintens = 6;ones = total - 60;endelse if (total < 80 && total >= 70) begintens = 7;ones = total - 70;endelse if (total < 90 && total >= 80) begintens = 8;ones = total - 80;endelse if (total < 100 && total >= 90) begintens = 9;ones = total - 90;endelsebegintens = 9;ones = 9;endendalways @ (posedge clk or negedge reset) // undo key jitter fsm for button1_in beginif (!reset)beginbutton1 <= 1'b0;cnt1 <= 0;state1 <= wait0;endelsebeginbutton1 <= 1'b0;case (state1)wait0: beginif (button1_in)state1 <= delay;elsestate1 <= wait0;enddelay: beginif (cnt1 == 24)begincnt1 <= 0;if (button1_in)beginbutton1 <= 1'b1;state1 <= wait1;endelsestate1 <= wait0;endelsebegincnt1 <= cnt1 + 1;state1 <= delay;endendwait1: beginif (button1_in)state1 <= wait1;elsestate1 <= wait0;enddefault: state1 <= wait0;endcaseendendalways @ (posedge clk or negedge reset) // undo key jitter fsm for button2_in beginif (!reset)beginbutton2 <= 1'b0;cnt2 <= 0;state2 <= wait0;endelsebeginbutton2 <= 1'b0;case (state2)wait0: beginif (button2_in)state2 <= delay;elsestate2 <= wait0;enddelay: beginif (cnt2 == 24)begincnt2 <= 0;if (button2_in)beginbutton2 <= 1'b1;state2 <= wait1;endelsestate2 <= wait0;endelsebegincnt2 <= cnt2 + 1;state2 <= delay;endendwait1: beginif (button2_in)state2 <= wait1;elsestate2 <= wait0;enddefault: state2 <= wait0;endcaseendendalways @ (posedge clk or negedge reset) // undo key jitter fsm for button3_in beginif (!reset)beginbutton3 <= 1'b0;cnt3 <= 0;state3 <= wait0;endelsebeginbutton3 <= 1'b0;case (state3)wait0: beginif (button3_in)state3 <= delay;elsestate3 <= wait0;enddelay: beginif (cnt3 == 24)begincnt3 <= 0;if (button3_in)beginbutton3 <= 1'b1;state3 <= wait1;endelsestate3 <= wait0;endelsebegincnt3 <= cnt3 + 1;state3 <= delay;endendwait1: beginif (button3_in)state3 <= wait1;elsestate3 <= wait0;enddefault: state3 <= wait0;endcaseendendalways @ (posedge clk or negedge reset) // undo key jitter fsm for button3_in beginif (!reset)beginbutton4 <= 1'b0;cnt4 <= 0;state4 <= wait0;endelsebeginbutton4 <= 1'b0;case (state4)wait0: beginif (button4_in)state4 <= delay;elsestate4 <= wait0;enddelay: beginif (cnt4 == 24)begincnt4 <= 0;if (button4_in)beginbutton4 <= 1'b1;state4 <= wait1;endelsestate4 <= wait0;endelsebegincnt4 <= cnt4 + 1;state4 <= delay;endendwait1: beginif (button4_in)state4 <= wait1;elsestate4 <= wait0;enddefault: state4 <= wait0;endcaseendendalways @ (posedge clk or negedge reset) //FSM for automat beginif (!reset)begintotal <= 0;Led <= 3'b000;state <= idle;endelsebegincase (state)idle: beginLed <= 3'b000;if (button1)state <= selA;elsestate <= idle;endselA: begintotal <= 0;Led <= 3'b100;if (button1)state <= selB;else if (button2)beginstate <= count;total <= total + 10;endelse if (button3)beginstate <= count;total <= total + 5;endelse if (button4)beginstate <= count;total <= total + 1;endelsestate <= selA;endselB: beginLed <= 3'b010;if (button1)state <= selC;else if (button2)beginstate <= count;total <= total + 10;endelse if (button3)beginstate <= count;total <= total + 5;endelse if (button4)beginstate <= count;total <= total + 1;endelsestate <= selB;endselC: beginLed <= 3'b001;if (button2)beginstate <= count;total <= total + 10;endelse if (button3)beginstate <= count;total <= total + 5;endelse if (button4)beginstate <= count;total <= total + 1;endelsestate <= selC;endcount: beginif (button2)beginstate <= count;total <= total + 10;endelse if (button3)beginstate <= count;total <= total + 5;endelse if (button4)beginstate <= count;total <= total + 1;endelse if (button1 && (total >= 10) && Led == 3'b100)begintotal <= total - 10;state <= idle;endelse if (button1 && (total >= 15) && Led == 3'b010)begintotal <= total - 15;state <= idle;endelse if (button1 && (total >= 16) && Led == 3'b001)begintotal <= total - 16;state <= idle;endelsestate <= count;enddefault: state <= idle;endcaseendendendmodule3.仿真:Tb代码:`timescale 1ns / 1psmodule tb;reg clk_in;reg reset;reg button1_in;reg button2_in;reg button3_in;reg button4_in;wire [3:0] cs;wire [2:0] Led;wire [7:0] seg;automat uut (.clk_in(clk_in),.reset(reset),.cs(cs),.Led(Led),.seg(seg),.button1_in(button1_in),.button2_in(button2_in),.button3_in(button3_in),.button4_in(button4_in) );initial begin// Initialize Inputsclk_in = 0;reset = 0;button1_in = 0;button2_in = 0;button3_in = 0;button4_in = 0;#1000;reset = 1;#1000;button1_in = 1;#2000000button1_in = 0;#2000000button1_in = 1;#2000000button1_in = 0;#2000000button1_in = 1;#2000000button1_in = 0;#2000000button1_in = 1;#2000000button1_in = 0;#2000000button1_in = 1;#2000000button1_in = 0;#2000000button1_in = 1;#50000000button1_in = 0;//delay 50ms#50000000button2_in = 1;#50000000button2_in = 0;#50000000button3_in = 1;#50000000button3_in = 0;#50000000button4_in = 1;#50000000button4_in = 0;#50000000button1_in = 1;#50000000button1_in = 0;endalways#5 clk_in = ~clk_in;endmodule把button1_in 仿真成与物理电路一样有大约十几秒的抖动Button1 正确的忽略掉抖动产生的影响,产生了一个周期的脉冲买A=1元仿真的过程:button1一来state进入买selA状态button2一来state 进入count状态且total+10 (total=投进钱总数剩10)即表示投进了1元,button3一来total = 15 表示投进了1.5元,button4一来total = 16 表示投了1.6元,最后按button1 出货和找零,total=6表示找零0.6角4.实物展示:本设计下载平台是Nexys3™BoardUcf:#clkNet "clk_in" LOC=V10 | IOSTANDARD=LVCMOS33;Net "clk_in" TNM_NET = sys_clk_pin;TIMESPEC TS_sys_clk_pin = PERIOD sys_clk_pin 100000 kHz;Net "reset" LOC = T10 | IOSTANDARD = LVCMOS33; #Bank = 2, pin name = IO_L29N_GCLK2, Sch name = SW0## LedsNet "Led<0>" LOC = U16 | IOSTANDARD = LVCMOS33; #Bank = 2, pin name = IO_L2P_CMPCLK, Sch name = LD0Net "Led<1>" LOC = V16 | IOSTANDARD = LVCMOS33; #Bank = 2, pin name = IO_L2N_CMPMOSI, Sch name = LD1Net "Led<2>" LOC = U15 | IOSTANDARD = LVCMOS33; #Bank = 2, pin name = IO_L5P, Sch name = LD2#Net "seg<7>" LOC = M13 | IOSTANDARD = LVCMOS33; #Bank = 1, pin name = IO_L61N, Sch name = DP## 7 segment displayNet "seg<6>" LOC = T17 | IOSTANDARD = LVCMOS33; #Bank = 1, pin name = IO_L51P_M1DQ12, Sch name = CANet "seg<5>" LOC = T18 | IOSTANDARD = LVCMOS33; #Bank = 1, pin name = IO_L51N_M1DQ13, Sch name = CBNet "seg<4>" LOC = U17 | IOSTANDARD = LVCMOS33; #Bank = 1, pin name = IO_L52P_M1DQ14, Sch name = CCNet "seg<3>" LOC = U18 | IOSTANDARD = LVCMOS33; #Bank = 1, pin name = IO_L52N_M1DQ15, Sch name = CDNet "seg<2>" LOC = M14 | IOSTANDARD = LVCMOS33; #Bank = 1, pin name = IO_L53P, Sch name = CENet "seg<1>" LOC = N14 | IOSTANDARD = LVCMOS33; #Bank = 1, pin name = IO_L53N_VREF, Sch name = CFNet "seg<0>" LOC = L14 | IOSTANDARD = LVCMOS33; #Bank = 1, pin name = IO_L61P, Sch name = CGNet "seg<7>" LOC = M13 | IOSTANDARD = LVCMOS33; #Bank = 1, pin name = IO_L61N, Sch name = DPNet "cs<0>" LOC = N16 | IOSTANDARD = LVCMOS33; #Bank = 1, pin name = IO_L50N_M1UDQSN, Sch name = AN0Net "cs<1>" LOC = N15 | IOSTANDARD = LVCMOS33; #Bank = 1, pin name = IO_L50P_M1UDQS, Sch name = AN1Net "cs<2>" LOC = P18 | IOSTANDARD = LVCMOS33; #Bank = 1, pin name =IO_L49N_M1DQ11, Sch name = AN2Net "cs<3>" LOC = P17 | IOSTANDARD = LVCMOS33; #Bank = 1, pin name = IO_L49P_M1DQ10, Sch name = AN3## ButtonsNet "button1_in" LOC = A8 | IOSTANDARD = LVCMOS33; #Bank = 0, pin name = IO_L33N, Sch name = BTNUNet "button2_in" LOC = C4 | IOSTANDARD = LVCMOS33; #Bank = 0, pin name = IO_L1N_VREF, Sch name = BTNLNet "button3_in" LOC = C9 | IOSTANDARD = LVCMOS33; #Bank = 0, pin name = IO_L34N_GCLK18, Sch name = BTNDNet "button4_in" LOC = D9 | IOSTANDARD = LVCMOS33; # Bank = 0, pin name = IO_L34P_GCLK19, Sch name = BTNR实物图:。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

module sw_de(clk,rst_n,sw1_n,sw2_n,sw3_n,led_d1,led_d2,led_d3);
input clk; //主时钟信号 50MHz
input 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_r
always @ (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)
begin
d1<=1'b0;
d2<=1'b0;
d3<=1'b0;
end
else begin //某个按键值变化时,LED将亮灭翻转 if (led_ctrl[0]) d1<=~d1;
if (led_ctrl[1]) d2<=~d2;
if (led_ctrl[2]) d3<=~d3;
end
assign led_d3=d1?1'b1:1'b0;
assign led_d2=d2?1'b1:1'b0;
assign led_d1=d3?1'b1:1'b0;
endmodule。

相关文档
最新文档