Arithmetic Logic Unit
The ALU, of course, is rather fundamental to any computer, and so it was the idea of building one that operates on data in a bit-serial fashion that really drove the design of the rest of the system. The primary advantage to this approach is that it requires dramatically less wiring than running full 32-bit-wide data paths throughout the system, but of course the trade-off is in speed — every operation that acts upon data needs to take 32 clock cycles to complete...
The core of System/1's ALU is a simple 1-bit adder, which takes the single bits present on each of the A and B buses, along with a carry input, and generates a single-bit result and carry. The carry output is latched so that it can be fed back in as the carry input of the next bit, although of course this latched value is ignored for the first bit of a cycle.
Once we have that, we may as well extend it so that the carry input for the first cycle can optionally be preset to 1 and the B input forced to all-zeroes — that gives us 'add' and 'increment' operations — and then by optionally inverting the B input and the sense of the preset-carry signal we get two's-complement 'decrement' and 'subtract' as well.
Finally, a handful of the spare gates can be pressed into service to give us AND, OR, XOR and NOT operations, so adding a multiplexer at the output gives us a total of eight ALU operations to work with. The final carry output is gated so that the logic operations never generate a carry, and also inverted when performing a subtraction — the initial design didn't do this, and the resulting sense of the carry for a subtraction struck me as counter-intuitive otherwise!
In order to make life a little easier for the control unit and the rest of the system, the ALU operation code (which is provided on the SUBOPn signals, which in turn come direction from the instruction word) are gated with an ALU_OPVALID signal; if this is low, the ALU is forced into performing an 'add' operation (which corresponds to SUBOP=0b0000). Since the control unit will need to perform additions for its own purposes rather frequently — during the fetch cycle, and for branches and jumps — this allows it to only assert ALU_OPVALID during the execution of actual ALU instructions, and not need to worry about the SUBOP lines changing during instruction fetch etc.
Related Build Log Entries
- 26th September, 2014 (backdated) - Prototyping and building the ALU