提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
按键消抖
- 前言
- 一、按键消抖原理
- 二、状态机实现按键消抖
- 三、Verilog代码实现
- 四、TB文件
- 五、仿真波形展示
前言
按键作为基本的人机输入接口,由于其机械特性,在按键按下或松开的时候,都是会有抖动的。按键小豆的方式有很多。我的方法是通过计时来消抖,通过一个计数器,当按键输入有变化时,计数器清零,否则就累加,直到加到一个预定值,就认为按键稳定,输出按键值,这样就得到了没有抖动的按键值。
提示:以下是本篇文章正文内容,下面案例可供参考
一、按键消抖原理
普通按键的硬件示意图如下图所示。
按键结构示意图中可以看到按键存在一个反作用弹簧,因此当按下或者松开时均会产生额外的物理抖动,物理抖动便会产生电平的抖动。在按键从按下再到松开的过程中,其电平变化如下图所示,上为理想波形输出,下为实际波形输出。
上图中,产生的抖动次数以及间隔时间均是不可预期的,这就需要通过滤波来消除抖动可能对外部其他设备造成的影响。一般情况下抖动的总时间会持续 20ms 以内。这种抖动,可以通过硬件电路或者逻辑设计的方式来消除,也可以通过软件的方式完成。其中硬件电路消除抖动适用于按键数目较少的场合。
二、状态机实现按键消抖
对于单按键的消抖模块,其接口如下图所示,接口声明功能描述如下:
各模块功能描述:
状态图如下:
三、Verilog代码实现
代码如下(示例):文章来源:https://uudwc.com/A/DNkYr
module key_filter(
Clk,
Reset_n,
Key,
// Key_P_Flag,
// Key_R_Flag,
Key_Flag,
Key_State
);
input Clk;
input Reset_n;
input Key;
// output reg Key_P_Flag;
// output reg Key_R_Flag;
output Key_Flag;
output reg Key_State;
reg Key_P_Flag;
reg Key_R_Flag;
assign Key_Flag = Key_P_Flag | Key_R_Flag;
reg [2:0] r_Key; //防止亚稳态用三个移位寄存器
always@(posedge Clk)
r_Key <= {r_Key[1:0],Key};
// always@(posedge Clk)begin
// r_Key[0] <= Key;
// r_Key[1] <= r_Key[0];
// r_Key[2] <= r_Key[1];
// end
wire pedge_key;
assign pedge_key = (r_Key[2:1] == 2'b01);
wire nedge_key;
assign nedge_key = (r_Key[2:1] == 2'b10);
reg [19:0]cnt;
reg [1:0]state;
always@(posedge Clk or negedge Reset_n)
if(!Reset_n)begin
state <= 0;
Key_R_Flag <= 1'b0;
Key_P_Flag <= 1'b0;
cnt <= 0;
Key_State <= 1;
end
else begin
case(state)
0:
begin
Key_R_Flag <= 1'b0;
if(nedge_key)
state <= 1;
else
state <= 0;
end
1:
if((pedge_key)&&(cnt <1000000 -1))begin
state <= 0;
cnt <= 0;
end
else if(cnt >= 1000000 -1)begin
state <= 2;
cnt <= 0;
Key_P_Flag <= 1;
Key_State <= 0;
end
else begin
cnt <= cnt + 1'b1;
state <= 1;
end
2:
begin
Key_P_Flag <= 0;
if(pedge_key)
state <= 3;
else
state <= 2;
end
3:
if((nedge_key)&&(cnt <1000000 -1))begin
state <= 2;
cnt <= 0;
end
else if(cnt >= 1000000 -1)begin
state <= 0;
cnt <= 0;
Key_R_Flag <= 1'b1;
Key_State <= 1;
end
else begin
cnt <= cnt + 1'b1;
state <= 3;
end
endcase
end
endmodule
【注】:上述代码注释处采用三个移位寄存器防止亚稳态产生(触发器在时钟上升沿来临时对数据进行采样,产生对应的输出。但是实际器件无法瞬时完成数据采样这一过程,需要数据在时钟沿前后均稳定一定时间)具体可参考:亚稳态现象
四、TB文件
代码如下(示例):
`timescale 1ns / 1ps
module key_filter_tb2();
reg Clk;
reg Reset_n;
reg Key;
// wire Key_P_Flag;
// wire Key_R_Flag;
wire Key_Flag;
wire Key_State;
key_filter key_filter(
Clk,
Reset_n,
Key,
// Key_P_Flag,
// Key_R_Flag,
Key_Flag,
Key_State
);
initial Clk = 1;
always#10 Clk = ~Clk;
initial begin
Reset_n = 0;
Key = 1;
#201;
Reset_n = 1;
#3000;
press_key(2);
$stop;
end
reg [31:0]rand;
task press_key;
input [3:0]seed;
begin
Key = 1;
#20000000;
repeat(5)begin
rand = {$random(seed)} % 10000000;//(0,9999999)
#rand Key = ~Key;
end
Key = 0;
#40000000;
repeat(5)begin
rand = {$random(seed)} % 10000000;//(0,9999999)
#rand Key = ~Key;
end
Key = 1;
#40000000;
end
endtask
endmodule
五、仿真波形展示
【附件:】链接:https://pan.baidu.com/s/1fZESYFREq6r3kTjIeDXlXA?pwd=vj42
提取码:vj42文章来源地址https://uudwc.com/A/DNkYr