---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 15:52:22 12/30/2008 -- Design Name: -- Module Name: toplevel - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; use IEEE.NUMERIC_STD.ALL; ---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code. library UNISIM; use UNISIM.VComponents.all; entity keyboard is port ( -- PS/2 Interface PS2_CLK : inout std_logic; PS2_DATA : inout std_logic; -- Z80 interface CLK_16M : in std_logic; IORQ_n : in std_logic; RD_n, WR_n : in std_logic; DATA_I : in std_logic_vector(7 downto 0); DATA_O : out std_logic_vector(7 downto 0); -- DEBUG DEBUG : out std_logic_vector(7 downto 0) -- DEBUGLED : out std_logic_vector(7 downto 0) ); end keyboard; architecture Behavioral of keyboard is type states is (ST_RESET, ST_IDLE, ST_READ, ST_PARITY, ST_ERROR, ST_STOP); signal state : states := ST_RESET; signal parity_r, up_r, ext_r : std_logic := '0'; signal key_in_r : std_logic_vector(7 downto 0); signal count : unsigned(2 downto 0); type line_lut_t is array (0 to 255) of integer range 0 to 9; type bit_lut_t is array (0 to 255) of integer range 0 to 7; signal line_lut : line_lut_t; signal bit_lut : bit_lut_t; signal ps2clk_s, ps2data_s : std_logic_vector(2 downto 0) := "111"; signal debug_evt_counter : std_logic_vector(7 downto 0) := X"00"; type key_buffer_t is array (0 to 9) of std_logic_vector(7 downto 0); signal key_buffer : key_buffer_t; signal keyb_row_r : unsigned(3 downto 0) := to_unsigned(0, 4); signal lastin_r : std_logic_vector(1 downto 0) := "00"; begin -- Behavioral -- 0 1 2 3 4 5 6 7 8 9 A B C D E F line_lut <= (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, -- 0_ 0, 0, 0, 0, 0, 5, 6, 0, 0, 0, 2, 3, 4, 4, 6, 0, -- 1_ 0, 7, 1, 2, 3, 7, 5, 0, 0, 7, 7, 1, 1, 7, 1, 0, -- 2_ 0, 2, 1, 1, 7, 2, 2, 0, 0, 0, 3, 2, 3, 3, 4, 0, -- 3_ 0, 4, 3, 4, 5, 6, 5, 0, 0, 5, 6, 4, 5, 6, 8, 0, -- 4_ 0, 0, 6, 0, 6, 0, 0, 0, 0, 0, 8, 7, 0, 5, 0, 0, -- 5_ 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 6_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 7_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- e0 0_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- e0 1_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- e0 2_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- e0 3_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- e0 4_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- e0 5_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, -- e0 6_ 0, 0, 3, 0, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); -- e0 7_ -- 0 1 2 3 4 5 6 7 8 9 A B C D E F bit_lut <= (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, -- 0_ 0, 0, 4, 0, 0, 4, 4, 0, 0, 0, 5, 4, 4, 3, 3, 0, -- 1_ 0, 3, 4, 3, 3, 2, 3, 0, 0, 4, 1, 3, 5, 5, 2, 0, -- 2_ 0, 1, 1, 0, 0, 4, 2, 0, 0, 0, 1, 0, 5, 2, 2, 0, -- 3_ 0, 1, 0, 5, 5, 2, 2, 0, 0, 1, 1, 0, 0, 5, 2, 0, -- 4_ 0, 0, 0, 0, 6, 0, 0, 0, 0, 4, 1, 6, 0, 6, 0, 0, -- 5_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 6_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 7_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- e0 0_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- e0 1_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- e0 2_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- e0 3_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- e0 4_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- e0 5_ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, -- e0 6_ 0, 0, 6, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); -- e0 7_ z80bus: process(CLK_16M) begin if rising_edge(CLK_16M) then if (IORQ_n = '0') and (WR_n = '0') then if (DATA_I(0) = '0') and (lastin_r(0) = '1') then if keyb_row_r < 9 then keyb_row_r <= keyb_row_r + 1; end if; elsif (DATA_I(1) = '0') and (lastin_r(1) = '1') then keyb_row_r <= to_unsigned(0, keyb_row_r'length); end if; lastin_r <= DATA_I(1 downto 0); end if; end if; end process; DATA_O <= key_buffer(to_integer(keyb_row_r)); process (CLK_16M) begin if rising_edge(CLK_16M) then ps2clk_s <= ps2clk_s(1 downto 0) & PS2_CLK; ps2data_s <= ps2data_s(1 downto 0) & PS2_DATA; end if; end process; fsm: process (CLK_16M) variable next_state : states; variable line_v : integer range 0 to 8; variable bit_v : integer range 0 to 7; begin if rising_edge(CLK_16M) then next_state := state; case state is when ST_RESET => key_buffer <= (X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF", X"FF"); next_state := ST_IDLE; when ST_IDLE => if (ps2clk_s(2) = '1') and (ps2clk_s(1) = '0') then -- falling edge if ps2data_s(2) = '0' then count <= to_unsigned(0, count'length); parity_r <= '0'; next_state := ST_READ; end if; end if; when ST_READ => if (ps2clk_s(2) = '1') and (ps2clk_s(1) = '0') then -- falling edge key_in_r(to_integer(count)) <= ps2data_s(2); parity_r <= parity_r xor ps2data_s(2); if count = 7 then next_state := ST_PARITY; else count <= count + 1; end if; end if; when ST_PARITY => if (ps2clk_s(2) = '1') and (ps2clk_s(1) = '0') then -- falling edge if parity_r = ps2data_s(2) then -- ext_r <= '0'; -- up_r <= '0'; next_state := ST_ERROR; else if key_in_r = X"E0" then ext_r <= '1'; elsif key_in_r = X"F0" then up_r <= '1'; else -- process key code line_v := line_lut(conv_integer(ext_r & key_in_r(6 downto 0))); bit_v := bit_lut(conv_integer(ext_r & key_in_r(6 downto 0))); if not ((line_v = 0) and (bit_v = 0)) then key_buffer(line_v)(bit_v) <= up_r; end if; ext_r <= '0'; up_r <= '0'; end if; next_state := ST_STOP; end if; end if; when ST_ERROR => debug_evt_counter <= debug_evt_counter + 1; next_state := ST_IDLE; when ST_STOP => next_state := ST_IDLE; when others => null; end case; state <= next_state; end if; end process; -- DEBUGLED <= debug_evt_counter; PS2_CLK <= 'Z'; PS2_DATA <= 'Z'; end Behavioral;