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

📄 ps2inerface.vhd

📁 actel BASYs开发板自带的demo程序
💻 VHD
📖 第 1 页 / 共 3 页
字号:
------------------------------------------------------------------------
-- ps2interface.vhd
------------------------------------------------------------------------
-- Author : Ulrich Zolt醤
--          Copyright 2006 Digilent, Inc.
------------------------------------------------------------------------
-- Software version : Xilinx ISE 7.1.04i
--                    WebPack
-- Device	        : 3s200ft256-4
------------------------------------------------------------------------
-- This file contains the implementation of a generic bidirectional
-- ps/2 interface.
------------------------------------------------------------------------
--  Behavioral description
------------------------------------------------------------------------
-- Please read the following article on the web for understanding how
-- the ps/2 protocol works.
-- http://www.computer-engineering.org/ps2protocol/

-- This module implements a generic bidirectional ps/2 interface. It can
-- be used with any ps/2 compatible device. It offers its clients a
-- convenient way to exchange data with the device. The interface
-- transparently wraps the byte to be sent into a ps/2 frame, generates
-- parity for byte and sends the frame one bit at a time to the device.
-- Similarly, when receiving data from the ps2 device, the interface
-- receives the frame, checks for parity, and extract the usefull data
-- and forwards it to the client. If an error occurs during receiving
-- or sending a byte, the client is informed by settings the err output
-- line high. This way, the client can resend the data or can issue
-- a resend command to the device.

-- The physical ps/2 interface uses 4 lines
-- For the 6-pin connector pins are assigned as follows: 
-- 1 - Data
-- 2 - Not Implemented
-- 3 - Ground
-- 4 - Vcc (+5V)
-- 5 - Clock
-- 6 - Not Implemented

-- The clock line carries the device generated clock which has a 
-- frequency in range 10 - 16.7 kHz (30 to 50us). When line is idle
-- it is placed in high impedance. The clock is only generated when
-- device is sending or receiving data.
-- The Data and Clock lines are both open-collector with pullup
-- resistors to Vcc. An "open-collector" interface has two possible
-- states: low('0') or high impedance('Z').

-- When device wants to send a byte, it pulls the clock line low and the
-- host(i.e. this interfaces) recognizes that the device is sending data
-- When the host wants to send data, it maeks a request to send. This
-- is done by holding the clock line low for at least 100us, then with
-- the clock line low, the data line is brought low. Next the clock line
-- is released (placed in high impedance). The devices begins generating
-- clock signal on clock line.
-- When receiving data, bits are read from the data line (ps2_data) on
-- the falling edge of the clock (ps2_clk). When sending data, the
-- device reads the bits from the data line on the rising edge of the
-- clock.
-- A frame for sending a byte is comprised of 11 bits as shown bellow:
-- bits     10     9    8    7    6    5    4    3    2    1      0
--        -------------------------------------------------------------
--        | STOP| PAR | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | START |
--        -------------------------------------------------------------
-- STOP  - stop  bit, always '1'
-- PAR   - parity bit, odd parity for the 8 data bits.
--       - select in such way that the number of bits of '1' in the data
--       - bits together with parity bit is odd.
-- D0-7  - data bits.
-- START - start bit, always '0'
--
-- Frame is sent bit by bit starting with the least significant bit
-- (starting bit) and is received the same way. This is done, when
-- receiving, by shifting the frame register to the left when a bit
-- is available and placing the bit on data line on the most significant
-- bit. This way the first bit sent will reach the least significant bit
-- of the frame when all the bits have been received. When sending data
-- the least significant bit of the frame is placed on the data line
-- and the frame is shifted to the right when another bit needs to be
-- sent. During the request to send, when releasing the clock line,
-- the device reads the data line and interprets the data on it as the
-- first bit of the frame. Data line is low at that time, at this is the
-- way the start bit('0') is sent. Because of this, when sending, only
-- 10 shifts of the frame will be made.
-- While the interface is sending or receiving data, the busy output
-- signal goes high. When interface is idle, busy is low.
-- After sending all the bits in the frame, the device must acknowledge
-- the data sent. This is done by the host releasing and data line
-- (clock line is already released) after the last bit is sent. The
-- devices brings the data line and the clock line low, in this order,
-- to acknowledge the data. If data line is high when clock line goes
-- low after last bit, the device did not acknowledge the data and
-- err output is set.
-- A FSM is used to manage the transitions the set all the command
-- signals. States that begin with "rx_" are used to receive data
-- from device and states begining with "tx_" are used to send data
-- to the device.
-- For the parity bit, a ROM holds the parity bit for all possible
-- data (256 possible values, since 8 bits of data). The ROM has
-- dimensions 256x1bit. For obtaining the parity bit of a value,
-- the bit at the data value address is read. Ex: to find the parity
-- bit of 174, the bit at address 174 is read.
-- For generating the necessary delay, counters are used. For example,
-- to generate the 100us delay a 14 bit counter is used that has the
-- upper limit for counting 10000. The interface is designed to run
-- at 100MHz. Thus, 10000x10ns = 100us.

-----------------------------------------------------------------------
-- If using the interface at different frequency than 100MHz, adjusting
-- the delay counters is necessary!!!
-----------------------------------------------------------------------

