---
# System prepended metadata

title: 'ARCH2025: Discussion on Nov. 18'

---

# ARCH2025: Discussion on Nov. 18
GitHub repository: [dozingmoon/ca2025-mycpu](https://github.com/dozingmoon/ca2025-mycpu)

---
### From [2025-11-18 CA](https://hackmd.io/QERe1qMbSra0UqdfEPUhMw?view#dozingmoon):
> Take `addi` for example. Show details in MyCPU
> 1. Fetch intructions from InstructionMemory
> 2. Decode: `addi` is I-type
> 3. Execute (no ~~WB~~**[memory-write needed]**)

## Fetch instructions from Instruction Memory
CPU fetches instruction `0x28c28293  addi x5, x5, 652` from memory, which is initiated by `TestTopModule.scala`
```scala
//TestTopModule.scala
mem.io.instruction_address    := cpu.io.instruction_address
cpu.io.instruction            := mem.io.instruction
```
```scala
//CPU.scala
io.instruction_address          := inst_fetch.io.instruction_address
inst_fetch.io.rom_instruction   := io.instruction
```
```scala
// InstructonFetch.scala
io.instruction_address := pc
io.id_instruction      := Mux(io.instruction_valid, io.rom_instruction, InstructionsNop.nop)
```
![image](https://hackmd.io/_uploads/r1xcfYubbg.png)

## Decode: Check which type `addi` is
We retrieve the `opcode` of `addi` `('b0010011)`, and lookup the instruction types to extend the immediate field of I-type instructions `(=0x284)`.
```scala
// Execute.scala
// ...
object InstructionTypes {
  val L  = "b0000011".U
  val I  = "b0010011".U
  val S  = "b0100011".U
  val RM = "b0110011".U
  val B  = "b1100011".U
}

class InstructionDecode extends Module{
  //...
  val opcode = io.instruction(6, 0)
  val funct3 = io.instruction(14, 12)
  val funct7 = io.instruction(31, 25)
  val rd     = io.instruction(11, 7)
  val rs1    = io.instruction(19, 15)
  val rs2    = io.instruction(24, 20)
    
  io.ex_immediate := MuxLookup(opcode, Cat(Fill(20, io.instruction(31)), io.instruction(31, 20))
    )(
    IndexedSeq(
      InstructionTypes.I -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)),
      //...
    )
  )
}
```
![image](https://hackmd.io/_uploads/rJqCfYdW-g.png)

## Execute: What operations are done?
`ALU` will receive the control signal decoded from `opcode`, `funct3` and `funct7` by`ALUControl`, and `Execute` will select the operand source. `ALU` will enter the switch case, matching `ALUFunctions.add`, and do add to `op1` and `op2`.
```scala
// Execute.scala
// ...
  alu_ctrl.io.opcode := opcode
  alu_ctrl.io.funct3 := funct3
  alu_ctrl.io.funct7 := funct7
  alu.io.func        := alu_ctrl.io.alu_funct

  val reg1_data = // forwarding...
  alu.io.op1 := Mux(
    io.aluop1_source === ALUOp1Source.InstructionAddress,
    io.instruction_address,
    reg1_data
  )

  val reg2_data = // forwarding...
  alu.io.op2 := Mux(
    io.aluop2_source === ALUOp2Source.Immediate,
    io.immediate,
    reg2_data
  )
// ...
```
```scala
// ALU.scala
// ...
  io.result := 0.U
  switch(io.func) {
    is(ALUFunctions.add) {
      io.result := io.op1 + io.op2
    }
// ...
```
![image](https://hackmd.io/_uploads/B1yg7tO-We.png)

## Memory: No memory access needed
![image](https://hackmd.io/_uploads/BkeZmFd--g.png)

## Write-Back
![image](https://hackmd.io/_uploads/rkGf7tOWWx.png)

