Skip to main content
@shmVirus

Control Unit Design

Design hardwired CPU control as a finite-state machine: specify the datapath, derive microoperations and control signals, and implement one-hot, encoded, PLA, or ROM controllers.

Updated

Learning objectives

  • Separate a digital system into its datapath and control unit
  • Translate an algorithmic flowchart into a control-state diagram and timed microoperations
  • Derive control words, next-state equations, and flip-flop excitation equations
  • Trace hardwired controllers for signed addition/subtraction and shift-and-add multiplication
  • Compare one-hot, encoded, PLA, and ROM control implementations

Prerequisites

  • Datapath and Microoperations
  • Computer Arithmetic

A processor datapath can add, complement, shift, load, and clear values, but it does not decide when those operations happen. The control unit supplies that sequence. It observes an operation request and datapath status, enters a state, asserts the corresponding control signals, and moves to the next state on a clock edge.

This chapter develops that idea through two complete hardwired-control examples. The first uses one flip-flop per state to control sign-magnitude addition and subtraction. The second encodes four multiplication states in two flip-flops. The examples expose the same reusable design path:

algorithm -> datapath -> state diagram -> control table -> Boolean logic

Central idea: the datapath performs microoperations; the controller sequences them. A correct arithmetic algorithm is not yet a hardware design until every operation has a destination register, a control signal, a state, and a clock edge.

Control-Unit Foundations

TermController meaning
StateThe controller’s stored memory of which step is currently active.
Status inputA datapath condition, such as zero, sign, carry, or a tested multiplier bit.
Control signalOne bit that selects a route, ALU function, register load, shift, or clear.
Control wordAll control signals asserted together during one state.
Next-state logicCombinational logic that chooses the state loaded at the next clock edge.

Datapath and controller

The two parts form a synchronous feedback loop. The controller says what to do now; the datapath reports what just happened.

Control loop in which a state register drives control logic, the control word operates the datapath, and datapath status returns to the next-state logic
Requests and status choose the next state. The current state chooses the control word. The clock commits both datapath and state changes.

The visual key is consistent throughout the chapter: blue identifies stored state and registers, teal identifies control and decisions, amber identifies arithmetic or datapath actions, and purple identifies status, correction, and shift operations. The colours explain hardware roles; the connections and branches retain the structure of the source figures.

PartContainsReceivesProduces
DatapathRegisters, ALU, shifter, buses, status flip-flopsOperand data and control signalsResults and status conditions
ControllerState register and next-state/output logicRequests, status conditions, and clockALU selects, register enables, and completion signals

A microoperation is an elementary register action completed in one clock interval, such as AA+BA \leftarrow A+B, E0E \leftarrow 0, or AQshr(EAQ)AQ \leftarrow \operatorname{shr}(EAQ). Register-transfer notation names the destination on the left and the value computed during that interval on the right.

Suppose A=01012A=0101_2 and B=00112B=0011_2. While the controller is in an “add” state, it selects the ALU’s add function and asserts the load enable for AA. The ALU output changes combinationally to 1000, but the stored value of AA remains 0101 until the active clock edge. At that edge, AA becomes 1000 and the controller enters its next state.

during the interval: current state -> control signals -> ALU result
at the clock edge:   registers load result; state register loads next state
after the edge:      new state and new register values are visible

This “compute during the interval, commit at the edge” model explains why a status value written by one state is normally tested by the following state.

From an algorithm to hardware

  1. Write the algorithm. Show operations, decisions, repetition, and termination.
  2. Specify the datapath. Choose registers and functional units, then name every control input and status output.
  3. Assign control states. A state groups compatible microoperations that can occur on one active clock edge.
  4. Draw transitions. Label every conditional edge and account for every input combination.
  5. Create the output table. For each state, identify the required datapath control word.
  6. Choose an encoding. Use one-hot, binary, Gray, or another justified assignment.
  7. Derive and verify logic. Obtain next-state and output equations, then trace normal and boundary cases.

The conversion from flowchart to state diagram is not unique. Two controllers may implement the same algorithm with different state counts. A valid choice must still respect hardware constraints: a register cannot be loaded before its source is ready, a status bit written on an edge cannot be tested before the following state, and incompatible transfers cannot share one resource in the same cycle.

