---
title: Assembling SEQ
module: Processor Design
moduleNumber: 4
lessonNumber: 4
order: 404
summary: >
  We wire the whole thing together. The functional units from digital logic and the
  control signals from the last lesson assemble into the complete SEQ datapath, laid
  out the way CS:APP draws it — six stages stacked bottom to top, Fetch at the floor
  and PC update at the ceiling, signals flowing up the margins. Then the timing
  analysis: why everything must settle in one cycle, the no-reading-back principle
  that makes single-cycle execution consistent, and the critical path that sets the
  clock. We close by walking an OPq and a ret through the assembled machine.
topics: [Processor Design]
sources:
  - book: Bryant & O'Hallaron
    ref: "CS:APP — §4.3 Sequential Y86-64 Implementations"
  - book: Bistriceanu
    ref: "Computer Architecture Notes — §5 CPU Implementation (Executing an instruction; Hardwired control)"
---

We have the parts and we have the wiring diagram in words. The
[stage tables](/computer-architecture/processor-design/the-seq-stages) gave the
computations; the [control logic](/computer-architecture/processor-design/control-logic-and-sequencing)
gave the signals; the [digital-logic module](/computer-architecture/digital-logic/multiplexers-decoders-and-the-alu)
gave the units. This lesson bolts them together into **SEQ**, the complete sequential
Y86-64 processor, and draws it the canonical way: the six stages as horizontal bands,
**Fetch at the bottom and PC update at the top**, so that signals flow generally
upward and the next-PC value loops back down to the PC register. Then we work out the
timing (what one cycle must accomplish and what sets its length) and trace two
instructions through the assembled datapath to prove the wiring is right.

## The layout: stages as bands, bottom to top

CS:APP draws SEQ upside-down relative to the stage list: the work starts at the floor
and rises. The reason is the data flow. Fetch reads the PC and produces the fields;
those feed Decode just above; the register values rise into Execute; the ALU result
rises into Memory; the loaded or computed values rise toward Write-back; and at the
very top, PC update computes `newPC` and sends it back **down** the left margin to
the PC register, ready for the next cycle. Drawing it this way keeps every hand-off
vertical, and it puts the two long feedback paths — write-back into the register
file, `newPC` into the PC — in the margins where they cross nothing they should not.

