We now come to crunch-time. Having spent the best part of a week thinking about the Instruction Set and the Addressing Modes - I now have to review the wish-list and determine what can easily be implemented in readily available hardware. I need to make some hard choices of what is realistic and what will be left out for a later machine (possibly on a FPGA where resources are less limited). It's time to cut my coat according to my cloth.
This will mean examining every proposed instruction in detail and working out the data paths and internal cycles required just to make the instruction function. It's good that I only have 31 instructions to analyse and many of them fall into convenient groups.
Suite-16 already has some self-imposed limitations. The accumulator always forms one of the operands to the ALU. This makes it a whole lot simpler and you eliminate the need for a whole lot of data selectors connecting the register file to the ALU. Unlike an MSP430 where you can happily do an instruction like ADD R4,R5 our destination register is always the accumulator.
The register file I have selected has tri-state outputs, and this forms a natural data selector - during a register read cycle only the data from the register currently being addressed will appear on the register bus.
For direct addressing, the contents of the selected register is put onto the ALU bus. The register file already has internal address decoding, so the 4-bits needed to select the register can come directly from the bit-field in the instruction register.
For register indirect addressing we need to gate the register output bus across to an address register and gate the memory data bus across to the ALU bus.
Hardware limitations mean that there is currently no mechanism to transfer a memory read directly into a register. We need to load the accumulator from memory first and then store the accumulator to the register.
Arithmetic and Logic Instructions
These are probably the easiest to implement as they use only the accumulator AC and a designated register Rn as the operands. The result of the operation is deposited into the Accumulator
8n AND Rn AND AC = AC & Rn 9n OR Rn OR AC = AC | Rn An ADD Rn ADD AC = AC + Rn Bn SUB Rn SUB AC = AC - Rn Cn CPR Rn Compare AC = AC - Rn Fn XOR Rn XOR AC = AC ^ Rn
It has been stated that the 16 registers are general purpose and R0 is the accumulator.
However, because of the nature of the accumulator, and its unique relationship to the ALU, and the desire to clear it, complement it, increment it or decrement it - it is probably best that it exists outside of the register file - i.e. as a separate register.
This means that opcodes 80, 90, A0 etc can detect the "0" and use the payload byte to form a zeropage memory address, and use a word from memory instead of using the Rn as the 2nd operand.
This access to zeropage memory could also be used for the direct addressing mode instructions:
0n --- -- 1n SET Rn Set Constant Rn = @(PC+1) 2n LD Rn Load AC = Rn 3n ST Rn Store Rn = AC
It would be useful to be able to directly address zeropage memory - with the address contained in the instruction:-
20nn LD AC, (nn) or more simply LD @nn
30nn ST (nn), AC ST @nn
After an instruction has been fetched, and is latched into the Instruction Register, the PC can be tristated and the Address Bus can be driven from a Memory Address Register MAR. The MAR is responsible for putting the effective address onto the Address bus. This leads to the added complication of the Von Neumann model - where program and data are stored in a single, unified memory space, and the fetch and execute cycles have different addressing requirements to the memory.
Several of the addressing modes require the PC or a register to be modified by an index X. There are also the requirements of auto incrementing and auto decrementing of registers.
Fortunately when we are addressing memory, the ALU is generally not being used to operate directly on operands. We can use the ALU to calculate the new effective address by modifying the effective address by either adding a signed displacement to the selected register, or using the ALU to add 1 or subtract one from the selected register. It sounds simple - but will probably be challenging to implement in hardware.