--********************************************************** -- Game Pal development Team -- -- KEYPAD CONTROLLER -- Revision 0.1 -- 1998/04/06 --********************************************************** library ieee; use ieee.std_logic_1164.all; ENTITY keypad IS PORT( clock : IN STD_LOGIC; --system clock reset : OUT STD_LOGIC; --system reset (key from keypad to reset rest of system) key1, key2, key3, key4, key5, key6, key7, key8, key9, key_enter, key_roll : OUT STD_LOGIC; -- keys on the keypad pinA, pinB, pinG, pinH : OUT STD_LOGIC; -- output pins on keypad pinC, pinD, pinE, pinF: IN STD_LOGIC -- input pins on keypad ); END keypad; ARCHITECTURE behavior OF keypad IS TYPE state_type IS (reset_state, first_row, second_row, third_row, fourth_row, deb_first, deb_second, deb_third, deb_fourth, set_first, set_second, set_third, set_fourth); -- state machine states SIGNAL state : state_type; --current state the circuit is in SIGNAL key_clock : STD_LOGIC; SIGNAL next_state : state_type; --next state circuit will go to (on next clock rising edge) SIGNAL k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12, k13, k14, k15, k16 : STD_LOGIC; -- names of keys on keypad -- SIGNAL pinA, pinB, pinC, pinD, pinE, pinF, pinG, pinH: STD_LOGIC; BEGIN state_machine : process --(clock) BEGIN CASE state IS WHEN reset_state => next_state <= first_row; -- go to debounce WHEN first_row => IF (pinE = '0') OR (pinF = '0') OR (pinD = '0') OR (pinC = '0') THEN-- if a pin is pulled low next_state <= deb_first; -- go to debounce ELSE next_state <= second_row; -- sample next column END IF; WHEN second_row => IF (pinE = '0') OR (pinF = '0') OR (pinD = '0') OR (pinC = '0') THEN-- if a pin is pulled low next_state <= deb_second; -- go to debounce ELSE next_state <= third_row; -- sample next column END IF; WHEN third_row => IF (pinE = '0') OR (pinF = '0') OR (pinD = '0') OR (pinC = '0') THEN-- if a pin is pulled low next_state <= deb_third; -- go to debounce ELSE next_state <= fourth_row; -- sample next column END IF; WHEN fourth_row => IF (pinE = '0') OR (pinF = '0') OR (pinD = '0') OR (pinC = '0') THEN-- if a pin is pulled low next_state <= deb_fourth; -- go to debounce ELSE next_state <= first_row; -- sample next column END IF; -- debounce states provide an extra clock delay for keys to settle before being assigned WHEN deb_first => IF (pinE = '0') OR (pinF = '0') OR (pinD = '0') OR (pinC = '0') THEN -- if a pin is still pulled low next_state <= set_first; -- go to set key ELSE next_state <= reset_state; -- reset and start sampling again END IF; WHEN deb_second => IF (pinE = '0') OR (pinF = '0') OR (pinD = '0') OR (pinC = '0') THEN -- if a pin is still pulled low next_state <= set_second; -- go to set key ELSE next_state <= reset_state; -- reset and start sampling again END IF; WHEN deb_third => IF (pinE = '0') OR (pinF = '0') OR (pinD = '0') OR (pinC = '0') THEN -- if a pin is still pulled low next_state <= set_third; -- go to set key ELSE next_state <= reset_state; -- reset and start sampling again END IF; WHEN deb_fourth => IF (pinE = '0') OR (pinF = '0') OR (pinD = '0') OR (pinC = '0') THEN -- if a pin is still pulled low next_state <= set_fourth; -- go to set key ELSE next_state <= reset_state; -- reset and start sampling again END IF; -- states to set keys WHEN set_first => IF (pinE = '0') OR (pinF = '0') OR (pinD = '0') OR (pinC = '0') THEN -- if a pin is still pulled low next_state <= set_first; ELSE next_state <= reset_state; -- reset and start sampling again END IF; WHEN set_second => IF (pinE = '0') OR (pinF = '0') OR (pinD = '0') OR (pinC = '0') THEN -- if a pin is still pulled low next_state <= set_second; ELSE next_state <= reset_state; -- reset and start sampling again END IF; WHEN set_third => IF (pinE = '0') OR (pinF = '0') OR (pinD = '0') OR (pinC = '0') THEN -- if a pin is still pulled low next_state <= set_third; ELSE next_state <= reset_state; -- reset and start sampling again END IF; WHEN set_fourth => IF (pinE = '0') OR (pinF = '0') OR (pinD = '0') OR (pinC = '0') THEN -- if a pin is still pulled low next_state <= set_fourth; ELSE next_state <= reset_state; -- reset and start sampling again END IF; WHEN OTHERS => next_state <= reset_state;-- if an unknown state is encountered, go to first_row END CASE; END PROCESS state_machine; -- ***************** state_register : PROCESS (key_clock)-- advances the state machine on the clock pulse BEGIN IF rising_edge(key_clock) THEN -- rising edge of clock triggers transition to next state of state machine state <= next_state; END IF; END PROCESS state_register; -- ***************** extract_keys : PROCESS BEGIN END PROCESS extract_keys; -- ***************** assign_keys : PROCESS BEGIN CASE state IS WHEN reset_state => key1 <= '1'; -- set all keys equal to zero key2 <= '1'; -- key3 <= '1'; -- key4 <= '1'; -- key5 <= '1'; -- key6 <= '1'; -- key7 <= '1'; -- key8 <= '1'; -- key9 <= '1'; -- key_enter <= '1'; -- key_roll <= '1'; -- reset <= '1'; -- WHEN set_first => IF (pinE = '0')THEN key1 <= '0'; -- ELSIF (pinF = '0') THEN key2 <= '0'; -- ELSIF (pinD = '0') THEN key3 <= '0'; -- ELSIF (pinC = '0') THEN key4 <= '0'; END IF; key5 <= '1'; -- set all other keys to zero key6 <= '1'; -- key7 <= '1'; -- key8 <= '1'; -- key9 <= '1'; -- key_enter <= '1'; -- key_roll <= '1'; -- reset <= '1'; -- WHEN set_second => IF (pinE = '0')THEN key5 <= '0'; -- ELSIF (pinF = '0')THEN key6 <= '0'; -- ELSIF (pinD = '0')THEN key7 <= '0'; -- ELSIF (pinC = '0') THEN key8 <= '0'; END IF; key1 <= '1'; -- set all other keys to zero key2 <= '1'; -- key3 <= '1'; -- key4 <= '1'; -- key9 <= '1'; -- key_enter <= '1'; -- key_roll <= '1'; -- reset <= '1'; -- WHEN set_third => IF (pinE = '0')THEN key9 <= '0'; -- ELSIF (pinF = '0')THEN -- unused key ELSIF (pinD = '0')THEN -- unused key ELSIF (pinC = '0')THEN reset <= '0'; END IF; key1 <= '1'; -- set all other keys equal to zero key2 <= '1'; -- key3 <= '1'; -- key4 <= '1'; -- key5 <= '1'; -- key6 <= '1'; -- key7 <= '1'; -- key8 <= '1'; -- key_enter <= '1'; -- key_roll <= '1'; -- WHEN set_fourth => IF (pinE = '0')THEN key_roll <= '0'; ELSIF (pinF = '0')THEN key_enter <= '0'; ELSIF (pinD = '0')THEN -- unused key ELSIF (pinC = '0')THEN -- unused key END IF; key1 <= '1'; -- set all other keys to zero key2 <= '1'; -- key3 <= '1'; -- key4 <= '1'; -- key5 <= '1'; -- key6 <= '1'; -- key7 <= '1'; -- key8 <= '1'; -- key9 <= '1'; -- reset <= '1'; -- WHEN others => key1 <= '1'; -- set all keys equal to zero key2 <= '1'; -- key3 <= '1'; -- key4 <= '1'; -- key5 <= '1'; -- key6 <= '1'; -- key7 <= '1'; -- key8 <= '1'; -- key9 <= '1'; -- key_enter <= '1'; -- key_roll <= '1'; -- reset <= '1'; -- END CASE; END PROCESS assign_keys; -- **************** drive_pins : PROCESS -- advances the state machine on the clock pulse BEGIN CASE state IS WHEN first_row => pinA <= '0'; pinB <= '1'; pinG <= '1'; pinH <= '1'; WHEN deb_first => pinA <= '0'; pinB <= '1'; pinG <= '1'; pinH <= '1'; WHEN set_first => pinA <= '0'; pinB <= '1'; pinG <= '1'; pinH <= '1'; WHEN second_row => pinA <= '1'; pinB <= '0'; pinG <= '1'; pinH <= '1'; WHEN deb_second => pinA <= '1'; pinB <= '0'; pinG <= '1'; pinH <= '1'; WHEN set_second => pinA <= '1'; pinB <= '0'; pinG <= '1'; pinH <= '1'; WHEN third_row => pinA <= '1'; pinB <= '1'; pinG <= '0'; pinH <= '1'; WHEN deb_third => pinA <= '1'; pinB <= '1'; pinG <= '0'; pinH <= '1'; WHEN set_third => pinA <= '1'; pinB <= '1'; pinG <= '0'; pinH <= '1'; WHEN fourth_row => pinA <= '1'; pinB <= '1'; pinG <= '1'; pinH <= '0'; WHEN deb_fourth => pinA <= '1'; pinB <= '1'; pinG <= '1'; pinH <= '0'; WHEN set_fourth => pinA <= '1'; pinB <= '1'; pinG <= '1'; pinH <= '0'; WHEN OTHERS => pinA <= '1'; pinB <= '1'; pinG <= '1'; pinH <= '1'; END CASE; END PROCESS drive_pins; -- ***************** clock_divider: PROCESS (clock)IS CONSTANT stepdown: integer :=25175; --25175000; --sample at 1 kHz TYPE stepdown_type IS RANGE 0 TO stepdown; VARIABLE c :stepdown_type; BEGIN WAIT UNTIL RISING_EDGE(clock); c:= c + 1; IF c = 0 THEN key_clock <= NOT key_clock; END IF; END PROCESS clock_divider; --**************** END behavior;