$$
% caption: The complete SEQ datapath, Fetch (bottom) to PC update (top). The center
% caption: column rises from the PC through instruction memory, the register file,
% caption: the ALU muxes and ALU, data memory, and the New-PC mux. Bypass lanes carry
% caption: valC and valP up the right margin and valC into aluA on the left; valE and
% caption: valM return down the left margin to the write ports (dstE, dstM), and
% caption: newPC loops down the far left into the PC register. The aluA mux also
% caption: takes the constants +8/-8, and aluB the constant 0 (not drawn).
\begin{tikzpicture}[font=\footnotesize,>=stealth,
  u/.style={draw, fill=acc!8, align=center, inner sep=2pt, minimum height=11mm},
  mux/.style={draw, fill=acc!8, align=center, inner sep=1pt,
              minimum width=8mm, minimum height=9mm, font=\scriptsize},
  band/.style={anchor=west, text=acc, font=\scriptsize\itshape},
  wl/.style={font=\scriptsize}]
  \definecolor{acc}{HTML}{2348F2}
  % ===== units, bottom to top =====
  \node[u, minimum width=16mm, minimum height=9mm] (pc) at (0.6,-1.4) {PC};
  \node[u, minimum width=26mm] (imem) at (0.6,0) {Instruction\\memory};
  \node[u, minimum width=30mm] (rf) at (0.6,2.4) {Register f\/ile};
  \node[mux] (aluA) at (0,4.2) {aluA};
  \node[mux] (aluB) at (1.2,4.2) {aluB};
  \node[u, minimum width=18mm, minimum height=9mm] (alu) at (0.6,5.6) {ALU};
  \node[u, minimum width=10mm, minimum height=9mm] (cc) at (3.2,5.6) {CC};
  \node[u, minimum width=28mm, minimum height=12mm] (dmem) at (0.6,7.6) {Data memory};
  \node[u, minimum width=16mm, minimum height=12mm] (npc) at (0.6,10.3) {New\\PC};
  % ===== center column =====
  \draw[->] (pc.north) -- (imem.south) node[wl,midway,right]{addr};
  \draw[->] (imem.north) -- (rf.south) node[wl,midway,right]{rA, rB};
  \draw[->] ([xshift=-6mm]rf.north) -- (aluA.south) node[wl,midway,left]{valA};
  \draw[->] ([xshift=6mm]rf.north) -- (aluB.south) node[wl,midway,right]{valB};
  \draw[->] (aluA.north) -- ([xshift=-6mm]alu.south);
  \draw[->] (aluB.north) -- ([xshift=6mm]alu.south);
  \draw[->] (alu.north) -- (dmem.south) node[wl,midway,right]{valE (addr)};
  \draw[->] (alu.east) -- (cc.west) node[wl,midway,above]{set CC};
  \draw[->, acc] (cc.north) -- ++(0,0.4) node[wl,anchor=south,text=acc]{Cnd};
  \draw[->] (dmem.north) -- (npc.south) node[wl,pos=0.25,right]{valM};
  % ===== right margin: valA store data, valC, valP bypass lanes =====
  \draw[->] (rf.east) -- (4.6,2.4) -- (4.6,7.6) -- (dmem.east);
  \node[wl, anchor=south] at (3.2,2.4) {valA (data in)};
  \draw[->] ([yshift=3mm]imem.east) -- (5.4,0.3) -- (5.4,10.0) -- (1.4,10.0);
  \node[wl, anchor=south] at (3.2,10.0) {valC};
  \node[wl, anchor=south] at (3.2,0.3) {valC};
  \draw[->] ([yshift=-3mm]imem.east) -- (6.2,-0.3) -- (6.2,10.6) -- (1.4,10.6);
  \node[wl, anchor=south] at (3.2,10.6) {valP};
  \node[wl, anchor=north] at (3.2,-0.35) {valP};
  % ===== left margin: valC into aluA; write-back lanes; newPC loop =====
  \draw[->] ([yshift=3mm]imem.west) -- (-3.0,0.3) -- (-3.0,4.2) -- (aluA.west);
  \node[wl, anchor=south] at (-1.9,0.3) {valC};
  \draw[->] (0.6,6.5) -- (-3.8,6.5) -- (-3.8,2.6) -- ([yshift=2mm]rf.west);
  \node[wl, anchor=south] at (-1.6,6.5) {valE};
  \node[wl, anchor=south] at (-2.0,2.62) {dstE};
  \draw[->] (0.6,9.0) -- (-4.6,9.0) -- (-4.6,2.2) -- ([yshift=-2mm]rf.west);
  \node[wl, anchor=south] at (-2.0,9.0) {valM};
  \node[wl, anchor=north] at (-2.0,2.15) {dstM};
  \draw[->, acc] (npc.west) -- (-5.6,10.3) -- (-5.6,-1.4) -- (pc.west);
  \node[text=acc, anchor=south, rotate=90, font=\scriptsize] at (-5.85,4.4) {newPC};
  % ===== control-point annotations =====
  \draw[->, acc] (-1.35,5.6) -- (alu.west);
  \node[wl, anchor=east, text=acc] at (-1.4,5.6) {alufun};
  \draw[->, acc] (0.6,11.5) -- (npc.north);
  \node[wl, anchor=south] at (0.6,11.55) {icode, Cnd (select)};
  \node[wl, anchor=east, text=acc] at (-1.0,7.9) {read / write};
  % ===== band labels on the far right =====
  \node[band] at (7.0,0)    {Fetch};
  \node[band] at (7.0,2.4)  {Decode};
  \node[band] at (7.0,5.0)  {Execute};
  \node[band] at (7.0,7.6)  {Memory};
  \node[band] at (7.0,9.0)  {Write-back};
  \node[band] at (7.0,10.3) {PC update};
