2_ZYBO FPGA 按键控制蜂鸣器 key_beep=>key_led
创始人
2024-03-21 00:25:14
0

2_ZYBO FPGA 按键控制蜂鸣器 key_beep=>key_led - xiongyuqing - 博客园 (cnblogs.com)

问题与思路

使用按键控制蜂鸣器发声。 初始状态为蜂鸣器鸣叫,按下开关后蜂鸣器停止鸣叫,再次按下开关,蜂鸣器重新鸣叫

按键抖动

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dc76K7iJ-1670228874727)(https://gitee.com/xiongyuqing/PicGo-bed/raw/master/img/image-20221202191430622.png)]

按键消抖

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MzigB0Mx-1670228874728)(https://gitee.com/xiongyuqing/PicGo-bed/raw/master/img/image-20221202191502184.png)]

系统框图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5AiDeCzJ-1670228874728)(https://gitee.com/xiongyuqing/PicGo-bed/raw/master/img/image-20221202191518440.png)]

消抖方式

  • 输入key的按键信号,输出一个value表示按键状态,以及一个flag表示状态是否稳定有效

  • 设置一个计数器,表示按键在同一状态稳定的时间,达到这个时间阈值表示按键按下有效

    • 这里的cnt设置为1_000_000个周期,每个周期20ns,也就是20_000_000ns=20ms=0.2s
  • 把key存在一个寄存器key_reg里,当key_reg != 按键key 表示状态发生了变化按键按下了,但是不知是抖动还是稳定,计数器赋初值

  • 否则key_reg=key表示按键没有变化处于稳定状态,计数器自减计算稳定时长,当时长达到阈值后即计数器为0后不再自减维持为0

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dkjHtOWM-1670228874728)(https://gitee.com/xiongyuqing/PicGo-bed/raw/master/img/image-20221202192638835.png)]

  • 如果以cnt为0作为判断条件,由于cnt在稳定后一直为0,那么key_flag和key_value会一直高电平和低电平,如果一直高电平蜂鸣器会认为一直处于按键变化状态,就会一直处于开关开关状态,所以我们只需要一个电平脉冲

  • 所以在计数器为1的时候拉高,为0的时候拉低,只一个周期为高电平

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wSneirwv-1670228874728)(https://gitee.com/xiongyuqing/PicGo-bed/raw/master/img/image-20221202194338977.png)]

key_debounce.v

注意这里是key_value = key 而不是 key_value = 1'b0

因为我们要的是按键按下持续0.02s后状态改变,而不是按键的任何状态即按下或松开持续0.02s就变

module key_debounce (input  sys_clk,input  sys_rst_n,input  key,output reg key_value,output reg key_flag
);reg [19:0] cnt;
reg key_reg;always @(posedge sys_clk or negedge sys_rst_n) beginif (!sys_rst_n) beginkey_reg <= 1'b1;cnt <= 1'b0;endelse beginkey_reg <= key;if(key_reg != key)cnt <= 20'd1_000_000;else beginif(cnt <= 1'b0)cnt <= 1'b0;else cnt <= cnt - 1'b1;endend
endalways @(posedge sys_clk or negedge sys_rst_n) beginif (!sys_rst_n) beginkey_value <= 1'b1;key_flag <= 1'b0;endelse beginif(cnt == 1)beginkey_value <= key;key_flag <= 1'b1;endelse beginkey_value <= key_value;key_flag <= 1'b0;endend
endendmodule

beep_control.v

module beep_control (input sys_clk,input sys_rst_n,input key,input key_value,input key_flag,output reg beep
);always @(posedge sys_clk or negedge sys_rst_n) beginif (!sys_rst_n)beep <= 1'b1;else if (key_flag && key_value == 1'b0)beep <= ~beep;elsebeep <= beep;
end
endmodule

top_key_beep.v

顶层模块连接两个底层模块,连接两个模块之间的变量需要定义位宽,类型为wire型,相当于水管连接两个模块,位宽是水管的粗细

module top_key_beep(input sys_clk,input sys_rst_n,input key,output beep
);wire key_value;
wire key_flag;key_debounce u_key_debounce(.sys_clk(sys_clk),.sys_rst_n(sys_rst_n),.key(key),.key_value(key_value),.key_flag(key_flag)
);beep_control u_beep_control(.sys_clk(sys_clk),.sys_rst_n(sys_rst_n),.key_value(key_value),.key_flag(key_flag),.beep(beep)
);endmodule

tb_key_beep.v

需要模拟抖动

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/12/05 10:42:28
// Design Name: 
// Module Name: tb_key_beep
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//module tb_key_beep();
reg sys_clk;
reg sys_rst_n;
reg key;wire beep;initial beginsys_clk = 1'b0;sys_rst_n = 1'b0;key = 1'b1;#60sys_rst_n = 1'b1;#40key = 1'b0;#100key = 1'b1;#40key = 1'b0;#120key = 1'b1;#40key = 1'b0;#140key = 1'b1;#40key = 1'b0;#240key = 1'b1;#40key = 1'b0;#280key = 1'b1;
endalways #10 sys_clk = ~sys_clk;top_key_beep u_top_key_beep(.sys_clk(sys_clk),.sys_rst_n(sys_rst_n),.key(key),.beep(beep)
);endmodule

仿真

cnt的阈值改为10,便于观察

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qwoZQ9Cu-1670228874729)(https://gitee.com/xiongyuqing/PicGo-bed/raw/master/img/image-20221205151621223.png)]

下载验证

注意的是zybo无复位按钮,这里将btn[1]作为sys_rst_n, btn[0]作为key,led[0]作为beep

将top函数的复位按钮前加上!取反,因为按钮是高电平有效的,所以key_control文件里的判断条件也要改为else if (key_flag && (key_value == 1'b1))

约束:

##Clock signal
set_property -dict { PACKAGE_PIN L16   IOSTANDARD LVCMOS33 } [get_ports { sys_clk }]; ##Buttons
set_property -dict { PACKAGE_PIN R18   IOSTANDARD LVCMOS33 } [get_ports {key }]; #IO_L20N_T3_34 Sch=BTN0
set_property -dict { PACKAGE_PIN P16   IOSTANDARD LVCMOS33 } [get_ports { sys_rst_n }]; #IO_L24N_T3_34 Sch=BTN1##LEDs
set_property -dict { PACKAGE_PIN M14   IOSTANDARD LVCMOS33 } [get_ports { beep }]; #IO_L23P_T3_35 Sch=LED0

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...