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:
|1||A register input from bus|
|2||A register output to bus|
|3||B register input from bus|
|4||B register output to bus|
|7||RAM memory register set|
|8||PC counter set|
|9||Conditional PC counter set|
|10||PC high bits set|
|12||Output Enable (bus => output system)|
|13||Load instruction register|
|14||Program 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 #immediate||Load a value in to A|
|0x20 <addr>||LDA $address||Load A from memory address|
|0x30 <byte>||LDB #immediate||Load a value in to B|
|0x40 <addr>||LDB $address||Load B from memory address|
|0x50 <addr>||STA $address||Store A in memory address|
|0x60 <addr>||STB $address||Store B in memory address|
|0x70 <page>||MEMPAGE $page||Select RAM page $page (4 or 5 bits?)|
|0x80||ADD||ADD A + B => bus|
|0x81||SUB||SUB A - B => bus|
|0x82||AND||AND A and B => bus|
|0x84||OR||OR A or B => bus|
|0x86||XOR||XOR A xor B => bus|
|0x88||CMP||compare A and B; set Carry status flag?|
|0x8B||INV||Invert B => Bus|
|0x8C||LSL||Shift A left 1 bit => Bus|
|0x8E||LSR||Shift A right 1 bit => Bus|
|0x90||JMP||Jump to new program counter address|
|0xA0||JCS||If the status Carry flag is set, then jump to program counter address|
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.