\end{tikzpicture}
$$

The figure is busy because the machine is, but the discipline is simple. Functional
units sit in their band, and data rises through the center column. Values that skip
stages ride **bypass lanes** in the margins: `valC` and `valP` climb the right side
from Fetch straight to the New-PC mux, `valA` rides across to the data-memory write
port, and `valC` cuts up the left into the `aluA` mux. The two write-back values,
`valE` and `valM`, tee off their rising wires and descend the left margin into the
register file's E and M write ports. The one wire that travels the whole height is
`newPC`, looping from the top back down into the PC. Every wire in the figure is one
row of some stage table made physical; if a wire seems unmotivated, some instruction
in [lesson 2](/computer-architecture/processor-design/the-seq-stages) is its reason.

Two wires reward a second look. The `valA` lane into data memory exists because
`rmmovq` and `pushq` store a register value the ALU never touches; the ALU is busy
computing the _address_. And `valM` rises all the way into the New-PC mux because of
one instruction, `ret`; for every other instruction that input is ignored.

## Timing: one cycle, one instruction

SEQ has exactly four clocked state elements: the **PC**, the **condition codes**,
the **register file**, and **data memory**. Everything else — every mux, the ALU,
the control logic, the wires above — is combinational: outputs follow inputs after a
gate delay, with no memory of their own. The processor's operation is then a strict
two-beat rhythm:

1. **During the cycle**, the state elements hold still and the combinational logic
   settles. The PC's current value ripples up the figure: fetch produces the fields,
   decode reads registers, the ALU computes, memory reads, and the New-PC mux
   produces `newPC`. Late in the cycle every wire holds its final value.
2. **At the rising clock edge**, all four state elements load at once, each with its
   commit condition:

   | State element | Loads | Commit condition |
   | --- | --- | --- |
   | PC | `newPC` | always |
   | Condition codes | ALU flags | `set_cc` |
   | Register file | `valE→dstE`, `valM→dstM` | `dst ≠ RNONE` |
   | Data memory | `valA→mem_addr` | `mem_write` |

   The instant after the edge, the next instruction's cycle begins from the new state.

$$
% caption: One SEQ cycle. Between rising clock edges the combinational logic settles
% caption: stage by stage — fetch, decode, execute, memory, PC selection — and the
% caption: state elements hold still. At the edge, PC, CC, register file, and data
% caption: memory all commit their new values simultaneously, and the next cycle
% caption: begins from that state.
\begin{tikzpicture}[font=\footnotesize,>=stealth,
  bar/.style={draw, fill=acc!8, minimum height=6mm, inner sep=1pt, font=\scriptsize}]
  \definecolor{acc}{HTML}{2348F2}
  % clock waveform
  \draw[thick] (0,2.7) -- (1,2.7) -- (1,3.3) -- (4.6,3.3) -- (4.6,2.7)
               -- (9,2.7) -- (9,3.3) -- (10.2,3.3);
  \node[anchor=west, font=\scriptsize] at (10.4,3.0) {clock};
  % rising edges
  \draw[acc, dashed] (1,-1.3) -- (1,3.6);
  \draw[acc, dashed] (9,-1.3) -- (9,3.6);
  \node[text=acc, anchor=south, font=\scriptsize] at (1,3.65) {rising edge};
  \node[text=acc, anchor=south, font=\scriptsize] at (9,3.65) {rising edge};
  % settling bars
  \node[bar, minimum width=16mm, anchor=west] at (1.1,1.9)  {Fetch};
  \node[bar, minimum width=13mm, anchor=west] at (2.8,1.9)  {Decode};
  \node[bar, minimum width=15mm, anchor=west] at (4.2,1.9)  {Execute};
  \node[bar, minimum width=17mm, anchor=west] at (5.8,1.9)  {Memory};
  \node[bar, minimum width=13mm, anchor=west] at (7.6,1.9)  {newPC};
  \node[anchor=west, font=\scriptsize] at (1.1,1.1) {combinational logic settles; state elements hold};
  % commits at the edge
  \node[anchor=west, font=\scriptsize, text=acc] at (4.7,0.35)
        {at the edge: PC, CC, registers,};
  \node[anchor=west, font=\scriptsize, text=acc] at (4.7,-0.1)
        {memory commit together};
  \draw[->, acc] (4.7,-0.55) -- (8.85,-0.55);
  % cycle span
  \draw[<->] (1,-0.9) -- (9,-0.9) node[midway, below, font=\scriptsize]{one cycle = one instruction};
