-------------------------------------------------------------------------------- -- File Name : Keydecoder.vhd -- Created by Su Tarn, Lim -- Keypad driver -- -- This file contains the VHDL keyboard handling. -- -- Descriptions: -- It takes 8 inputs from a 83-BB1-002 4x4 keyboard and give a 4-bit -- binary signal to indicate which key was pressed -- -- The layout of the 4x4 Keyboard is -- -- 0 1 2 3 -- 4 5 6 7 -- 8 9 A B -- C D E F -- -- X0-X3 goes from right to left -- Y0-Y3 goes from down to top -- -- The pins from the columns will be active high, it will be high -- when one of the key in the column is pressed. The pins from the -- rows are connected active, low which will only go low when one -- of the key in the row is pressed. -- -- Reference to Edgar Wong with help in debouncing -------------------------------------------------------------------------------- ------------------------- -- Package Declaration -- ------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; package Keypad_Package is component keydecoder is port( clock: in std_logic; -- output to Control keyData: out std_logic_vector(3 downto 0); keyDataAvailable: out std_logic; -- input from keyboard col_input : in std_logic_vector (7 downto 0) ); end component keydecoder; end Keypad_Package; -------------------------------------------------------------------------------- ------------------------ -- Entity Declaration -- ------------------------ LIBRARY IEEE; USE ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity keydecoder is port ( clock : in std_logic; KeyData : out std_logic_vector (3 downto 0); KeyDataAvailable : out std_logic; col_input : in std_logic_vector (7 downto 0) ); end keydecoder; architecture behavioural of keydecoder is type state_type1 is (nokey, debounce, keypress, outputkey, waitforrelease, debounce_output, keyrelease); signal NextState : state_type1; signal keydetect : std_logic; signal yrow : std_logic_vector (3 downto 0) := "1111"; signal xrow : std_logic_vector (3 downto 0) := "0000"; signal key : std_logic_vector (3 downto 0); signal deb_reset : std_logic; begin -- latch inputs latchinputs : process is begin if falling_edge(clock) then yrow(3 downto 0) <= col_input(3 downto 0); xrow(3 downto 0) <= col_input(7 downto 4); end if; end process latchinputs; delay: process(clock) variable count: std_logic_vector(14 downto 0) :=(others => '0'); begin if rising_edge(clock) then -- if keydetect = '0' then if (NextState = debounce or NextState = debounce_output) then if count = "110001001010111" then deb_reset <= '1'; count:= "000000000000000"; else deb_reset <= '0'; -- a key is being pressed count := count + 1; end if; else count:= "000000000000000"; end if; -- end if; end if; end process delay; -- signal used to detect if a key is pressed key_press_detect : process is begin keydetect <= (yrow(0) and yrow(1)) and (yrow(2) and yrow(3)); -- active low end process key_press_detect; -- state logic to determine the current state statelogic : process (NextState, clock) is begin if rising_edge (clock) then case NextState is when nokey => if keydetect = '1' then NextState <= nokey; elsif keydetect = '0' then NextState <= debounce; else NextState <= nokey; end if; when debounce => if keydetect = '0' then if deb_reset = '1' then NextState <= keypress; elsif deb_reset = '0' then NextState <= debounce; else NextState <= keyrelease; end if; else NextState <= keyrelease; end if; when keypress => if keydetect = '0' then NextState <= outputkey; else NextState <= keyrelease; end if; when outputkey => NextState <= waitforrelease; when waitforrelease => if keydetect = '0' then NextState <= waitforrelease; else NextState <= debounce_output; end if; when debounce_output => if keydetect = '1' then if deb_reset = '1' then NextState <= keyrelease; elsif deb_reset = '0' then NextState <= debounce_output; end if; else NextState <= waitforrelease; end if; when keyrelease => NextState <= nokey; when others => NextState <= nokey; end case; end if; end process statelogic; -- outputs a 4-bit signals representing which key was pressed EncodeOutput : process (clock) begin if NextState = keypress then if yrow(0) = '0' then if xrow(0) = '1' then key <= "1111"; -- key F elsif xrow(1) = '1' then key <= "1110"; -- key E elsif xrow(2) = '1' then key <= "1101"; -- key D elsif xrow(3) = '1' then key <= "1100"; -- key C else key <= (others => '0'); -- other cases end if; elsif yrow(1) = '0' then if xrow(0) = '1' then key <= "1011"; -- key B elsif xrow(1) = '1' then key <= "1010"; -- key A elsif xrow(2) = '1' then key <= "1001"; -- key 9 elsif xrow(3) = '1' then key <= "1000"; -- key 8 else key <= (others => '0'); -- other cases end if; elsif yrow(2) = '0' then if xrow(0) = '1' then key <= "0111"; -- key 7 elsif xrow(1) = '1' then key <= "0110"; -- key 6 elsif xrow(2) = '1' then key <= "0101"; -- key 5 elsif xrow(3) = '1' then key <= "0100"; -- key 4 else key <= (others => '0'); -- other cases end if; elsif yrow(3) = '0' then if xrow(0) = '1' then key <= "0011"; -- key 3 elsif xrow(1) = '1' then key <= "0011"; -- key 2 elsif xrow(2) = '1' then key <= "0001"; -- key 1 elsif xrow(3) = '1' then key <= "0000"; -- key 0 else key <= (others => '0'); -- other cases end if; else key <= (others => '0'); end if; end if; end process EncodeOutput; -- latch output output : process (NextState) is begin if (NextState = outputkey or NextState = waitforrelease) then KeyData <= key; keyDataAvailable <= '1'; else -- KeyData <= (others => '0'); keyDataAvailable <= '0'; end if; end process output; end behavioural;