JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

The Datapath: Where Data Flows

We have the instruction set and the building blocks; now we wire them together into a working CPU. Meet the datapath — the rivers and roads that carry data between the program counter, register file, ALU, and memory — and see how one instruction's worth of values flows through it in a single tick of the clock.

From contract to circuit

So far this rung has handed us two halves of a CPU. The instruction set told us what the machine promises to do — add, load, store, branch — as a contract written for the programmer. The building-block guides gave us the hardware that can keep such promises: an ALU that adds and subtracts, a register file that holds the working variables, and memories that store instructions and data. The datapath is where those two worlds finally meet: it is the network of wires, muxes, and units through which actual bits travel as one instruction executes.

Picture a small factory floor. Raw materials arrive, get carried along belts to a workbench, are reshaped there, and the finished part is set back on a shelf. The datapath is that floor: the shelves are the register file and memory, the workbench is the ALU, and the belts are the bundles of wires connecting them. Crucially, the datapath only carries and transforms values — it has no opinion about which belt to run or what the workbench should do today. Those decisions belong to a separate boss we will meet later, the control unit; for now we are just laying the roads.

Meet the components, one shelf at a time

Every instruction begins at the program counter, a small register holding the address of the instruction we are about to run. The PC feeds the instruction memory, which hands back the 32-bit instruction word sitting at that address. Meanwhile a tiny adder quietly computes PC + 4 — the address of the next instruction in line — because most of the time we just walk forward through the program one word at a time. (A RISC-V instruction is four bytes wide, hence + 4.)

The instruction word, once fetched, is sliced into fields by position. Some bits name source and destination registers; the register file takes up to two register numbers and reads out their values onto two output ports at once, and can write one value back through a third port. Other bits form an immediate — a small constant baked into the instruction itself. Because immediates are stored narrow but the ALU works on full-width numbers, a sign-extender widens them: it copies the sign bit leftward so that, in two's complement, a negative small number stays the same negative number at full width. This is exactly the sign extension we met among the data-representation rungs, now wired into a real CPU.

At the heart of the floor sits the ALU — the workbench that adds, subtracts, ANDs, ORs, and compares. Off to one side is the data memory, the large shelf that load and store instructions reach into; instruction memory is read-only during a run, but data memory can be both read and written. And threaded all through the diagram are multiplexers: little two-input switches that choose, on a single control wire, which of two values flows onward. The mux is the unsung hero of the datapath, because it is what lets one set of wires serve many different instructions.

Wiring it into one single-cycle machine

Now connect the shelves with belts. The PC drives instruction memory; the fetched instruction's register fields drive the read ports of the register file; the two register outputs (and possibly the sign-extended immediate, chosen by a mux) drive the ALU's two inputs; the ALU result either goes to data memory as an address, or comes straight back to be written into the register file. One more mux at the very end chooses what gets written back to a register: the ALU's result, or a value just loaded from data memory. That single connected web — fetch, decode, read, compute, access memory, write back — is a complete single-cycle processor: every instruction finishes in exactly one clock cycle.

                +--------+        +--------------+
   PC --------->| Instr  |--word->| split into   |
   |   +4       | Memory |        | reg# / reg# /|
   |  (next)    +--------+        | immediate    |
   |                              +------+-------+
   |                                     |
   |        +-----------+    rs1 val     v
   |        | Register  |---------->[mux]----+
   |        |   File    |---rs2 val--->[mux] |
   |        +-----------+    immediate->     v
   |              ^                        +-----+
   |              | write-back             | ALU |--result--+
   |              |                        +-----+          |
   |          [mux]<--- loaded value --+      |             |
   |              ^                    |      | address     |
   |              +-- ALU result ------|------+-----+       |
   |                                   |            v       |
   |                              +----------+  +--------+   |
   +-- branch target (PC+offset)--| (branch) |  |  Data  |<--+ (store data)
                                  +----------+  | Memory |--> loaded value
                                                +--------+

  Flow for one instruction, left to right: fetch -> decode/read
  -> ALU compute -> (maybe) memory -> write back. The [mux]es are
  the only places the control unit gets to steer the traffic.
