FPGA按键消抖2

module  key_debounce(
    input   wire            clk     	,//system clock input 50M
    input   wire            rst_n       ,//system reset
    input   wire    [1:0]   key_in      ,//key input,right and left
    output  reg     [3:0]   led
);

//==================================================
//parameter define
//==================================================
parameter   CNT_MAX =   1000_000 - 1;   //20ms counter max data

//==================================================
//internal signals
//==================================================
reg     [21:0]  cnt_time    ;//timer counter
wire            add_cnt_time;//add condition
wire            end_cnt_time;//end condition

reg     [3:0]   key_dd      ;//aim to Eliminate metastable state
reg             key_flag    ;//key has been push down flag
reg             flag        ;
reg     [3:0]   led_r       ;//led control   


//--------------------key_dd--------------------
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        key_dd <= 'd0;
    end
    else begin       //延时缓存
        key_dd <= {key_dd[1:0],key_in};//key_in delay 2 beats
    end
end

wire key_sig=key_dd[3] & key_dd[2];//只要有键按下就标志


//--------------------cnt_time--------------------
always @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        cnt_time <= 'd0;
    end
    else if(add_cnt_time)begin     //只有key低电平期间才计数
        if(end_cnt_time)
            cnt_time <= cnt_time;
        else
            cnt_time <= cnt_time + 1'b1;
    end
    else begin 
        cnt_time <= 'd0; //只要key为高电平就归零,保证了低电平持续时间超过20ms才被判定有效
    end 
end

assign add_cnt_time = (key_sig==1'b0); //有键按下就开始计数标志
 //时间到达计数值最大值后保持标志,表示用户长按
assign end_cnt_time = add_cnt_time && cnt_time== CNT_MAX; 
//-------------------------------------------

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        flag=1'b0;  //指示ctime已经到达了最大值
    else if(!key_sig && cnt_time==CNT_MAX)
        flag=1'b1;
    else
        flag=1'b0;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        key_flag<=1'b0;   //指示本次按键成功
    else if(cnt_time==CNT_MAX && flag==1'b0)
        key_flag<=1'b1;
    else
        key_flag<=1'b0;
end


//--------------------led_r--------------------
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        led_r <= 4'b0001;
    end
    //延时时间到达20ms对缓存键值采样判断,长按由于key_flag无效所以不会连续移位
    else if(cnt_time==CNT_MAX)begin 
        if(!key_dd[3] && key_flag)begin
            led_r<={led_r[2:0],led_r[3]};//左移
        end
        else if(!key_dd[2] && key_flag)begin
            led_r<={led_r[0],led_r[3:1]};//右移
        end
    end
    else 
        led_r<=led_r;
end


//--------------------led--------------------
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        led <= 4'b1111;
    end
    else begin
        led <= ~led_r; //由于低电平有效,所以需要进行反转赋值
    end
end

endmodule

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值