按键检测

注:key_in 默认为高电平,按键按下为低电平

其实只要检测到20ms内有持续为低电平,就可以认为按键有被按下,如下时序图

在抖动阶段,有检测到高电平的,计数器停止计数add_cnt = 0,计数器cnt清0 ,便于下一次重新计时。

 

module key_module(
    clk    ,
    rst_n  ,
    key_in ,
    key_vld 
);
parameter                      DATA_W       = 20          ;
parameter                      KEY_W       = 4           ;
parameter                   TIME_20MS = 500_000     ;

input                        clk                     ;
input                       rst_n                   ;
input                       key_in                  ;
output                      key_vld                 ;
reg                         key_vld                 ;
reg        [DATA_W-1:0]     cnt                     ;
wire                           add_cnt                 ;
wire                           end_cnt                 ;
reg                            flag                    ;
reg                         key_in_ff1              ;
reg                         key_in_ff0              ;

//检测20ms内持续为低电平,就被认为有按键被按下
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        cnt <= 20'b0;
    end
    else if(add_cnt)begin
        if(end_cnt)
            cnt <= 20'b0;
        else
            cnt <= cnt + 1'b1;
    end
    else begin
        cnt <= 0;
    end
end

assign add_cnt = flag==1'b0 && (key_in_ff1 != 1'b1);    //检测到有抖动,也就是检测有高的脉冲,计数器停止,cnt清0,便于下次重新计数
assign end_cnt = add_cnt && cnt == TIME_20MS - 1;

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        flag <= 1'b0;
    end
    else if(end_cnt)begin   //能够完整的计数到20ms结束, 说明已经检测到了按键有被按下
        flag <= 1'b1;
    end
    else if(key_in_ff1 == 1'b1)begin    //按键释放后,flag 置0 ,方便下次检测
        flag <= 1'b0;
    end
end


//打两拍,消除亚稳态
always  @(posedge clk)begin
    if(rst_n==1'b0)begin
        key_in_ff0 <= 0;
        key_in_ff1 <= 0;
    end
    else begin
        key_in_ff0 <= key_in    ;
        key_in_ff1 <= key_in_ff0;
    end
end

always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        key_vld <= 0;
    end
    else if(end_cnt)begin
        key_vld <= ~key_in_ff1;
    end
    else begin
        key_vld <= 0;
    end
end
endmodule
View Code

 

posted @ 2023-09-14 22:26  MyBooks  阅读(20)  评论(0编辑  收藏  举报