按键消抖模块的设计与验证

1. 实验目标

        本章节中,我们要根据机械按键的构造与原理,设计并实现按键消抖模块。以开发板上的物理按键作为输入信号,使用设计的按键消抖模块对输入的按键信号进行消抖处理, 输出能够正常使用的按键触发信号。

2. 理论学习

        我们所使用的按键开关为机械弹性开关,当机械触点断开、闭合时, 由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而做的措施就是按键消抖。

        抖动时间的长短由按键的机械特性决定,一般为 5ms~10ms。按键稳定闭合时间的长短则是由操作人员的按键动作决定的,一般为零点几秒至数秒。按键抖动会引起一次按键被误读多次。为确保控制器对按键的一次闭合仅作一次处理,必须去除按键的抖动。在按键闭合稳定时读取按键的状态,并且必须判别到按键释放稳定后再作处理。

消抖是为了避免在按键按下或是抬起时电平剧烈抖动带来的影响。按键的消抖,可用硬件或软件两种方法。

2.1 硬件消抖

        通过加一个RS触发器来进行按键消抖,但硬件消抖会使用一些额外的器件占用电路板上的空间,从而在一定程度上增加了 PCB 布局布线的复杂度。

2.2 软件消抖

        如果按键个数较多,常用软件方法去抖,即检测出按键闭合后执行一个延时程序,根据抖动的时间为 5ms~10ms,我们产生一个 20ms 的延时,让前沿抖动消失后再一次检测键的状态,如果仍保持闭合状态电平,则确认为真正有键按下。

        用软件消抖的方式来实现去抖动的操作,去抖动后的效果是当按键按下后能够准确检测到按键被按下了一次,而不会因机械抖动发生按键重复多次按下的现象。

3. 实战演练

        设计并实现一个按键消抖模块,将外部输入的单比特按键信号做消抖处理后输出,输出信号正常可被其他模块调用。

3.1 按键消抖模块框图

        一个输入信号就是按键的输入 key_in,输出信号为去抖动后的稳定的按键信号 key_flag(去抖后按键被按下的标志信号)。

3.2 波形图

CLK 50MHZ = 20ns     计数20ms 计数值为M = 999_999

4 代码编写

module key_filter
#(
    parameter CNT_MAX = 20'd999_999
)
(
    input wire sys_clk   ,
    input wire sys_rst_n ,
    input wire key_in    ,
    
    output reg key_flag
);


reg [19:0] cnt_20ms;

always @ (posedge sys_clk or negedge sys_rst_n)
    if (sys_clk == 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'b0;
    else if (cnt_20ms == CNT_MAX - 1'b1)
        key_flag <= 1'b1;
    else 
        key_flag <= 1'b0;

endmodule

5. 仿真验证

`timescale 1ns / 1ns
module tb_key_filter();

//parameter define
//为了缩短仿真时间,我们将参数化的时间值改小
//但位宽依然定义和参数名的值保持一致
//也可以将这些参数值改成和参数名的值一致
parameter   CNT_1MS = 20'd19 ,
            CNT_11MS = 21'd69 ,
            CNT_41MS = 22'd149 ,
            CNT_51MS = 22'd199 ,
            CNT_60MS = 22'd249 ;

reg sys_clk;
reg sys_rst_n;
reg key_in;

reg [7:0] tb_cnt;

wire key_flag;

initial 
    begin
        sys_clk = 1'b1;
        sys_rst_n <= 1'b0;
        #20
        sys_rst_n <= 1'b1;
    end
    
always #10 sys_clk = ~sys_clk;

//tb_cnt:按键过程计数器,通过该计数器的计数时间来模拟按键的抖动过程
always @(posedge sys_clk or negedge sys_rst_n)
    if (sys_rst_n == 1'b0)
        tb_cnt <= 8'd0;
    else if (tb_cnt == CNT_60MS)
        tb_cnt <= 8'd0;
    else 
        tb_cnt <= tb_cnt + 8'd1;
        
//key_in:产生输入随机数,模拟按键的输入情况
always @(posedge sys_clk or negedge sys_rst_n)
    if (sys_rst_n == 1'b0)
        key_in <= 1'b1;
    else if ((tb_cnt >= CNT_1MS && tb_cnt <= CNT_11MS)||(tb_cnt >= CNT_41MS&&tb_cnt <= CNT_51MS))
        key_in <= {$random} % 2;
    else if ((tb_cnt >= CNT_11MS)&&(tb_cnt <= CNT_41MS))
        key_in <= 1'b0;
    else
        key_in <= 1'b1;

key_filter
#(
    .CNT_MAX (20'd24)
    //修改的 CNT_MAX 值一定要小于(CNT_41MS - CNT_11MS)
    //否则就会表现为按键一直处于“抖动状态”而没有“稳定状态”
    //无法模拟出按键消抖的效果
)
key_filter_inst
(
    .sys_clk   (sys_clk),
    .sys_rst_n (sys_rst_n),
    .key_in    (key_in),
    
    .key_flag  (key_flag)
);

endmodule

5. 仿真波形分析

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值