Example 1: Sign-Magnitude Addition and Subtraction

Problem and notation

Two sign-magnitude operands are split into sign bits As,BsA_s,B_s and magnitude registers A,BA,B. The controller accepts separate add and subtract requests.

With a four-bit magnitude, the representation has one separate sign bit:

ValueSignMagnitudeWritten as
+5+5001010 0101
5-5101011 0101
+0+0000000 0000
0-0100001 0000

The magnitude is ordinary unsigned binary. The sign bit is not part of a two’s-complement word. This is why the hardware must decide separately what to do with the signs and the magnitudes—and why sign-magnitude has two encodings for zero.

SymbolMeaning
qaq_aRequest addition
qsq_sRequest subtraction
S=AsBsS=A_s\oplus B_s0 when the effective signs match; 1 when they differ
EEALU end carry/status flip-flop
CoutC_{out}Current ALU carry output
xxReady/initial-state output

Subtraction is reduced to addition by first complementing BsB_s. The controller can then apply one common rule: add magnitudes when the effective signs match; otherwise subtract the smaller magnitude from the larger one.

The design assumes qaq_a and qsq_s are mutually exclusive request pulses. If an interface can assert both—or hold either request high after completion—the controller needs explicit priority and acknowledgement rules.

Four sign-magnitude addition cases showing when magnitudes are added and when the larger magnitude is reduced by the smaller
The sign bits choose the arithmetic path. In an unlike-sign case, the operand with the larger magnitude supplies the result sign.
Flowchart for sign-magnitude addition and subtraction, including sign comparison, magnitude subtraction, and result correction
Sign-magnitude add/subtract algorithm. The subtraction request first reverses the effective sign of operand B.

Reading the algorithm

  • With equal effective signs, compute AA+BA\leftarrow A+B. The sign AsA_s already belongs to the result, and ECoutE\leftarrow C_{out} records magnitude overflow.
  • With unlike signs, compute AA+B+1A\leftarrow A+\overline B+1. This is ABA-B using two’s-complement addition. Ordinary signed overflow is not possible in this branch.
  • If the subtraction produces an end carry, there was no borrow: the magnitude in AA is already non-negative. Clear EE and retain AsA_s.
  • If there is no end carry, then A<B|A|<|B|. The register contains a negative two’s-complement intermediate value. Complement and increment AA to recover its magnitude, then complement AsA_s so the sign follows the operand with the larger magnitude.

The correction is split into AAA\leftarrow\overline A and AA+1A\leftarrow A+1 because the available ALU provides complement and increment, but not a single “two’s complement” function. When the magnitudes are equal, the subtraction magnitude is zero; a practical design should also define whether zero is canonicalised to a positive sign.

Numeric examples: every arithmetic path

Use four-bit magnitude registers throughout these examples:

OperationEffective sign relationMagnitude calculationResult
+5+(+3)+5+(+3)Same0101 + 0011 = 1000+8+8
5+(3)-5+(-3)Same0101 + 0011 = 10008-8
+5+(3)+5+(-3)Unlike, A>B\lvert A\rvert>\lvert B\rvert0101 − 0011 = 0010+2+2
+3+(5)+3+(-5)Unlike, A<B\lvert A\rvert<\lvert B\rvert0101 − 0011 = 00102-2

The datapath does not contain a magnitude comparator. It discovers which magnitude is larger from the carry produced by two’s-complement subtraction.

For +5+(3)+5+(-3), As=0A_s=0, Bs=1B_s=1, so S=1S=1 and the controller subtracts:

  A              0101
  complement B   1100
  input carry    0001
                 ----
                 1 0010

The stored magnitude is 0010 and E=1E=1. End carry 1 means no borrow, so AB|A|\ge|B|; the sign stays As=0A_s=0, producing +2+2.

For +3+(5)+3+(-5), the same circuit produces a negative intermediate result:

  A              0011
  complement B   1010
  input carry    0001
                 ----
                   1110   E = 0

  complement     0001
  increment      0010
  flip A_s       0 -> 1

No end carry means a borrow occurred and A<B|A|<|B|. States T6T_6 and T7T_7 convert 1110 to magnitude 0010 and reverse the sign, producing 2-2.

