diff --git a/alu.sv b/alu.sv index 9e69242c..c775d917 100644 --- a/alu.sv +++ b/alu.sv @@ -36,6 +36,7 @@ module alu input logic [`ALU_OP_WIDTH-1:0] operator_i, input logic [31:0] operand_a_i, input logic [31:0] operand_b_i, + input logic [31:0] operand_c_i, // for jump target calculation input logic carry_i, input logic flag_i, @@ -44,12 +45,15 @@ module alu input logic [1:0] vec_ext_i, output logic [31:0] result_o, + output logic [31:0] jump_target_o, output logic overflow_o, output logic carry_o, output logic flag_o ); + logic [31:0] pc_after_jal; + logic [31:0] operand_a_rev; // bit reversed signal of operand_a_i // bit reverse operand_a for left shifts @@ -140,6 +144,9 @@ module alu assign {carry_out[2], adder_result[23:16]} = adder_op_a[23:16] + adder_op_b[23:16] + carry_in[2]; assign {carry_out[3], adder_result[31:24]} = adder_op_a[31:24] + adder_op_b[31:24] + carry_in[3]; + // additional 32 bit adder for PC after JAL(R) instruction + assign pc_after_jal = operand_c_i + 32'd4; + // averaging by right shifting of one bit logic [31:0] result_avg; @@ -539,18 +546,19 @@ module alu always_comb begin - shift_left = 1'b0; - shift_amt = operand_b_i; - result_o = 'x; - carry_o = 1'b0; - overflow_o = 1'b0; - flag_o = 1'b0; + shift_left = 1'b0; + shift_amt = operand_b_i; + result_o = 'x; + jump_target_o = 1'b0; + carry_o = 1'b0; + overflow_o = 1'b0; + flag_o = 1'b0; unique case (operator_i) // Standard Operations `ALU_ADD, `ALU_ADDC, `ALU_SUB: begin // Addition defined above - result_o = adder_result[31:0]; + result_o = adder_result; carry_o = carry_out[3]; overflow_o = (adder_op_a[31] ^ adder_result[31]) & (adder_op_b[31] ^ adder_result[31]); // ++ => - and -- => + end @@ -559,6 +567,13 @@ module alu `ALU_OR: result_o = operand_a_i | operand_b_i; `ALU_XOR: result_o = operand_a_i ^ operand_b_i; + // Jump Target Calculation + `ALU_JAL: + begin + result_o = pc_after_jal; + jump_target_o = adder_result; + end + // Shift Operations `ALU_MOVHI: begin diff --git a/controller.sv b/controller.sv index 12ea5e22..2019e6a3 100644 --- a/controller.sv +++ b/controller.sv @@ -53,6 +53,7 @@ module controller output logic extend_immediate_o, // Extend a 16 bit immediate to 32 bit output logic [1:0] alu_op_a_mux_sel_o, // Operator a is selected between reg value, PC or immediate output logic [1:0] alu_op_b_mux_sel_o, // Operator b is selected between reg value or immediate + output logic alu_op_c_mux_sel_o, // Operator c is selected between reg value or PC output logic alu_pc_mux_sel_o, // selects IF or ID PC for ALU computations output logic [3:0] immediate_mux_sel_o, @@ -134,6 +135,9 @@ module controller output logic [1:0] operand_b_fw_mux_sel_o, // regfile rb data selector form ID stage output logic [1:0] operand_c_fw_mux_sel_o, // regfile rc data selector form ID stage + // Jump target calcuation done detection + input logic jump_in_ex_i, // jump is being calculated in ALU + 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 @@ -175,7 +179,7 @@ module controller logic mfspr_stall; logic instr_ack_stall; logic load_stall; - logic jr_stall; + logic j_stall; logic set_npc; `ifdef BRANCH_PREDICTION @@ -207,6 +211,7 @@ module controller extend_immediate_o = 1'b0; alu_op_a_mux_sel_o = `OP_A_REGA_OR_FWD; alu_op_b_mux_sel_o = `OP_B_REGB_OR_FWD; + alu_op_c_mux_sel_o = `OP_C_REGC_OR_FWD; alu_pc_mux_sel_o = 1'b1; vector_mode_o = `VEC_MODE32; @@ -318,6 +323,7 @@ module controller pc_mux_sel_o = `PC_FROM_ALU; alu_op_a_mux_sel_o = `OP_A_CURRPC; alu_op_b_mux_sel_o = `OP_B_IMM; + alu_op_c_mux_sel_o = `OP_C_CURRPC; immediate_mux_sel_o = `IMM_UJ; alu_operator = `ALU_JAL; regfile_alu_we = 1'b1; @@ -330,6 +336,7 @@ module controller if (instr_rdata_i ==? `INSTR_JALR) begin pc_mux_sel_o = `PC_FROM_ALU; alu_op_b_mux_sel_o = `OP_B_IMM; + alu_op_c_mux_sel_o = `OP_C_CURRPC; immediate_mux_sel_o = `IMM_I; alu_operator = `ALU_JAL; regfile_alu_we = 1'b1; @@ -1141,13 +1148,13 @@ module controller endcase; // case (instr_rdata_i[6:0]) + // synopsys translate_off if (illegal_insn_o == 1'b1) begin - // synopsys translate_off - $display("%t: Illegal instruction:", $time, instr_rdata_i); - prettyPrintInstruction(instr_rdata_i); + $display("%t: Illegal instruction:", $time); + prettyPrintInstruction(instr_rdata_i, id_stage.current_pc_id_i); $stop; - // synopsys translate_on end + // synopsys translate_on // misaligned access was detected by the LSU if (data_misaligned_i == 1'b1) @@ -1196,7 +1203,7 @@ module controller mfspr_stall = 1'b0; mtspr_stall = 1'b0; load_stall = 1'b0; - jr_stall = 1'b0; + j_stall = 1'b0; deassert_we = 1'b0; @@ -1230,16 +1237,24 @@ module controller // Stall because of jr path // - Load results cannot directly be forwarded to PC // - Multiplication results cannot be forwarded to PC - if (((instr_rdata_i[6:0] == `OPCODE_JALR) || (instr_rdata_i[6:0] == `OPCODE_JAL)) && + if ((instr_rdata_i[6:0] == `OPCODE_JALR) && (((regfile_we_wb_i == 1'b1) && (reg_d_wb_is_reg_b_id == 1'b1) && (data_rvalid_i == 1'b1)) || ((regfile_we_ex_i == 1'b1) && (reg_d_ex_is_reg_b_id == 1'b1)) || ((regfile_alu_we_fw_i == 1'b1) && (reg_d_alu_is_reg_b_id == 1'b1) && (mult_is_running_ex_i == 1'b1))) ) begin - jr_stall = 1'b1; + j_stall = 1'b1; 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) ) + begin + j_stall = 1'b1; + //deassert_we = 1'b1; + end + `ifdef BRANCH_PREDICTION // Stall because of set_flag path if (wrong_branch_taken) @@ -1247,14 +1262,13 @@ module controller deassert_we = 1'b1; end `endif - */ end `ifdef BRANCH_PREDICTION - assign drop_instruction_o = wrong_branch_taken; + assign drop_instruction_o = wrong_branch_taken | j_stall; `else - assign drop_instruction_o = 1'b0; + assign drop_instruction_o = j_stall; `endif // Stall because of IF miss @@ -1285,8 +1299,8 @@ module controller // we unstall the if_stage if the debug unit wants to set a new // pc, so that the new value gets written into current_pc_if and is // used by the instr_core_interface - stall_if_o = (instr_ack_stall | mfspr_stall | mtspr_stall | load_stall | jr_stall | lsu_stall | misalign_stall | dbg_stall_i | (~pc_valid_i)); - stall_id_o = instr_ack_stall | mfspr_stall | mtspr_stall | load_stall | jr_stall | lsu_stall | misalign_stall | dbg_stall_i; + stall_if_o = (instr_ack_stall | mfspr_stall | mtspr_stall | load_stall | j_stall | lsu_stall | misalign_stall | dbg_stall_i | (~pc_valid_i)); + stall_id_o = instr_ack_stall | mfspr_stall | mtspr_stall | load_stall | j_stall | lsu_stall | misalign_stall | dbg_stall_i; stall_ex_o = instr_ack_stall | lsu_stall | dbg_stall_i; stall_wb_o = lsu_stall | dbg_stall_i; end @@ -1297,14 +1311,14 @@ module controller // RiscV register encoding: rs1 is [19:15], rs2 is [24:20], rd is [11:7] // // Or10n register encoding: ra is [20:16], rb is [15:11], rd is [25:21] // //////////////////////////////////////////////////////////////////////////////////////////// - assign reg_d_ex_is_reg_a_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_RS1]) && (rega_used == 1'b1); - assign reg_d_ex_is_reg_b_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_RS2]) && (regb_used == 1'b1); - assign reg_d_ex_is_reg_c_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_RD]) && (regc_used == 1'b1); - assign reg_d_wb_is_reg_a_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_RS1]) && (rega_used == 1'b1); - assign reg_d_wb_is_reg_b_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_RS2]) && (regb_used == 1'b1); - assign reg_d_wb_is_reg_c_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_RD]) && (regc_used == 1'b1); - assign reg_d_alu_is_reg_a_id = (regfile_alu_waddr_fw_i == instr_rdata_i[`REG_RS1]) && (rega_used == 1'b1); - assign reg_d_alu_is_reg_b_id = (regfile_alu_waddr_fw_i == instr_rdata_i[`REG_RS2]) && (regb_used == 1'b1); + assign reg_d_ex_is_reg_a_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_S1]) && (rega_used == 1'b1); + assign reg_d_ex_is_reg_b_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_S2]) && (regb_used == 1'b1); + assign reg_d_ex_is_reg_c_id = (regfile_waddr_ex_i == instr_rdata_i[`REG_D]) && (regc_used == 1'b1); + assign reg_d_wb_is_reg_a_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_S1]) && (rega_used == 1'b1); + assign reg_d_wb_is_reg_b_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_S2]) && (regb_used == 1'b1); + assign reg_d_wb_is_reg_c_id = (regfile_waddr_wb_i == instr_rdata_i[`REG_D]) && (regc_used == 1'b1); + assign reg_d_alu_is_reg_a_id = (regfile_alu_waddr_fw_i == instr_rdata_i[`REG_S1]) && (rega_used == 1'b1); + assign reg_d_alu_is_reg_b_id = (regfile_alu_waddr_fw_i == instr_rdata_i[`REG_S2]) && (regb_used == 1'b1); //assign reg_d_alu_is_reg_c_id = (regfile_alu_waddr_fw_i == instr_rdata_i[`REG_RD]) && (regc_used == 1'b1); always_comb diff --git a/ex_stage.sv b/ex_stage.sv index 52dd386a..c88c6121 100644 --- a/ex_stage.sv +++ b/ex_stage.sv @@ -119,7 +119,10 @@ module ex_stage output logic [4:0] regfile_alu_waddr_fw_o, output logic regfile_alu_we_fw_o, output logic [31:0] regfile_alu_wdata_fw_o, // forward to RF and ID/EX pipe, ALU & MUL - output logic [31:0] regfile_alu_wdata_fw_pc_o // forward to PC, no multiplication + 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 `ifdef TCDM_ADDR_PRECAL , @@ -134,6 +137,7 @@ module ex_stage // Internal output of the LU logic [31:0] alu_result; + logic [31:0] alu_jump_target_int; logic [31:0] alu_adder_lsu_int; // to LS unit @@ -182,6 +186,10 @@ module ex_stage assign data_addr_ex_o = (prepost_useincr_i == 1'b1) ? alu_adder_lsu_int : alu_operand_a_i; + // PC calculation for JAL/JALR + assign jump_target_o = alu_jump_target_int; + + //////////////////////////// // _ _ _ _ // // / \ | | | | | | // @@ -192,21 +200,22 @@ module ex_stage //////////////////////////// alu alu_i ( - .operator_i ( alu_operator_i ), - .operand_a_i ( alu_operand_a_i ), - .operand_b_i ( alu_operand_b_i ), - .carry_i ( alu_carry_i ), - .flag_i ( alu_flag_i ), + .operator_i ( alu_operator_i ), + .operand_a_i ( alu_operand_a_i ), + .operand_b_i ( alu_operand_b_i ), + .operand_c_i ( alu_operand_c_i ), + .carry_i ( alu_carry_i ), + .flag_i ( alu_flag_i ), - .vector_mode_i ( vector_mode_i ), - .cmp_mode_i ( alu_cmp_mode_i ), - .vec_ext_i ( alu_vec_ext_i ), + .vector_mode_i ( vector_mode_i ), + .cmp_mode_i ( alu_cmp_mode_i ), + .vec_ext_i ( alu_vec_ext_i ), - .adder_lsu_o ( alu_adder_lsu_int ), - .result_o ( alu_result ), - .overflow_o ( alu_overflow_int ), // Internal signal - .carry_o ( alu_carry_int ), // Internal signal - .flag_o ( alu_flag_o ) + .result_o ( alu_result ), + .jump_target_o ( alu_jump_target_int ), + .overflow_o ( alu_overflow_int ), // Internal signal + .carry_o ( alu_carry_int ), // Internal signal + .flag_o ( alu_flag_o ) ); diff --git a/id_stage.sv b/id_stage.sv index b7670031..dfd503e9 100644 --- a/id_stage.sv +++ b/id_stage.sv @@ -177,111 +177,113 @@ module id_stage // Immediate decoding and sign extension - logic [31:0] imm_i_type; - logic [31:0] imm_s_type; - logic [31:0] imm_sb_type; - logic [31:0] imm_u_type; - logic [31:0] imm_uj_type; + logic [31:0] imm_i_type; + logic [31:0] imm_s_type; + logic [31:0] imm_sb_type; + logic [31:0] imm_u_type; + logic [31:0] imm_uj_type; - logic [31:0] immediate_b; // contains the immediate for operand b + logic [31:0] immediate_b; // contains the immediate for operand b - logic [31:0] current_pc; // PC to be used in ALU (either IF or ID) + logic [31:0] current_pc; // PC to be used in ALU (either IF or ID) - logic exc_pc_sel; - logic [2:0] pc_mux_sel_int; // selects next PC in if stage - logic pc_from_immediate_mux_sel = 1'b0; // TODO: FIXME + logic exc_pc_sel; + logic [2:0] pc_mux_sel_int; // selects next PC in if stage + //logic pc_from_immediate_mux_sel = 1'b0; // TODO: FIXME (remove) - logic irq_present; + logic irq_present; // Signals running between controller and exception controller - logic jump_in_id; - logic jump_in_ex; // registered copy of jump_in_id - logic illegal_insn; - logic trap_insn; - logic pipe_flush; - logic pc_valid; - logic clear_isr_running; + logic jump_in_id; + logic jump_in_ex; // registered copy of jump_in_id + logic illegal_insn; + logic trap_insn; + logic pipe_flush; + logic pc_valid; + logic clear_isr_running; - logic [4:0] regfile_addr_ra_id; - logic [4:0] regfile_addr_rb_id; - logic [4:0] regfile_addr_rc_id; + logic [4:0] regfile_addr_ra_id; + logic [4:0] regfile_addr_rb_id; + logic [4:0] regfile_addr_rc_id; - logic [4:0] regfile_waddr_id; - logic [4:0] regfile_alu_waddr_id; - logic regfile_alu_we_id; + logic [4:0] regfile_waddr_id; + logic [4:0] regfile_alu_waddr_id; + logic regfile_alu_we_id; - logic [31:0] regfile_data_ra_id; - logic [31:0] regfile_data_rb_id; - logic [31:0] regfile_data_rc_id; + logic [31:0] regfile_data_ra_id; + logic [31:0] regfile_data_rb_id; + logic [31:0] regfile_data_rc_id; - logic imm_sign_ext_sel; + logic imm_sign_ext_sel; // ALU Control - logic [`ALU_OP_WIDTH-1:0] alu_operator; - logic [1:0] alu_op_a_mux_sel; - logic [1:0] alu_op_b_mux_sel; - logic scalar_replication; + logic [`ALU_OP_WIDTH-1:0] alu_operator; + logic [1:0] alu_op_a_mux_sel; + logic [1:0] alu_op_b_mux_sel; + logic alu_op_c_mux_sel; + logic scalar_replication; - logic [1:0] vector_mode; - logic [1:0] alu_cmp_mode; - logic [1:0] alu_vec_ext; + logic [1:0] vector_mode; + logic [1:0] alu_cmp_mode; + logic [1:0] alu_vec_ext; - logic alu_pc_mux_sel; - logic [3:0] immediate_mux_sel; + logic alu_pc_mux_sel; + logic [3:0] immediate_mux_sel; // Multiplier Control - logic mult_is_running; // output of the controller (1 if the opcode is a multiplication) - logic [1:0] mult_sel_subword; // Select a subword when doing multiplications - logic [1:0] mult_signed_mode; // Signed mode multiplication at the output of the controller, and before the pipe registers - logic mult_use_carry; // Enables carry in for the MAC - logic mult_mac_en; // Enables the use of the accumulator + logic mult_is_running; // output of the controller (1 if the opcode is a multiplication) + logic [1:0] mult_sel_subword; // Select a subword when doing multiplications + logic [1:0] mult_signed_mode; // Signed mode multiplication at the output of the controller, and before the pipe registers + logic mult_use_carry; // Enables carry in for the MAC + logic mult_mac_en; // Enables the use of the accumulator - logic eoc; // End of computation generated from the controller + logic eoc; // End of computation generated from the controller // Register Write Control - logic regfile_wdata_mux_sel; - logic regfile_we_id; - logic [1:0] regfile_alu_waddr_mux_sel; // TODO: FixMe -> 1bit + logic regfile_wdata_mux_sel; + logic regfile_we_id; + logic [1:0] regfile_alu_waddr_mux_sel; // TODO: FixMe -> 1bit // Special-Purpose Register Write Control - logic sp_we_id; + logic sp_we_id; // Data Memory Control - logic data_we_id; - logic [1:0] data_type_id; - logic data_sign_ext_id; - logic [1:0] data_reg_offset_id; - logic data_req_id; + logic data_we_id; + logic [1:0] data_type_id; + logic data_sign_ext_id; + logic [1:0] data_reg_offset_id; + logic data_req_id; // hwloop signals - logic [1:0] hwloop_regid; - logic [2:0] hwloop_we; - logic hwloop_wb_mux_sel; - logic [1:0] hwloop_cnt_mux_sel; - logic [31:0] hwloop_cnt; - logic hwloop_jump; - logic hwloop_enable; + logic [1:0] hwloop_regid; + logic [2:0] hwloop_we; + logic hwloop_wb_mux_sel; + logic [1:0] hwloop_cnt_mux_sel; + logic [31:0] hwloop_cnt; + logic hwloop_jump; + logic hwloop_enable; // Supervision Register - logic set_flag; - logic set_carry; - logic set_overflow; + logic set_flag; + logic set_carry; + logic set_overflow; - logic prepost_useincr; + logic prepost_useincr; // Forwarding - logic [1:0] operand_a_fw_mux_sel; - logic [1:0] operand_b_fw_mux_sel; - logic [1:0] operand_c_fw_mux_sel; - logic [31:0] operand_a_fw_id; - logic [31:0] operand_b_fw_id; + logic [1:0] operand_a_fw_mux_sel; + logic [1:0] operand_b_fw_mux_sel; + logic [1:0] operand_c_fw_mux_sel; + logic [31:0] operand_a_fw_id; + logic [31:0] operand_b_fw_id; - logic [31:0] alu_operand_a; - logic [31:0] alu_operand_b; - logic [31:0] alu_operand_c; - logic [31:0] operand_b; // before going through the scalar replication mux - logic [31:0] operand_b_vec; // scalar replication of operand_b for 8 and 16 bit + logic [31:0] alu_operand_a; + logic [31:0] alu_operand_b; + logic [31:0] alu_operand_c; + logic [31:0] operand_b; // before going through the scalar replication mux + logic [31:0] operand_b_vec; // scalar replication of operand_b for 8 and 16 bit + logic [31:0] operand_c; // TODO: FIXME temporary assignments while not everything is implemented (e.g. exceptions) @@ -301,12 +303,13 @@ module id_stage instr_rdata_i[20], instr_rdata_i[30:21], 1'b0 }; // source registers - assign regfile_addr_ra_id = instr_rdata_i[`REG_RS1]; - assign regfile_addr_rb_id = instr_rdata_i[`REG_RS2]; + assign regfile_addr_ra_id = instr_rdata_i[`REG_S1]; + assign regfile_addr_rb_id = instr_rdata_i[`REG_S2]; //assign regfile_addr_rc_id = instr_rdata_i[25:21]; + assign regfile_addr_rc_id = 32'd0; // destination registers - assign regfile_waddr_id = instr_rdata_i[`REG_RD]; + assign regfile_waddr_id = instr_rdata_i[`REG_D]; //assign alu_vec_ext = instr_rdata_i[9:8]; @@ -333,14 +336,14 @@ module id_stage /////////////////////////////////////////////////////////////////////////////////////// // PC offset for `PC_FROM_IMM PC mux - //assign pc_from_immediate_o = imm_uj_type; - always_comb - begin : pc_from_immediate_mux - case (pc_from_immediate_mux_sel) - 1'b0: pc_from_immediate_o = imm_uj_type; // JAL - 1'b1: pc_from_immediate_o = imm_i_type; // JALR - endcase // case (pc_from_immediate_mux_sel) - end + //assign pc_from_immediate_o = imm_uj_type; // riscv no longer used + //always_comb + //begin : pc_from_immediate_mux + // case (pc_from_immediate_mux_sel) + // 1'b0: pc_from_immediate_o = imm_uj_type; // JAL + // 1'b1: pc_from_immediate_o = imm_i_type; // JALR + // endcase // case (pc_from_immediate_mux_sel) + //end // PC Mux always_comb @@ -472,14 +475,23 @@ module id_stage // |_| // ////////////////////////////////////////////////////// + // ALU OP C Mux + always_comb + begin : alu_operand_c_mux + case (alu_op_c_mux_sel) + `OP_C_CURRPC: operand_c = current_pc; + default: operand_c = regfile_data_rc_id; + endcase // case (alu_op_c_mux_sel) + end + // Operand c forwarding mux always_comb begin : operand_c_fw_mux case (operand_c_fw_mux_sel) `SEL_FW_EX: alu_operand_c = regfile_alu_wdata_fw_i; `SEL_FW_WB: alu_operand_c = regfile_wdata_wb_i; - `SEL_REGFILE: alu_operand_c = regfile_data_rc_id; - default: alu_operand_c = regfile_data_rc_id; + `SEL_REGFILE: alu_operand_c = operand_c; + default: alu_operand_c = operand_c; endcase; // case (operand_b_fw_mux_sel) end @@ -551,6 +563,7 @@ module id_stage .extend_immediate_o ( imm_sign_ext_sel ), .alu_op_a_mux_sel_o ( alu_op_a_mux_sel ), .alu_op_b_mux_sel_o ( alu_op_b_mux_sel ), + .alu_op_c_mux_sel_o ( alu_op_c_mux_sel ), .alu_pc_mux_sel_o ( alu_pc_mux_sel ), .immediate_mux_sel_o ( immediate_mux_sel ), @@ -638,11 +651,13 @@ module id_stage .operand_b_fw_mux_sel_o ( operand_b_fw_mux_sel ), .operand_c_fw_mux_sel_o ( operand_c_fw_mux_sel ), + .jump_in_ex_i ( jump_in_ex ), + // branch prediction - .drop_instruction_o ( drop_instruction_o ), + .drop_instruction_o ( drop_instruction_o ), `ifdef BRANCH_PREDICTION - .wrong_branch_taken_o ( wrong_branch_taken_o ), - .take_branch_o ( take_branch_o ), + .wrong_branch_taken_o ( wrong_branch_taken_o ), + .take_branch_o ( take_branch_o ), `endif // Stall signals .stall_if_o ( stall_if_o ), diff --git a/if_stage.sv b/if_stage.sv index 583c52d3..6ff9cd67 100644 --- a/if_stage.sv +++ b/if_stage.sv @@ -52,7 +52,8 @@ module if_stage input logic force_nop_i, // insert a NOP in the pipe 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_immediate_i, // pc from immediate + 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_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 @@ -93,8 +94,8 @@ 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_not_taken = current_pc_if_o + 32'd4; + //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 always_comb @@ -103,7 +104,8 @@ module if_stage `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_IMM: begin next_pc = branch_taken; end // PC is taken from current PC in id + the immediate displacement + `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_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 5662584f..3a964cf7 100644 --- a/include/defines.sv +++ b/include/defines.sv @@ -164,13 +164,13 @@ */ // Source/Destination register instruction index -`define REG_RS1 19:15 -`define REG_RS2 24:20 -`define REG_RD 11:07 +`define REG_S1 19:15 +`define REG_S2 24:20 +`define REG_D 11:07 // synopsis translate off -function void prettyPrintInstruction(input [31:0] instr); +function void prettyPrintInstruction(input [31:0] instr, input [31:0] pc); string opcode; begin unique case (instr[6:0]) @@ -188,10 +188,10 @@ function void prettyPrintInstruction(input [31:0] instr); default: opcode = "Unknown"; endcase // unique case (instr[6:0]) - $display("%t: %s Instruction 0x%h.", $time, opcode, instr[31:0]); + $display("%t: %s Instruction 0x%h at 0x%h.", $time, opcode, instr[31:0], pc[31:0]); $display("%t: | fct7 | rs2 | rs1 | | rd | opc. |", $time); - $display("%t: 0b %b %b %b %b %b %b", $time, instr[31:25], instr[`REG_RS2], - instr[`REG_RS1], instr[14:12], instr[`REG_RD], instr[6:0]); + $display("%t: 0b %b %b %b %b %b %b", $time, instr[31:25], instr[`REG_S2], + instr[`REG_S1], instr[14:12], instr[`REG_D], instr[6:0]); $display(); end endfunction // prettyPrintInstruction @@ -268,6 +268,9 @@ endfunction // prettyPrintInstruction `define ALU_FL1 6'b11_0011 `define ALU_CLB 6'b11_0001 +// next PC and PC+4 computation for JAL/JALR in RiscV +`define ALU_JAL 6'b11_1000 + // Vector Mode `define VEC_MODE32 2'b00 @@ -321,20 +324,24 @@ endfunction // prettyPrintInstruction `define SR_DSX 5'd13 // forwarding operand mux -`define SEL_REGFILE 2'b00 -`define SEL_FW_EX 2'b01 -`define SEL_FW_WB 2'b10 +`define SEL_REGFILE 2'b00 +`define SEL_FW_EX 2'b01 +`define SEL_FW_WB 2'b10 // operand a selection -`define OP_A_REGA_OR_FWD 2'b00 -`define OP_A_CURRPC 2'b10 -`define OP_A_IMM16 2'b11 -`define OP_A_ZERO 2'b11 +`define OP_A_REGA_OR_FWD 2'b00 +`define OP_A_CURRPC 2'b10 +`define OP_A_IMM16 2'b11 +`define OP_A_ZERO 2'b11 // operand b selection -`define OP_B_REGB_OR_FWD 2'b00 -`define OP_B_REGC_OR_FWD 2'b01 -`define OP_B_IMM 2'b10 +`define OP_B_REGB_OR_FWD 2'b00 +`define OP_B_REGC_OR_FWD 2'b01 +`define OP_B_IMM 2'b10 + +// operand c selection +`define OP_C_REGC_OR_FWD 1'b0 +`define OP_C_CURRPC 1'b1 // immediate selection // - `define IMM_5N11 4'b0000 @@ -357,7 +364,8 @@ endfunction // prettyPrintInstruction `define INCR_PC 3'b000 `define NO_INCR 3'b001 `define PC_FROM_REGFILE 3'b010 -`define PC_FROM_IMM 3'b011 +//`define PC_FROM_IMM 3'b011 Replaced in RiscV +`define PC_FROM_ALU 3'b011 `define PC_EXCEPTION 3'b100 `define EXC_PC_REG 3'b101 `define HWLOOP_ADDR 3'b110 diff --git a/instr_core_interface.sv b/instr_core_interface.sv index 2306d22c..71385234 100644 --- a/instr_core_interface.sv +++ b/instr_core_interface.sv @@ -7,8 +7,8 @@ // Additional contributions by: // // // // // -// Create Date: 06/08/2014 // -// Design Name: Instruction Fetch interface // +// Create Date: 06/08/2014 // +// Design Name: Instruction Fetch interface // // Module Name: instr_core_interface.sv // // Project Name: OR10N // // Language: SystemVerilog // @@ -31,20 +31,20 @@ module instr_core_interface ( input logic clk, input logic rst_n, - - + + input logic req_i, input logic [31:0] addr_i, output logic ack_o, output logic [31:0] rdata_o, - - + + output logic instr_req_o, output logic [31:0] instr_addr_o, input logic instr_gnt_i, input logic instr_r_valid_i, input logic [31:0] instr_r_rdata_i, - + input logic stall_if_i, input logic drop_request_i @@ -58,7 +58,7 @@ module instr_core_interface logic wait_gnt; logic [31:0] addr_Q; - + always_ff @(posedge clk, negedge rst_n) begin if(rst_n == 1'b0) @@ -70,19 +70,19 @@ module instr_core_interface else begin CS <= NS; - + if(wait_gnt) addr_Q <= addr_i; - + if(save_rdata) rdata_Q <= instr_r_rdata_i; end end - - + + always_comb begin - + instr_req_o = 1'b0; ack_o = 1'b0; save_rdata = 1'b0; @@ -90,16 +90,16 @@ module instr_core_interface instr_addr_o = addr_i; wait_gnt = 1'b0; - + case(CS) - - IDLE : + + IDLE : begin instr_req_o = req_i; ack_o = 1'b0; rdata_o = rdata_Q; - - + + if(req_i) begin if(instr_gnt_i) //~> granted request @@ -115,10 +115,10 @@ module instr_core_interface end end // case: IDLE - + WAIT_GNT : begin - + instr_addr_o = addr_Q; instr_req_o = 1'b1; @@ -131,17 +131,17 @@ module instr_core_interface // else NS = WAIT_GNT; end - + end // case: WAIT_GNT - - - PENDING : + + + PENDING : begin if(instr_r_valid_i) begin save_rdata = 1'b1; - + ack_o = 1'b1; if(stall_if_i) begin @@ -165,7 +165,7 @@ module instr_core_interface end else NS = IDLE; - end + end end else begin @@ -174,23 +174,23 @@ module instr_core_interface ack_o = 1'b0; end end // case: PENDING - - WAIT_RVALID : + + WAIT_RVALID : begin - - + + if(instr_r_valid_i) begin - + ack_o = 1'b1; save_rdata = 1'b1; - - + + if(stall_if_i) begin instr_req_o = 1'b0; NS = WAIT_IF_STALL; - + end else begin @@ -205,7 +205,7 @@ module instr_core_interface else NS = IDLE; end - + end else begin @@ -214,14 +214,14 @@ module instr_core_interface instr_req_o = 1'b0; end end // case: WAIT_RVALID - - - + + + WAIT_IF_STALL : begin ack_o = 1'b1; rdata_o = rdata_Q; - + if(stall_if_i) begin instr_req_o = 1'b0; @@ -229,7 +229,7 @@ module instr_core_interface end else begin - + instr_req_o = req_i; if(req_i) if(instr_gnt_i) @@ -241,11 +241,11 @@ module instr_core_interface else NS = IDLE; end - - - + + + end // case: WAIT_IF_STALL - + ABORT: begin ack_o = 1'b1; @@ -264,17 +264,17 @@ module instr_core_interface NS = IDLE; end end // case: ABORT - - - default : + + + default : begin NS = IDLE; instr_req_o = 1'b0; end - + endcase - + end - + endmodule \ No newline at end of file diff --git a/riscv_core.sv b/riscv_core.sv index 64087e80..ddab1fc5 100644 --- a/riscv_core.sv +++ b/riscv_core.sv @@ -89,7 +89,10 @@ 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 Jump + + // Jump handling + logic [31:0] jump_target; // Stalling logic stall_if; // Stall instruction fetch(deassert request) @@ -278,7 +281,8 @@ 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 .pc_mux_boot_i ( pc_mux_boot ), // load boot address as PC @@ -362,7 +366,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 ), @@ -563,6 +567,9 @@ module riscv_core .sp_we_wb_o ( sp_we_wb ), .eoc_o ( eoc_wb ), + // Jump target address + .jump_target_o ( jump_target ), + // To ID stage: Forwarding signals .regfile_alu_waddr_fw_o ( regfile_alu_waddr_fw ), .regfile_alu_we_fw_o ( regfile_alu_we_fw ),