0
0
VhdlHow-ToBeginner · 4 min read

VHDL Code for VGA Controller: Syntax, Example, and Tips

A VGA controller in VHDL manages timing signals like hsync and vsync to display images on a VGA monitor. It uses counters to generate pixel coordinates and sync pulses according to VGA standards. The controller outputs RGB signals and sync signals to drive the display.
📐

Syntax

A basic VGA controller in VHDL uses counters for horizontal and vertical pixel positions, and generates hsync and vsync signals based on timing parameters. It outputs RGB color signals and sync pulses.

  • clk: input clock signal (usually 25 MHz for 640x480 VGA)
  • hsync: horizontal sync output
  • vsync: vertical sync output
  • rgb: color output (usually 3 bits for R, G, B)
  • h_count, v_count: counters for pixel position
vhdl
entity VGA_Controller is
    Port (
        clk    : in  std_logic;
        hsync  : out std_logic;
        vsync  : out std_logic;
        rgb    : out std_logic_vector(2 downto 0)
    );
end VGA_Controller;

architecture Behavioral of VGA_Controller is
    -- Timing constants for 640x480 @ 60Hz VGA
    constant H_DISPLAY    : integer := 640;
    constant H_FRONT_PORCH: integer := 16;
    constant H_SYNC_PULSE : integer := 96;
    constant H_BACK_PORCH : integer := 48;
    constant H_TOTAL      : integer := H_DISPLAY + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH;

    constant V_DISPLAY    : integer := 480;
    constant V_FRONT_PORCH: integer := 10;
    constant V_SYNC_PULSE : integer := 2;
    constant V_BACK_PORCH : integer := 33;
    constant V_TOTAL      : integer := V_DISPLAY + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH;

    signal h_count : integer range 0 to H_TOTAL - 1 := 0;
    signal v_count : integer range 0 to V_TOTAL - 1 := 0;

begin
    -- Process to generate horizontal and vertical counters
    process(clk)
    begin
        if rising_edge(clk) then
            if h_count = H_TOTAL - 1 then
                h_count <= 0;
                if v_count = V_TOTAL - 1 then
                    v_count <= 0;
                else
                    v_count <= v_count + 1;
                end if;
            else
                h_count <= h_count + 1;
            end if;
        end if;
    end process;

    -- Generate hsync pulse (active low)
    hsync <= '0' when (h_count >= H_DISPLAY + H_FRONT_PORCH and h_count < H_DISPLAY + H_FRONT_PORCH + H_SYNC_PULSE) else '1';

    -- Generate vsync pulse (active low)
    vsync <= '0' when (v_count >= V_DISPLAY + V_FRONT_PORCH and v_count < V_DISPLAY + V_FRONT_PORCH + V_SYNC_PULSE) else '1';

    -- Generate RGB output (white color inside visible area, black outside)
    rgb <= "111" when (h_count < H_DISPLAY and v_count < V_DISPLAY) else "000";

end Behavioral;
Output
Outputs hsync and vsync pulses with RGB signals for 640x480 VGA timing; drives VGA monitor sync and color signals.
💻

Example

This example shows a simple VGA controller generating sync signals and white pixels on the visible screen area. It uses a 25 MHz clock for standard 640x480 VGA timing.

vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity VGA_Controller is
    Port (
        clk    : in  std_logic;
        hsync  : out std_logic;
        vsync  : out std_logic;
        rgb    : out std_logic_vector(2 downto 0)
    );
end VGA_Controller;

architecture Behavioral of VGA_Controller is
    constant H_DISPLAY    : integer := 640;
    constant H_FRONT_PORCH: integer := 16;
    constant H_SYNC_PULSE : integer := 96;
    constant H_BACK_PORCH : integer := 48;
    constant H_TOTAL      : integer := H_DISPLAY + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH;

    constant V_DISPLAY    : integer := 480;
    constant V_FRONT_PORCH: integer := 10;
    constant V_SYNC_PULSE : integer := 2;
    constant V_BACK_PORCH : integer := 33;
    constant V_TOTAL      : integer := V_DISPLAY + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH;

    signal h_count : integer range 0 to H_TOTAL - 1 := 0;
    signal v_count : integer range 0 to V_TOTAL - 1 := 0;

begin
    process(clk)
    begin
        if rising_edge(clk) then
            if h_count = H_TOTAL - 1 then
                h_count <= 0;
                if v_count = V_TOTAL - 1 then
                    v_count <= 0;
                else
                    v_count <= v_count + 1;
                end if;
            else
                h_count <= h_count + 1;
            end if;
        end if;
    end process;

    hsync <= '0' when (h_count >= H_DISPLAY + H_FRONT_PORCH and h_count < H_DISPLAY + H_FRONT_PORCH + H_SYNC_PULSE) else '1';
    vsync <= '0' when (v_count >= V_DISPLAY + V_FRONT_PORCH and v_count < V_DISPLAY + V_FRONT_PORCH + V_SYNC_PULSE) else '1';

    rgb <= "111" when (h_count < H_DISPLAY and v_count < V_DISPLAY) else "000";

end Behavioral;
Output
Generates VGA sync signals and white pixels on visible area for 640x480 display.
⚠️

Common Pitfalls

Common mistakes when writing a VGA controller in VHDL include:

  • Using incorrect timing constants that do not match the VGA standard, causing no or distorted image.
  • Not resetting counters properly, leading to sync signals that never toggle.
  • Forgetting that hsync and vsync are usually active low signals.
  • Driving RGB signals outside the visible area, which can cause flickering or noise.

Always verify timing values and test with a VGA monitor or simulator.

vhdl
wrong_hsync <= '1' when (h_count >= H_DISPLAY and h_count < H_DISPLAY + H_SYNC_PULSE) else '0'; -- Incorrect polarity

-- Correct way:
hsync <= '0' when (h_count >= H_DISPLAY + H_FRONT_PORCH and h_count < H_DISPLAY + H_FRONT_PORCH + H_SYNC_PULSE) else '1';
📊

Quick Reference

Key timing parameters for 640x480 @ 60Hz VGA:

ParameterValue (pixels/lines)
Horizontal Display640
Horizontal Front Porch16
Horizontal Sync Pulse96
Horizontal Back Porch48
Horizontal Total800
Vertical Display480
Vertical Front Porch10
Vertical Sync Pulse2
Vertical Back Porch33
Vertical Total525

Key Takeaways

Use correct VGA timing constants for horizontal and vertical sync signals.
Generate hsync and vsync pulses as active low signals based on counters.
Reset horizontal counter at end of line and vertical counter at end of frame.
Output RGB signals only during visible pixel area to avoid noise.
Test your VGA controller with a real monitor or simulation for correct timing.