\end{tikzpicture}
$$

The design works only if a consistency condition holds: nothing computed during the
cycle may depend on state the _same_ instruction is about to write. Otherwise the
combinational logic would chase its own tail: the write would change a value that
fed the write.

> **Principle (No reading back).** The processor never needs to read back state
> updated by an instruction in order to complete that instruction's own processing.
> Every value an instruction uses is either prior state (held steady all cycle) or a
> named intermediate signal (`valA`, `valE`, ...) carried on wires.

The stage tables were written to respect this. `pushq %rsp` stores the
_old_ stack pointer because Memory stores `valA`, a wire that captured the register
_before_ any update; the decremented `valE` lands in `%rsp` only at the edge, after
the store's data is already decided. `popq %rsp` never re-reads `%rsp` after its
increment; both candidate values (`valE`, `valM`) are wires, and a mux picks which
one the register file commits. Even the condition codes obey it: an `OPq` _sets_ CC
at the edge, and the `jXX` that _reads_ CC is a later instruction, reading the
committed value in its own cycle. State is read at the top of the cycle and written
at the bottom, never both.

## The critical path

The clock cannot tick until the slowest signal has settled, so the cycle time is set
by the **critical path**: the longest chain of combinational delay between one
rising edge and the next. Writing $t_i$ for the propagation delay of unit $i$ and
$t_\text{setup}$ for the register setup time, the minimum clock period is

$$
T_\text{clk} \;\ge\; \max_{\text{instr}} \!\sum_{i \in \text{path}} t_i \;+\; t_\text{setup},
\qquad
f_\text{max} = \frac{1}{T_\text{clk}}.
$$

In SEQ that maximizing chain belongs to the instructions that use
memory late and need its answer for state: think of `ret`, where the PC's value must
traverse instruction memory (fetch the `icode`), the register file (read `%rsp`),
the ALU path, then **data memory** (read the return address), and finally the New-PC
mux — all before `newPC` is stable enough to clock in.

$$
% caption: The critical path through SEQ, with illustrative delays. A ret must ripple
% caption: through instruction memory, the register file, the ALU, data memory, and
% caption: the New-PC mux before newPC may clock into the PC; the sum, plus register
% caption: setup time, is the minimum clock period. Faster instructions (an OPq stops
% caption: at the ALU) still wait out the full cycle.
\begin{tikzpicture}[font=\footnotesize,>=stealth,
  u/.style={draw, fill=acc!8, align=center, inner sep=2pt,
            minimum width=20mm, minimum height=10mm}]
  \definecolor{acc}{HTML}{2348F2}
  \node[u] (im) at (0,0)    {Instruction\\memory};
  \node[u] (rf) at (2.9,0)  {Register\\f\/ile};
  \node[u] (al) at (5.8,0)  {ALU};
  \node[u] (dm) at (8.7,0)  {Data\\memory};
  \node[u] (np) at (11.6,0) {New-PC\\mux};
  \draw[->, acc, thick] (im.east) -- (rf.west);
  \draw[->, acc, thick] (rf.east) -- (al.west);
  \draw[->, acc, thick] (al.east) -- (dm.west);
  \draw[->, acc, thick] (dm.east) -- (np.west);
  \draw[->, acc, thick] (np.east) -- ++(1.2,0) node[anchor=west]{newPC};
  \node[anchor=north, font=\scriptsize] at (0,-0.75)    {90 ps};
  \node[anchor=north, font=\scriptsize] at (2.9,-0.75)  {60 ps};
  \node[anchor=north, font=\scriptsize] at (5.8,-0.75)  {80 ps};
  \node[anchor=north, font=\scriptsize] at (8.7,-0.75)  {120 ps};
  \node[anchor=north, font=\scriptsize] at (11.6,-0.75) {20 ps};
  \node[anchor=west, text=acc, font=\scriptsize] at (0,-1.5)
        {clock period at least 370 ps + setup; every instruction gets the same cycle};
