目录
1.原理
2.代码
2.1 key_filter.v
2.2 tb_key_filter.v
1.原理
按键分为自锁式按键和机械按键,图左边为自锁式按键
上图为RS触发器硬件消抖,当按键的个数比较多时常常使用软件消抖。硬件消抖会使用额外的器件占用电路板上的空间。
思路就是使用延时程序去掉抖动的部分,抖动就是不规则的高低电平变化。
只要在20ms之内没有抖动的产生,就可以认为按键的可用的。计数器的作用就是当检测道低电平时就开始计数,当检测到高电平时就清零。
因为50MHZ的时钟,周期为20ns,要计满20ms,20ms=20000_000ns,则计数器要计数20000_000/20=1000_000个时钟周期,所以计数器的值是从0-999_999。
出现了一个问题,若稳定的时间足够长,在稳定期间就会出现多次清零,多个最大值,多个脉冲信号,这不是我们想要的结果。为此对波形图做修改。
此时的原理就是当计数道最大值时计数器不清零,直到下一个按键输入检测到为高电平再清零。
但此时输出信号就不再是一个脉冲信号了,而是一个长长的高电平。因此再次对波形图做修改。
当计数到999_999-1时,就把输出拉高一个时钟周期,然后清零。
以上这张图的tb_cnt是为了仿真的。19-49(前抖动),149-199赋值随机数模拟抖动(后抖动),0-19,199-249赋值为高电平模仿按键未被按下,其余时间赋值为0模仿按键按下。
2.代码
2.1 key_filter.v
module key_filter
#(
parameter CNT_MAX=20'd999_999
)
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire key_in ,
output reg key_flag
);
reg [19:0] cnt_20ms ;
always @(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n==1'b0)
cnt_20ms<=20'd0;
else if(key_in==1'b1)
cnt_20ms<=20'd0;
else if(cnt_20ms==CNT_MAX)
cnt_20ms<=CNT_MAX;
else
cnt_20ms<=cnt_20ms+20'd1;
always @(posedge sys_clk or negedge sys_rst_n)
if (sys_rst_n==1'b0)
key_flag<=1'b0;
else if(cnt_20ms==CNT_MAX-20'd1)
key_flag<=1'b1;
else
key_flag<=1'b0;
endmodule
2.2 tb_key_filter.v
`timescale 1ns/1ns
module tb_key_filter();
reg sys_clk ;
reg sys_rst_n;
reg key_in ;
reg [7:0] tb_cnt ;//使用计数器进行一个周期的计数,模拟一次按键按下,计数的最大值暂定为250次(8位)
wire key_flag ;
initial
begin
sys_clk=1'b1;
sys_rst_n<=1'b0;
#20
sys_rst_n<=1'b1;
end
always #10 sys_clk=~sys_clk;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
tb_cnt<=8'd0;
else if(tb_cnt==8'd249)
tb_cnt<=8'd0;
else
tb_cnt<=tb_cnt+8'd1;
//模拟按键过程,检测到低电平开始计数,检测到高电平清0
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
key_in<=1'b1;
else if(((tb_cnt>=8'd19)&&(tb_cnt<=8'd49))
||((tb_cnt>=8'd149)&&(tb_cnt<=8'd199))) //模仿抖动
key_in<={$random}%2;
else if((tb_cnt<8'd19)||(tb_cnt>8'd199))//模仿按键未被按下
key_in<=1'b1;
else
key_in<=1'b0; //模仿稳定时候
key_filter
#(
.CNT_MAX(20'd24) //相当于计数25
)
tb_key_filter
(
. sys_clk (sys_clk),
. sys_rst_n (sys_rst_n),
. key_in (key_in) ,
. key_flag (key_flag)
);
endmodule
计数器最大计数到249,共计数250正确。
0-19 key_in是高电平
计数器计数19-49模拟抖动
49-149模拟按键按下稳定状态
观察标志信号,确在计数稳定25次之后,也就是计数第24的时候拉高标志信号一个时钟周期