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

📄 mousectrl.vhd

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

-- This controller is implemented as described in the above article.
-- The mouse controller receives bytes from the ps2interface which, in
-- turn, receives them from the mouse device. Data is received on the
-- rx_data input port, and is validated by the read signal. read is
-- active for one clock period when new byte available on rx_data. Data
-- is sent to the ps2interface on the tx_data output port and validated
-- by the write output signal. 'write' should be active for one clock
-- period when tx_data contains the command or data to be sent to the
-- mouse. ps2interface wraps the byte in a 11 bits packet that is sent
-- through the ps/2 port using the ps/2 protocol. Similarly, when the
-- mouse sends data, the ps2interface receives 11 bits for every byte,
-- extracts the byte from the ps/2 frame, puts it on rx_data and
-- activates read for one clock period. If an error occurs when sending
-- or receiving a frame from the mouse, the err input goes high for one
-- clock period. When this occurs, the controller enters reset state.

-- When in reset state, the controller resets the mouse and begins an
-- initialization procedure that consists of tring to put mouse in
-- scroll mode (enables wheel if the mouse has one), setting the
-- resolution of the mouse, the sample rate and finally enables
-- reporting. Implicitly the mouse, after a reset or imediately after a
-- reset, does not send data packets on its own. When reset(or power-up)
-- the mouse enters reset state, where it performs a test, called the
-- bat test (basic assurance test), when this test is done, it sends
-- the result: AAh for test ok, FCh for error. After this it sends its
-- ID which is 00h. When this is done, the mouse enters stream mode,
-- but with reporting disabled (movement data packets are not sent).
-- To enable reporting the enable data reporting command (F4h) must be
-- sent to the mouse. After this command is sent, the mouse will send
-- movement data packets when the mouse is moved or the status of the
-- button changes.

-- After sending a command or a byte following a command, the mouse
-- must respond with ack (FAh). For managing the intialization
-- procedure and receiving the movement data packets, a FSM is used.
-- When the fpga is powered up or the logic is reset using the global
-- reset, the FSM enters reset state. From this state, the FSM will
-- transition to a series of states used to initialize the mouse. When
-- initialization is complete, the FSM remains in state read_byte_1,
-- waiting for a movement data packet to be sent. This is the idle
-- state if the FSM. When a byte is received in this state, this is
-- the first byte of the 3 bytes sent in a movement data packet (4 bytes
-- if mouse in scrolling mode). After reading the last byte from the
-- packet, the FSM enters mark_new_event state and sets new_event high.
-- After that FSM enterss read_byte_1 state, resets new_event and waits
-- for a new packet.
-- After a packet is received, new_event is set high for one clock
-- period to "inform" the clients of this controller a new packet was
-- received and processed.

-- During the initialization procedure, the controller tries to put the
-- mouse in scroll mode (activates wheel, if mouse has one). This is
-- done by successively setting the sample rate to 200, then to 100, and
-- lastly to 80. After this is done, the mouse ID is requested by 
-- sending get device ID command (F2h). If the received ID is 00h than
-- the mouse does not have a wheel. If the received ID is 03h than the
-- mouse is in scroll mode, and when sending movement data packets
-- (after enabling data reporting) it will include z movement data.
-- If the mouse is in normal, non-scroll mode, the movement data packet
-- consists of 3 successive bytes. This is their format:
--
--
--
-- bits      7     6     5     4     3     2     1     0
--        -------------------------------------------------
-- byte 1 | YOVF| XOVF|YSIGN|XSIGN|  1  | MBTN| RBTN| LBTN|
--        -------------------------------------------------
--        -------------------------------------------------
-- byte 2 |                  X MOVEMENT                   |
--        -------------------------------------------------
--        -------------------------------------------------
-- byte 3 |                  Y MOVEMENT                   |
--        -------------------------------------------------
-- OVF = overflow
-- BTN = button
-- M = middle
-- R = right
-- L = left
--
-- When scroll mode is enabled, the mouse send 4 byte movement packets.
-- bits      7     6     5     4     3     2     1     0
--        -------------------------------------------------
-- byte 1 | YOVF| XOVF|YSIGN|XSIGN|  1  | MBTN| RBTN| LBTN|
--        -------------------------------------------------
--        -------------------------------------------------
-- byte 2 |                  X MOVEMENT                   |
--        -------------------------------------------------
--        -------------------------------------------------
-- byte 3 |                  Y MOVEMENT                   |
--        -------------------------------------------------
--        -------------------------------------------------
-- byte 4 |                  Z MOVEMENT                   |
--        -------------------------------------------------
-- x and y movement counters are represented on 8 bits, 2's complement
-- encoding. The first bit (sign bit) of the counters are the xsign and
-- ysign bit from the first packet, the rest of the bits are the second
-- byte for the x movement and the third byte for y movement. For the
-- z movement the range is -8 -> +7 and only the 4 least significant
-- bits from z movement are valid, the rest are sign extensions.
-- The x and y movements are in range: -256 -> +255

