# RV32C support for srv32
> 宋唯廷, 劉孟璋
:::info
The [RV32IM](#RV32IM), [RV32C](#RV32C), [SRV32](#SRV32) sections of this note serve as the theoretical notes.
The implementation part of srv32c starts from the [Implementation](#Implementation) section.
:::
[GitHub](https://github.com/timsong1/srv32)
<br>
# RV32IM
## Format
### `R-Type`

| inst | length |
|:------:|:-----------------:|
| op | 7-bit **[0-6]** |
| rd | 5-bit **[7-11]** |
| funct3 | 3-bit **[12-14]** |
| rs1 | 5-bit **[15-19]** |
| rs2 | 5-bit **[20-24]** |
| funct7 | 7-bit **[25-31]** |
**instructions** - `SLT`, `SLTU`, `AND`, `OR`, `XOR`, `SLL`, `SRL`, `SRA`, `ADD`, `SUB`, `MUL`, `MULH`, `MULSU`, `MULU`, `DIV`, `DIVU`, `REM`, `REMU`
> M-extension instructions expande to `R-Type` format
<br>
### `I-Type`

| inst | length |
|:------:|:------------------:|
| op | 7-bit **[0-6]** |
| rd | 5-bit **[7-11]** |
| funct3 | 3-bit **[12-14]** |
| rs1 | 5-bit **[15-19]** |
| imm | 12-bit **[20-31]** |
**instructions** - `ADDI`, `SLTI`, `SLTIU`, `ANDI`, `ORI`, `XORI`, `SLLI`, `SLRI`, `SRAI`, `LW`, `LH`, `LHU`, `LB`, `LBU`
<br>
### `S-Type`

| inst | length |
|:------:|:-----------------:|
| op | 7-bit **[0-6]** |
| imm | 5-bit **[7-11]** |
| funct3 | 3-bit **[12-14]** |
| rs1 | 5-bit **[15-19]** |
| rs2 | 5-bit **[20-24]** |
| imm | 7-bit **[25-31]** |
**instructions** - `SB`, `SH`, `SW`
<br>
### `B-Type`

| inst | length |
|:------:|:-----------------:|
| op | 7-bit **[0-6]** |
| imm | 1-bit **[7]** |
| imm | 4-bit **[8-11]** |
| funct3 | 3-bit **[12-14]** |
| rs1 | 5-bit **[15-19]** |
| rs2 | 5-bit **[20-24]** |
| imm | 6-bit **[25-30]** |
| imm | 1-bit **[31]** |
**instructions** - `BEQ`, `BNE`, `BLT`, `BLTU`, `BGE`, `BGEU`
<br>
### `U-Type`

| inst | length |
|:----:|:------------------:|
| op | 7-bit **[0-6]** |
| rd | 5-bit **[7-11]** |
| imm | 20-bit **[12-31]** |
**instructions** - `LUI`, `AUIPC`
<br>
### `J-Type`

| inst | length |
|:----:|:------------------:|
| op | 7-bit **[0-6]** |
| rd | 5-bit **[7-11]** |
| imm | 8-bit **[12-19]** |
| imm | 1-bit **[20]** |
| imm | 10-bit **[21-30]** |
| imm | 1-bit **[31]** |
**instructions** - `JAL`, `JALR`
<br>
### `NOP`

**instructions** - `NOP`
> `NOP` instruction is encoded as `ADDI x0, x0, 0`
<br>
### `SYSTEM`

**instructions** - `ECALL`, `EBREAK`
<br>
## Decode
<table>
<thead>
<tr>
<th style="text-align: center">op</th>
<th style="text-align: center">description</th>
<th style="text-align: center">type</th>
</tr>
</thead>
<tbody>
<tr>
<td>0110011</td>
<td>arithmetic between <code>reg</code> and <code>reg</code></td>
<td>R-Type</td>
</tr>
<tr>
<td>0010011</td>
<td>arithmetic between <code>reg</code> and <code>imm</code></td>
<td rowspan="2">I-Type</td>
</tr>
<tr>
<td>0010011</td>
<td>load data</td>
</tr>
<tr>
<td>0100011</td>
<td>store data</td>
<td rowspan>S-Type</td>
</tr>
<tr>
<td>1100011</td>
<td>conditional branch</td>
<td rowspan>B-Type</td>
</tr>
<tr>
<td>0010011</td>
<td rowspan="2">upper <code>imm</code> arithmetic</td>
<td rowspan="2">U-Type</td>
</tr>
<tr>
<td>0110111</td>
</tr>
<tr>
<td>1101111</td>
<td rowspan="2">unconditional jump</td>
<td rowspan="2">J-Type</td>
</tr>
<tr>
<td>1100111</td>
</tr>
</tbody>
</table>
<br>
# RV32C
## Introduction
When certain 32-bit instructions have specific characteristics that allow them to be converted into compressed instructions:
> 1. the immediate or address offset is small
> 2. one of the registers is the zero register (x0), the ABI link register (`x1`), or the ABI stack pointer (`x2`)
> 3. the **<font color="red">destination register</font>** and the **<font color="red">first source register</font>** are identical
> 4. the registers used are **<font color="red">the 8 most popular ones</font>** (`x8` - `x15`). This is also the reason why some register fields in the C extension instructions are only **<font color="red">3 bits long</font>**
RVC is designed such that each compressed instruction maps directly to a single 32-bit instruction in the base ISA (e.g., RV32I/E, RV64I, RV128I) or the F/D extensions. This design offers two key benefits:
1. **Simplified Hardware**: Hardware can expand RVC instructions during decoding, minimizing changes to existing microarchitectures and simplifying verification.
2. **Compiler Flexibility**: Compilers do not need to be aware of RVC; compression can be handled by the assembler and linker. However, compression-aware compilers can produce better results.
The C extension integrates seamlessly with other standard extensions (e.g., M, A, F) without restricting functionality or reducing architectural flexibility.
The C extension is not a standalone ISA and must be used alongside a base ISA.

<br>
## Format
### `CR-Type`
**Instructions for arithmetic operations between registers**

| inst | length |
|:------:|:-----------------:|
| op | 2-bit **[0-1]** |
| rs2 | 5-bit **[2-6]** |
| rs1/rd | 5-bit **[7-11]** |
| funct4 | 4-bit **[12-15]** |
**instructions** - `C.JR`, `C.JALR`, `C.MV`, `C.ADD`
<br>
### `CI-Type`
**Instructions for arithmetic operations between immediate value and register**

| inst | length |
|:------:|:-----------------:|
| op | 2-bit **[0-1]** |
| imm | 5-bit **[2-6]** |
| rs1/rd | 5-bit **[7-11]** |
| imm | 1-bit **[12]** |
| funct3 | 3-bit **[13-15]** |
**instructions** - `C.LWSP`, `C.LDSP`, `C.LQSP`, `C.FLWSP`, `C.FLDSP`, `C.LI`, `C.LUI`, `C.ADDI`, `C.ADDIW`, `C.ADDI16SP`, `C.SLLI`
<br>
### `CSS-Type`
**Instructions for stack-pointer-based stores**

| inst | length |
|:------:|:-----------------:|
| op | 2-bit **[0-1]** |
| rs2 | 5-bit **[2-6]** |
| imm | 1-bit **[7-12]** |
| funct3 | 3-bit **[13-15]** |
**instructions** - `C.SWSP`, `C.SDSP`, `C.SQSP`, `C.FSWSP`, `C.FSDSP`
<br>
### `CIW-Type`
**Instructions for stack-pointer-based loads**

| inst | length |
|:------:|:-----------------:|
| op | 2-bit **[0-1]** |
| rd' | 3-bit **[2-4]** |
| imm | 8-bit **[5-12]** |
| funct3 | 3-bit **[13-15]** |
**instructions** - `C.ADDI4SPN`
<br>
### `CL-Type`
**Instructions for register-based loads**

| inst | length |
|:------:|:-----------------:|
| op | 2-bit **[0-1]** |
| rd' | 3-bit **[2-4]** |
| imm | 2-bit **[5-6]** |
| rs1' | 3-bit **[7-9]** |
| imm | 2-bit **[10-12]** |
| funct3 | 3-bit **[13-15]** |
**instructions** - `C.LW`, `C.LD`, `C.LQ`, `C.FLW`, `C.FLD`
<br>
### `CS-Type`
**Instructions for register-based stores**

| inst | length |
|:------:|:-----------------:|
| op | 2-bit **[0-1]** |
| rs2' | 3-bit **[2-4]** |
| imm | 2-bit **[5-6]** |
| rs1' | 3-bit **[7-9]** |
| imm | 3-bit **[10-12]** |
| funct3 | 3-bit **[13-15]** |
**instructions** - `C.SW`, `C.SD`, `C.SQ`, `C.FSW`, `C.FSD`
<br>
### `CA-Type`
**Instructions for atomic operations between immediate value and register**

| inst | length |
|:--------:|:-----------------:|
| op | 2-bit **[0-1]** |
| rs2' | 3-bit **[2-4]** |
| funct2 | 2-bit **[5-6]** |
| rs1'/rd' | 3-bit **[7-9]** |
| funct6 | 6-bit **[10-15]** |
**instructions** - `C.AND`, `C.OR`, `C.XOR`, `C.SUB`
<br>
### `CB-Type`
**Instructions for conditional control transfers / register shift**

| inst | length |
|:------:|:-----------------:|
| op | 2-bit **[0-1]** |
| imm | 5-bit **[2-6]** |
| rs1' | 3-bit **[7-9]** |
| imm | 3-bit **[10-12]** |
| funct3 | 3-bit **[13-15]** |
**instructions** - `C.BEQZ`, `C.BNEZ`, `C.SRLI`, `C.SRAI`, `C.ANDI`
<br>
### `CJ-Type`
**Instructions for unconditional control transfers**

| inst | length |
|:------:|:-----------------:|
| op | 2-bit **[0-1]** |
| imm | 11-bit **[2-12]** |
| funct3 | 3-bit **[13-15]** |
**instructions** - `C.J`, `C.JAL`
<br>
### `NOP`

**instructions** - `C.NOP`
<br>
### `Breakpoint`

**instructions** - `C.EBREAK`
<br>
### `Illegal`

<br>
---
<br>
## Decode
### `Type Decode`
The following is the decoding method for C-Extension instructions.
<table style="text-align: center">
<thead>
<tr>
<th style="text-align:center">op</th>
<th style="text-align:center">func3</th>
<th style="text-align:center">type</th>
</tr>
</thead>
<tbody>
<tr>
<td>10</td>
<td>100</td>
<td>CR-type</td>
</tr>
<tr>
<td rowspan="3" style="border-right: 1px solid #52525b">01</td>
<td>000</td>
<td rowspan="5">CI-type</td>
</tr>
<tr>
<td>010</td>
</tr>
<tr>
<td>011</td>
</tr>
<tr>
<td rowspan="2" style="border-right: 1px solid #52525b">10</td>
<td>000</td>
</tr>
<tr>
<td>010</td>
</tr>
<tr>
<td>10</td>
<td>110</td>
<td>CSS-type</td>
</tr>
<tr>
<td>00</td>
<td>000</td>
<td>CIW-type</td>
</tr>
<tr>
<td>00</td>
<td>010</td>
<td>CL-type</td>
</tr>
<tr>
<td>00</td>
<td>110</td>
<td>CS-type</td>
</tr>
<tr>
<td style="color:red"><b>01</b></td>
<td style="color:red"><b>100</b></td>
<td>CA-type</td>
</tr>
<tr>
<td rowspan="3" style="color:red;border-right: 1px solid #52525b"><b>01</b></td>
<td style="color:red"><b>100</b></td>
<td rowspan="3">CB-type</td>
</tr>
<tr>
<td>110</td>
</tr>
<tr>
<td>111</td>
</tr>
<tr>
<td rowspan="2" style="border-right: 1px solid #52525b">01</td>
<td>001</td>
<td rowspan="2">CJ-type</td>
</tr>
<tr>
<td>101</td>
</tr>
</tbody>
</table>
<br>
It can be observed that most of the C-extension instructions can be directly decoded using the `op` and `func3`. However, when `op=01` and `func3=100`, two different instruction formats (CA-type and CB-type) can be decoded.
<br>
<table style="text-align: center">
<thead>
<tr>
<th style="text-align:center">op</th>
<th style="text-align:center">func3</th>
<th style="text-align:center">inst[11:10]</th>
<th style="text-align:center">type</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="6" style="border-right: 1px solid #52525b">01</td>
<td rowspan="4" style="border-right: 1px solid #52525b">100</td>
<td>11</td>
<td>CA-type</td>
</tr>
<tr>
<td>00</td>
<td rowspan="5">CB-type</td>
</tr>
<tr>
<td>01</td>
</tr>
<tr>
<td>10</td>
</tr>
<tr>
<td>110</td>
<td rowspan="2">-</td>
</tr>
<tr>
<td>111</td>
</tr>
</tbody>
</table>
Therefore, in the case where `op=01` and `func3=100`, we will need an additional 2 bits `inst[11:10]` to assist in decoding.
<br>
### `Register Decode`
* `CR-Type`, `CI-Type`, and `CSS-Type` instructions can use any of the RV32I registers (`x0`-`x31`)
> This means that the register field (`rs1` / `rs2` / `rd`) length of these three types of instructions is as same as normal instructions (**5-bit**).
* `CIW-Type`, `CL-Type`, `CS-Type`, `CA-Type`, and `CB-Type` instructions are limited to just 8 of them (`x8`-`x15`)
> This means that the register field (`rs1'` / `rs2'` / `rd'`) length of these five types is shorter than normal instructions (**<font color="red">3-bit</font>**)
> The regisers are mapped to `x8` - `x15`
<table>
<thead>
<tr>
<th colspan=2>reg(3-bit)</th>
<th colspan=2>mapped reg(5-bit)</th>
</tr>
</thead>
<tbody>
<tr>
<td>x0</td>
<td>000</td>
<td>x8 ( <code>s0</code> )</td>
<td>01000</td>
</tr>
<tr>
<td>x1</td>
<td>001</td>
<td>x9 ( <code>s1</code> )</td>
<td>01001</td>
</tr>
<tr>
<td>x2</td>
<td>010</td>
<td>x10 ( <code>a0</code> )</td>
<td>01010</td>
</tr>
<tr>
<td>x3</td>
<td>011</td>
<td>x11 ( <code>a1</code> )</td>
<td>01011</td>
</tr>
<tr>
<td>x4</td>
<td>100</td>
<td>x12 ( <code>a2</code> )</td>
<td>01100</td>
</tr>
<tr>
<td>x5</td>
<td>101</td>
<td>x13 ( <code>a3</code> )</td>
<td>01101</td>
</tr>
<tr>
<td>x6</td>
<td>110</td>
<td>x14 ( <code>a4</code> )</td>
<td>01110</td>
</tr>
<tr>
<td>x7</td>
<td>111</td>
<td>x15 ( <code>a5</code> )</td>
<td>01111</td>
</tr>
</tbody>
</table>
<br>
### `Expansion`
Each C Extension instructions usually corresponds to a base instruction
#### CR-type
<table>
<thead>
<tr>
<th width="100px" style="text-align:center">RV32C</th>
<th width="100px" style="text-align:center">RV32I</th>
<th style="text-align:center">Description</th>
</tr>
</thead>
<tbody>
<tr>
<th>C.JALR</th>
<th>JALR</th>
<th>Perform an unconditional control transfer to the address in register <code>rs1</code> and write the address of the instruction following the jump (pc+2) to the link register.</th>
</tr>
<tr>
<th>C.JR</th>
<th>JALR</th>
<th>Perform an unconditional control transfer to the address in register <code>rs1</code></th>
</tr>
<tr>
<th>C.ADD</th>
<th>ADD</th>
<th>Add the values in registers <code>rd</code> and <code>rs2</code> and write the result to register <code>rd</code></th>
</tr>
<tr>
<th>C.MV</th>
<th>ADD</th>
<th>Copy the value in register <code>rs2</code> into register <code>rd</code></th>
</tr>
</tbody>
</table>
* `C.JALR` expands to `jalr x0, 0(rs1)`
* `C.JR` expands to `jalr x1, 0(rs1)`
* `C.ADD` expands to `add rd, rd, rs2`
* `C.MV` expands to `add rd, x0, rs2`
<br>
#### CI-type
<table>
<thead>
<tr>
<th width="125px" style="text-align:center">RV32C</th>
<th width="125px" style="text-align:center">RV32I</th>
<th style="text-align:center">Description</th>
</tr>
</thead>
<tbody>
<tr>
<th>C.LUI</th>
<th>LUI</th>
<th>Load the non-zero 6-bit immediate field into bits 17–12 of the destination register, clear the bottom 12 bits, and sign-extend bit 17 into all higher bits of the destination</th>
</tr>
<tr>
<th>C.LI</th>
<th>ADDI</th>
<th>Load the sign-extended 6-bit immediate, <code>imm</code>, into register <code>rd</code></th>
</tr>
<tr>
<th>C.ADDI</th>
<th>ADDI</th>
<th>Add the non-zero sign-extended 6-bit immediate to the value in register <code>rd</code> then writes the result to <code>rd</code></th>
</tr>
<tr>
<th>C.ADDI16SP</th>
<th>ADDI</th>
<th>Add the non-zero sign-extended 6-bit immediate to the value in the stack pointer (x2), usually be used to adjust the stack pointer in procedure prologues and epilogues</th>
</tr>
<tr>
<th>C.SLLI</th>
<th>SLLI</th>
<th>Load the sign-extended 6-bit immediate, `imm`, into register <code>rd</code></th>
</tr>
<tr>
<th>C.LWSP</th>
<th>LW</th>
<th>Loads a 32-bit value from memory into register <code>rd</code></th>
</tr>
</tbody>
</table>
* `C.LUI` expands to `lui rd, nzimm`
* `C.LI` expands to `addi rd, x0, imm`
* `C.ADDI` expands to `addi rd, rd, nzimm`
* `C.ADDI16SP` expands to `addi x2, x2, nzimm`
* `C.SLLI` expands to `slli rd, rd, shamt`
* `C.LWSP` expands to `lw rd, offset(x2)`
<br>
> `C.ADDI` is valid when `rd!=x0` and `imm!=0`,
> The code points with `rd=x0` encode the `C.NOP`,
> The code points with `imm=0` encode the `C.HINT`
<br>
#### CSS-type
<table>
<thead>
<tr>
<th width="125px" style="text-align:center">RV32C</th>
<th width="125px" style="text-align:center">RV32I</th>
<th style="text-align:center">Description</th>
</tr>
</thead>
<tbody>
<tr>
<th>C.SWSP</th>
<th>SW</th>
<th>Store a 32-bit value in register <code>rs2</code> to memory. It computes an effective address by adding the zero-extended offset, scaled by 4, to the stack pointer (x2)</th>
</tr>
</tbody>
</table>
* `C.SWSP` expands to `sw rs2, offset(x2)`
<br>
#### CIW-type
<table>
<thead>
<tr>
<th width="125px" style="text-align:center">RV32C</th>
<th width="125px" style="text-align:center">RV32I</th>
<th style="text-align:center">Description</th>
</tr>
</thead>
<tbody>
<tr>
<th>C.ADDI4SPN</th>
<th>ADDI</th>
<th>Add a zero-extended non-zero immediate, scaled by 4, to the stack pointer (x2), and write the result to <code>rd '</code></th>
</tr>
</tbody>
</table>
* `C.ADDI4SPN` expands to `addi rd ', x2, nzuimm`
<br>
#### CL-type
<table>
<thead>
<tr>
<th width="125px" style="text-align:center">RV32C</th>
<th width="125px" style="text-align:center">RV32I</th>
<th style="text-align:center">Description</th>
</tr>
</thead>
<tbody>
<tr>
<th>C.LW</th>
<th>LW</th>
<th>Load a 32-bit value from memory into register <code>rd '</code></th>
</tr>
</tbody>
</table>
* `C.LW` expands to `lw rd, offset(rs1')`
<br>
#### CS-type
<table>
<thead>
<tr>
<th width="125px" style="text-align:center">RV32C</th>
<th width="125px" style="text-align:center">RV32I</th>
<th style="text-align:center">Description</th>
</tr>
</thead>
<tbody>
<tr>
<th>C.SW</th>
<th>SW</th>
<th>Store a 32-bit value in register <code>rs2 ′</code> to memory</th>
</tr>
</tbody>
</table>
* `C.SW` expands to `sw rs2, offset(rs1')`
<br>
#### CA-type
<table>
<thead>
<tr>
<th width="125px" style="text-align:center">RV32C</th>
<th width="125px" style="text-align:center">RV32I</th>
<th style="text-align:center">Description</th>
</tr>
</thead>
<tbody>
<tr>
<th>C.SUB</th>
<th>SUB</th>
<th>Subtract the value in register <code>rs2 ′</code> from the value in register <code>rd ′</code>, then write the result to register <code>rd ′</code></th>
</tr>
<tr>
<th>C.XOR</th>
<th>XOR</th>
<th>Compute the bitwise XOR of the values in registers <code>rd ′</code> and <code>rs2 ′</code>, then write the result to register <code>rd ′</code></th>
</tr>
<tr>
<th>C.OR</th>
<th>OR</th>
<th>Compute the bitwise OR of the values in registers <code>rd ′</code> and <code>rs2 ′</code>, then write the result to register <code>rd ′</code></th>
</tr>
<tr>
<th>C.AND</th>
<th>AND</th>
<th>Compute the bitwise AND of the values in registers <code>rd ′</code> and <code>rs2 ′</code>, then write the result to register <code>rd ′</code></th>
</tr>
</tbody>
</table>
* `C.SUB` expands to `sub rd', rd', rs2'`
* `C.XOR` expands to `xor rd', rd', rs2'`
* `C.OR` expands to `or rd', rd', rs2'`
* `C.AND` expands to `and rd', rd', rs2'`
<br>
#### CB-type
<table>
<thead>
<tr>
<th width="125px" style="text-align:center">RV32C</th>
<th width="125px" style="text-align:center">RV32I</th>
<th style="text-align:center">Description</th>
</tr>
</thead>
<tbody>
<tr>
<th>C.SRLI</th>
<th>SRLI</th>
<th>Perform a logical right shift of the value in register <code>rd ′</code> then write the result to <code>rd ′</code></th>
</tr>
<tr>
<th>C.SRAI</th>
<th>SRAI</th>
<th>Perform a arithmetic right shift of the value in register <code>rd ′</code> then write the result to <code>rd ′</code></th>
</tr>
<tr>
<th>C.ANDI</th>
<th>ANDI</th>
<th>Compute the bitwise AND of the value in register <code>rd ′</code> and the sign-extended 6-bit immediate, then write the result to <code>rd ′</code></th>
</tr>
<tr>
<th>C.BEQZ</th>
<th>BEQ</th>
<th>Perform conditional control transfers, and take the branch if the value in register <code>rs1 ′</code> is zero</th>
</tr>
<tr>
<th>C.BNEZ</th>
<th>BNE</th>
<th>Perform conditional control transfers, and take the branch if the value in register <code>rs1 ′</code> contains a nonzero value</th>
</tr>
</tbody>
</table>
* `C.SRLI` expands to `srli rd', rd', shamt`
* `C.SRAI` expands to `srai rd', rd', shamt`
* `C.ANDI` expands to `andi rd', rd', imm`
* `C.BEQZ` expands to `beq rs1, x0, offset`
* `C.BNEZ` expands to `bne rs1, x0, offset`
<br>
#### CJ-type
<table>
<thead>
<tr>
<th width="125px" style="text-align:center">RV32C</th>
<th width="125px" style="text-align:center">RV32I</th>
<th style="text-align:center">Description</th>
</tr>
</thead>
<tbody>
<tr>
<th>C.JAL</th>
<th>JAL</th>
<th>Perform an unconditional control transfer</th>
</tr>
<tr>
<th>C.J</th>
<th>JAL</th>
<th>Perform an unconditional control transfer and additionally write the address of the instruction following the jump (pc+2) to the link register (x1)</th>
</tr>
</tbody>
</table>
* `C.JAL` expands to `jal x1, offset`
* `C.J` expands to `jal x0, offset`
> <font color="red">**`C.JAL` is an RV32C-only instruction**</font>
<br>
### Conclusion
<table style="text-align: center">
<thead>
<tr>
<th style="text-align:center">op</th>
<th style="text-align:center">func</th>
<th style="text-align:center">inst[11:10]</th>
<th style="text-align:center">type</th>
<th style="text-align:center">reg len</th>
</tr>
</thead>
<tbody>
<tr>
<td>10</td>
<td>100</td>
<td rowspan="10">-</td>
<td>CR-type</td>
<td rowspan="7">5-bit ( <code>x0</code>-<code>x31</code> )</td>
</tr>
<tr>
<td rowspan="3" style="border-right: 1px solid #52525b">01</td>
<td>000</td>
<td rowspan="5">CI-type</td>
</tr>
<tr>
<td>010</td>
</tr>
<tr>
<td>011</td>
</tr>
<tr>
<td rowspan="2" style="border-right: 1px solid #52525b">10</td>
<td>000</td>
</tr>
<tr>
<td>010</td>
</tr>
<tr>
<td>10</td>
<td>110</td>
<td>CSS-type</td>
</tr>
<tr>
<td>00</td>
<td>000</td>
<td>CIW-type</td>
<td rowspan="9">3-bit ( <code>x8</code>-<code>x15</code> )</td>
</tr>
<tr>
<td>00</td>
<td>010</td>
<td>CL-type</td>
</tr>
<tr>
<td>00</td>
<td>110</td>
<td>CS-type</td>
</tr>
<tr>
<td style="color:red"><b>01</b></td>
<td style="color:red"><b>100</b></td>
<td>11</td>
<td>CA-type</td>
</tr>
<tr>
<td rowspan="3" style="color:red;border-right: 1px solid #52525b"><b>01</b></td>
<td style="color:red"><b>100</b></td>
<td>00</td>
<td rowspan="3">CB-type</td>
</tr>
<tr>
<td>110</td>
<td>01</td>
</tr>
<tr>
<td>111</td>
<td>10</td>
</tr>
<tr>
<td rowspan="2" style="border-right: 1px solid #52525b">01</td>
<td>001</td>
<td rowspan="2">-</td>
<td rowspan="2">CJ-type</td>
</tr>
<tr>
<td>101</td>
</tr>
</tbody>
</table>
<br>
# SRV32
## Introduction
srv32 is a simple RISC-V 3-stage pipeline processor and supports FreeRTOS
## Stages
### `stage 1 - IF/ID`
#### instruction fetch
* If reset signal is `True`, instruction will be `NOP`
* If reset signal is `False` and stall signal is `False`, read instruction
```verilog=
always @(posedge clk or negedge resetb) begin
if (!resetb) begin
ex_insn <= NOP;
end else if (!if_stall) begin
ex_insn <= inst;
end
end
```
<br>
#### immediate decode & extend
* set `imm` according to the instruction
```verilog=
always @* begin
case(inst[`OPCODE])
OP_AUIPC : imm = {inst[31:12], 12'd0}; // U-type
OP_LUI : imm = {inst[31:12], 12'd0}; // U-type
OP_JAL : imm = {{12{inst[31]}}, inst[19:12], inst[20], inst[30:21], 1'b0}; // J-type
OP_JALR : imm = {{20{inst[31]}}, inst[31:20]}; // I-Type
OP_BRANCH: imm = {{20{inst[31]}}, inst[7], inst[30:25], inst[11:8], 1'b0}; // B-type
OP_LOAD : imm = {{20{inst[31]}}, inst[31:20]}; // I-type
OP_STORE : imm = {{20{inst[31]}}, inst[31:25], inst[11:7]}; // S-type
OP_ARITHI: imm = (inst[`FUNC3] == OP_SLL || inst[`FUNC3] == OP_SR) ?
{27'h0, inst[24:20]} : {{20{inst[31]}}, inst[31:20]}; // I-type
OP_ARITHR: imm = 'd0; // R-type
OP_FENCE : imm = 'd0;
OP_SYSTEM: imm = {20'h0, inst[31:20]};
default : imm = 'd0;
endcase
end
```
> Used instruction : `AUIPC`, `LUI`, `JAL`, `JALR`, `BEQ`, `BNE`, `BLTU`, `BGEU`, `AUIPC`, `AUIPC`, `AUIPC`, `AUIPC`, `AUIPC`, `AUIPC`, `AUIPC`, `AUIPC`,
<br>
#### Control Signal / Register setting
```verilog=
always @(posedge clk or negedge resetb) begin
if (!resetb) begin
ex_imm <= 32'h0;
ex_imm_sel <= 1'b0;
ex_src1_sel <= 5'h0;
ex_src2_sel <= 5'h0;
ex_dst_sel <= 5'h0;
ex_alu_op <= 3'h0;
ex_subtype <= 1'b0;
ex_memwr <= 1'b0;
ex_alu <= 1'b0;
ex_csr <= 1'b0;
ex_csr_wr <= 1'b0;
ex_lui <= 1'b0;
ex_auipc <= 1'b0;
ex_jal <= 1'b0;
ex_jalr <= 1'b0;
ex_branch <= 1'b0;
ex_system <= 1'b0;
ex_system_op <= 1'b0;
ex_pc <= RESETVEC;
ex_illegal <= 1'b0;
ex_mul <= 1'b0;
end else if (!if_stall) begin
ex_imm <= imm;
ex_imm_sel <= (inst[`OPCODE] == OP_JALR ) ||
(inst[`OPCODE] == OP_LOAD ) ||
(inst[`OPCODE] == OP_ARITHI);
ex_src1_sel <= inst[`RS1];
ex_src2_sel <= inst[`RS2];
ex_dst_sel <= inst[`RD];
ex_alu_op <= inst[`FUNC3];
ex_subtype <= inst[`SUBTYPE] &&
!(inst[`OPCODE] == OP_ARITHI && inst[`FUNC3] == OP_ADD);
ex_memwr <= inst[`OPCODE] == OP_STORE;
ex_alu <= (inst[`OPCODE] == OP_ARITHI) ||
((inst[`OPCODE] == OP_ARITHR) &&
(inst[`FUNC7] == 'h00 || inst[`FUNC7] == 'h20));
ex_csr <= (inst[`OPCODE] == OP_SYSTEM) &&
(inst[`FUNC3] != OP_ECALL);
// CSRRS and CSRRC, if rs1==0, then the instruction
// will not write to the CSR at all
ex_csr_wr <= (inst[`OPCODE] == OP_SYSTEM) &&
(inst[`FUNC3] != OP_ECALL) &&
!(inst[`FUNC3] != OP_CSRRW && inst[`FUNC3] != OP_CSRRWI &&
inst[`RS1] == 5'h0);
ex_lui <= inst[`OPCODE] == OP_LUI;
ex_auipc <= inst[`OPCODE] == OP_AUIPC;
ex_jal <= inst[`OPCODE] == OP_JAL;
ex_jalr <= inst[`OPCODE] == OP_JALR;
ex_branch <= inst[`OPCODE] == OP_BRANCH;
ex_system <= (inst[`OPCODE] == OP_SYSTEM) &&
(inst[`FUNC3] == 3'b000);
ex_system_op <= inst[`OPCODE] == OP_SYSTEM;
ex_pc <= if_pc;
ex_illegal <= !((inst[`OPCODE] == OP_AUIPC )||
(inst[`OPCODE] == OP_LUI )||
(inst[`OPCODE] == OP_JAL )||
(inst[`OPCODE] == OP_JALR )||
(inst[`OPCODE] == OP_BRANCH)||
((inst[`OPCODE] == OP_LOAD ) &&
((inst[`FUNC3] == OP_LB) ||
(inst[`FUNC3] == OP_LH) ||
(inst[`FUNC3] == OP_LW) ||
(inst[`FUNC3] == OP_LBU) ||
(inst[`FUNC3] == OP_LHU))) ||
((inst[`OPCODE] == OP_STORE) &&
((inst[`FUNC3] == OP_SB) ||
(inst[`FUNC3] == OP_SH) ||
(inst[`FUNC3] == OP_SW))) ||
(inst[`OPCODE] == OP_ARITHI)||
((inst[`OPCODE] == OP_ARITHR) &&
(inst[`FUNC7] == 'h00 || inst[`FUNC7] == 'h20)) ||
((inst[`OPCODE] == OP_ARITHR) && (inst[`FUNC7] == 'h01) &&
(RV32M == 1)) ||
(inst[`OPCODE] == OP_FENCE )||
(inst[`OPCODE] == OP_SYSTEM));
ex_mul <= (inst[`OPCODE] == OP_ARITHR) && (inst[`FUNC7] == 'h1) &&
(RV32M == 1);
end
end
```
<br>
### `stage 2 - EX`
#### Branch Next PC Computation
```verilog=
`define IF_NEXT_PC (4)
always @* begin
branch_taken = !ex_flush;
next_pc = fetch_pc + `IF_NEXT_PC;
ex_ill_branch = 1'b0;
case(1'b1)
ex_jal : next_pc = {result_jal[31: 1], 1'b0}; // setting the least-signicant bit of the result to zero
ex_jalr : next_pc = {result_jalr[31: 1], 1'b0}; // setting the least-signicant bit of the result to zero
ex_branch: begin
case(ex_alu_op)
OP_BEQ : begin
next_pc = (result_subs[32: 0] == 'd0) ?
ex_pc + ex_imm : fetch_pc + `IF_NEXT_PC;
if (result_subs[32: 0] != 'd0) branch_taken = 1'b0;
end
OP_BNE : begin
next_pc = (result_subs[32: 0] != 'd0) ?
ex_pc + ex_imm : fetch_pc + `IF_NEXT_PC;
if (result_subs[32: 0] == 'd0) branch_taken = 1'b0;
end
OP_BLT : begin
next_pc = result_subs[32] ?
ex_pc + ex_imm : fetch_pc + `IF_NEXT_PC;
if (!result_subs[32]) branch_taken = 1'b0;
end
OP_BGE : begin
next_pc = !result_subs[32] ?
ex_pc + ex_imm : fetch_pc + `IF_NEXT_PC;
if (result_subs[32]) branch_taken = 1'b0;
end
OP_BLTU: begin
next_pc = result_subu[32] ?
ex_pc + ex_imm : fetch_pc + `IF_NEXT_PC;
if (!result_subu[32]) branch_taken = 1'b0;
end
OP_BGEU: begin
next_pc = !result_subu[32] ?
ex_pc + ex_imm : fetch_pc + `IF_NEXT_PC;
if (result_subu[32]) branch_taken = 1'b0;
end
default: begin
next_pc = fetch_pc;
ex_ill_branch = 1'b1;
end
endcase
end
default : begin
next_pc = fetch_pc + `IF_NEXT_PC;
branch_taken = 1'b0;
end
endcase
end
```
<br>
#### Result Computation
```verilog=
always @* begin
case(1'b1)
ex_memwr: ex_result = alu_op2;
ex_jal: ex_result = ex_pc + `EX_NEXT_PC;
ex_jalr: ex_result = ex_pc + `EX_NEXT_PC;
ex_lui: ex_result = ex_imm;
ex_auipc: ex_result = ex_pc + ex_imm;
ex_csr: ex_result = ex_csr_read;
ex_mul:
case(ex_alu_op)
OP_MUL : ex_result = result_mul [31: 0];
OP_MULH : ex_result = result_mul [63:32];
OP_MULSU : ex_result = result_mulsu[63:32];
OP_MULU : ex_result = result_mulu [63:32];
OP_DIV : ex_result = result_div [31: 0];
OP_DIVU : ex_result = result_divu [31: 0];
OP_REM : ex_result = result_rem [31: 0];
// OP_REMU
default : ex_result = result_remu [31: 0];
endcase
ex_alu:
case(ex_alu_op)
OP_ADD : if (ex_subtype == 1'b0)
ex_result = alu_op1 + alu_op2;
else
ex_result = alu_op1 - alu_op2;
// In RISC-V ISA spec, only shift amount
// held in lower 5 bits of register
OP_SLL : ex_result = alu_op1 << alu_op2[4:0];
OP_SLT : ex_result = result_subs[32] ? 'd1 : 'd0;
OP_SLTU: ex_result = result_subu[32] ? 'd1 : 'd0;
OP_XOR : ex_result = alu_op1 ^ alu_op2;
OP_SR : if (ex_subtype == 1'b0) // notes: shift more than 32 is undefined
ex_result = alu_op1 >>> alu_op2[4:0];
else
ex_result = $signed(alu_op1) >>> alu_op2[4:0];
OP_OR : ex_result = alu_op1 | alu_op2;
// OP_AND
default: ex_result = alu_op1 & alu_op2;
endcase
default: begin
ex_result = 32'h0;
end
endcase
end
```
### `stage 3 - WB`
#### write back data
```verilog=
always @* begin
case(wb_alu_op)
OP_LB : begin
case(wb_raddr[1:0])
2'b00: wb_rdata[31: 0] = {{24{dmem_rdata[7]}},
dmem_rdata[ 7: 0]};
2'b01: wb_rdata[31: 0] = {{24{dmem_rdata[15]}},
dmem_rdata[15: 8]};
2'b10: wb_rdata[31: 0] = {{24{dmem_rdata[23]}},
dmem_rdata[23:16]};
2'b11: wb_rdata[31: 0] = {{24{dmem_rdata[31]}},
dmem_rdata[31:24]};
endcase
end
OP_LH : begin
wb_rdata = (wb_raddr[1]) ?
{{16{dmem_rdata[31]}}, dmem_rdata[31:16]} :
{{16{dmem_rdata[15]}}, dmem_rdata[15: 0]};
end
OP_LW : begin
wb_rdata = dmem_rdata;
end
OP_LBU : begin
case(wb_raddr[1:0])
2'b00: wb_rdata[31: 0] = {24'h0, dmem_rdata[7:0]};
2'b01: wb_rdata[31: 0] = {24'h0, dmem_rdata[15:8]};
2'b10: wb_rdata[31: 0] = {24'h0, dmem_rdata[23:16]};
2'b11: wb_rdata[31: 0] = {24'h0, dmem_rdata[31:24]};
endcase
end
OP_LHU : begin
wb_rdata = (wb_raddr[1]) ?
{16'h0, dmem_rdata[31:16]} :
{16'h0, dmem_rdata[15: 0]};
end
default: begin
wb_rdata = 32'h0;
end
endcase
end
```
<br>
---
## Control Signal
### 1. `ex_imm_sel`
#### Assignment
```verilog=
ex_imm_sel <= (inst[`OPCODE] == OP_JALR) ||
(inst[`OPCODE] == OP_LOAD) ||
(inst[`OPCODE] == OP_ARITHI);
```
* `ex_imm_sel=True`, when the instruction is ***I-type*** format
* `ex_imm_sel=False`, when the instruction is other format
#### Used Instruction: `JALR`, `LB`, `LH`, `LW`, `LBU`, `LHU`, `ADDI`, `SLTI`, `SLTIU`, `XORI`, `ORI`, `ANDI`, `SLLI`, `SRLI`, `SRAI`
<br>
### 2. `ex_subtype`
<br>
### 3. `ex_memwr`
#### Assignment
```verilog=
ex_memwr <= inst[`OPCODE] == OP_STORE;
```
* `ex_memwr <= True`, when the instruction is ***LOAD*** format
* `ex_memwr <= False`, when the instruction is other format
#### Used Instruction: `LB`, `LH`, `LW`, `LBU`, `LHU`
<br>
### 4. `ex_alu`
#### Assignment
```verilog=
ex_alu <= (inst[`OPCODE] == OP_ARITHI) ||
((inst[`OPCODE] == OP_ARITHR) &&
(inst[`FUNC7] == 'h00 || inst[`FUNC7] == 'h20));
```
* `ex_alu <= True`, when the instruction is ***ARITH*** format
* `ex_alu <= False`, when the instruction is other format
#### Used Instruction: `ADDI`, `SLTI`, `SLTIU`, `XORI`, `ORI`, `ANDI`, `SLLI`, `SRLI`, `SRAI`, `ADD`, `SUB`, `SLT`, `SLTU`, `XOR`, `OR`, `AND`, `SRL`, `SRA`, `MUL`, `MULH`, `MULSU`, `MULU`, `DIV`, `DIVU`, `REM`, `REMU`
<br>
### 5. `ex_lui`
#### Assignment
```verilog=
ex_lui <= inst[`OPCODE] == OP_LUI;
```
* `ex_lui <= True`, when the instruction is `LUI`
* `ex_lui <= False`, when the instruction is other
#### Used Instruction: `LUI`
<br>
### 6. `ex_auipc`
#### Assignment
```verilog=
ex_auipc <= inst[`OPCODE] == OP_AUIPC;
```
* `ex_auipc <= True`, when the instruction is `AUIPC`
* `ex_auipc <= False`, when the instruction is other
#### Used Instruction: `AUIPC`
<br>
### 7. `ex_jal`
#### Assignment
```verilog=
ex_jal <= inst[`OPCODE] == OP_JAL;
```
* `ex_jal <= True`, when the instruction is `JAL`
* `ex_jal <= False`, when the instruction is other
#### Used Instruction: `JAL`
<br>
### 8. `ex_jalr`
#### Assignment
```verilog=
ex_jalr <= inst[`OPCODE] == OP_JALR;
```
* `ex_jalr <= True`, when the instruction is `JALR`
* `ex_jalr <= False`, when the instruction is other
#### Used Instruction: `JALR`
<br>
### 9. `ex_branch`
#### Assignment
```verilog=
ex_branch <= inst[`OPCODE] == OP_BRANCH;
```
* `ex_branch <= True`, when the instruction is ***BRANCH*** format
* `ex_branch <= False`, when the instruction is other
#### Used Instruction: `BEQ`, `BNE`, `BLT`, `BGE`, `BLTU`, `BGEU`
<br>
### 10. `ex_mul`
#### Assignment
```verilog=
ex_mul <= (inst[`OPCODE] == OP_ARITHR) && (inst[`FUNC7] == 'h1) && (RV32M == 1);
```
* `ex_mul <= True`, when the instruction is ***MULTIPLE***
* `ex_mul <= False`, when the instruction is other
#### Used Instruction: `MUL`, `MULH`, `MULSU`, `MULU`, `DIV`, `DIVU`, `REM`, `REMU`
<br>
### 11. `ex_system`
#### Assignment
```verilog=
ex_system <= (inst[`OPCODE] == OP_SYSTEM) &&(inst[`FUNC3] == 3'b000);
```
* `ex_system <= True`, when the instruction is `ECALL`, `EBREAK`, `MRET`
* `ex_system <= False`, when the instruction is other
#### Used Instruction: `ECALL`, `EBREAK`, `MRET`
<br>
### 12. `ex_system_op`
#### Assignment
```verilog=
ex_system_op <= inst[`OPCODE] == OP_SYSTEM;
```
* `ex_system_op <= True`, when the instruction is ***SYSTEM*** format
* `ex_system_op <= False`, when the instruction is other
#### Used Instruction: `ECALL`, `EBREAK`, `MRET`, `CSSRW`, `CSSRS`, `CSSRC`, `CSSRWI`, `CSSRSI`, `CSSRCI`
<br>
### 13. `ex_csr`
#### Assignment
```verilog=
ex_csr <= (inst[`OPCODE] == OP_SYSTEM) && (inst[`FUNC3] != OP_ECALL);
```
* `ex_csr <= True`, when the instruction is `CSSRW`, `CSSRS`, `CSSRC`, `CSSRWI`, `CSSRSI`, `CSSRCI`
* `ex_csr <= False`, when the instruction is other
#### Used Instruction: `CSSRW`, `CSSRS`, `CSSRC`, `CSSRWI`, `CSSRSI`, `CSSRCI`
<br>
### 14. `ex_csr_wr`
#### Assignment
```verilog=
ex_csr_wr <= (inst[`OPCODE] == OP_SYSTEM) &&
(inst[`FUNC3] != OP_ECALL) &&
!(inst[`FUNC3] != OP_CSRRW && inst[`FUNC3] != OP_CSRRWI && inst[`RS1] == 5'h0);
```
* `ex_csr_wr <= True`, when the instruction is `CSRRW`, `CSRRWI`, `CSRRS`, `CSRRC`
(Only when the value of `rs1` of `CSRRS`, `CSRRC` instruction is not equal to 0)
* `ex_csr_wr <= False`, when the instruction is other
#### Used Instruction: `CSSRW`, `CSSRS`, `CSSRC`, `CSSRWI`
<br>
### Conclusion
| | ex_imm_sel | ex_subtype | ex_memwr | ex_alu | ex_lui | ex_auipc | ex_jal | ex_jalr | ex_branch | ex_mul | ex_system | ex_system_op | ex_csr_wr | ex_csr |
|:------ |:----------:|:----------:|:--------:|:------:|:------:|:--------:|:------:|:-------:|:---------:|:------:|:---------:|:------------:|:---------:|:------:|
| LUI | ❌ | | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| AUIPC | ❌ | | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| JAL | ❌ | | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| JALR | ✔️ | | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| BEQ | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ |
| BNE | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ |
| BLT | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ |
| BGE | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ |
| BLTU | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ |
| BGEU | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ |
| LB | ✔️ | | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| LH | ✔️ | | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| LW | ✔️ | | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| LBU | ✔️ | | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| LHU | ✔️ | | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| SB | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| SH | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| SW | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| ADDI | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| SLTI | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| SLTIU | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| XORI | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| ORI | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| ANDI | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| SLLI | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| SRAI | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| SRAI | ✔️ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| ADD | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| SUB | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| SLL | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| SLT | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| SLTU | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| XOR | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| SRL | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| SRA | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| OR | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| AND | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| MUL | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ |
| MULH | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ |
| MULSU | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ |
| MULU | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ |
| DIV | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ |
| DIVU | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ |
| REM | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ |
| REMU | ❌ | | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ❌ | ❌ | ❌ | ❌ |
| ECALL | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ❌ | ❌ |
| EBREAK | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ❌ | ❌ |
| MERT | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ❌ | ❌ |
| CSRRW | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ✔️ |
| CSRRS | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ✔️ |
| CSRRC | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ✔️ |
| CSRRWI | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ✔️ |
| CSRRSI | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ❌ |
| CSRRCI | ❌ | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ❌ |
---
<br>
# Implementation
## Architecture

1. Decode the instructions according to the opcode (`inst[1:0]`)
* If op2 equals to `11`, then the instruction is base instruction
* If op2 equals to `00`, `01`, or `10`, then the instruction is c-extension instruction
> ex:
> If instruction is `C.ADD`, then the instruction information ALU gains should be `ADD`
2. Execute instruction
3. Write back data
<br>
## op & func3 Define
```verilog=
// INST[1:0] = 2'b00
localparam [ 4: 0] OP_CADDI4SPN = 5'b00000,
OP_CLW = 5'b01000,
OP_CSW = 5'b11000;
// INST[1:0] = 2'b01
localparam [ 4: 0] OP_CADDI = 5'b00001,
OP_CJAL = 5'b00101,
OP_CLI = 5'b01001,
OP_CADDI16SP = 5'b01101,
OP_CLUI = 5'b01101,
OP_CSRLI = 5'b10001,
OP_CSRAI = 5'b10001,
OP_CANDI = 5'b10001,
OP_CJ = 5'b10101,
OP_CBEQZ = 5'b11001,
OP_CBNEZ = 5'b11101;
// INST[1:0] = 2'b01, no imm
localparam [ 4: 0] OP_CSUB = 5'b10001,
OP_CXOR = 5'b10001,
OP_COR = 5'b10001,
OP_CAND = 5'b10001;
// INST[1:0] = 2'b10
localparam [ 4: 0] OP_CSLLI = 5'b00010,
OP_CLWSP = 5'b01010,
OP_CSWSP = 5'b11010;
// INST[1:0] = 2'b10, no imm
localparam [ 4: 0] OP_CJR = 5'b10010,
OP_CMV = 5'b10010,
OP_CJALR = 5'b10010,
OP_CADD = 5'b10010,
OP_CSYSTEM = 5'b10010;
```
> This part is for instruction define, the parameter `OP_XXX` is composed of `funct3` and `op2` ({inst[15:13]})
<br>
## Imm Decode
This section is modified from [here](#immediate-decode-amp-extend).
``` diff=
always @* begin
case(inst[`OPCODE])
OP_AUIPC : imm = {inst[31:12], 12'd0}; // U-type
OP_LUI : imm = {inst[31:12], 12'd0}; // U-type
OP_JAL : imm = {{12{inst[31]}}, inst[19:12], inst[20], inst[30:21], 1'b0}; // J-type
OP_JALR : imm = {{20{inst[31]}}, inst[31:20]}; // I-Type
OP_BRANCH: imm = {{20{inst[31]}}, inst[7], inst[30:25], inst[11:8], 1'b0}; // B-type
OP_LOAD : imm = {{20{inst[31]}}, inst[31:20]}; // I-type
OP_STORE : imm = {{20{inst[31]}}, inst[31:25], inst[11:7]}; // S-type
OP_ARITHI: imm = (inst[`FUNC3] == OP_SLL || inst[`FUNC3] == OP_SR) ?
{27'h0, inst[24:20]} : {{20{inst[31]}}, inst[31:20]}; // I-type
OP_ARITHR: imm = 'd0; // R-type
OP_FENCE : imm = 'd0;
OP_SYSTEM: imm = {20'h0, inst[31:20]};
default : imm = 'd0;
endcase
// case for C-Extenstion
case({inst[`CFUNC3], inst[`COPCODE]})
// CI-type
+ OP_CLI : imm = {26'b0, inst[12], inst[6:2]};
+ OP_CADDI : imm = {26'b0, inst[12], inst[6:2]};
+ OP_CSLLI : imm = {26'b0, inst[12], inst[6:2]};
// C.LUI & C.ADDI16SP
+ OP_CLUI : imm = (inst[`C5RD]==5'd2) ? {22'b0, inst[12], inst[4:3], inst[5], inst[2], inst[6], 4'b0} : {14'b0, inst[12], inst[6:2], 12'b0};
+ OP_CLWSP : imm = {24'b0, inst[3:2], inst[12], inst[6:4], 2'b0};
// CSS-type
+ OP_CSWSP : imm = {24'b0, inst[8:7], inst[12:9], 2'b0};
// CIW-type
+ OP_CADDI4SPN : imm = {22'b0, inst[10:7], inst[12:11], inst[5], inst[6], 2'b0};
// CL-type
+ OP_CLW : imm = {25'b0, inst[5], inst[12:10], inst[6], 2'b0};
// CS-type
+ OP_CSW : imm = {25'b0, inst[5], inst[12:10], inst[6], 2'b0};
// CB-type
+ OP_CBEQZ : imm = {23'b0, inst[12], inst[6:5], inst[2], inst[11:10], inst[4:3], 1'b0};
+ OP_CBNEZ : imm = {23'b0, inst[12], inst[6:5], inst[2], inst[11:10], inst[4:3], 1'b0};
+ OP_CSRLI : imm = (inst[11:10]==2'b0) ? {27'b0, inst[6:2]} :
+ (inst[11:10]==2'b1) ? {26'b0, inst[12], inst[6:2]} :
+ {26'b0, inst[12], inst[6:2]};
// CJ-type
+ OP_CJ : imm = {20'b0, inst[12], inst[8], inst[10:9], inst[7], inst[6], inst[2], inst[11], inst[4:2], 1'b0};
+ OP_CJAL : imm = {20'b0, inst[12], inst[8], inst[10:9], inst[7], inst[6], inst[2], inst[11], inst[4:2], 1'b0};
+ OP_CSYSTEM : imm = (inst[`C5RD] == 0 && inst[`C5RS2] == 0) ? 32'b1 : 32'b0;
+ default : imm = 'd0;
endcase
end
```
> The upper part is for base instructions, then the lower part is for c-extension instructions
<br>
## Register
This section is modified from [here](#Control-Signal--Register-setting)
``` diff=
case(inst[`COPCODE])
+ 2'b00: // CIW-type, CL-type, CS-type
+ begin
+ instc <= 1'b1;
+ ex_src1_sel <= {2'b1, inst[`C3RS1]};
+ ex_src2_sel <= {2'b1, inst[`C3RS2]};
+ ex_dst_sel <= {2'b1, inst[`C3RD]};
+ end
+ 2'b01:
+ begin
+ case(inst[`CFUNC3])
+ 3'b000, // CI-type
+ 3'b010, // CI-type
+ 3'b011: // CI-type
+ begin
+ instc <= 1'b1;
+ ex_src1_sel <= inst[`C5RS1];
+ ex_src2_sel <= inst[`C5RS2];
+ ex_dst_sel <= inst[`C5RD];
+ end
+ 3'b001, // CJ-type
+ 3'b100, // CA-type, CB-type
+ 3'b101, // CJ-type
+ 3'b110, // CB-type
+ 3'b111: // CB-type
+ begin
+ instc <= 1'b1;
+ ex_src1_sel <= {2'b1, inst[`C3RS1]};
+ ex_src2_sel <= {2'b1, inst[`C3RS2]};
+ ex_dst_sel <= {2'b1, inst[`C3RD]};
+ end
+ endcase
+ end
+ 2'b10: // CI-type, CSS-type
+ begin
+ instc <= 1'b1;
+ ex_src1_sel <= inst[`C5RS1];
+ ex_src2_sel <= inst[`C5RS2];
+ ex_dst_sel <= inst[`C5RD];
+ end
2'b11: // base
begin
instc <= 1'b0;
ex_src1_sel <= inst[`RS1];
ex_src2_sel <= inst[`RS2];
ex_dst_sel <= inst[`RD];
end
endcase
```
> Because `CIW`, `CL`, `CS`, `CA`, `CB`, and `CJ` format instruction can use only part of the RV32I registers, we have to map the `rs1'`, `rs2'`, and `rd'` to the corresponded register.
<br>
## ALU OP
This section is modified from [here](#Control-Signal--Register-setting)
```diff=
case(inst[`COPCODE])
2'b11:
ex_alu_op <= inst[`FUNC3];
default:
begin
// c-ext
+ case({inst[`CFUNC3], inst[`COPCODE]})
+ OP_CLW: ex_alu_op <= OP_LW;
+ OP_CLWSP: ex_alu_op <= OP_LW;
+ OP_CSW: ex_alu_op <= OP_SW;
+ OP_CSWSP: ex_alu_op <= OP_SW;
+ OP_CBEQZ: ex_alu_op <= OP_BEQ;
+ OP_CBNEZ: ex_alu_op <= OP_BNE;
+ OP_CADD: ex_alu_op <= OP_ADD;
+ OP_COR:
+ begin
+ case(inst[6:5])
+ 2'b00: ex_alu_op <= OP_ADD;
+ 2'b01: ex_alu_op <= OP_XOR;
+ 2'b10: ex_alu_op <= OP_OR;
+ 2'b11: ex_alu_op <= OP_AND;
+ endcase
+ end
+ default: ;
endcase
end
endcase
```
> This part is for instruction expanding.
> If the instruction is based instruction, then set the `ex_alu_op` with `funct3`
> If the instruction is c-extension instruction, then decode the instruction with op2 and funct3, and set the `ex_alu_op` with corresponded `funct3` of based instruction.
<br>
## Control Signal
### 1. `ex_imm_sel`
This section is modified from [here](#1-ex_imm_sel).
```diff=
ex_imm_sel <= (inst[`OPCODE] == OP_JALR ) ||
(inst[`OPCODE] == OP_LOAD ) ||
(inst[`OPCODE] == OP_ARITHI) ||
// c-ext
+ (({inst[`CFUNC3], inst[`COPCODE]} == OP_CJR) && (inst[12] == 1'b0) && (inst[`C5RS2] == 5'b0) && (inst[`C5RS1] != 5'b0)) || // C.JR
+ (({inst[`CFUNC3], inst[`COPCODE]} == OP_CJALR) && (inst[12] == 1'b1) && (inst[`C5RS2] == 5'b0) && (inst[`C5RS1] != 5'b0)) || // C.JALR
+ ({inst[`CFUNC3], inst[`COPCODE]} == OP_CLW) || // C.LW
+ ({inst[`CFUNC3], inst[`COPCODE]} == OP_CLWSP) || // C.LWSP
+ (({inst[`COPCODE], inst[`CFUNC3]} == OP_CADDI) && (inst[`C5RS1] != 5'b0)) || // C.ADDI
+ (({inst[`COPCODE], inst[`CFUNC3]} == OP_CLI) && (inst[`C5RS1] != 5'b0)) || // C.LI
+ (({inst[`COPCODE], inst[`CFUNC3]} == OP_CSLLI) && (inst[`C5RS1] != 5'b0)) || // C.SLLI
+ (({inst[`COPCODE], inst[`CFUNC3]} == OP_CSRLI) && (inst[`CFUNC2] == 2'b00)) || // C.SRLI
+ (({inst[`COPCODE], inst[`CFUNC3]} == OP_CSRAI) && (inst[`CFUNC2] == 2'b01)) || // C.SRAI
+ (({inst[`COPCODE], inst[`CFUNC3]} == OP_CANDI) && (inst[`CFUNC2] == 2'b10)); // C.SRAI
```
> Add additional conditions for c instructions - `C.JR`, `C.JALR`, `C.LW`, `C.LWSP`, `C.ADDI`, `C.LI`, `C.SLLI`, `C.SRLI`, `C.SRAI`, `C.ANDI`
<br>
### 2. `ex_subtype`
### 3. `ex_memwr`
This section is modified from [here](#3-ex_memwr)
```diff=
ex_memwr <= (inst[`OPCODE] == OP_STORE) ||
// c-ext
+ ({inst[`CFUNC3], inst[`COPCODE]} == OP_CSW) || // C.SW
+ ({inst[`CFUNC3], inst[`COPCODE]} == OP_CSWSP); // C.SWSP
```
> Add additional instruction conditions for c instruction - `C.SW`, `CSWSP`
<br>
### 4. `ex_alu`
This section is modified from [here](#4-ex_alu)
```diff=
ex_alu <= (inst[`OPCODE] == OP_ARITHI) ||
((inst[`OPCODE] == OP_ARITHR) && (inst[`FUNC7] == 'h00 || inst[`FUNC7] == 'h20)) ||
// c-ext
+ (({inst[`COPCODE], inst[`CFUNC3]} == OP_CADD) && (inst[12]) && (inst[`CRD] != 5'b0) && (inst[`C5RS2] != 5'b0)) || // C.ADD
+ (({inst[`COPCODE], inst[`CFUNC3]} == OP_CMV) && (!inst[12]) && (inst[`CRD] != 5'b0) && (inst[`C5RS2] != 5'b0)) || // C.MV
+ (({inst[`COPCODE], inst[`CFUNC3]} == OP_CSUB) && (inst[`CFUNC6] == 6'b100011)) || // C.SUB, C.XOR, C.OR, C.AND
+ (({inst[`COPCODE], inst[`CFUNC3]} == OP_CADDI) && (inst[`C5RS1] != 5'b0)) || // C.ADDI
+ (({inst[`COPCODE], inst[`CFUNC3]} == OP_CLI) && (inst[`C5RS1] != 5'b0)) || // C.LI
+ (({inst[`COPCODE], inst[`CFUNC3]} == OP_CSLLI) && (inst[`C5RS1] != 5'b0)) || // C.SLLI
+ (({inst[`COPCODE], inst[`CFUNC3]} == OP_CSRLI) && (inst[`CFUNC2] == 2'b00)) || // C.SRLI
+ (({inst[`COPCODE], inst[`CFUNC3]} == OP_CSRAI) && (inst[`CFUNC2] == 2'b01)) || // C.SRAI
+ (({inst[`COPCODE], inst[`CFUNC3]} == OP_CANDI) && (inst[`CFUNC2] == 2'b10)); // C.ANDI
```
> Add additional conditions for c instructions - `C.ADD`, `C.MV`, `C.SUB`, `C.XOR`, `C.OR`, `C.AND`, `C.ADDI`, `C.LI`, `C.SLLI`, `C.SRLI`, `C.SRAI`, `C.ANDI`
<br>
### 5. `ex_lui`
This section is modified from [here](#5-ex_lui)
```diff=
ex_lui <= (inst[`OPCODE] == OP_LUI) ||
// c-ext
+ (({inst[`CFUNC3], inst[`COPCODE]} == OP_CLUI) && (inst[`RD] != 5'd0) && (inst[`RD] != 5'd1) && (inst[`RD] != 5'd2)); // C.LUI
```
> Add additional conditions for c instruction - `C.LUI`
<br>
### 6. `ex_jal`
This section is modified from [here](#7-ex_jal)
```diff=
ex_jal <= (inst[`OPCODE] == OP_JAL) ||
// c-ext
+ ({inst[`CFUNC3], inst[`COPCODE]} == OP_CJ) || // C.J
+ ({inst[`CFUNC3], inst[`COPCODE]} == OP_CJAL); // C.JAL
```
> Add additional conditions for c instructions - `C.J`, `C.JAL`
<br>
### 7. `ex_jalr`
This section is modified from [here](#8-ex_jalr)
```diff=
ex_jalr <= (inst[`OPCODE] == OP_JALR) ||
// c-ext
+ (({inst[`CFUNC3], inst[`COPCODE]} == OP_CJR) && (!inst[12]) && (inst[`C5RS1] != 5'b0) && (inst[`C5RS2] == 5'b0)) || // C.JR
+ (({inst[`CFUNC3], inst[`COPCODE]} == OP_CJALR) && (inst[12]) && (inst[`C5RS1] != 5'b0) && (inst[`C5RS2] == 5'b0)) ; // C.JALR
```
> Add additional conditions for c instructions - `C.JR`, `C.JALR`
<br>
### 8. `ex_branch`
This section is modified from [here](#9-ex_branch)
```diff=
ex_branch <= (inst[`OPCODE] == OP_BRANCH) ||
// c-ext
+ ({inst[`CFUNC3], inst[`COPCODE]} == OP_CBEQZ) || // C.BEQZ
+ ({inst[`CFUNC3], inst[`COPCODE]} == OP_CBNEZ); // C.BNEZ
```
> Add additional conditions for c instructions - `C.BEQZ`, `C.BNEZ`
<br>
### 9. `ex_system`
This section is modified from [here](#11-ex_system)
```diff=
ex_system <= ((inst[`OPCODE] == OP_SYSTEM) && (inst[`FUNC3] == 3'b000)) ||
// c-ext
+ (({inst[`CFUNC3], inst[`COPCODE]} == OP_CSYSTEM) && (inst[12]) && (inst[`CRD] == 5'b0) && (inst[`C5RS2] == 5'b0));
```
> Add additional instruction conditions for c instruction - `C.EBREAK`
<br>
### 10. `ex_system_op`
This section is modified from [here](#12-ex_system_op)
```diff=
ex_system_op <= (inst[`OPCODE] == OP_SYSTEM) ||
// c-ext
+ (({inst[`CFUNC3], inst[`COPCODE]} == OP_CSYSTEM) && (inst[12]) && (inst[`CRD] == 5'b0) && (inst[`C5RS2] == 5'b0));
```
> Add additional conditions for c instruction - `C.EBREAK`
<br>
### 11. `ex_csr`
This section is modified from [here](#13-ex_csr)
```diff=
ex_csr <= ((inst[`OPCODE] == OP_SYSTEM) && (inst[`FUNC3] != OP_ECALL)) ||
// c-ext
+ (inst[`CINST] == 16'h9002);
```
> Add additional conditions for c instruction - `C.EBREAK`
<br>
## PC
### Define
```diff=
`define IF_NEXT_PC (4)
`define EX_NEXT_PC (4)
// c-ext pc
+`define IF_NEXT_C_PC (2)
+`define EX_NEXT_C_PC (2)
```
> Because the c extension instruction is 16-byte long, the program counter (`PC`) should increment by 2 by step instead of by 4
<br>
### Branch PC
This section is modified from [here](#Branch-Next-PC-Computation)
```diff=
always @* begin
branch_taken = !ex_flush;
+ next_pc = (instc) ? (fetch_pc + `IF_NEXT_C_PC) : (fetch_pc + `IF_NEXT_PC);
ex_ill_branch = 1'b0;
case(1'b1)
ex_jal : next_pc = {result_jal[31: 1], 1'b0}; // setting the least-signicant bit of the result to zero
ex_jalr : next_pc = {result_jalr[31: 1], 1'b0}; // setting the least-signicant bit of the result to zero
ex_branch: begin
case(ex_alu_op)
OP_BEQ : begin
+ next_pc = (result_subs[32: 0] == 'd0) ?
+ (ex_pc + ex_imm) : (instc) ?
+ (fetch_pc + `IF_NEXT_C_PC) : (fetch_pc + `IF_NEXT_PC);
if (result_subs[32: 0] != 'd0) branch_taken = 1'b0;
end
OP_BNE : begin
+ next_pc = (result_subs[32: 0] != 'd0) ?
+ (ex_pc + ex_imm) : (instc) ?
+ (fetch_pc + `IF_NEXT_C_PC) : (fetch_pc + `IF_NEXT_PC);
if (result_subs[32: 0] == 'd0) branch_taken = 1'b0;
end
OP_BLT : begin
+ next_pc = result_subs[32] ?
+ (ex_pc + ex_imm) : (instc) ?
+ (fetch_pc + `IF_NEXT_C_PC) : (fetch_pc + `IF_NEXT_PC);
if (!result_subs[32]) branch_taken = 1'b0;
end
OP_BGE : begin
+ next_pc = !result_subs[32] ?
+ (ex_pc + ex_imm) : (instc) ?
+ (fetch_pc + `IF_NEXT_C_PC) : (fetch_pc + `IF_NEXT_PC);
if (result_subs[32]) branch_taken = 1'b0;
end
OP_BLTU: begin
+ next_pc = result_subu[32] ?
+ (ex_pc + ex_imm) : (instc) ?
+ (fetch_pc + `IF_NEXT_C_PC) : (fetch_pc + `IF_NEXT_PC);
if (!result_subu[32]) branch_taken = 1'b0;
end
OP_BGEU: begin
+ next_pc = !result_subu[32] ?
+ (ex_pc + ex_imm) : (instc) ?
+ (fetch_pc + `IF_NEXT_C_PC) : (fetch_pc + `IF_NEXT_PC);
if (result_subu[32]) branch_taken = 1'b0;
end
default: begin
+ next_pc = fetch_pc;
ex_ill_branch = 1'b1;
end
endcase
end
default : begin
+ next_pc = (instc) ? (fetch_pc + `IF_NEXT_C_PC) : (fetch_pc + `IF_NEXT_PC);
branch_taken = 1'b0;
end
endcase
end
```
> This part is for ***BRANCH*** instruction
> Use a control signal (`instc`) to determine whether the PC should increment by 2 or 4
> * If `instc=0` (means base instruction), `PC` will increment by 4
> * If `instc=0` (means C extension instruction), `PC` will increment by 2
> The value of control signal `instc` is set at [here](#Register)
<br>
### Jump PC
This section is modified from [here](#Result-Computation)
```diff=
always @* begin
case(1'b1)
ex_memwr: ex_result = alu_op2;
+ ex_jal: ex_result = (instc) ? (ex_pc + `EX_NEXT_C_PC) : (ex_pc + `EX_NEXT_PC);
+ ex_jalr: ex_result = (instc) ? (ex_pc + `EX_NEXT_C_PC) : (ex_pc + `EX_NEXT_PC);
ex_lui: ex_result = ex_imm;
ex_auipc: ex_result = ex_pc + ex_imm;
ex_csr: ex_result = ex_csr_read;
ex_mul:
(...) // Remaining code is the same
```
> This part is for ***JUMP*** instruction
> Use a control signal (`instc`) to determine whether the PC should increment by 2 or 4
> * If `instc=0` (means base instruction), `PC` will increment by 4
> * If `instc=0` (means C extension instruction), `PC` will increment by 2
> The value of control signal `instc` is set at [here](#Register)
<br>
# Test
The origin structure is in `~/test/srv32` directory
Our c-extension supported structure is in `~/repos/srv32`
First, we test the original structure in RTL simulation
Type `make all` in folder `srv32`

Test out c-extension supported structure

The error message show `Unsupport CSR register 0x0 at PC 0x00000010`
Because the conversion of CSR instructions has not been successfully handled so far.
### Problem analysis
1. Some instructions might have been mistakenly identified as CSR instructions, resulting in illegal instructions.
2. Since the c-extension instructions related to CSR only include c.ebreak, there might have been an error during the decoding of this instruction.
**We should be able to figure it out within a few days.**
# Reference
* https://hackmd.io/@kaeteyaruyo/risc-v-rvc#Instruction-Decompression
* https://hackmd.io/@2gMSvG25RxKj2-N_rAY6zg/HkKaA_qUs?utm_source=preview-mode&utm_medium=rec
* https://groups.google.com/a/groups.riscv.org/g/isa-dev/c/QJX63LeEux8?pli=1
* http://atp.ee.ncku.edu.tw/classview_58.html