fpga - VHDL button debouncing in state machine application -
i'm programming fpga board w/ lattice xp2-5e chip. on board 4 rows , 2 columns of led lights i'm trying control 4 directional push-buttons , 1 reset push-button. instance, if (1st row/1st column) led turned on , if press button right, (1st row/2nd column) led turn on , (1st row/1st column) led turn off.
since there no hardware debouncing circuit implemented, need implement software solution. tick rate 25 mhz , minimal button hold time 25 ms. code shown below:
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity sklop port ( btn_center : in std_logic; btn_left : in std_logic; btn_right : in std_logic; btn_up : in std_logic; btn_down : in std_logic; clk_25m : in std_logic; led : out std_logic_vector (7 downto 0)); end sklop; architecture behv of sklop type state_type (s0, s1, s2, s3, s4, s5, s6, s7); signal curs : state_type := s0; signal nxts : state_type := s0; signal counter : std_logic_vector (22 downto 0) := (others => '0'); signal is_ok : std_logic := '0'; signal btn_press : std_logic := '0'; signal start_cnt : std_logic := '0'; begin process(is_ok) -- state switching begin if(btn_left = '1' , rising_edge(is_ok)) case curs when s0 => nxts <= s0; when s1 => nxts <= s1; when s2 => nxts <= s2; when s3 => nxts <= s3; when s4 => nxts <= s0; when s5 => nxts <= s1; when s6 => nxts <= s2; when s7 => nxts <= s3; end case; end if; if(btn_right = '1' , rising_edge(is_ok)) case curs when s0 => nxts <= s4; when s1 => nxts <= s5; when s2 => nxts <= s6; when s3 => nxts <= s7; when s4 => nxts <= s4; when s5 => nxts <= s5; when s6 => nxts <= s6; when s7 => nxts <= s7; end case; end if; if(btn_up = '1' , rising_edge(is_ok)) case curs when s0 => nxts <= s0; when s1 => nxts <= s0; when s2 => nxts <= s1; when s3 => nxts <= s2; when s4 => nxts <= s4; when s5 => nxts <= s4; when s6 => nxts <= s5; when s7 => nxts <= s6; end case; end if; if(btn_down = '1' , rising_edge(is_ok)) case curs when s0 => nxts <= s1; when s1 => nxts <= s2; when s2 => nxts <= s3; when s3 => nxts <= s3; when s4 => nxts <= s5; when s5 => nxts <= s6; when s6 => nxts <= s7; when s7 => nxts <= s7; end case; end if; if(btn_center = '1' , rising_edge(is_ok)) nxts <= s0; end if; end process; process(curs) -- output of state machine begin case curs when s0 => led <= "10000000"; when s1 => led <= "01000000"; when s2 => led <= "00100000"; when s3 => led <= "00010000"; when s4 => led <= "00001000"; when s5 => led <= "00000100"; when s6 => led <= "00000010"; when s7 => led <= "00000001"; end case; end process; process(clk_25m) -- debouncing begin if(btn_center = '1' or btn_right = '1' or btn_left = '1' or btn_up = '1' or btn_down = '1') btn_press <= '1'; else btn_press <= '0'; end if; if(rising_edge(btn_press)) start_cnt <= '1'; end if; if(falling_edge(btn_press)) start_cnt <= '1'; end if; if(rising_edge(clk_25m)) if(counter /= "10111110101111000010000" , start_cnt = '1') counter <= counter + '1'; is_ok <= '0'; elsif(start_cnt = '1' , btn_press = '1') is_ok <= '1'; curs <= nxts; start_cnt <= '0'; counter <= "00000000000000000000000"; end if; end if; end process; end behv;
sometimes code works intended times there multiple led lights turned on or no led turned on - wonder how can possible - , state doesn't change when pushing button (even when holding button longer 25 ms).
what seems problem. running out of ideas.
Comments
Post a Comment