四种状态
按键未按下:静止状态呈高电平;
按下过程中:抖动状态呈高低电平;
按键已按下:静止状态呈低电平;
释放过程中:抖动状态呈高低电平。
按键消抖思路:区别于单片机使用20ms延时判断电平正负,FPGA中采用电平保持计时,若时间长度超过20ms则认为发生了一次按键操作。
按键实际电路存在亚稳态现象,当按键正好在时钟上升沿按下时,触发器1的输出Q_1将不确定,可能为1,也可能为0,此时无法准确的判断下降沿的触发,通过两个触发器可有效解决上述问题,通过判断Q_1与Q_2,将有效的判断按键下降沿的触发,且判断仅有一个始终距离。
仿真波形
设计文件程序
`timescale 1ns / 1ns
module Key_Filter(
Clk,
Reset_N,
Key,
Key_P_Flag,
Key_R_Flag,
Key_State
);
input Clk;
input Reset_N;
input Key;
output reg Key_P_Flag;
output reg Key_R_Flag;
output reg Key_State;
reg [1:0]R_Key;
reg [1:0]Sync_Key;
wire Pedge_Key;
wire Nedge_Key;
always@(posedge Clk)begin
Sync_Key <= #1 {Sync_Key[0],Key};
end
always@(posedge Clk)begin
R_Key <= #1 {R_Key[0],Sync_Key[1]};
// R_Key[0] <= Key;
// R_Key[1] <= R_Key[0];
end
//Posedge Check
assign Pedge_Key = (R_Key == 2'b01);
//Negedge Check
assign Nedge_Key = (R_Key == 2'b10);
reg [19:0]Counter;
localparam IDLE = 0;
reg [1:0]state;
always@(posedge Clk or negedge Reset_N)
if(!Reset_N)begin
state <= #1 0;
Counter <= #1 0;
Key_P_Flag <= #1 0;
Key_R_Flag <= #1 0;
Key_State <= #1 1;
end
else begin
case(state)
0:
begin
Key_R_Flag <= #1 0;
if(Nedge_Key)
state <= #1 1;
else
state <= #1 0;
end
1:
if((Pedge_Key)&&(Counter < 1000000 - 1))begin
state <= #1 0;
Counter <= #1 0;
end
else if(Counter >= 1000000 -1)begin
state <= #1 2;
Counter <= #1 0;
Key_P_Flag <= #1 1;
Key_State <= #1 0;
end
else begin
Counter <= #1 Counter + 1'd1;
state <= #1 1;
end
2:
begin
Key_P_Flag <= #1 0;
if(Pedge_Key)
state <= #1 3;
else
state <= #1 2;
end
3:
if((Nedge_Key)&&(Counter < 1000000 - 1))begin
state <= #1 2;
Counter <= #1 0;
end
else if(Counter >= 1000000 -1)begin
state <= #1 0;
Counter <= #1 0;
Key_R_Flag <= #1 1;
Key_State <= #1 1;
end
else begin
Counter <= #1 Counter + 1'd1;
state <= #1 3;
end
endcase
end
endmodule
仿真文件程序
`timescale 1ns / 1ns
module Key_Filter_tb();
reg Clk;
reg Reset_N;
reg Key;
wire Key_P_Flag;
wire Key_R_Flag;
wire Key_State;
Key_Filter Key_Filter(
Clk,
Reset_N,
Key,
Key_P_Flag,
Key_R_Flag,
Key_State
);
initial Clk = 1;
always #10 Clk = !Clk;
initial begin
Reset_N = 0;Key = 1;
#201;
Reset_N = 1;
#2000;
Key = 0;
#20000;
Key = 1;
#30000;
Key = 0;
#20000;
Key = 1;
#30000;
Key = 0;
#50000000;
Key = 1;
#30000;
Key = 0;
#20000;
Key = 1;
#30000;
Key = 0;
#20000;
Key = 1;
#50000000;
$stop;
end
endmodule
`timescale 1ns/1ns
// Random Function
module Key_Filter_tb2();
reg Clk;
reg Reset_N;
reg Key;
wire Key_P_Flag;
wire Key_R_Flag;
wire Key_State;
Key_Filter Key_Filter(
Clk,
Reset_N,
Key,
Key_P_Flag,
Key_R_Flag,
Key_State
);
initial Clk = 1;
always #10 Clk = !Clk;
initial begin
Reset_N = 0;Key = 1;
#201;
Reset_N = 1;
#2000;
press_Key(2);
$stop;
end
reg [24:0]rand;
task press_Key;
input [3:0]seed;
begin
Key = 1;
#20000000;
repeat(5)begin
rand = {$random(seed)}%10000000;
#rand Key = ~Key;
end
Key = 0;
#40000000;
repeat(5)begin
rand = {$random}%10000000;
#rand Key = ~Key;
end
Key = 1;
#40000000;
end
endtask
endmodule
使用Random函数进行设计仿真时,发现了原设计文件中未及时将Counter置零的问题,现已对设计文件修正。
文章来源:https://www.toymoban.com/news/detail-764987.html
文章来源地址https://www.toymoban.com/news/detail-764987.html
到了这里,关于FPGA入门学习笔记(十三)Vivado实现按键消抖的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!