My First Didactic 8-bit Z80-based Computer
I built this computer because I’ve been interested in creating a working computer from TTL chips since my high school days. The Z80 microprocessor, first introduced by Zilog in 1976, was an ideal choice for this project. As an enhanced version of the Intel 8080, it became one of the most successful 8-bit CPUs ever made, powering iconic computers like the Sinclair ZX Spectrum, Radio Shack TRS-80, and many early CP/M machines.
I was intrigued by the idea of better understanding PC architecture, and I wanted to learn assembly language programming. The Z80’s rich instruction set, which includes powerful block move, block I/O, and bit manipulation instructions, makes it an excellent platform for learning assembly programming.
Project Overview
My project started by following Grant Searle’s ingenious design: Grant’s 7-chip Z80 Computer. What makes this design remarkable is its minimalist approach – achieving a fully functional computer with just seven integrated circuits.
UART Modifications
Please note that I’ve modified the UART/RS232 converter wiring. The original Universal Asynchronous Receiver/Transmitter (UART) design gave me some challenges. I actually spent a lot of time troubleshooting Grant’s schematic: everything was double-checked, but no data was being received through the serial port. I solved it this way:
No jumpers between DB9 connector pins or other RTS complications – just a simple, direct RX-TX converter between the 6850 UART and DB9 connector. The Motorola 6850 ACIA (Asynchronous Communications Interface Adapter) is a versatile chip that handles serial communications, but it sometimes requires careful timing considerations.
Construction Details
I built it using point-to-point wire soldering on a veroboard prototyping board. While this construction method requires more patience than using a printed circuit board, it offers great flexibility for modifications and debugging. The system communicates via an RS232 serial link, which, despite its age, remains a reliable and straightforward protocol for computer communications.
Clock and Timing Considerations
The schematic is the same as Searle’s design, except I modified the clock source and the init.asm code that drives the 68B50 ACIA. The Z80 CPU is remarkably flexible with clock speeds, capable of operating from DC (0 Hz) up to its rated maximum frequency, which varies by version (2.5 MHz to 8 MHz for original variants).
Initially, I used a 1.8432MHz crystal oscillator for both CPU and ACIA, but later switched to drive the CPU with a 10.240MHz crystal oscillator. The 1.8432MHz crystal now only drives the ACIA – setting the divider byte to 16 generates 115200bps. This split clock arrangement allows for optimal CPU performance while maintaining reliable serial communications.
ACIA Configuration Details
I’m not using the RTS (Request to Send) signal, as it’s not wired at all, but RTS_HIGH and RTS_LOW values in int32.asm code needed to be changed to make it work. Understanding the control register configuration is crucial for proper ACIA operation:
RTS_HIGH is D6h and equals binary 11010110b. According to the MC6850’s datasheet (page 8), from left to right, one bit at a time:
1 - CR7 register, interrupt enabled 1 - CR6 and 0 - CR5 these bits plus the previous one select RTS HIGH transmitting interrupt disabled 1 - CR4 and 0 - CR3 and 1 - CR2 selects 8 bits + 1 stop bit 1 - CR1 and 0 - CR0 selects clock divider /64
For achieving 115200bps from a 1.82MHz crystal, you’ll need 1.82/0.1152 = 16, then according to the datasheet, CR1 must be 0 and CR0 must be 1. The new data for RTS_HIGH is then 11010101b = D5h. As you can see, the difference between divider by 16 and 64 is just one bit – simply subtract one bit! Final values: RTS_HIGH is D5h and RTS_LOW is 95h.
Solving the MC6850 Timing Challenge
An interesting challenge emerged with the MC6850, which was originally designed to operate with MC68000 timings. It usually doesn’t enter master reset mode, especially if your Z80 clock is faster than its own clock. This timing mismatch is a common issue when mixing components designed for different processor families.
Initially, I “fixed” this by hot-swapping the MC6850 (with the circuit powered) by removing it from its socket and reinserting it, then applying a reset via the reset circuit button. While this worked, it wasn’t an elegant solution.
The breakthrough came when Joe Helmick contacted me and shared a much better solution: using a strong pull-up resistor (1KΩ) on the /INT line solved the boot timing issue. He uses this approach in his homebrew Z80 SBC with great success. Joe has also created a fascinating implementation of “Conway’s Game of Life” for his Z80. You can see his work here: Conway’s Game of Life on Z80
Performance Testing
To evaluate the system’s performance, I used the classic Mandelbrot fractal generator from the RC2014 project. The Mandelbrot set calculation is particularly interesting for benchmarking because it heavily exercises the Z80’s arithmetic capabilities and memory access patterns.
The RC2014 project, another fascinating Z80 experimental project, started like mine by adapting Searle’s project and improving upon it. It has since grown into a complete modular computer system with a variety of expansion options.
The benchmark results clearly show the impact of clock speed on performance:
- At 1.832MHz: 46:52 minutes to complete
- At 10.240MHz: 8:31 minutes to complete
This nearly linear scaling with clock speed is characteristic of the Z80’s architecture, where most instructions take a fixed number of clock cycles to execute.
Programming Resources
For those interested in programming this system, here are some valuable resources:
Here you can find the complete MS Basic language reference Microsoft_Basic_8086Xenix_Reference
And here is the Nascom Basic manual NASCOM_Basic_Manual
These manuals provide comprehensive documentation for both Microsoft BASIC and Nascom BASIC, two popular implementations of the BASIC programming language for Z80 systems.
Future Enhancements
Possible future improvements could include:
- Adding a parallel I/O port for external peripherals
- Implementing a simple memory banking system
- Adding support for CP/M operating system
- Interfacing with period-correct storage devices