VGA Synchronization Driver for FPGA


In order to use the VGA connection on an FPGA there needs to be a vga timer that can change the pixels as it goes across the screen. I won’t go into detail here about VGA standards, or how the horizontal and vertical refreshes work, but rather just give some example VHDL code that will refresh a screen that is 640 X 480 pixels in size. This can then be declared as an entity in other VHDL code that can generate blocks and other movements on the screen.


Port Name Direction Width Purpose
clk Input 1 Input clock (50 MHz)
rst Input 1 Asynchronous reset
HS Output 1 Low asserted horizontal sync VGA signal
VS Output 1 Low asserted vertical sync VGA signal
pixel_x Output 10 Indicates the column of the current VGA pixel
pixel_y Output 10 Indicates the row of the current VGA pixel
last_column Output 1 Indicates that the current pixel_x correspond to the last visible column
last_row Output 1 Indicates that the current pixel_y corresponds to the last visible row
blank Output 1 Indicates that the current pixel is part of a horizontal or vertical retrace and that the output color must be blanked. The VGA pixel must be set to “Black” during blanking.

Screen Shot 2013-12-24 at 10.56.10 PM


library IEEE;

-- arithmetic functions with Signed or Unsigned values

entity vga_timing is
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC;
           HS : out  STD_LOGIC;
           VS : out  STD_LOGIC;
           pixel_x : out  STD_LOGIC_VECTOR (9 downto 0);
           pixel_y : out  STD_LOGIC_VECTOR (9 downto 0);
           last_column : out  STD_LOGIC;
           last_row : out  STD_LOGIC;
           blank : out  STD_LOGIC);
end vga_timing;

architecture vga_timer of vga_timing is

signal pixel_en, row_en, visible, column_intermed: STD_LOGIC;
signal horiz_counter, vertical_counter, nexthcount, nextvcount : unsigned (9 downto 0) := (others=>'0');


--toggle register for pixel en, giving 25MHz clk
if (rst = '1') then 
pixel_en <= '0';
elsif (clk'event and clk = '1') then
pixel_en <= not pixel_en;
end if;
end process;

--horizontal pixel counter register based off of pixel_en
if (rst = '1') then
horiz_counter <= (others => '0');
elsif (clk'event and clk = '1') then
        if (pixel_en = '1') then
        horiz_counter <= nexthcount;
        end if;
end if;
end process;

nexthcount <= (horiz_counter + 1) when (horiz_counter < 799) else
                                        (others => '0');
pixel_x <= std_logic_vector(horiz_counter);
column_intermed <= '1' when (horiz_counter = 639)
                                        else '0';
row_en <= '1' when (horiz_counter = 799) else 
last_column <= column_intermed;
HS <= '0' when ((horiz_counter > 655) and (horiz_counter < 752))
                else '1';
--vertical pixel counter increments only with last_column
if (rst = '1') then
vertical_counter <= (others => '0');

Comments are closed.