# Construct a single-cycle CPU with Chisel
contributed by < [TRChen11011](https://github.com/TRChen11011/ca2023-lab3) >
## Environment setup
OS : Ubuntu 22.
### Install
jave : jdk 11
verilog : verilator, gtkwave
apt : curl, sbt
## MyCPU
### Finish Scala
#### IFE
:::info
Need to consider jal,j...... etc. instruction.
:::
At first,I don't consider jump,so it went wrong first.
#### ID
:::info
consider the instruction whether L type or S type.
Then give the `io.memory_read_enable` and `io.memory_write_enable`
:::
#### EXE
:::info
Need to consider op1 and op2 need address or reg_data.
:::
At first,I don't consider Itype,so it went wrong first.
#### CPU
:::info
connect EXE stage with other stages.
:::
### Check Waveform
#### IFE

When `io.jump_flag = 1` PC will be the PC that the instruction want to jump `100C -> 1000`
#### ID

According to `opcode = 23`,so the instruction will be `aupic`,which will be L type.
#### EXE

`aluop1_source`is true, so op1 will be `io.instruction_address`.
## Modify HW2
I change the instruction `mv` into `addi` for Match MyCPU.
### orignal code
```c=27
mv a0, s0
jal ra, CLZ
mv t5, a0 #A's CLZ -> t5
mv a0, s1
```
### modified code
```c=27
addi a0, s0, 0
jal ra, CLZ
addi t5, a0, 0 #A's CLZ -> t5
addi a0, s1, 0
```
## Modify CPUTest.scala
### failed case
Add code below
```c=117
class mul_clz_Test extends AnyFlatSpec with ChiselScalatestTester {
behavior.of("Single Cycle CPU")
it should "0x1234567 * 0xffffdddd = 0x1234540a8f5c3d98" in {
test(new TestTopModule("mul_clz.asmbin")).withAnnotations(TestAnnotations.annos) { c =>
for (i <- 1 to 50) {
c.clock.step(1000)
c.io.regs_debug_read_address.poke((i * 4).U) // Avoid timeout
}
c.io.regs_debug_read_address.poke(18.U)
c.io.regs_debug_read_data.expect(0x1234540a.U)
c.io.regs_debug_read_address.poke(19.U)
c.io.regs_debug_read_data.expect(0x8f5c3d98.U)
}
}
}
```
But I met these problem :
:::warning
> [info] <span style="color:red"> - should 0x1234567 * 0xffffdddd = 0x1234540a8f5c3d98 *** FAILED ***</span>
> [info] <span style="color:red"> java.lang.IllegalArgumentException: requirement failed: UInt literal -1889780328 is negative</span>
> [info] <span style="color:red">at scala.Predef.require(Predef.scala:337)</span>
> [info] <span style="color:red"> at chisel3.internal.firrtl.ULit.<init>(IR.scala:150)</span>
> [info] <span style="color:red"> at chisel3.UIntFactory.Lit(UIntFactory.scala:21)</span>
> [info] <span style="color:red"> at chisel3.UIntFactory.Lit(UIntFactory.scala:20)</span>
> [info] <span style="color:red"> at chisel3.packageUInt.Lit(package.scala:182)</span>
> [info] <span style="color:red"> at chisel3.packagefromBigIntToLiteral.U(package.scala:51)</span>
> [info] <span style="color:red"> at riscv.singlecycle.mul_clz_Test.anonfunnew40(CPUTest.scala:128)</span>
> [info] <span style="color:red"> at riscv.singlecycle.mul_clz_Test.anonfunnew40adapted(CPUTest.scala:120)</span>
> [info] <span style="color:red"> at chiseltest.internal.GenericBackend.anonfunrun1(GenericBackend.scala:170)</span>
> [info] <span style="color:red"> at chiseltest.internal.ThreadedBackendTesterThreadanon1.anonfunrun1(ThreadedBackend.scala:495)</span>
> [info] <span style="color:red"> ...</span>
:::
### Modify again
After I modify the code
```scla=125
c.io.regs_debug_read_address.poke(18.U)
c.io.regs_debug_read_data.expect(0x1234540aL.U)
c.io.regs_debug_read_address.poke(19.U)
c.io.regs_debug_read_data.expect(0x8f5c3d98L.U)
```
:::success
> [info] <span style="color:green"> mul_clz_Test:
> [info] <span style="color:green">Single Cycle CPU</span>
> [info] <span style="color:green">- should 0x1234567 * 0xffffdddd = 0x1234540a8f5c3d98</span>
> [info] <span style="color:blue">Run completed in 23 seconds, 303 milliseconds.</span>
> [info] <span style="color:blue">Total number of tests run: 11</span>
> [info] <span style="color:blue">Suites: completed 9, aborted 0</span>
> [info] <span style="color:blue">Tests: succeeded 11, failed 0, canceled 0, ignored 0, pending 0</span>
> [info] <span style="color:green">All tests passed.</span>
> [success] <span style="color:green">Total time: 27 s, completed Nov 22, 2023, 1:18:53 PM</span>
:::
## Verilator
WRITE_VCD=1 sbt test
:::success
> [info] <span style="color:blue">Run completed in 26 seconds, 573 milliseconds.</span>
> [info] <span style="color:blue">Total number of tests run: 11</span>
> [info] <span style="color:blue">Suites: completed 9, aborted 0</span>
> [info] <span style="color:blue">Tests: succeeded 11, failed 0, canceled 0, ignored 0, pending 0</span>
> [info] <span style="color:green">All tests passed.</span>
> [success] <span style="color:green">Total time: 27 s, completed Nov 22, 2023, 1:21:59 PM</span>
:::
make verilator
:::success
> <span style="color:green">Total time: 3 s, completed Nov 22, 2023, 1:26:33 PM</span>
:::
./run-verilator.sh -instruction src/main/resources/mul_clz.asmbin
:::success
> -time 10000
> -memory 1048576
> -instruction src/main/resources/mul_clz.asmbin
> [-------------------->] 100%
:::
hexdump src/main/resources/mul_clz.asmbin | head -1
:::success
> 0000000 00ef 1c00 0113 ffc1 2023 00a1 0417 0000
:::

above waveform prove the instruction is correct.