rv32g_hart.sv (9365B)
1 module rv32g_hart 2 import rv32g_pkg::*; 3 (input logic clk, 4 input logic rstN, 5 6 output logic [31:0] imem_addr, 7 input logic [31:0] imem_data, 8 input logic imem_valid, 9 10 output logic [31:0] dmem_addr, 11 input logic dmem_valid, 12 input logic [31:0] dmem_rdata, 13 output logic [31:0] dmem_wdata, 14 output logic dmem_we, 15 output logic [3:0] dmem_be, 16 17 output reg_t pc_out, 18 19 output exception_t exception); 20 21 reg_t next_pc; 22 23 // pipeline registers 24 ifid_reg_t ifid_reg; 25 idex_reg_t idex_reg; 26 exmem_reg_t exmem_reg; 27 memwb_reg_t memwb_reg; 28 29 // temporary fetch signals 30 logic [31:0] fetch_inst, ifid_inst, replay_inst; 31 logic replay_valid; 32 reg_t pc_reg, pc_plus4; // pre-computed registered +4 for critical path 33 34 // temporary decode signals 35 ctrl_t dec_ctrl; 36 reg_t dec_pc, dec_imm, idex_rs1_val, idex_rs2_val; 37 logic [4:0] dec_rs1_num, dec_rs2_num, dec_rd_num; 38 39 // temporary execute signals 40 reg_t ex_rs1_val, ex_rs2_val, ex_alu_out, ex_jalr_target, ex_wb_value; 41 logic ex_branch_taken; 42 43 // temporary memory signals 44 loadop_t mem_loadop; 45 storeop_t mem_storeop; 46 logic [31:0] mem_mem_out; 47 reg_t memwb_value; 48 49 // temporary writeback signals 50 logic wb_valid, wb_we; 51 52 // hazards and control flow 53 logic dec_uses_rs1, dec_uses_rs2; 54 forward_t dec_rs1_forward, dec_rs2_forward; 55 logic load_use_stall; 56 logic redirect_valid; 57 reg_t redirect_target; 58 59 // ============= 60 // === FETCH === 61 // ============= 62 63 assign pc_out = pc_reg; 64 assign ifid_inst = replay_valid ? replay_inst : fetch_inst; 65 66 stage_fetch u_fetch(.clk, .rstN, .flush_i(idex_reg.valid && idex_reg.ctrl.fence_flush), 67 .pc(pc_reg), .imem_addr, .imem_data, .imem_valid, 68 .inst(fetch_inst)); 69 // IF/ID pipeline register 70 always_ff @(posedge clk) begin 71 if (!rstN) begin 72 pc_reg <= BASE_ADDR; 73 pc_plus4 <= BASE_ADDR + 4; 74 ifid_reg.valid <= 1'b0; 75 replay_valid <= 1'b0; 76 end else if (redirect_valid) begin 77 pc_reg <= redirect_target; 78 pc_plus4 <= redirect_target + 4; 79 ifid_reg.valid <= 1'b0; 80 replay_valid <= 1'b0; 81 end else if (load_use_stall) begin 82 if (!replay_valid) replay_inst <= fetch_inst; 83 replay_valid <= 1'b1; 84 end else begin 85 pc_reg <= next_pc; 86 pc_plus4 <= next_pc + 4; 87 ifid_reg.valid <= 1'b1; 88 ifid_reg.pc <= pc_reg; 89 replay_valid <= 1'b0; 90 end 91 end 92 93 // ============== 94 // === DECODE === 95 // ============== 96 97 stage_decode u_decode(.clk, .rstN, .inst(ifid_inst), 98 .wb_we, .wb_rd_num(memwb_reg.rd_num), .wb_data(memwb_value), 99 .ctrl(dec_ctrl), .imm(dec_imm), 100 .rs1_num(dec_rs1_num), .rs2_num(dec_rs2_num), 101 .rs1_val(idex_rs1_val), .rs2_val(idex_rs2_val), 102 .rd_num(dec_rd_num)); 103 104 // assign control hazard signals 105 always_comb begin 106 dec_uses_rs1 = 1'b0; 107 dec_uses_rs2 = 1'b0; 108 dec_rs1_forward = FWD_REG; 109 dec_rs2_forward = FWD_REG; 110 111 unique case (opcode_t'(ifid_inst[6:0])) 112 OPCODE_JALR, OPCODE_LOAD, OPCODE_OP_IMM: dec_uses_rs1 = 1'b1; 113 OPCODE_BRANCH, OPCODE_STORE, OPCODE_OP: begin 114 dec_uses_rs1 = 1'b1; 115 dec_uses_rs2 = 1'b1; 116 end 117 default: ; 118 endcase 119 120 if (dec_uses_rs1 && dec_rs1_num != 0) begin 121 if (idex_reg.valid && idex_reg.ctrl.wbsrc != WB_NONE && 122 idex_reg.ctrl.wbsrc != WB_MEM && idex_reg.rd_num == dec_rs1_num) 123 dec_rs1_forward = FWD_EXMEM; 124 else if (exmem_reg.valid && exmem_reg.wbsrc != WB_NONE && 125 exmem_reg.wbsrc != WB_MEM && exmem_reg.rd_num == dec_rs1_num) 126 dec_rs1_forward = FWD_MEMWB; 127 end 128 129 if (dec_uses_rs2 && dec_rs2_num != 0) begin 130 if (idex_reg.valid && idex_reg.ctrl.wbsrc != WB_NONE && 131 idex_reg.ctrl.wbsrc != WB_MEM && idex_reg.rd_num == dec_rs2_num) 132 dec_rs2_forward = FWD_EXMEM; 133 else if (exmem_reg.valid && exmem_reg.wbsrc != WB_NONE && 134 exmem_reg.wbsrc != WB_MEM && exmem_reg.rd_num == dec_rs2_num) 135 dec_rs2_forward = FWD_MEMWB; 136 end 137 138 load_use_stall = ifid_reg.valid && imem_valid && 139 ((idex_reg.valid && idex_reg.ctrl.wbsrc == WB_MEM && 140 idex_reg.rd_num != 0 && 141 ((dec_uses_rs1 && dec_rs1_num == idex_reg.rd_num) || 142 (dec_uses_rs2 && dec_rs2_num == idex_reg.rd_num))) || 143 (exmem_reg.valid && exmem_reg.wbsrc == WB_MEM && 144 exmem_reg.rd_num != 0 && 145 ((dec_uses_rs1 && dec_rs1_num == exmem_reg.rd_num) || 146 (dec_uses_rs2 && dec_rs2_num == exmem_reg.rd_num)))); 147 end 148 149 // ID/EX pipeline register 150 always_ff @(posedge clk or negedge rstN) begin 151 if (!rstN) begin 152 idex_reg <= '0; 153 end else if (redirect_valid || load_use_stall) begin 154 idex_reg.valid <= 1'b0; 155 end else begin 156 // latch decode outputs in normal operation 157 idex_reg.valid <= ifid_reg.valid && imem_valid; 158 idex_reg.ctrl <= dec_ctrl; 159 idex_reg.pc <= ifid_reg.pc; 160 idex_reg.imm <= dec_imm; 161 idex_reg.rs1_forward <= dec_rs1_forward; 162 idex_reg.rs2_forward <= dec_rs2_forward; 163 idex_reg.rd_num <= dec_rd_num; 164 end 165 end 166 167 // =============== 168 // === EXECUTE === 169 // =============== 170 171 // select EX stage operands via forwarding from EX/MEM and MEM/WB pipeline registers 172 always_comb begin 173 unique case (idex_reg.ctrl.wbsrc) 174 WB_PC: ex_wb_value = idex_reg.pc + 4; 175 WB_ALU: ex_wb_value = ex_alu_out; 176 WB_IMM: ex_wb_value = idex_reg.imm; 177 default: ex_wb_value = '0; 178 endcase 179 180 memwb_value = memwb_reg.wbsrc == WB_MEM ? mem_mem_out : 181 memwb_reg.wb_value; 182 183 unique case (idex_reg.rs1_forward) 184 FWD_REG: ex_rs1_val = idex_rs1_val; 185 FWD_EXMEM: ex_rs1_val = exmem_reg.wb_value; 186 FWD_MEMWB: ex_rs1_val = memwb_reg.wb_value; 187 default: ex_rs1_val = '0; 188 endcase 189 190 unique case (idex_reg.rs2_forward) 191 FWD_REG: ex_rs2_val = idex_rs2_val; 192 FWD_EXMEM: ex_rs2_val = exmem_reg.wb_value; 193 FWD_MEMWB: ex_rs2_val = memwb_reg.wb_value; 194 default: ex_rs2_val = '0; 195 endcase 196 end 197 198 stage_execute u_execute(.clk, 199 .imm(idex_reg.imm), 200 .pc(idex_reg.pc), 201 .rs1_val(ex_rs1_val), 202 .rs2_val(ex_rs2_val), 203 .op(idex_reg.ctrl.aluop), 204 .op1src(idex_reg.ctrl.aluop1src), 205 .op2src(idex_reg.ctrl.aluop2src), 206 .branchop(idex_reg.ctrl.branchop), 207 .out(ex_alu_out), 208 .branch_taken(ex_branch_taken), 209 .jalr_target(ex_jalr_target)); 210 // EX/MEM pipeline register 211 always_ff @(posedge clk or negedge rstN) begin 212 if (!rstN) begin 213 exmem_reg <= '0; 214 end else begin 215 exmem_reg.valid <= idex_reg.valid; 216 exmem_reg.alu_out <= ex_alu_out; 217 exmem_reg.rs2_val <= ex_rs2_val; 218 exmem_reg.wb_value <= ex_wb_value; 219 exmem_reg.rd_num <= idex_reg.rd_num; 220 exmem_reg.branch_taken <= ex_branch_taken; 221 exmem_reg.branchop <= idex_reg.ctrl.branchop; 222 exmem_reg.loadop <= idex_reg.ctrl.loadop; 223 exmem_reg.storeop <= idex_reg.ctrl.storeop; 224 exmem_reg.wbsrc <= idex_reg.ctrl.wbsrc; 225 exmem_reg.pcsrc <= idex_reg.ctrl.pcsrc; 226 exmem_reg.exception <= idex_reg.ctrl.exception; 227 exmem_reg.fence_flush <= idex_reg.ctrl.fence_flush; 228 end 229 end 230 231 // resolve control transfers in EX stage and select the next PC 232 always_comb begin 233 redirect_valid = 1'b0; 234 redirect_target = idex_reg.pc + 4; 235 236 if (idex_reg.valid) begin 237 if (idex_reg.ctrl.fence_flush) begin 238 redirect_valid = 1'b1; 239 end else begin 240 unique case (idex_reg.ctrl.pcsrc) 241 PC_IMM: begin 242 if (idex_reg.ctrl.branchop == BRANCH_NONE || ex_branch_taken) begin 243 redirect_valid = 1'b1; 244 redirect_target = idex_reg.pc + idex_reg.imm; 245 end 246 end 247 PC_ALU: begin 248 redirect_valid = 1'b1; 249 redirect_target = ex_jalr_target & ~32'b1; 250 end 251 default: ; 252 endcase 253 end 254 end 255 256 next_pc = redirect_valid ? redirect_target : pc_plus4; 257 end 258 259 // ============== 260 // === MEMORY === 261 // ============== 262 263 assign mem_loadop = memwb_reg.valid ? memwb_reg.loadop : LD_NONE; 264 assign mem_storeop = exmem_reg.valid ? exmem_reg.storeop : ST_NONE; 265 266 stage_memory u_mem(.loadop(mem_loadop), 267 .storeop(mem_storeop), 268 .addr(memwb_reg.alu_out), 269 .alu_out(exmem_reg.alu_out), 270 .rs2_val(exmem_reg.rs2_val), 271 .mem_out(mem_mem_out), 272 .dmem_addr, .dmem_rdata, .dmem_wdata, .dmem_we, .dmem_be); 273 // MEM/WB pipeline register 274 always_ff @(posedge clk or negedge rstN) begin 275 if (!rstN) begin 276 memwb_reg <= '0; 277 end else begin 278 memwb_reg.valid <= exmem_reg.valid; 279 memwb_reg.alu_out <= exmem_reg.alu_out; 280 memwb_reg.wb_value <= exmem_reg.wb_value; 281 memwb_reg.rd_num <= exmem_reg.rd_num; 282 memwb_reg.loadop <= exmem_reg.loadop; 283 memwb_reg.storeop <= exmem_reg.storeop; 284 memwb_reg.wbsrc <= exmem_reg.wbsrc; 285 memwb_reg.exception <= exmem_reg.exception; 286 end 287 end 288 289 // ================= 290 // === WRITEBACK === 291 // ================= 292 293 // assigns signals that are forwarded back to ID stage 294 always_comb begin 295 wb_valid = memwb_reg.valid && 296 (memwb_reg.wbsrc != WB_MEM || dmem_valid); 297 wb_we = wb_valid && memwb_reg.wbsrc != WB_NONE && memwb_reg.rd_num != 0; 298 end 299 300 assign exception = memwb_reg.valid ? memwb_reg.exception : EXC_NONE; 301 302 endmodule: rv32g_hart