按键产生的抖动原理
空闲态 (IDLE)》:等待按键按下(等待下降沿),-旦出现下降沿,就开始 20ms 的计时
按下消抖状态:20ms 的计时状态,在这个状态里,一边计时,一边检测有没有出现上升沿,
如果有出现上升沿,回到空闲态;如果计时满 20ms,没有出现上升沿,发出按键按下的通
知信号。
等待释放:等待按键释放(等待上升沿),一旦出现上升沿,就开始 20ms 的计时~
释放消抖状态:20ms 的计时状态,在这个状态里,一边计时,一边检测按键有没有出现下
降沿,如果出现下降沿,则回到等待释放状态,如果计时满 20ms 没有出现下降沿,发出
按键释放的通知信号。
利用状态机消抖的状态转移图
按键消抖:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/06/29 17:14:51
// Design Name: czy
// Module Name: key_filter
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module key_filter(
Clk,
Reset_n,
key,
key_flag,
key_state
);
input Clk;
input Reset_n;
input key;
output key_flag;
output reg key_state;
reg press_flag;
reg release_flag;
//定义状态机 4个状态 2位
localparam IDLE=0;
localparam Pr_f=1;
localparam WAIT=2;
localparam Re_f=3;
//key_flag
assign key_flag = press_flag|release_flag;
reg [1:0] state;
//定义上升沿 、下降沿
wire key_pedge;
wire key_nedge;
//检验上升沿or下降沿
reg [1:0] key_edge;//移位寄存器
reg [19:0] cnt;
always@(posedge Clk)
key_edge <= {key_edge[0],key};
assign key_pedge=key_edge==2'b01;
assign key_nedge=key_edge==2'b10;
//定义计数器 20 000 000(20ms)/20(20ns时钟周期)=1 000 000周期 20'b 1111 0100 0010 0100 0000
always@(posedge Clk or negedge Reset_n )
if(!Reset_n)begin
state <= IDLE;
release_flag <= 0;
press_flag <= 0;
cnt <= 1'b0;
key_state<=1;
end
else begin
case(state)
IDLE:
begin
release_flag<=0;
if(key_nedge)
state <= Pr_f;
else
state <= IDLE;
end
Pr_f:
begin
if((key_pedge)&&(cnt<1_000_000-1))
state <= IDLE;
else if(cnt>=1_000_000-1)begin
press_flag<=1;
key_state<=0;
state <= WAIT;
cnt<=0;
end
else begin
cnt<=cnt+1'b1;
state <= Pr_f;
end
end
WAIT:begin
press_flag<=0;
if(key_pedge)
state <= Re_f;
else
state <= WAIT;
end
Re_f:
begin
if((key_nedge)&&(cnt<1_000_000-1))
state <= WAIT;
else if(cnt>1_000_000-1)begin
state <= IDLE;
release_flag<=1;
key_state<=1;
cnt<=0;
end
else begin
cnt<=cnt+1'b1;
state <= Re_f;
end
end
endcase
end
endmodule
测试文件:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/07/06 16:45:46
// Design Name: czy
// Module Name: key_filter_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module key_filter_tb();
reg Clk;
reg Reset_n;
reg key;
wire key_flag;
wire key_state;
key_filter key_filter(
Clk,
Reset_n,
key,
key_flag,
key_state
);
//产生时钟
initial Clk=1;
always#10 Clk=~Clk;
initial begin
Reset_n = 0;
key=1;//按键正常情况高电平
#201;//避开时钟的上升沿
Reset_n = 1;//释放复位
#30000;
key = 0;
#20000;
key = 1;
#30000;
key = 0;
#20000;
key = 1;
#30000;
key=0;
#50_000_000;
key = 1;
#30000;
key = 0;
#20000;
key = 1;
#30000;
key=0;
#20000;
key = 1;
#50_000_000;
$stop;
end
endmodule
仿真波形
放大看...