-- ********************************************************************** -- Filename: VGA_Control.vhd -- Authors: Ram S., Maziyar K., Yongjie L., Rejean L. -- Date: -- -- Description: Top level for the VGA controller. Creates the VGA synch -- signals from the SVGA_TIMING_GENERATION signals on reset. Needs an input signal -- RGB_Data_Ready that starts the SVGA_TIMING_GENERATION address counter. -- -- The low level synch information is provided in SVGADEFINES.v -- file, however two counters defined in a package can track the pixel location in -- in the VGA_TOP_LEVEL, which provides user control of pixels, and a level of abstraction -- which is easier to use. -- The RGB buffer in this case uses a 256 (deep) x 24 bit (wide) single port block -- ram which is to be generated through the Xilinx Core gen tools. It is programmed -- to store 256 pixels for a 16 x 16 pixel image. The rgb.coe file needs to be initialized -- in the file, so that an image can be seen. -- This program demonstrates usage of the counters by drawing frame borders at the top -- and left of the screen, and places the 16 x 16 pixel image on the top left -- screen (upside down smiley face) -- -- ********************************************************************** Package VGA_PixlCount is constant HORIZONTAL_MAX : positive := 800; --for a 800 x 600 display constant VERTICAL_MAX : positive := 600; end VGA_PixlCount; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use work.VGA_PixlCount.all; entity VGA_TOP_LEVEL is port ( pixel_clock : in std_logic; RGB_Data_Ready : in std_logic; h_synch_delay : out std_logic; v_synch_delay : out std_logic; comp_synch : out std_logic; blank : out std_logic; pixel_clock_out : out std_logic; R_out, G_out, B_out : out std_logic_vector(7 downto 0) --Memory signals ); end VGA_TOP_LEVEL; architecture behavioral of VGA_TOP_LEVEL is --not used signals from SVGA_timing_generator signal user_access_ok : std_logic; signal select_user_clock : std_logic; --signal for pixel_counter --to be tied to vga_ram_read_address from SVGATIMINGGENERATOR.v signal Pixel_Counter : std_logic_vector(19 downto 0); signal Pixel_Counter_Last : std_logic_vector(19 downto 0); --necessary reset signal to start the Pixel_Counter signal reset : std_logic; --memory signals for 24 x 256 RGB block signal addr : std_logic_vector(7 downto 0); signal din, dout : std_logic_vector(23 downto 0); signal en, we : std_logic; --component declarations --declare verilog component SVGA_Timing_Generation --Description: Component generates the VGA monitor control signals -- and also generates the RGB pixel addresses -- so that they are synchronized component SVGA_TIMING_GENERATION is port ( pixel_clock, reset : in std_logic; h_synch_delay, v_synch_delay, comp_synch, blank : out std_logic; vga_ram_read_address : out std_logic_vector (19 downto 0); --serves as pixel counter starting from 0 to (600 * 800 - 1) user_access_ok, select_user_clock : out std_logic; pixel_clk_out : out std_logic ); end component SVGA_TIMING_GENERATION; --RGB Block - will use to read RGB values --must be generated from the Xilinx core gen --using the same component name and data widths --(256 deep) (24 wide) or else change these values COMPONENT get_ram_data24_256 port ( addr: IN std_logic_vector(7 downto 0); clk: IN std_logic; din: IN std_logic_vector(23 downto 0); dout: OUT std_logic_vector(23 downto 0); en: IN std_logic; we: IN std_logic ); END COMPONENT get_ram_data24_256; begin --begin architecture --instantiate components SVGA_Controller : SVGA_TIMING_GENERATION port map ( pixel_clock => pixel_clock, reset => reset, h_synch_delay => h_synch_delay, v_synch_delay => v_synch_delay, comp_synch => comp_synch, blank => blank, vga_ram_read_address => Pixel_Counter, user_access_ok => user_access_ok, select_user_clock => select_user_clock, pixel_clk_out => pixel_clock_out ); ram0 : get_ram_data24_256 port map ( addr => addr, clk => pixel_clock, din => din, dout => dout, en => en, we => we ); --processes RGB_Converter_behaviour : process (pixel_clock) variable hpixl_counter : integer := 0; variable vpixl_counter : integer := 0; begin if rising_edge(pixel_clock) then if (RGB_Data_Ready = '1') then --signal that RGB is written to the buffer if (Pixel_Counter /= Pixel_Counter_Last) then Pixel_Counter_Last <= Pixel_Counter; if (Pixel_Counter="00000000000000000000") then hpixl_counter := 0; vpixl_counter := 0; --read from base memory addr <= (others => '0'); en<='1'; we<='0'; elsif (Pixel_Counter/="00000000000000000000") then vpixl_counter := vpixl_counter + 1; hpixl_counter := hpixl_counter + 1; if (vpixl_counter <= 16 * HORIZONTAL_MAX) then --output from memory if (hpixl_counter <= 16 ) then R_out <=dout(23 downto 16); G_out <=dout(15 downto 8); B_out <=dout(7 downto 0); if (addr = "11111111") then addr <= (others => '0'); else addr <= addr + 1; end if; en<='1'; we<='0'; --enable read for next address end if; if (hpixl_counter >16) then R_out <= "00000111"; --blue G_out <= "00001111"; B_out <= "00111111"; end if; elsif (hpixl_counter >16) then R_out <= "00001111"; --green G_out <= "00111111"; B_out <= "00001111"; elsif (hpixl_counter <= 16) then --purple R_out <= "01111111"; G_out <= "00011111"; B_out <= "11111111"; end if; end if; if (hpixl_counter = HORIZONTAL_MAX) then hpixl_counter := 0; --reset hpixel_counter to 0 end if; if (vpixl_counter = VERTICAL_MAX*HORIZONTAL_MAX) then --reset vpixel_counter to 0 vpixl_counter := 0; end if; end if; end if; end if; end process RGB_Converter_behaviour; --Reset will start the Pixel_Counter Reset_process : process (pixel_clock) is variable counter : integer := 0; begin if (rising_edge(pixel_clock)) then if (RGB_Data_Ready = '1') then if (counter = 0) then reset <= '1'; counter := counter + 1; else reset <= '0'; end if; end if; end if; end process; end architecture behavioral;