--Mouse demonstration for Altera UP1 board --Authors: Stangeland, Duane; Koziar, Kory; McDermott, Ashley --See video references in tcgrom.mif. library IEEE; use IEEE.STD_LOGIC_1164.all; package my_constants is -- Row 0 is the first line of the screen were the data packet is displayed constant Row0 : std_logic_vector(3 downto 0) := "0000"; --Column 3 - 31 is used to display the 29 bits of information that the mouse sends --through the serial data line. This is used to print each bit of data in a unique --location on the top row (Row 0). (Only ones and zeros will be printed). constant Col3 : std_logic_vector(5 downto 0) := "000111"; constant Col4 : std_logic_vector(5 downto 0) := "001000"; constant Col5 : std_logic_vector(5 downto 0) := "001001"; constant Col6 : std_logic_vector(5 downto 0) := "001010"; constant Col7 : std_logic_vector(5 downto 0) := "001011"; constant Col8 : std_logic_vector(5 downto 0) := "001100"; constant Col9 : std_logic_vector(5 downto 0) := "001101"; constant Col10 : std_logic_vector(5 downto 0) := "001110"; constant Col11 : std_logic_vector(5 downto 0) := "001111"; constant Col12 : std_logic_vector(5 downto 0) := "010000"; constant Col13 : std_logic_vector(5 downto 0) := "010001"; constant Col14 : std_logic_vector(5 downto 0) := "010010"; constant Col15 : std_logic_vector(5 downto 0) := "010011"; constant Col16 : std_logic_vector(5 downto 0) := "010100"; constant Col17 : std_logic_vector(5 downto 0) := "010101"; constant Col18 : std_logic_vector(5 downto 0) := "010110"; constant Col19 : std_logic_vector(5 downto 0) := "010111"; constant Col20 : std_logic_vector(5 downto 0) := "011000"; constant Col21 : std_logic_vector(5 downto 0) := "011001"; constant Col22 : std_logic_vector(5 downto 0) := "011010"; constant Col23 : std_logic_vector(5 downto 0) := "011011"; constant Col24 : std_logic_vector(5 downto 0) := "011100"; constant Col25 : std_logic_vector(5 downto 0) := "011101"; constant Col26 : std_logic_vector(5 downto 0) := "011110"; constant Col27 : std_logic_vector(5 downto 0) := "011111"; constant Col28 : std_logic_vector(5 downto 0) := "100000"; constant Col29 : std_logic_vector(5 downto 0) := "100001"; constant Col30 : std_logic_vector(5 downto 0) := "100010"; constant Col31 : std_logic_vector(5 downto 0) := "100011"; end my_constants; use work.my_constants.all; library ieee; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.all; use IEEE.STD_LOGIC_UNSIGNED.all; LIBRARY lpm; USE lpm.lpm_components.ALL; entity mouse is port( signal Clock : in std_logic; --System Clock signal MouseData : in std_logic; --Direct Data from Mouse signal Red : out std_logic; -- Red Data for Video signal Green : out std_logic; -- Green Data for Video signal Blue : out std_logic; -- Blue Data for Video signal Horiz_sync : out std_logic; -- Sync Signals for VGA Monitor signal Vert_sync : out std_logic -- Sync Signals for VGA Monitor ); end mouse; architecture behavior of mouse is signal MouseL : std_logic := '0'; -- Left Mouse Button signal MouseR : std_logic := '0'; -- Right Mouse Button signal IncommingDataDetected : std_logic := '0'; -- Used to Start MouseDataLatchClock signal MouseDatalatchClock : std_logic; -- Clock used to latch incomming mouse data signal data : std_logic_vector(29 downto 0); -- Data From Mouse signal MouseX : std_logic_vector(6 downto 0) := (others => '0'); -- Mouse X Location signal MouseY : std_logic_vector(6 downto 0) := (others => '0'); -- Mouse Y Location signal DeltaX : std_logic_vector(6 downto 0) := (others => '0'); -- Change in X Location signal DeltaY : std_logic_vector(6 downto 0) := (others => '0'); -- Change in Y Location signal Counter1 : integer := 0; -- Used to divide the system clock signal Counter2 : integer range 0 to 29; -- Used to Count mouse data bits ------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------- -- This following section of code was taken from the Mips program found on the following homepage: -- http://www.ee.gatech.edu/users/hamblen/ALTERA/altera.htm -- Written by : Jim Hamblen, Georgia Tech School of ECE -- It has not been changed in any way, execpt for coding style purposes. ------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------- -- Video Display Signals signal H_count : std_logic_vector(9 Downto 0); signal V_count : std_logic_vector(9 Downto 0); signal F_count : std_logic_vector(4 Downto 0); signal Color_count : std_logic_vector(3 Downto 0); signal Red_Data : std_logic; signal Green_Data : std_logic; signal Blue_Data : std_logic; signal Power_on : std_logic; signal Rev_video : std_logic; -- Signals for Video ROM Memory for Pixel Data signal rom_address : std_logic_vector(8 Downto 0); signal sum_address : std_logic_vector(6 Downto 0); signal rom_data : std_logic_vector(7 Downto 0); signal col_address : std_logic_vector(5 Downto 0); signal row_address : std_logic_vector(5 Downto 0); signal pixel_col_count : std_logic_vector(5 Downto 0); signal pixel_row_count : std_logic_vector(5 Downto 0); signal rom_mux_output : std_logic; signal format_address : std_logic_vector(6 downto 0); signal format_data : std_logic_vector(5 downto 0); constant H_max : std_logic_vector(9 Downto 0) := CONV_STD_LOGIC_VECTOR(799,10); -- 799 is max horiz count constant V_max : std_logic_vector(9 Downto 0) := CONV_STD_LOGIC_VECTOR(524,10); -- 524 is max vert count signal video_on : std_logic; signal video_on_H : std_logic; signal video_on_V : std_logic; begin -- Small 8 by 8 Character Genrator ROM for Video Display tiny_char_gen_rom: lpm_rom GENERIC MAP ( lpm_widthad => 9, lpm_numwords => "512", lpm_outdata => "UNREGISTERED", lpm_address_control => "UNREGISTERED", lpm_file => "tcgrom.mif", lpm_width => 8) PORT MAP ( address => rom_address, q => rom_data); -- MouseL and MouseR added to ensure that the Mouse Buttons were recorded properly as beind pressed. -- This will cause the screen to change colour. Red_Data <= not ((rom_mux_output) xor Rev_video) or MouseL; Green_Data <= not ((rom_mux_output)) or MouseR; Blue_Data <= '1'; rom_address(2 Downto 0) <= pixel_row_count(3 Downto 1); rom_mux_output <= rom_data ( (CONV_INTEGER(NOT pixel_col_count(3 downto 1)))); Red <= Red_Data and video_on; Green <= Green_Data and video_on; Blue <= Blue_Data and video_on; video_on <= video_on_H and video_on_V; ------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------- -- The following process is used to display the data from the mouse on the top line of the screen -- It is a graphical representation of the 1's and 0's from the data line of the mouse to show what -- bits are changing when the mouse moves. This is also taken from the above homepage, with a -- few modifications for our specific needs. The first bit to be printed corresponds to the first -- bit received by the mouse, and the last bit corresponds to the last bit of the third packet. -- A "60" is a '0' and a "61" is a '1'. ------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------- VIDEO_DISPLAY_DATA: process begin wait until (clock'event) and (clock='1'); If (row_address <= "00010") Then rev_video <= '1'; ELSE rev_video <= '0'; End if; If (row_address(0)='0') or (col_address < "000010") or (col_address >"100110") Then rom_address(8 Downto 3) <= "100000"; Else case row_address(4 downto 1) is when Row0 => case col_address(5 downto 0) is when Col3 => if (data(0) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col4 => if (data(1) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col5 => if (data(2) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col6 => if (data(3) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col7 => if (data(4) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col8 => if (data(5) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col9 => if (data(6) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col10=> if (data(7) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col11=> if (data(8) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col12=> if (data(9) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col13=> if (data(10) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col14=> if (data(11) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col15=> if (data(12) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col16=> if (data(13) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col17=> if (data(14) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col18=> if (data(15) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col19=> if (data(16) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col20=> if (data(17) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col21=> if (data(18) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col22=> if (data(19) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col23=> if (data(20) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col24=> if (data(21) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col25=> if (data(22) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col26=> if (data(23) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col27=> if (data(24) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col28=> if (data(25) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col29=> if (data(26) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col30=> if (data(27) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when Col31=> if (data(28) = '1' ) then rom_address(8 Downto 3) <=To_Stdlogicvector(O"61"); else rom_address(8 Downto 3) <=To_Stdlogicvector(O"60"); end if; when others => rom_address(8 Downto 3) <=To_Stdlogicvector(O"40"); end case; -- The character "76" corresponds to our Mouse Pointer. If the location of MouseY is equal to the present -- row address, AND the location of MouseX is equal to the present column address, display the mouse pointer. -- Otherwise, display a blank character "40". WHEN others => If (MouseY(4 downto 1) = row_address(4 downto 1) and MouseX(5 downto 0) = col_address(5 downto 0)) then rom_address(8 downto 3) <= To_Stdlogicvector(O"76"); Else rom_address(8 Downto 3) <=To_Stdlogicvector(O"40"); End if; end CASE; end if; end process VIDEO_DISPLAY_DATA; VIDEO_DISPLAY: Process Begin Wait until(Clock'Event) and (Clock='1'); If Power_on = '0' Then H_count <= CONV_STD_LOGIC_VECTOR(654,10); V_count <= CONV_STD_LOGIC_VECTOR(493,10); Video_on_H <= '0'; Video_on_V <= '0'; Power_On <= '1'; Else If (H_count >= H_max) then H_count <= To_Stdlogicvector(B"0000000000"); Else H_count <= H_count + To_Stdlogicvector(B"0000000001"); End if; If (H_count <= CONV_STD_LOGIC_VECTOR(755,10)) and (H_count >= CONV_STD_LOGIC_VECTOR(659,10)) Then Horiz_Sync <= '0'; ELSE Horiz_Sync <= '1'; End if; If (V_count >= V_max) and (H_count >= CONV_STD_LOGIC_VECTOR(699,10)) then V_count <= To_Stdlogicvector(B"0000000000"); Else If (H_count = CONV_STD_LOGIC_VECTOR(699,10)) Then V_count <= V_count + To_Stdlogicvector(B"0000000001"); End if; End if; If (V_count <= CONV_STD_LOGIC_VECTOR(494,10)) and (V_count >= CONV_STD_LOGIC_VECTOR(493,10)) Then Vert_Sync <= '0'; ELSE Vert_Sync <= '1'; End if; If (H_count <= CONV_STD_LOGIC_VECTOR(639,10)) Then video_on_H <= '1'; If pixel_col_count < CONV_STD_LOGIC_VECTOR(15,6) Then pixel_col_count <= pixel_col_count + '1'; Else pixel_col_count <= "000000"; col_address <= col_address + '1'; End if; ELSE video_on_H <= '0'; pixel_col_count <= "000000"; col_address <= "000000"; End if; IF(H_COUNT = CONV_STD_LOGIC_VECTOR(641,10)) Then pixel_row_count <= pixel_row_count + '1'; If (pixel_row_count = CONV_STD_LOGIC_VECTOR(15,6)) THEN pixel_row_count <= "000000"; row_address <= row_address + '1'; End if; End if; If (V_count <= CONV_STD_LOGIC_VECTOR(479,10)) Then video_on_V <= '1'; ELSE video_on_V <= '0'; pixel_row_count <= "000000"; row_address <= "000000"; End if; If (V_count = CONV_STD_LOGIC_VECTOR(0,10)) and (H_count = CONV_STD_LOGIC_VECTOR(0,10)) then If (F_count = CONV_STD_LOGIC_VECTOR(30,5)) then F_count <= To_Stdlogicvector(B"00000"); Else F_count <= F_count + To_Stdlogicvector(B"00001"); End if; End if; End if; end process VIDEO_DISPLAY; format_address(1 Downto 0) <= Col_address(1 Downto 0); format_address(6 Downto 2) <= Row_address(4 Downto 0); ------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------- -- End of code from -- http://www.ee.gatech.edu/users/hamblen/ALTERA/altera.htm' -- Start of Code for Mouse Written by: Kory W. Koziar, Duane Stangeland, Ashley McDermott ------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------- -- MouseDetect is used to detect information from the serial line of the mouse, and to break up the packets -- into understandable bits. MouseDetect : process (Clock) begin -- Starting location of the mouse If Power_On = '0' then MouseX <= "000000100"; MouseY <= "000000100"; Else -- Sychronize the mouse with the system clock. if (Clock='1' and Clock'Event) then -- If the first data packet is starting, signal the counters to start. And initalize the clock divider, -- and the loop counter. The sampling clock is set to sample on low to high transition. if(IncommingDataDetected='0' and MouseData='1') then IncommingDataDetected<='1'; Counter1<=0; Counter2<=0; MouseDataLatchClock<='0'; -- Data packets are already arriving, so keep implementing the clock divider. elsif (IncommingDataDetected='1') then Counter1<=Counter1+1; -- 10070 = 400us @ 25.175MHz. This places the rising edge of the sampling clock in the middle of a data -- pulse. Data pulses are 800us long, so sample in the middle. The bits need to be flipped such that if -- no movment on the mouse, the Delta's are 0, and not 1 (which they arrive from the data line of the mouse) if (Counter1=10070) then MouseDataLatchClock<='1'; data(Counter2) <= not MouseData; -- 20140 = 800us @ 25.175MHz. Change Mouse data clock to falling edge, reinitialize the clock divider, -- increment loop counter. elsif (Counter1=20140) then MouseDataLatchClock<='0'; Counter1<=0; Counter2<=Counter2+1; -- If all the packets have been received, reset all signals. And analyze data received. if(Counter2>27) then IncommingDataDetected<='0'; Counter1<=0; Counter2<=0; MouseDataLatchClock<='0'; -- If there was a overflow in the X direction, set delta movment to zero. If data(1) /= data(2) then DeltaX <= "0000000"; -- If there was a overflow in the Y direction, set delta movment to zero. Elsif data(3) /= data(4) then DeltaY <= "0000000"; -- If there was a overflow in both directions, set both X and Y delta movement to zero. Elsif ((data(1) /= data(2)) and (data(3) /= data(4))) then DeltaX <= "0000000"; DeltaY <= "0000000"; -- No overflow detected. Check the direction of the mouse. If the direction bit is equal to '1', -- the movement is in the negative direction. If the direction bit is equal to '0', the movement -- is in the positive direction. This is true for both the X and Y direction. Else if data(1) = '1' then DeltaX <= "000" & (not data(17 downto 14)); MouseX <= MouseX - DeltaX; else DeltaX <= "000" & data(17 downto 14); MouseX <= MouseX + DeltaX; end if; if data(3) = '1' then DeltaY <= "000" & (not data(27 downto 24)); MouseY <= MouseY - DeltaY; else DeltaY <= "000" & data(27 downto 24); MouseY <= MouseY + DeltaY; end if; -- Check to see if either the Left or the Right mouse button has been depressed. MouseL <= data(6); MouseR <= data(5); end if; end if; end if; end if; end if; end if; end process MouseDetect; ------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------- -- End of Code for Mouse Written by: Kory W. Koziar, Duane Stangeland, Ashley McDermott ------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------- end behavior;