ALU, Data-path & Control Unit
A processor divides cleanly into two halves. The datapath holds the resources — registers, the ALU, buses and memory ports — and the control unit decides which of them are used in each clock cycle.
That division is the key to the whole topic. A micro-operation is not a mysterious primitive; it is simply the set of control signals asserted during one clock cycle, and executing an instruction means asserting a particular sequence of such sets.
The second organising fact is that the number of cycles an instruction needs is decided by resource conflicts, not by how complicated the instruction sounds. Two transfers that need the same bus cannot happen together, so they occupy separate cycles. Two transfers using disjoint resources can share a cycle.
That single rule answers most questions about cycle counts, and it also explains why adding a bus or a second memory port reduces the cycle count of specific instructions.
The third is that hardwired and microprogrammed control implement the same schedule by different means: one as combinational logic, the other as a lookup in a control memory. Speed against flexibility is the entire trade.
1. The Datapath
The datapath contains the storage and the functional units.
| Element | Role |
|---|---|
| Program counter | Holds the address of the next instruction |
| Instruction register | Holds the instruction being executed |
| Memory address register | Drives the address lines to memory |
| Memory buffer register | Holds data going to or coming from memory |
| General registers | Hold operands and results |
| ALU | Performs arithmetic and logic |
| Temporary registers | Hold intermediate values inside one instruction |
The memory address and buffer registers exist because memory is slow and external. They isolate the processor's internal timing from the memory's, so the datapath can proceed while a memory access completes.
A register transfer is written in the notation , meaning the contents of are copied into at the end of the current clock cycle. Several transfers written on the same line are simultaneous and must use disjoint resources.
The widths of the memory address and buffer registers are fixed by the memory, not by the processor's word size, and questions exploit that distinction.
The memory address register must be wide enough to name every location, so its width is the base-two logarithm of the number of addressable locations. A memory of 64 K locations needs a 16-bit address register whatever the data width.
The memory buffer register must be as wide as one addressable unit. On a byte-addressable machine with a 32-bit data bus, four bytes move per access, so the buffer register is 32 bits while the addressing granularity remains one byte.
That mismatch is why the low-order address bits are used to select a byte within a fetched word rather than being sent to the memory array at all.
2. Bus Structures
The number of internal buses limits how many transfers can happen at once, and it is the dominant factor in cycle counts.
On a single-bus datapath, only one value can move per cycle. Adding two registers therefore takes three cycles: move the first operand to a temporary input of the ALU, move the second onto the bus while the ALU computes, and move the result back.
A two-bus datapath lets two values move simultaneously, so both ALU inputs can be supplied in one cycle and the result written in the next, giving two cycles.
A three-bus datapath supplies both operands and writes the result in a single cycle, because two source buses and one destination bus operate concurrently.
The cost is wiring and multiplexer complexity, which grows quickly. This is exactly the resource-conflict rule made concrete: more buses means fewer conflicts means fewer cycles per operation, at higher area cost.
3. The ALU
The arithmetic logic unit performs the operations an instruction names, selected by function-select control lines.
An -bit ALU is built as identical bit slices sharing the select lines, with the carry chaining between slices. This regularity is why ALU width is easy to change and why carry propagation dominates its delay.
Arithmetic operations reuse a single adder. Subtraction is addition of the complement, and the same adder computes increment and decrement by forcing the carry-in and one operand.
Logic operations are performed in parallel with the arithmetic, and a multiplexer at the output selects which result to present, controlled by the operation-select lines.
Status flags summarise the result for later branch instructions.
| Flag | Meaning |
|---|---|
| Z | Result is zero |
| N | Result is negative, that is the sign bit is 1 |
| C | Carry out of the most significant bit |
| V | Signed overflow |
The carry and overflow flags are distinct and answer different questions, exactly as in the arithmetic chapter: carry detects unsigned overflow while V detects signed overflow.
A conditional branch tests these flags rather than recomputing anything, which is why comparison instructions are usually just subtractions whose result is discarded.
4. The Instruction Cycle
Every instruction passes through the same outer phases, and only the execute phase differs between instruction types.
Fetch is identical for every instruction, which is what makes it worth hardwiring and later pipelining.
The fetch sequence on a single-bus machine is three cycles:
The program counter increment shares a cycle with the memory read, because the two use disjoint resources: the increment uses the ALU or a dedicated incrementer while the memory read uses the memory bus.
Decode extracts the opcode and operand specifiers. Operand fetch depends entirely on the addressing mode, which is why an indirect operand adds a cycle relative to a direct one.
Execute performs the operation, and writeback stores the result. Some machines add an interrupt-check phase at the end of every instruction, which is why interrupts are recognised between instructions rather than during one.
5. Hardwired Control
A hardwired control unit generates control signals with combinational logic driven by the opcode, a timing counter and status flags.
Each control signal becomes a Boolean function of the current state and the instruction. The signal that loads the instruction register, for example, is asserted whenever the timing counter reaches the third fetch cycle, regardless of opcode.
The advantages are speed and area: with no memory lookup in the path, the control signals appear after a single level of gate delay.
The disadvantage is rigidity. Changing or adding an instruction means redesigning and refabricating the logic, which is why hardwired control suits small, stable instruction sets — precisely the RISC case.
6. Microprogrammed Control
A microprogrammed control unit stores the control signals in a control memory. Each word of that memory is a microinstruction, and its bits are the control signals for one clock cycle.
The control unit fetches microinstructions in sequence, using a microprogram counter, and the microroutine for each machine instruction is a small program in this internal language.
| Component | Role |
|---|---|
| Control memory | Stores microinstructions |
| Microprogram counter | Addresses the next microinstruction |
| Control address register | Holds the current microinstruction address |
| Sequencer | Decides the next address, including branches |
| Mapping logic | Converts an opcode into a microroutine start address |
The mapping logic is what connects the two levels: an opcode arrives, and the mapper produces the address in control memory where that instruction's microroutine begins.
The advantage is flexibility. Adding an instruction means writing a new microroutine, not redesigning gates, and the same hardware can implement a different instruction set entirely.
The disadvantage is speed, since every cycle now includes a control memory read. This is why complex instruction sets were microprogrammed and why RISC designs, chasing a low cycle time, returned to hardwired control.
7. Microinstruction Formats
Microinstructions differ in how densely they encode the control signals.
A horizontal microinstruction devotes one bit to each control signal. It is wide, it allows any combination of signals to be asserted simultaneously, and it needs no decoding.
A vertical microinstruction encodes signals into fields. It is narrow and needs a decoder, and because a field can name only one signal at a time, mutually exclusive signals must be grouped into the same field.
| Property | Horizontal | Vertical |
|---|---|---|
| Width | Wide | Narrow |
| Decoding | None | Required |
| Parallelism | Full | Limited |
| Control memory size | Large | Small |
| Microroutine length | Shorter | Longer |
The trade is width against length. A horizontal microprogram completes an instruction in fewer microinstructions because more can happen per cycle; a vertical one uses less memory per microinstruction but needs more of them.
Nanoprogramming inserts a second level: a short vertical microinstruction indexes a table of horizontal control words, capturing the density of vertical encoding while retaining full parallelism, at the cost of an extra memory access.
Sequencing within a microprogram needs its own addressing decisions, and two schemes appear.
In the next-address field scheme, every microinstruction carries the address of its successor explicitly. Microinstructions can then be placed anywhere in control memory, and branching costs nothing extra, but every word pays for the address field.
In the incremented-counter scheme, a microprogram counter advances by default and only branch microinstructions carry an address. Words are narrower, but microroutines must be laid out contiguously.
The choice mirrors the horizontal-versus-vertical trade exactly: pay width on every word, or pay length and layout constraints instead.
8. Worked Examples
Example 1. On a single-bus datapath, write the micro-operations for the instruction ADD R1, R2 meaning , and count the cycles.
Only one value can travel on the bus per cycle, so each transfer needs its own cycle unless it uses a different resource.
Cycle 1: , moving the first operand into the ALU's holding register.
Cycle 2: , placing on the bus as the ALU's second input and latching the sum in the output register .
Cycle 3: , returning the result.
The execute phase takes 3 cycles.
Adding the 3 fetch cycles gives 6 cycles for the whole instruction.
On a three-bus datapath the entire execute phase collapses to a single cycle, since both operands travel on two source buses and the result returns on the destination bus simultaneously. That is the resource-conflict rule made concrete.
Example 2. A machine has 32 control signals, a control memory of 1024 words, and uses horizontal microinstructions with a next-address field. What is the microinstruction width, and how large is the control memory in bits?
The control signal field needs one bit per signal in a horizontal format, so 32 bits.
The next-address field must be able to name any of the 1024 control memory locations, requiring bits.
The microinstruction width is bits.
The control memory holds 1024 words of 42 bits, which is bits, about 5.25 KB.
Note how the horizontal format's cost appears here. A vertical format grouping the 32 signals into, say, 5 fields of 3 bits each would need only 15 signal bits plus the 10 address bits, cutting the width to 25 bits and the memory to 25,600 bits — but at the cost of asserting at most 5 signals per cycle instead of all 32.
Example 3. Compare the number of cycles to execute LOAD R1, (R2) on a single-bus and a two-bus datapath, including fetch.
Fetch takes 3 cycles on a single-bus machine as derived earlier, and can take 2 on a two-bus machine, since the program counter increment and the address transfer no longer contend.
For the execute phase on the single-bus machine:
Cycle 1: , sending the pointer to memory. Cycle 2: , reading the operand. Cycle 3: , storing it.
That is 3 execute cycles, giving 6 in total.
On the two-bus machine, cycles 1 and 3 remain distinct because both need the single memory port in sequence, but the fetch saving carries through, giving 5 in total.
The instructive point is that a second bus does not help a memory-bound instruction as much as it helps a register-to-register one, because the bottleneck moved from the internal bus to the memory port. This is a general pattern: adding a resource helps only until a different resource becomes the constraint.
Example 4. Why is the program counter increment placed in the same cycle as the memory read during fetch?
Because the two operations use disjoint resources and therefore do not conflict.
The memory read occupies the memory address register, the memory bus and the memory buffer register. The increment occupies the program counter and either a dedicated incrementer or the ALU.
Nothing is shared, so both can be driven by the same set of control signals in one clock cycle, and the fetch phase costs 3 cycles rather than 4.
The consequence appears in branch instructions. By the time the instruction is decoded, the program counter already holds the address of the next instruction, which is why PC-relative displacements are measured from there and why a branch simply overwrites the program counter rather than computing from scratch.
Had the increment been deferred, the fetch would be one cycle longer on every single instruction, which is precisely the kind of cost that a per-instruction phase cannot afford.
Example 5. A microprogrammed control unit has 40 control signals, of which the signals divide into 4 mutually exclusive groups of sizes 10, 8, 12 and 10. Compare the horizontal and vertical microinstruction widths.
Horizontal format: one bit per signal, so 40 bits for the control field.
Vertical format: each group becomes a field wide enough to name any signal in it, plus one code for "no signal in this group".
Group of 10 needs to name 11 possibilities, requiring 4 bits. Group of 8 needs 9 possibilities, requiring 4 bits. Group of 12 needs 13 possibilities, requiring 4 bits. Group of 10 needs 11 possibilities, requiring 4 bits.
The vertical control field is bits, against 40 horizontal.
The saving is 60 per cent of the control field width, and it is available only because the signals within each group are genuinely mutually exclusive — no two can ever need asserting in the same cycle.
If any two signals in a group did need simultaneous assertion, the vertical encoding would make it impossible and the microprogram would need an extra cycle, which is exactly the width-against-length trade.
Example 6. Explain why interrupts are recognised between instructions rather than during one.
Because an instruction leaves the machine in a well-defined state only at its boundaries.
Partway through an instruction, temporary registers hold intermediate values, the memory buffer may hold a partially processed word, and the program counter may already have advanced past the instruction being executed. Saving and restoring all of that would require the interrupt mechanism to know the internal microstate of every instruction.
At an instruction boundary, by contrast, the entire visible state is the architectural registers and the program counter. Saving those is sufficient to resume exactly where execution left off, which is what makes interrupt handling tractable.
The cost is interrupt latency: a long instruction delays recognition until it completes. This is one reason instruction sets avoid unboundedly long instructions, and why those that have them — block move or string operations — are usually made interruptible by recording partial progress in architectural registers rather than internal ones.
Summary
The datapath holds resources and the control unit schedules them; a micro-operation is the set of control signals asserted in one clock cycle.
Cycle counts are decided by resource conflicts. Transfers sharing a bus or a memory port must occupy separate cycles; transfers using disjoint resources can share one.
A single-bus register addition takes three cycles, a two-bus version two, and a three-bus version one — at rising wiring cost.
An -bit ALU is identical bit slices sharing the select lines, with the carry chain dominating its delay. One adder serves addition, subtraction, increment and decrement.
The Z, N, C and V flags summarise a result, with C detecting unsigned overflow and V signed overflow, and conditional branches test them rather than recomputing.
Fetch is identical for every instruction and takes three cycles on a single-bus machine, with the program counter increment sharing the memory-read cycle because the resources are disjoint.
Hardwired control generates signals combinationally: fast, compact and rigid. Microprogrammed control reads them from a control memory: flexible and slower, with mapping logic converting an opcode into a microroutine address.
Horizontal microinstructions are wide, need no decoding and allow full parallelism; vertical ones are narrow, need a decoder and restrict mutually exclusive signals to one per field. The trade is microinstruction width against microprogram length.
Interrupts are recognised at instruction boundaries because only there is the visible state sufficient to resume from.