# Assignment3: Single-cycle RISC-V CPU
contributed by < [`RayChen`](https://github.com/padaray) >
## Environment Issue
When executing the `sbt -version` command in the terminal of VSCode, the response is correct.
```
sbt version in this project: 1.9.7
sbt script version: 1.9.7
```
When executing `sbt test` the following error occurs.
```
[error] /home/ray870317/java/jdk/ca2023-lab3/src/main/scala/riscv/core/ALU.scala:6:8: not found: object chisel3
[error] import chisel3._
[error] ^
```
Initially, I thought that the "build.sbt" file was not properly configured, causing it to be unable to recognize the `import chisel3`. Last, it was discovered that opening the folder in VSCode needs to be done from the root directory `/java/jdk/ca2023-lab3`.
</br>
## Operation of ‘Hello World in Chisel’
```scala
// Hello World in Chisel
class Hello extends Module {
val io = IO(new Bundle {
val led = Output(UInt(1.W))
})
val CNT_MAX = (50000000 / 2 - 1).U;
val cntReg = RegInit(0.U(32.W))
val blkReg = RegInit(0.U(1.W))
cntReg := cntReg + 1.U
when(cntReg === CNT_MAX) {
cntReg := 0.U
blkReg := ~blkReg
}
io.led := blkReg
}
```
1. `led` is an unsigned integer output with a width of 1 bit
2. `CNT_MAX` is a constant with a value of 24999999
3. `cntReg` and`blkReg` are both unsigned integers with widths of 32 bits and 1 bit
4. `cntReg` increments by 1 for each cycle. When it reaches 24999999, it resets to 0, and simultaneously, `blkReg` is inverted.
5. Assigns the value of `blkReg` to the output `io.led`.
In conclusion, this code appears to make the led flash once every 24999999 cycles.
</br>
**Enhance operation by incorporating logic circuit**
```scala
class Hello extends Module {
val io = IO(new Bundle {
val led = Output(UInt(1.W))
})
val CNT_MAX = (50000000 / 2 - 1).U;
val cntReg = RegInit(0.U(32.W))
val blkReg = RegInit(0.U(1.W))
cntReg := Mux(cntReg === CNT_MAX,0.U,cntReg + 1.U)
blkReg := Mux(cntReg === CNT_MAX,~blkReg,blkReg)
io.led := blkReg
}
```
</br>
## Complete Lab3 and Test
After completing lab3 with the filled-in code, we need to run tests using the test files located under the directory `/ca2023-lab3/src/test/scala/riscv/singlecycle`, and I will explain the testing process using Waveform.
The waveform file is generated using the following command :
```
$ WRITE_VCD=1 sbt test
```
generated `.vcd` file will store at `/ca2023-lab3/test_run_dir`
</br>
### **InstructionFetchTest**
**Code Behavior :**
   We have a random constant, either 0 or 1. When the is constant equal to 0, `jump_flag_id` set False, and `instruction address` is incremented by 4; When the constant is 1, `jump_flag_id` set True, and `instruction address` jumps to 0x1000. These actions are repeated 100 times.
**Waveform Analysis :**
- Initial part :

   At the beginning, we initialize the value. The `instruction_valid` is set after one clock cycle, and the program starts executing instructions sequentially after a delay of 5 ps. I don't understand why this delay exists.
- case 0 :

   When constant equal to 0, `jump_flag_id` is set to 0 (False), and the instruction address changes from 0x1000 to 0x1004, without performing a jump action.
- case 1 :

   When constant equal to 1, `jump_flag_id` is set to 1 (True), and the instruction address from 0x1010 jump back to 0x1000.
### **InstructionDecoderTest**
**Code Behavior :**
   We sequentially inputs `sw`, `lui`, and `add` instructions while checking the signals of `ex_aluop1_source`, `ex_aluop2_source`, `regs_reg1_read_address`, and `regs_reg2_read_address` to verify if these four variables behave as expected.
**Waveform Analysis :**
- sw instruction :

   "0x00a02223" address represents the `sw` instruction. We can observe that the `memory_read` signal is 0, and the `memory_write` signal is 1, indicating that data can be written to memory.
- lui instruction :

   "0x00a02223" address represents the `lui` instruction. The `aluop1` signal matches the expected value 1. `memory_read` and `memory_write` are both 0, indicating there is no memory access.
### **ExecuteTest**
**Code Behavior :**
   Testing whether the ALU functions correctly. The test includes `add` and `beq` instructions. For the `add` instruction, it verifies if the sum of two values is correct. In the case of the beq instruction, it tests whether if_jump_flag is set to 1 when the two values are equal.
**Waveform Analysis :**

   the sum of `op1` and `op2` equals result, indicating that our calculation result is correct. When `func` is 1, it corresponds to the `add` instruction.
### **FibonacciTest**
**Code Behavior :**
   Execute the fibonacci.asmbin with the CPU and verify if the values stored in the memory locations it occupies match our expected values.