# The register file

*The CPU's fast scratch storage*

A register file is a small array of registers with several independent read and write ports addressed by register number, so a datapath can read two source operands and write one result in the same clock cycle.

Group: Processor
URL: https://digiwleea.wleeaf.dev/learn/register-file/

An [8-bit register](https://digiwleea.wleeaf.dev/learn/register8/) stores one byte, and you write it by asserting its write-enable and pulsing the clock. A CPU needs a handful of these that it can name, so it can hold several values at once and pick any of them by number. Line up `N` registers, give them an **address**, and add ports to read and write the one the address selects: that is a **register file**, the fast scratch storage the processor does its work in.

You already have all three ingredients. The registers are [8-bit registers](https://digiwleea.wleeaf.dev/learn/register8/). Choosing which one to *write* is an addressing job, so it uses a [decoder](https://digiwleea.wleeaf.dev/learn/decoder/). Choosing which one to *read* is a selection job, so it uses a [multiplexer](https://digiwleea.wleeaf.dev/learn/mux/). The file is those blocks wired together, addressed by register number.

> **TIP:** Think of a small **rack of numbered lockers**. A `2`-bit address names one of four lockers. To put something away you open exactly the addressed locker (the decoder); to take something out you reach into the addressed locker and pull its contents onto the counter (the mux). Because looking in one locker does not disturb another, you can read from two lockers and drop something into a third all at once.

## N registers, a log2(N)-bit address

With four registers `R0`-`R3` you need a `2`-bit address, because two bits count to four (`log2(4) = 2`). In general `N` registers need a `log2(N)`-bit register number: eight registers need a `3`-bit address, thirty-two (a typical RISC file) need `5` bits. Each read or write port carries its own address, so a port can name any register independently of the others.

## The write port: a decoder plus write-enable

The write port takes a write address `WA`, a data bus `DIN`, and a global write-enable `WE`. Feed `WA` into a [decoder](https://digiwleea.wleeaf.dev/learn/decoder/); it raises exactly one select line, `select_k`, for the addressed register. Each register's own write-enable is that select ANDed with `WE`, so on a clock edge only the addressed register loads `DIN` and every other register holds. This is the same `select AND write` trick that gates a write into one cell of [RAM](https://digiwleea.wleeaf.dev/learn/ram/).

```
WE_k = select_k AND WE     (only the addressed register loads on a write)
```

## The read ports: one mux each, and why more than one

A read port takes a read address and drives that register's value onto a read bus. That is exactly a [multiplexer](https://digiwleea.wleeaf.dev/learn/mux/): the register outputs are the data inputs, the read address is the select, and the output is the chosen register's value. One mux, one read port, one register on the bus.

So why give the file two read ports? Because a single operation usually needs **two** source operands. To compute `R3 = R1 + R2` the [ALU](https://digiwleea.wleeaf.dev/learn/alu/) must see `R1` and `R2` at the same instant, and one mux can only surface one register at a time. Add a second, independent mux with its own read address and the file can present two different registers on two buses simultaneously. A typical register file is **2-read, 1-write** (2R1W): read two operands and write one result every cycle. The ports are independent, so reading does not disturb writing.

## A worked cycle: R3 = R1 + R2

Say the four registers hold `R0 = 0`, `R1 = 25`, `R2 = 17`, `R3 = 0`, and the datapath wants `R3 = R1 + R2` in one cycle. Register numbers in binary: `R0 = 00`, `R1 = 01`, `R2 = 10`, `R3 = 11`.

1. Set read-port-A address to `01` (`R1`). Its mux drives `25` onto bus A.
2. Set read-port-B address to `10` (`R2`). Its mux drives `17` onto bus B, at the same time.
3. The [ALU](https://digiwleea.wleeaf.dev/learn/alu/) adds the two buses: `25 + 17 = 42`.
4. Set the write address to `11` (`R3`), route the ALU result to `DIN`, raise `WE`, and pulse the clock. The decoder raises only `select_3`, so only `R3` loads, becoming `42`.
5. `R0`, `R1`, `R2` are untouched, and because the read ports are independent of the write port, reading `R1` and `R2` while writing `R3` in the same cycle is perfectly fine.

_Circuit diagram: The full architecture at 4 words by 1 bit (a 2R1W file): a 2-to-4 decoder turns the write address WA1 WA0 into one-hot write selects (each ANDed with WE), and two multiplexers form the two read ports, QA selected by RA1 RA0 and QB by RB1 RB0. Open it in the lab: write a 1 into register 2 (set WA = 10, DIN = 1, raise WE, clock), then read it on port A (RA = 10) while port B reads a different register. Widen each cell to an 8-bit register and it stores a byte per register._

> **WARN:** Two things to get right. First, **one read port cannot serve two operands**: an add needs both sources at once, so you need one mux per read port, not one mux shared between them. Second, **read-during-write of the same register** needs a defined policy: if a port reads `R1` in the very cycle another port writes `R1`, does it see the old value or the new one? Real files pick one rule (often the old value, since the write lands on the clock edge) and stick to it. Do not assume it just works out.

> **KEY:** The register file is the working storage a CPU actually computes on. A RISC processor keeps its operands in a register file (often thirty-two registers, with register `0` hardwired to `0`), reads two per instruction, and writes one back, all in a cycle. It sits between our single [8-bit register](https://digiwleea.wleeaf.dev/learn/register8/) (one value) and [RAM](https://digiwleea.wleeaf.dev/learn/ram/) (many values, but one slow single-port access at a time): a register file is **small, multi-port, and fast**, exactly what the arithmetic core needs feeding it. It is the storage the [datapath](https://digiwleea.wleeaf.dev/learn/datapath/) is built around.

**Q (Try it):** On the 4-register file, you want to copy `R2` into `R0` in one cycle: read `R2` and write the result into `R0`. What read address and what write address do you set, and why can the read and the write happen together?

**A:** Set a read port's address to `10` (that is `R2`), routing `R2`'s value onto its bus, and set the write address to `00` (that is `R0`), with `WE` high, so on the clock edge the decoder raises only `select_0` and `R0` loads that value. The read and write happen together because the read port (a mux) and the write port (a decoder plus per-register write-enable) are independent circuits sharing only the register outputs: selecting `R2` to read does not gate any register's load, and enabling `R0`'s load does not disturb `R2`'s stored value.

### FAQ

**Q:** What is a register file?

**A:** A register file is a small array of registers with several independent read and write ports addressed by register number. It lets a datapath read two source operands and write one result in the same clock cycle, and it is the fast working storage a CPU computes on. It is built from [registers](https://digiwleea.wleeaf.dev/learn/register8/), a [decoder](https://digiwleea.wleeaf.dev/learn/decoder/) for the write port, and a [multiplexer](https://digiwleea.wleeaf.dev/learn/mux/) per read port.

**Q:** What is the difference between a register file and RAM?

**A:** Both are addressed banks of storage, but a register file is **small, multi-port, and fast** while [RAM](https://digiwleea.wleeaf.dev/learn/ram/) is **large and single-port**. A register file has a handful of registers (say 32) with two or three ports, so it reads two operands and writes one result every cycle; RAM has thousands or millions of cells but usually only one access per cycle. The register file is where the CPU works; RAM is where the program and its data live.

**Q:** Why does a register file have two read ports?

**A:** Because most operations need two source operands at once. To compute `R3 = R1 + R2` the [ALU](https://digiwleea.wleeaf.dev/learn/alu/) must see `R1` and `R2` simultaneously, and a single [multiplexer](https://digiwleea.wleeaf.dev/learn/mux/) can only present one register at a time. A second, independent read mux with its own address lets the file surface two different registers on two buses in the same cycle. The common organization is 2-read, 1-write (2R1W).

**Q:** How is a register selected for reading or writing?

**A:** By its register number. Each port carries an address; `N` registers need a `log2(N)`-bit address. For a write, the address feeds a [decoder](https://digiwleea.wleeaf.dev/learn/decoder/) that raises one write-enable, so only the addressed register loads on the clock edge. For a read, the address is the select of a [multiplexer](https://digiwleea.wleeaf.dev/learn/mux/) that routes the chosen register's value onto the read bus.
