Assignment3: Single-cycle RISC-V CPU

contributed by < RayChen >

Environment Issue

When executing the sbt -version command in the terminal of VSCode, the response is correct.

sbt version in this project: 1.9.7
sbt script version: 1.9.7

When executing sbt test the following error occurs.

[error] /home/ray870317/java/jdk/ca2023-lab3/src/main/scala/riscv/core/ALU.scala:6:8: not found: object chisel3
[error] import chisel3._
[error]        ^

Initially, I thought that the "build.sbt" file was not properly configured, causing it to be unable to recognize the import chisel3. Last, it was discovered that opening the folder in VSCode needs to be done from the root directory /java/jdk/ca2023-lab3.

Operation of ‘Hello World in Chisel’

// 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
}
  1. led is an unsigned integer output with a width of 1 bit
  2. CNT_MAX is a constant with a value of 24999999
  3. cntReg andblkReg are both unsigned integers with widths of 32 bits and 1 bit
  4. cntReg increments by 1 for each cycle. When it reaches 24999999, it resets to 0, and simultaneously, blkReg is inverted.
  5. Assigns the value of blkReg to the output io.led.

In conclusion, this code appears to make the led flash once every 24999999 cycles.

Enhance operation by incorporating logic circuit

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 := Mux(cntReg === CNT_MAX,0.U,cntReg + 1.U)
  blkReg := Mux(cntReg === CNT_MAX,~blkReg,blkReg)
  io.led := blkReg
}

Complete Lab3 and Test

After completing lab3 with the filled-in code, we need to run tests using the test files located under the directory /ca2023-lab3/src/test/scala/riscv/singlecycle, and I will explain the testing process using Waveform.

The waveform file is generated using the following command :

$ WRITE_VCD=1 sbt test

generated .vcd file will store at /ca2023-lab3/test_run_dir

InstructionFetchTest

Code Behavior :
   We have a random constant, either 0 or 1. When the is constant equal to 0, jump_flag_id set False, and instruction address is incremented by 4; When the constant is 1, jump_flag_id set True, and instruction address jumps to 0x1000. These actions are repeated 100 times.

Waveform Analysis :

  • Initial part :

    Image Not Showing Possible Reasons
    • The image was uploaded to a note which you don't have access to
    • The note which the image was originally uploaded to has been deleted
    Learn More →

       At the beginning, we initialize the value. The instruction_valid is set after one clock cycle, and the program starts executing instructions sequentially after a delay of 5 ps. I don't understand why this delay exists.

  • case 0 :

    Image Not Showing Possible Reasons
    • The image was uploaded to a note which you don't have access to
    • The note which the image was originally uploaded to has been deleted
    Learn More →

       When constant equal to 0, jump_flag_id is set to 0 (False), and the instruction address changes from 0x1000 to 0x1004, without performing a jump action.

  • case 1 :

    Image Not Showing Possible Reasons
    • The image was uploaded to a note which you don't have access to
    • The note which the image was originally uploaded to has been deleted
    Learn More →

       When constant equal to 1, jump_flag_id is set to 1 (True), and the instruction address from 0x1010 jump back to 0x1000.

InstructionDecoderTest

Code Behavior :
   We sequentially inputs sw, lui, and add instructions while checking the signals of ex_aluop1_source, ex_aluop2_source, regs_reg1_read_address, and regs_reg2_read_address to verify if these four variables behave as expected.

Waveform Analysis :

  • sw instruction :

    Image Not Showing Possible Reasons
    • The image was uploaded to a note which you don't have access to
    • The note which the image was originally uploaded to has been deleted
    Learn More →

       "0x00a02223" address represents the sw instruction. We can observe that the memory_read signal is 0, and the memory_write signal is 1, indicating that data can be written to memory.

  • lui instruction :

    Image Not Showing Possible Reasons
    • The image was uploaded to a note which you don't have access to
    • The note which the image was originally uploaded to has been deleted
    Learn More →

       "0x00a02223" address represents the lui instruction. The aluop1 signal matches the expected value 1. memory_read and memory_write are both 0, indicating there is no memory access.

ExecuteTest

Code Behavior :
   Testing whether the ALU functions correctly. The test includes add and beq instructions. For the add instruction, it verifies if the sum of two values is correct. In the case of the beq instruction, it tests whether if_jump_flag is set to 1 when the two values are equal.

Waveform Analysis :

image
   the sum of op1 and op2 equals result, indicating that our calculation result is correct. When func is 1, it corresponds to the add instruction.

FibonacciTest

Code Behavior :
   Execute the fibonacci.asmbin with the CPU and verify if the values stored in the memory locations it occupies match our expected values.