⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ps2_keyboard_interface.vhd

📁 BurchED B5-X300 Spartan2e using XC2S300e device Top level file for 6809 compatible system on a chi
💻 VHD
📖 第 1 页 / 共 3 页
字号:
---------------------------------------------------------------------------------------
--
-- Author: John Clayton
-- Date  : April 30, 2001
-- Update: 4/30/01 copied this file from lcd_2.v (pared down).
-- Update: 5/24/01 changed the first module from "ps2_keyboard_receiver"
--                 to "ps2_keyboard_interface"
-- Update: 5/29/01 Added input synchronizing flip-flops.  Changed state
--                 encoding (m1) for good operation after part config.
-- Update: 5/31/01 Added low drive strength and slow transitions to ps2_clk
--                 and ps2_data in the constraints file.  Added the signal
--                 "tx_shifting_done" as distinguished from "rx_shifting_done."
--                 Debugged the transmitter portion in the lab.
-- Update: 6/01/01 Added horizontal tab to the ascii output.
-- Update: 6/01/01 Added parameter TRAP_SHIFT_KEYS.
-- Update: 6/05/01 Debugged the "debounce" timer functionality.
--                 Used 60usec timer as a "watchdog" timeout during
--                 receive from the keyboard.  This means that a keyboard
--                 can now be "hot plugged" into the interface, without
--                 messing up the bit_count, since the bit_count is reset
--                 to zero during periods of inactivity anyway.  This was
--                 difficult to debug.  I ended up using the logic analyzer,
--                 and had to scratch my head quite a bit.
-- Update: 6/06/01 Removed extra comments before the input synchronizing
--                 flip-flops.  Used the correct parameter to size the
--                 5usec_timer_count.  Changed the name of this file from
--                 ps2.v to ps2_keyboard.v
-- Update: 6/06/01 Removed "&& q[7:0]" in output_strobe logic.  Removed extra
--                 commented out "else" condition in the shift register and
--                 bit counter.
-- Update: 6/07/01 Changed default values for 60usec timer parameters so that
--                 they correspond to 60usec for a 49.152MHz clock.
--
--	Converted to VHDL: 10 February 2004 - John Kent
--
--
--
-- Description
---------------------------------------------------------------------------------------
-- This is a state-machine driven serial-to-parallel and parallel-to-serial
-- interface to the ps2 style keyboard interface.  The details of the operation
-- of the keyboard interface were obtained from the following website:
--
--   http:--www.beyondlogic.org/keyboard/keybrd.htm
--
-- Some aspects of the keyboard interface are not implemented (e.g, parity
-- checking for the receive side, and recognition of the various commands
-- which the keyboard sends out, such as "power on selt test passed," "Error"
-- and "Resend.")  However, if the user wishes to recognize these reply
-- messages, the scan code output can always be used to extend functionality
-- as desired.
--
-- Note that the "Extended" (0xE0) and "Released" (0xF0) codes are recognized.
-- The rx interface provides separate indicator flags for these two conditions
-- with every valid character scan code which it provides.  The shift keys are
-- also trapped by the interface, in order to provide correct uppercase ASCII
-- characters at the ascii output, although the scan codes for the shift keys
-- are still provided at the scan code output.  So, the left/right ALT keys
-- can be differentiated by the presence of the rx_entended signal, while the
-- left/right shift keys are differentiable by the different scan codes
-- received.
--
-- The interface to the ps2 keyboard uses ps2_clk clock rates of
-- 30-40 kHz, dependent upon the keyboard itself.  The rate at which the state
-- machine runs should be at least twice the rate of the ps2_clk, so that the
-- states can accurately follow the clock signal itself.  Four times 
-- oversampling is better.  Say 200kHz at least.  The upper limit for clocking
-- the state machine will undoubtedly be determined by delays in the logic 
-- which decodes the scan codes into ASCII equivalents.  The maximum speed
-- will be most likely many megahertz, depending upon target technology.
-- In order to run the state machine extremely fast, synchronizing flip-flops
-- have been added to the ps2_clk and ps2_data inputs of the state machine.
-- This avoids poor performance related to slow transitions of the inputs.
-- 
-- Because this is a bi-directional interface, while reading from the keyboard
-- the ps2_clk and ps2_data lines are used as inputs.  While writing to the
-- keyboard, however (which may be done at any time.  If writing interrupts a
-- read from the keyboard, the keyboard will buffer up its data, and send
-- it later) both the ps2_clk and ps2_data lines are occasionally pulled low,
-- and pullup resistors are used to bring the lines high again, by setting
-- the drivers to high impedance state.
--
-- The tx interface, for writing to the keyboard, does not provide any special
-- pre-processing.  It simply transmits the 8-bit command value to the
-- keyboard.
--
-- Pullups MUST BE USED on the ps2_clk and ps2_data lines for this design,
-- whether they be internal to an FPGA I/O pad, or externally placed.
-- If internal pullups are used, they may be fairly weak, causing bounces
-- due to crosstalk, etc.  There is a "debounce timer" implemented in order
-- to eliminate erroneous state transitions which would occur based on bounce.
-- 
-- Parameters are provided in order to configure and appropriately size the
-- counter of a 60 microsecond timer used in the transmitter, depending on
-- the clock frequency used.  The 60 microsecond period is guaranteed to be
-- more than one period of the ps2_clk_s signal.
--
-- Also, a smaller 5 microsecond timer has been included for "debounce".
-- This is used because, with internal pullups on the ps2_clk and ps2_data
-- lines, there is some bouncing around which occurs
--
-- A parameter TRAP_SHIFT_KEYS allows the user to eliminate shift keypresses
-- from producing scan codes (along with their "undefined" ASCII equivalents)
-- at the output of the interface.  If TRAP_SHIFT_KEYS is non-zero, the shift
-- key status will only be reported by rx_shift_key_on.  No ascii or scan
-- codes will be reported for the shift keys.  This is useful for those who
-- wish to use the ASCII data stream, and who don't want to have to "filter
-- out" the shift key codes.
--
---------------------------------------------------------------------------------------

