# Assignment3: single-cycle RISC-V CPU
contributed by < [Daniel-0224](https://github.com/Daniel-0224) >
## Hello World in Chisel
This code toggles an LED output based on a counter `cntReg`.LED change after `CNT_MAX` cycles.
```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 := cntReg + 1.U
when(cntReg === CNT_MAX) {
cntReg := 0.U
blkReg := ~blkReg
}
io.led := blkReg
}
```
* The module has an IO bundle, which includes an output named `led` of type UInt with a width of 1 bit.
```scala
val io = IO(new Bundle {
val led = Output(UInt(1.W))
})
```
* `cntReg` is a counter.
* `blkReg` is the current state of the LED.
* `cntReg` is incremented by 1 in each clock cycle.
```scala
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` reaches the value of CNT_MAX, it resets to 0, and blkReg toggles its value
```scala
when(cntReg === CNT_MAX) {
cntReg := 0.U
blkReg := ~blkReg
}
```
## complete the code of lab3
The code in ca2023_lab3 is nearly complete.I only have to write some instruction.
### Run the test
This is the command
```shell
$ sbt test
```
Here is the output
```
[info] welcome to sbt 1.9.7 (Eclipse Adoptium Java 11.0.21)
[info] loading settings for project ca2023-lab3-build from plugins.sbt ...
[info] loading project definition from /home/tseng/ca2023-lab3/project
[info] loading settings for project root from build.sbt ...
[info] set current project to mycpu (in build file:/home/tseng/ca2023-lab3/)
[info] InstructionFetchTest:
[info] InstructionFetch of Single Cycle CPU
[info] - should fetch instruction
[info] ExecuteTest:
[info] Execution of Single Cycle CPU
[info] - should execute correctly
[info] InstructionDecoderTest:
[info] InstructionDecoder of Single Cycle CPU
[info] - should produce correct control signal
[info] QuicksortTest:
[info] Single Cycle CPU
[info] - should perform a quicksort on 10 numbers
[info] FibonacciTest:
[info] Single Cycle CPU
[info] - should recursively calculate Fibonacci(10)
[info] ByteAccessTest:
[info] Single Cycle CPU
[info] - should store and load a single byte
[info] RegisterFileTest:
[info] Register File of Single Cycle CPU
[info] - should read the written content
[info] - should x0 always be zero
[info] - should read the writing content
[info] Run completed in 52 seconds, 865 milliseconds.
[info] Total number of tests run: 9
[info] Suites: completed 7, aborted 0
[info] Tests: succeeded 9, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 55 s, completed Nov 30, 2023, 1:30:34 PM
```
### InstructionFetchTest
In this unit test utilizes Random.nextInt(2) to determine jump or not.
Then,we checks whether the module generate correct PC address.
* Initial address : `0X1000`
Because `io_jump_flag_id = 0`, next instruction address will be `pc+4 = 0X1004`

* address : `0X1004`
Because `io_jump_flag_id = 1`, next instruction address will jump to `0X1000`

### InstructionDecoderTest
In this unit test is to determine `memory_read_enable` and `memory_write_enable` based on the opcode.The following instructions are `sw`、`lui`、`add`.
* `opcode` is 0X23. It means it's a S type instruction.`memory_write_enable` set to 1.
* There doesn't have the instruction that will trigger the signal, so the `memory_read_enable` is always set to 0.

### ExecuteTest
In this unit, we test `add` & `beq` instruction
* `add` instruction, we can see that `io_mem_alu_result` = `io_reg1_data`+`io_reg2_data`, `opcode` = `0X33`, and `io_if_jump_flag` = 0.

* `beq`instruction, `io_reg1_data` != `io_reg2_data`.So, `io_if_jump_flag` = 0.

* `beq`instruction, `io_reg1_data` = `io_reg2_data`.So, `io_if_jump_flag` = 1.

## HW2 Adaptation
First we have to add the test class to CPUTest.scala
```scala
class HW2Test extends AnyFlatSpec with ChiselScalatestTester {
behavior.of("Single Cycle CPU")
it should "implement HW2" in {
test(new TestTopModule("hw.asmbin")).withAnnotations(TestAnnotations.annos) { c =>
for (i <- 1 to 50) {
c.clock.step(1000)
c.io.mem_debug_read_address.poke((i * 4).U) // Avoid timeout
}
c.io.mem_debug_read_address.poke(4.U)
c.clock.step()
c.io.mem_debug_read_data.expect(1.U)
c.io.mem_debug_read_address.poke(8.U)
c.clock.step()
c.io.mem_debug_read_data.expect(5.U)
c.io.mem_debug_read_address.poke(12.U)
c.clock.step()
c.io.mem_debug_read_data.expect(3.U)
}
}
}
```
* $ sbt "testOnly riscv.singlecycle.HW2Test"
```
tseng@tseng-virtual-machine:~/ca2023-lab3$ sbt "testOnly riscv.singlecycle.HW2Test"
[info] welcome to sbt 1.9.7 (Eclipse Adoptium Java 11.0.21)
[info] loading settings for project ca2023-lab3-build from plugins.sbt ...
[info] loading project definition from /home/tseng/ca2023-lab3/project
[info] loading settings for project root from build.sbt ...
[info] set current project to mycpu (in build file:/home/tseng/ca2023-lab3/)
[info] compiling 1 Scala source to /home/tseng/ca2023-lab3/target/scala-2.13/test-classes ...
[info] HW2Test:
[info] Single Cycle CPU
[info] - should implement HW2
[info] Run completed in 17 seconds, 128 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: 30 s, completed Dec 2, 2023, 8:58:24 PM
```
* This is waveform gragh