\end{tikzpicture}
$$

The numbers are illustrative; the structure is not. Two consequences matter. First,
**every instruction pays the worst-case time**: a `nop` finishes its "work" almost
instantly and then idles for the rest of the cycle, because the clock serves the
slowest customer. Second, the path runs through **two memory accesses in series**
(instruction fetch, then data access) plus the register file and ALU between them —
which is most of the reason SEQ's clock must be slow. Cutting this chain into pieces
that run concurrently is the job of
[pipelining](/computer-architecture/pipelining/from-seq-to-pipe), and the
six-band drawing above is already the blueprint for those pipeline stages.

Put numbers to it to see what the single-cycle rule costs. With the illustrative
delays above — 90, 60, 80, 120, 20 ps — a `ret` needs
$90 + 60 + 80 + 120 + 20 = 370$ ps of settling; add $t_\text{setup} = 20$ ps and
$T_\text{clk} \ge 390$ ps, an $f_\text{max} \approx 2.56$ GHz ceiling. But `addq`
stops at the ALU: its longest path skips data memory, giving
$t_\text{addq} = 90 + 60 + 80 + 20 = 250$ ps, a would-be 4 GHz. SEQ does not allow
it: one clock serves every instruction, so `addq` runs at 390 ps and idles the slack
$390 - 250 = 140$ ps every cycle. A program that is mostly arithmetic pays the memory
instructions' worst-case time on every single cycle. This is the concrete, measurable
cost of "one cycle per instruction, sized for the worst instruction," and it is the
motivation for everything that comes after SEQ.

## Walking an OPq through SEQ

Take a concrete `OPq`: `subq %rdx, %rbx`, computing $R[\texttt{\%rbx}] \leftarrow
R[\texttt{\%rbx}] - R[\texttt{\%rdx}]$. Follow it up the bands.

- **Fetch** reads two bytes at the PC: `61 23`. `icode:ifun = 6:1` (`OPq`, `subq`);
  the register byte is `rA:rB = 2:3` (`%rdx`:`%rbx`). `valP = PC + 2`.
- **Decode** sets `srcA = rA = %rdx` and `srcB = rB = %rbx`, reading
  `valA = R[%rdx]` and `valB = R[%rbx]`. `dstE = rB = %rbx`; `dstM = RNONE`.
- **Execute** sends `valA` to `aluA` and `valB` to `aluB`, with `alufun = ifun =
  subq`, so `valE = valB - valA`. Because `icode == IOPQ`, `set_cc` is true and the
  ALU flags will latch into `ZF`/`SF`/`OF` at the edge.
- **Memory** does nothing: `mem_read` and `mem_write` are both false for `OPq`.
- **Write-back** commits `valE` into `dstE = %rbx` through the `E` port; the `M`
  port is idle (`dstM = RNONE`).
- **PC update** finds `icode` is not call, jump, or ret, so `newPC = valP`, and `PC`
  advances to the next instruction.

Every band did exactly what its row in the OPq stage table promised, and the only
muxes that mattered were `aluA`/`aluB` (picking the register values) and `New PC`
(picking `valP`).

