关于FPGA的按键消抖问题
相关的Verilog HDL代码如下:
wire key_send1_down,key_send2_down;
reg [2:0] key_send1_reg,key_send2_reg;
always @(posedge clk_9600 or negedge reset_n)
begin
if (!reset_n)
begin
key_send1_reg <= 3'd0;
key_send2_reg <= 3'd0;
end
else
begin
key_send1_reg[0] <= key_send1;
key_send1_reg[2:1] <= key_send1_reg[1:0];
key_send2_reg[0] <= key_send2;
key_send2_reg[2:1] <= key_send2_reg[1:0];
end
end
assign key_send1_down = key_send1_reg[2] && ~key_send1_reg[1];
assign key_send2_down = key_send2_reg[2] && ~key_send2_reg[1];
这种方法还是挺好的,只不过理解起来有点困难,在网络上有大概有两种方法,一种是类似于前面的这种方法,另一种是计数延时5~10ms来实现。相应的参考网址为:
http://wenku.baidu.com/view/aef08500b52acfc789ebc932.html
http://bbs.eeworld.com.cn/thread-106469-1-1.html
类似于前面的方法如下所示:
具体的Veilog HDL实现有:
reg [3:0] key_press;
//用于存放和读取按键的值,设置为reg可以写又可以读。key_press相当于原寄存器
always@(posedge clk or negedge rst_n)
if(!rst_n)
key_press <= 4'b1111;//复位
else
key_press <={sw4_n,sw3_n,sw2_n,sw1_n};
reg[3:0] key_press_r;
//每个时钟周期的上升沿将low_sw信号锁存到low_press_r中,low_press_r相当于新寄存器
always@(posedge clk or negedge rst_n)
if(!rst_n)
low_press_r <= 4'b1111;
else
key_press_r <= key_press;
wire[3:0] key_pressed = key_press_r & (~key_press);//实现检测是否有键按下,同时可以实现哪个键被按下。
最后一句代码,关键要注意两个寄存其中的时序关系。
但是这个方法,只能检测对于按下为低电平的电路,对于按下为高电平的,不能实现,因为只能在松开过程检测到有按键按下。
但是,这种方法消抖的实现还是不太好,经常就是按一次按键发送了两个甚至好几个数据。而另一种方法,就是通过计数实现延时判断的方法,这种方法目前还是不能实现。
实际上,前面的这种方法,消抖功能还是不太好。前面只用3位寄存器。而我猜想,如果把寄存器的位数该大一点,比如说改为4,那么,是否可以呢。这个当然目前还没有测试。