A subtraction request only changes the effective sign of BB. For example, +5(3)+5-(-3) first changes BsB_s from 1 to 0; the controller then sees equal signs and adds the magnitudes, obtaining +8+8.

Finally, four magnitude bits can hold at most 1515. For +9+(+8)+9+(+8), 1001 + 1000 = 1 0001: AA receives 0001, while E=1E=1 reports that the mathematical result 1717 did not fit. The carry must be interpreted as overflow in the equal-sign addition path, not as a fifth magnitude bit silently discarded.

Datapath specification

Block diagram separating the A and B registers, ALU, E carry flip-flop, sign controls, and finite-state controller
The controller drives the datapath and receives requests plus the derived sign comparison and stored carry status.

The ALU receives AA, BB, the selection word s2s1s0s_2s_1s_0, and input carry CinC_{in}. Signal LL loads the ALU result into AA and CoutC_{out} into EE. Three direct controls handle operations outside the ALU:

ControlDatapath action
yyComplement BsB_s
zzComplement AsA_s
wwClear EE

The controller inputs are qaq_a, qsq_s, SS, and EE. Although AsA_s and BsB_s enter the comparison logic physically, using S=AsBsS=A_s\oplus B_s reduces the controller’s sign decision to one variable.

Control-state diagram

Eight-state controller for sign-magnitude addition and subtraction with transitions labelled by operation request, sign comparison, and end carry
One valid state diagram. Other state assignments can implement the same flowchart if their timing remains correct.

The state sequence is deliberately explicit:

  • T0T_0 is idle and asserts xx. It stays there while both requests are low.
  • A subtract request enters T1T_1 to complement BsB_s; an add request can go directly to T2T_2.
  • T2T_2 tests the updated sign relation SS. Matching signs select T3T_3; unlike signs select T4T_4.
  • T3T_3 adds magnitudes and finishes. T4T_4 subtracts magnitudes and stores the end carry.
  • T5T_5 clears overflow status and chooses whether result correction is needed.
  • T6T_6 and T7T_7 form the two’s complement of AA and reverse AsA_s before returning to idle.

The value ECoutE\leftarrow C_{out} is written on the edge that leaves T4T_4. Therefore the controller tests EE in T5T_5, not in T4T_4. Clearing EE while leaving T5T_5 is safe: the old value selects the outgoing edge during the interval, and the edge simultaneously stores the next state and clears EE.

Clock trace: positive 3 plus negative 5

The numeric example becomes a hardware execution when placed on clock intervals. Initial values are As=0A_s=0, A=0011A=0011, Bs=1B_s=1, B=0101B=0101 and qa=1q_a=1:

IntervalCurrent stateCondition seen during intervalTransfer committed at edgeState after edge
0T0T_0qa=1q_a=1NoneT2T_2
1T2T_2S=AsBs=1S=A_s\oplus B_s=1NoneT4T_4
2T4T_4Unlike signsA1110, E0A\leftarrow1110,\ E\leftarrow0T5T_5
3T5T_5Stored E=0E=0E0E\leftarrow0T6T_6
4T6T_6Correction requiredA1110=0001A\leftarrow\overline{1110}=0001T7T_7
5T7T_7Final correctionA0010, As1A\leftarrow0010,\ A_s\leftarrow1T0T_0

There are six state intervals from accepting the request to becoming ready again. Only three intervals change arithmetic data: T4T_4, T6T_6, and T7T_7. The other intervals route the controller using conditions that are stable for the entire interval.

State outputs and microoperations

StateMicrooperationxxs2s1s0s_2s_1s_0CinC_{in}LLyyzzww
T0T_0Initial/ready state100000000
T1T_1BsBsB_s\leftarrow\overline{B_s}000000100
T2T_2No transfer; evaluate SS000000000
T3T_3AA+B, ECoutA\leftarrow A+B,\ E\leftarrow C_{out}000101000
T4T_4AA+B+1, ECoutA\leftarrow A+\overline B+1,\ E\leftarrow C_{out}001011000
T5T_5E0E\leftarrow0000000001
T6T_6AAA\leftarrow\overline A011101000
T7T_7AA+1, AsAsA\leftarrow A+1,\ A_s\leftarrow\overline{A_s}000011010

The load signal LL must be 1 whenever an ALU result is intended to change AA (and, where relevant, EE). In other states, the ALU may still produce a combinational value, but it has no architectural effect.

