# Assignment3: Single-cycle RISC-V CPU
contributed by < [terry23304](https://github.com/terry23304/ca2023-lab3) >
## Hello World in Chisel
```c
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
}
```
Switch the LED output every `CNT_MAX` clock cycles.
It is a I/O Bundle that has only one output signal and no input signals. It includes two registers, `cntReg` and `blkReg`, `cntReg` is used to count the number of clock cycles passed. When it reaches`CNT_MAX`, which is `24999999`, reset `cntReg` to 0 and invert the value of `blkReg`. The output will be the same as `blkReg`
## MyCPU
### Instruction Fetch
![image](https://hackmd.io/_uploads/Sk6nMUVB6.png)
Using `jump_flag_id` to determine next pc will be `jump_address_id` or `pc + 4`.
![image](https://hackmd.io/_uploads/H1BWX8EHp.png)
`instruction valid` is false only in the beginning. Therefore, the instruction is `0x00000013`, and after that, the instruction will be `0x00000000`.
### Instruction Decode
![image](https://hackmd.io/_uploads/Bkz6Wv4H6.png)
The testing instruction would be:
- sw x10, 4(x0)
- lui x5, 2
- add x3, x1, x2
![image](https://hackmd.io/_uploads/HkpeFwNBp.png)
Set `memory_read_enable` to `1` when the instruction is of L type and set `memory_write_enable` to `1` when the instruction is of S type. Therefore, `memory_write_enable` is set to `1` only when executing the `instruction sw x10`, 4(x0).
### Execute
![image](https://hackmd.io/_uploads/rknCbDNHT.png)
Using aluop_source to determine the values of `op1` and `op2`. When aluop_source is 0, op will be set to the data in register; otherwise, op will be set to 0 and immediate value.
![image](https://hackmd.io/_uploads/H1UpwONrT.png)
## Run RISC-V assembly code in Homework2
- Move assembly code to csrc directory.
- Modify the makefile in csrc directory to generate corresponding .asmbin file
```
BINS = \
fibonacci.asmbin \
hello.asmbin \
mmio.asmbin \
quicksort.asmbin \
sb.asmbin \
binarization.asmbin
```
- Add test in CPUTest.scala
- Run `make update`
- Run `sbt "testOnly riscv.singlecycle.BinarizationTest"`
```
[info] BinarizationTest:
[info] Single Cycle CPU
[info] - should do binarization with threshold 128
[info] Run completed in 3 seconds, 314 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 4 s, completed Dec 1, 2023, 12:24:30 AM
```
## Analysis
Execute the following command to generate Verilog file.z
```
$ make verilator
$ ./run-verilator.sh -instruction src/main/resources/binarization.asmbin -time 2000 -vcd dump.vcd
```
Then, run `gtkwave dump.vcd` to check waveform.