本帖最后由 拾光333 于 2020-1-12 13:58 编辑
设计内容
按KEY0时点亮最右边的灯,按动按键KEY1时依次往左移动,按下KEY2时关闭蜂鸣器,按动按键KEY3时打开蜂鸣器,首先分几个模块实现不同的功能,然后将子模块组合实现总功能。
消抖:因为在按键按下的过程中存在按键开关接触与不接触的临界点,这些抖动可能会被FPGA捕捉到,造成误操作。
有按键消抖模块,BEEP模块,LED流水模块。
设置一个计数器为10ms的,目的是当按键保持10ms后才认为该按键被按下了 ,按下过程中前面和后面的那一瞬间都是不稳定的高低电压,中间部分被计时的是10ms保持时间。当计数器技术到10ms时,并且按键仍然是按下的,值保持寄存器为10ms数为500000个时钟周期不变,为了防止按下一次按键后,如果按下的时间超过20ms,就会产生两个flag标志,输出2个信号。
设置flag作用是计数器计数到499999并且按键电压依旧保持为0时,可以认为按键被按下,这时产生一个高电平标志。
LED,按键按下时最右边灯亮,此时4个灯为0001,按键按下时为0010,再次按下时0100,以此类推。
管脚:key[0] E16 key[1] E15 key[2] M2 key[3] M16 beep D12
按键低电平有效
仿真文件
- `timescale 1 ns/ 1 ns
- module key_led_beep_vlg_tst();
- // constants
- // general purpose registers
- // test vector input registers
- reg [3:0]sw;
- reg sys_clk;
- reg sys_rst;
- reg [8:0] timel;
- // wires
- wire [3:0] led;
- wire beep;
- // assign statements (if any)
- key_led_beep i1 (
- // port map - connection between master ports and signals/registers
- .led(led),
- .sw(sw),
- .sys_clk(sys_clk),
- .sys_rst(sys_rst)
- );
- initial
- begin
- sys_clk = 1'd0;
- sys_rst <= 1'd0;
- timel <= 9'd0;
- sw <= 4'b1110;
- #100 sys_rst <= 1;
- #1000 sw <= 4'b1111;
- end
- always #10 sys_clk = ~sys_clk;
- always #20
- if(timel == 200) timel<= 0;
- else timel <= timel + 1'd1;
- always #20
- if((timel < 20)||(timel>70&&timel<100))sw[1]<={$random};
- else if(timel>100)sw[1] <= 0;
- else sw[1] <= 1;
- endmodule
模拟按键按动,采用随机数的方法,轮流计数200的方法,计数在21~70时模拟按下,计数在71~100时模拟抬起,计数在101~200时模拟不按按键过程计数到200重新计数,在这只模拟其中一个按键key1,其他的类似。
可以看到在按键按下消抖后仍然处于低电平的则led向右移动。beep默认高电平响,没有模拟按键。