A Poem by FPGA

This article is about using an Altera FPGA board to generate images on a VGA monitor.

There are many different engineering or experimental FPGA boards that you can get. Each FPGA vendor has a lineup of their own and they can be quite pricey. I purchased mine on eBay from a Chinese seller. They made a board with a plethora of peripherals. Documentation was not great; many things were written in Chinese. I had to copy & paste to Google Translate to get some of the details out of it. However, the price was right!

This is a board that I got. It is marked as “RedCore”:

FPGA board with Altera Cyclone II on it
FPGA board with Altera Cyclone II on it

After a little bit of experimentation and cramming to learn some Verilog, I set about creating a simple project of having it display some text on a VGA monitor.

The overall design was done in Altera Quartus II software. The top-level code was made through a block diagram (schematic). Several blocks were imported from the rich Quartus software support library. Finally, two critical modules that actually bind those pieces into a cohesive implementation were custom-written in Verilog.

Here is the top-level diagram with annotations (click to enlarge):

Top level diagram of the FPGA VGA text output
Top-level diagram of the FPGA VGA text output

The numbers in blue follow the flow:

  1. Input pin 24 is connected to a 40 MHz crystal oscillator which is on the board outside the FPGA chip. This frequency is fed into a PLL that is generating 21.175 MHz. That is the required pixel clock for a 640×480 VGA mode I wanted to use.
  2. The pixel clock is fed into the vga_sync custom module written in Verilog. This module literally counts pixel clocks and generates VGA synchronization pulses. VGA standard is not too difficult to implement: everything is a multiple of pixel clock. Here is the actual Verilog code implementing this module:
  3. The vertical and horizontal synchronization pulses are output to appropriate pins. These pins (as well as RGB out) are hard coded to the VGA connector on the board.
  4. This module, “sequencer” is orchestrating all the action. It will be easier to understand it if I explain the rest of the flow first.
  5. This is the “display buffer” implemented as ROM. Normally, display buffers use RAM memory (so they can be modified), but I used ROM since I just wanted to display a single static page of text. The memory content of this ROM is set to ASCII text to be displayed. Each line is 40 characters wide, so there are 30 lines with the text that looks like this:
  6. This is the “character ROM”. It contains font definition for each ASCII character. The size of the font used is 16×16 pixels which translates to 16 bit wide x 16 lines, or 2 bytes x 16, or 32 bytes per character. I will explain how I compiled the font later. Sequencer sends a current pixel address scaled down to address individual character in the display memory. Display memory outputs the ASCII character at that location into the font ROM, which in turn returns that character shape back to the sequencer. It then simply shifts it out through its own vga_out port, 8 times for each byte. This repeats every 8 pixels, every line of display.
  7. This mux is a bypass for the text image. If a button (“btn_menu”, pin 129) is pressed, this part will select a color from a pixel clock instead and will display a colorful pattern. It can be used to test timings without having the rest of the font stuff working.
  8. Finally, the RGB wires are gated by a display enable signal which is set active only during a time when VGA outputs the text and not a blanking period.

Sequencer is the most complicated Verilog block in this design.

Still, it should be easy to conceptualize if you carefully read the comments in the code.

Getting the right font was a bit of a separate task with its own challenge. I needed a 16×16 font to divide it nicely into 640×480 pixel resolution. I wanted to use an existing font and not create my own. I also needed to import it as an Intel HEX file in a specific binary format so that my sequencer engine would understand it.

After some experimentation, I settled with a program called Bitmap Font Builder which could load any font from your system and save it as a RAW file (a simple monochrome bitmap without a header). Then I wrote a small utility to read this RAW format and write out a binary file consisting of font data in the particular format I needed. The last step is to have it in Intel HEX file format which Quartus could read when generating the font ROM instance. I used the excellent Hex Workshop editor program to read binary files and export them as Intel HEX.

The process seems a bit convoluted, but it is done only once to generate a font file.

This is the source of my utility to read bitmap and write out the binary font file (click to expand):

Finally, here is an image of A Poem by FPGA:

FPGA driving VGA with a poem
FPGA driving VGA with a poem

If you press a MENU button on the board, a set of bypass MUXes select the alternative color sources (from the pixel counters) and display this test pattern:

FPGA driving a test pattern
FPGA driving a test pattern
Bookmark the permalink.


  1. Thank you for you amazing article…
    Your work is helping me a lot and I would like to contribute to improve it even more, if you want!
    I found a small problem in font_correct.cpp, in the following line:
    120 outData <<= 1;
    When X = 7, should not cause a left shift. Only the first seven bits.
    As your raw character have an edge, its not a problem, however they are rolled to the left… I my case, some characters have all eight bits and don't have edge (something like this: 01010101,10101010,01010101,etc…) and in this case, its a problem for your algorithm.
    I suggest you use the following line instead of the current:
    120 if (x<size_x-1) outData <<= 1;

    Thank you and best regards,
    (and sorry-me about my poor English)

  2. Thank you so so much

  3. Hello Goran Devic ,

    I have since short a DE1 Board of Altera and try my prgrogrammieren with Verilog teach themselves using examples from the WEB . Could you with posting on their site to complete the project the code for ROM modules yet .

    Thank you for this program

Leave a Reply (your email address will not be published):