207 lines
7.5 KiB
VHDL
Executable File
207 lines
7.5 KiB
VHDL
Executable File
----------------------------------------------------------------------------------
|
|
-- 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;
|