APPLICATION NOTES: Provided by: Tyler Brandon, Chris Blasko, Kevin Lister. This file contains 4 potentially usefull VHDL programs. These include: --PS/2 Mouse controller --Simplified VGA display code --VGA frame buffer code --Beep generator It should be noted that while this code is mostly functioning, all of the bugs have not been worked out. So if you need a template these programs are a good place to start. Also, as the programs are developed the newer versions will be posted to the Application notes. |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -- m2.vhd (PS/2 mouse code) -- -- compiles without errors -- Does not produce the correct results when hooked up to the Altera Board -- -- Under construction -- By Tyler Brandon, Chris Blasko, Kevin Lister -- U of Alberta -- library ieee; use ieee.std_logic_1164.ALL; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity m2 is port( Clock : in std_logic; --system clock (pin 91), 25.175MHz mouse_data : in std_logic; --data from the PS/2 mouse (pin 31) mouse_clk : in std_logic; --Clock from the PS/2 mouse (pin 30) --MouseX : buffer std_logic_vector(9 downto 0); --current X position of mouse --MouseY : buffer std_logic_vector(8 downto 0); --current Y position of mouse MouseL : out std_logic; MouseR : out std_logic ); --Left mouse button end m2; architecture behavior of m2 is --signal IncommingDataDetected : std_logic; --Set, when start bit of packet found signal data : std_logic_vector(34 downto 0); --Data from the mouse data packet signal clkCounter : integer range 0 to 1007; signal waitCounter : integer range 0 to 1800; --Division of the clock signal reciving_data : std_logic; begin process( Clock ) begin if rising_edge( Clock ) then if mouse_clk = '1' then waitCounter <= waitCounter + 1; else reciving_data <= '1'; waitCounter <= 0; end if; if waitCounter > 1762 then --if 70us has passed without the mouse_clk --going low, then re-synchronize the system reciving_data <= '0'; waitCounter <= 0; end if; end if; end process; process (mouse_clk) variable NumDataBits : integer range 0 to 34; --Number of bits captured begin if (mouse_clk'EVENT and mouse_clk = '1') then if reciving_data = '1' then data(NumDatabits) <= mouse_data; NumDatabits := NumDatabits + 1; if NumDatabits = 33 then MouseL <= data(1); MouseR <= data(2); end if; else NumDatabits := 0; end if; end if; end process; -- if reset = '0' then --MouseL <= '0'; --mouse button not pressed -- mouse_clk <= '1'; -- NumDatabits <= 0; --Starting coordinates -- MouseX <= START_X; --place mouse initially in 2nd column -- MouseY <= START_Y; --place mouse initially in 3rd row -- elsif NumDatabits <= 33 then -- clkCounter <= clkCounter + 1; -- if clkCounter = 504 then -- mouse_clk <= '1'; -- data(NumDatabits) <= MouseData; -- NumDatabits <= NumDatabits + 1; -- elsif clkCounter = 1007 then -- clkCounter <= 0; -- mouse_clk <= '0'; -- end if; -- else -- waitCounter <= waitCounter + 1; -- if waitCounter = 386352 then -- NumDatabits <= 0; -- waitCounter <= 0; -- end if; -- MouseL <= data(1); -- end if; -- end if; -- end process; end behavior; -- Monitor.vhd -- -- Displays different colored vertical bars. Each bar is one pixel in with -- and 480 pixles in length. Resolution 640x480 -- -- It is our intent to provide a simple, ready to use, -- module (the code your looking at) to control the monitor. -- The VGA monitor is controled by ONLY TWO outputs: a horizontal sync -- and a vertical sync. Other than those two signals the monitor, does -- everything else on its own. IT IS YOUR DUTY piolet to fire the Red, -- Green and Blue outputs at the apropriate time to create the picture -- on the screen, BY NO MEANS is the monitor going to wait for you. -- -- The vertical sync (active low) will send the electron beam to the top left most -- corner of the screen. The Horizontal sycn (active low) will send the electron -- beam to the next line (or row, for you spredsheet people). Timing -- documentation can be viewed in the, Altera University Program Design Laboratory -- Package (you thing they could have found a longer name?) -- -- Good luck (the way this code is written, your going to need it ;) ) -- Uses Flex 10K20 Device -- -- Oginial code (razzle.vhd) by Jim Hamblen, -- Georgia Tech School of ECE -- -- Modified for use in the Arkanoid project by Tyler Brandon, Chris Blasco -- and Kevin Lister, -- University of Alberta -- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity monitor is port( signal Clock, reset : in std_logic; signal Red,Green,Blue : out std_logic; signal Horiz_sync,Vert_sync : out std_logic ); end monitor; architecture behavior of monitor is -- Video Display Signals signal H_count,V_count: std_logic_vector(9 Downto 0); signal Red_Data, Green_Data, Blue_Data : std_logic; constant H_max : std_logic_vector(9 Downto 0) := "1100011111";--799 -- 799 is max horiz count constant V_max : std_logic_vector(9 Downto 0) := "1000001100";--524 -- 524 is max vert count signal video_on, video_on_H, video_on_V: std_logic; begin -- Colors for pixel data on video signal (Unrelated to the actual -- generation of output on a VGA monitor.) -- -- *This just determines "what" to display* -- -- (in this case, it displays vertical bars of color) process( Clock ) variable sum : std_logic_vector( 2 downto 0); begin if rising_edge( Clock ) then if reset = '0' then sum := "000"; else sum := sum + '1'; end if; Red_Data <= sum(2); Green_Data <= sum(1); Blue_Data <= sum(0); end if; end process; -- -- -- Makes sure the electron beam in the monitor isn't trying to display -- colors outside of the view area (i.e. on your lab partners forhead). Red <= Red_Data and video_on; Green <= Green_Data and video_on; Blue <= Blue_Data and video_on; -- video_on turns off pixel data when not in the view area video_on <= video_on_H and video_on_V; --Generate Horizontal and Vertical Timing Signals for Video Signal VIDEO_DISPLAY: process begin Wait until(Clock'Event) and (Clock='1'); if reset = '0' Then H_count <= (others => '0'); V_count <= (others => '0'); Video_on_H <= '0'; Video_on_V <= '0'; else -- H_count counts pixels (640 + extra time for sync signals) -- -- <-Clock out RGB Pixel Row Data -> <-H Sync-> -- ------------------------------------__________-------- -- 0 640 659 755 799 -- if (H_count >= H_max) then H_count <= (others => '0'); else H_count <= H_count + '1'; end if; --Generate Horizontal Sync Signal if (H_count <= 755) and (H_count >= 659) Then Horiz_Sync <= '0'; else Horiz_Sync <= '1'; end if; --V_count counts rows of pixels (480 + extra time for sync signals) -- -- <---- 480 Horizontal Syncs (pixel rows) --> ->V Sync<- -- -----------------------------------------------_______--------- -- 0 480 493-494 524 -- if (V_count >= V_max) and (H_count >= 699) then V_count <= (others => '0'); else If (H_count = 699) Then V_count <= V_count + '1'; end if; end if; -- Generate Vertical Sync Signal if (V_count <= 494) and (V_count >= 493) Then Vert_Sync <= '0'; else Vert_Sync <= '1'; end if; -- Generate Video on Screen Signals for Pixel Data if (H_count <= 639) Then video_on_H <= '1'; else video_on_H <= '0'; end if; -- Has the beam reached the bottom of the viewing area? if (V_count <= 479) Then video_on_V <= '1'; else video_on_V <= '0'; end if; end if; --End Wait until clock end process VIDEO_DISPLAY; end behavior; ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -- VGA.vhd (part of VGA_buf.vhd) -- 320x240 resolution -- -- Uses Flex 10K20 Device -- -- Modified from Monitor.vhd (Arkanoid project) which was in turn modified -- from the oginial code razzle.vhd by Jim Hamblen, Georgia Tech School of -- ECE -- -- Modified for use in VGA_buf.vhd by Tyler Brandon, Chris Blasko -- and Kevin Lister, -- University of Alberta -- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity vga is generic( ADDRESS_WIDTH : positive := 17; DATA_WIDTH : positive := 8 ); port( signal clock, reset : in std_logic; signal v_sync : out std_logic; signal Red,Green,Blue : out std_logic; signal Horiz_sync,Vert_sync : buffer std_logic; Address :out std_logic_vector(ADDRESS_WIDTH-1 downto 0); data :in std_logic_vector(DATA_WIDTH-1 downto 0) ); end vga; architecture behavior of vga is -- Video Display Signals signal H_count,V_count: std_logic_vector(9 Downto 0); signal Red_Data, Green_Data, Blue_Data : std_logic; constant H_max : std_logic_vector(9 Downto 0) := "1100011111"; -- 799 is max horiz count constant V_max : std_logic_vector(9 Downto 0) := "1000001100"; -- 524 is max vert count signal video_on, video_on_H, video_on_V: std_logic; signal toggle : std_logic; begin -- Colors for pixel data on video signal (Unrelated to the actual -- generation of output on a VGA monitor.) -- -- *This just determines "what" to display* -- -- Assumpitions: 320x240, 70ns RAM, 40ns Clock process( Clock ) variable sum : std_logic_vector(ADDRESS_WIDTH-1 downto 0); begin if rising_edge( Clock ) then if reset = '0' then sum := (others=>'0'); toggle <= '0'; elsif video_on = '1' then if toggle = '1' then sum := sum + '1'; toggle <= '0'; else toggle <= '1'; end if; end if; if Vert_sync = '0' then sum := (others => '0'); end if; Address <= sum; Red_Data <= data(2); Green_Data <= data(1); Blue_Data <= data(0); end if; end process; -- -- Red <= Red_Data and video_on; Green <= Green_Data and video_on; Blue <= Blue_Data and video_on; v_sync <= not video_on_V;--Output the vetical sync signal. --the v_sync signal represents the starting of the longest --period of time in which the display is inactive. -- video_on turns off pixel data when not in the view area video_on <= video_on_H and video_on_V; --Generate Horizontal and Vertical Timing Signals for Video Signal VIDEO_DISPLAY: Process Begin Wait until(Clock'Event) and (Clock='1'); if reset = '0' Then H_count <= (others => '0'); V_count <= (others => '0'); Video_on_H <= '0'; Video_on_V <= '0'; else -- H_count counts pixels (640 + extra time for sync signals) -- -- <-Clock out RGB Pixel Row Data -> <-H Sync-> -- ------------------------------------__________-------- -- 0 640 659 755 799 -- If (H_count >= H_max) then H_count <= (others => '0'); Else H_count <= H_count + '1'; End if; --Generate Horizontal Sync Signal If (H_count <= 755) and (H_count >= 659) Then Horiz_Sync <= '0'; ELSE Horiz_Sync <= '1'; End if; --V_count counts rows of pixels (480 + extra time for sync signals) -- -- <---- 480 Horizontal Syncs (pixel rows) --> ->V Sync<- -- -----------------------------------------------_______--------- -- 0 480 493-494 524 -- If (V_count >= V_max) and (H_count >= 699) then V_count <= (others => '0'); Else If (H_count = 699) Then V_count <= V_count + '1'; End if; End if; -- Generate Vertical Sync Signal if (V_count <= 494) and (V_count >= 493) Then Vert_Sync <= '0'; ELSE Vert_Sync <= '1'; End if; -- Generate Video on Screen Signals for Pixel Data If (H_count <= 639) Then video_on_H <= '1'; ELSE video_on_H <= '0'; End if; If (V_count <= 479) Then video_on_V <= '1'; ELSE video_on_V <= '0'; End if; End if; --End Wait until clock end process VIDEO_DISPLAY; end behavior; |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -- -- VGA_buf.vhd -- -- When compiling this code causes a fatal error. -- *Still under construction* -- -- Designed to operate in 320x240 and designed to make -- video output simple. -- -- ** -- ALL YOU DO is tell it which pixel address and which color, -- then when your done coloring, tell it to swap buffers and -- your picture is displayed (free of charge, well almost). -- ** -- -- (We couldn't find two 256Kbyte 32-pin SRAM chips that -- ran under 40ns. If we had, this would have been a -- 640x480 frame buffered display. Sorry. -- -- Look at it this way, for extra marks, all you have to -- do is find the chips described above and poof, instant -- marks for improving the design ;p ) -- -- -- Just give us some credit: Tyler Brandon, Chris Blasco, -- and Kevin Lister, U of A. -- (that "A" stands for Alberta, not Alabama) -- -- -- Ok, do NOT hold swap true for more than one clock or your -- output will look totaly messed up. Swap, causes the code -- to switch (or swap) the buffers you are writing to, on the -- clock's rising edge. If swap is held high, the program -- will continue to swap the buffers every clock. -- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity VGA_buf is generic( ADDRESS_WIDTH : positive := 17; DATA_WIDTH : positive := 8; VERTI_BIT_WIDTH : positive := 8; HORIZ_BIT_WIDTH : positive := 9 ); port( clock : in std_logic; reset : in std_logic; wAddress: in std_logic_vector(ADDRESS_WIDTH-1 downto 0); color : in std_logic_vector(DATA_WIDTH-1 downto 0); input : in std_logic; ready : out std_logic; swap : in std_logic; v_sync : out std_logic; Red,Green,Blue : out std_logic; Horiz_sync,Vert_sync : buffer std_logic ); end VGA_buf; architecture VGA_video_buffer of VGA_buf is component vga generic( ADDRESS_WIDTH : positive := 17; DATA_WIDTH : positive := 8 ); port( signal clock, reset : in std_logic; signal v_sync : out std_logic; signal Red,Green,Blue : out std_logic; signal Horiz_sync,Vert_sync : buffer std_logic; Address :out std_logic_vector(ADDRESS_WIDTH-1 downto 0); data :in std_logic_vector(DATA_WIDTH-1 downto 0) ); end component; COMPONENT lpm_ram_dq GENERIC (LPM_WIDTH: POSITIVE; --LPM_TYPE: STRING := L_RAM_DQ; LPM_WIDTHAD: POSITIVE --LPM_NUMWORDS: STRING := UNUSED; --LPM_FILE: STRING := UNUSED; --LPM_INDATA: STRING := REGISTERED; --LPM_ADDRESS_CONTROL: STRING := REGISTERED; --LPM_OUTDATA: STRING := REGISTERED; --LPM_HINT: STRING := UNUSED ); PORT ( data: IN STD_LOGIC_VECTOR(LPM_WIDTH-1 DOWNTO 0); address: IN STD_LOGIC_VECTOR(LPM_WIDTHAD-1 DOWNTO 0); we: IN STD_LOGIC := '1'; inclock: IN STD_LOGIC := '1'; outclock: IN STD_LOGIC := '1'; q: OUT STD_LOGIC_VECTOR(LPM_WIDTH-1 DOWNTO 0) ); END COMPONENT; signal Address : std_logic_vector(ADDRESS_WIDTH-1 downto 0); signal Dataout : std_logic_vector(DATA_WIDTH-1 downto 0); signal address1 : std_logic_vector(ADDRESS_WIDTH-1 downto 0); signal address2 : std_logic_vector(ADDRESS_WIDTH-1 downto 0); signal address3 : std_logic_vector(ADDRESS_WIDTH-1 downto 0); signal data1 : std_logic_vector(DATA_WIDTH-1 downto 0); signal data2 : std_logic_vector(DATA_WIDTH-1 downto 0); signal data3 : std_logic_vector(DATA_WIDTH-1 downto 0); signal dataout1 : std_logic_vector(DATA_WIDTH-1 downto 0); signal dataout2 : std_logic_vector(DATA_WIDTH-1 downto 0); -- A dummy signal (it goes no where) signal dataout3 : std_logic_vector(DATA_WIDTH-1 downto 0); signal write : std_logic; signal nwrite : std_logic; signal wait_toggle : std_logic; begin -- Swap the buffers process( clock ) begin if rising_edge( clock ) then if reset = '0' then write <= '0'; address1 <= Address; data1 <= (others => '0'); dataout <= dataout1; elsif swap = '1' then if write = '1' then write <= '0'; address1 <= Address; data1 <= (others => '0' ); Dataout <= dataout1; address2 <= address3; data2 <= data3; dataout3 <= dataout2; else write <= '1'; address2 <= Address; data2 <= (others => '0' ); Dataout <= dataout2; address1 <= address3; data1 <= data3; dataout3 <= dataout1; end if; end if; end if; end process; nwrite <= not write; --draw the pixel process( clock ) begin if rising_edge( clock ) then if wait_toggle = '1' then wait_toggle <= '0'; ready <= '1'; elsif input = '1' then address3 <= wAddress; data3 <= color; wait_toggle <= '1'; ready <= '0'; end if; end if; end process; A : lpm_ram_dq generic map( LPM_WIDTH => DATA_WIDTH, LPM_WIDTHAD => ADDRESS_WIDTH ) port map ( data => data1, address => address1, we => write, inclock => clock, outclock => clock, q => dataout1 ); B : lpm_ram_dq generic map( LPM_WIDTH => DATA_WIDTH, LPM_WIDTHAD => ADDRESS_WIDTH ) port map ( data => data2, address => address2, we => nwrite, inclock => clock, outclock => clock, q => dataout2 ); vga_connect : vga generic map( ADDRESS_WIDTH => ADDRESS_WIDTH, DATA_WIDTH => DATA_WIDTH ) port map( clock => clock, reset => reset, v_sync => v_sync, Red => Red, Green => Green, Blue => Blue, Horiz_sync => Horiz_sync, Vert_sync => Vert_sync, Address => Address, data => Dataout ); end VGA_video_buffer; ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ----------------------- -- 1, 100Hz beep with trigger signal timed for a 40ns clock -- Beep duration 0.25s --coding by --Chris Blasko, Kevin Lister, Tyler Brandon --This will produce a 100Hz square wave, which will need --amplification and probably an isolation capacitor. --Compilation fault?? Under construction. library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity beep is port(clk, collision: in std_logic; sound: buffer std_logic); end beep; architecture behavioral of beep is begin counter :process(collision, clk) variable count, count2: natural; begin count := 0; if collision = '0' then for count2 in 1 to 25 loop while count < 125000 loop if rising_edge(clk) then count := count + 1; end if; end loop; if sound = '1' then sound <= '0'; else sound <= '1'; end if; end loop; end if; end process counter; end behavioral;