用Verilog实现按键抖动消除电路,抖动小于15ms,输入时钟12MHz。
module debounce(
input clk,
input rst_n,
input key_in,
output key_out
);
//按键原始值为1,按下后为0;
reg [1:0] key_in_r;
reg [20:0] cnt; //15ms/(1/12Mhz)≈180000,取21位存储
//检测抖动
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
key_in_r <= 1'b0;
else
key_in_r <= {key_in_r[0],key_in};
end
assign change = ((~key_in_r[1] & key_in_r[0]) | (key_in_r[1] & ~key_in_r[0]));
//抖动产生后开始计数
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
cnt <= 21'b0;
else if(change == 1)
cnt <= 21'b0;
else
cnt <= cnt + 1;
end
//计数到抖动结束后,将key_in赋给key_out
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
key_out <= 1;
else if(cnt == 21'd180000 - 1)
key_out <= key_in;
else
key_out <= key_out;
end
endmodule
//仿真文件
module tb();
logic clk, rst_n, key_in, key_out;
rebounce rebounce(clk, rst_n, key_in, key_out);
initial begin clk=0; forever #5 clk=~clk; end
initial begin rst_n=0; #30 rst_n=1; end
initial begin
key_in=1;
#30 key_in=0;
#10 key_in=~key_in;
#10 key_in=~key_in;
#10 key_in=~key_in;
#10 key_in=~key_in;
#10 key_in=0;
#2000_0000
key_in=1;
#10 key_in=~key_in;
#10 key_in=~key_in;
#10 key_in=~key_in;
#10 key_in=~key_in;
key_in=1;
end
endmodule