October 2019
Device ID Codes
The actual identifications will be assigned later, when the hardware is assembled most likely, but this will be a helpful guide as I work out the backplane (currently considering three options between 56 and 80 lanes).
Device ID | Signals/Commands | Description and Notes |
00000 | we,oe | Zero/Null Register |
00001 | we,oe | A-Register, half of the ALU input |
00010 | we,oe | B-Register, half of the ALU input |
00011 | we,oe, inc | Program Counter |
00100 | we,oe | SRAM, 64k bank 1 |
00101 | we, oe | General purpose data register (temporary value storage?) |
00110 | we, oe | General purpose data register (output register?) |
00111 | we, oe | General purpose address register (branch address?) |
The idea is we can identify most devices using a 5-digit code. If we start with nine devices, we will have an ALU, 64k of memory, and four general purpose registers to work with.
The Instruction Register is not listed above as there will be no instructions that affect it directly. The ALU does not need an identifier, either. We can use the 5-digits of the "source" to pass the ALU a mode (1-bit flag to switch between logical and mathematical functions) and command (4-bit signal to indicate which of sixteen functions to execute).
To start, a minimal setup would need the following five addressable devices, plus the Instruction Register and ALU.
Device ID | Signals/Commands | Description and Notes |
00000 | we,oe | Zero/Null Register |
00001 | we,oe | A-Register, half of the ALU input |
00010 | we,oe | B-Register, half of the ALU input |
00011 | we,oe, inc | Program Counter |
00100 | we,oe | SRAM, 64k bank 1 |
Note that the "Zero Register" might not actually be a card, it could be pull down resistors directly soldered to the backplane, as long as no actual device is assigned the 00000 identifier. The Instruction Register will need to reside on the data bus as well, but is not included in the above as it is not accessible to instructions (i.e. there are no software instructions to manipulate the IR). The ALU is not addressed by a device number, but will still need to take up a slot on the backplane to output results.
16-bit Instruction Plans... Rough Draft?
I finally decided to go with a full 16-bit computer, after four years of prototyping an 8-bit system. Why? Well, 16-bit instructions give us a lot of "resources" to work with, without having to split instructions across multiple words. 16-bit registers and ALU simplify a lot of maths, and make it trivial to manipulate addresses. 16-bit instructions also simplify a lot of hardware concerns, including breaking instructions up over several IR fetches and very limited identifiers for devices (registers, SRAM, etc.)
With 16-bits to work with, we are able to dedicate 5-bits to identification giving us a maximum of thirty-two devices. For example, the "A-Register" may be device 00001, while an SRAM bank may be device 00110. Device 00000 will be the "Zero-Register, effectively identifying no device and allowing the pull down resistors to control the bus.
Examples
With 5-bit identification, the first instruction to consider is a MOV, or copy instruction between two devices.
MOV 00001 00010 - Output Enable for device 1, and Write Enable for device 2
Source and destination identifiers take up ten binary digits, leaving six more, so these six will be available for all move/copy instructions. Where a source and destination are not required... an increment instruction, for example... more digits are obviously available. So, knowing this, how do we decide how an instruction is laid out?
MOV Instruction
We need five digits for the source and five digits for the destination when moving or copying values between devices. This can be as simple as copying values between two registers. Note that this also works for SRAM, EEPROMs, etc, except that in those cases the addressing needs to be setup ahead of time.
Source Destination
00001 01110
STO Instruction
A store instruction immediately stores a value, encoded as part of the instruction, to the destination device. The first bit of an instruction can be used to determine when an immediate store is called, the next ten digits (numbers up to 1023) are the value, and the final five digits are the destination device.
Value Destination
0000000010 11001
ALU Instruction
Assuming the ALU is always connected to the A-Register and B-Register as inputs, we can assign 5-digits to the mode and signals, with the other 5-digits indicating a destination to store the result.
Mode Signal Destination
0 0001 01110
Because instructions can be variable... we do not always have a "source" device, for example... it is important to create a sensible guide.
1vvvvvvvvvvyyyyy - Store the 10-bit value "vvvvvvvvvv" into the "yyyyy" device. This may often be an 8-bit number, but 10-bits can be available in this instruction and those extra bits are the difference between a maximum of 255 and 1023.
010000xxxxxyyyyy - Write the 16-bit value stored in the "xxxxx" device to the bus, and write that value to "yyyyy".
001000mssssyyyyy - Execute the ALU function indicated by mode "m" and signal "ssss". and write the 16-bit result to the "yyyyy" device.
This is just a start, but I do like 5-digit identifiers as that means we can have 32 devices... way more than needed. The original 8-bit design was going to have 3-digit identifiers, limiting us to nine separate devices. That can work, but is limiting and would greatly impact the difficulty of hand-coding useful software. With thirty-two devices, we can have the ALU, A-Register, B-Register, several general purpose data and address registers, several address pointers (including the Program Counter), multiple banks of SRAM and EEPROMs... even things like sound and video cards, or input devices.
I need to give some thought to conditionals... branches, jumps, whatever we want to call them. These commands will follow a similar design as above, but will be conditional based on a flag (carry, negative, zero, etc). The remainder of the instruction can be an offset (requiring the ALU to calculate a destination address by adding or subtracting that offset from the PC), or perhaps a device containing that address (a Jump Register is loaded with an address, then that address is put onto the address bus *if* the condition is met.