> For the complete documentation index, see [llms.txt](https://osh.fducslg.com/notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://osh.fducslg.com/notes/computer-architecture/01-single-cycle-cpus.md).

# Single Cycle RISC-V CPU

For single cycle CPU, all stages of an instruction is completed within one long clock cycle. THe clock cycle should be sufficiently long to allow each instruction to complete all stages without interruption within one cycle.

Five phases of execution: (1) **IF** (Instruction Fetch) (2) **ID** (Instruciton Decoding) (3) **EX** (Execute) (4) **MEM** (Memory) (5) **WB** (Write Back)

## V1: R-Types

<figure><img src="https://p.ipic.vip/m4wgbp.png" alt="RV32I-v1.drawio"><figcaption></figcaption></figure>

* **Register File** consists of 31 registers.
* CLK is passed to all internal registers so they can be written to if they match RW and Write Enable is 1.
* **ALUSel** is a control bit which encodes the operation we should perform on the given operands.

## V2: Arithmetic I-Type

<figure><img src="https://p.ipic.vip/hcng36.png" alt="RV32I-v2.drawio"><figcaption></figcaption></figure>

The lower 12 bits of `imm` sign-extend to a 32-bit immediate number.

## V2.1: Load I-Type

<figure><img src="https://p.ipic.vip/d02n63.png" alt="RV32I-v2.1.drawio"><figcaption></figcaption></figure>

The loading instructions utilize all of the components mentioned above (critical path).

There are two ways to write data back to the registers:

* Execute an operation directly between `rs1` and `imm`, and then write the result back.
* Calculate an address by performing an operation between `rs1` and `imm`, and then write the data from memory to the register.

Note that we assume the logic for sign-extending/zero-extending the memory data is implemented in DMEM.

## V3: S-Type

Note that the pseudo-assembly instruction for this type looks like `sw rs2, offset(rs1)`.

In RISC-V, the base address is given by `rs1`, and the offset is determined by the `imm` fields.

> **Difference Between S-Type and Load I-Type**
>
> While `sw` and `lw` appear to be symmetrical operations, there is a subtle asymmetry in their instruction formats.
>
> * `lw` includes `rd` (the register where data is loaded) but lacks `r2`.
> * `sw` includes `rs2` (the word to be stored) but does not have `rd`.
>
> But they both use `rs1` as the base address for address calculating.

<figure><img src="https://p.ipic.vip/z0eu6o.png" alt="RV32I-v3.drawio"><figcaption></figcaption></figure>

## V3.1: SB-Type

The difference between S-Type and SB-Type:

* `rs1` is not used as base address now. The base address is `PC`.
* The `imm` field now represents a 12-bit signed immediate.

<figure><img src="https://p.ipic.vip/nccxxu.png" alt="RV32I-v3.1.drawio"><figcaption></figcaption></figure>

## V4: Jumping I-Type

Semantics of `jalr rd, rs1, imm`:

* Writes PC + 4 to `rd` (return address)
* Sets PC = `rs1 + imm`
* Uses same immediates as arithmetic and loads (i.e. there's no multiplication by 2 bytes and is different from branch)

<figure><img src="https://p.ipic.vip/7fxkuf.png" alt="RV32I-v4.drawio"><figcaption></figcaption></figure>

## V5: J-Type

No new changes to the data path.

* `jal` saves PC + 4 to `rd` (the return address)
* Set PC = PC + offset (PC-relative jump, $$\pm 2^{18}$$ 32-bit instructions)

## Performance

The performance of a machine is determined by:

$$
\text{Perf} = # \text{Inst} \times \text{CPI} \times \frac{\text{Time}}{\text{Cycle}}
$$
