Over the summer of 2023 I decided to keep myself busy with a relatively ambitious project; I wanted to build an 80s-style terminal computer based off of the classic 6502 processor chip, and I wanted to build a graphics processing circuit capable of terminal-style text-based video output. This project essentially followed Ben Eater's 6502 computer video series, with some minor tweaks and additions of my own. I haven't even come close to a conclusion for this project, and I want the final product to be printed on a custom PCB with a nice-looking enclosure (probably an old PC case retrofitted for this purpose.)
The MOS 6502 processor was one of the earliest processor chips that were affordable enough for large-scale home PC and console manufacturing. Early computer and game consoles such as the apple I and II, Nintendo Entertainment System, Commodore 64, and many of the 8-bit atari home computers used the 6502 processor or a similar variant. The original MOS chips are out of production, but Western Design Center manufactures a near-identical 6502 chip with some modern amenities such has higher max clock speeds and easier halting protocol. This is the chip Ben Eater uses in his project and I will be using the same one.
In Ben's guide, he primarily uses a serial connection to a modern computer for interfacing with the terminal, instead of implementing standalone graphics circuitry. He does include a tangential project where he builds a rudimentary graphics system that supports color but requires that the CPU write each pixel to the frame buffer manually, and uses a very rough but straightforward method to provide DMA to the graphics unit. This is the main area where I would like to insert my own improvements.
For my project, I want to implement basic terminal-style graphics support, similar to the graphics functionality of the original Apple I computer. I am not interested in color support whatsoever, I just want the CPU to write ASCII characters into the frame buffer in black and white. I believe that when color and pixel-by-pixel frame writing are scrapped, my video system could easily support much larger ASCII-based frame buffers at higher resolutions.
But before I could get started on the video system, I had to actually build the 6502 computer. My computer is pretty much the same as Ben's, except I really had an issue with his memory address allocation for peripherals. He sacrificed a lot of address space for the sake of ease of implementation, and I wasn't as concerned about ease of implementation. Ben managed his addressing with a few NAND gates. I upgraded to a set of demuxers/decoders so that more specific address ranges could be reserved. I also halved the amount of ROM space and doubled RAM space, just because I doubt any program on this computer will exceed a few kilobytes. I kept the peripherals; A general I/O chip (6522), serial chip (6551), and an added graphics processor. My new addressing logic allows for a greater addition of peripheral however, and I'd like to add a few DAC's at the least. The last step of building the computer was getting Wozmon working. Wozmon was an extremely rudimentary kernel designed by Steve Wozniak for the Apple I which allowed for program writing (In hexadecimal assembly) and executing, as well as browsing the address space. After I was able to confirm Wozmon was working via a serial connection, I was ready to get started on my graphics system.
Fortunately, in order to implement graphics, I don't need to diverge much from Ben's video design except for the last bits of the logic chain. The largest portion of the complexity of the design comes from the logic that reads the pixel-by-pixel frame buffer and transmits the buffer to the screen via a VGA signal. At the end of this logic chain is a system that reads the buffer from memory. This end ought to be replaced by a ROM which contains the pixel-by-pixel ACSII character set where each line of a character is addressed by its corresponding ASCII code and the line number that should be displayed. This means the ROM's address lines should be tied to the video system (which counts lines), and the frame buffer in memory. If the width of each character is 8 bits/pixels, then this means the ROM will have to access memory directly every 8th pixel on the screen. I plan to run the video system at 40MHz, which means every 8th pixel occurs every 200ns, or at a frequency of 5Mhz. Before that 8th pixel is written by the video logic, some system must halt the 6502 (or otherwise stop it from accessing memory), read from the proper address in memory, increment that address before the start of the next cycle, make sure that the ROM has had enough time for its output to stabilize, and shift each bit from the ROM into the VGA signal. This time constraint is the greatest hurdle to this design, although I still believe I may be able to find parts that can run this fast. Once I can actually write a character to the screen (via hard-coding and not DMA), then I have to find a way for the processor to be able to run for some portion of this time. This means that the graphics processor needs to access the RAM for as little time as possible. This problem iz significant, and may require the pixel frequency to be halfed or quartered to reduce resolution and allow the hardware more time. As of writing, I have built this video circuitry without DMA, but have been unable to get a character to output to a screen. I believe this is a timing issue, and will update once I have solved the issue.
This is the state of my project so far. But before I conclude, I would like to lay out my plans for this project once the hardware is working. I would like to use the computer to interface with analog synthesis circuitry to mak some kind of roided-up sound card for music. I would also like to get a more complex operating system running on the computer. I would start this process by getting a C compiler running on the 6502, and then getting some kind of basic Unix- like kernel up and running. This is likely overambitious and I suspect I will just end up getting BASIC running on it instead, but these are the end goals for the project.
This project has been very valuable to me in several ways. Building a computer from chips, getting to the point of writing code for it in assembly, and seeing a basic kernel running really helps build a rigorous understanding of how computer code really is just a high-level abstraction from the bare metal hardware. I think with modern computers and their complexity, this is a kind of holistic understanding that is lost. The hardware becomes a black box which just runs code. This project helps remind me that no matter how complex our computers get, at the end of the day they really do just execute binary instructions.