In the last article, I presented a different way of architecturally modeling a Zilog Z80 processor. It is time to do something really useful with it and what could be better than reliving the past for a moment? Let's recreate an old computer and load in and play some games!
Sinclair ZX Spectrum was my second computer, the first one being ZX81. As I was growing up in Croatia, I had a good friend whose brother, living in Germany, regularly sent him tapes with new games. Through this steady stream of games I've probably seen most of them (thank you, Krešo!) However, although I could, I had never played them through. Instead, I would load in DevPac - a debugger - and disassemble them trying to decipher how they were made and occasionally find some pokes for infinite lives.
The time is finally ripe to mend that omission and to kick a midlife crisis with a high score in Manic Miner!
Sinclair ZX Spectrum
I used an Altera DE1 board with Cyclone II FPGA on it. With 512 Kb of static RAM and plenty of other peripherals and connectors, the board is very suitable for this design.
You can find this project on GitHub: https://github.com/gdevic/A-Z80
It contains several documents and readme's which might have more technical details than described in this blog.
Two kinds of Spectrum ROMs were flashed into the 4 MB flash part: the original ROM and an enhanced "Gosh Wonderful" ROM. They are selectable by an onboard switch.
The ULA/Video subsystem drives a VGA monitor at 640x480 resolution. The video timings are shown in this external document.
Video does not use SRAM chips but internal FPGA RAM blocks configured as two-port RAM with separate read/write ports and timings. Consequently, the design does not implement memory contention.
As expected, the PS/2 keyboard driver maps all Spectrum keys but then also implements several enhancements. CTRL maps to Spectrum CAPS SHIFT and ALT maps to SYMBOL SHIFT. ESC key will issue a true break (BREAK SPACE) and many other PS/2 symbol keys will properly show in Spectrum so when you type you can just press keys you are used to and not have to look at the Spectrum keyboard image to find out where a certain symbol is.
The complete ZX Spectrum project (including the A-Z80 CPU), compiles in Quartus for the Cyclone II device using just about 20% of its available LEs:
Since I had switched to a 100% flop design, I was able to fully constrain the timings with enough slack to spare!
Info (332146): Worst-case setup slack is 16.142
Info (332146): Worst-case hold slack is 0.445
Info (332146): Worst-case recovery slack is 138.585
Info (332146): Worst-case removal slack is 1.856
Info (332146): Worst-case minimum pulse width slack is 3.889
Info: Analyzing Fast Model
Info (332146): Worst-case setup slack is 18.959
Info (332146): Worst-case hold slack is 0.215
Info (332146): Worst-case recovery slack is 141.035
Info (332146): Worst-case removal slack is 0.864
Info (332146): Worst-case minimum pulse width slack is 4.000
Info (332101): Design is fully constrained for setup requirements
Info (332101): Design is fully constrained for hold requirements
Info: Quartus II 64-Bit TimeQuest Timing Analyzer was successful. 0 errors, 542 warnings
Info (293000): Quartus II Full Compilation was successful. 0 errors, 1455 warnings
Unless you experienced it yourself, it is hard to describe a rush one gets when a design starts working!
The old Kempston joystick was a very popular gaming stick at the time and many ZX Spectrum games supported it. Its interface was simple: the state of joystick directions and (two) buttons directly read out at the IO port 0x1F.
I had a "Bluetooth joystick for iPad" in my box of junk. I got it deeply discounted somewhere but it refused to connect to my Android tablet.
The actual joystick has 8 push buttons and a digital, 8-directional stick. You can see the slot into which you'd put a tablet for a connector-less, Bluetooth enjoyment.
When you open a controller box, its mess of wires does look robust and nicely tied up. A perfect box to mod with plenty of interior real estate.
I removed the Bluetooth controller since it was useless to me anyway. As with all electronic junk, I stashed it away for a "future project" 🙂
There was more than enough room in the box to add a piece of proto-board with resistor pull-ups connecting selected buttons - I had to choose and expose two buttons out of the eight. It's a bit wasteful for the other 6, now defunct buttons, but it got the job done quickly.
You can see the new "Kempston" board and a long ribbon cable conveniently going through the unused power-jack hole.
At the other end, I clamped it to a 40-pin connector and plugged it into one of two DE1's expansion slots. I aligned it so to get the 3.3V and ground needed for the design while using a 10-wire ribbon that I happen to have.
I'd say the final "product" is both beautiful and functional. A ribbon cable is long enough to make a comfortable setup and effective retro-gaming (or less effective in my case!).
In the SystemVerilog code for the Spectrum host (see "host\zxspectrum\zxspectrum_board.sv", line 110) this simply translated to reading those GPIOs when the CPU executes IN instruction with address A[7:0] set to 8'h1F.
To fire it up, I used Patrick's excellent PlayTZX app which you can download from the Google App store. It does everything for you including a web search for the apps you wish to load.
Note: In the meantime, I have written my own Android app with a built-in database of more than 10,000 games and a stellar way to search, download and play them. Patrick's app is still a good app - I just needed a few extra features. You can download it for free here.
Once selected, you load a game by simply connecting the audio out from your Android device to the LINE-IN of a DE1 board.
You can see how it all works in this video. Yes, I cheated on Manic Miner: entering a code 6031769 will show a little boot on the bottom and will let you jump to any game level. 6031769 was apparently Matthew Smith's license plate. He wrote the game.
Kick back and Enjoy!
I have brought the FPGA setup to a friend of mine and his kid mastered, in a very short time, pretty much every game we loaded in. He just had a knack for it! It was cool to see a new generation kid puzzled by our patience of waiting 3, 4, and even 5 minutes to load a game!
I decided not to add the divIDE interface (or any other load-quick scheme) since I felt that would take away from the retro pleasure. I also did not add more advanced Spectrum designs (Spectrum 128 or +2A) since they came much later than the original 48K model which I really cared for. All of these could be added, though - it's a solved problem.