VGA Controller - red-bote/VHDL_Demos GitHub Wiki
This demo uses the VGA Controller tutorial from the DigiKey TechForum presented by Scott_1767 DigiKey Employee. Please checkout that tutorial but any questions about the information on this wiki page should be directed to me.
The following files are used:
- VGA Controller: vga_controller.vhd
- Test image generator: hw_image_generator.vhd
The circuit drives 5 signals to the monitor:
- Red
- Green
- Blue
- Vsync
- Hsync
The VGA output port consists of 4-bits for each of red, green and blue color components.
In a new Vivado project the following external ports are defined.
Port Name | Direction | Bus | MSB | LSB |
---|---|---|---|---|
clk | in | |||
reset | in | 0 | ||
sw | in | Checked | 15 | 0 |
Hsync | out | Checked | 15 | 0 |
Vsync | out | Checked | 15 | 0 |
vgaRed | out | Checked | 3 | 0 |
vgaGreen | out | Checked | 3 | 0 |
vgaBlue | out | Checked | 3 | 0 |
In the Basys 3 constraints (.xdc) file the center button btnC is mapped to the top-level reset port and the VGA output port must be enabled:
##Buttons
set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports reset]
#set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports btnC]
#VGA Connector
set_property -dict { PACKAGE_PIN G19 IOSTANDARD LVCMOS33 } [get_ports {vgaRed[0]}]
set_property -dict { PACKAGE_PIN H19 IOSTANDARD LVCMOS33 } [get_ports {vgaRed[1]}]
set_property -dict { PACKAGE_PIN J19 IOSTANDARD LVCMOS33 } [get_ports {vgaRed[2]}]
.
.
.
set_property -dict { PACKAGE_PIN D17 IOSTANDARD LVCMOS33 } [get_ports {vgaGreen[3]}]
set_property -dict { PACKAGE_PIN P19 IOSTANDARD LVCMOS33 } [get_ports Hsync]
set_property -dict { PACKAGE_PIN R19 IOSTANDARD LVCMOS33 } [get_ports Vsync]
The VGA demo is setup to drive a display screen of size 640x480, requiring a pixel clock of just over 25 Mhz. The VGA clock is derived with a counter dividing the 100 Mhz clock by 4.
Clock Divider
Instantiate clock divider from counters_1.vhd. New signals are added for the counter output, VGA clock, inverted reset, and video on.
architecture Behavioral of vga_top is
signal clk_count : std_logic_vector(3 downto 0);
signal clk_vga : std_logic;
signal reset_l : std_logic;
signal video_on : std_logic;
signal RGB : std_logic_vector(23 downto 0);
signal vga_col : integer;
signal vga_row : integer;
begin
u_clkdiv : entity work.counters_1
port map(
C => clk,
CLR => reset,
Q => clk_count
);
clk_vga <= clk_count(1); -- pixel clock set to 25Mhz
VGA Controller
The default timings the VGA controller are for an HDMI screen but is instantiated with generic values set for 640x480 VGA mode. An active low reset_n is generated to match the reset_n input to the controller. The 12-bits of color signals are connected directly to switches allowing the screen to be filled with any combination of 4-bit red green and blue.
reset_l <= not reset;
u_vga_control : entity work.vga_controller
GENERIC map (
h_pulse => 96,
h_bp => 46, -- verify
h_pixels => 640,
h_fp => 16,
h_pol => '0',
v_pulse => 2,
v_bp => 33,
v_pixels => 480,
v_fp => 10,
v_pol => '0')
port map(
pixel_clk => clk_vga, -- 25 Mhz
reset_n => reset_l,
h_sync => Hsync,
v_sync => Vsync,
disp_ena => video_on,
column => vga_col,
row => vga_row,
n_blank => open,
n_sync => open
);
vgaRed <= sw(11 downto 8) when video_on = '1' else (others => '0');
vgaGreen <= sw(7 downto 4) when video_on = '1' else (others => '0');
vgaBlue <= sw(3 downto 0) when video_on = '1' else (others => '0');
pixel_x and pixel_y provide the current location of the raster scan, but are not required for this simple demonstration and may be wired to open.
The video_on signal is active only while the raster scan location is within the viewable area of the display.
Test Image
Import hw_image_generator.vhd.
Instantiate the image generator in the top-level.
-- output of image generator is 24-bit RGB
signal RGB : std_logic_vector(23 downto 0);
-- raster-scan location is used to locate the image on screen
signal vga_col : integer;
signal vga_row : integer;
.
.
.
-- instantiate the image generator block
u_image_gen : entity work.hw_image_generator
generic map(
pixels_y => 240,
pixels_x => 320)
port map(
disp_ena => video_on,
row => vga_row,
column => vga_col,
red => RGB(23 downto 16),
green => RGB(15 downto 8),
blue => RGB(7 downto 0)
);
-- connect upper 4-bits of each color to output ports
vgaRed <= RGB(23 downto 20);
vgaGreen <= RGB(15 downto 12);
vgaBlue <= RGB(7 downto 4);
The image generator was written for a system that used 8-bits for each color. For the Basys 3, the upper 4-bits of each color are connected to the external RGB output ports.
The complete demo project can be found in the VHDL Demos repo.