diff --git a/controller.sv b/controller.sv index 2019e6a3..fd1b4851 100644 --- a/controller.sv +++ b/controller.sv @@ -138,6 +138,9 @@ module controller // Jump target calcuation done detection input logic jump_in_ex_i, // jump is being calculated in ALU + // Branch result from ALU + input logic branch_taken_i, + output logic drop_instruction_o, // prevent instruction to enter ID stage `ifdef BRANCH_PREDICTION output logic wrong_branch_taken_o, // 1 if the wrong branch was selected @@ -346,6 +349,30 @@ module controller end end + `OPCODE_BRANCH: begin // Branch + rega_used = 1'b1; + regb_used = 1'b1; + + unique case (instr_rdata_i) inside + `INSTR_BEQ: alu_operator = `ALU_EQ; + `INSTR_BNE: alu_operator = `ALU_NE; + `INSTR_BLT: alu_operator = `ALU_LTS; + `INSTR_BGE: alu_operator = `ALU_GES; + `INSTR_BLTU: alu_operator = `ALU_LTU; + `INSTR_BGEU: alu_operator = `ALU_GEU; + + default: begin + illegal_insn_o = 1'b1; + end + endcase // case (instr_rdata_i) + + if (branch_taken_i == 1'b1) begin + pc_mux_sel_o = `PC_FROM_IMM; // TODO: Think about clever adder use + end else begin + pc_mux_sel_o = `INCR_PC; + end + end + /* `OPCODE_JR: @@ -1246,10 +1273,10 @@ module controller deassert_we = 1'b1; end - // Stall because of JAL/JALR - // Stall until jump target is calculated in EX (1 cycle, then fetch instruction) - if ( (instr_rdata_i[6:0] == `OPCODE_JAL || instr_rdata_i[6:0] == `OPCODE_JALR) && - (jump_in_ex_i == 1'b0) ) + // Stall because of JAL/JALR/branch + // Stall until jump target or branch decision is calculated in EX (1 cycle, then fetch instruction) + if ( (instr_rdata_i[6:0] == `OPCODE_JAL || instr_rdata_i[6:0] == `OPCODE_JALR + || instr_rdata_i[6:0] == `OPCODE_BRANCH) && (jump_in_ex_i == 1'b0) ) begin j_stall = 1'b1; //deassert_we = 1'b1; @@ -1265,6 +1292,7 @@ module controller end + // NOTE: current_pc_id_i is wrong after drop instruction ! `ifdef BRANCH_PREDICTION assign drop_instruction_o = wrong_branch_taken | j_stall; `else @@ -1365,7 +1393,8 @@ module controller (instr_rdata_i[31:26] == `OPCODE_RFE) ); */ // TODO: FIXME - assign jump_in_id_o = ((instr_rdata_i[6:0] == `OPCODE_JAL) || (instr_rdata_i[6:0] == `OPCODE_JALR)); + assign jump_in_id_o = ((instr_rdata_i[6:0] == `OPCODE_JAL) || (instr_rdata_i[6:0] == `OPCODE_JALR) || + (instr_rdata_i[6:0] == `OPCODE_BRANCH)); // update registers diff --git a/ex_stage.sv b/ex_stage.sv index c88c6121..265f2edb 100644 --- a/ex_stage.sv +++ b/ex_stage.sv @@ -122,7 +122,10 @@ module ex_stage output logic [31:0] regfile_alu_wdata_fw_pc_o, // forward to PC, no multiplication // JAL/JALR jumpt target calculation (to IF) - output logic [31:0] jump_target_o + output logic [31:0] jump_target_o, + + // Branch decision (to controller) + output logic branch_taken_o `ifdef TCDM_ADDR_PRECAL , @@ -189,6 +192,9 @@ module ex_stage // PC calculation for JAL/JALR assign jump_target_o = alu_jump_target_int; + // Branch is taken when result == 1'b1 + assign branch_taken_o = alu_result[0]; + //////////////////////////// // _ _ _ _ // diff --git a/id_stage.sv b/id_stage.sv index dfd503e9..73c967d7 100644 --- a/id_stage.sv +++ b/id_stage.sv @@ -41,6 +41,8 @@ module id_stage input logic fetch_enable_i, output logic core_busy_o, + input logic branch_taken_i, + // Interface to instruction memory input logic [31:0] instr_rdata_i, // comes from pipeline of IF stage output logic instr_req_o, @@ -297,7 +299,7 @@ module id_stage assign imm_i_type = { {20 {instr_rdata_i[31]}}, instr_rdata_i[31:20] }; assign imm_s_type = { {20 {instr_rdata_i[31]}}, instr_rdata_i[31:25], instr_rdata_i[11:7] }; assign imm_sb_type = { {20 {instr_rdata_i[31]}}, instr_rdata_i[31], instr_rdata_i[7], - instr_rdata_i[30:25], instr_rdata_i[11:8] }; + instr_rdata_i[30:25], instr_rdata_i[11:8], 1'b0 }; assign imm_u_type = { instr_rdata_i[31:12], {12 {1'b0}} }; assign imm_uj_type = { {20 {instr_rdata_i[31]}}, instr_rdata_i[19:12], instr_rdata_i[20], instr_rdata_i[30:21], 1'b0 }; @@ -344,6 +346,7 @@ module id_stage // 1'b1: pc_from_immediate_o = imm_i_type; // JALR // endcase // case (pc_from_immediate_mux_sel) //end + assign pc_from_immediate_o = imm_sb_type; // TODO: Remove/Replace? // PC Mux always_comb @@ -550,6 +553,8 @@ module id_stage .eoc_o ( eoc ), .core_busy_o ( core_busy_o ), + .branch_taken_i ( branch_taken_i ), + // Signal from-to PC pipe (instr rdata) and instr mem system (req and ack) .instr_rdata_i ( instr_rdata_i ), .instr_req_o ( instr_req_o ), diff --git a/if_stage.sv b/if_stage.sv index 6ff9cd67..8e503572 100644 --- a/if_stage.sv +++ b/if_stage.sv @@ -53,7 +53,7 @@ module if_stage input logic [31:0] exception_pc_reg_i, // address used to restore the program counter when the interrupt/exception is served input logic [31:0] pc_from_regfile_i, // pc from reg file input logic [31:0] pc_from_alu_i, // calculated jump target form ALU - //input logic [31:0] pc_from_immediate_i, // pc from immediate + input logic [31:0] pc_from_immediate_i, // pc from immediate input logic [31:0] pc_from_hwloop_i, // pc from hwloop start addr input logic [2:0] pc_mux_sel_i, // sel for pc multiplexer input logic pc_mux_boot_i, // load boot address as PC @@ -94,7 +94,7 @@ module if_stage // Address to fetch the instruction assign instr_addr_o = next_pc; - //assign branch_taken = current_pc_id_o + pc_from_immediate_i; + assign branch_taken = current_pc_id_o + pc_from_immediate_i; //assign branch_not_taken = current_pc_if_o + 32'd4; // Next PC Selection: pc_mux_sel_i comes from id_stage.controller @@ -103,9 +103,9 @@ module if_stage case (pc_mux_sel_i) `INCR_PC: begin next_pc = current_pc_if_o + 32'd4; end // PC is incremented and points the next instruction `NO_INCR: begin next_pc = current_pc_if_o; end // PC is not incremented - `PC_FROM_REGFILE: begin next_pc = pc_from_regfile_i; end // PC is taken from the regfile + //`PC_FROM_REGFILE: begin next_pc = pc_from_regfile_i; end // PC is taken from the regfile `PC_FROM_ALU: begin next_pc = pc_from_alu_i; end // use calculated jump target from ALU - //`PC_FROM_IMM: begin next_pc = branch_taken; end // PC is taken from current PC in id + the immediate displacement + `PC_FROM_IMM: begin next_pc = branch_taken; end // PC is taken from current PC in id + the immediate displacement `PC_EXCEPTION: begin next_pc = exc_pc; end // PC that points to the exception `EXC_PC_REG: begin next_pc = exception_pc_reg_i; end // restore the PC when exiting from interr/ecpetions `HWLOOP_ADDR: begin next_pc = pc_from_hwloop_i; end // PC is taken from hwloop start addr diff --git a/include/defines.sv b/include/defines.sv index 3a964cf7..297b1de1 100644 --- a/include/defines.sv +++ b/include/defines.sv @@ -363,7 +363,8 @@ endfunction // prettyPrintInstruction // PC mux selector defines `define INCR_PC 3'b000 `define NO_INCR 3'b001 -`define PC_FROM_REGFILE 3'b010 +//`define PC_FROM_REGFILE 3'b010 Removed in RiscV +`define PC_FROM_IMM 3'b010 //`define PC_FROM_IMM 3'b011 Replaced in RiscV `define PC_FROM_ALU 3'b011 `define PC_EXCEPTION 3'b100 diff --git a/riscv_core.sv b/riscv_core.sv index f21454aa..9d29f8d4 100644 --- a/riscv_core.sv +++ b/riscv_core.sv @@ -90,10 +90,14 @@ module riscv_core // Forwarding //logic [31:0] pc_from_immediate_id; //take PC from immediate in case of Jump + logic [31:0] pc_from_immediate_id; //take PC from immediate in case of branch (RiscV) // Jump handling logic [31:0] jump_target; + // Branch decision from EX + logic branch_taken; + // Stalling logic stall_if; // Stall instruction fetch(deassert request) logic stall_id; // Stall PC stage and instr memory and data memo @@ -281,7 +285,7 @@ module riscv_core .force_nop_i ( force_nop_id ), // select incoming instr or NOP .exception_pc_reg_i ( epcr ), // Exception PC register .pc_from_regfile_i ( pc_from_regfile_id ), // pc from reg file - //.pc_from_immediate_i ( pc_from_immediate_id ), // pc from immediate + .pc_from_immediate_i ( pc_from_immediate_id ), // pc from immediate .pc_from_alu_i ( jump_target ), // calculated jump target from ALU (EX) .pc_from_hwloop_i ( hwloop_targ_addr ), // pc from hwloop start address .pc_mux_sel_i ( pc_mux_sel_id ), // sel for pc multiplexer @@ -350,6 +354,8 @@ module riscv_core // Processor Enable .fetch_enable_i ( fetch_enable_i ), + .branch_taken_i ( branch_taken ), + .core_busy_o ( core_busy_o ), // Interface to instruction memory @@ -366,7 +372,7 @@ module riscv_core .pc_from_regfile_o ( pc_from_regfile_id ), .current_pc_if_i ( current_pc_if ), .current_pc_id_i ( current_pc_id ), - //.pc_from_immediate_o ( pc_from_immediate_id ), + .pc_from_immediate_o ( pc_from_immediate_id ), .sr_flag_fw_i ( sr_flag_fw ), .sr_flag_i ( sr_flag ), @@ -570,6 +576,9 @@ module riscv_core // Jump target address .jump_target_o ( jump_target ), + // Branch decision + .branch_taken_o ( branch_taken ), + // To ID stage: Forwarding signals .regfile_alu_waddr_fw_o ( regfile_alu_waddr_fw ), .regfile_alu_we_fw_o ( regfile_alu_we_fw ), @@ -818,7 +827,6 @@ module riscv_core // log execution always @(posedge clk) begin - #1 r = id_stage_i.registers_i.MemContentxDP; instr = id_stage_i.instr_rdata_i[31:0]; pc = id_stage_i.current_pc_id_i; @@ -827,7 +835,7 @@ module riscv_core begin //$display("%h", instr); $fwrite(f, "%t:\t0x%h\t0x%h\t", $time, pc, instr); - casex (instr) + unique case (instr) inside `INSTR_LUI: printIInstr("LUI"); `INSTR_AUIPC: printIInstr("AUIPC"); `INSTR_JAL: printUJInstr("JAL"); @@ -912,7 +920,7 @@ module riscv_core logic [31:0] s_imm; begin s_imm = { {20 {instr[31]}}, instr[31:25], instr[11:7] }; - $fdisplay(f, "%s x%0d (0x%h), x%d (0x%h), 0x%h (imm)", mnemonic, + $fdisplay(f, "%s x%0d (0x%h), x%0d (0x%h), 0x%h (imm)", mnemonic, instr[`REG_S1], r[instr[`REG_S1]], instr[`REG_S2], r[instr[`REG_S2]], s_imm); end @@ -922,7 +930,7 @@ module riscv_core logic [31:0] sb_imm; begin sb_imm = { {20 {instr[31]}}, instr[31], instr[7], instr[30:25], instr[11:8] }; - $fdisplay(f, "%s x%0d (0x%h), x%d (0x%h), 0x%h (imm)", mnemonic, + $fdisplay(f, "%s x%0d (0x%h), x%0d (0x%h), 0x%h (imm)", mnemonic, instr[`REG_S1], r[instr[`REG_S1]], instr[`REG_S2], r[instr[`REG_S2]], sb_imm); end