$$
% caption: Signal flow for subq %rdx,%rbx through SEQ. The live values on the key
% caption: wires: Fetch yields icode 6:1 and rA:rB 2:3; Decode reads valA,valB; the
% caption: ALU subtracts and sets CC; Write-back stores valE into %rbx; PC takes valP.
\begin{tikzpicture}[font=\footnotesize,>=stealth,
  s/.style={draw, fill=acc!8, minimum width=40mm, minimum height=9mm, align=center}]
  \definecolor{acc}{HTML}{2348F2}
  \node[s] (f) at (0,0)    {Fetch};
  \node[s] (d) at (0,-1.5) {Decode};
  \node[s] (e) at (0,-3.0) {Execute};
  \node[s] (w) at (0,-4.5) {Write-back};
  \node[s] (p) at (0,-6.0) {PC update};
  \foreach \a/\b in {f/d, d/e, e/w, w/p} \draw[->] (\a.south) -- (\b.north);
  \node[anchor=west, text=acc] at (2.6,0)    {$\mathtt{icode{:}ifun}=6{:}1$, $\mathtt{rA{:}rB}=2{:}3$};
  \node[anchor=west, text=acc] at (2.6,-1.5) {$\mathtt{valA}=R[\mathtt{\%rdx}]$, $\mathtt{valB}=R[\mathtt{\%rbx}]$};
  \node[anchor=west, text=acc] at (2.6,-3.0) {$\mathtt{valE}=\mathtt{valB}$ - $\mathtt{valA}$; set CC};
  \node[anchor=west, text=acc] at (2.6,-4.5) {$R[\mathtt{\%rbx}] = \mathtt{valE}$};
  \node[anchor=west, text=acc] at (2.6,-6.0) {$\mathtt{PC} = \mathtt{valP}$};
\end{tikzpicture}
$$

## Walking a ret through SEQ

`ret` exercises the parts `OPq` left idle: the stack, the memory read port, and the
interesting input to the New-PC mux. Its one byte is `90`.

- **Fetch** reads `90`: `icode:ifun = 9:0`. There is no register byte and no constant,
  so `valP = PC + 1`.
- **Decode** has no `rA`/`rB`, but the control logic sets `srcA = %rsp` and `srcB =
  %rsp` for `ret`, so both `valA` and `valB` read the stack pointer. `dstE = %rsp`;
  `dstM = RNONE`.
- **Execute** picks `aluA = +8` and `aluB = valB`, with `alufun = ADD`, so `valE =
  R[%rsp] + 8`, the incremented stack pointer. `set_cc` is false; the flags are
  untouched.
- **Memory** has `mem_read` true with `mem_addr = valA = R[%rsp]` — the **old** stack
  top — so `valM = M[R[%rsp]]`, the return address.
- **Write-back** commits `valE` (the incremented pointer) into `dstE = %rsp`. `dstM`
  is `RNONE`, so the loaded `valM` is **not** written to any register; it is bound
  for the PC instead.
- **PC update** finds `icode == IRET`, so `newPC = valM`. The processor jumps to the
  return address, and `%rsp` has moved up by 8.

The decisive wire is the one carrying `valM` past Write-back and into the New-PC mux:
that single connection, selected only when `icode == IRET`, is what makes `ret` a
control transfer rather than a load. Contrast `popq`, which routes the very same
`valM` into a register (`dstM = rA`) and lets `newPC` fall through to `valP`. Same
memory read, different destination — and the difference is one mux input.

## SEQ+ and the road to the pipeline

The SEQ we just assembled computes `newPC` at the very _end_ of the cycle, at the top
of the drawing, and loops it all the way back down to the PC register. That long
feedback wire is harmless in a single-cycle machine, but it is precisely the wrong
shape for pipelining, where each stage must begin and end at a clean register
boundary. CS:APP's next step, **SEQ+** (Bryant & O'Hallaron, _CS:APP_ §4.5.1), fixes
this with a small rearrangement: move the PC computation to the _start_ of the cycle,
so the machine computes the address of the instruction it is _about to run_ from
signals it saved on the previous cycle.