-- The mouse uses as axes origin the lower-left corner. For the purpose
-- of displaying a mouse cursor on the screen, the controller inverts
-- the y axis to move the axes origin in the upper-left corner. This
-- is done by negating the y movement value (following the 2s complement
-- encoding). The movement data received from the mouse are delta
-- movements, the data represents the movement of the mouse relative
-- to the last position. The controller keeps track of the position of
-- the mouse relative to the upper-left corner. This is done by keeping
-- the mouse position in two registers x_pos and y_pos and adding the
-- delta movements to their value. The addition uses saturation. That
-- means the value of the mouse position will not exceed certain bounds
-- and will not rollover the a margin. For example, if the mouse is at
-- the left margin and is moved left, the x position remains at the left
-- margin(0). The lower bound is always 0 for both x and y movement.
-- The upper margin can be set using input pins: value, setmax_x,
-- setmax_y. To set the upper bound of the x movement counter, the new
-- value is placed on the value input pins and setmax_x is activated
-- for at least one clock period. Similarly for y movement counter, but
-- setmax_y is activated instead. Notice that value has 10 bits, and so
-- the maximum value for a bound is 1023.

-- The position of the mouse (x_pos and y_pos) can be set at any time,
-- by placing the x or y position on the value input pins and activating
-- the setx, or sety respectively, for at least one clock period. This
-- is useful for setting an original position of the mouse different
-- from (0,0).
------------------------------------------------------------------------
--  Port definitions
------------------------------------------------------------------------
-- clk            - global clock signal (100MHz)
-- rst            - global reset signal
-- read           - input pin, from ps2interface
--                - active one clock period when new data received
--                - and available on rx_data
-- err            - input pin, from ps2interface
--                - active one clock period when error occurred when
--                - receiving or sending data.
-- rx_data        - input pin, 8 bits, from ps2interface
--                - the byte received from the mouse.
-- xpos           - output pin, 10 bits
--                - the x position of the mouse relative to the upper
--                - left corner
-- ypos           - output pin, 10 bits
--                - the y position of the mouse relative to the upper
--                - left corner
-- zpos           - output pin, 4 bits
--                - last delta movement on z axis
-- left           - output pin, high if the left mouse button is pressed
-- middle         - output pin, high if the middle mouse button is
--                - pressed
-- right          - output pin, high if the right mouse button is
--                - pressed
-- new_event      - output pin, active one clock period after receiving
--                - and processing one movement data packet.
-- tx_data        - output pin, 8 bits, to ps2interface
--                - byte to be sent to the mouse
-- write          - output pin, to ps2interface
--                - active one clock period when sending a byte to the
--                - ps2interface.
------------------------------------------------------------------------
-- 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 mouse_controller entity declaration
-- read above for behavioral description and port definitions.
entity mouse_controller is
port(
   clk         : in std_logic;
   rst         : in std_logic;
   read        : in std_logic;
   err         : in std_logic;
   rx_data     : in std_logic_vector(7 downto 0);
   
   xpos        : out std_logic_vector(9 downto 0);
   ypos        : out std_logic_vector(9 downto 0);
   zpos        : out std_logic_vector(3 downto 0);
   left        : out std_logic;
   middle      : out std_logic;
   right       : out std_logic;
   new_event   : out std_logic;
   tx_data     : out std_logic_vector(7 downto 0);
   write       : out std_logic;
   
   value       : in std_logic_vector(9 downto 0);
   setx        : in std_logic;
   sety        : in std_logic;
   setmax_x    : in std_logic;
   setmax_y    : in std_logic
);
end mouse_controller;

architecture Behavioral of mouse_controller is

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

-- constants defining commands to send or received from the mouse
constant FA: std_logic_vector(7 downto 0) := "11111010"; -- 0xFA(ACK)
constant FF: std_logic_vector(7 downto 0) := "11111111"; -- 0xFF(RESET)
constant AA: std_logic_vector(7 downto 0) := "10101010"; -- 0xAA(BAT_OK)
constant OO: std_logic_vector(7 downto 0) := "00000000"; -- 0x00(ID)
                         -- (atention: name is 2 letters O not zero)

