📄 mousectrl.vhd
字号:
------------------------------------------------------------------------
-- 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 + -