-- Functional Description -- -- The keypad works with drive and sense lines. -- The rows are the sense lines. -- The columns are the drive lines. -- Each of the four sense lines is pulled up with a 10kohm -- resister. -- The drive lines drive all '0' and once a sense of '0' is -- seen then we know that a key has been pressed. -- Once the key has been pressed then a '1' bit is shifted through all -- of the drive lines. -- Then once the sense lines goes high again then we know which key -- was pressed. -- The key is then registed using the keydetected signal. -- Then the kaypad logic waits for the key to be released and for a signal -- to continue normal operation. -- -- -------------------------------------------------------- ------------------------------------------------------------------------ -- keypad ------------------------------------------------------------------------ LIBRARY IEEE; USE ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; ENTITY keypad IS PORT( clk : IN STD_LOGIC; reset : IN STD_LOGIC; --KeyDetected : OUT STD_LOGIC; Key : OUT STD_LOGIC_VECTOR(3 downto 0); -- External Signals row : IN STD_LOGIC_VECTOR(3 downto 0); col : OUT STD_LOGIC_VECTOR(3 downto 0) ); END keypad; ARCHITECTURE behavioural OF keypad IS TYPE STATE_TYPE IS (--Nokey, Drive0, Drive1, Drive2, Drive4, Drive8, Foundkey --debounce, debounce_out, --Keyrelease ); SIGNAL state : STATE_TYPE; -- SIGNAL stateDrive : STATE_TYPE; SIGNAL Sense : STD_LOGIC; --SIGNAL Key : STD_LOGIC_VECTOR(3 downto 0); SIGNAL rowint : STD_LOGIC_VECTOR(3 downto 0); SIGNAL IntCack : STD_LOGIC; --signal deb_reset : std_logic; BEGIN -- Latch the inputs Internalrow: PROCESS BEGIN IF(falling_edge(clk)) THEN rowint <= row; END IF; END PROCESS Internalrow; -- Create the sense signal. SenseDetect: PROCESS BEGIN Sense <= (rowint(0) AND rowint(1)) AND (rowint(2) AND rowint(3)); END PROCESS SenseDetect; --delay: process(clk) -- variable count: std_logic_vector(7 downto 0) :=(others => '0'); --begin --if rising_edge(clk) then -- if keydetect = '0' then --if (state = debounce or state = debounce_out) then --if count = "00010111" then --deb_reset <= '1'; --count:= "00000000"; --else --deb_reset <= '0'; -- a key is being pressed --count := count + 1; --end if; --else --count:= "00000000"; --end if; -- end if; --end if; --end process delay; -- This is the state that handles all of the state machine. StateLogic : PROCESS (reset, clk) --variable count, count2 : integer; BEGIN IF reset = '0' THEN --state <= Nokey; key <= "0000"; --keyDetected <= '0'; -- stateDrive <= Drive0; ELSIF rising_edge(clk) THEN CASE state IS --WHEN Nokey => --IF Sense = '0' THEN --state <= Drive1; --state <= debounce; --ELSE --state <= Drive0; --state <= Nokey; --END IF; --when debounce => --if Sense = '0' then --if deb_reset = '1' then --state <= Drive1; --elsif deb_reset = '0' then --state <= debounce; --else --state <= keyrelease; --end if; --else --state <= keyrelease; --end if; --when Drive0 => --state <= debounce; --state <= Drive1; --when debounce=> --for count in 0 to 20 loop --end loop; --for count2 in 0 to 20 loop --end loop; --end loop; --state <= Drive1; WHEN Drive1 => IF Sense = '0' THEN IF rowint(0) = '0' THEN Key <= "0000"; -- Key 0 ELSIF rowint(1) = '0' THEN Key <= "0100"; --Key 4 ELSIF rowint(2) = '0' THEN Key <= "1000"; -- Key 8 ELSIF rowint(3) = '0' THEN Key <= "1100"; -- Key 12 end if; state <= Foundkey; ELSE state <= Drive2; END IF; WHEN Drive2 => IF Sense = '0' THEN if rowint(0) = '0' THEN Key <= "0001"; -- 1 ELSIF rowint(1) = '0' THEN Key <= "0101"; -- 5 ELSIF rowint(2) = '0' THEN Key <= "1001"; -- 9 ELSIF rowint(3) = '0' THEN Key <= "1101"; -- 13 end if; state <= Foundkey; ELSE state <= Drive4; END IF; WHEN Drive4 => IF Sense = '0' THEN if rowint(0) = '0' THEN Key <= "0010"; -- 2 ELSIF rowint(1) = '0' THEN Key <= "0110"; --6 ELSIF rowint(2) = '0' THEN Key <= "1010"; -- 10 ELSIF rowint(3) = '0' THEN Key <= "1110"; -- 14 END IF; state <= Foundkey; ELSE state <= Drive8; END IF; WHEN Drive8 => IF Sense = '0' THEN IF rowint(0) = '0' THEN Key <= "0011"; -- 3 ELSIF rowint(1) = '0' THEN Key <= "0111"; -- 7 ELSIF rowint(2) = '0' THEN Key <= "1011"; -- 11 ELSIF rowint(3) = '0' THEN Key <= "1111"; -- 15 END IF; state <= Foundkey; ELSE --state <= keyrelease; state <= Drive1; END IF; when Foundkey => --state <= debounce_out; if sense = '1' then --state <= debounce_out; --state <= keyrelease; state <= Drive1; else --state <= keyrelease; --state <= Nokey; state <= Foundkey; end if; --when debounce_out => --if Sense = '1' then --if deb_reset = '1' then --state <= keyrelease; --elsif deb_reset = '0' then --state <= debounce_out; --end if; --else --state <= keyrelease; --end if; --when debounce_out=> --for count in 0 to 20 loop --end loop; --for count2 in 0 to 20 loop --end loop; --end loop; --state <= keyrelease; -- stateDrive <= Drive1; --WHEN Keyrelease => -- stateDrive <= Drive0; --state <= Nokey; --WHEN OTHERS => -- stateDrive <= Drive0; --state <= Nokey; END CASE; -- Button numbers for the keypad -- 0 1 2 3 -- 4 5 6 7 -- 8 9 10 11 -- 12 13 14 15 -- This case determines what key has been pressed -- based on the drive and the row. END IF; END PROCESS StateLogic; -------------------------------------------------------- -- Send the key to the output when the Register key state is found --Outputs: PROCESS(state) --BEGIN --IF(state = Foundkey) THEN --KeyData <= Key; --KeyDetected <= '1'; --ELSE --KeyData <= "0000"; --keyDetected <= '0'; --END IF; --END PROCESS Outputs; WITH state SELECT col <= "0111" WHEN Drive1, --7 "1011" WHEN Drive2, --11 "1101" WHEN Drive4, --13 "1110" WHEN Drive8, --14 --"0000" WHEN Drive0, --15 "0000" when others; END behavioural;