FPGA项目(3)--按键消抖

        机械按键是平时做设计的时候很常见的电子元件,但是,不管是应用在单片机的场合还是FPGA的场合,这种按键出来的信号如果不加任何的处理,是无法被单片机/FPGA直接使用的。下面看一个波形图:

FPGA项目(3)--按键消抖_第1张图片

        key_in是没有经过处理的按键按下后的原始信号,不加处理的话,就会导致单片机误认为按键被按下了很多次,对于FPGA而言,FPGA在50M高速时钟的驱动下,它会认为按键被按下了n多次!!!

        所以要对按键进行消抖处理。FPGA按键消抖的基本思路是:使用一个计数器,记录按键按下的时间。如果按键在规定的时间内一直处于按下的状态,那么就在计数器计数值要满的时候,将按键输出信号标记为1,输出一个周期的高电平,表示已经读取到按键被按下了。

        下面再给一个波形图用于说明:

        FPGA项目(3)--按键消抖_第2张图片 

 

        这里的cnt_20ms就是用于记录按键按下的持续时间的。在50M时钟的驱动下,计数器从0记录到999999,说明时间已经过去了20ms。也就是说,只要按键按下的时间持续了20ms,就认为本次按键按下有效。上图中,在计数器记录到999998时,key_flag(按键消抖后输出的信号,后续模块如果要读取按键的话,就是读取这个信号)就输出1,并且在计数到999999时,只要按键不松手,计数值就一直维持在999999不改变,这样可以避免多次重复触发。

       下面给出设计的代码:

        

module key_filter
#(parameter WIDTH = 20'd99)		//因为是仿真,所以该值要小一点。如果是下载到实物上,这个值就改为999_999
(
input			sys_clk,sys_rest,key_in,
output	 reg 	key_flag
);

reg[19:0]	CNT_20MS;

always @(posedge sys_clk or negedge sys_rest) begin
	if(!sys_rest)
		CNT_20MS<=20'd0;
	else if(key_in==1'b1)				//按键未按下为1   按下为0
		CNT_20MS<=20'd0;
	else if(CNT_20MS==WIDTH)
		CNT_20MS<=WIDTH;
	else
		CNT_20MS<=CNT_20MS+1;
end

always @(posedge sys_clk or negedge sys_rest) begin
	if(!sys_rest)
		key_flag<=1'b0;
	else if(CNT_20MS==WIDTH-1)
		key_flag<=1'b1;
	else
		key_flag<=1'b0;
end

endmodule

        下面看该模块的仿真图:

        

         因为是仿真,所以将计数器记录的最大值改为了99,从仿真图确实可以看出,当按键按下后,时钟过了99个周期时,key_flag确实输出了一个周期的高电平。

你可能感兴趣的:(FPGA项目,fpga开发,嵌入式硬件)