我本以为按键直接可以用硬件检测到输入,然后就可以直接连接LED输出来达到按键的目的,但是我如果那样子写程序,我最后得到的效果是所有灯全亮,并没有能实现按键效果。之后我看了范例程序,他用到了D触发器。
原因的话请见下文:
是这样的,第一个D触发器,是用来检测时钟信号的上升或者下降沿,然后来一直持续读取按键的状态,只要按键被按下,电平被拉低,那么D触发器的反相输出端连接的LED就会被点亮。
但是按键按下去的时候,D触发器的建立和保持时间可能会影响信号的进入,可能会进入一种亚稳态,即在高电平和低电平之间变化,这对后面的电路会造成不良的影响。
为了去除这种建立和保持时间造成的影响,就要用2个D触发器,在这里,第二个D触发器就可以来实现这种功能。因为第二个D触发器,如果前一个D触发器进入亚稳态,那么他的输出就不会满足第二个D触发器的建立和保持时间的要求,这样就不会进入第二个D触发器从而影响后面的电路了。所以一般对于这种按键检测电路,通常都带上2个D触发器来抑制按键消抖。
虽然说2个D触发器可能同时进入亚稳态,不过几率比较小,所以2个D触发器还是比较稳的
普及一下,触发器的建立时间是指在触发器的时钟信号到达之前,输入信号必须保持一种单一状态的时间,如果不能达到那个时间长度,则输入信号不会被打入触发器。同样的,保持时间则是,在时钟信号到来以后,信号要保持不变的时间。必须同时满足建立时间和保持时间,触发器才能起作用。
最后,带上双D触发器的按键代码:
`timescale 1ns / 1ps
module Keys
(
input Clk,
input [3:0]Key, //Detect which Key
output [3:0]LED //Why wire type varible can drive LED?
);
reg[3:0]D; //a four bit D flip-flop
reg[3:0]D1;
//D flip-flop
always@(posedge Clk)
begin
D <= ~Key;
end
always@(posedge Clk)
begin
D1 <= D;
end
assign LED = D1;
endmodule