宋唯廷, 劉孟璋
The RV32IM, RV32C, SRV32 sections of this note serve as the theoretical notes.
The implementation part of srv32c starts from the Implementation section.
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
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
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
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
U-Type
inst | length |
---|---|
op | 7-bit [0-6] |
rd | 5-bit [7-11] |
imm | 20-bit [12-31] |
instructions - LUI
, AUIPC
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
NOP
NOP
NOP
instruction is encoded asADDI x0, x0, 0
SYSTEM
ECALL
, EBREAK
op | description | type |
---|---|---|
0110011 | arithmetic between reg and reg |
R-Type |
0010011 | arithmetic between reg and imm |
I-Type |
0010011 | load data | |
0100011 | store data | S-Type |
1100011 | conditional branch | B-Type |
0010011 | upper imm arithmetic |
U-Type |
0110111 | ||
1101111 | unconditional jump | J-Type |
1100111 |
When certain 32-bit instructions have specific characteristics that allow them to be converted into compressed instructions:
- the immediate or address offset is small
- one of the registers is the zero register (x0), the ABI link register (
x1
), or the ABI stack pointer (x2
)- the destination register and the first source register are identical
- the registers used are the 8 most popular ones (
x8
-x15
). This is also the reason why some register fields in the C extension instructions are only 3 bits long
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:
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.
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
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
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
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
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
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
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
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
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
NOP
instructions - C.NOP
Breakpoint
instructions - C.EBREAK
Illegal
Type Decode
The following is the decoding method for C-Extension instructions.
op | func3 | type |
---|---|---|
10 | 100 | CR-type |
01 | 000 | CI-type |
010 | ||
011 | ||
10 | 000 | |
010 | ||
10 | 110 | CSS-type |
00 | 000 | CIW-type |
00 | 010 | CL-type |
00 | 110 | CS-type |
01 | 100 | CA-type |
01 | 100 | CB-type |
110 | ||
111 | ||
01 | 001 | CJ-type |
101 |
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.
op | func3 | inst[11:10] | type |
---|---|---|---|
01 | 100 | 11 | CA-type |
00 | CB-type | ||
01 | |||
10 | |||
110 | - | ||
111 |
Therefore, in the case where op=01
and func3=100
, we will need an additional 2 bits inst[11:10]
to assist in decoding.
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 (3-bit)
The regisers are mapped to
x8
-x15
reg(3-bit) | mapped reg(5-bit) | ||
---|---|---|---|
x0 | 000 | x8 ( s0 ) |
01000 |
x1 | 001 | x9 ( s1 ) |
01001 |
x2 | 010 | x10 ( a0 ) |
01010 |
x3 | 011 | x11 ( a1 ) |
01011 |
x4 | 100 | x12 ( a2 ) |
01100 |
x5 | 101 | x13 ( a3 ) |
01101 |
x6 | 110 | x14 ( a4 ) |
01110 |
x7 | 111 | x15 ( a5 ) |
01111 |
Expansion
Each C Extension instructions usually corresponds to a base instruction
RV32C | RV32I | Description |
---|---|---|
C.JALR | JALR | Perform an unconditional control transfer to the address in register rs1 and write the address of the instruction following the jump (pc+2) to the link register. |
C.JR | JALR | Perform an unconditional control transfer to the address in register rs1 |
C.ADD | ADD | Add the values in registers rd and rs2 and write the result to register rd |
C.MV | ADD | Copy the value in register rs2 into register rd |
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
RV32C | RV32I | Description |
---|---|---|
C.LUI | LUI | 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 |
C.LI | ADDI | Load the sign-extended 6-bit immediate, imm , into register rd |
C.ADDI | ADDI | Add the non-zero sign-extended 6-bit immediate to the value in register rd then writes the result to rd |
C.ADDI16SP | ADDI | 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 |
C.SLLI | SLLI | Load the sign-extended 6-bit immediate, `imm`, into register rd |
C.LWSP | LW | Loads a 32-bit value from memory into register rd |
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)
C.ADDI
is valid whenrd!=x0
andimm!=0
,
The code points withrd=x0
encode theC.NOP
,
The code points withimm=0
encode theC.HINT
RV32C | RV32I | Description |
---|---|---|
C.SWSP | SW | Store a 32-bit value in register rs2 to memory. It computes an effective address by adding the zero-extended offset, scaled by 4, to the stack pointer (x2) |
C.SWSP
expands to sw rs2, offset(x2)
RV32C | RV32I | Description |
---|---|---|
C.ADDI4SPN | ADDI | Add a zero-extended non-zero immediate, scaled by 4, to the stack pointer (x2), and write the result to rd ' |
C.ADDI4SPN
expands to addi rd ', x2, nzuimm
RV32C | RV32I | Description |
---|---|---|
C.LW | LW | Load a 32-bit value from memory into register rd ' |
C.LW
expands to lw rd, offset(rs1')
RV32C | RV32I | Description |
---|---|---|
C.SW | SW | Store a 32-bit value in register rs2 ′ to memory |
C.SW
expands to sw rs2, offset(rs1')
RV32C | RV32I | Description |
---|---|---|
C.SUB | SUB | Subtract the value in register rs2 ′ from the value in register rd ′ , then write the result to register rd ′ |
C.XOR | XOR | Compute the bitwise XOR of the values in registers rd ′ and rs2 ′ , then write the result to register rd ′ |
C.OR | OR | Compute the bitwise OR of the values in registers rd ′ and rs2 ′ , then write the result to register rd ′ |
C.AND | AND | Compute the bitwise AND of the values in registers rd ′ and rs2 ′ , then write the result to register rd ′ |
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'
RV32C | RV32I | Description |
---|---|---|
C.SRLI | SRLI | Perform a logical right shift of the value in register rd ′ then write the result to rd ′ |
C.SRAI | SRAI | Perform a arithmetic right shift of the value in register rd ′ then write the result to rd ′ |
C.ANDI | ANDI | Compute the bitwise AND of the value in register rd ′ and the sign-extended 6-bit immediate, then write the result to rd ′ |
C.BEQZ | BEQ | Perform conditional control transfers, and take the branch if the value in register rs1 ′ is zero |
C.BNEZ | BNE | Perform conditional control transfers, and take the branch if the value in register rs1 ′ contains a nonzero value |
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
RV32C | RV32I | Description |
---|---|---|
C.JAL | JAL | Perform an unconditional control transfer |
C.J | JAL | Perform an unconditional control transfer and additionally write the address of the instruction following the jump (pc+2) to the link register (x1) |
C.JAL
expands to jal x1, offset
C.J
expands to jal x0, offset
C.JAL
is an RV32C-only instruction
op | func | inst[11:10] | type | reg len |
---|---|---|---|---|
10 | 100 | - | CR-type | 5-bit ( x0 -x31 ) |
01 | 000 | CI-type | ||
010 | ||||
011 | ||||
10 | 000 | |||
010 | ||||
10 | 110 | CSS-type | ||
00 | 000 | CIW-type | 3-bit ( x8 -x15 ) |
|
00 | 010 | CL-type | ||
00 | 110 | CS-type | ||
01 | 100 | 11 | CA-type | |
01 | 100 | 00 | CB-type | |
110 | 01 | |||
111 | 10 | |||
01 | 001 | - | CJ-type | |
101 |
srv32 is a simple RISC-V 3-stage pipeline processor and supports FreeRTOS
stage 1 - IF/ID
True
, instruction will be NOP
False
and stall signal is False
, read instruction
always @(posedge clk or negedge resetb) begin
if (!resetb) begin
ex_insn <= NOP;
end else if (!if_stall) begin
ex_insn <= inst;
end
end
imm
according to the instruction
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
,
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
stage 2 - EX
`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
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
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
ex_imm_sel
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 formatex_imm_sel=False
, when the instruction is other formatJALR
, LB
, LH
, LW
, LBU
, LHU
, ADDI
, SLTI
, SLTIU
, XORI
, ORI
, ANDI
, SLLI
, SRLI
, SRAI
ex_subtype
ex_memwr
ex_memwr <= inst[`OPCODE] == OP_STORE;
ex_memwr <= True
, when the instruction is LOAD formatex_memwr <= False
, when the instruction is other formatLB
, LH
, LW
, LBU
, LHU
ex_alu
ex_alu <= (inst[`OPCODE] == OP_ARITHI) ||
((inst[`OPCODE] == OP_ARITHR) &&
(inst[`FUNC7] == 'h00 || inst[`FUNC7] == 'h20));
ex_alu <= True
, when the instruction is ARITH formatex_alu <= False
, when the instruction is other formatADDI
, 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
ex_lui
ex_lui <= inst[`OPCODE] == OP_LUI;
ex_lui <= True
, when the instruction is LUI
ex_lui <= False
, when the instruction is otherLUI
ex_auipc
ex_auipc <= inst[`OPCODE] == OP_AUIPC;
ex_auipc <= True
, when the instruction is AUIPC
ex_auipc <= False
, when the instruction is otherAUIPC
ex_jal
ex_jal <= inst[`OPCODE] == OP_JAL;
ex_jal <= True
, when the instruction is JAL
ex_jal <= False
, when the instruction is otherJAL
ex_jalr
ex_jalr <= inst[`OPCODE] == OP_JALR;
ex_jalr <= True
, when the instruction is JALR
ex_jalr <= False
, when the instruction is otherJALR
ex_branch
ex_branch <= inst[`OPCODE] == OP_BRANCH;
ex_branch <= True
, when the instruction is BRANCH formatex_branch <= False
, when the instruction is otherBEQ
, BNE
, BLT
, BGE
, BLTU
, BGEU
ex_mul
ex_mul <= (inst[`OPCODE] == OP_ARITHR) && (inst[`FUNC7] == 'h1) && (RV32M == 1);
ex_mul <= True
, when the instruction is MULTIPLEex_mul <= False
, when the instruction is otherMUL
, MULH
, MULSU
, MULU
, DIV
, DIVU
, REM
, REMU
ex_system
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 otherECALL
, EBREAK
, MRET
ex_system_op
ex_system_op <= inst[`OPCODE] == OP_SYSTEM;
ex_system_op <= True
, when the instruction is SYSTEM formatex_system_op <= False
, when the instruction is otherECALL
, EBREAK
, MRET
, CSSRW
, CSSRS
, CSSRC
, CSSRWI
, CSSRSI
, CSSRCI
ex_csr
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 otherCSSRW
, CSSRS
, CSSRC
, CSSRWI
, CSSRSI
, CSSRCI
ex_csr_wr
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
rs1
of CSRRS
, CSRRC
instruction is not equal to 0)ex_csr_wr <= False
, when the instruction is otherCSSRW
, CSSRS
, CSSRC
, CSSRWI
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 | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | ❌ |
inst[1:0]
)
11
, then the instruction is base instruction00
, 01
, or 10
, then the instruction is c-extension instructionex:
If instruction isC.ADD
, then the instruction information ALU gains should beADD
// 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 offunct3
andop2
({inst[15:13]})
This section is modified from here.
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
This section is modified from here
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
, andCJ
format instruction can use only part of the RV32I registers, we have to map thers1'
,rs2'
, andrd'
to the corresponded register.
This section is modified from here
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
withfunct3
If the instruction is c-extension instruction, then decode the instruction with op2 and funct3, and set the
ex_alu_op
with correspondedfunct3
of based instruction.
ex_imm_sel
This section is modified from here.
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
ex_subtype
ex_memwr
This section is modified from here
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
ex_alu
This section is modified from here
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
ex_lui
This section is modified from here
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
ex_jal
This section is modified from here
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
ex_jalr
This section is modified from here
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
ex_branch
This section is modified from here
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
ex_system
This section is modified from here
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
ex_system_op
This section is modified from here
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
ex_csr
This section is modified from here
ex_csr <= ((inst[`OPCODE] == OP_SYSTEM) && (inst[`FUNC3] != OP_ECALL)) ||
// c-ext
+ (inst[`CINST] == 16'h9002);
Add additional conditions for c instruction -
C.EBREAK
`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
This section is modified from here
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
This section is modified from here
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
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.
We should be able to figure it out within a few days.