2019-08-14 – Part 4 – The EightThirtyTwo ISA
In order to experiment properly with the instruction set I need some way of assembling and running programs. Luckily I wrote a ZPU simulator some time ago, and this is easily re-purposed for the EightThirtyTwo instruction set. The simulator is part of the EightThirtyTwo project on github.
In the longer term, to be useful this ISA will need a fully-functional toolchain, which means writing a backend for GCC – or perhaps LLVM, or maybe even lcc, vbcc, or some other C compiler. That’s going to be a rabbit hole in its own right, however, and for now we just want a quick and easy way of turning an assembly listing into a binary file of bytes ready for execution.
Part 3 – 2019-08-12 – Nailing down the instruction set
My initial plan for the EightThirtyTwo ISA was to define eight general purpose registers, and use the ninth “temp” register as an accumulator. Immediate values would be assigned here, as would the result of any arithmetic operations. The best way to test the concept is, of course, to write some actual code. So let’s see what simple looping looks like with this concept:
li 99 // (needs two li instructions since 99 doesn't fit within a signed 6-bit value)
// take one down, pass it around
cond NEQ // Disable execution if we've reached zero
mr r7 // if not, do another iteration
cond EX // return to normal execution
That’s not too bad – weighing in at 10 bytes – way better than MIPS, but 68K beats us easily thanks to its dbf instruction. Let’s try something more involved…
2019-08-10 – Part 2 – Choosing the Instruction Set
In part 1 I talked about why I wanted to design my own microprocessor, and how I’d settled upon an architecture using eight-bit instruction words and eight addressable thirty-two bit registers.
Because our instruction words won’t have room to encode two registers in them, each instruction will only take one operand – so we need a way of supplying a second operand to instructions such as add, xor, load immediate, etc. For this I’ve defined a ninth register, which I’ll call temp. This register isn’t addressable via the instruction word – it’s simply used implictly wherever it’s needed. One of the key decisions to make will be whether the result of arithmetic instructions will go the nominated register or the temp register.
It’s not entirely clear without giving the matter some thought (and ideally writing some test programs) exactly which instructions we need to implement, so initially I’ll list all the possible instructions that come to mind, and then figure out what’s mandatory, what’s optional, and what’s most beneficial in terms of keeping code size down, in the hope that we can hit our target of 25 instructions.
2019-08-09 – Part 1 – The Pipe Dream
In 2019 there are any number of off-the-shelf CPU cores which can be used in FPGA projects, some imitating long-established CPUs such as x86, MC68000, Z80, MIPS, ARM, etc – and some more specifically targetted at the FPGA space, such as NIOS, Microblaze, ZPU, Moxie and suchlike. So why on earth would I consider creating a brand new one from scratch?
As always, because I wanted to learn something, and because even though there are so many existing options, there are still applications for which none of them is ideal.
My design goal is to create a CPU that’s reasonably small – not much bigger than ZPUFlex – so takes up somewhere in the region of 1500 logic elements, while being somewhat faster and offering better code density. Ideally I want something that can supplant the ZPU for control module applications and allow me to reduce the amount of block RAM I have to devote to the code.
A few years ago I ported three of the PACE arcade cores – namely Pacman, Pengo and Moon Patrol – to the Turbo Chameleon cartridge. Since then the original pacedev.net site seems to have gone down, but the source repo is now on github. Over the last few days, in odd moments I’ve cloned that repo, and added support for the new Chameleon V2 hardware – and now have the same three arcade cores working on the new hardware.
The cores can be downloaded here. Please note, these are straight ports of the cores to V2 hardware – do not attempt to flash them to an original Chameleon.
All three cores can be played using a PS/2 keyboard or a CDTV pad.
Coins can be added using the leftmost button on the Chameleon itself, the Run/Stop key on the C64, the 5 key on a PS/2 keyboard, or the Power button on a CDTV pad.
The Start button is mapped to the middle button on the Chameleon, the cursor up/down key on the C64, the 1 key on a PS/2 keyboard, or the Play button on a CDTV pad.
All three games can be played with a joystick, too – however Moon Patrol requires a second button.
Here’s an initial port of the Sega Megadrive / Genesis FGPA core to Chameleon V2 hardware.
Please note, this is specific to V2 hardware – do not attempt to flash this core to V1 hardware. There are no improvements to the existing V1 core, it’s merely a port of the existing version and doesn’t yet incorporate upstream improvements.
The on-screen display is toggled with F12, and gamepads can be emulated using either the CDTV control pad (port 1 only, buttons A and Start are mapped to volume down and volume up, respectively) or a PS/2 keyboard.
On the PS/2 keyboard, port 1’s controls are Cursor Up/Down/Left/Right, Right Ctrl, Right Alt, Right Shift and Enter.
Port 2’s controls are W, S, A, D, Left Ctrl, Left Alt, Left Shift and Caps Lock.
I found out recently that there is now a second version of the Turbo Chameleon 64 cartridge for the Commodore 64. The reason for this is, apparently, that the Cyclone III FPGA that was used in the original design has been superceded and is difficult to obtain at affordable prices. For this reason Individual Computers have redesigned the cartridge to use a Cyclone 10 FPGA instead. The model chosen is essentially the same thing in a different package, so porting cores would simply be a case of recompiling with the new device and pinout as the target – except they’ve also taken the opportunity to make small improvements to the design. For this reason it now takes a little bit of work to port existing cores to the V2 hardware.
I now have an initial build of the Minimig core for V2 hardware, which is available as before on the Minimig TC64 Snapshots page.
Edit: Since the V2 hardware is likely to attract newcomers to the Chameleon platform, I should explain what to do with the two files in the snapshop archive:
- The fampiga_tc64v2.rbf file is the core itself, and needs to be flashed into the Chameleon cartridge using the Chaco utility.
- The OSD_CA01.sys file is the firmware for the secondary CPU core that runs the menu system and disk emulation, and needs to be written to the root directory of an SD card. The card will also need to contain a Kickstart image, named kick.rom
Another point to bear in mind is that the core doesn’t yet attempt to translate the C64 keyboard to the Amiga – so far just the run/stop key is used to toggle the OSD – so you will need a PS/2 keyboard to use the core for anything that requires keyboard input.
Source is availabe, as before, on github.
Here’s an updated snapshot of the FPGA Megadrive / Genesis core for both Chameleon64 and MIST with the latest memory speed improvements. I’m hopeful that this will pretty much eliminate the sprite issues that have been present in previous releases:
Part 3: Tweaking the VDP implementation
In the second part of this series, I increased the throughput of the Megadrive core’s SDRAM controller, which gave nearly but not quite enough extra bandwidth to solve the sprite display problems. To improve things yet further I need to look at the VDP implementation itself…
Following the SDRAM-related improvements to the Megadrive / Genesis core that I’ve covered in my last couple of posts, here’s an updated snapshot for both the Chameleon and MIST boards:
While it’s still not perfect, the glitches should be much less noticeable, and hopefully there will no more missing platforms or missiles making games unplayable!