Project: Using an FPGA to display RGB video, Part 2

In my last blog post, I talked about the process of programming an FPGA so that it would output digital RGB (red, green, blue) video signals to drive my Sony TV. I had successfully synthesized my Verilog code and turned it into a bitstream that I could use to program an iCEstick evaluation board, and now it was time to see if I could make things work in actual hardware. The iCEstick comes with a built-in 6×2 female header with 8 data pins, and also has through hole pads for an additional 16 data pins—more than enough connections for the signals needed to drive the TV. There are also 5 LEDs that can be turned on and off by the FPGA.

In addition to the red, green, and blue signals, there are also horizontal and vertical sync signals that need to be connected. First, a little explanation about how vintage TVs work. CRT TVs draw a picture by sweeping a beam of electrons across the screen. On the screen, there are hundreds of thousands of phosphor spots that light up when they are hit by the electron beam. In a color CRT TV, there are red, green, and blue phosphors (the primary colors of light, which can be combined in different intensities to form any color). The image is “painted” on the screen one line at a time by three separate electron beams (one each for red, green and blue). With the circuit I built there are a total of 240 lines that make up the full screen, or one frame. The electron beams start out aimed at the upper left-hand corner of the screen and are swept to the right to paint the first line of red, green and blue dots (the dots are small enough and so close together that your eye interprets the color combination of three RGB dots as a single spot on the screen). The intensity of each beam is controlled by the separate red, green, and blue (RGB) signals being fed to the TV, and this determines the color of each spot or pixel on the screen. Every time the electron beam reaches the end of a line, it has to be turned off and moved to the beginning of the next line (this is called “horizontal retrace”). The horizontal sync signal tells the TV when to go to the next line.

Raster scan, by Ian Harvey, public domain

Once all 240 lines have been painted on the screen, The electron gun again has to be turned off and moved all the way back to the upper left-hand corner of the screen in preparation to start painting a new frame (this is called “vertical retrace”). The vertical sync signal tells the TV when to go back to the start of the frame, and the TV displays 60 frames per second, which is fast enough that your eyes and brain interpret it as a smoothly moving image. As a sanity check to verify that the FPGA circuit was actually operating, I added some additional Verilog code to blink one of the LEDs provided on the iCEstick. The code consists of a counter that increases by one every time there is a vertical sync. When the counter reaches 30, it toggles the LED. Since there are 60 frames per second, this makes the LED blink on and off once per second. So, if the LED is blinking at the right rate, I know that the vertical sync signal is working properly, a good indication that the FPGA is doing what it’s supposed to do.

With the FPGA programmed and the LED blinking correctly, I hooked everything up to the TV, switched to the RGB input, and…nothing happened! So, now it was time to do some troubleshooting. I’ve always enjoyed debugging electrical circuits; it’s like being a detective and following clues that are revealed by your test equipment to zero in on the culprit (or bug). At this point, I needed some help from an oscilloscope to see what the FPGA was actually doing. An oscilloscope allows you to see a visual representation of how the signals in an electrical circuit are changing with time. I expected to see a series of regular, short pulses for the horizontal sync signal (remember, one pulse every time the TV needs to start scanning a new line), as well as a much slower series of pulses for the vertical sync signal (one pulse every time the TV needs to start scanning a new frame, 60 pulses per second). I also looked at the R, G, and B signals to verify that they were correct. The image below shows the horizontal sync signal, with the blue signal below it.

Okay, this looks good! Notice how the blue signal only pulses in the time between the horizontal sync signals; the red, green and blue signals contain picture information, so they should only be doing something when the TV is not performing a horizontal or vertical retrace. So, why was there no picture? My next step was to make sure I understood how the TV worked and what kind of signals it was expecting. For digital RGB signals, which can either be on or off, many TVs and monitors from the same era as my Sony TV feed the incoming sync signals into some digital logic to combine horizontal and vertical into a single mixed signal called composite sync. This signal is then used internally by the TV to figure out how to draw each frame. When I finally found the circuit diagram for my TV, I immediately had one of those great “aha!” moments where you know (or at least think you know) exactly what the problem is. It turns out that in this particular TV, the horizontal sync (Hsync) and vertical sync (Vsync) signals are fed into an AND gate:

