Line 1... |
Line 1... |
---------------------------------------------------------------------------------------
|
--===========================================================================--
|
|
-- --
|
|
-- keyboard.vhd - Synthesizable Interface to PS/2 Keyboard Module --
|
|
-- --
|
|
--===========================================================================--
|
--
|
--
|
-- Author: John Kent
|
-- File name : keyboard.vhd
|
-- Date : April 2, 2004
|
|
-- Interface to John Clayton's PS2 keyboard
|
|
--
|
--
|
---------------------------------------------------------------------------------------
|
-- Entity name : keyboard
|
--
|
--
|
-- 7th Februaury 2007 - John Kent
|
-- Purpose : Implements a CPU interface to John Clayton's PS/2 Keyboard
|
-- Added Generics for Keyboard Timing
|
--
|
|
-- Dependencies : ieee.std_logic_1164
|
|
-- ieee.std_logic_arith
|
|
-- ieee.std_logic_unsigned
|
|
-- ieee.numeric_std
|
|
-- unisim.vcomponents
|
|
--
|
|
-- Uses : ps2_keyboard_interface
|
|
--
|
|
-- Author : John E. Kent
|
|
--
|
|
-- Email : dilbert57@opencores.org
|
|
--
|
|
-- Web : http://opencores.org/project,system09
|
|
--
|
|
-- Registers :
|
|
--
|
|
-- IO address + 0 read - Status Register
|
|
--
|
|
-- Bit[0] - RX Data Ready
|
|
-- Bit[1] - TX Data Empty
|
|
-- Bit[2] - Extended
|
|
-- Bit[3] - Released
|
|
-- Bit[4] - Shift On
|
|
-- Bit[5] - Error (no keyboard acknowledge received)
|
|
-- Bit[6] - TX Interrupt Flag
|
|
-- Bit[7] - RX Interrupt Flag
|
|
--
|
|
-- IO address + 0 write - Control Register
|
|
--
|
|
-- Bit[0] - Undefined
|
|
-- Bit[1] - Undefined
|
|
-- Bit[2] - Undefined
|
|
-- Bit[3] - Undefined
|
|
-- Bit[4] - Undefined
|
|
-- Bit[5] - Undefined
|
|
-- Bit[6] - TX Interrupt Enable
|
|
-- Bit[7] - RX Interrupt Enable
|
|
--
|
|
-- IO address + 1 read - Receive Data Register
|
|
--
|
|
-- IO address + 1 write - Transmit Data Register
|
|
--
|
|
-- Copyright (C) 2004 - 2010 John Kent
|
|
--
|
|
-- This program is free software: you can redistribute it and/or modify
|
|
-- it under the terms of the GNU General Public License as published by
|
|
-- the Free Software Foundation, either version 3 of the License, or
|
|
-- (at your option) any later version.
|
|
--
|
|
-- This program is distributed in the hope that it will be useful,
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
-- GNU General Public License for more details.
|
|
--
|
|
-- You should have received a copy of the GNU General Public License
|
|
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
--
|
|
--===========================================================================--
|
|
-- --
|
|
-- Revision History --
|
|
-- --
|
|
--===========================================================================--
|
|
--
|
|
-- Version Author Date Description
|
|
-- 0.1 John Kent 2nd April 2004 Interface to John Clayton's PS2 keyboard
|
|
-- 0.2 John Kent 7th Februaury 2007 Added Generics for Keyboard Timing
|
|
-- 0.3 John Kent 30th May 2010 Updated Header, added unisim library
|
|
-- 0.4 John Kent 17th June 2010 Cleaned up signal names,
|
|
-- added TX interrupt enable
|
|
-- Modified assignment of status register
|
|
-- Revised hanshake control and input registers
|
--
|
--
|
|
|
library ieee;
|
library ieee;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use IEEE.STD_LOGIC_ARITH.ALL;
|
use ieee.std_logic_arith.all;
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
use ieee.std_logic_unsigned.all;
|
use ieee.numeric_std.all;
|
use ieee.numeric_std.all;
|
|
library unisim;
|
|
use unisim.vcomponents.all;
|
|
|
entity keyboard is
|
entity keyboard is
|
generic (
|
generic (
|
KBD_Clock_Frequency : integer
|
KBD_CLK_FREQ : integer
|
);
|
);
|
|
|
port(
|
port(
|
|
--
|
|
-- CPU Interface Signals
|
|
--
|
clk : in std_logic;
|
clk : in std_logic;
|
rst : in std_logic;
|
rst : in std_logic;
|
cs : in std_logic;
|
cs : in std_logic;
|
rw : in std_logic;
|
|
addr : in std_logic;
|
addr : in std_logic;
|
|
rw : in std_logic;
|
data_in : in std_logic_vector(7 downto 0);
|
data_in : in std_logic_vector(7 downto 0);
|
data_out : out std_logic_vector(7 downto 0);
|
data_out : out std_logic_vector(7 downto 0);
|
irq : out std_logic;
|
irq : out std_logic;
|
|
--
|
|
-- Keyboard Interface Signals
|
|
--
|
kbd_clk : inout std_logic;
|
kbd_clk : inout std_logic;
|
kbd_data : inout std_logic
|
kbd_data : inout std_logic
|
);
|
);
|
end keyboard;
|
end keyboard;
|
|
|
architecture rtl of keyboard is
|
architecture rtl of keyboard is
|
|
|
constant Clock_Frequency_MHz : integer := KBD_Clock_Frequency / 1000000;
|
constant CLK_FREQ_MHZ : integer := KBD_CLK_FREQ / 1000000;
|
|
|
signal kbd_stat : std_logic_vector(7 downto 0);
|
signal kbd_status : std_logic_vector(7 downto 0);
|
signal kbd_ctrl : std_logic_vector(7 downto 6);
|
signal kbd_control : std_logic_vector(7 downto 0);
|
signal kbd_ascii_code : std_logic_vector(7 downto 0);
|
signal kbd_rx_data : std_logic_vector(7 downto 0);
|
signal kbd_tx_data : std_logic_vector(7 downto 0);
|
signal kbd_tx_data : std_logic_vector(7 downto 0);
|
signal kbd_read : std_logic;
|
signal kbd_read : std_logic;
|
signal kbd_write : std_logic;
|
signal kbd_write : std_logic;
|
signal kbd_write_ack : std_logic;
|
signal kbd_data_ready : std_logic; -- => kbd_status(0)
|
|
signal kbd_data_empty : std_logic; -- => kbd_status(1)
|
|
signal kbd_extended : std_logic; -- => kbd_status(2)
|
|
signal kbd_released : std_logic; -- => kbd_status(3)
|
|
signal kbd_shift_on : std_logic; -- => kbd_status(4)
|
|
signal kbd_error : std_logic; -- => kbd_status(5) (No receive acknowledge)
|
|
|
component ps2_keyboard_interface
|
component ps2_keyboard
|
generic (
|
generic (
|
Frequency_MHz : integer := Clock_Frequency_MHz
|
CLK_FREQ_MHZ : integer := CLK_FREQ_MHZ
|
);
|
);
|
|
|
port(
|
port(
|
clk : in std_logic;
|
clk : in std_logic;
|
reset : in std_logic;
|
reset : in std_logic;
|
ps2_clk : inout std_logic;
|
rx_data : out std_logic_vector(7 downto 0);
|
ps2_data : inout std_logic;
|
rx_read : in std_logic;
|
|
rx_data_ready : out std_logic;
|
rx_extended : out std_logic;
|
rx_extended : out std_logic;
|
rx_released : out std_logic;
|
rx_released : out std_logic;
|
rx_shift_key_on : out std_logic;
|
rx_shift_on : out std_logic;
|
-- rx_scan_code : out std_logic_vector(7 downto 0);
|
|
rx_ascii : out std_logic_vector(7 downto 0);
|
|
rx_data_ready : out std_logic; -- rx_read_o
|
|
rx_read : in std_logic; -- rx_read_ack_i
|
|
tx_data : in std_logic_vector(7 downto 0);
|
tx_data : in std_logic_vector(7 downto 0);
|
tx_write : in std_logic;
|
tx_write : in std_logic;
|
tx_write_ack : out std_logic;
|
tx_data_empty : out std_logic;
|
tx_error_no_keyboard_ack : out std_logic
|
tx_error : out std_logic;
|
|
ps2_clk : inout std_logic;
|
|
ps2_data : inout std_logic
|
);
|
);
|
end component;
|
end component;
|
|
|
begin
|
begin
|
|
|
my_ps2_keyboard_interface : ps2_keyboard_interface
|
my_ps2_keyboard : ps2_keyboard
|
generic map (
|
generic map (
|
Frequency_MHz => Clock_Frequency_MHz
|
CLK_FREQ_MHZ => CLK_FREQ_MHz
|
)
|
)
|
|
|
port map(
|
port map(
|
clk => clk,
|
clk => clk,
|
reset => rst,
|
reset => rst,
|
ps2_clk => kbd_clk,
|
rx_data => kbd_rx_data,
|
ps2_data => kbd_data,
|
|
rx_extended => kbd_stat(2),
|
|
rx_released => kbd_stat(3),
|
|
rx_shift_key_on => kbd_stat(4),
|
|
rx_ascii => kbd_ascii_code,
|
|
rx_data_ready => kbd_stat(0),
|
|
rx_read => kbd_read,
|
rx_read => kbd_read,
|
|
rx_data_ready => kbd_data_ready,
|
|
rx_extended => kbd_extended,
|
|
rx_released => kbd_released,
|
|
rx_shift_on => kbd_shift_on,
|
tx_data => kbd_tx_data,
|
tx_data => kbd_tx_data,
|
tx_write => kbd_write,
|
tx_write => kbd_write,
|
tx_write_ack => kbd_write_ack,
|
tx_data_empty => kbd_data_empty,
|
tx_error_no_keyboard_ack => kbd_stat(5)
|
tx_error => kbd_error,
|
|
ps2_clk => kbd_clk,
|
|
ps2_data => kbd_data
|
);
|
);
|
|
|
keyboard_strobe : process( clk, rst, cs, rw, kbd_stat )
|
--
|
|
-- Keyboard Read strobe
|
|
--
|
|
keyboard_read : process( clk, rst, cs, rw, kbd_data_ready )
|
begin
|
begin
|
if( rst = '1' ) then
|
if rst = '1' then
|
kbd_read <= '0';
|
kbd_read <= '0';
|
elsif( clk'event and clk='0' ) then
|
elsif( clk'event and clk='0' ) then
|
if( cs='1' and rw='1' and addr='1' ) then
|
if( cs = '1' and addr = '1' and rw = '1' ) then
|
kbd_read <= '1';
|
kbd_read <= '1';
|
elsif( kbd_stat(0)='1' ) then
|
elsif kbd_data_ready = '1' then
|
kbd_read <= '0';
|
kbd_read <= '0';
|
else
|
|
kbd_read <= kbd_read;
|
|
end if;
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
--
|
--
|
-- read keyboard registers
|
-- Keyboard Write strobe
|
--
|
--
|
keyboard_read : process( addr, kbd_ascii_code, kbd_stat )
|
keyboard_write : process( clk, rst, cs, rw, addr,
|
|
kbd_write, kbd_data_empty )
|
begin
|
begin
|
if( addr = '1' ) then
|
if rst = '1' then
|
data_out <= kbd_ascii_code;
|
kbd_write <= '0';
|
else
|
elsif( clk'event and clk='0' ) then
|
data_out <= kbd_stat;
|
if( cs = '1' and addr = '1' and rw = '0' ) then
|
|
kbd_write <= '1';
|
|
elsif kbd_data_empty = '1' then
|
|
kbd_write <= '0';
|
|
end if;
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
--
|
--
|
-- Write to keyboard register
|
-- Keyboard register input
|
--
|
--
|
keyboard_write : process( clk, rst, cs, rw, addr, data_in, kbd_tx_data,
|
keyboard_in : process( clk, rst, cs, rw, addr, data_in, kbd_rx_data )
|
kbd_write, kbd_write_ack )
|
|
begin
|
begin
|
if(rst = '1' ) then
|
if rst = '1' then
|
kbd_ctrl <= "00";
|
kbd_control <= (others => '0');
|
kbd_tx_data <= "00000000";
|
kbd_tx_data <= (others => '0');
|
kbd_write <= '0';
|
|
elsif( clk'event and clk='0' ) then
|
elsif( clk'event and clk='0' ) then
|
if( cs='1' and rw='0' ) then
|
if( cs='1' and rw='0' ) then
|
if( addr='1' ) then
|
if addr = '0' then
|
kbd_tx_data <= data_in;
|
kbd_control <= data_in;
|
kbd_ctrl <= kbd_ctrl;
|
|
kbd_write <= '1';
|
|
else
|
else
|
kbd_tx_data <= kbd_tx_data;
|
kbd_tx_data <= data_in;
|
kbd_ctrl <= data_in(7 downto 6);
|
|
kbd_write <= kbd_write;
|
|
end if;
|
end if;
|
elsif( kbd_write_ack='1' ) then
|
|
kbd_write <= '0';
|
|
else
|
|
kbd_write <= kbd_write;
|
|
end if;
|
end if;
|
kbd_stat(1) <= not kbd_write;
|
|
end if;
|
end if;
|
end process;
|
end process;
|
|
|
keyboard_interrupt : process( kbd_ctrl, kbd_stat )
|
--
|
|
-- Keyboard register output
|
|
--
|
|
keyboard_out : process( addr, kbd_rx_data, kbd_status )
|
begin
|
begin
|
kbd_stat(6) <= kbd_ctrl(6);
|
if( addr = '0' ) then
|
kbd_stat(7) <= kbd_ctrl(7) and kbd_stat(0);
|
data_out <= kbd_status;
|
irq <= kbd_stat(7);
|
else
|
|
data_out <= kbd_rx_data;
|
|
end if;
|
end process;
|
end process;
|
|
|
|
--
|
|
-- Assign Keyboard Status bits
|
|
--
|
|
keyboard_status : process( kbd_data_ready, kbd_data_empty,
|
|
kbd_extended, kbd_released, kbd_shift_on, kbd_error,
|
|
kbd_control)
|
|
begin
|
|
kbd_status(0) <= kbd_data_ready;
|
|
kbd_status(1) <= kbd_data_empty;
|
|
kbd_status(2) <= kbd_extended;
|
|
kbd_status(3) <= kbd_released;
|
|
kbd_status(4) <= kbd_shift_on;
|
|
kbd_status(5) <= kbd_error;
|
|
kbd_status(6) <= kbd_control(6) and kbd_data_empty; -- TX Interrupt Flag
|
|
kbd_status(7) <= kbd_control(7) and kbd_data_ready; -- RX Interrupt Flag
|
|
irq <= kbd_status(7) or kbd_status(6);
|
|
end process;
|
|
|
end rtl;
|
end rtl;
|
|
|
|
|
No newline at end of file
|
No newline at end of file
|