Verilog——FPGA button debounce operation

FPGA button debounce operation

Target

  • Verilog programming language to achieve key debounce.
  • Module: key_delay, the module can input the key debounce delay time parameter.
  • Input: clock, reset, key signal key_in
  • Output: debounced key signal key_out

code

  • Module implementation code:
module key_delay
#(
    parameter       FREQ        =       200     ,//MHz, 晶振频率
    parameter       DLY_TIME    =       20_000   //us, 按键延迟时间
)
(
    input           sys_clk_p           ,
    input           sys_clk_n           ,
    input           rst_n               ,
    input           key_in              ,
    output  reg     key_out             
);
localparam      MAX_TIME    =   FREQ * DLY_TIME;//延时时间对应计数值
wire            clk200M     ;
reg [31:0]      cnt         ; 
wire            max_flag    ;//计数器达到最大值
reg             key_in_r1   ;//按键key_in节拍
reg             key_in_r2   ;
wire            key_act     ;//按键动作标志
//clk200M, 原语,差分时钟转单端
IBUFDS
#(
    .DIFF_TERM      ("FALSE"        ),// Differential Termination
    .IBUF_LOW_PWR   ("TRUE"         ),// Low power="TRUE", Highest performance="FALSE" 
    .IOSTANDARD     ("DEFAULT"      ) // Specify the input I/O standard
) IBUFDS_inst
(
    .O              (clk200M        ),// Buffer output
    .I              (sys_clk_p      ),// Diff_p buffer input (connect directly to top-level port)
    .IB             (sys_clk_n      ) // Diff_n buffer input (connect directly to top-level port)
);
//key_in_r1, key_in_r2,打节拍
always @(posedge clk200M) begin
    key_in_r1 <= key_in;
    key_in_r2 <= key_in_r1;
end
//key_act, 按键有动作
assign key_act = key_in_r1 ^ key_in_r2;
//max_flag, 计数达到最大值
assign max_flag = (cnt == MAX_TIME) ? 1'b1 : 1'b0;
//cnt
always @(posedge clk200M) begin
    case({key_act, max_flag})
        2'b00://按键无动作, 且计数未达到最大值
            cnt <= cnt + 'd1;
        2'b01://按键无动作, 且计数达到最大值
            cnt <= cnt;
        default://按键有动作
            cnt <= 'd0;
    endcase
end
//key_out
always @(posedge clk200M or negedge rst_n) begin
    if(~rst_n)
        key_out <= key_in_r2;
    else if(cnt == MAX_TIME)
        key_out <= key_in_r2;
    else
        key_out <= key_out;
end
endmodule

*Simulation code

`timescale 1ns / 1ps
module tb_key_delay;

reg     sys_clk_p;
wire    sys_clk_n;
reg     rst_n;
reg     key_in;
wire    key_out;
//-----------------------------------------------
integer i;

key_delay
#(
    .FREQ           (200        ),//MHz, 晶振频率
    .DLY_TIME       (1          ) //us, 按键延迟时间
)
inst_key_delay
(
    .sys_clk_p      (sys_clk_p  ),
    .sys_clk_n      (sys_clk_n  ),
    .rst_n          (rst_n      ),
    .key_in         (key_in     ),
    .key_out        (key_out    )
);


initial begin
    sys_clk_p = 0;
    rst_n = 0;
    key_in = 0;
    #100;
    rst_n = 1;

    #100;
    for(i = 0; i <= 10; i = i + 1) begin
        key_in = ~key_in;
        #30;
    end

    #1500;

    for(i = 0; i <= 10; i = i + 1) begin
        key_in = ~key_in;
        #30;
    end
    
    #1500;

    for(i = 0; i <= 10; i = i + 1) begin
        key_in = ~key_in;
        #30;
    end
end
//时钟
always #2.5 sys_clk_p = ~sys_clk_p;
assign sys_clk_n = ~sys_clk_p;

endmodule
  • Simulation results
    Insert image description here

Guess you like

Origin blog.csdn.net/family5love/article/details/109747057