How to generate a VGA signal with a FPGA

Update 2015/03/08:
Added DE1 board files and a small bug fix. Fixed the repo link below to point to the right revision.

During my efforts to learn more about fpga’s I found a nice tutorial about VGA in VHDL on the DE1 board on youtube.
I was surprised how easy it is to do it when you got it explained 🙂

In short, you draw the pixel line by line on the screen and every line contains an active video phase in which the rgb pixels are sent and a blanking region which is divided into the front porch, sync pulse and back porch (see image below).

vga line

vga line

In the youtube tutorial its told that it starts with the blanking region followed by the active video phase. Probably it doesn’t matter but I did it in the same way (please comment if you know whats right and if it makes any difference).
It turned out that by starting with the visible area first the bending which was visible on the horizontal line is gone. I’ve updated the code accordingly.
The pixel clock and the pixel count of front porch, sync pulse, back porch and the active video phase is defined and can be seen here:
http://www-mtl.mit.edu/Courses/6.111/labkit/vga.shtml
http://tinyvga.com/vga-timing

I chose the resolution 640×480 with a pixel clock of 25.175 MHz. Let’s have a look at the code:

Our vga entity will get the pixel clock as input and outputs the horizontal and vertical sync pulse together with the rgb values (6 Bit for the MiST).
Below architecture are some constants which match the given values of our resolution. HPOS and VPOS are the horizontal and vertical counters which end positions are the sums of the above values.

With the pixel clock we change our counters. As long as HPOS is below 800 we increase it by one. If its higher we’re in the next line and set HPOS back to zero (begin of the next line). Then we check if VPOS is below 524 and if yes increase it by one and if not set it to zero (begin of the next frame).

From the figure above we see that HSYNC is only zero during the sync pulse. The same is valid for VSYNC. And thats exactly what the code above does.

The code above sets our pixels. The first section sets the rgb values to zero when we aren’t in the active video phase. Then the background is set to blue and “overdrawn” by white when the HPOS and VPOS matches certain values which will show a horizontal (HPOS) and a vertical (VPOS) white stripe in the middle of the screen.

The full source code of this example together with the Quartus project files for the MiST can be found here:
https://github.com/wsoltys/mist-cores/tree/77fea2dc1e3986daa9138dbb2fa91fd8267c3c9e/misc/vga

6 thoughts on “How to generate a VGA signal with a FPGA

  1. This could be VERY useful to test VGA handling of screens outside of cores, especially if you can make some of it configurable by OSD.

    Could you make it print a grid pattern (like alternating black and white pixels)?
    That should make any scaling issues obvious.

    • Newsdee says:

      I played around with the code, here’s a few fun patterns:
      — A nice 8×8 grid: if (HPOS mod 8 = 0) or (VPOS mod 8 = 0) then
      — Vertical lines: if (HPOS mod 2 = 0) then
      — Strange pattern: if (HPOS mod 2 = VPOS mod 2) then

  2. Newsdee says:

    FYI, I get these values on my RGB-Mini: 720x470p, V:59.82hz, CLK: 53.99 Mhz. I don’t get why the pixel clock is coming faster than the rate you feed to it? Also with direct VGA feed, my NTSC TV shows a yellow line (not a white line) and some kind of gradient on the blue. Very strange but could help debug issues with MiST cores.

    • WiSo says:

      Thanks for the interest. I’ll probably update it a little more when I get some time.
      On my Samsung VGA display it looks like it should (beside the small bend on the right of the horizontal line). I still need to figure out what’s wrong with it.
      I get the following values: 31.3kHz, 60Hz,PP,640×480

Leave a Reply to Newsdee Cancel reply

Your email address will not be published. Required fields are marked *