Editor's Note: I was recently perusing a new book called
Design Recipes for FPGAs that was written by Peter Wilson and published by Newnes (ISBN-13: 978-0750668453).
This is a rather interesting "Cook Book" jam-packed with "Design Recipes". Part 1 provides primers for FPGAs, VHDL, and standard design flows. Part 2 features some example applications that encompass many of the key design problems facing designers today; these examples are worked through from start to finish in a practical way. Part 3 presents a "Designer's Toolbox" of tricks and techniques; Part 4 covers optimizing designs; and Part 5 investigates fundamental issues with regard to implementing specific functions in VHDL.
The article presented here is abstracted from Chapter 13 - A Simple VGA Interface from the "Designer's Toolbox" in Part 3. It is reproduced here with the kind permission of the publisher. At the end of the article we present the full list of contents for the book along with a special code that will allow you to get a 20% discount from the publisher's website.
The Video Graphics Array (VGA) interface is common to most modern computer displays and is based on a pixel map, color planes and horizontal and vertical sync signals. A VGA monitor has three color signals (red, green and blue) that set one of these colors on or off on the screen. The intensity of each of those colors sets the final color seen on the display. For example, if the red was fully on, but the blue and green off, then the color would be seen as a strong red. Each analog intensity is defined by a two bit digital word for each color (e.g. redO and red l) that are connected to a simple digital to analog converter to obtain the correct output signal.
The resolution of the screen can vary from 480 × 320 up to much larger screens, but a standard default size is 640 – 480 pixels. This is 480 lines of 640 pixels in each line, so the aspect ratio is 640/480 leading to the classic landscape layout of a conventional monitor screen.
The VGA image is controlled by two signals – horizontal sync and vertical sync. The horizontal sync marks the start and finish of a line of pixels with a negative pulse in each case. The actual image data is sent in a 25.17 µs window in a 31.77 µs space between the sync pulses. (The time that image data is not sent is where the image is defined as a blank space and the image is dark.) The vertical sync is similar to the horizontal sync except that, in this case, the negative pulse marks the start and finish of each frame as a whole and the time for the frame (image as a whole) takes place in a 15.25 ms window in the space between pulses, which is
There are some constraints with regard to the spacing of the data between pulses that will be considered later in this chapter, but it is clear that the key to a correct VGA output is the accurate definition of timing and data by the VHDL.
Basic pixel timing
If there is a space of 25.17 µs to handle all of the required pixels, then some basic calculations needs to be carried out to make sure that the Field Programmable Gate Array (FPGA) can display the correct data in the time available. For example, if we have a 640 ×
480 VGA system, then that means that 640 pixels must be sent to the monitor in 25.17 µs. A simple calculation shows that for each pixel we need 25.17 µs/640 = 39.328 ns per pixel. If our clock frequency is 100 MHz on the FPGA, then that gives a minimum clock period of 10 ns, which can be achieved using a relatively standard FPGA.
Clearly it is not sensible to use an integrated image system on the FPGA, but rather it makes much more sense to store the image in memory (Random Access Memory (RAM)) and retrieve it frame by frame. Therefore, as well as the basic VGA interface it makes a lot of sense for the images to be moved around in memory and therefore using the same basic RAM interface as defined previously is sensible. Thus, as well as the VGA interface pins, our VGA handler should include a RAM interface.
VGA interface VHDL
The first stage in defining the VHDL for the VGA driver is to create a VHDL entity that has the global clock and reset, the VGA output pins, and a memory interface. The outline VHDL entity is given below:
The architecture contains a number of processes, with internal signals that manage the transfer of pixel data from memory to the screen. As can be seen from the entity, the data comes back from the memory in 8 bit blocks and we require 3 × 2 bits for each pixel and so when the data is returned, each memory byte will contain the data for a single pixel. In this example, as we are using a 640 × 480 pixel image, this will therefore require a memory that is 307,200 bytes in size as a minimum. To put this in perspective, this means that using a raw memory approach we can put three frames per megabyte. In practice, of course, we would use a form of image compression (such as JPEG for photographic images), but this is beyond the scope of this book.
We can therefore use a simple process to obtain the current pixel of data from memory as follows:
This process returns the current value of the pixel data into a signal called pixel_data, which is declared at the architecture level:
This has the red, green and blue data defined in lowest 6 bits of the 8 bit data word with the indexes, respectively, of 0–1, 2–3, 4–5.