$$
% caption: SEQ computes newPC at the end of the cycle from this instruction's signals
% caption: (top). SEQ+ saves those signals in small registers (pIcode, pValC, ...) and
% caption: computes the current PC at the start of the next cycle from them (bottom) --
% caption: the same logic, relocated. This is circuit retiming.
\begin{tikzpicture}[font=\footnotesize,>=stealth,
  u/.style={draw, fill=acc!8, align=center, inner sep=2pt, minimum height=8mm},
  wl/.style={font=\scriptsize}]
  \definecolor{acc}{HTML}{2348F2}
  % SEQ row
  \node[wl, anchor=east, text=acc] at (-0.4,0) {SEQ};
  \node[u, minimum width=22mm] (s1) at (1.6,0) {this instr:\\icode, valC, valM};
  \node[u, minimum width=18mm] (s2) at (5.2,0) {new-PC\\logic};
  \node[u, minimum width=14mm] (s3) at (8.2,0) {PC\\register};
  \draw[->] (s1.east) -- (s2.west);
  \draw[->] (s2.east) -- (s3.west) node[wl,midway,above]{newPC};
  \node[wl, anchor=west] at (9.2,0) {(end of cycle)};
  % SEQ+ row
  \node[wl, anchor=east, text=acc] at (-0.4,-2.2) {SEQ$+$};
  \node[u, minimum width=22mm] (p1) at (1.6,-2.2) {saved regs:\\pIcode, pValC, ...};
  \node[u, minimum width=18mm] (p2) at (5.2,-2.2) {PC-select\\logic};
  \node[u, minimum width=14mm] (p3) at (8.2,-2.2) {PC\\(current)};
  \draw[->] (p1.east) -- (p2.west);
  \draw[->] (p2.east) -- (p3.west) node[wl,midway,above]{PC};
  \node[wl, anchor=west] at (9.2,-2.2) {(start of cycle)};
\end{tikzpicture}
$$

What SEQ+ does _not_ have is a program-counter register. The PC is
reconstructed each cycle from the saved control signals `pIcode`, `pValC`, `pValM`, and
so on. CS:APP names this move **circuit retiming** (Leiserson & Saxe, 1991) — a
transformation that relocates state across combinational logic without changing what
the circuit computes, used here to balance stage delays. It rests on a principle
worth stating plainly: a processor may represent its state in any form, as long
as it produces the correct programmer-visible values for any program. SEQ+ exploits
this in a small way (no PC register); the pipelined PIPE design exploits it heavily,
and out-of-order cores take it to the extreme of running instructions in an order
entirely unlike the program's (CS:APP §5.7). SEQ+ is the single, cheap step that turns
SEQ's stage bands into pipeline stages: insert a register between each band and several
instructions can occupy the machine at once, which is where the
[pipelining module](/computer-architecture/pipelining/from-seq-to-pipe) begins.

> **Takeaway.** SEQ is the functional units of digital logic plus the control signals
> of the last lesson, wired as six bands from Fetch at the bottom to PC update at the
> top, with bypass lanes up the right margin and write-back and `newPC` looping down
> the left. Its timing is a two-beat rhythm — combinational logic settles during the
> cycle, then PC, CC, registers, and memory commit together at the rising edge — made
> consistent by the no-reading-back principle. The clock period is the critical
> path: for a `ret`, instruction memory, register file, ALU, data memory, and the
> New-PC mux in series, and every instruction pays that worst-case time.

The datapath is assembled, timed, and demonstrably correct on two instructions. The
[final lesson](/computer-architecture/processor-design/tracing-a-program) runs whole
programs through it, cycle by cycle, and watches real machine state evolve.
