本文主要阐述在FPGA中如何针对按键的抖动进行按键消抖模块的设计。
(基于Altera EP4CE10 征途Pro开发板)
一.按键的原理
按键是最为常见的电子元器件之一,在电子设计中应用广泛。在FPGA的实验工程中,我们可以使用其作为系统复位信号或者控制信号的外部输入。开发板上使用的机械按键也是按键的一种,特点是:接触电阻小 ,手感好,按键按下或弹起时有“滴答”清脆声;但由于其构造和原理,在按键闭合及断开的瞬间均伴随有一连串的抖动。如下图所示,按键按下时候会存在抖动:
按键消抖的方法有硬件消抖与软件消抖。此处描述软件消抖的方法。即检测出按键闭合后执行一个延时程序,根据抖动的时间为5ms~10ms,我们产生一个20ms的延时,让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有键按下。
本节采用实现按键控制LED灯的方式设计按键消抖模块并实现按键控制LED灯的亮灭。
二. 模块框图
按键消抖模块名称key_filter. 输入信号key_in, 时钟信号sys_clk,复位信号sys_rst_n,以及输出信号key_flag.
三. 程序设计
已知抖动的时间是小于10 ms的,而当有20ms的时间内都没有抖动就说明按键已经处于稳定状态了。因此我们只需要找到最后一次抖动的时间,并开启20ms的计数,如果低电平持续保持20ms,那么既可以视为按键按下。
Verilog代码如下:
module key_filter
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire key_in ,
output reg key_flag
);
parameter CNT_MAX = 20'd999_999 ;
reg [19:0] cnt_20ms ;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_20ms <= 20'b0;
else if(key_in == 1'b1)
cnt_20ms <= 20'b0;
else if(cnt_20ms == CNT_MAX && key_in == 1'b0)
cnt_20ms <= cnt_20ms;
else
cnt_20ms <= cnt_20ms + 1'b1;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
key_flag <= 1'b1;
else if(cnt_20ms == CNT_MAX - 1'b1)
key_flag <= ~key_flag;
else
key_flag <= 1'b1 ;
endmodule
key_flag信号初始为高电平,当检测到按键按下(即最后一次抖动之后低电平持续维持20ms),将key_flag信号取反,即生成一个时钟周期的低电平信号,表明按键按下。
四. 按键控制LED灯亮灭状态的转换
1. 模块设计
该工程包含顶层模块led_key和底层模块key_filter。
RTL视图如下:
2. Verilog代码实现
顶层模块led_key中只需例化按键消抖模块并且描述一个带有使能信号的触发器即可。
module led_key
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire key_in ,
output reg led_out
);
key_filter key_filter_U0
(
.sys_clk (sys_clk ),
.sys_rst_n (sys_rst_n ),
.key_in (key_in ),
.key_flag (key_flag )
);
always@( posedge sys_clk or negedge sys_rst_n )
if( sys_rst_n == 1'b0 )
led_out <= 1'b1 ;
else if( key_flag == 1'b0 )
led_out <= ~ led_out ;
else
led_out <= led_out ;
endmodule
3. 程序运行烧录结果
按键控制LED灯的亮灭,初始状态LED灯灭,按下按键LED灯亮起,再次按下熄灭。