System/1's control unit, as in any CPU, is responsible for decoding instructions and despatching the appropriate control signals to the execution units. System/1 uses a hardwired control unit — control signals are generated through a tree of logic gates that take an instruction as input — as opposed to a more modern microcoded design. Although microcode is more flexible, and no doubt easier to design and debug, I felt like doing things the hard way; besides, it's far more satisfying this way!
The design of the control unit is split into three main sections: the instruction word register, the routing of signals between the A, B and R buses, and the control logic itself. To take these in order:
The instruction word register is built up from four 74HC299 shift registers (as they have a control input to allow them to only shift during the appropriate phases of the execution cycle — and I had a surplus!), with a 74HC153 4:1 mux/selector allowing the immediate field of an instruction to be isolated. This kicks in after the instruction has been read; when the bottom 16 bits of the instruction contain immediate data, they can be shifted out independently of the top 16 bits (which contain the opcode and source/destination register information, and so much remain constant during the execution of the instruction). Since the immediate field may contain a signed operand, depending on the instruction, the '153 is wired such that it feeds the top of the field with either a zero (for an unsigned value) or the most-significant bit of the operand (to sign-extend it). During the fetch cycle, of course, the data being shifted down from the top half of the register is presented as-is.
The top eight bits of the instruction word contain the main opcode and four 'subop' bits; the main opcode is decoded using a 74HC4514 one-of-sixteen decoder to drive the instruction signal lines into the control logic, whereas the subop bits are presented directly to the system's backplane for other modules such as the ALU, flags/condition evaluator and shifter to interpret as they see fit. The control logic also uses some of the subop bits to alter the behaviour of some opcodes — for instance, SUBOP0 of a memory access instruction indicates whether the memory address should come from a register or the immediate field.
The next-most-significant four bits of the instruction indicate the destination register for any operations that produce a result, and the four below that represent the (first) source register; both of these values are routed to the backplane for the register file to consume, through a tristate buffer so that the backplane can be left undriven when the control unit isn't executing an instruction. Another buffer handles the other main control lines similarly; this arrangement allows the front panel interface to take control of the register file and memory interface when the machine is halted.
Finally, the second source register (for instructions that use one) is identified by the top four bits of the bottom half of the instruction word. This overlaps with the immediate field, so instructions can only use a second source register if they don't take an immediate value and vice versa.
The signal routing section of the control unit is very straightforward; apart from the buffer for the main control lines, described above, it consists of a set of tristate buffers that are wired to allow the backplane's A, B and R buses to be driven from various signal sources:
The control logic is the hairiest section of the design; it has to generate all the control signals for the rest of the system based on the sixteen decoded instruction inputs and (for some instructions) the subop bits and execution phase signals. The resulting matrix of outputs did rather illustrate the advantages of a microcoded design, but turning a table of ticks into a ROM image is far too much like programming for comfort.