Switch Debouncing

3/23/15

Mechanical switches tend to vibrate on the contacts when switching resulting in several closures and openings before the switch settles to a stable state (on or off).  The following image showes a typical switch bouncing from a high to low transition. 

If the switch is being used as a clock, several clock edges will be generated instead of just one. Consequently, it is necessary to debounce the switch. On way to do this is to simply wait until the transient phase (bouncing) is over and sample the switch. This can be done in Verilog with a counter and a clock source. There is a 50 MHz clock source available to the FPGA that we can count for a delay period and then sample the switch.

Counting KEY3 Presses With a De-Bouncer

The following module is an example of a debouncing application by counting KEY3 presses. A counter is used to count the presses, but KEY3 must be debounced first. If you want to see the consequences of not debouncing, you can connect KEY3 directly to the count block (use key3 instead of key3db) and you will see several counts accumulated with each KEY3 press.

module count_key3 ( //count key3 presses
input clk, //50 MHz clock (FPGA pin PIN_Y2)
input key3, //pushbutton KEY3 (FPGA pin PIN_R24)
output reg [2:0] count); //observe counts on RLEDs 0 -2
/*This module counts debounced presses of key3.
 *To see the effects of bouncing on the count, comment
 *out the instantiation of the debouncer module and replace
 *instances of key3db with key3
 */
wire key3db; //debounced key3

debouncer instdb(clk, key3, key3db); //Instantiate switch debouncer. Called outside of always block(s)

always @ (posedge key3db) //Use the debounced pushbutton key3db instead of key3 for all clock references
begin
count <= count + 1'b1;
end
endmodule

The De-Bouncer

The following module is a module that you can use in your code for debouncing the pushbuttons.

module debouncer(
    input clk, //this is a 50MHz clock provided on FPGA pin PIN_Y2
    input PB,  //this is the input to be debounced
     output reg PB_state  //this is the debounced switch
);
/*This module debounces the pushbutton PB.
 *It can be added to your project files and called as is:
 *DO NOT EDIT THIS MODULE
 */

// Synchronize the switch input to the clock
reg PB_sync_0;
always @(posedge clk) PB_sync_0 <= PB;
reg PB_sync_1;
always @(posedge clk) PB_sync_1 <= PB_sync_0;

// Debounce the switch
reg [15:0] PB_cnt;
always @(posedge clk)
if(PB_state==PB_sync_1)
    PB_cnt <= 0;
else
begin
    PB_cnt <= PB_cnt + 1'b1; 
    if(PB_cnt == 16'hffff) PB_state <= ~PB_state; 
end
endmodule