-- command to read id
constant READ_ID          : std_logic_vector(7 downto 0) := x"F2";
-- command to enable mouse reporting
-- after this command is sent, the mouse begins sending data packets
constant ENABLE_REPORTING : std_logic_vector(7 downto 0) := x"F4";
-- command to set the mouse resolution
constant SET_RESOLUTION   : std_logic_vector(7 downto 0) := x"E8";
-- the value of the resolution to send after sending SET_RESOLUTION
constant RESOLUTION       : std_logic_vector(7 downto 0) := x"03";
                                                  -- (8 counts/mm)
-- command to set the mouse sample rate
constant SET_SAMPLE_RATE  : std_logic_vector(7 downto 0) := x"F3";

-- the value of the sample rate to send after sending SET_SAMPLE_RATE
constant SAMPLE_RATE      : std_logic_vector(7 downto 0) := x"28";
                                                  -- (40 samples/s)

-- default maximum value for the horizontal mouse position
constant DEFAULT_MAX_X : std_logic_vector(9 downto 0) := "1001111111";
                                                      -- 639
-- default maximum value for the vertical mouse position
constant DEFAULT_MAX_Y : std_logic_vector(9 downto 0) := "0111011111";
                                                      -- 479

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

-- after doing the enable scroll mouse procedure, if the ID returned by
-- the mouse is 03 (scroll mouse enabled) then this register will be set
-- If '1' then the mouse is in scroll mode, else mouse is in simple
-- mouse mode.
signal haswheel: std_logic := '0';

-- horizontal and veritcal mouse position
-- origin of axes is upper-left corner
-- the origin of axes the mouse uses is the lower-left corner
-- The y-axis is inverted, by making negative the y movement received
-- from the mouse (if it was positive it becomes negative
-- and vice versa)
signal x_pos,y_pos: std_logic_vector(10 downto 0) := (others => '0');

-- active when an overflow occurred on the x and y axis
-- bits 6 and 7 from the first byte received from the mouse
signal x_overflow,y_overflow: std_logic := '0';

-- active when the x,y movement is negative
-- bits 4 and 5 from the first byte received from the mouse
signal x_sign,y_sign: std_logic := '0';

-- 2's complement value for incrementing the x_pos,y_pos
-- y_inc is the negated value from the mouse in the third byte
signal x_inc,y_inc: std_logic_vector(7 downto 0) := (others => '0');

-- active for one clock period, indicates new delta movement received
-- on x,y axis
signal x_new,y_new: std_logic := '0';

-- maximum value for x and y position registers(x_pos,y_pos)
signal x_max: std_logic_vector(9 downto 0) := DEFAULT_MAX_X;
signal y_max: std_logic_vector(9 downto 0) := DEFAULT_MAX_Y;

-- active when left,middle,right mouse button is down
signal left_down,middle_down,right_down: std_logic := '0';

-- the FSM states
-- states that begin with "reset" are part of the reset procedure.
-- states that end in "_wait_ack" are states in which ack is waited
-- as response to sending a byte to the mouse.
-- read behavioral description above for details.
type fsm_state is
(
   reset,reset_wait_ack,reset_wait_bat_completion,reset_wait_id,
   reset_set_sample_rate_200,reset_set_sample_rate_200_wait_ack,
   reset_send_sample_rate_200,reset_send_sample_rate_200_wait_ack,
   reset_set_sample_rate_100,reset_set_sample_rate_100_wait_ack,
   reset_send_sample_rate_100,reset_send_sample_rate_100_wait_ack,
   reset_set_sample_rate_80,reset_set_sample_rate_80_wait_ack,
   reset_send_sample_rate_80,reset_send_sample_rate_80_wait_ack,
   reset_read_id,reset_read_id_wait_ack,reset_read_id_wait_id,
   reset_set_resolution,reset_set_resolution_wait_ack,
   reset_send_resolution,reset_send_resolution_wait_ack,
   reset_set_sample_rate_40,reset_set_sample_rate_40_wait_ack,
   reset_send_sample_rate_40,reset_send_sample_rate_40_wait_ack,
   reset_enable_reporting,reset_enable_reporting_wait_ack,
   read_byte_1,read_byte_2,read_byte_3,read_byte_4,mark_new_event
);
-- holds current state of the FSM
signal state: fsm_state := reset;

begin

   -- left output the state of the left_down register   
   left <= left_down when rising_edge(clk);
   -- middle output the state of the middle_down register
   middle <= middle_down when rising_edge(clk);
   -- right output the state of the right_down register
   right <= right_down when rising_edge(clk);

   -- xpos output is the horizontal position of the mouse
   -- it has the range: 0-x_max
   xpos <= x_pos(9 downto 0) when rising_edge(clk);
   -- ypos output is the vertical position of the mouse
   -- it has the range: 0-y_max
   ypos <= y_pos(9 downto 0) when rising_edge(clk);

⌨️ 快捷键说明

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