FPGA按键消抖模块设计

        按键在日常生活中是十分常见的器件,但是在闭合及断开的一瞬间会有一连串的抖动。在单片机的设计中可以采用延时检测的方式去判断该按键是否按下,在FPGA设计中是不行的。在平时的设计中会有硬件和软件两种方式消抖。此处在用的是软件消抖。

       按键的抖动一般在5ms至10ms之间,所以设计一个20ms计时器,当计时器结束时是什么电平就是什么电平。

        以黑金板卡为例,当按键按下为低电平,未按下为高。那么在抖动时,只要对应端口检测到高电平时计数器清零,低电平开始计数。思路是这样的思路,那么就可以开始编程。

当计数器达到20ms时,输出一个flag,当输出flag时表示该按键按下。代码如下:

module key_filter
#(
    parameter  MAX_CNT= 20'd1_000_000
)
(
    input   wire    sys_clk,
    input   wire    sys_rst_n,
    input   wire    pi_key,

    output  reg     po_flag
);

reg [19:0] cnt_20ms;

//cnt_20ms:20ms计数器,当输入电平为0同时计满时,保持999_999
always @(posedge sys_clk or negedge sys_rst_n) begin
    if (~sys_rst_n) begin
        cnt_20ms <= 20'd0;
    end
    else if(pi_key == 1'b1) begin
        cnt_20ms <= 20'd0;
    end
    else if ((pi_key == 1'b0)&&(cnt_20ms == MAX_CNT - 1'd1)) begin
        cnt_20ms <= cnt_20ms;
    end   
    else begin
        cnt_20ms <= cnt_20ms + 1'd1;
    end 
end

//po_flag:在计数器计至999_998时输出po_flag
always @(posedge sys_clk or negedge sys_rst_n) begin
    if (~sys_rst_n) begin
        po_flag <= 1'b0;
    end
    else if (cnt_20ms == MAX_CNT - 2'd2) begin
        po_flag <= 1'b1;
    end
    else begin
        po_flag <= 1'b0;
    end
end

Testbench如下

`timescale 1ns / 1ns

module tb_key_filter();

parameter   CNT_1MS  = 20'd19,
            CNT_11MS = 21'd69,
            CNT_41MS = 22'd149,
            CNT_51MS = 22'd199,
            CNT_60MS = 22'd249;



//key_filter Parameters
parameter PERIOD    = 10           ;

//wire define
wire    key_flag;

//reg define
reg    clk;
reg    rst_n;
reg    key_in;
reg    tb_cnt;

initial
begin
    forever #(PERIOD)  clk=~clk;
end

initial
begin
    #(PERIOD*2) rst_n  =  1;
end

//tb_cnt:通过该计数器,模拟按键抖动过程
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        tb_cnt <= 22'd0;
    end
    else if (tb_cnt == CNT_60MS) begin
        tb_cnt <= 22'd0;
    end
    else begin
        tb_cnt <= tb_cnt + 1'd1;
    end
end

//key_in:模拟输入,1ms~11ms,51ms~60ms随机抖动。11ms~51ms之间表示按键按下.
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        key_in <= 1'b1;
    end
    else if((tb_cnt >= CNT_1MS) && (tb_cnt <= CNT_11MS) || (tb_cnt >= CNT_51MS)&&(tb_cnt <= CNT_60MS)) begin
        key_in <= {$random}%2;
    end
    else if((tb_cnt > CNT_11MS)&&(tb_cnt < CNT_51MS)) begin
        key_in <= 1'b0;
    end
    else begin
        key_in <= 1'b1;
    end
end


key_filter 
#(
    .CNT_MAX    (5'd24)
)
key_filter_inst(
    .sys_clk                 ( clk                 ),
    .sys_rst_n               ( rst_n               ),
    .pi_key                  ( key_in              ),

    .po_flag                 ( key_flag            )
);

modelsim仿真,由于我并没有建立该工程,但是这个模块在另外一个工程中使用,所以用另一个仿真放出。

        tb文件中写当tb_cnt计数为19时,开始产生随机数,一直到计数器为69时随机数产生结束。由此可见随机抖动时测试是正常的。 

 有上图可知按键在23时时有一个flag拉高的。

按键断开也是同理,

 这就是按键抖动软件消除的FPGA实现,最后给出总体仿真图。

如果有错欢迎指出。

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值