# Assignment3: single-cycle RISC-V CPU
contributed by < [spadee27357](https://github.com/spadee27357) >
```shell
# Ubuntu 22.04
$ sudo apt install build-essential verilator gtkwave
$ curl -s "https://get.sdkman.io" | bash
$ source "$HOME/.sdkman/bin/sdkman-init.sh
$ sdk install java 11.0.21-tem
$ sdk install sbt
```
## Chisel Tutorial
```
$ git clone https://github.com/ucb-bar/chisel-tutorial
$ cd chisel-tutorial
$ git checkout release
$ bt run
```
Reference output:
```
[info] Loading project definition from /home/james/ca2023-lab3/chisel-tutorial/project
[info] Loading settings for project chisel-tutorial from build.sbt ...
[info] Set current project to chisel-tutorial (in build file:/home/james/ca2023-lab3/chisel-tutorial/)
[info] Updating
https://repo1.maven.org/maven2/edu/berkeley/cs/chisel-iotesters_2.12/maven-meta…
No new update since 2023-01-12 14:48:24
[info] Resolved dependencies
[info] Compiling 56 Scala sources to /home/james/ca2023-lab3/chisel-tutorial/target/scala-2.12/classes ...
[info] running hello.Hello
[info] [0.002] Elaborating design...
[info] [0.063] Done elaborating.
Computed transform order in: 156.8 ms
Total FIRRTL Compile Time: 419.4 ms
End of dependency graph
Circuit state created
[info] [0.000] SEED 1701606622339
test Hello Success: 1 tests passed in 6 cycles taking 0.009268 seconds
[info] [0.002] RAN 1 CYCLES PASSED
```
Using Docker
```
$ docker run -it --rm -p 8888:8888 sysprog21/chisel-bootcamp
```
If we success run it.Then we can get LONG_RANDOM_TOKEN with http://127.0.0.1:8888/? , so we can start to learn Learn Chisel online
## 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
}
```
- CNT_MAX: CNT_MAX is a constant set to 29,999,999, representing the maximum count value for the counter.
- cntReg: cntReg is a 32-bit unsigned integer register, initialized to 0. With each clock cycle, the value of this register is incremented by 1.
- blkReg: blkReg is a 1-bit unsigned integer register, initialized to 0 using RegInit(0.U(1.W)). When cntReg reaches CNT_MAX, cntReg is reset to zero, but blkReg remains unchanged.
- LED State Control: Upon reaching each CNT_MAX unit, the value of blkReg is inverted (from 0 to 1, or from 1 to 0), and this value is assigned to the LED output (io.led := blkReg), thereby realizing the blinking effect of the LED light.
## Single-cycle RISC-V CPU
```
$ git clone https://github.com/sysprog21/ca2023-lab3
$ cd ca2023-lab3
```
To simulate and run tests for this project, execute the following commands under the ca2023-lab3 directory.
```
$ sbt test
```
Result:
```
[info] *** 6 TESTS FAILED ***
[error] Failed tests:
[error] riscv.singlecycle.InstructionDecoderTest
[error] riscv.singlecycle.ByteAccessTest
[error] riscv.singlecycle.InstructionFetchTest
[error] riscv.singlecycle.ExecuteTest
[error] riscv.singlecycle.FibonacciTest
[error] riscv.singlecycle.QuicksortTest
[error] (Test / test) sbt.TestsFailedException: Tests unsuccessful
```
so on the above error message, we need to complete the code.
### InstructionFetch
The system first fetches the next instruction from memory based on the value of the program counter. Then, it checks the jump_flag_id, if the flag is true, the program counter is updated to the jump_address, thereby altering the program's execution flow. if the flag is false, the program counter is simply increased by 4 units.
```
$ sbt "testOnly riscv.singlecycle.InstructionFetchTest"
```
```
[info] InstructionFetchTest:
[info] InstructionFetch of Single Cycle CPU
[info] - should fetch instruction
[info] Run completed in 4 seconds, 909 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.
```

### InstructionDecode
L-type:if the instructions (lw lh lb lhu lbu), whose opcode is 0x3, the memory_read_enable is set to true, indicating that data needs to be read from memory.Otherwise, false.
S-type :if the instructions (sw sh sb), whose opcode is 0x23, the memory_write_enable is set to true, indicating that data needs to be written into memory.Otherwise, false.
```
$ sbt "testOnly riscv.singlecycle.InstructionDecoderTest"
```
```
[info] InstructionDecoderTest:
[info] InstructionDecoder of Single Cycle CPU
[info] - should produce correct control signal
[info] Run completed in 5 seconds, 50 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.
```

### Execute
Connecting the ALU Control Unit to the ALU: The output alu_funct from the alu_ctrl unit is connected to the func input of the ALU, determining the specific operation that the ALU should perform.
The first operand op1 is determined by io.aluop1_source. If io.aluop1_source is true, then op1 is set to instruction_address. If it is false, it is set to reg1_data.
The second operand op2 is determined by io.aluop2_source. If io.aluop2_source is true, then op2 is set to immediate. If it is false, it is set to reg2_data.
```
$ sbt "testOnly riscv.singlecycle.ExecuteTest"
```
```
[info] ExecuteTest:
[info] Execution of Single Cycle CPU
[info] - should execute correctly
[info] Run completed in 5 seconds, 254 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.
```
