Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
18 years ago

DE2 Quartus debounced circuit

Hello,

I am working on a senior design project and have a DE2 board connected to external circuitry. There are pushbuttons on the external circuit which control leds also on that circuit board. My design requires that I press the pushbutton and the led lights up and I press it a second time and the led goes off.

It turns out that those pushbuttons which are single-pole-double-throw (SPDT) are not debounced and give multiple outputs when I want a clean signal.

I would like to know if there is a reference design so I can build debounced circuitry for the buttons in Quartus. If not, how do I build debouncers in Quartus for SPDT pushbuttons?

Thanks.

Kofi.

15 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hello,

    I made a simplest program for hex counter it supposed to count push-button clicks.

    It present the result on a single 7seg display and 4 LEDs, unfortunately I've got a bouncing problem.

    I'm using a Altera Cyclone II BAIXUN ASK2CB dev. board it has on board push-button

    Can you please suggest how can i debounce it, so the bits go one by one?

    Here is my code:

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

    library IEEE;

    use IEEE.STD_LOGIC_1164.ALL;

    use IEEE.STD_LOGIC_ARITH.ALL;

    use IEEE.STD_LOGIC_UNSIGNED.ALL;

    entity test is

    port (Y : out std_logic_vector (6 downto 0); -- 7 seg digit

    B : out std_logic;

    pb : in std_logic;

    count : out std_logic_vector(3 downto 0);

    reset :in std_logic

    );

    end entity test;

    architecture Behavioral of test is

    signal c: std_logic_vector(3 downto 0) :=(others => '0'); --initializing count to zero.

    begin

    counting: process(pb,reset) is

    begin

    if rising_edge (pb) then

    if(c = "1111") then -- when count reaches its maximum(that is 15) reset it to 0

    c <="0000";

    end if;

    c <= c+'1'; --increment count at every positive edge of clk.

    end if;

    if(reset='0') then --when reset equal to '0' make count equal to 0.

    c <=(others => '0'); -- c ="0000"

    end if;

    case c is

    when "0000"=>Y<="1000000";-- 0

    when "0001"=>Y<="1111001";-- 1

    when "0010"=>Y<="0100100";-- 2

    when "0011"=>Y<="0110000";-- 3

    when "0100"=>Y<="0011001";-- 4

    when "0101"=>Y<="0010010";-- 5

    when "0110"=>Y<="0000010";-- 6

    when "0111"=>Y<="1111000";-- 7

    when "1000"=>Y<="0000000";-- 8

    when "1001"=>Y<="0010000";-- 9

    when "1010"=>Y<="0001000";-- A

    when "1011"=>Y<="0000011";-- b

    when "1100"=>Y<="1000110";-- C

    when "1101"=>Y<="0100001";-- d

    when "1110"=>Y<="0000110";-- E

    when "1111"=>Y<="0001110";-- F

    when others=>Y<="1111111";-- in other cases balnk

    end case;

    end process counting;

    B<='0';

    count<=c;

    end architecture Behavioral;

    ==========================================
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    you shouldn't use the push button as clock input, it isvery unreliable and sensitive to bounces, as you discovered.

    Instead, use a regular clock (I'm sure the board has an oscillator you can use) and monitor the pb signal on each clock cycle. You can detect a change on the button status by comparing the current value of pb with the previous one. You will also probably need to implement a delay for proper debouncing.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thank you Daixiwen!

    I see, anyway i tried to make a delay but nothing seem to work yet, still trying.

    I'm a beginner, so i'll will be really glad if you can help me with solving upon my code,

    to understand it better! If its not to much to ask!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    How did you implement the delai? I can for example have a counter increasing from the last time you detected a rising edge, ad you don't take into account a new rising edge before this counter reaches a predetermined value.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Daixiwen and thanks,

    Sorry for a long time no answer. Finally solved the problem. using the following code:

    library ieee;

    use ieee.std_logic_1164.all;

    use ieee.std_logic_unsigned.all;

    entity debounce is

    generic(

    counter_size : INTEGER := 19); --counter size (19 bits gives 10.5ms with 50MHz clock)

    port(

    Digit : out std_logic_vector (6 downto 0); -- 7 seg digit

    hex_count : out std_logic_vector(3 downto 0); -- Hexadecimal result

    clk, reset, button : in std_logic; --input signals

    Digit_en : out std_logic); -- 7 seg digit enable

    end debounce;

    architecture logic of debounce is

    signal counter : std_logic_vector(3 downto 0) :=(others => '0'); --initializing count to zero.

    signal flipflops : std_logic_vector(1 downto 0); --input flip flops

    signal counter_out : std_logic_vector(counter_size downto 0) := (others => '0'); --counter output

    signal counter_set : std_logic; --sync reset to zero

    signal result : std_logic; --debouncer result

    begin

    counter_set <= flipflops(0) xor flipflops(1); --determine when to start/reset counter

    process(clk)

    begin

    if(clk'event and clk = '1') then

    flipflops(0) <= button;

    flipflops(1) <= flipflops(0);

    if(counter_set = '1') then --reset counter because input is changing

    counter_out <= (others => '0');

    elsif(counter_out(counter_size) = '0') then --stable input time is not yet met

    counter_out <= counter_out + 1;

    else --stable input time is met

    result <= not flipflops(1);

    end if;

    end if;

    end process;

    process(result)

    begin

    if(reset='0') then --when reset equal to '0' make count equal to 0.

    counter <=(others => '0'); -- c ="0000"

    elsif(result'event and result = '1') then

    if(counter = "1111") then -- when count reaches its maximum(that is 15) reset it to 0

    counter <="0000";

    end if;

    counter <= counter+'1'; --increment count at every positive edge of clk.

    end if;

    case counter is

    when "0000"=>Digit<="1000000";-- 0

    when "0001"=>Digit<="1111001";-- 1

    when "0010"=>Digit<="0100100";-- 2

    when "0011"=>Digit<="0110000";-- 3

    when "0100"=>Digit<="0011001";-- 4

    when "0101"=>Digit<="0010010";-- 5

    when "0110"=>Digit<="0000010";-- 6

    when "0111"=>Digit<="1111000";-- 7

    when "1000"=>Digit<="0000000";-- 8

    when "1001"=>Digit<="0010000";-- 9

    when "1010"=>Digit<="0001000";-- A

    when "1011"=>Digit<="0000011";-- b

    when "1100"=>Digit<="1000110";-- C

    when "1101"=>Digit<="0100001";-- d

    when "1110"=>Digit<="0000110";-- E

    when "1111"=>Digit<="0001110";-- F

    when others=>Digit<="1111111";-- in other cases balnk

    end case;

    end process;

    Digit_en<='0';

    hex_count<=counter;

    end;