One-hot implementation

Assign one D flip-flop to each state and use the flip-flop output itself as the timing variable TiT_i. Exactly one state bit is high. To obtain a D-input equation, AND each incoming transition condition with its source state and OR all paths entering the destination:

DT0=qaqsT0+T3+ET5+T7DT1=qsT0DT2=qaT0+T1DT3=ST2DT4=ST2DT5=T4DT6=ET5DT7=T6\begin{aligned} D_{T_0} &= \overline{q_a}\,\overline{q_s}T_0 + T_3 + ET_5 + T_7 \\ D_{T_1} &= q_sT_0 \\ D_{T_2} &= q_aT_0 + T_1 \\ D_{T_3} &= \overline ST_2 \\ D_{T_4} &= ST_2 \\ D_{T_5} &= T_4 \\ D_{T_6} &= \overline ET_5 \\ D_{T_7} &= T_6 \end{aligned}

Read each equation as an answer to “when must this state become 1?” For example:

  • T2T_2 is entered from T0T_0 when qa=1q_a=1, or from T1T_1 unconditionally. Therefore DT2=qaT0+T1D_{T_2}=q_aT_0+T_1.
  • T6T_6 is entered only from T5T_5 when E=0E=0. Therefore DT6=ET5D_{T_6}=\overline ET_5.
  • T0T_0 has four incoming paths: its idle self-loop, completion from T3T_3, the E=1E=1 branch from T5T_5, and completion from T7T_7. OR-ing those products gives DT0D_{T_0}.

Output equations are even more direct: OR the states whose table row contains 1 for that signal.

x=T0,s2=T6,s1=T4+T6,s0=T3+T6,Cin=T4+T7,L=T3+T4+T6+T7,y=T1,z=T7,w=T5.\begin{aligned} x&=T_0, & s_2&=T_6, & s_1&=T_4+T_6, & s_0&=T_3+T_6,\\ C_{in}&=T_4+T_7, & L&=T_3+T_4+T_6+T_7, & y&=T_1,\\ z&=T_7, & w&=T_5.&& \end{aligned}

As a quick check, let the current state be T4T_4. Then only T4=1T_4=1, so s2s1s0=010s_2s_1s_0=010, Cin=1C_{in}=1, and L=1L=1. Those are exactly the controls required for AA+B+1A\leftarrow A+\overline B+1. In T2T_2, none of the ALU or load equations is asserted; that state exists only to choose the next path.

One-hot control uses eight flip-flops here, but the logic is regular and can be read directly from the state diagram. A compact binary assignment would use only three flip-flops, at the cost of decoding states and usually more intricate next-state logic.

Example 2: Shift-and-Add Binary Multiplication

Datapath algorithm

Let BB hold the multiplicand, QQ hold the multiplier, AA accumulate the partial product, EE hold the adder carry, and PP count the remaining bit positions. The final 2k2k-bit magnitude appears in the concatenated registers AQAQ. The result sign is AsBsQsA_s\leftarrow B_s\oplus Q_s.

E, A, and Q registers arranged as one composite right-shift register, with B feeding an adder whose output returns to A
The adder changes A only when Q₁ is 1. The following right shift treats E, A, and Q as one connected bit string.

For k=4k=4, the shift register is nine bits wide: one carry bit, four accumulator bits, and four multiplier bits. If EAQ = 0 0101 0011, one right shift produces 0 0010 1001. The old least-significant bit of AA becomes the new most-significant bit of QQ; the old EE becomes the new most-significant bit of AA. This is why EE must participate in the shift rather than being discarded after an addition.

Flowchart for a sequential shift-and-add binary multiplier
For each multiplier bit, conditionally add B to A, decrement the counter, and shift the composite register EAQ right.

On a multiply request qmq_m:

  1. Initialise A0A\leftarrow0, E0E\leftarrow0, PkP\leftarrow k, and set the product sign.
  2. Inspect Q1Q_1, the current least-significant multiplier bit. If it is 1, perform AA+BA\leftarrow A+B and ECoutE\leftarrow C_{out}.
  3. Always perform PP1P\leftarrow P-1.
  4. Shift the concatenated value: AQshr(EAQ)AQ\leftarrow\operatorname{shr}(EAQ), then clear EE.
  5. If P0P\ne0, repeat from the bit test; otherwise return to idle.

