PGAs can greatly simplify circuit design, making it possible to synthe-size nearly all components of this project’s Sinclair ZX Spectrum 48 into one single integrated circuit.
My first idea was to have only the ULA part of the ZX Spectrum in the FPGA. It would generate the video signals for the TFT screen, accept the keyboard input, handle sound input and output and be responsible for all the memory control signals - more or less the stuff implemented in the original ULA. Together with a Z80 CPU, a 27128 ROM and some 62256 static RAM chips, it would compose the computer.
By luck, however, I discovered a project called the “T80” on the web. This is a configurable Z80 CPU core in VHDL. So, I decided to include as many parts as possible in the XC3S200 Spartan-III FPGA. This FPGA even includes about 27 kBytes of static RAM. I assigned the bottom 16k to the ZX Spectrum ROM which is available on the web (even as a very nicely commented version) and 8 of the remaining about 11 kBytes to the system RAM. An advantage of that decision was that the 7k video memory (6144 bytes for the 256 x 192 pixel grid, another 768 bytes for 32 x 24 attribute locations) could benefit from the dual-port functionality of the FPGA’s block RAM. Like this, I could significantly reduce the logic required to handle concurrent accesses to this memory area. In order to keep the video logic simple, I decided to assign 2 x 2 pixel squares of the VGA TFT display to the ZX Spectrum pixels, resulting in an image width of 512 and height of 384 pixels on the VGA display, with a 64 pixel border at the left and right side and an 48 pixel border at the top and bottom of the image.
The memory map splits memory into 3 areas:
Luckily, the Spartan-III starter board includes some SRAM which I used as RAM for the upper 40 kBytes. The 4-digit seven segment display was connected to the address bus to illustrate execution fetch addresses and verify program execution.
One point that was not immediately obvious was how to fill the 16 kBytes of ROM data into the Spartan-III’s Block RAM. After deciding not to do that by hand, I’ve written a very small C program, blockraminit, which reads a binary file and writes a text file in the format that you can copy-paste into the VHDL.
The Spartan-III starter board includes a PS/2 connector, however I thought it would be more fun to have a “real” ZX Spectrum keyboard. So I visited a nearby hardware store in a lunch break and bought some 5mm thick plexiglass which would be the basis of the keyboard. The surface is a laminated photography of a ZX Spectrum so that all the “special functions” are visible. Below all 40 keys, I drilled a 10mm diameter hole.
The 10 x 4 key matrix is realized with standard pushbuttons on a cheap stripboard. The backside of the stripboard is very ugly, as you can see on the photo.
One lesson I’ve learned the hard way is to be very careful with superglue. Not because it can glue your fingers together - I was well aware of that. But it generates some sort of “vapor” even hours after applying it, and the vapor was so aggressive that it killed more than 10 pushbuttons. I had used the superglue to glue the laminated screenshot to the plexiglass but not waited long enough for the glue to completely dry.
Anyway, after fixing a couple of bugs in the VHDL code, the screen finally showed the famous “red ink on paper” startup screen. Now, that was really a fantastic experience!