Basic VGA on an FPGA

I’ve been wanting to get into FPGAs for awhile. The fact that they are in a sense a very powerful carte blanche  for hardware projects is very tantalizing. A major motivation was the desire to understand video signal generation and to be able to do my own VGA projects. I was even thinking doing a scanline doubler for my Apple IIgs (with no RGB monitor) would be a great project.

To get started with FPGAs, I spent a bit of time looking into FPGA options. I really didn’t want to spend too much money but be able to do some reasonably sized. I settled on an older Altera EP2C5T144 clone. I downloaded it, learned a little Verilog and played with PCM blinking LEDs. I will spare you the details of getting the JTAG programmer to work with Ubuntu Linux (jtag needs to run as root). The Altera tools are a little complicated and clunky and compiling is quite slow on my 8 year old Linux box, but it works.

To take it to the next level, I knew I’d have to build some hardware to interface with a VGA port. I thought about it a bunch, designed a perfect R-2R resistor ladder that would take 3.3v in and have .7v nominal voltage when under a 75 ohm VGA spec load.  It seems like you should use opamp buffers or something, but I haven’t really searched hard for what the right chip for that would be. I also looked into DVI driver chips because the EP2CT5144 does not have the high speed differential outputs that I would need to reliably generate DVI. I actually picked up a few and I think when I do a real project, I’ll make a board that supports DVI and VGA for maximum awesome.  I thought about etching my own R-2R board that interfaces with my fpga, and I think that would be a good approach in the future.

Of course like most well-laid out hardware project plans I didn’t have time to do anything on this for a long time. I’ve been trying to cut down my internet “research” (watching other people do their own projects), but youtube is addictive.  Interestingly the reason I started this project was that my son has an obsession with helicopters that I thought would be well served by getting my dead battery containing Syma helicopter working. So, I figured that while I had my soldering iron out to fix the helicopter I should at least build the hardware for the VGA.

Since I had limited time, I decided to solder the minimum possible VGA board. The main question is what resistor to use for the RGB signals. I want a load 75 ohm to achieve about .7 volts so I have
 i_1 = i_2  \Rightarrow .7/75 = (3.3-0.7)/x \Rightarrow x=278\Omega \approx 270\Omega.
Given that we have this schematic:

That should give us about 8 colors. I’ll solder the leads and feed into a breadboard to put our resistors on. Then, we’ll connect to the EP2CT5144 dev board’s male jacks using a male to female ribbon connector.  (aside: The connectors and wires to use is always a part of electronics that I seem to do badly. In fact, I’d really like to know where I can find ribbon cable connector supplies, or if there is a good tutorial on what kind of connector stuff to use when). The finish product turned out crappy but workable as shown here:


Of course I couldn’t really keep myself to working only the hardware at that point. I had been reading fpga4fun’s intro to VGA, and I had gotten that working to the point where it simulated ok. After hooking this up and reassigning the pins I thought it would just work. Of course it didn’t really work, and after a bunch of debugging, I found that I had swapped the hsync and vsync lines. So I fixed that, and it worked. Then I got to trying to draw a test pattern. I wasn’t really happy white the white level or the accuracy of the pixel placement (my LCD’s auto centering was totally flaking out), so I thought I’d have to play a little less fast and loose with the blanking portion.

I then wanted to be more precise about pixel locations and properly doing the front and back porch. I read the wikipedia page on VGA and I found that it would be smarter to do everything in terms of the pixel clock over the standard number of pixels. Then I played with it a bunch, and I really wasn’t super happy with the implementation. I wanted to try to do a better job of staying in spec, whereas fpga4fun plays really fast and loose, I only wanted to play kinda fast and loose. I modified the verilog implementation to do everything in terms of virtual pixel clock pixels.

Param Horizontal Vertical
Pixel clock 25.175MHz
Pixels 800 525
Sync range (in pixels) [16,112) [10,12)
Image range (in pixels) [160,800) [45,525)
Sync Frequency 25e6/800 = 31.25 kHz 25e6/800/525 = 59.52 Hz

Ideally this should be implementable with two counters and a state machine.  You could up the counters until they get to threshold for a given state and then transition. For now, I just went simpler and use 4 counters, two for the raw pixels and two for the visible pixels.  I am using all kinds of inefficient logic that probably creates adders to do comparisons, so I should try to optimize the number of gates down at some point. FPGAs really make it to waste lots of hardware, but that really is no different than writing in an inefficient scripting language on the software end. On the software side, I know better, I’m a newbie at hardware, so I’m sure I’m doing a lot wrong.

One big deal is this is the first project I’ve been working on using an oscilloscope. Debugging this with the oscilloscope was so much easier (and more fun), and I’m glad I waited to attempt this project until I got one.

pixelDataAndHsync signalGenerationHsyncVsync

Once the signals looked perfect and awesome, I decided to make sure I actually can see the full width of the screen, so I drew a box on the outer edge and I drew some colored boxes. I was having trouble with getting a proper full screen view on my LCD before my rewrite. Now it worked perfectly. Another improvement  that occurred from this rewrite was that the brightness of the whites improved (I had a very dim grey before).

While I was this far and it was only 1am, I decided to make another module that handles bouncing a ball. This was pretty easy, but I needed to make sure to denote my registers for pixel location as signed, so the twos complement addition for the velocity to position update. The final result showing the results is here:


You probably want to checkout the youtube of this in action