原创 按键消抖部分

2013-12-24 22:18 942 16 16 分类: FPGA/CPLD

看完特权同学的视频后,自己做按键消抖这课,上次出了点问题,一直没成功,今天终于完成了。

 
module key_shake(
clk,rst_n,key_n,
led
 );
 
input clk;  //输入时钟,50MHz
input rst_n; //复位信号,低电平有效
input [7:0] key_n; //8个按键输入,低电平表示按下
 
output [7:0] led;  //8个led灯,由8个按键控制亮灭
 
reg [7:0] key_rst;//存储当前按键状态值
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
key_rst<=8'b1111_1111;//检测到复位时,当前按键状态赋值为高电平,未按下
else
key_rst<=key_n;//若没有复位,则按键值为按键的实际状态
end
 
reg [7:0] key_rst_b ; //存储前一时刻的按键状态 
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
key_rst_b<=8'b1111_1111;
else
key_rst_b<=key_rst; //将按键状态存储到key_rst_b中,而key_rst中继续存储下一个按键状态
end
wire [7:0] key_in=key_rst_b & (~key_rst) ; //key_in对按键进行边沿检测的结果
 
reg [19:0] clk_cnt;//时钟计数器
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
clk_cnt<=0;
else if(key_in)
clk_cnt<=0; //若key_in不为0时,表示检测到按键按下,这时可能是抖动,也可能是按键按下,
           //故计数器清0,再重新计数20ms,防止是抖动。
else
clk_cnt<=clk_cnt+1'b1; //若未检测到按键的变化,则将计数器加1,一直计数到20ms
end
 
reg [7:0] key_low; //定义消除抖动之后的按键状态
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
key_low<=8'b1111_1111;
else if(clk_cnt==20'hfffff)
key_low<=key_n; //计数器计到20ms时,已经消除抖动,将此时的按键值锁存到key_low
end
 
reg [7:0] key_low_b;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
key_low_b<=8'b1111_1111;
else 
key_low_b<=key_low; //将key_low中的按键值锁存到key_low_b,即锁存前一时刻的按键值
end
//上边的key_low锁存的值是按键的状态,并将此状态锁存20ms,而key_low_b锁存的是每个时钟周期的
//按键状,若按键状态发生变化,可以通过边缘检测出来,从而检测到是哪个按键被按下的
wire [7:0] key_ctrl=key_low_b & (key_low);//对消抖后的按键值进行边缘检测,检测是哪个按键被按下
 
reg [7:0] led_r;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
led_r<=8'b1111_1111;
else if(key_ctrl)
led_r<=key_ctrl;
else
led_r<=led_r;
end
 
assign led=led_r;
 
endmodule
 
 
             
检查之后发现问题出在了第二次进行按键值边缘检测的地方,之前是将第一次检测后的按键值放到了第二级寄存器中,而不是实际检测到的,改完之后没问题了。
 
 

文章评论0条评论)

登录后参与讨论
我要评论
0
16
关闭 站长推荐上一条 /2 下一条