Forum Discussion

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

DE2 push buttons question

I have a simple counter in VHDL for DE2-115 (should work with any DE2). KEY0 starts counting, KEY1 stops, KEY2 resets. The output is displayed on 7-seg LEDs HEX0 - HEX3 in hexa digits (to be simple manner).

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity led_counter_ent is
    port (     CLOCK_50: in std_logic;
--            LEDR    : out std_logic_vector(15 downto 0);
            HEX0    : out std_logic_vector(6 downto 0);
            HEX1    : out std_logic_vector(6 downto 0);
            HEX2    : out std_logic_vector(6 downto 0);
            HEX3    : out std_logic_vector(6 downto 0);
            HEX4    : out std_logic_vector(6 downto 0) := (others => '1');
            HEX5    : out std_logic_vector(6 downto 0) := (others => '1');
            HEX6    : out std_logic_vector(6 downto 0) := (others => '1');
            HEX7    : out std_logic_vector(6 downto 0) := (others => '1');
            KEY        : in std_logic_vector(3 downto 0);
            LEDG    : out std_logic_vector(1 downto 0));
end led_counter_ent;
architecture behavior of led_counter_ent is
signal count    : std_logic_vector(24 downto 0) := (others => '0');
signal beat_count: std_logic_vector(15 downto 0) := (others => '0');
signal run        : std_logic                        := '0';
signal reset    : std_logic                        := '0';
procedure segment_proced (signal data : in std_logic_vector(3 downto 0); signal digit : out std_logic_vector(6 downto 0)) is
begin                          
    case data 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"; -- switch off
    end case;
end segment_proced;
    
begin
    buttons_process:process (key(0), key(1), key(2), key(3))
    begin
        -- signals run and reset are set due the first expression in the process - why ??
            if (key(1) = '0') then
                run <= '0';
                hex5    <= "1000000"; -- 0
            else    
                hex5    <= "1111001"; -- 1
            end if;
            
            if (key(0) = '1') then
                hex4    <= "1111001"; -- 1
            else
                hex4    <= "1000000"; -- 0
                reset <= '0';
                run <= '1';
                --run <= not run; -- switch ON/OFF does't work properly - why ??
            end if;
            
            if (key(3) = '0') then
                hex7    <= "1000000"; -- 0
                run <= not run; -- switch ON/OFF does't work properly - why ??
            else    
                hex7    <= "1111001"; -- 1
            end if;
            
            if (key(2) = '0') then
                hex6    <= "1000000"; -- 0
                reset <= '1';
            else
                hex6    <= "1111001"; -- 1
            end if;
    end process;
    counter_process:process (clock_50)
    begin
        if clock_50 = '1' and clock_50'event then
            count <= count + 1;
            --if count = "1111111111001011010000000" then -- 33.527.424
            --if count = "111111111001011010000000" then -- 16.750.208
            --if count = "110110001001011010000000" then -- 14.194.304
            --if count = "100110001001011010000000" then -- 10.000.000 - 200ms
            if count = "10011000100101101000000" then -- 5.000.000 - 100ms
            --if count = "111101000010010000000" then -- 2.000.000 - 40ms
            --if count = "1111010000100100000" then -- 500.000 - 10ms
            --if count = "1111010000100011111" then -- 499.999 - 10ms proper
                count    <= (others => '0');
--                tik <= not tik;
                if (run = '1') then
                    beat_count <= beat_count + 1;
                end if;
                if (reset = '1') then
                    beat_count <= (others => '0');
                end if;
            end if;
        end if;
    end process;    
    
    segment_proced(beat_count(3 downto 0), hex0);
    segment_proced(beat_count(7 downto 4), hex1);
    segment_proced(beat_count(11 downto 8), hex2);
    segment_proced(beat_count(15 downto 12), hex3);
    
--    ledr <= beat_count;
    ledg(0) <= run;
    ledg(1) <= reset;
                
end behavior;
I want to have only one button to start/stop the counter (not KEY0 for starting and KEY1 for stopping). But if I use the solution as it is used with KEY3, start/stop is not working properly ('run' is signal to indicate whether to count).
run <= not run;
Counting will not start/stop reliably with every button push which is not clear to me.

I appreciate any advise, thank you.

7 Replies

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

    Right now, KEY is level sensitive. You can make KEY edge-triggered input to counter. For example, a press on KEY will toggle state from STOP to START. Another press on KEY will toggle state from START to STOP. And back and forth.

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

    I have changed the process like this:

        buttons_process:process (key)
        begin
                if ((key(0) = '0' and key(0)'event)) then
                    run <= not run; -- switch ON/OFF does't work properly - why ??
                    reset <= '0';
                end if;
                if (key(1) = '0') then
                    hex6    <= "1000000"; -- 0
                    reset <= '1';
                else
                    hex6    <= "1111001"; -- 1
                end if;
        end process;
    but the key is still not toggling properly. If I change key(0) detection to rising edge
    (key(0) = '1' and key(0)'event)
    the key shouldn't be working from my opinion. But it is the same inproper toggling. What am I missing ?

    Thanks for reply.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    P1: process (key(0))

    begin

    if (rising_edge(key(0)) then

    run <= not run;

    reset <= '0';

    end if;

    end process;

    P2: process (key(1))

    begin

    if (rising_edge(key(1)) then

    if (run = '0') then

    hex6 <= hex6 - 1;

    else

    hex6 <= hex6 + 1;

    end if;

    end if;

    end process;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I made more experiments and I feel that there is problem with buttons edge detection on the DE2 board. I tried T flip flop:

    library ieee;
    use ieee.std_logic_1164.all;
    entity t_ff_async is
       port (
          t : in std_logic;
          r : in std_logic;
          q : out std_logic;
          n_q : out std_logic
       );
    end t_ff_async;
    architecture struct of t_ff_async is
    begin
       process (r, t)
          variable ff : std_logic;
       begin
          -- reset
          if r = '1' then
             ff := '0';
          elsif t'event and t = '1' then
             ff := not ff;
          end if;
          q <= ff;
          n_q <= not ff;
       end process;
    end struct;
    Toggle is 't' in here - in which I have tested step by step all 4 keys (buttons) on the DE2. Code defines rising edge which is every release of the key (button). I assigned LEDs to Q and n_Q, so LED light should switch with every release of the key (button) which was not 100% event; it sometimes switched also when the button was pressed and then when released. I have also assigned another LEDs to indicate immediate value of the key ledr <= key which is working 100% correct.

    So I have reached a view that those type of buttons isn't good to use in applications where edge detection (due electrical characteristic) is needed. Do you think that this could be correct explanation ?

    Thanks for reply.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    There are two type of switches KEY and SW. KEY is debounced, SW is NOT debounced. I am using KEY in my NIOS projects. It can register falling edge properly. Try use the falling edge instead to see there is any improvement.

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

    ... I was investigating where should be the the problem but I am still confused :confused:.

    I have tried detection of KEY's falling edge (KEY is pressed) and I think it was ~70% successful; else there was detected KEY's release instead of press or it was detected press and release (during one push). Shouldn't be there a problem with voltage setting (there is 2.5V in pin planner) or some voltage bouncing during the falling/rising edge ? I have any other explanation ...

    I have also upgraded Quartus from 9.1sp2 to 10.1 but there is no difference.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I have also confirmed that although there is a debounce it is not good because it doesn't actually make use of a double throw switch. In other words the mechanical characteristic of this cheap switch allows contact-no contact to occur when it is being held depressed. This activity is similar to one methodically pressing and releasing the PB, giving multiple debounced responses. In other words, this kind of debounce can't solve the mechanical switch shortcoming.