# 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. ``` ![InstructionFetch](https://hackmd.io/_uploads/HkO8uZarp.jpg) ### 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. ``` ![InstructionDecode](https://hackmd.io/_uploads/H1bPd-aBp.jpg) ### 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. ``` ![Execute](https://hackmd.io/_uploads/ry329-6Sa.jpg)