rv32g-core

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

stage_decode.sv (5652B)


      1 module stage_decode
      2   import rv32g_pkg::*;
      3    (input logic		clk,
      4     input logic		rstN,
      5     input logic [31:0]	inst,
      6     input logic		wb_we,
      7     input logic [4:0]	wb_rd_num,
      8     input logic [31:0]	wb_data,
      9     output ctrl_t	ctrl,
     10     output logic [31:0]	imm,
     11     output logic [31:0]	rs1_val,
     12     output logic [31:0]	rs2_val,
     13     output logic [4:0]	rs1_num,
     14     output logic [4:0]	rs2_num,
     15     output logic [4:0]	rd_num);
     16 
     17    logic [6:0] funct7;
     18    logic [2:0] funct3;
     19    opcode_t    opcode;
     20    inst_type_t inst_type;
     21    reg_t       regfile [0:31];
     22    reg_t       regfile_b [0:31];
     23 
     24    always_comb begin
     25      funct7 = inst[31:25];
     26      rs2_num = inst[24:20];
     27      rs1_num = inst[19:15];
     28      funct3 = inst[14:12];
     29      rd_num = inst[11:7];
     30      opcode = opcode_t'(inst[6:0]);
     31    end
     32 
     33    // parse the type for each instruction
     34    always_comb begin
     35      unique case (opcode)
     36        // rv32i
     37        OPCODE_LUI: inst_type = UTYPE;
     38        OPCODE_AUIPC: inst_type = UTYPE;
     39        OPCODE_JAL: inst_type = JTYPE;
     40        OPCODE_JALR: inst_type = ITYPE;
     41        OPCODE_BRANCH: inst_type = BTYPE;
     42        OPCODE_LOAD: inst_type = ITYPE;
     43        OPCODE_STORE: inst_type = STYPE;
     44        OPCODE_OP_IMM: inst_type = ITYPE;
     45        OPCODE_OP: inst_type = RTYPE;
     46        OPCODE_MISC_MEM: inst_type = ITYPE;
     47        OPCODE_SYSTEM: inst_type = ITYPE;
     48        default: inst_type = INVALIDTYPE;
     49      endcase
     50    end
     51 
     52    // parse the (sign-extended) immediate value
     53    // based off of Unprivileged ISA Section 2.3 Figure 1
     54    always_comb begin
     55      unique case (inst_type)
     56        ITYPE: imm = {{20{inst[31]}}, inst[31:20]};
     57        STYPE: imm = {{20{inst[31]}}, inst[31:25], inst[11:7]};
     58        BTYPE: imm = {{20{inst[31]}}, inst[7], inst[30:25], inst[11:8], 1'b0};
     59        UTYPE: imm = inst[31:12] << 12;
     60        JTYPE: imm = {{12{inst[31]}}, inst[19:12], inst[20], inst[30:25], inst[24:21], 1'b0};
     61        default: imm = '0;
     62      endcase
     63    end
     64 
     65    // set control signals
     66    always_comb begin
     67      ctrl = '{aluop:       ALU_NONE,
     68 	      aluop1src:   ALUOP1_NONE,
     69 	      aluop2src:   ALUOP2_NONE,
     70 	      loadop:      LD_NONE,
     71 	      storeop:     ST_NONE,
     72 	      pcsrc:       PC_SEQ,
     73 	      branchop:    BRANCH_NONE,
     74 	      wbsrc:       WB_NONE,
     75 	      exception:   EXC_NONE,
     76 	      fence_flush: 1'b0};
     77 
     78      // the major opcodes share the same signals, just operation varies based on funct
     79      unique case (opcode)
     80        OPCODE_LUI: ctrl.wbsrc = WB_IMM;
     81        OPCODE_AUIPC: begin
     82          ctrl.aluop = ALU_ADD;
     83          ctrl.aluop1src = ALUOP1_PC;
     84          ctrl.aluop2src = ALUOP2_IMM;
     85          ctrl.wbsrc = WB_ALU;
     86        end
     87        OPCODE_JAL: begin
     88          ctrl.pcsrc = PC_IMM;
     89          ctrl.wbsrc = WB_PC;
     90        end
     91        OPCODE_JALR: begin
     92 	 ctrl.aluop = ALU_ADD;
     93 	 ctrl.aluop1src = ALUOP1_REG;
     94 	 ctrl.aluop2src = ALUOP2_IMM;
     95          ctrl.pcsrc = PC_ALU;
     96          ctrl.wbsrc = WB_PC;
     97        end
     98        OPCODE_BRANCH: begin
     99 	 ctrl.aluop1src = ALUOP1_REG;
    100 	 ctrl.aluop2src = ALUOP2_REG;
    101 	 ctrl.pcsrc = PC_IMM;
    102 	 ctrl.branchop = branchop_t'(funct3);
    103        end
    104        OPCODE_LOAD: begin
    105          ctrl.aluop = ALU_ADD;
    106 	 ctrl.aluop1src = ALUOP1_REG;
    107 	 ctrl.aluop2src = ALUOP2_IMM;
    108 	 ctrl.wbsrc = WB_MEM;
    109 	 ctrl.loadop = loadop_t'(funct3);
    110        end
    111        OPCODE_STORE: begin
    112          ctrl.aluop = ALU_ADD;
    113 	 ctrl.aluop1src = ALUOP1_REG;
    114 	 ctrl.aluop2src = ALUOP2_IMM;
    115 	 ctrl.storeop = storeop_t'(funct3);
    116        end
    117        OPCODE_OP_IMM: begin
    118 	 ctrl.aluop1src = ALUOP1_REG;
    119 	 ctrl.aluop2src = ALUOP2_IMM;
    120 	 ctrl.wbsrc = WB_ALU;
    121 	 unique case (funct3)
    122 	   // rv32i; done in same order as it appears in chapter 36 of unprivileged manual
    123 	   3'b000: ctrl.aluop = ALU_ADD;
    124 	   3'b010: ctrl.aluop = ALU_SLT;
    125 	   3'b011: ctrl.aluop = ALU_SLTU;
    126 	   3'b100: ctrl.aluop = ALU_XOR;
    127 	   3'b110: ctrl.aluop = ALU_OR;
    128 	   3'b111: ctrl.aluop = ALU_AND;
    129 	   3'b001: ctrl.aluop = (funct7 == '0) ? ALU_SLL : ALU_NONE;
    130 	   3'b101: begin
    131 	     if ({funct7[6], funct7[4:0]} == '0) ctrl.aluop = (funct7[5] == '0) ? ALU_SRL : ALU_SRA;
    132 	     else ctrl.aluop = ALU_NONE;
    133 	   end
    134 	 endcase
    135        end
    136        OPCODE_OP: begin
    137 	 ctrl.aluop1src = ALUOP1_REG;
    138 	 ctrl.aluop2src = ALUOP2_REG;
    139 	 ctrl.wbsrc = WB_ALU;
    140 	 unique case ({funct7, funct3})
    141 	   // rv32i
    142 	   {7'b0000000, 3'b000}: ctrl.aluop = ALU_ADD;
    143 	   {7'b0100000, 3'b000}: ctrl.aluop = ALU_SUB;
    144 	   {7'b0000000, 3'b001}: ctrl.aluop = ALU_SLL;
    145 	   {7'b0000000, 3'b010}: ctrl.aluop = ALU_SLT;
    146 	   {7'b0000000, 3'b011}: ctrl.aluop = ALU_SLTU;
    147 	   {7'b0000000, 3'b100}: ctrl.aluop = ALU_XOR;
    148 	   {7'b0000000, 3'b101}: ctrl.aluop = ALU_SRL;
    149 	   {7'b0100000, 3'b101}: ctrl.aluop = ALU_SRA;
    150 	   {7'b0000000, 3'b110}: ctrl.aluop = ALU_OR;
    151 	   {7'b0000000, 3'b111}: ctrl.aluop = ALU_AND;
    152 	   default: ctrl.aluop = ALU_NONE;
    153 	 endcase
    154        end
    155        OPCODE_MISC_MEM: ctrl.fence_flush = rs1_num == '0 && rd_num == '0 && inst[31:20] == '0;
    156        OPCODE_SYSTEM: begin
    157 	 // ECALL and EBREAK encoding is also a bit different
    158 	 if (rs1_num == '0 && rd_num == '0 && rs2_num[4:1] == '0) begin
    159 	   ctrl.exception = (rs2_num[0] == '0) ? EXC_CALL : EXC_BKPT;
    160 	 end else ctrl.exception = EXC_NONE;
    161        end
    162        default: ;
    163      endcase
    164    end
    165 
    166    always_ff @(posedge clk or negedge rstN) begin
    167      if (!rstN) begin
    168        rs1_val <= '0;
    169        rs2_val <= '0;
    170      end else begin
    171        if (wb_we) begin
    172          regfile[wb_rd_num] <= wb_data;
    173          regfile_b[wb_rd_num] <= wb_data;
    174        end
    175 
    176        rs1_val <= (rs1_num == 0) ? '0 :
    177 		  ((wb_we && wb_rd_num == rs1_num) ? wb_data : regfile[rs1_num]);
    178        rs2_val <= (rs2_num == 0) ? '0 :
    179 		  ((wb_we && wb_rd_num == rs2_num) ? wb_data : regfile_b[rs2_num]);
    180      end
    181    end
    182 
    183 endmodule: stage_decode