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表示状态是否稳定有效
设置一个计数器,表示按键在同一状态稳定的时间,达到这个时间阈值表示按键按下有效
把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_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
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
顶层模块连接两个底层模块,连接两个模块之间的变量需要定义位宽,类型为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
需要模拟抖动
`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