FPGARelated.com
Forums

vhdl code for debouncing push button

Started by Zhane July 27, 2008
are there any vhdl codes that are available for free to debounce the
pushbutton on my spartan 3E?

I require the push button to generate only 1 clock for 50mhz only upon
release.

I've gotten some code from the net but aint sure if it does what I
need....

==============================================================

library ieee;
use ieee.std_logic_1164.all;

entity debouncer is
	port (clk,reset: in std_logic; -- clk frequency = 50Mhz
			pb: in std_logic;
			pb_debounced: out std_logic
			);
end entity debouncer;

architecture rtl of debouncer is
	signal count500000 : integer range 0 to 499999;
	signal clk_100Hz: std_logic;
	signal pb_sampled: std_logic;
begin

div_100Hz: process(clk,reset) is
begin
	if reset ='1' then
		clk_100Hz <= '0';
		count500000 <= 0;
	elsif rising_edge(clk) then
		if count500000 = 499999 then
			count500000 <= 0;
			clk_100Hz <='1';
		else
			count500000 <= count500000 + 1;
			clk_100Hz <='0';
		end if;
	end if;
end process div_100Hz;

debounce_pb: process(clk) is
begin
	if rising_edge(clk) then
		if clk_100Hz ='1' then
			if pb = pb_sampled then
				pb_debounced <= pb;
			end if;
			pb_sampled <= pb;
		end if;
	end if;
end process debounce_pb;

end architecture rtl;
==================================================

pls advise
I think whether this code works for you depends on the push button.  I
have some tactile switches that initially showed *no* bouncing.  After
just a week or two of use they bounce so badly that it is impossible
to debounce them.

The best switch to debounce is a double throw switch.  The FF stays in
a given state until the other contact is made.  Very simple, but it
requires two inputs and a more complex switch.

Rick


On Jul 27, 9:41 am, Zhane <m...@hotmail.com> wrote:
> are there any vhdl codes that are available for free to debounce the > pushbutton on my spartan 3E? > > I require the push button to generate only 1 clock for 50mhz only upon > release. > > I've gotten some code from the net but aint sure if it does what I > need.... > > ============================================================== > > library ieee; > use ieee.std_logic_1164.all; > > entity debouncer is > port (clk,reset: in std_logic; -- clk frequency = 50Mhz > pb: in std_logic; > pb_debounced: out std_logic > ); > end entity debouncer; > > architecture rtl of debouncer is > signal count500000 : integer range 0 to 499999; > signal clk_100Hz: std_logic; > signal pb_sampled: std_logic; > begin > > div_100Hz: process(clk,reset) is > begin > if reset ='1' then > clk_100Hz <= '0'; > count500000 <= 0; > elsif rising_edge(clk) then > if count500000 = 499999 then > count500000 <= 0; > clk_100Hz <='1'; > else > count500000 <= count500000 + 1; > clk_100Hz <='0'; > end if; > end if; > end process div_100Hz; > > debounce_pb: process(clk) is > begin > if rising_edge(clk) then > if clk_100Hz ='1' then > if pb = pb_sampled then > pb_debounced <= pb; > end if; > pb_sampled <= pb; > end if; > end if; > end process debounce_pb; > > end architecture rtl; > ================================================== > > pls advise
Zhane wrote:

