-- Draw.vhd -- -- 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 Blasko -- and Kevin Lister, -- University of Alberta -- -- Total logic cells used: 232/1152 ( 20%) -- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity draw is port( signal Clock : in std_logic; --signal reset : in std_logic; signal Red,Green,Blue : out std_logic; signal ball_x, ball_y : std_logic_vector(10 downto 0); signal paddle_x : std_logic_vector(10 downto 0); signal Horiz_sync,Vert_sync : buffer std_logic; signal blocks_gone : out std_logic; signal lives : in std_logic_vector(1 downto 0); signal blockaddress : out std_logic_vector(9 downto 0); signal blockdata : in std_logic ); end draw; architecture behavior of draw is constant CBALL_WIDTH : std_logic_vector(10 downto 0) := "00000001010"; --10; constant CBALL_HEIGHT : std_logic_vector(10 downto 0) := "00000001010"; --10; constant CPADDLE_TOP : std_logic_vector(10 downto 0) := "00111000010"; --450; constant CPADDLE_BOTTOM : std_logic_vector(10 downto 0) := "00111010001"; --465; constant CPADDLE_WIDTH : std_logic_vector(10 downto 0) := "00000110010"; --50; constant CLIFE1_TOP : std_logic_vector(10 downto 0) := "00111010101"; --469; constant CLIFE1_BOTTOM : std_logic_vector(10 downto 0) := "00111011111"; --479; constant CLIFE1_LEFT : std_logic_vector(10 downto 0) := "01001101100"; --620; constant CLIFE1_RIGHT : std_logic_vector(10 downto 0) := "01001110110"; --630; constant CLIFE2_TOP : std_logic_vector(10 downto 0) := "00111010101"; --469; constant CLIFE2_BOTTOM : std_logic_vector(10 downto 0) := "00111011111"; --479; constant CLIFE2_LEFT : std_logic_vector(10 downto 0) := "01001011101"; --605; constant CLIFE2_RIGHT : std_logic_vector(10 downto 0) := "01001100111"; --615; -- 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; signal ball_right : std_logic_vector(10 downto 0); signal ball_left : std_logic_vector(10 downto 0); signal ball_top : std_logic_vector(10 downto 0); signal ball_bottom : std_logic_vector(10 downto 0); signal paddle_right : std_logic_vector(10 downto 0); signal paddle_left : std_logic_vector(10 downto 0); signal ball : std_logic; signal paddle : std_logic; signal h_line : std_logic; signal v_line : std_logic; signal life1 : std_logic; signal life2 : std_logic; begin --Calculate the coordinates of the top, bottom, left and right of the ball --and left and right position of the paddle (as the top and bottom of the --paddle remain constant). Do this ONCE at the start of drawing a new screen. --(Note: do not perform excess calulations will drawing, or "flickering" may --occur) process( Vert_Sync ) begin if rising_edge( Vert_Sync ) then ball_left <= ball_x; ball_right <= ball_x + CBALL_WIDTH; ball_top <= ball_y; ball_bottom <= ball_y + CBALL_HEIGHT; paddle_left <= paddle_x; paddle_right <= paddle_x + CPADDLE_WIDTH; end if; end process; --Is the electon beam passing over the ball? If so, set "ball" equal to one. --(Note: "ball" will be used to change the color being drawn.) --(Note the lack of a "clock" signal. This process occurs continuously, all the time) process begin ball <= '0'; if ((H_count > ball_left) and (H_count < ball_right)) then if ((V_count > ball_top) and (V_count < ball_bottom )) then ball <= '1'; end if; end if; end process; --Is the electon beam passing over the paddle? If so, set "paddle" equal to one. --(Note: "paddle" will be used to change the color being drawn.) --(Note the lack of a "clock" signal. This process occurs continuously, all the time) process begin paddle <= '0'; if ((H_count > paddle_left) and (H_count < paddle_right)) then if ((V_count > CPADDLE_TOP) and (V_count < CPADDLE_BOTTOM)) then paddle <= '1'; end if; end if; end process; process begin life1 <= '0'; if (H_count > CLIFE1_LEFT) and (H_count < CLIFE1_RIGHT) then if (V_count > CLIFE1_TOP) and (V_count < CLIFE1_BOTTOM) then life1 <= '1'; end if; end if; end process; process begin life2 <= '0'; if ((H_count > CLIFE2_LEFT) and (H_count < CLIFE2_RIGHT)) then if ((V_count > CLIFE2_TOP) and (V_count < CLIFE2_BOTTOM)) then life2 <= '1'; end if; end if; end process; --Is the electon beam passing over a block during drawing (Vert_sync = 1)? --Use the vertical and horizontal counts to index the Embedded Array Block (memory) -- --This process creates the address to access the memory where the blocks are stored. --(If a block is pressent, the input "blockdata" is one, else "blockdata" is zero.) -- --The block dimensions are 32 pixels by 16 pixels. By ingoring the least significant --5 bits (2 to the power of 5 is 32) of the H_count, the address remains fixed for --32 horizontal pixels, which is the exact length of a block (definately not coincedence ;) ). --The same aplies to the vertical count, by ingoring the least significant 4 bits the --appropriate address is generated. process begin if Vert_Sync = '1' then blockaddress(4 downto 0) <= H_count(9 downto 5); blockaddress(9 downto 5) <= V_count(8 downto 4); else blockaddress <= (others => '0'); end if; end process; --This process is responsible for generating the vertical lines between the blocks. --If this process were taken out, the blocks would appear to be merged together. --Using the same principle as with generating the block memroy address above, we --look for when the 5 least significant bits are zero, which indicates a multiple --of 32 pixels (which is the exact width of a block, again, no coincedence). -- --If it is a multiple of 32 pixels, then set "h_line" to one, else zero. --(Note: "h_line" will be used to change the color being displayed). process begin if H_count(4 downto 0) = "00000" then h_line <= '1'; else h_line <= '0'; end if; end process; --The same as the process above except it generates horizontal lines and is --based on the 4 least significant bits of the Vertical count. process begin if V_count(3 downto 0) = "0000" then v_line <= '1'; else v_line <= '0'; end if; end process; --Were any blocks drawn? --This process is used to determine if all the blocks have been destroyed. --If all the blocks are gone, then tell the game logic that the level is --over (blocks_gone equal to one). process begin if Vert_sync = '1' and blockdata = '1' then blocks_gone <= '0'; elsif rising_edge(Vert_sync) then blocks_gone <= '1'; end if; end process; -- 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 a ball, a paddle and the blocks. -- --Note the order in which the objects are displayed. Objects that --are drawn first can be drawn over by objects drawn latter in the --sequence (i.e. the blocks are drawn over by the lines and the lines --are drawn over by the paddle and the ball). process( Clock ) begin if rising_edge( Clock ) then --if reset = '0' then -- Red_Data <= '0'; -- Green_Data <= '0'; -- Blue_Data <= '0'; --else --Background (Blue) Red_Data <= '0'; Green_Data <= '0'; Blue_Data <= '1'; --Blocks (Red) if blockdata = '1' then Red_Data <= V_count(4); Green_Data <= V_count(5); Blue_Data <= '0'; end if; --Lines (Blue, same as background) if h_line = '1' then Red_Data <= '0'; Green_Data <= '0'; Blue_Data <= '1'; end if; --Lines (Blue, same as background) if v_line = '1' then Red_Data <= '0'; Green_Data <= '0'; Blue_Data <= '1'; end if; --Ball (Green) if ball = '1' then Red_Data <= '0'; Green_Data <= '1'; Blue_Data <= '0'; end if; --Paddle (White) if paddle = '1' then Red_Data <= '1'; Green_Data <= '1'; Blue_Data <= '1'; end if; --Life 1 (Green) if life1 = '1' and lives > "01" then Red_Data <= '0'; Green_Data <= '1'; Blue_Data <= '0'; end if; --Life 2 (Green) if life2 = '1' and lives > "10" then Red_Data <= '0'; Green_Data <= '1'; Blue_Data <= '0'; end if; --end if; end if; end process; -- -- This next section of code (written by Jim Hamblen) is responsible -- for generating the timing and output signals that control the monitor -- -- 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 -- Hcount 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'); elsif (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;