rv32g-core

Pipelined, synthesizable, and fabricable RISC-V core in SystemVerilog+Yosys+OpenROAD
Log | Files | Refs | LICENSE

commit b912995e94db9b6dad3d569897771ac3336e66ea
parent dd7a05cc0e99dde0c7c9db643ffbe2bacf84d186
Author: Vineet Kumar <git@vineetk.net>
Date:   Sun, 31 May 2026 17:26:14 -0400

parse instructions into names to generate control signals

Diffstat:
Mrtl/stage_decode.sv | 92++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 80 insertions(+), 12 deletions(-)

diff --git a/rtl/stage_decode.sv b/rtl/stage_decode.sv @@ -16,7 +16,7 @@ module stage_decode JTYPE} inst_type_t; - typedef enum {INVALID, + typedef enum {NAME_INVALID, // rv32i LUI, AUIPC, @@ -30,6 +30,7 @@ module stage_decode BGEU, LB, LH, + LW, LBU, LHU, SB, @@ -64,17 +65,17 @@ module stage_decode // based off of Unprivileged ISA Chapter 36 Table 72 (no reserved) typedef enum logic [6:0] {OPCODE_INVALID = 'b0000000, // rv32i/m + OPCODE_LUI = 'b0110111, + OPCODE_AUIPC = 'b0010111, + OPCODE_JAL = 'b1101111, + OPCODE_JALR = 'b1100111, + OPCODE_BRANCH = 'b1100011, OPCODE_LOAD = 'b0000011, OPCODE_STORE = 'b0100011, - OPCODE_BRANCH = 'b1100011, - OPCODE_JALR = 'b1100111, - OPCODE_JAL = 'b1101111, - OPCODE_MISC_MEM = 'b0001111, OPCODE_OP_IMM = 'b0010011, OPCODE_OP = 'b0110011, + OPCODE_MISC_MEM = 'b0001111, OPCODE_SYSTEM = 'b1110011, - OPCODE_AUIPC = 'b0010111, - OPCODE_LUI = 'b0110111, // rv32f/d OPCODE_LOAD_FP = 'b0000111, OPCODE_STORE_FP = 'b0100111, @@ -93,7 +94,7 @@ module stage_decode OPCODE_CUSTOM_1 = 'b0101011, OPCODE_CUSTOM_2 = 'b1011011, OPCODE_CUSTOM_3 = 'b1111011} - opcode_t; + opcode_t; logic [6:0] funct7 = inst[31:25]; logic [4:0] rs2_num = inst[24:20]; @@ -109,15 +110,15 @@ module stage_decode always_comb begin unique case (opcode) // rv32i - OPCODE_OP: inst_type = RTYPE; - OPCODE_OP_IMM: inst_type = ITYPE; - OPCODE_AUIPC: inst_type = ITYPE; OPCODE_LUI: inst_type = ITYPE; - OPCODE_BRANCH: inst_type = BTYPE; + OPCODE_AUIPC: inst_type = ITYPE; OPCODE_JAL: inst_type = JTYPE; OPCODE_JALR: inst_type = ITYPE; + OPCODE_BRANCH: inst_type = BTYPE; OPCODE_LOAD: inst_type = ITYPE; OPCODE_STORE: inst_type = STYPE; + OPCODE_OP_IMM: inst_type = ITYPE; + OPCODE_OP: inst_type = RTYPE; OPCODE_MISC_MEM: inst_type = ITYPE; OPCODE_SYSTEM: inst_type = ITYPE; default: inst_type = INVALIDTYPE; @@ -137,6 +138,73 @@ module stage_decode endcase end + // parse what the actual instruction + always_comb begin + casez ({funct7, funct3, opcode}) + // rv32i + {7'b???????, 3'b???, OPCODE_LUI}: name = LUI; + {7'b???????, 3'b???, OPCODE_AUIPC}: name = AUIPC; + {7'b???????, 3'b???, OPCODE_JAL}: name = JAL; + {7'b???????, 3'b???, OPCODE_JALR}: name = JALR; + {7'b???????, 3'b000, OPCODE_BRANCH}: name = BEQ; + {7'b???????, 3'b001, OPCODE_BRANCH}: name = BNE; + {7'b???????, 3'b100, OPCODE_BRANCH}: name = BLT; + {7'b???????, 3'b101, OPCODE_BRANCH}: name = BGE; + {7'b???????, 3'b110, OPCODE_BRANCH}: name = BLTU; + {7'b???????, 3'b111, OPCODE_BRANCH}: name = BGEU; + {7'b???????, 3'b000, OPCODE_LOAD}: name = LB; + {7'b???????, 3'b001, OPCODE_LOAD}: name = LH; + {7'b???????, 3'b010, OPCODE_LOAD}: name = LW; + {7'b???????, 3'b100, OPCODE_LOAD}: name = LBU; + {7'b???????, 3'b101, OPCODE_LOAD}: name = LHU; + {7'b???????, 3'b000, OPCODE_STORE}: name = SB; + {7'b???????, 3'b001, OPCODE_STORE}: name = SH; + {7'b???????, 3'b010, OPCODE_STORE}: name = SW; + {7'b???????, 3'b000, OPCODE_OP_IMM}: name = ADDI; + {7'b???????, 3'b010, OPCODE_OP_IMM}: name = SLTI; + {7'b???????, 3'b011, OPCODE_OP_IMM}: name = SLTIU; + {7'b???????, 3'b100, OPCODE_OP_IMM}: name = XORI; + {7'b???????, 3'b110, OPCODE_OP_IMM}: name = ORI; + {7'b???????, 3'b111, OPCODE_OP_IMM}: name = ANDI; + {7'b0000000, 3'b001, OPCODE_OP_IMM}: name = SLLI; + {7'b0000000, 3'b101, OPCODE_OP_IMM}: name = SRLI; + {7'b0100000, 3'b101, OPCODE_OP_IMM}: name = SRAI; + {7'b0000000, 3'b000, OPCODE_OP}: name = ADD; + {7'b0100000, 3'b000, OPCODE_OP}: name = SUB; + {7'b0000000, 3'b001, OPCODE_OP}: name = SLL; + {7'b0000000, 3'b010, OPCODE_OP}: name = SLT; + {7'b0000000, 3'b011, OPCODE_OP}: name = SLTU; + {7'b0000000, 3'b100, OPCODE_OP}: name = XOR; + {7'b0000000, 3'b101, OPCODE_OP}: name = SRL; + {7'b0100000, 3'b101, OPCODE_OP}: name = SRA; + {7'b0000000, 3'b110, OPCODE_OP}: name = OR; + {7'b0000000, 3'b111, OPCODE_OP}: name = AND; + {7'b???????, 3'b000, OPCODE_MISC_MEM}: begin + // FENCE{,.TSO}/PAUSE encoding is a bit different + if (rs1_num == '0) begin + if (inst[31:20] == 'b1000_0011_0011) name = FENCE_TSO; + else if (inst[31:20] == 'b0000_0001_0000) name = PAUSE; + else name = NAME_INVALID; + end else name = FENCE; + end + {7'b0000000, 3'b000, OPCODE_SYSTEM}: begin + // ECALL and EBREAK encoding is also a bit different + if (rs1_num == '0 && rd_num == '0 && rs2_num[4:1] == '0) begin + name = (rs2_num[0] == '0) ? ECALL : EBREAK; + end else name = NAME_INVALID; + end + default: name = NAME_INVALID; + endcase + end + + // set control signals based on instruction name + always_comb begin + case (name) + // rv32i + default: ctrl = '0; + endcase + end + assign rs1_val = regfile[rs1_num]; assign rs2_val = regfile[rs2_num];