> debounce_pb: process(clk) is > begin > if rising_edge(clk) then > if clk_100Hz ='1' then > if pb = pb_sampled then > pb_debounced <= pb; > end if; > pb_sampled <= pb; > end if; > end if; > end process debounce_pb;
Usually every unsychronized external input should be latched. A switch doesn't change very often, so the probality to cause problems is very low, but I would add another signal, something like this: debounce_pb: process(clk) is begin if rising_edge(clk) then if clk_100Hz ='1' then if pb_latched = pb_sampled then pb_debounced <= pb_latched; end if; pb_sampled <= pb_latched; pb_latched <= pb; end if; end if; end process debounce_pb; The rest of the code looks ok. It filters single spikes, which are shorter than 20ms and filters any bouncing sequence shorter than 10ms. I would add a generic parameter for specifying the clock frequency to make the entity more resuable. -- Frank Buss, fb@frank-buss.de http://www.frank-buss.de, http://www.it4-systems.de
rickman wrote:
> I think whether this code works for you depends on the push button. I > have some tactile switches that initially showed *no* bouncing. After > just a week or two of use they bounce so badly that it is impossible > to debounce them. > > The best switch to debounce is a double throw switch. The FF stays in > a given state until the other contact is made. Very simple, but it > requires two inputs and a more complex switch.
Yes, a SPCO switch (classic Micro-switch action) is more complex, as it has an extra contact, but I cannot see the 'requires two inputs' in any I have used ? Wire one end to Vcc, one to GND, and the contact to the Pin, and enable the Pin-Keep if you like, and you are done. Did you mean a SET/RESET action, which needs two pins, and two resistors (can be pin-pulldowns) ? SPCO switches should be the default on demo-boards, as you can also clock off them... -jg
"Zhane" <me75@hotmail.com> wrote in message 
news:ab0ae7bc-b7a5-47bd-bc2e-33d350f3026a@n33g2000pri.googlegroups.com...
> are there any vhdl codes that are available for free to debounce the > pushbutton on my spartan 3E? > > I require the push button to generate only 1 clock for 50mhz only upon > release. > > I've gotten some code from the net but aint sure if it does what I > need.... > > ============================================================== > > library ieee; > use ieee.std_logic_1164.all; > > entity debouncer is > port (clk,reset: in std_logic; -- clk frequency = 50Mhz > pb: in std_logic; > pb_debounced: out std_logic > ); > end entity debouncer; > > architecture rtl of debouncer is > signal count500000 : integer range 0 to 499999; > signal clk_100Hz: std_logic; > signal pb_sampled: std_logic; > begin > > div_100Hz: process(clk,reset) is > begin > if reset ='1' then > clk_100Hz <= '0'; > count500000 <= 0; > elsif rising_edge(clk) then > if count500000 = 499999 then > count500000 <= 0; > clk_100Hz <='1'; > else > count500000 <= count500000 + 1; > clk_100Hz <='0'; > end if; > end if; > end process div_100Hz; > > debounce_pb: process(clk) is > begin > if rising_edge(clk) then > if clk_100Hz ='1' then > if pb = pb_sampled then > pb_debounced <= pb; > end if; > pb_sampled <= pb; > end if; > end if; > end process debounce_pb; > > end architecture rtl; > ================================================== > > pls advise
There are a few methods of debouncing switches. One way of thinking is what's the minimum period between switch operations, then having a timer-counter to ensure that another swich operations can't occur during this period. constant integer max := xxxxx; if reset then timer_count = 0; pb_debounced = '0'; else rising_edge(clk) then if pb = '0' then if timer_count = max then pb_debounced <= '1'; timer_count <= 0; else timer_count <= 0; end if; else if timer_count = max then pb_debounced <= '1'; else timer_count <= timer_count +1; end if; end if; end if; E&OE!
On Jul 27, 3:51 pm, Jim Granville <no.s...@designtools.maps.co.nz>
wrote:
> rickman wrote: > > I think whether this code works for you depends on the push button. I > > have some tactile switches that initially showed *no* bouncing. After > > just a week or two of use they bounce so badly that it is impossible > > to debounce them. > > > The best switch to debounce is a double throw switch. The FF stays in > > a given state until the other contact is made. Very simple, but it > > requires two inputs and a more complex switch. > > Yes, a SPCO switch (classic Micro-switch action) is more complex, > as it has an extra contact, but I cannot see > the 'requires two inputs' in any I have used ? > > Wire one end to Vcc, one to GND, and the contact to the Pin, > and enable the Pin-Keep if you like, and you are done. > > Did you mean a SET/RESET action, which needs two pins, and two > resistors (can be pin-pulldowns) ? > > SPCO switches should be the default on demo-boards, as you can > also clock off them...
If you don't have the "pin-keep" (bus-hold) enabled (or available) what state is the input in while the switch is in transition? I would think the input would be floating which is not a good idea. In essence, you are asking the capacitance of the input to perform the bus-hold function. To be honest, I had to look up a SPCO switch. It seems to be a three position switch. Why do you need three positions? Wouldn't a SPDT with break before make do what you are describing? Rick
If you have a single-pole double-throw switch with break before make
(or a three-position switch) just connect the center to a pin,and the
two terminals to Vcc and ground. Then, inside the chip make the input
drive the active, non-inverted output on the same pin. That creates a
latch, that you can force either way, and it will respond within about
a nanosecond, and will ignore all bounce. Use the lowest drive
strength setting.
Brute-force shortening the output amy be unconventional, but works
like a champ.
Peter Alfke

