Fpga Vga Driver For Mac
Learning how to directly drive a VGA monitor with an FPGA opens up a window for many potential projects: video games, image processing, a terminal window for a custom processor, and many more. To get started, we will need to learn how to drive the necessary signals to display things on a VGA monitor.
We will then use a test circuit to display some colors on the screen. In future posts I will detail how to design pixel generating circuits for displaying custom graphics and animations. More on that soon! Computer monitors used to be bulky cathode ray tube (CRT) devices. VGA technology was developed with driving the physical CRT in mind, so knowing how that device works can be instructive in understanding why VGA signals are driven the way they are. That being said, computer monitors nowadays are LCD monitors without a CRT, yet the VGA interfaces for these monitors still use the same signals to display images on their screens. Instead of going into the details of CRTs in this post, we will instead inspect the necessary signals for a VGA monitor and their timing diagrams, and implement a synchronization circuit in Verilog HDL.
Keep in mind that different FPGA development boards have different color depth capabilities. I will focus here on using the Basys 2 which has 8-bit color and the Basys 3 which has 12-bit color. While I am covering the Basys 2 here, in the future I will focus on and use the more capable Basys 3 for my VGA projects. Each pixel on the monitor has a red, green, and blue color component. The red, green, and blue color signals from the VGA port to the monitor are analog and are generated by resistor ladder DACs on the FPGA board that receive input from dedicated FPGA IO lines.
Fpga Sata

The Basys 2 board used eight IO lines to drive the color signals, and therefore uses an 8-bit color scheme, with 3 bits determining red and green color intensities, and 2 bits determining the blue color intensity. The Basys 3 has 12 IO lines to drive color signals, with 4 bits driving each respective RGB color intensity. The VGA ports on both boards use two synchronization signals, one called hsync (horizontal sync) to specify the time taken to scan through a row of pixels, and the other called vsync (vertical sync) to specify the time taken to scan through an entire screen of pixel rows. Properly driving the hysnc and vsync signals will be our main focus. Once the VGA synchronization circuit is designed and tested, we can in the future abstract away the details and just use it as a ready made module for our VGA projects. Now we will begin to talk about resolution and pixels.
Keep in mind that the display area on the screen using VGA has a resolution of 640 by 480 pixels. The origin of the display area is (0,0) and is located in the upper left corner. The x dimension increases from left to right, while y increases from top to bottom. We will run our VGA circuit at a 25 MHz pixel rate, meaning that 25 million pixels will be scanned each second.


The monitors usually include small black borders surrounding the display area. We will divide each horizontal scan row into 800 pixels, starting at pixel 0 and ending at pixel 799. We will scan through each horizontal row of pixels at 25 MHz. The pixel count begins at the start of the display area, and runs through all 640 display pixels, followed by a 16 pixel right border. Next is a 96 “pixel” retrace, which is a delay artifact of CRT monitors that we must include, and finally a 48 pixel left border. We will divide the vertical space into 525 horizontal rows, with the scanning through of all rows counting as one refresh of the screen.
The vertical pixel count starts in the display area and ends at pixel 479, continues into a 10 pixel bottom border, then a 2 pixel retrace, and finally ends after a 33 pixel top border. The pixels in the border and retrace areas should be black, so we will generate a videoon signal that is asserted when the current pixel is in the horizontal and vertical display region. This signal will turn on our RGB color signals for the display pixels only. To avoid noticeable flickering from the screen, a goal of a 60 Hz refresh rate is generally acceptable. If the VGA circuit is clocked at 25 MHz, then each pixel scan will have a period of 1/25 Mhz = 40 ns. If we multiply that by 800 pixels per row, and 525 rows per screen, we get around 1/60 seconds per screen refresh, which meets our goal.
Let’s take a look at the code for the Basys 2 Verilog HDL implementation. Module vgatest ( input wire clk, reset, input wire 7: 0 sw, output wire hsync, vsync, output wire 7: 0 rgb ); // register for Basys 2 8-bit RGB DAC reg 7: 0 rgbreg; // video status output from vgasync to tell when to route out rgb signal to DAC wire videoon; // instantiate vgasync vgasync vgasyncunit (.clk(clk),.reset(reset),.hsync(hsync),.vsync(vsync),.videoon(videoon),.ptick,.x,.y); // rgb buffer always @( posedge clk, posedge reset) if (reset) rgbreg. Module vgatest ( input wire clk, reset, input wire 11: 0 sw, output wire hsync, vsync, output wire 11: 0 rgb ); // register for Basys 2 8-bit RGB DAC reg 11: 0 rgbreg; // video status output from vgasync to tell when to route out rgb signal to DAC wire videoon; // instantiate vgasync vgasync vgasyncunit (.clk(clk),.reset(reset),.hsync(hsync),.vsync(vsync),.videoon(videoon),.ptick,.x,.y); // rgb buffer always @( posedge clk, posedge reset) if (reset) rgbreg. Above is a video demonstrating some colors on my VGA monitor using the Basys 3.
Remember that the Basys 2 has 8-bit color, meaning that there are 2 8 = 256 possible colors that can be displayed, while the Basys 3 has 12-bit color, with 2 12 = 4096 possible colors. You don’t have to use all of the color bits that a given FPGA board supplies you, and if you wish you can hold some bits constant and reduce the memory requirements for an image at the cost of reduced color depth. In my next post we will consider how to store image data in an FPGA’s Block RAM, and design a pixel generation circuit that will move a video game sprite around on the screen:).
To see a complete FPGA video game project using VGA and block RAM to store sprites,.