library ieee;
   use ieee.std_logic_1164.all;
   use IEEE.STD_LOGIC_ARITH.ALL;
   use IEEE.STD_LOGIC_UNSIGNED.ALL;
   use ieee.numeric_std.all;

entity ps2_keyboard_interface is
  port(
  clk             : in    std_logic;
  reset           : in    std_logic;
  ps2_clk         : inout std_logic;
  ps2_data        : inout std_logic;
  rx_extended     : out   std_logic;
  rx_released     : out   std_logic;
  rx_shift_key_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_write        : in    std_logic;
  tx_write_ack    : out   std_logic;
  tx_error_no_keyboard_ack	: out  std_logic
  );
end ps2_keyboard_interface;

-------------------------------------------------------------------------------
-- Architecture for ps2 keyboard interface
-------------------------------------------------------------------------------
architecture my_ps2_keyboard of ps2_keyboard_interface is
  -----------------------------------------------------------------------------

constant TOTAL_BITS   : integer := 11;
constant EXTEND_CODE  : integer := 16#E0#;
constant RELEASE_CODE : integer := 16#F0#;
constant LEFT_SHIFT   : integer := 16#12#;
constant RIGHT_SHIFT  : integer := 16#59#;


-- constants

-- The timer value can be up to (2^bits) inclusive.
-- Values for 49.152 MHz clock
--constant TIMER_60USEC_VALUE_PP : integer := 2950; -- Number of sys_clks for 60usec.
--constant TIMER_60USEC_BITS_PP  : integer := 12;   -- Number of bits needed for timer
--constant TIMER_5USEC_VALUE_PP  : integer := 186;   -- Number of sys_clks for debounce
--constant TIMER_5USEC_BITS_PP   : integer := 8;     -- Number of bits needed for timer

-- Values for  12.5 MHz Clock
constant TIMER_60USEC_VALUE_PP : integer := 750; -- Number of sys_clks for 60usec.
constant TIMER_60USEC_BITS_PP  : integer := 10;  -- Number of bits needed for timer
constant TIMER_5USEC_VALUE_PP  : integer := 62;  -- Number of sys_clks for debounce
constant TIMER_5USEC_BITS_PP   : integer := 6;   -- Number of bits needed for timer

constant TRAP_SHIFT_KEYS_PP    : integer := 0;   -- Default: No shift key trap.

-- State encodings, provided as constants
-- for flexibility to the one instantiating the module.
-- In general, the default values need not be changed.

