My Bentium Pro computer is a Ben Eater inspired machine which uses many of the same ideas and many identical or very similar circuits. My intention with these blog posts was to write about the things I have added or done differently and leave the same/similar stuff for people to copy from Ben.
I also had the assumption that my build would serve as inspiration and a source of ideas for what could be done to extend Ben’s computer or build a more complex version.
While I’m still not sure anyone wants to build a clone of the Bentuim Pro I am realising that there’s a demand for a complete description along with schematics. So I’m now going to go ‘back to the beginning’, starting with the ALU which I’ve been writing about recently, to describe the entire system in detail and with full schematics which will include a Github repo for both the schematics along with anything else which may be of interest/use to the reader.
A side note as far as schematics is that I’ve never drawn one before. I played with Fritzing a few months ago and hated it (part of the reason I was planning not to give schematics) but I’ve been using KiCad recently which is an absolute joy and makes me realise I’ve chosen the wrong career in life. Since I’m a newbie I’m sure I’m making some glaring schoolboy errors for which I apologise and I’d appreciate any helpful comments, especially on style etc. which I’m not appreciating.
When I gave my introduction to the ALU recently I feel as though I glossed over the general principles on how it functions. I hope this block diagram explains things a bit better.
The ALU uses two internal, registers, W and Z, for storing operands. These registers can read from the bus but not write to it. These registers are then passed, via a pair of internal busses, to each of the functional units. The functional units being the adder for addition and subtraction, the logic units for AND, OR, XOR operations and the shift/rotate unit for, left and right shift and rotate operations.
These functional units ‘calculate’ their respective output. Each operation within the functional units has a bus transceiver for output to the system bus. Thus each functional unit is always active and the control logic determines which unit’s output is needed for the current operation and enables that units bus transceiver to write that output to the bus.
There is also a 4-bit flags register and associated circuitry (not shown in the block diagram) to evaluate the flag values to be written to the flags register and also circuitry to feed the carry flag as input to the other units as needed.
The W And Z Registers
The W and Z registers, as stated above, are purely internal to the ALU and invisible to the programmer, although the control logic can use the W register as a temporary register, which will be needed for CALL to subroutine operations.
In reference to Ben’s original design my W register is equivalent to his A register and my Z register is equivalent to his B register.
The design of these registers is identical to Ben’s with each using a pair or 74LS173 4-bit latches. The Z register however, can be independently cleared (the z_clear control signal) which is needed for the INCrement and DECrement operations as well as for the temporary storage ability. (The temporary storage feature will simply add 0 to the value stored in W).
The W and Z registers each output onto one-way, permanently on busses which pass to the other functional units (adder, logic, shift/rotate). (The shift/rotate units only operate on the W register).
The Adder Circuit
The ALU can actually perform add and subtract with and without carry as well as increment (add one) and decrement (subtract one) operations but this is all done by manipulating the carry in and Z register with no changes needed directly to the adder. This is discussed in my post about adding extra operations to Ben’s ALU.
Looking at the circuit diagram you will also see XOR gates inverting the raw_carry_in input and the carry_out output if the operation is a subtraction. The function of these is detailed in my blog posts about adding extra operations to Ben’s ALU and the flags register respectively.
The carry_out and carry_in outputs are both fed out to the carry selection circuit in the flags unit as possible values to write to the carry flag. Bit 7 of the result from the adders is fed, as the adder_bit_7 signal, to the negative flag in the flags register to signify that the result of a two’s complement operation was negative. For an unsigned operation this value is meaningless. These lines are explained in more detail in my post about the flags register.
The functioning of the logic units is pretty simple. Each bit of the W and Z busses is fed into an array of logic gates and the outputs fed to their respective bus transceiver for output to the system bus.
The only thing of note here is the xor_bit_7 output which is fed back to the flags unit to be used in calculating the overflow flag. Again this is explained in my post on the flags register.
Shift And Rotate Operations
The shift and rotate circuit is a little more interesting.
All operations happen against the W register. Again there’s a bus transceiver for output of each of the left and right operations. The appropriate lines from the W bus are fed directly to the inputs of each transceiver but shifted one bit to the right or left. All that’s left to do is shift the correct value into the remaining bit.
This is done with a 74LS153 4-bit selector/multiplexer. This chip allows the selection of one of four possible inputs (I0 to I3) depending on a two-bit selector input (S0 and S1). The chip contains two ‘units’ and I’m using one unit for each direction. The selectors (S0, S1) apply to both units at the same time.
For a right shift/rotate operation the four possible input values are (with the equivalent z80 opcodes) :
- carry flag (rotate through carry): RR/RRA
- W bit 0 (rotate with carry): RRC/RRCA
- 0 (shift logical): SRL
- W bit 7 (shift arithmetic – see below): SRA
For a left shift/rotate operation the four possible input values are:
- carry flag (rotate through carry): RL/RLA
- W bit 7 (rotate branch carry): RLC/RRLA
- 0 (shift arithmetic): SLA
- 1 (shift logical. Not really needed, but we have the input so may as well use it <g>. On the z80 this is an undocumented instruction usually referred to as SLL): SLL
The diagram below shows each of the operations visually:
The shift right arithmetic operation preserves the value of bit 7. Why might this be useful? Think about two’s complement binary. Bit 7 is the sign bit so if we preserve it then we preserve the sign of the value and the operation as a whole gives us a two’s complement divide by two which works with both positive and negative numbers. Neat. This can be extended across multiple bytes by using the rotate right through carry (RR/RRA) operation on the less significant byte(s).
The ‘spare’ bit from both left and write operations – the bit which ‘falls out’ the other end – get fed back to the carry flag. You won’t see these output from the schematic though as they are fed to the flag circuitry directly from the W register which keeps the wiring shorter. And bit 7 of the W register is also used as part of the overflow flag calculation. You can see these two bits paring off the W bus on the ALU overview schematic (see next section). For discussion of the carry out circuitry see my post on the flags register.
The 74LS153, as described, uses two bits to select the desired operation. In the Bentium Pro I have a very limited number of control lines available so I’m reusing the use_carry and carry_set signals from the carry select circuit. Since we won’t be using both the shifter and the adder at the same time this won’t cause any problems. The choice if which line is used for which input is purely arbitrary.
Talking of the ALU overview schematic and the carry select circuit you can see this circuitry towards the bottom-left of the schematic below. This circuit is described in my post on expanding the adder but, for the schematic, the XOR with the subtract signal has been moved to within the adder unit, where it makes both logical sense – being paired with the invert carry out on subtraction – and simplifies the overview schematic.
And finally, and for completeness, here are the schematics for the flags section of the ALU.
UPDATE: I’ve corrected the carry select circuit in the overview schematic