I’m building an 8-bit computer. I should probably write an overview of the project, why I decided to do it, how I got started, etc, but today I have a problem to solve.
Take a look at the following image:
This shows a VGA monitor displaying text at a resolution of 40 columns x 30 rows. Each character is an 8x8 block, giving an overall screen resolution of 320x240 pixels.
Now, what’s the problem?
Look closely at the first column. Does it look a little off to you? It did do me, which caused me to zoom in.
The first column is one half-line lower than all the following columns.
How can this be?
It’s time to talk about how this is supposed to work.
I have an FPGA that is acting as a video processor (like the VIC II in the Commodore or the ANTIC/GTIA combo in the Atari). I have a character font stored in ROM. There’s also a section of RAM that stores the ASCII values of the characters to display on the screen in order. The first byte in this section of RAM controls the character in the top-left corner of the screen. The last byte controls the character displayed in the bottom-right corner of the screen.
In order to control a VGA monitor, the video processor sends the pixel data (either on or off in my case) for each pixel on the display starting at the top-left, one line at a time, moving left-to-right. This happens at a constant rate, with a fixed-length break at the end of each line, and a slightly longer break at the end of each screen. This process happens 60 times every second.1
In order to display the expected values on the screen, the video processor must do the following:
- Load the next character from RAM.
- Combine the value from RAM with the vertical position on the screen to look up the font data from ROM. (Remember each font is 8 lines tall, so we need to know which line of the font to draw.)
- Send the font data out one pixel at a time.
As you can imagine, the timing of these operations is critical. We need to load the next character from RAM and the font data from ROM while we are in the process of sending the pixel data to the monitor for the last character.
Oh yeah, one other thing. VGA doesn’t technically support a screen resolution of 320x240, but it does support 640x480. So I’m drawing every pixel twice per line, and drawing every line twice.2
When the processor is outputting the 5th pixel for a character, it starts loading the data for the next character. This seems to work just fine for almost the entire screen, except for the first column.
Remember, there’s a break at the end of every line. This means that I need to start loading the character data for the start of the next line at the end of this blank period. There’s also a longer break at the end of each screen. This means that I need to load the data for the first character of the screen at the end of this blank period.
I think this is where the bug is. All the characters in the first column are one half-line (at 320x240) lower than the rest of the screen. My best guess is that I need to start the data load a little sooner during the blank period.
- For a much better explanation of how VGA works, I recommend Ben Eater's excellent video.↩︎
- I want a 320x240 screen size because my 8-bit system doesn't have enough memory to support a 640x480 size screen.↩︎