Files
nascom2_t80/keyboard.vhd
2009-01-15 19:17:56 +00:00

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;