show menu

Connected users can download this tutorial in pdf

Create a VGA controller for the ZedBoard

Posted by Florent - 20 July 2017


In this tutorial we will create a VGA controller to display an image on a monitor using the ZedBoard and Xilinx Vivado 2017.2 (but it should work with any other release of Xilinx Vivado). The controller will be coded using VHDL.

Download the VHDL files for the project (zip file): here

Introduction to video display

What is an image?

An image is an array of pixel (for picture (x) elements). For a Black and white image, a pixel is defined by one value representing the luminosity. If this value is high, the pixel will be bright (white) and if it is low, the pixel will be dark (black). For a colour image, in most cases the pixel is composed of three values: its level of Red, its level of Green and its level of Blue (this is why we usually call colour images RGB images (for Red Green and Blue)). The combination of these 3 values will give the final colour of the pixel. For example, in a lot a software tools, you can create customs colours by setting the value of Red, Green and Blue. As shown in the Figure 1, if you select the maximum value for Green and Blue (255 in this case) and 0 for Red, you obtain the colour cyan.

Example of custom colour definition tool

Figure 1 - Example of custom colour definition tool

To display an image on a monitor, the image is sent line per line, starting with the top one and each line is sent pixel per pixel, starting with the left one.

For example, the Figure 2 shows how a 3x3 pixels image could be sent to a monitor using 3 data lanes (Red Green Blue).

Example of how an	image is sent to a monitor

Figure 2 - Example of how an image is sent to a monitor

Introduction to VGA on the ZedBoard

A colour VGA video signal is composed by 5 different signals: two synchronization signals (HSYNC and VSYNC) and three analog colour signals (R, G, B).

A video frame (one single image of a video) comprises active video and blanking periods (no data sent). The vertical (VSYNC) and horizontal (HSYNC) synchronization signals describe the video frame timing.

Example Video Frame and Synchronization Signals

Figure 3 - Example Video Frame and Synchronization Signals

The Figure 3 shows an example of a video frame along with the synchronization signals. During the Active Video period, the data are sent to the monitors. During the Horizontal and Vertical blanking, no data are sent and after a defined period (which depends on the output video format) synchronisation pulses (HSYNC and VSYNC) are sent to the monitor. These pulses can be positives or negatives (depending on the output video format). The periods before a synchronisation signal and after a synchronisation signal are called respectively Front Porch and Back Porch.

VGA connector schematic on the ZedBoard

Figure 4 - VGA connector schematic on the ZedBoard

In VGA, the colour data are voltage value between +0V and +3.3V. On the ZedBoard, these values are sent using a 4-bit input Digital to Analog converter as shown on the Figure 4.

VGA Connector on the ZedBoard

Figure 5 - VGA Connector on the ZedBoard

The Figure 5 shows how the signals are connected to the VGA connector of the ZedBoard. From the ZedBoard user guide ( 2_v2_2.pdf ) we can see that the red signal is connected to the ports V20, U20, V19 and V18 of the FPGA, the green signal is connected to AB22, AA22, AB21 and AA21, the blue signal is connected to Y21, Y20, AB20 and AB19, the HSYNC is connected to AA19 and VSYNC is connected to Y19.

Timing information (1680 x 1050 @60Hz)

For this tutorial, we will output a VGA signal with the output format 1680 x 1050 @60Hz. In this format the pixel are send with a 147.14 MHz frequency.

Horizontal timing

With the output format 1680 x 1050@60Hz, the size of the active line is 1680 pixels, the horizontal synchronisation signal, which is negative, is sent after 104 clock signals in the blanking period, and last 184 clock signals and there are 288 clock signals between the horizontal synchronisation signal and a new active line. The Table 1 summarise the horizontal timing.

Line Part

Clock Signals

Time [µs]

Visible area



Front porch



Sync pulse



Back porch



Whole line



 Table 1 - 1680 x 1050 @ 60 Hz Horizontal timing

Vertical Timing

With the output format 1680 x 1050@60Hz, the size of the active frame is 1050 lines, the vertical synchronisation signal, which is positive, is sent after a period corresponding to 1 line signals in the blanking period, and last for a period of 3 lines. This synchronisation signals is followed by a period corresponding to 33 lines before a new active frame. The Table 2 summarise the vertical timing.

Frame Part


Time [ms]

Visible area



Front porch



Sync pulse



Back porch



Whole frame



Table 2 - 1680 x 1050 @ 60 Hz Vertical timing

Clocking on the ZedBoard

According to the ZedBoard Hardware User’s Guide: “An on-board 100 MHz oscillator, IC17, Fox 767-100-136, supplies the PL subsystem clock input on bank 13, pin Y9”. As we need a 147.14 MHz frequency clock we will use the clocking wizard to generate the needed clock using an MMCM.

Create the timing controller

Open Vivado 2017.2 and create a new RTL project targeting the ZedBoard.

Firstly, we have a 100MHz clock in input but we need to convert it to a 147.14MHz (pixel clock). To do this, we will use the Xilinx IP Clocking Wizard. In the flow navigator, click on “IP Catalog”. In the search bar, enter “clocking” and then double click on the “Clocking Wizard” IP to add it to the project.

Vivado 2017.2 - Add a Clocking Wizard IP to the project

Figure 6 - Add a Clocking Wizard IP to the project

A GUI window should appear to customize the IP. The component name for this IP should be clk_wiz_0. In the page “Clocking Option”, check that the Primary Input clock frequency is set to 100MHz.

Vivado 2017.2 - Clocking Wizard GUI - Clocking Options

Figure 7 - Clocking Wizard GUI - Clocking Options

In the “Output Clocks” page, set 147.14MHz for the requested frequency for clk_out1 and disable “reset” and “locked” in the “Enable Optional Inputs / Outputs for MMCP/PLL” and then click OK.

Vivado 2017.2 -  Clocking Wizard GUI - Output Clocks

Figure 8 - Clocking Wizard GUI - Output Clocks

A “Generate Outputs Products” window should appear. Select “Out of context per IP” and click “Generate”.

Vivado 2017.2 - Generate Outputs Products Window

Figure 9 - Generate Outputs Products Window

Add the VDHL files hdl/TOP_LEVEL, hdl/VGA_timing_controller.vhd and hdl/reset_synchronizer.vhd to the project. You should see the hierarchy showed in the Figure 10 in the Sources window.

Vivado 2017.2 - Project Hierarchy

Figure 10 - Project Hierarchy

The file reset_synchronizer.vhd contains a simple reset synchronizer, the file VGA_timing_controller.vhd contains a code used to generate the horizontal and vertical pulses and a signal which indicates when the timing is in the “Active Video” part. The file TOP_LEVEL outputs values for the signals R, G and B when the video is active.

Try the project on board

Add the constraint file constr/phys_const.xdc to the project and generate the Bitstream.

When the Bitstream has been generated, open Hardware Manger in Vivado and program the FPGA. Connect the ZedBoard to a monitor. Make sure that the SW0 (used as reset) is on position ‘0’. You should see a green screen on the monitor. If this is not working, try the Bitstream from the downloaded folder.

Green screen displayed on the monitor

Figure 11 - Green screen displayed on the monitor