So, I have shared this project on a few Discord servers now and taken some criticism, especially for my memory considerations. And now that I’ve slept over that criticism and been at work thinking, I have to admit that some of my originally planned features are, well, feature creep.
Do I need 32 registers for the CPU? Do they need to reside in RAM? Do I need a native context switching capability that switches between registers in RAM?
Oh, they would certainly be cool, and they might make some work on the design easier. But in the end… I don’t need those features. Just like I do not need any fixed stack for every context.
So I decided to change my desired features.
For one, I will move the registers into the CPU proper, which will remove a big addressing headache and turn it into a simple Mux/Demux problem.
And since the registers are removed from RAM, it will also see a change in its layout.
I will also drop the pipeline from my list of features for the time being, as the pipeline would make any circuit design much more complex than a more normal linear operation of the CPU, though it would mean slower speed.
Register Revision
When it comes to registers, I will drop from 32 registers down to 13 registers, though they can be addressed like 16 registers. Why? You’ll see…
Registers R00 to R07 will be 16 bit general purpose registers for everyday tasks, with the rest being special purpose registers. They can be read, written, operated on and saved to the Stack.
Register Z, R08 or Zero Register, is more or less just the 16 bit value 0x00 and cannot be written to. This is followed by the 16 bit F, R09 or Flag Register, containing all the flags of the CPU. It can be read, written and operated on, for example, to set or reset the Carry Bit, allowing to go without any special instructions to do the same, and to save it to the Stack.
The next two registers are 24 bits in size, so they are accessed as two 16 bit registers. One is the Program Counter, PC, PCH and PCL, or R10 and R11. The other is the Stack Pointer, SP, PSH and SPL, or R12 and R13. Both of these can, again, be read, written and operated on.
Finally, we have a 32 bit wide register, Z, ZH and ZL, or R14 and R15. It is meant for addressing through registers
General Register Layout
R00 | R01 | R02 | R03 | R04 | R05 | R06 | R07 |
R08 Z | R09 F | R10 PCL | R11 PCH | R12 SPL | R13 SPH | R14 ZL | R15 ZH |
Register | Register Label | |
---|---|---|
R08 | Z | The Value Zero |
R09 | F | Flag Register |
(R10,R11) | PC | Program Counter |
(R12,R13) | SP | Stack Pointer |
(R14,R15) | Z | Z Address Register |
Memory Layout
This leaves the new general memory layout.
And without the register contexts, the interrupts must be handled more normally, via interrupt vectors. In this case, the first 16 words of memory, from 0x000000 to 0x00000F, are reserved for seven interrupts and the reset handler, with the latter pointing at the start address of the Monitor/OS.
The Memory Mapped IO is also moved into the lower memory from 0x000010 to 0x0003FF, which should leave enough space for a few things.
This means that the Monitor/OS is moved to 0x000400 to 0x01FFFF. And the rest is the normal RAM.
Memory Layout
0x000000 – 0x000001 | Reset Vector |
0x000002 – 0x000003 | Interrupt Vector 1 |
0x000004 – 0x000005 | Interrupt Vector 2 |
0x000006 – 0x000007 | Interrupt Vector 3 |
0x000008 – 0x000009 | Interrupt Vector 4 |
0x00000A – 0x00000B | Interrupt Vector 5 |
0x00000C – 0x00000D | Interrupt Vector 6 |
0x00000E – 0x00000F | Interrupt Vector 7 |
0x000010 – 0x0003FF | Memory Mapped IO |
0x000400 – 0x01FFFF | Monitor/OS |
0x020000 – 0xFFFFFF | Main RAM |
ALU
Another small redesign option falls to the ALU, where I will remove the input and output buffers from the logic circuit, which will be moved outside, to be replaced by dedicated Register Modules designed separately. It might have been a bad design to start with.
Conclusions
Just because something seems like a nice feature, I should not jump directly into adding it.
This is my first design, and therefore, even if it’s meant to be 16 bit, it should be relatively simple to design and build. And more advanced features like pipelining or registers in RAM are a bit past my experience to design.
Another thing is that I should validate the design before I build it. Doing it in a simulation is all well and good, but I think some sort of hardware will be needed. So I will have to look into creating this in the form of an FPGA, before I start building it in discrete logic.