Peter Alfke wrote:

> If you have a single-pole double-throw switch with break before make > (or a three-position switch) just connect the center to a pin,and the > two terminals to Vcc and ground. Then, inside the chip make the input > drive the active, non-inverted output on the same pin. That creates a > latch, that you can force either way, and it will respond within about > a nanosecond, and will ignore all bounce. Use the lowest drive > strength setting.
I was about to comment on the current surge before it switches, but I suppose at low drive setting it should be fine. I might wonder, though, on outputs with only high drive current. -- glen
glen herrmannsfeldt wrote:
> Peter Alfke wrote: > >> If you have a single-pole double-throw switch with break before make >> (or a three-position switch) just connect the center to a pin,and the >> two terminals to Vcc and ground. Then, inside the chip make the input >> drive the active, non-inverted output on the same pin. That creates a >> latch, that you can force either way, and it will respond within about >> a nanosecond, and will ignore all bounce. Use the lowest drive >> strength setting. > > > I was about to comment on the current surge before it switches, > but I suppose at low drive setting it should be fine. I might > wonder, though, on outputs with only high drive current.
That's not a bug, it's a feature!: It does Contact cleaning!! ;) -jg
rickman wrote:
> On Jul 27, 3:51 pm, Jim Granville <no.s...@designtools.maps.co.nz> > wrote: > >>rickman wrote: >> >>>I think whether this code works for you depends on the push button. I >>>have some tactile switches that initially showed *no* bouncing. After >>>just a week or two of use they bounce so badly that it is impossible >>>to debounce them. >> >>>The best switch to debounce is a double throw switch. The FF stays in >>>a given state until the other contact is made. Very simple, but it >>>requires two inputs and a more complex switch. >> >>Yes, a SPCO switch (classic Micro-switch action) is more complex, >>as it has an extra contact, but I cannot see >>the 'requires two inputs' in any I have used ? >> >>Wire one end to Vcc, one to GND, and the contact to the Pin, >>and enable the Pin-Keep if you like, and you are done. >> >>Did you mean a SET/RESET action, which needs two pins, and two >>resistors (can be pin-pulldowns) ? >> >>SPCO switches should be the default on demo-boards, as you can >>also clock off them... > > > If you don't have the "pin-keep" (bus-hold) enabled (or available) > what state is the input in while the switch is in transition? I would > think the input would be floating which is not a good idea. In > essence, you are asking the capacitance of the input to perform the > bus-hold function. > > To be honest, I had to look up a SPCO switch. It seems to be a three > position switch. Why do you need three positions? Wouldn't a SPDT > with break before make do what you are describing?
Yes, SPCO and SPDT are effectively interchangable (change Over/Double Throw) - The venerable Microswitch has that, as does the Digitast buttons. Digikey shows those for 28c+cap -jg