Each shift places one newly settled product bit into QQ and exposes the next multiplier bit at Q1Q_1. After kk iterations, AA contains the most-significant half and QQ the least-significant half. PzP_z denotes the zero test: Pz=1P_z=1 exactly when P=0P=0.

The useful invariant is: before iteration ii, the unprocessed multiplier bits remain in QQ, while the partial product accumulated so far occupies the left side of AQAQ. Testing Q1Q_1 decides whether the current power-of-two copy of BB contributes to the product; the shift then aligns the registers for the next bit.

Four-state controller

Four-state finite-state controller for the sequential multiplier
The conditional add and unconditional decrement share state T2; the condition qualifies only the load operation.
StateRegister transfers
T0T_0Initial state; wait for qmq_m
T1T_1AsBsQs, A0, E0, PkA_s\leftarrow B_s\oplus Q_s,\ A\leftarrow0,\ E\leftarrow0,\ P\leftarrow k
T2T_2If Q1=1Q_1=1: AA+B, ECoutA\leftarrow A+B,\ E\leftarrow C_{out}; always PP1P\leftarrow P-1
T3T_3AQshr(EAQ), E0AQ\leftarrow\operatorname{shr}(EAQ),\ E\leftarrow0; test PzP_z

The conditional control function for loading the sum is L=Q1T2L=Q_1T_2. In contrast, the decrement is enabled by T2T_2 alone. Moving the decrement into T2T_2 makes the new counter value available for the PzP_z decision in T3T_3.

Worked trace: multiplying 5 by 3

For k=4k=4, begin with B=0101B=0101, Q=0011Q=0011, A=0000A=0000, and E=0E=0:

IterationEAQ before addQ1Q_1E
after optional add
A
after shift
PP after decrement
10 0000 001110:01010010:10013
20 0010 100110:01110011:11002
30 0011 110000:0011 (unchanged)0001:11101
40 0001 111000:0001 (unchanged)0000:11110

Look closely at iteration 1. Because Q1=1Q_1=1, the datapath first adds 0000 + 0101, making E:A = 0:0101. It then shifts the complete string 0 0101 0011 to 0 0010 1001. Reversing those two actions would produce a different—and incorrect—partial product.

The final concatenation is AQ=000011112=1510AQ=0000\,1111_2=15_{10}. If the original operands were 5-5 and +3+3, the magnitude trace would be identical; only As=BsQs=1A_s=B_s\oplus Q_s=1 would change, so the interpreted result would be 15-15.

The carry register matters when an addition exceeds four bits. If A=1100A=1100 and B=1010B=1010, their sum is 1 0110. Storing E:A = 1:0110 and then shifting preserves the leading 1 as the new most-significant bit of AA.

Encoded-state excitation table

Encode T0,T1,T2,T3T_0,T_1,T_2,T_3 as 00,01,10,1100,01,10,11 in state bits G2G1G_2G_1. For JK flip-flops, X is a don’t-care excitation:

Present bitRequired next bitRequired excitation
00J=0J=0, K=XK=X
01J=1J=1, K=XK=X
10J=XJ=X, K=1K=1
11J=XJ=X, K=0K=0

Apply these four rules independently to G2G_2 and G1G_1 in every state-table row.

PresentG2G1G_2G_1qmq_mPzP_zNextG2+G1+G_2^+G_1^+JG2J_{G_2}KG2K_{G_2}JG1J_{G_1}KG1K_{G_1}
T0T_0000XT0T_0000X0X
T0T_0001XT1T_1010X1X
T1T_101XXT2T_2101XX1
T2T_210XXT3T_311X01X
T3T_311X0T2T_210X0X1
T3T_311X1T0T_000X1X1

Inspection and simplification give:

JG2=T1,KG2=T3Pz,JG1=T0qm+T2,KG1=1.J_{G_2}=T_1,\qquad K_{G_2}=T_3P_z,\qquad J_{G_1}=T_0q_m+T_2,\qquad K_{G_1}=1.