With digital circuitry, signals can either be high (typically positive voltage, in this case around 5 volts), or low (typically ground or 0 volts). When you feed two signals into an AND gate, the output is only high if both signals are high. If either signal is low (or both signals are low), the output is low. And, here’s the big aha: I was using positive sync polarity in my FPGA circuit (see the oscilloscope traces above), which means that each sync signal was normally low and only pulsed high for a short time when it was time for a retrace. So, the vertical sync signal was low the entire time that the TV was supposed to be drawing the frame (remember, vertical sync only pulses when the frame is complete and it is time to move the electron beam back to the top), and this meant that the output of the sync combining AND gate was also low. Effectively, the TV was killing the horizontal sync pulses and therefore couldn’t figure out where to start drawing each line! The built-in circuitry in the TV was smart enough to not even attempt to draw the lines without seeing valid sync signals. Notice in the simulation below that with positive sync polarity, the only time something makes it through the AND gate is during the vertical sync pulse, when a few horizontal sync pulses make it through (these are the only times that both inputs of the AND gate are high).

Luckily, the fix for this was simple: change from positive sync polarity to negative sync polarity. This means that the sync signals are normally high and only pulse low when it is time for a retrace. With this setup, the vertical sync signal is high the entire time the TV is supposed to be drawing the frame, therefore, negative pulses on the horizontal sync signal will still make it through to the output of the AND gate (remember, if only one of the inputs to the AND gate goes low, the output also goes low).

I made the change in my code, hooked everything up again, and…success!

An FPGA-based pattern generator! Note: the extra circuitry attached to the iCEstick consists of a 74LS244 line driver IC (purchased of course from my favorite local parts store) and 5V power supply to boost the output of the iCEstick.

Project: Using an FPGA to display RGB video, Part 1

Lately I’ve been refreshing my Verilog skills—Verilog is a hardware description language (or HDL), which means that the code you write can be synthesized into actual hardware (e.g. logic gates and flip flops). As luck would have it, I stumbled across a great book that allowed me to combine learning Verilog with one of my passions, vintage computer and video game hardware. The book is called Designing Video Game Hardware in Verilog, written by Steven Hugg. In addition to the book, the author created an awesome Verilog IDE (Integrated Development Environment) on the 8bitworkshop website, where you can explore sample code, as well as write your own code. Not only does this IDE include a waveform viewer so you can see the signals your code is driving, it also includes a virtual TV screen, allowing you to write code that creates digital RGB signals and to immediately see what the results would look like if you connected your hardware to an RGB TV or monitor.

As soon as I saw this book, I thought about making something that would drive my vintage Sony TV—I wrote about building an RGB cable for this TV in a previous post. One way to actually implement what you’ve written in Verilog is to synthesize your code and download it into a field-programmable gate array, or FPGA chip. The book suggests using an iCEstick evaluation board, which is based on a Lattice FPGA. One nice thing about this board is that it comes with an onboard USB interface, so it will plug directly into your computer for programming without any additional hardware. Another great thing about this board is that there is an open source toolchain (IceStorm) available to program the FPGA using Verilog, which means it’s totally free to use the tools!

The first thing to do was download the tools and make sure I could install and use them. Thankfully, there are scripts that will automatically complete the installation on OSX (using Homebrew), and I was able to get through this with only a few easily resolved hiccups. Next, I tried using the tools to go through the complete Verilog to FPGA flow. There are four tools needed to go from Verilog to a programmed FPGA:

  • yosys takes your Verilog code and synthesizes it into an actual logic circuit
  • arachne-pnr takes the circuit from yosys and, with knowledge of the specific FPGA you are using, does place and route (determining how to map the logic circuit to the resources available on the FPGA)
  • icepack takes the output of arachne-pnr and converts it to a bitstream, which can be directly downloaded into the FPGA in order to configure it with your circuit
  • iceprog uses the USB port to send the bitstream to the FPGA, programming it

For my first design, I decided to implement a simple SMPTE color bar pattern generator. This would allow me to see all 8 colors possible with 3-bit digital RGB, which is what the examples in the book use. Thanks to the 8bitworkshop IDE, I was immediately able to see the TV output of my code:

Whoops! I swapped the position of the red and blue bits, so the colors aren’t in the correct order. The beauty of using Verilog to define hardware is that a change is as simple as editing your code. A quick fix and everything was working correctly. I ran the IceStorm toolchain and everything seemed to go okay, so I was ready to order the iCEstick evaluation board. In my next post I’ll talk about my experience with using this board to try to get a picture on the TV!