Day 6: designing the instruction set

A project log for Detritus, the 8-bit ... computer?

I have a lot of random spare parts doing nothing and a need to make them do things...

Jorj BauerJorj Bauer 05/20/2017 at 12:140 Comments

First of all: in thinking about the ALU and the parts I've got, I would have to order more register latches if I want to keep the X/Y register along with at least one register for the ALU. So I'm going to scrap that plan; I'll have two registers that are tied to the ALU, and I'll make them both general purpose.

Now, with A and B ALU registers, what functions do I want the ALU to perform?

Certainly, ADD and SUB. I've got enough gates for AND and OR, and I just placed an order for XOR. I'd like INVERT. And bit shifts, left and right (LSL and LSR).

Each of those will need an output control gate to the bus, or a wicked mess of multiplexers that select which goes to the bus. I'll stick with individual outputs, which means they'll need individual control lines.

Exactly what control lines do I have (and think I'm going to add)? Well, maybe these 15:

0Clock Halt
1A register input from bus
2A register output to bus
3B register input from bus
4B register output to bus
5RAM in
6RAM out
7RAM memory register set
8PC counter set
9Conditional PC counter set
10PC high bits set
11increment PC
12Output Enable (bus => output system)
13Load instruction register
14Program data byte => bus

If I add the 9 ALU actions, then that's more than 16 bits of control. I'd really rather not have *three* EEPROMs running the control logic. And if we just add one more control line - an ALU Active line - then maybe we can encode the specifics of *which* ALU action in the opcode itself.

Which begs the question: what are the opcodes? Do we have enough bits to be able to do that? Hmm...

0x10 <byte>LDA #immediateLoad a value in to A
0x20 <addr>LDA $addressLoad A from memory address
0x30 <byte>LDB #immediateLoad a value in to B
0x40 <addr>LDB $addressLoad B from memory address
0x50 <addr>STA $addressStore A in memory address
0x60 <addr>STB $addressStore B in memory address
0x70 <page>MEMPAGE $pageSelect RAM page $page (4 or 5 bits?)
0x80ADDADD A + B => bus
0x81SUBSUB A - B => bus
0x82ANDAND A and B => bus
0x84OROR A or B => bus
0x86XORXOR A xor B => bus
0x88CMPcompare A and B; set Carry status flag?
0x8BINVInvert B => Bus
0x8CLSLShift A left 1 bit => Bus
0x8ELSRShift A right 1 bit => Bus
0x90JMPJump to new program counter address
0xA0JCSIf the status Carry flag is set, then jump to program counter address
0xB0HALTHalt instruction

That looks plausible. The high 4 bits of each instruction will feed the address input of the control EEPROMs; the 8 bits of output from those EEPROMs will feed the 16 control lines through the computer.

The low 4 bits of the instruction will be tied to logic that selects ALU functions. It's tempting to run them through another EEPROM, but then I'm back to three EEPROMs running the control circuitry. Instead, I've got some 1-of-8 decoder ICs (like the 74LS138) which I can use. So three of the low 4 bits will feed a '151 or similar; while the fourth low bit will enable the "invert B" input in to the adder, for subtraction.

Nice, this might even work.