Here is how to read the result:

  • G2G_2 must change from 0 to 1 only when leaving T1T_1, so JG2=T1J_{G_2}=T_1.
  • G2G_2 must reset while leaving T3T_3 only when the counter is zero, so KG2=T3PzK_{G_2}=T_3P_z.
  • G1G_1 must set for the request transition T0T1T_0\rightarrow T_1 and for T2T3T_2\rightarrow T_3, so JG1=T0qm+T2J_{G_1}=T_0q_m+T_2.
  • Whenever G1=1G_1=1—in T1T_1 or T3T_3—the next state’s G1G_1 is 0. Choosing KG1=1K_{G_1}=1 therefore handles both cases; its value is irrelevant while G1=0G_1=0.
Encoded multiplier controller with two JK flip-flops, a two-to-four state decoder, and qualified load output
Two state flip-flops feed a 2-to-4 decoder. Combinational logic implements the excitation equations and the qualified load L = Q₁T₂.

Equations derived by inspection are candidates, not proof. Substitute every table row—or simulate all reachable state/input combinations—to confirm that the resulting circuit produces the specified transitions. This four-state example uses every two-bit encoding; a controller with unused encodings should also define a safe recovery path, usually to the idle state.

PLA and ROM Control

A hardwired controller combines a state register with fixed gates and decoders. The combinational part can instead be replaced by a programmable logic array (PLA). The state register still holds the current control state; the PLA receives that state plus external/status inputs and produces both the next-state bits and datapath control outputs.

The state table already contains the information needed to create a PLA program table or a ROM truth table:

address/input side: current state + requests + status
data/output side:   next state + datapath controls
ImplementationState storageCombinational implementationBest fitMain trade-off
One-hot hardwiredOne flip-flop per stateSmall AND/OR equationsFew states, clarity, fast decodingMore flip-flops
Encoded hardwiredlog2N\lceil\log_2N\rceil state bitsCustom next-state and decode logicRegular small controllersEquations can become irregular
PLA controlEncoded state registerProgrammable product and sum termsTables with many useful don’t-caresRequires careful minimisation and verification
ROM controlEncoded state register or address fieldStored truth tableDense or highly irregular tablesMay store many redundant combinations

A PLA is attractive when shared product terms and don’t-care entries reduce the logic. A ROM is often simpler when most combinations need explicit outputs. In both cases, “programmable” refers to the combinational mapping; the clocked state register still determines the control sequence.

For a concrete sizing comparison, the multiplier has two state bits and two relevant inputs, qmq_m and PzP_z. A ROM indexed by all four bits needs 24=162^4=16 words. If the controller needs two next-state bits and six datapath controls, each word is eight bits, for a total of 16×8=12816\times8=128 stored bits—even though several address combinations behave identically. A PLA can express only the required product terms, such as T1T_1, T3PzT_3P_z, and T0qmT_0q_m, and share them between outputs. The ROM is more regular; the PLA may be smaller when the table is sparse.

A Controlled Accumulator Bit Slice

A compact accumulator unit shows how a control word becomes gates. Nine mutually exclusive variables select one register operation:

ControlRegister transferFunctionControlRegister transferFunction
p1p_1AA+BA\leftarrow A+BAddp6p_6AABA\leftarrow A\oplus BExclusive OR
p2p_2A0A\leftarrow0Clearp7p_7AshrAA\leftarrow\operatorname{shr}AShift right
p3p_3AAˉA\leftarrow\bar AComplementp8p_8AshlAA\leftarrow\operatorname{shl}AShift left
p4p_4AABA\leftarrow A\land BANDp9p_9AA+1A\leftarrow A+1Increment
p5p_5AABA\leftarrow A\lor BOR
One repeated JK accumulator bit slice with arithmetic, logic and shift input terms, carry chain, and common zero detector
One slice is repeated for every bit. Adjacent slices share the arithmetic carry and shift links; all $A_i$ outputs feed the common zero detector.

For each bit ii, combinational logic forms the requested next value Ai+A_i^+. A D flip-flop could load that value directly. With a JK flip-flop, the excitation can be written Ji=AˉiAi+J_i=\bar A_iA_i^+ and Ki=AiAˉi+K_i=A_i\bar A_i^+. Because the controls are mutually exclusive, their candidate next values can be ORed without two operations fighting for the same destination.

