同步时钟域的应用 – 按键消抖程序
机械按键的抖动示意图
采用20ms按键消抖
FPGA 的晶振时钟一般为 50Mhz,也就是 每个时钟周期为 20ns(1/50Mhz=20ns),那么计数值为 20ms/20ns=32’d1_000_000
按键消抖verilog程序
/**
* @description: 多个按键消抖程序 --主时钟频率 - 50MHZ
* @return {*}
* @author: Fangyeye
*/
module ip_key_debounce #(
parameter N = 2 //多少位输入的按键
)
(
input wire clk, //50MHZ频率
input wire rst_n,
input wire [N-1:0] key, //输入的按键信号
output wire [N-1:0] key_deb //消抖后的按键信号
);
// 50MHZ频率经过分频计数得到 50HZ ,周期约为20ms,满足去除抖动要求
parameter CNT_MAX = ( (1_000_000 / 2) -1 );
reg [23:0] cnt;
reg clk_50hz;
// 3级寄存器延时消抖 -- 同步时钟域思想
reg [N-1:0] key_r, key_rr, key_rrr;
// 对应的Testbench测试程序:
// always @(posedge clk , negedge rst_n) begin
// if(!rst_n)begin
// cnt <= 24'b0;
// clk_50hz <= 1'b0;
// end
// else if(cnt == CNT_MAX)begin
// cnt <= 24'b0;
// clk_50hz <= ~clk_50hz;
// end
// else
// cnt <= cnt + 1'b1;
// end
always @(posedge clk_50hz , negedge rst_n) begin
if(!rst_n)begin
key_r <= 'b0;
key_rr <= 'b0;
key_rrr <= 'b0;
end
else begin
key_rrr <= key_rr;
key_rr <= key_r;
key_r <= key;
end
end
assign key_deb = key_r & key_rr & key_rrr;
endmodule
按键消抖Testbench
`timescale 1ms / 1ms //毫秒的时间刻度
module key0_debounce _test;
// Inputs
reg clk_50Hz;
reg key;
reg rst;
// Outputs
wire keydeb;
// Instantiate the Unit Under Test (UUT)
key0_debounce uut (
.clk_50Hz(clk_50Hz),
.rst(rst),
.key0(key),
.keydeb(keydeb)
);
initial begin
clk_50Hz = 0;
forever
#10 clk_50Hz = ~clk_50Hz;
end
initial begin
rst = 1;
#15 rst = 0;
#10 rst = 1;
end
initial begin
key = 1;
#30 key = 0;
#18 key = 1;
#7 key = 0;
#10 key = 1;
#200 key = 0;
#15 key = 1;
#8 key = 0;
#15 key = 1;
#12 key = 0;
#15 key = 1;
end
endmodule
仿真波形
容易得出 :在按键按下期间,电平毛刺对其无影响
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)