module key_debounce(
input wire clk ,//system clock input 50M
input wire rst_n ,//system reset
input wire [1:0] key_in ,//key input,right and left
output reg [3:0] led
);
//==================================================
//parameter define
//==================================================
parameter CNT_MAX = 1000_000 - 1; //20ms counter max data
//==================================================
//internal signals
//==================================================
reg [21:0] cnt_time ;//timer counter
wire add_cnt_time;//add condition
wire end_cnt_time;//end condition
reg [3:0] key_dd ;//aim to Eliminate metastable state
reg key_flag ;//key has been push down flag
reg flag ;
reg [3:0] led_r ;//led control
//--------------------key_dd--------------------
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
key_dd <= 'd0;
end
else begin //延时缓存
key_dd <= {key_dd[1:0],key_in};//key_in delay 2 beats
end
end
wire key_sig=key_dd[3] & key_dd[2];//只要有键按下就标志
//--------------------cnt_time--------------------
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
cnt_time <= 'd0;
end
else if(add_cnt_time)begin //只有key低电平期间才计数
if(end_cnt_time)
cnt_time <= cnt_time;
else
cnt_time <= cnt_time + 1'b1;
end
else begin
cnt_time <= 'd0; //只要key为高电平就归零,保证了低电平持续时间超过20ms才被判定有效
end
end
assign add_cnt_time = (key_sig==1'b0); //有键按下就开始计数标志
//时间到达计数值最大值后保持标志,表示用户长按
assign end_cnt_time = add_cnt_time && cnt_time== CNT_MAX;
//-------------------------------------------
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
flag=1'b0; //指示ctime已经到达了最大值
else if(!key_sig && cnt_time==CNT_MAX)
flag=1'b1;
else
flag=1'b0;
end
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
key_flag<=1'b0; //指示本次按键成功
else if(cnt_time==CNT_MAX && flag==1'b0)
key_flag<=1'b1;
else
key_flag<=1'b0;
end
//--------------------led_r--------------------
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
led_r <= 4'b0001;
end
//延时时间到达20ms对缓存键值采样判断,长按由于key_flag无效所以不会连续移位
else if(cnt_time==CNT_MAX)begin
if(!key_dd[3] && key_flag)begin
led_r<={led_r[2:0],led_r[3]};//左移
end
else if(!key_dd[2] && key_flag)begin
led_r<={led_r[0],led_r[3:1]};//右移
end
end
else
led_r<=led_r;
end
//--------------------led--------------------
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
led <= 4'b1111;
end
else begin
led <= ~led_r; //由于低电平有效,所以需要进行反转赋值
end
end
endmodule
FPGA按键消抖2
最新推荐文章于 2024-07-25 17:21:09 发布