The add and increment terms propagate carry from bit ii to i+1i+1; shift-right takes Ai+1A_{i+1}, shift-left takes Ai1A_{i-1}, with defined serial inputs at the ends. A zero-status output is

Z=A0A1An1.Z=\overline{A_0\lor A_1\lor\cdots\lor A_{n-1}}.

This slice is the gate-level version of a control table: each symbolic transfer must have a data path, and each pjp_j must activate exactly that path at the clock edge.

From Arithmetic Control to CPU Control

An instruction controller uses exactly the same construction at a larger scale. Its datapath adds a program counter, instruction register, memory interface, register file, and condition flags. A simple multicycle fetch might be divided as follows:

StateRepresentative microoperationsWhy it needs a state
Fetch addressMARPCMAR\leftarrow PCPresent a stable memory address
Fetch dataMDRM[MAR], PCPC+1MDR\leftarrow M[MAR],\ PC\leftarrow PC+1Wait for/read memory and advance the program counter
Capture and decodeIRMDRIR\leftarrow MDR; decode opcodeStore the instruction before selecting an execution path
ExecuteInstruction-specific ALU, memory, or branch transfersDifferent opcodes activate different datapath resources
Write backDestination register \leftarrow resultCommit the architectural result

An opcode plays the role of an operation request; zero, carry, overflow, and comparison flags play the role of SS, EE, Q1Q_1, and PzP_z; and the controller outputs become mux selects, ALU functions, memory enables, and register write enables. Pipelining later overlaps these phases, but it does not remove the need to generate correct control for each stage.

For example, suppose PC = 0x20 and memory location 0x20 contains ADD R3, R1, R2, with R1 = 9 and R2 = 6:

StateValues before edgeControls and computationValues after edge
Fetch addressPC = 0x20Route PC to memory-address input; load MARMAR = 0x20
Fetch dataM[0x20] = ADD...Read memory; increment PC by 4MDR = ADD..., PC = 0x24
DecodeMDR = ADD R3,R1,R2Load IR; select the ADD pathIR = ADD R3,R1,R2
ExecuteR1 = 9, R2 = 6Select register operands and ALU additionALUOut = 15
Write backALUOut = 15Enable destination R3R3 = 15

The arithmetic is simple; the controller’s job is to guarantee that the correct sources, destination, ALU function, and write enable are selected in the correct intervals. A mistaken R3 write enable one interval early would store an old value even if the ALU itself were perfect.

Design Checks and Refinements

Before treating a controller as complete, check the following:

  • Idle protocol: Is there a ready signal, and what happens if requests overlap or remain asserted?
  • Complete transitions: Does every reachable state define a next state for every relevant condition?
  • Clock semantics: Is each decision based on a value that was already stored before the active edge?
  • Control safety: Are incompatible enables mutually exclusive, and are write enables low when results should be ignored?
  • Arithmetic boundaries: What happens for zero, equal magnitudes, maximum carry, negative zero, and the most negative representable value?
  • Counter convention: Is the loop count tested before or after decrement, and does the controller run exactly kk iterations?
  • Reset and recovery: Which state is entered after reset, and can an illegal encoded state return safely to idle?
  • Equation verification: Do the simplified equations reproduce every state-table row, including intended don’t-cares?

The two examples differ in arithmetic and encoding, but their architecture is the same: status flows from datapath to controller, control flows back to datapath, and the state register turns an algorithm into a clock-by-clock sequence. That pattern scales from a small arithmetic unit to the instruction fetch-decode-execute controller of a CPU.

Quick self-check

  1. Why is EE tested in T5T_5 rather than in T4T_4?
  2. For 6+(+2)-6+(+2), which arithmetic branch runs, and what sign should the result have?
  3. In the multiplier, why is the shift applied to EAQ rather than only AQ?
  4. Which term in DT0D_{T_0} keeps the sign-magnitude controller idle when no request is present?
Answers
  1. T₄ stores the ALU carry into E on its outgoing clock edge. T₅ is the first interval in which that stored value is stable and available for a transition decision.
  2. The signs differ, so the controller subtracts magnitudes. Since 6 is larger than 2, it retains A's negative sign and produces −4.
  3. An addition may produce a carry in E. Including E in the right shift moves that bit into the most-significant position of A instead of losing it.
  4. The idle self-loop term is q̅ₐq̅ₛT₀.