Debouncing Switches in Verilog / VHDL

Switches are used as primary inputs from the user in many of the circuits we design. They can be simple pushbutton or slider or toggle switches etc. They look fairly simple to interface. In fact, we all must have started our circuit design journey by plugging an LED and switch circuit on breadboard. So, what’s there so much to talk about switches? While they look so simple, there is something interesting about them that most of us overlook sometimes. An inherent behavior in almost all mechanical switches: Bouncing.

What is Bouncing !?

In an ideal world, switches are perfect. We expect following behavior for a simple switch with pull-down network when it switches ON/OFF:

Ideal Switch

Ideal switch in ideal world

But in real world, the contacts of a mechanical switch are not perfect. When a switch is pressed/released, it sort of shows some ‘hesitance’ and transits between ON/OFF states for duration of order of micro/milliseconds before it actually settles down to the final stable state. As a result, the actual behavior of a switch looks like:

Bouncing Switch

Bouncing switch in real life

Typically, bounce time can vary anywhere from 10 \text{ } \mu \text{s} to 100 \text{ ms} , depending on the quality of the switch. Hmm, doesn’t look good… does it?

Bouncing – can it be ignored ?

Whether bouncing of switch can turn things bad or can be simply ignored, depends on your application.

Suppose, you want to design a vote counting circuit where pressing the pushbutton increment the vote counter by one. Here, you surely don’t want to increment the votes by 10 or 15 times on a single press!!

On the other hand, if you simply want to turn an LED on or off with a switch, you may not have to worry about bouncing.

Let’s Debounce!

Debouncing is the technique used to suppress bouncing in switches and achieve close-to-ideal switching characteristics. Popular hardware-based techniques involve RC filter circuits and schmitt triggers. While this solves the underlying problem, it may not be always a cost and area effective solution, especially when there are many switches on board. Software based techniques are handy and low-cost solutions especially when switches are interfaced with digital circuitry like a micro-controller. It also adds another layer of protection from EMI noise which may behave like mechanical transitions in switch.

In this blog, we are more interested in software-based techniques. We will see how to implement one of the software algorithms in RTL. Our mission is to design a simple configurable debouncer which can be integrated while interfacing switches on FPGA/ASIC.

Debouncer Design

One popular technique is to poll the state of switch in fixed time intervals. Another technique is to poll the state of switch at the very first transition and then disable the polling for a fixed amount of time. Both have the problem of latency/delay regardless of whether the switch was pressed or not. Besides, the first technique has the disadvantage of sampling wrong value if the sampling interval falls within the bouncing time. The second technique has the disadvantage of sampling glitchy or noisy transitions by mistake as switch transitions.

Our debouncer will follow a more reliable technique. The debouncer will change the output state (to 1 or 0) only when either 1 or 0 is continuously sampled at input for a fixed amount of time. If it is not able to sample the same input state continuously, it is considered as unstable and glitchy transition. This will make sure that only a valid and stable switch transition is passed through to output. Also, since the switch inputs from the external world is asynchronous in nature, we would synchronize it to the Debouncer clock domain using classic 2FF synchronizer to avoid metastability issues.

The above technique can be easily implemented using counters in RTL. Counters have to be simply incremented when two consecutive states are sampled at same value. Otherwise, reset the counter. Once the counter reaches a threshold, the input state can be considered stable and the output state is updated. This kind of functions like schmitt trigger, where you have to cross the threshold for the other state to switch from the current state.

The following waveform shows how such a debouncer will behave with bouncing switches and ensures clean glitch-free state change at output.

Debouncing switch in Verilog / VHDL

Debouncer in simulation

The counter threshold can be computed as a function of system clock frequency and bouncing time of the switch, and then round it off to the higher and nearest power of two for efficient hardware implementation. The size of the N-bit counter can be calculated as:

N = \text{ceil } (log_{2}(\frac {T_{bounce}}{T_{clk}}))

Smaller the clock frequency, smaller the counter size. I recommend using clock < 10 \text{ MHz} , assuming bounce times are less than 10 \text{ ms} .

Debouncer – using Averaging technique

An improved version of debouncer can be designed by using averaging technique. The idea is to sample the input state and increment the counter only if a new state is sampled. If old state is sampled, decrement the counter. In this way the sampled state is filtered, and if the counter crosses the threshold (typically configured > 50\% bouncing time), then we can register it as the new state. The advantage of this technique is we have power saving in counters as the counter is idle when the switch state is idle. Also this debouncer has lesser latency than the one we discussed earlier.

Debouncer – Source Codes

The above discussed techniques were used to build our simple Debouncer, which is configurable and can debounce both ON/OFF transitions. Fully synthesisable and tested Debouncer source codes are available in my github for free use in your designs.

On-board Testing

Time to get the hands dirty! I have got a bunch of low-cost tactile toggle switches at home, which I tested out on breadboard with my DSO.

Switches being tested

Bouncing switch

Switching to ON state

Switching to OFF state

Seems like my toggle switch has a decent response compared to typical push buttons, but it still has a bouncing time of order of 100 \text{ } \mu \text{s} . Which is why, we shall now add our Debouncer at the switch output.

Debouncer was synthesised and tested on Basys-3 FPGA board with the same switch…. and my DSO says….

Debounced switch

Debounced switch state – ON

Debouncing switch

Debounced switch state – OFF

Oh yeah! We can notice pretty clean switch transitions after debouncing!! The yellow channel is the actual input with visible bouncing, and the green channel shows corresponding Debouncer output. Debouncer was configured for quite pessimistic scenario, i.e., for around 10 \text{ ms} bouncing time, hence the delay/latency as shown in the DSO.

Takeaways

Switches can be simple and yet nasty customers. Always be on the safer side by properly debouncing switches before you feed it to the hardware. Use dedicated circuitry or software routine for debouncing. In RTL designs, if feasible, integrate the debouncers in the RTL itself.

Support

Leave a comment or visit support for any queries/feedback regarding the content of this blog.
If you liked Chipmunk , don’t forget to follow!:

Follow Chipmunk

Loading

1 COMMENT

Queries?! Leave a comment ...

Chipmunk Logic™ © 2024 Contact me