A sketch of the single-cycle datapath. Data flows left to right through fetch, register read, the ALU, optional memory access, and write-back. Each [mux] is a steering point the control unit will later drive.

Why does the same web serve four very different instructions? Because the muxes reconfigure the route without rewiring anything. An add sends two register values into the ALU and writes the result back. A load sends a register plus an immediate into the ALU to compute an address, reads data memory, and writes the loaded value back. A store computes an address the same way but writes a register value into memory and writes nothing back to the register file. A branch uses the ALU to compare two registers and, if they match, steers the next-PC mux toward a target address instead of PC + 4. Same roads, different switch settings.

Tracing one tick of the clock

Let us trace an add — in RISC-V style, `add x5, x6, x7`, meaning 'put x6 + x7 into x5'. In a single-cycle machine this entire journey happens within one clock period, with the combinational logic settling from left to right, and the result latched into x5 at the closing clock edge. Watch how each component does its one job in turn, with the muxes already set (by the control unit) to the 'arithmetic' route.

  1. Fetch: the PC holds the instruction's address and presents it to instruction memory, which returns the 32-bit word for `add x5, x6, x7`. In parallel, the +4 adder computes the address of the next instruction.
  2. Decode and read: the word is split into fields. The two source register numbers (6 and 7) go to the register file's read ports, which place the values of x6 and x7 on its two output buses.
  3. Compute: a mux selects the register value (not the immediate) for the ALU's second input. The ALU adds x6 + x7 and produces the sum on its result output.
  4. Skip memory: for an arithmetic op there is no load or store, so the data memory is left untouched and the result simply flows past it.
  5. Write back: the final mux selects the ALU result (not a loaded value), and at the clock edge it is written into register x5. The PC also accepts PC + 4, so the next cycle fetches the following instruction.

Notice what made the trace effortless: the datapath did not decide anything. It faithfully carried x6 and x7 to the ALU and the sum to x5 because the muxes happened to be set the arithmetic way. Set those same switches differently and the identical hardware would route an address into data memory instead. The data flows; the control steers. Holding those two ideas apart is the single most important habit for understanding any processor.

The price of doing everything in one cycle

The single-cycle design is beautifully easy to reason about, but it hides an expensive flaw. Because every instruction must finish within one clock period, that period has to be long enough for the slowest instruction. A load must fetch the instruction, read a register, add an address in the ALU, and read data memory, all in series — a long chain. A simple add finishes far sooner, yet it is forced to wait out the same long cycle. We are clocking the whole machine at the speed of its worst case. This is the single-cycle limitation, and it is a direct lesson from the iron law: a low CPI of exactly 1 is no bargain if it forces a punishingly long cycle time.

The first fix is the multi-cycle datapath. Instead of doing fetch, decode, execute, memory, and write-back all in one long cycle, break the work into short steps and give each step its own short clock cycle. A simple add might take three cycles; a load might take five. Now the clock can be fast because each cycle only has to cover one small step, and cheap instructions genuinely finish in fewer cycles. The cost is a more elaborate control unit that must remember which step it is on — but this stepwise thinking is precisely the seed of pipelining, which overlaps the steps of different instructions instead of doing one instruction's steps at a time.

There is a last seam worth naming before we go. The control that flips all those switches can itself be built two ways. Hardwired control burns the rules into fixed logic gates — fast, but rigid and hard to change. Microprogrammed control stores the control signals as tiny rows in a small memory, like a lookup table the machine steps through, which made richer instruction sets far easier to design and patch. Real CPUs blend both, and that very table is how modern chips quietly crack a complex instruction into the simpler micro-ops we will meet later. That split between data and its director is the doorway from organization into the pipeline ahead.