-- Clock line(ps2_clk) and data line(ps2_data) are passed through a
-- debouncer for the transitions of the clock and data to be clean.
-- Also, ps2_clk_s and ps2_data_s hold the debounced and synchronized
-- value of the clock and data line to the system clock(clk).
------------------------------------------------------------------------
--  Port definitions
------------------------------------------------------------------------
-- ps2_clk        - inout pin, clock line of the ps/2 interface
-- ps2_data       - inout pin, clock line of the ps/2 interface
-- clk            - input pin, system clock signal
-- rst            - input pin, system reset signal
-- tx_data        - input pin, 8 bits, from client
--                - data to be sent to the device
-- write          - input pin, from client
--                - should be active for one clock period when then
--                - client wants to send data to the device and
--                - data to be sent is valid on tx_data
-- rx_data        - output pin, 8 bits, to client
--                - data received from device
-- read           - output pin, to client
--                - active for one clock period when new data is
--                - available from device
-- busy           - output pin, to client
--                - active while sending or receiving data.
-- err            - output pin, to client
--                - active for one clock period when an error occurred
--                - during sending or receiving.
------------------------------------------------------------------------
-- Revision History:
-- 09/18/2006(UlrichZ): created
------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- simulation library
library UNISIM;
use UNISIM.VComponents.all;

-- the ps2interface entity declaration
-- read above for behavioral description and port definitions.
entity ps2interface is
port(
   ps2_clk  : inout std_logic;
   ps2_data : inout std_logic;

   clk      : in std_logic;
   rst      : in std_logic;

   tx_data  : in std_logic_vector(7 downto 0);
   write    : in std_logic;
   
   rx_data  : out std_logic_vector(7 downto 0);
   read     : out std_logic;
   busy     : out std_logic;
   err      : out std_logic
);

-- forces the extraction of distributed ram for
-- the parityrom memory.
-- please remove if block ram is preffered.
attribute rom_extract : string;
attribute rom_extract of ps2interface: entity is "yes";
attribute rom_style : string;
attribute rom_style of ps2interface: entity is "distributed";

end ps2interface;

architecture Behavioral of ps2interface is

------------------------------------------------------------------------
-- CONSTANTS
------------------------------------------------------------------------

-- Values are valid for a 100MHz clk. Please adjust for other
-- frequencies if necessary!

-- upper limit for 100us delay counter.
-- 10000 * 10ns = 100us
constant DELAY_100US : std_logic_vector(13 downto 0):= "10011100010000";
                                                 -- 10000 clock periods
-- upper limit for 20us delay counter.
-- 2000 * 10ns = 20us
constant DELAY_20US  : std_logic_vector(10 downto 0) := "11111010000";
                                                  -- 2000 clock periods
-- upper limit for 63clk delay counter.
constant DELAY_63CLK : std_logic_vector(5 downto 0)  := "111111";
                                                    -- 63 clock periods
-- delay from debouncing ps2_clk and ps2_data signals
constant DEBOUNCE_DELAY : std_logic_vector(3 downto 0)  := "1111";

-- number of bits in a frame
constant NUMBITS: std_logic_vector(3 downto 0) := "1011"; -- 11

-- parity bit position in frame
constant PARITY_BIT: positive := 9;

-- (odd) parity bit ROM
-- Used instead of logic because this way speed is far greater
-- 256x1bit rom
-- If the odd parity bit for a 8 bits number, x, is needed
-- the bit at address x is the parity bit.
type ROM is array(0 to 255) of std_logic;
constant parityrom : ROM := (
'1','0','0','1','0','1','1','0',
'0','1','1','0','1','0','0','1',
'0','1','1','0','1','0','0','1',
'1','0','0','1','0','1','1','0',
'0','1','1','0','1','0','0','1',
'1','0','0','1','0','1','1','0',
'1','0','0','1','0','1','1','0',
'0','1','1','0','1','0','0','1',
'0','1','1','0','1','0','0','1',
'1','0','0','1','0','1','1','0',
'1','0','0','1','0','1','1','0',
'0','1','1','0','1','0','0','1',
'1','0','0','1','0','1','1','0',
'0','1','1','0','1','0','0','1',
'0','1','1','0','1','0','0','1',
'1','0','0','1','0','1','1','0',
'0','1','1','0','1','0','0','1',
'1','0','0','1','0','1','1','0',
'1','0','0','1','0','1','1','0',
'0','1','1','0','1','0','0','1',
'1','0','0','1','0','1','1','0',
'0','1','1','0','1','0','0','1',
'0','1','1','0','1','0','0','1',
'1','0','0','1','0','1','1','0',
'1','0','0','1','0','1','1','0',
'0','1','1','0','1','0','0','1',
'0','1','1','0','1','0','0','1',
'1','0','0','1','0','1','1','0',
'0','1','1','0','1','0','0','1',
'1','0','0','1','0','1','1','0',
'1','0','0','1','0','1','1','0',
'0','1','1','0','1','0','0','1'
);

------------------------------------------------------------------------
-- SIGNALS
------------------------------------------------------------------------

-- 14 bits counter
-- max value DELAY_100US
-- used to wait 100us
signal delay_100us_count: std_logic_vector(13 downto 0) :=
                                          (others => '0');

-- 11 bits counter
-- max value DELAY_20US
-- used to wait 20us
signal delay_20us_count: std_logic_vector(10 downto 0) :=
                                         (others => '0');
-- 11 bits counter
-- max value DELAY_63CLK
-- used to wait 63 clock periods
signal delay_63clk_count: std_logic_vector(5 downto 0) :=

⌨️ 快捷键说明

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