一、按键消抖简介
按键抖动
按键消抖
二、硬件设计
三、实验任务
本节的实验任务是使用开发板上的KEY0按键控制蜂鸣器发声。初始状态为蜂鸣器鸣叫,按下按键后蜂鸣器停止鸣叫,再次按下按键后,蜂鸣器重新鸣叫。
四、程序设计
1.思维导图
2.波形图
按键消抖波形图
按键控制蜂鸣器
3.代码编写
按键消抖模块
module key_debounce(
input sys_clk,
input sys_rst_n,
input key,
output reg key_filter //滤除抖动后的KEY
);
parameter CNT_MAX = 20'd1000000; //计时20ms
reg key_d0;
reg key_d1;
reg [19:0] cnt;
//打两拍消抖
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
key_d0 <= 1'b1;
key_d1 <= 1'b1;
end
else begin
key_d0 <= key;
key_d1 <= key_d0;
end
end
//如果按键有变化,重新计数20ms
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
cnt <= 20'd0;
else if(key_d0 != key_d1)
cnt <= CNT_MAX;
else if(cnt > 20'd0)
cnt <= cnt - 20'd1;
else
cnt <= 20'd0;
end
//滤除抖动后的KEY赋值
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
key_filter <= 1'b1;
else if(cnt == 20'd1)
key_filter <= key_d1;
else
key_filter <= key_filter;
end
endmodule
按键控制蜂鸣器模块
module key_beep(
input sys_clk,
input sys_rst_n,
input key_filter, //滤除抖动后的KEY
output reg beep
);
reg key_filter_d0;
wire neg_key_filter;
assign neg_key_filter = key_filter_d0 & (~key_filter)
//打一拍
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
key_filter_d0 <= 1'b1;
else
key_filter_d0 <= key_filter_d0;
end
//控制蜂鸣器鸣叫状态
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
beep <= 1'b1;
else if(neg_key_filter)
beep <= ~beep;
else
beep <= beep;
end
endmodule
顶层例化上述两模块
module top_key_beep(
input sys_clk,
input sys_rst_n,
input key,
output beep
);
parameter CNT_MAX = 20'd1000000; //计时20ms
wire key_filter;
key_debounce #(
.CNT_MAX (CNT_MAX)
)
u_key_debounce(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n ),
.key (key ),
.key_filter (key_filter)
);
key_beep u_key_beep(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n ),
.key_filter (key_filter),
.beep (beep )
);
endmodule
4.实验仿真
编写tb_key_led文件
'timescale 1ns/1ns //仿真单位/仿真精度
module tb_top_key_beep();
parameter CLK_PERIOD = 20;
parameter CNT_MAX = 20'd10; //计时200nss
reg sys_clk; //周期20ns
reg sys_rst_n;
reg key;
wire beep;
initial begin
sys_clk <= 1'b0;
sys_rst_n <= 1'b0;
key <= 1'b1;
#200
sys_rst_n <= 1'b1;
key <= 1'b0; //按键被按下
#40
key <= 1'b1; //按键抖动
#40
key <= 1'b0; //按键抖动结束
#1000
key <= 1'b1; //松开按键
#50
key <= 1'b0; //按键抖动
#30
key <= 1'b1; //按键抖动结束
end
always #(CLK_PERIOD/2) sys_clk = ~sys_clk;
top_key_beep #(
.CNT_MAX (CNT_MAX)
)
u_top_key_beep(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n),
.key (key ),
.beep (beep )
);
endmodule
在modulesim仿真,以500ns为周期(减少仿真时间),下图为部分放大后仿真结果。
消抖后波形图
按键控制蜂鸣器波形图
顶层控制模块波形图
五、下载验证
通过vivado创建工程,配置IO口和约束文件。
编译之后下载到开发板。
显示编译成功。
通过open target自动连接开发板再选择到指定文件(代码)下载。
开发板实现控制效果。