Forum Discussion
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
Honored 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
Honored Contributor
I have changed the process like this:
but the key is still not toggling properly. If I change key(0) detection to rising edgebuttons_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;
the key shouldn't be working from my opinion. But it is the same inproper toggling. What am I missing ? Thanks for reply.(key(0) = '1' and key(0)'event) - Altera_Forum
Honored 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
Honored 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:
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.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; - Altera_Forum
Honored 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
Honored 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
Honored 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.