开发板上的按键,有的自带消抖功能,有的则没有。因为按键存在一个反作用弹簧,所以在按下的或松开的时候会产生额外的物理抖动进而导致电平抖动,如图:使用硬件逻辑电路消除抖动。
上代码:
module key_debounce(
input clk,
input rst_n,
input key,
output reg key_flag,
output reg key_value
);
reg [31:0] cnt;
reg key_reg;
always@(posedge clk or negedge rst_n)
if(!rst_n)begin
cnt <= 32'd0;
key_reg <= 1'b0;
end
else begin
key_reg <= key;
if(key_reg != key)
cnt <= 32'd1000000;
else if(key_reg == key)begin
if(cnt > 32'd0)
cnt <= cnt - 1'b1;
else
cnt <= cnt;
end
end
always@(posedge clk or negedge rst_n)
if(!rst_n)begin
key_flag <= 1'b0;
key_value <= 1'b0;
end
else begin
if(cnt == 32'd1)begin
key_flag <= 1'b1;
key_value <= key;
end
else begin
key_flag <= 1'b0;
key_value <= key_value;
end
end
endmodule
抖动时间设置20ms在50MHZ下位宽32位,最大值1000000,定义一个按键寄存器,当按键抖动时key_reg 不等于key时,开始计数,当计数到1后按键标志位拉高,key_value = key。
实验中好像计数器从1加到1000000和从1000000减到1的效果不同,只是好像,没仔细比较哈。
这里直接上仿真代码
`timescale 1ns/1ns
`define clock_period 20
module key_debounce_tb;
reg clk;
reg rst_n;
reg key;
wire key_flag;
wire key_value;
key_debounce u_key_debounce(
.clk(clk),
.rst_n(rst_n),
.key(key),
.key_flag(key_flag),
.key_value(key_value)
);
initial clk = 1;
always#(`clock_period/2)clk = ~clk;
initial begin
rst_n = 1'b0;
key = 1'b0;
#(`clock_period*200)
rst_n = 1'b1;
#(`clock_period*200)
key = 1'b1;
#(`clock_period*200)
key = 1'b1;
#(`clock_period*200)
key = 1'b0;
#200000;
$stop;
end
endmodule
仿真的时候把1000000改为1000这样方便点,
有什么不对的地方可以一起讨论。