# 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` ![image](https://hackmd.io/_uploads/Hk6tov_rp.png) * address : `0X1004` Because `io_jump_flag_id = 1`, next instruction address will jump to `0X1000` ![image](https://hackmd.io/_uploads/BJnIiv_H6.png) ### 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. ![image](https://hackmd.io/_uploads/rkzix_dBT.png) ### 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. ![image](https://hackmd.io/_uploads/HyBGnYOHp.png) * `beq`instruction, `io_reg1_data` != `io_reg2_data`.So, `io_if_jump_flag` = 0. ![image](https://hackmd.io/_uploads/Sy2X0tdrp.png) * `beq`instruction, `io_reg1_data` = `io_reg2_data`.So, `io_if_jump_flag` = 1. ![image](https://hackmd.io/_uploads/H1M80KuS6.png) ## 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 ![image](https://hackmd.io/_uploads/Sknwpj_ra.png)