-- State "m1_rx_clk_l" has been chosen on purpose.  Since the input
-- synchronizing flip-flops initially contain zero, it takes one clk
-- for them to update to reflect the actual (idle = high) status of
-- the I/O lines from the keyboard.  Therefore, choosing 0 for m1_rx_clk_l
-- allows the state machine to transition to m1_rx_clk_h when the true
-- values of the input signals become present at the outputs of the
-- synchronizing flip-flops.  This initial transition is harmless, and it
-- eliminates the need for a "reset" pulse before the interface can operate.

type m1_type is ( m1_rx_clk_h, m1_rx_clk_l,
                  m1_tx_wait_clk_h, m1_tx_force_clk_l,
						m1_tx_clk_h, m1_tx_clk_l,
						m1_tx_wait_keyboard_ack, m1_tx_done_recovery,
						m1_tx_error_no_keyboard_ack, m1_tx_rising_edge_marker,
						m1_tx_first_wait_clk_h, m1_tx_first_wait_clk_l, m1_tx_reset_timer, 
                  m1_rx_falling_edge_marker, m1_rx_rising_edge_marker );

type m2_type is (	m2_rx_data_ready_ack, m2_rx_data_ready );

-- Internal signal declarations
signal timer_60usec_done  : std_logic;
signal timer_5usec_done   : std_logic;
signal extended           : std_logic;
signal released           : std_logic;
signal shift_key_on       : std_logic;

                         -- NOTE: These two signals used to be one.  They
                         --       were split into two signals because of
                         --       shift key trapping.  With shift key
                         --       trapping, no event is generated externally,
                         --       but the "hold" data must still be cleared
                         --       anyway regardless, in preparation for the
                         --       next scan codes.
signal rx_output_event    : std_logic;    -- Used only to clear: hold_released, hold_extended
signal rx_output_strobe   : std_logic;   -- Used to produce the actual output.

signal tx_parity_bit      : std_logic;
signal rx_shifting_done   : std_logic;
signal tx_shifting_done   : std_logic;
signal shift_key_plus_code: std_logic_vector(11 downto 0);

signal q                  : std_logic_vector(TOTAL_BITS-1 downto 0);
signal m1_state           : m1_type;
signal m1_next_state      : m1_type;
signal m2_state           : m2_type;
signal m2_next_state      : m2_type;
signal bit_count          : std_logic_vector(3 downto 0);
signal enable_timer_60usec: std_logic;
signal enable_timer_5usec : std_logic;
signal timer_60usec_count : std_logic_vector(TIMER_60USEC_BITS_PP-1 downto 0);
signal timer_5usec_count  : std_logic_vector(TIMER_5USEC_BITS_PP-1 downto 0);
signal ascii              : std_logic_vector(7 downto 0);      -- "REG" type only because a case statement is used.
signal left_shift_key     : std_logic;
signal right_shift_key    : std_logic;
signal hold_extended      : std_logic;  -- Holds prior value, cleared at rx_output_strobe
signal hold_released      : std_logic;  -- Holds prior value, cleared at rx_output_strobe
signal ps2_clk_s          : std_logic;  -- Synchronous version of this input
signal ps2_data_s         : std_logic;  -- Synchronous version of this input
signal ps2_clk_hi_z       : std_logic;  -- Without keyboard, high Z equals 1 due to pullups.
signal ps2_data_hi_z      : std_logic;  -- Without keyboard, high Z equals 1 due to pullups.
signal tx_write_ack_o	  : std_logic;

begin
----------------------------------------------------------------------------
-- Module code
-- assign ps2_clk = ps2_clk_hi_z?1'bZ:1'b0;
-- assign ps2_data = ps2_data_hi_z?1'bZ:1'b0;
--
ps2_direction : process( ps2_clk_hi_z, ps2_data_hi_z )
begin
  if( ps2_clk_hi_z = '1' ) then
     ps2_clk <= 'Z';
  else
     ps2_clk <= '0';
  end if;
  if( ps2_data_hi_z = '1' ) then
     ps2_data <= 'Z';
  else
     ps2_data <= '0';
  end if;
end process;
   
-- Input "synchronizing" logic -- synchronizes the inputs to the state
-- machine clock, thus avoiding errors related to
-- spurious state machine transitions.
ps2_synch : process(clk, ps2_clk, ps2_data)
begin
  if clk'event and clk='1' then
    ps2_clk_s <= ps2_clk;
    ps2_data_s <= ps2_data;
  end if;
end process;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -