热度 16
2013-12-24 22:18
957 次阅读|
0 个评论
看完特权同学的视频后,自己做按键消抖这课,上次出了点问题,一直没成功,今天终于完成了。 module key_shake( clk,rst_n,key_n, led ); input clk; //输入时钟,50MHz input rst_n; //复位信号,低电平有效 input key_n; //8个按键输入,低电平表示按下 output led; //8个led灯,由8个按键控制亮灭 reg 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 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 key_in=key_rst_b (~key_rst) ; //key_in对按键进行边沿检测的结果 reg 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 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 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 key_ctrl=key_low_b (key_low);//对消抖后的按键值进行边缘检测,检测是哪个按键被按下 reg 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 检查之后发现问题出在了第二次进行按键值边缘检测的地方,之前是将第一次检测后的按键值放到了第二级寄存器中,而不是实际检测到的,改完之后没问题了。