Electronic – Designing an instruction set for a homebrew computer

cpudesignhomebrew-cpuinstruction-set

I'm going to begin the adventure of building an 8-bit homebrew computer.

Right now, I'm considering the instruction set. SAP-1 seems a bit too sparse, so I'm designing my own.

Some facts:

  • My primary goal is to learn. I'll be building this on breadboards.
  • I plan on using 4 bit addresses (so 16 bytes of RAM).
  • The computer will have a 7-segment display for its output.
  • I want to be able to easily write simple math programs (addition, subtraction,
    multiplication, division). Do I have enough RAM for this?
  • I plan on using an ALU with zero, sign and carry status bits.
  • The system will have two registers for computation (A and B).
  • I'll have additional registers for current instruction and output.
  • Each machine code instruction will use the 4 highest bits for operation codes and the 4 lowest bits for data.

Here is the instruction set I'm thinking about. Does this make sense? Are any of these redundant/unnecessary? Is anything missing?

0000 | NOP | No-op
0001 | LIA | Immediately load data into A register
0010 | LDA | Load contents of memory address into A register 
0011 | STA | Store contents of A register into memory address
0100 | CAB | Copy contents of A register into B register
0101 | CBA | Copy contents of B register into A register
0110 | ADD | Add contents of memory address to A register
0111 | SUB | Subtract contents of memory address from A register
1000 | INC | Increment contents of A register
1001 | DEC | Decrement contents of A register
1010 | JMP | Jump unconditionally
1011 | JEQ | Jump if ALU zero bit is expressed
1100 | JNG | Jump if ALU sign bit (negative) is expressed
1101 | JCA | Jump if ALU carry bit is expressed
1110 | OUT | Copy A register into output register
1111 | HLT | Halt

Also, please let me know of any good resources for instruction set design, or general homebrew computer design.

I'm currently working through The Elements of Computing Systems and Ben Eater's YouTube videos.

Best Answer

since this is more like feedback: let's have a wiki.

  • You need some way to store the current (or next) PC. That and a JMP can form a CALL; then you need JUMP (contents of address where you stored it) to RETURN. Stack is a convenient way to handle call/return and a lot of other stuff, but quite a big change to your architecture.
  • why do you have fused load+arithmetic ops? Wouldn't a "SUBtract value of register B from register A" be significantly more handy? Otherwise you'd first have to STA to do arithmetic.
  • OUT is a fun operation, but honestly, I'd go the arm route and simply use reserved addresses for that. That is, of course, unless you need all your address space because it's really not that large.
  • integer-to-seven-segment conversion will be pretty complicated using these instructions, if you can't waste a lot of memory space on a lookup table. So, maybe have an instruction to convert a register value to the appropriate output.
  • Instead of the two A->B and B->A copy instructions, I'd go with one copy, and a swap instruction.
  • You have an operation to load 4 bits of an immediate value into an 8 bit registers. How do you set the other bits? Maybe you want a "swap high and low nibble" instruction, or even more versatile, a shift?