按键消抖
module Debounce # ( parameter KEY_WIDTH = 1 //消抖按键数量 ) ( input clk, //系统时钟 12MHz input rst_n, //系统复位 低有效 input [KEY_WIDTH-1:0] key_n, //按键信号输入 output reg [KEY_WIDTH-1:0] key_jit, //延时消抖输出 output wire[KEY_WIDTH-1:0] key_pulse, //消抖脉冲输出 output reg [KEY_WIDTH-1:0] key_state //消抖翻转输出 ); localparam CNT_NUM = 18'd240000;//20ms计时 reg [KEY_WIDTH-1:0] key_n_r,key_n_r1,key_n_r2;//延时锁存,消除亚稳态 always@(posedge clk) begin key_n_r <= key_n; key_n_r1 <= key_n_r; key_n_r2 <= key_n_r1; end wire key_edge = (key_n_r1 == key_n_r2)? 1'b0:1'b1; //边沿检测 reg [17:0] cnt; //20ms延时 always@(posedge clk or negedge rst_n) if(!rst_n) cnt <= 18'd0; else if(key_edge) cnt <= 18'd0; else cnt <= cnt +1'b1; always@(posedge clk or negedge rst_n)//延时20ms时间采样,得到延时消抖输出 if(!rst_n) key_jit <= {KEY_WIDTH{1'b1}}; else if(cnt == CNT_NUM-1) key_jit <= key_n_r2; reg [KEY_WIDTH-1:0] key_jit_r;//对延时消抖输出key_jit延迟锁存 always @(posedge clk or negedge rst_n) if (!rst_n) key_jit_r <= {KEY_WIDTH{1'b1}}; else key_jit_r <= key_jit; //检测延时消抖输出key_jit下降沿,得到消抖脉冲输出 assign key_pulse = key_jit_r & ( ~key_jit); //根据消抖脉冲信号,对应按键输出翻转,像自锁开关一样 always @(posedge clk or negedge rst_n) if (!rst_n) key_state <= {KEY_WIDTH{1'b1}}; else if(key_pulse) key_state <= key_state ^ key_pulse; //当按键未按下时,key_pluse为0,key_state =1; //当第一次按下时,key_pluse=1,key_state=1^1=0; //当第二次按下时,key_pluse=1;key_state=0^1=1;实现翻转 else key_state <= key_state; endmodule