diff --git a/alu.sv b/alu.sv index c775d917..becaaf65 100644 --- a/alu.sv +++ b/alu.sv @@ -36,7 +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 [31:0] operand_c_i, input logic carry_i, input logic flag_i, @@ -45,15 +45,12 @@ 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 @@ -144,9 +141,6 @@ 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; @@ -549,7 +543,6 @@ module alu 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; @@ -567,13 +560,6 @@ 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 fd1b4851..e8e15ff9 100644 --- a/controller.sv +++ b/controller.sv @@ -40,6 +40,8 @@ module controller output logic eoc_o, // End of computation: triggered by a special instruction output logic core_busy_o, // Core is busy processing instructions + output logic force_nop_o, + input logic [31:0] instr_rdata_i, // Instruction read from instr memory/cache: (sampled in the if stage) output logic instr_req_o, // Fetch instruction Request: input logic instr_gnt_i, // grant from icache @@ -103,7 +105,7 @@ module controller input logic irq_present_i, // there is an IRQ, so if we are sleeping we should wake up now // Exception Controller Signals - output logic jump_in_id_o, // jump instruction in ID stage + //output logic jump_in_id_o, // jump instruction in ID stage output logic illegal_insn_o, // illegal instruction encountered output logic trap_insn_o, // trap instruction encountered output logic pipe_flush_o, // pipe flush requested by controller @@ -136,16 +138,9 @@ module controller 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 + input logic [1:0] jump_in_ex_i, // jump is being calculated in ALU + output logic [1:0] jump_in_id_o, // 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 - output logic take_branch_o, // 1 if branch should be taken -`endif output logic stall_if_o, // Stall IF stage (deassert requests) output logic stall_id_o, // Stall ID stage (and instr and data memory interface) ( ID_STAGE ) output logic stall_ex_o, // Stall ex stage ( EX_STAGE ) @@ -182,7 +177,7 @@ module controller logic mfspr_stall; logic instr_ack_stall; logic load_stall; - logic j_stall; + logic jr_stall; logic set_npc; `ifdef BRANCH_PREDICTION @@ -207,8 +202,9 @@ module controller instr_req_o = 1'b1; - pc_mux_sel_o = `INCR_PC; + pc_mux_sel_o = `PC_INCR; pc_mux_boot_o = 1'b0; + jump_in_id_o = 2'b00; alu_operator = `ALU_NOP; extend_immediate_o = 1'b0; @@ -287,7 +283,7 @@ module controller // we begin execution when either fetch_enable is high or an // interrupt has arrived instr_req_o = fetch_enable_i || irq_present_i; - pc_mux_sel_o = `NO_INCR; + pc_mux_sel_o = `PC_NO_INCR; if (fetch_enable_i || irq_present_i) begin @@ -323,13 +319,17 @@ module controller `OPCODE_JAL: begin // Jump and Link if (instr_rdata_i ==? `INSTR_JAL) begin - pc_mux_sel_o = `PC_FROM_ALU; + // Insert bubbles + pc_mux_sel_o = `PC_NO_INCR; + jump_in_id_o = 2'b01; + // Calculate and store PC+4 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; + immediate_mux_sel_o = `IMM_HEX4; + alu_operator = `ALU_ADD; regfile_alu_we = 1'b1; + // Calculate jump target (= PC + UJ imm) + alu_op_c_mux_sel_o = `OP_C_JT; end else begin illegal_insn_o = 1'b1; end @@ -337,21 +337,29 @@ module controller `OPCODE_JALR: begin // Jump and Link Register if (instr_rdata_i ==? `INSTR_JALR) begin - pc_mux_sel_o = `PC_FROM_ALU; + // Insert bubbles + pc_mux_sel_o = `PC_NO_INCR; + jump_in_id_o = 2'b01; + // Calculate and store PC+4 + 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_I; - alu_operator = `ALU_JAL; + immediate_mux_sel_o = `IMM_HEX4; + alu_operator = `ALU_ADD; regfile_alu_we = 1'b1; + // Calculate jump target (= RS1 + I imm) rega_used = 1'b1; + alu_op_c_mux_sel_o = `OP_C_JT; end else begin illegal_insn_o = 1'b1; end end `OPCODE_BRANCH: begin // Branch - rega_used = 1'b1; - regb_used = 1'b1; + pc_mux_sel_o = `PC_NO_INCR; + jump_in_id_o = 2'b10; + alu_op_c_mux_sel_o = `OP_C_JT; + rega_used = 1'b1; + regb_used = 1'b1; unique case (instr_rdata_i) inside `INSTR_BEQ: alu_operator = `ALU_EQ; @@ -366,32 +374,15 @@ module controller end endcase // case (instr_rdata_i) - if (branch_taken_i == 1'b1) begin + /*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*/ end /* - `OPCODE_JR: - begin // Jump Register - pc_mux_sel_o = `PC_FROM_REGFILE; - regb_used = 1'b1; - end - - `OPCODE_JALR: begin // Jump and Link Register - pc_mux_sel_o = `PC_FROM_REGFILE; - alu_op_a_mux_sel_o = `OP_A_CURRPC; - alu_op_b_mux_sel_o = `OP_B_IMM; - immediate_mux_sel_o = `IMM_HEX4; - alu_operator = `ALU_ADD; - regfile_alu_waddr_mux_sel_o = 2'b10; // select r9 to write back return address - regfile_alu_we = 1'b1; - regb_used = 1'b1; - end - `ifndef BRANCH_PREDICTION `OPCODE_BNF: begin // Branch if No Flag @@ -448,7 +439,7 @@ module controller `OPCODE_EOC: begin // End of Computation (Custom Instruction 1) eoc_o = 1'b1; - pc_mux_sel_o = `NO_INCR; + pc_mux_sel_o = `PC_NO_INCR; end `OPCODE_RFE: @@ -619,9 +610,9 @@ module controller data_sign_extension_o = instr_rdata_i[1]; end - */ + ////////////////////////// // _ _ _ _ // // / \ | | | | | | // @@ -671,19 +662,7 @@ module controller endcase // unique case (instr_rdata_i) end // case: `OPCODE_OPIMM - /* - `OPCODE_ADDIC: begin // Add Immediate and Carry - alu_op_b_mux_sel_o = `OP_B_IMM; - immediate_mux_sel_o = `IMM_16; - alu_operator = `ALU_ADDC; - regfile_alu_we = 1'b1; - set_overflow = 1'b1; - set_carry = 1'b1; - rega_used = 1'b1; - end - */ - - `OPCODE_OP: begin // ALU register-register operation + `OPCODE_OP: begin // Register-Register ALU operation regfile_alu_we = 1'b1; rega_used = 1'b1; regb_used = 1'b1; @@ -712,24 +691,6 @@ module controller /* - `OPCODE_MOVHI: - begin - if (instr_rdata_i[16] == 1'b0) - begin // Move Immediate High - extend_immediate_o = 1'b1; - alu_op_a_mux_sel_o = `OP_A_IMM16; - alu_operator = `ALU_MOVHI; - regfile_alu_we = 1'b1; - end - else - begin - // synopsys translate_off - $display("%t: Illegal l.movhi received.", $time); - // synopsys translate_on - illegal_insn_o = 1'b1; - end - end - `OPCODE_MULI: begin // Multiply Immediate Signed alu_op_b_mux_sel_o = `OP_B_IMM; immediate_mux_sel_o = `IMM_16; @@ -911,37 +872,6 @@ module controller endcase end - `OPCODE_SFI: begin // Set Flag Immediate-Instructions - if (instr_rdata_i[25] == 1'b0) begin - alu_op_b_mux_sel_o = `OP_B_IMM; - immediate_mux_sel_o = `IMM_16; - alu_operator = {2'b10, instr_rdata_i[24:21]}; - set_flag = 1'b1; - rega_used = 1'b1; - end - else begin - // synopsys translate_off - $display("%t: Illegal Set Flag Immediate instruction received.", $time); - // synopsys translate_on - illegal_insn_o = 1'b1; - end - end - - `OPCODE_SF: begin // Set Flag Instruction - if (instr_rdata_i[25] == 1'b0) begin - alu_operator = {2'b10, instr_rdata_i[24:21]}; - set_flag = 1'b1; - rega_used = 1'b1; - regb_used = 1'b1; - end - else begin - // synopsys translate_off - $display("%t: Illegal Set Flag instruction received.", $time); - // synopsys translate_on - illegal_insn_o = 1'b1; - end - end - `OPCODE_VEC: begin // vectorial alu operations rega_used = 1'b1; regfile_alu_we = 1'b1; @@ -1168,11 +1098,10 @@ module controller */ default: begin - illegal_insn_o = 1'b1; // TODO: Replace with exception - pc_mux_sel_o = `NO_INCR; + illegal_insn_o = 1'b1; + pc_mux_sel_o = `PC_NO_INCR; end - endcase; // case (instr_rdata_i[6:0]) // synopsys translate_off @@ -1203,7 +1132,7 @@ module controller end if ( set_npc == 1'b1 ) - pc_mux_sel_o = `NO_INCR; + pc_mux_sel_o = `PC_NO_INCR; // hwloop detected, jump to start address! if (hwloop_jump_i == 1'b1) @@ -1218,184 +1147,153 @@ module controller ctrl_fsm_ns = IDLE; end endcase - end + end - assign core_busy_o = (ctrl_fsm_cs != IDLE); + assign core_busy_o = (ctrl_fsm_cs != IDLE); - //////////////////////////////////////////////////////////////////////////////////////////// - // Generate Stall Signals! // - //////////////////////////////////////////////////////////////////////////////////////////// - always_comb - begin - mfspr_stall = 1'b0; - mtspr_stall = 1'b0; - load_stall = 1'b0; - j_stall = 1'b0; - deassert_we = 1'b0; + //////////////////////////////////////////////////////////////////////////////////////////// + // Generate Stall Signals! // + //////////////////////////////////////////////////////////////////////////////////////////// + always_comb + begin + mfspr_stall = 1'b0; + mtspr_stall = 1'b0; + load_stall = 1'b0; + jr_stall = 1'b0; + deassert_we = 1'b0; + + /* + // Stall because of l.mfspr with dependency + if ((regfile_wdata_mux_sel_ex_i == 1'b0) && (regfile_we_ex_i == 1'b1) && + ((reg_d_ex_is_reg_a_id == 1'b1) || (reg_d_ex_is_reg_b_id == 1'b1) || (reg_d_ex_is_reg_c_id == 1'b1)) ) + begin + deassert_we = 1'b1; + mfspr_stall = 1'b1; + end + + // Stall because of l.mtspr (always...) + // mtspr in ex stage, normal instruction in id stage which can change an spr reg + if ((sp_we_ex_i == 1'b1) && (instr_rdata_i[31:26] != `OPCODE_MTSPR)) + begin + deassert_we = 1'b1; + mtspr_stall = 1'b1; + end + */ + + // Stall because of load operation + if ((data_req_ex_i == 1'b1) && (regfile_we_ex_i == 1'b1) && + ((reg_d_ex_is_reg_a_id == 1'b1) || (reg_d_ex_is_reg_b_id == 1'b1) || (reg_d_ex_is_reg_c_id == 1'b1)) ) + begin + deassert_we = 1'b1; + load_stall = 1'b1; + end + + // TODO: check JALR/JR + // 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) && + (((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; + deassert_we = 1'b1; + end + end + + // Stall because of IF miss + assign instr_ack_stall = ~instr_ack_i; + + // Stall if TCDM contention has been detected + assign lsu_stall = ~data_ack_i; + + assign misalign_stall = data_misaligned_i; + + // deassert we signals (in case of stalls) + assign alu_operator_o = (deassert_we) ? `ALU_NOP : alu_operator; + assign mult_is_running_o = (deassert_we) ? 1'b0 : mult_is_running; + assign regfile_we_o = (deassert_we) ? 1'b0 : regfile_we; + assign regfile_alu_we_o = (deassert_we) ? 1'b0 : regfile_alu_we; + assign data_we_o = (deassert_we) ? 1'b0 : data_we; + assign data_req_o = (deassert_we) ? 1'b0 : data_req; + assign set_flag_o = (deassert_we) ? 1'b0 : set_flag; + assign set_overflow_o = (deassert_we) ? 1'b0 : set_overflow; + assign set_carry_o = (deassert_we) ? 1'b0 : set_carry; - /* - // Stall because of l.mfspr with dependency - if ((regfile_wdata_mux_sel_ex_i == 1'b0) && (regfile_we_ex_i == 1'b1) && - ((reg_d_ex_is_reg_a_id == 1'b1) || (reg_d_ex_is_reg_b_id == 1'b1) || (reg_d_ex_is_reg_c_id == 1'b1)) ) - begin - deassert_we = 1'b1; - mfspr_stall = 1'b1; - end + //////////////////////////////////////////////////////////////////////////////////////////// + // Jump and Branch handling // + //////////////////////////////////////////////////////////////////////////////////////////// - // Stall because of l.mtspr (always...) - // mtspr in ex stage, normal instruction in id stage which can change an spr reg - if ((sp_we_ex_i == 1'b1) && (instr_rdata_i[31:26] != `OPCODE_MTSPR)) - begin - deassert_we = 1'b1; - mtspr_stall = 1'b1; - end - */ + assign force_nop_o = (jump_in_id_o != 2'b00 || jump_in_ex_i != 2'b00)? 1'b1 : 1'b0; + assign drop_instruction_o = 1'b0; - // Stall because of load operation - if ((data_req_ex_i == 1'b1) && (regfile_we_ex_i == 1'b1) && - ((reg_d_ex_is_reg_a_id == 1'b1) || (reg_d_ex_is_reg_b_id == 1'b1) || (reg_d_ex_is_reg_c_id == 1'b1)) ) - begin - deassert_we = 1'b1; - load_stall = 1'b1; - end - - // TODO: check JALR/JR - // 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) && - (((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 - j_stall = 1'b1; - deassert_we = 1'b1; - end - - // 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; - end - -`ifdef BRANCH_PREDICTION - // Stall because of set_flag path - if (wrong_branch_taken) - begin - deassert_we = 1'b1; - end -`endif - - end - - // NOTE: current_pc_id_i is wrong after drop instruction ! -`ifdef BRANCH_PREDICTION - assign drop_instruction_o = wrong_branch_taken | j_stall; -`else - assign drop_instruction_o = j_stall; -`endif - - // Stall because of IF miss - assign instr_ack_stall = ~instr_ack_i; - - // Stall if TCDM contention has been detected - assign lsu_stall = ~data_ack_i; - - assign misalign_stall = data_misaligned_i; - - // deassert we signals (in case of stalls) - assign alu_operator_o = (deassert_we) ? `ALU_NOP : alu_operator; - assign mult_is_running_o = (deassert_we) ? 1'b0 : mult_is_running; - assign regfile_we_o = (deassert_we) ? 1'b0 : regfile_we; - assign regfile_alu_we_o = (deassert_we) ? 1'b0 : regfile_alu_we; - assign data_we_o = (deassert_we) ? 1'b0 : data_we; - assign data_req_o = (deassert_we) ? 1'b0 : data_req; - assign set_flag_o = (deassert_we) ? 1'b0 : set_flag; - assign set_overflow_o = (deassert_we) ? 1'b0 : set_overflow; - assign set_carry_o = (deassert_we) ? 1'b0 : set_carry; + //////////////////////////////////////////////////////////////////////////////////////////// + // Freeze Unit. This unit controls the pipeline stages // + //////////////////////////////////////////////////////////////////////////////////////////// + always_comb + begin + // 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_ex_o = instr_ack_stall | lsu_stall | dbg_stall_i; + stall_wb_o = lsu_stall | dbg_stall_i; + end - //////////////////////////////////////////////////////////////////////////////////////////// - // Freeze Unit. This unit controls the pipeline stages // - //////////////////////////////////////////////////////////////////////////////////////////// - always_comb - begin - // 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 | 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 + //////////////////////////////////////////////////////////////////////////////////////////// + // Forwarding control unit. (Forwarding from wb and ex stage to id stage) // + // 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_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 + begin + // default assignements + operand_a_fw_mux_sel_o = `SEL_REGFILE; + operand_b_fw_mux_sel_o = `SEL_REGFILE; + operand_c_fw_mux_sel_o = `SEL_REGFILE; - //////////////////////////////////////////////////////////////////////////////////////////// - // Forwarding control unit. (Forwarding from wb and ex stage to id stage) // - // 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_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); + // Forwarding WB -> ID + if (regfile_we_wb_i == 1'b1) + begin + if (reg_d_wb_is_reg_a_id == 1'b1) + operand_a_fw_mux_sel_o = `SEL_FW_WB; + if (reg_d_wb_is_reg_b_id == 1'b1) + operand_b_fw_mux_sel_o = `SEL_FW_WB; + if (reg_d_wb_is_reg_c_id == 1'b1) + operand_c_fw_mux_sel_o = `SEL_FW_WB; + end - always_comb - begin - // default assignements - operand_a_fw_mux_sel_o = `SEL_REGFILE; - operand_b_fw_mux_sel_o = `SEL_REGFILE; - operand_c_fw_mux_sel_o = `SEL_REGFILE; - - // Forwarding WB -> ID - if (regfile_we_wb_i == 1'b1) - begin - if (reg_d_wb_is_reg_a_id == 1'b1) - operand_a_fw_mux_sel_o = `SEL_FW_WB; - if (reg_d_wb_is_reg_b_id == 1'b1) - operand_b_fw_mux_sel_o = `SEL_FW_WB; - if (reg_d_wb_is_reg_c_id == 1'b1) - operand_c_fw_mux_sel_o = `SEL_FW_WB; - end - - // Forwarding EX -> ID - if (regfile_alu_we_fw_i == 1'b1) - begin - if (reg_d_alu_is_reg_a_id == 1'b1) - operand_a_fw_mux_sel_o = `SEL_FW_EX; - if (reg_d_alu_is_reg_b_id == 1'b1) - operand_b_fw_mux_sel_o = `SEL_FW_EX; - if (reg_d_alu_is_reg_c_id == 1'b1) - operand_c_fw_mux_sel_o = `SEL_FW_EX; - end - - if (data_misaligned_i == 1'b1) - begin - operand_a_fw_mux_sel_o = `SEL_FW_EX; - operand_b_fw_mux_sel_o = `SEL_REGFILE; - end - end - - // check if jump or branch in pipeline - /* - assign jump_in_id_o = ((instr_rdata_i[31:26] == `OPCODE_BF) || (instr_rdata_i[31:26] == `OPCODE_BNF) || - (instr_rdata_i[31:26] == `OPCODE_J) || (instr_rdata_i[31:26] == `OPCODE_JR) || - (instr_rdata_i[31:26] == `OPCODE_JAL) || (instr_rdata_i[31:26] == `OPCODE_JALR) || - (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) || - (instr_rdata_i[6:0] == `OPCODE_BRANCH)); + // Forwarding EX -> ID + if (regfile_alu_we_fw_i == 1'b1) + begin + if (reg_d_alu_is_reg_a_id == 1'b1) + operand_a_fw_mux_sel_o = `SEL_FW_EX; + if (reg_d_alu_is_reg_b_id == 1'b1) + operand_b_fw_mux_sel_o = `SEL_FW_EX; + if (reg_d_alu_is_reg_c_id == 1'b1) + operand_c_fw_mux_sel_o = `SEL_FW_EX; + end + if (data_misaligned_i == 1'b1) + begin + operand_a_fw_mux_sel_o = `SEL_FW_EX; + operand_b_fw_mux_sel_o = `SEL_REGFILE; + end + end // update registers always_ff @(posedge clk , negedge rst_n) @@ -1426,20 +1324,4 @@ module controller end end -`ifdef BRANCH_PREDICTION - // Wrong branch was taken! - always_ff @(posedge clk , negedge rst_n) - begin : WRONG_BRANCH - if ( rst_n == 1'b0 ) - begin - wrong_branch_taken <= 1'b0; - end - else - begin - if (stall_if_o == 1'b0) - wrong_branch_taken <= wrong_branch_taken_o; - end - end -`endif - endmodule // controller diff --git a/ex_stage.sv b/ex_stage.sv index 265f2edb..f05d5274 100644 --- a/ex_stage.sv +++ b/ex_stage.sv @@ -121,11 +121,13 @@ module ex_stage 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 - // JAL/JALR jumpt target calculation (to IF) - output logic [31:0] jump_target_o, + // From ID: Jump and branch indication + input logic [1:0] jump_in_id_i, - // Branch decision (to controller) - output logic branch_taken_o + // To IF: Jump and branch target and decision + output logic [31:0] jump_target_o, + output logic [1:0] jump_in_ex_o, + output logic branch_decision_o `ifdef TCDM_ADDR_PRECAL , @@ -140,7 +142,6 @@ 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 @@ -183,17 +184,17 @@ module ex_stage // NOTE a dedicated adder, no carry is considered , just op_a + op_b from id stage `ifdef TCDM_ADDR_PRECAL assign alu_adder_lsu_int = alu_adder_i; + $stop("TCDM_ADDR_PRECAL unsupported in RiscV! (jump/branch target calculation not implemented yet"); `else assign alu_adder_lsu_int = alu_operand_a_i + alu_operand_b_i; `endif 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; // Branch is taken when result == 1'b1 - assign branch_taken_o = alu_result[0]; + assign branch_decision_o = alu_result[0]; + assign jump_target_o = alu_operand_c_i; //////////////////////////// @@ -218,7 +219,6 @@ module ex_stage .vec_ext_i ( alu_vec_ext_i ), .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 ) @@ -269,6 +269,7 @@ module ex_stage regfile_rb_data_wb_o <= 32'h0000_0000; sp_we_wb_o <= 1'b0; eoc_o <= 1'b0; + jump_in_ex_o <= '0; end else begin @@ -281,6 +282,7 @@ module ex_stage regfile_rb_data_wb_o <= regfile_rb_data_i; sp_we_wb_o <= sp_we_i; eoc_o <= eoc_i; + jump_in_ex_o <= jump_in_id_i; end end end diff --git a/id_stage.sv b/id_stage.sv index 73c967d7..de360a5a 100644 --- a/id_stage.sv +++ b/id_stage.sv @@ -41,16 +41,18 @@ 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, input logic instr_gnt_i, input logic instr_ack_i, + // Jumps and branches + output logic [1:0] jump_in_id_o, + input logic [1:0] jump_in_ex_i, + // IF and ID stage signals - output logic [31:0] pc_from_immediate_o, + //output logic [31:0] pc_from_immediate_o, // TODO: remove output logic [2:0] pc_mux_sel_o, output logic pc_mux_boot_o, @@ -61,12 +63,6 @@ module id_stage input logic [31:0] current_pc_if_i, input logic [31:0] current_pc_id_i, - // branch prediction - output logic drop_instruction_o, -`ifdef BRANCH_PREDICTION - output logic wrong_branch_taken_o, - output logic take_branch_o, -`endif // STALLS output logic stall_if_o, output logic stall_id_o, @@ -189,15 +185,19 @@ module id_stage logic [31:0] current_pc; // PC to be used in ALU (either IF or ID) + logic [31:0] jump_target; // calculated jump target (-> EX -> IF) + 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 force_nop_controller; + 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 jump_in_id; + //logic jump_in_ex; // registered copy of jump_in_id logic illegal_insn; logic trap_insn; logic pipe_flush; @@ -308,7 +308,6 @@ module id_stage 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_D]; @@ -346,7 +345,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? + //assign pc_from_immediate_o = imm_sb_type; // TODO: Remove/Replace? // PC Mux always_comb @@ -384,6 +383,26 @@ module id_stage */ + ////////////////////////////////////////////////////////////////// + // _ _____ _ // + // | |_ _ _ __ ___ _ __ |_ _|_ _ _ __ __ _ ___| |_ // + // _ | | | | | '_ ` _ \| '_ \ | |/ _` | '__/ _` |/ _ \ __| // + // | |_| | |_| | | | | | | |_) | | | (_| | | | (_| | __/ |_ // + // \___/ \__,_|_| |_| |_| .__/ |_|\__,_|_| \__, |\___|\__| // + // |_| |___/ // + ////////////////////////////////////////////////////////////////// + + always_comb + begin + unique case (instr_rdata_i[6:0]) + `OPCODE_JAL: jump_target = current_pc_id_i + imm_uj_type; + `OPCODE_JALR: jump_target = operand_a_fw_id + imm_i_type; + `OPCODE_BRANCH: jump_target = current_pc_id_i + imm_sb_type; + default: jump_target = '0; + endcase // unique case (instr_rdata_i[6:0]) + end + + //////////////////////////////////////////////////////// // ___ _ _ // // / _ \ _ __ ___ _ __ __ _ _ __ __| | / \ // @@ -429,13 +448,12 @@ module id_stage always_comb begin : immediate_mux case (immediate_mux_sel) - default: immediate_b = 32'h4; //`IMM_VEC: immediate_b = immediate_vec_id; - `IMM_I: immediate_b = imm_i_type; - `IMM_S: immediate_b = imm_s_type; - //`IMM_SB: immediate_b = imm_sb_type; - `IMM_U: immediate_b = imm_u_type; - `IMM_UJ: immediate_b = imm_uj_type; + `IMM_I: immediate_b = imm_i_type; + `IMM_S: immediate_b = imm_s_type; + `IMM_U: immediate_b = imm_u_type; + `IMM_HEX4: immediate_b = 32'h4; + default: immediate_b = 32'h4; endcase; // case (immediate_mux_sel) end @@ -482,8 +500,9 @@ module id_stage 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; + `OP_C_JT: operand_c = jump_target; + //`OP_C_CURRPC: operand_c = current_pc; + default: operand_c = regfile_data_rc_id; endcase // case (alu_op_c_mux_sel) end @@ -553,7 +572,7 @@ module id_stage .eoc_o ( eoc ), .core_busy_o ( core_busy_o ), - .branch_taken_i ( branch_taken_i ), + .force_nop_o ( force_nop_controller ), // Signal from-to PC pipe (instr rdata) and instr mem system (req and ack) .instr_rdata_i ( instr_rdata_i ), @@ -620,7 +639,7 @@ module id_stage .irq_present_i ( irq_present ), // Exception Controller Signals - .jump_in_id_o ( jump_in_id ), + //.jump_in_id_o ( jump_in_id ), .illegal_insn_o ( illegal_insn ), .trap_insn_o ( trap_insn ), .pipe_flush_o ( pipe_flush ), @@ -656,14 +675,12 @@ 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 ), + // To controller (TODO: Remove when control/decode separated and moved) + .jump_in_ex_i ( jump_in_ex_i ), + + // To EX: Jump/Branch indication + .jump_in_id_o ( jump_in_id_o ), - // branch prediction - .drop_instruction_o ( drop_instruction_o ), -`ifdef BRANCH_PREDICTION - .wrong_branch_taken_o ( wrong_branch_taken_o ), - .take_branch_o ( take_branch_o ), -`endif // Stall signals .stall_if_o ( stall_if_o ), .stall_id_o ( stall_id_o ), @@ -680,7 +697,8 @@ module id_stage // // /////////////////////////////////////////////////////////////////////// - assign force_nop_o = 1'b0; + assign force_nop_o = force_nop_controller; + /* exc_controller exc_controller_i ( @@ -823,8 +841,6 @@ module id_stage hwloop_wb_mux_sel_ex_o <= 1'b0; hwloop_cnt_o <= 32'b0; - jump_in_ex <= 1'b0; - eoc_ex_o <= 1'b0; `ifdef TCDM_ADDR_PRECAL @@ -898,14 +914,11 @@ module id_stage hwloop_wb_mux_sel_ex_o <= hwloop_wb_mux_sel; hwloop_cnt_o <= hwloop_cnt; - jump_in_ex <= jump_in_id; - eoc_ex_o <= eoc; `ifdef TCDM_ADDR_PRECAL alu_adder_o <= alu_operand_a + alu_operand_b; `endif - end end diff --git a/if_stage.sv b/if_stage.sv index 8e503572..f0a7a6d6 100644 --- a/if_stage.sv +++ b/if_stage.sv @@ -40,42 +40,39 @@ module if_stage input logic [31:0] boot_addr_i, // Output of IF Pipeline stage - output logic [31:0] instr_rdata_id_o, // read instruction is sampled and sent to ID stage for decoding - output logic [31:0] current_pc_if_o, // current pc program counter - output logic [31:0] current_pc_id_o, // current pc program counter + output logic [31:0] instr_rdata_id_o, // read instruction is sampled and sent to ID stage for decoding + output logic [31:0] current_pc_if_o, // "current" pc program counter + output logic [31:0] current_pc_id_o, // current pc program counter // From to Instr memory - input logic [31:0] instr_rdata_i, // Instruction read from instruction memory /cache - output logic [31:0] instr_addr_o, // address for instruction fetch + input logic [31:0] instr_rdata_i, // Instruction read from instruction memory /cache + output logic [31:0] instr_addr_o, // address for instruction fetch // Forwarding ports - control signals - 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_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 - input logic [1:0] exc_pc_mux_i, // select which exception to execute + 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_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 + input logic [1:0] exc_pc_mux_i, // select which exception to execute + + // jump and branch target and decision + input logic [31:0] jump_target_i, // jump target + input logic [1:0] jump_in_ex_i, // jump in EX -> get PC from jump target (could also be branch) + input logic branch_decision_i, // from debug unit input logic [31:0] dbg_pc_from_npc, input logic dbg_set_npc, - // branch prediction - input logic drop_instruction_i, -`ifdef BRANCH_PREDICTION - input logic wrong_branch_taken_i, - input logic take_branch_i, -`endif // pipeline stall input logic stall_if_i, input logic stall_id_i // Stall in the id stage: here (if_stage) freeze the registers ); - //////////////////////////////////// // Instruction Fetch (IF) signals // //////////////////////////////////// @@ -83,29 +80,18 @@ module if_stage logic [31:0] exc_pc; // Exception PC logic [31:0] instr_rdata_int; // The instruction read from instr memory/cache is forwarded to ID stage, and the controller can force this forwarding to a nop (BUBBLE) -`ifdef BRANCH_PREDICTION - logic [31:0] correct_branch; -`endif - - logic [31:0] branch_taken; - logic [31:0] branch_not_taken; - // 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; - // Next PC Selection: pc_mux_sel_i comes from id_stage.controller - always_comb + /*always_comb begin : PC_MUX 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_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_ALU: begin next_pc = pc_from_alu_i; end // use calculated jump target from ALU `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 @@ -114,8 +100,7 @@ module if_stage `endif default: begin next_pc = current_pc_if_o + 32'd4; end endcase //~case (pc_mux_sel_i) - end - + end */ // Exception PC selection always_comb @@ -128,8 +113,45 @@ module if_stage endcase //~case (exc_pc_mux_i) end - // NOP = addi x0, x0, 0 - assign instr_rdata_int = (force_nop_i == 1'b1) ? { {25 {1'b0}}, `OPCODE_OPIMM } : instr_rdata_i; + + // PC selection and force NOP logic + always_comb + begin + next_pc = current_pc_if_o; + instr_rdata_int = instr_rdata_i; + + unique case (pc_mux_sel_i) + `PC_INCR: next_pc = current_pc_if_o + 32'd4; // PC is incremented and points the next instruction + `PC_NO_INCR: next_pc = current_pc_if_o; // PC is not incremented + `PC_EXCEPTION: next_pc = exc_pc; // PC that points to the exception + `EXC_PC_REG: next_pc = exception_pc_reg_i; // restore the PC when exiting from interr/ecpetions + `HWLOOP_ADDR: next_pc = pc_from_hwloop_i; // PC is taken from hwloop start addr + default: + begin + next_pc = current_pc_if_o; + // synopsis translate off + $display("%t: Illegal pc_mux_sel value (%0d)!", $time, pc_mux_sel_i); + // synopsis translate on + end + endcase // unique case (pc_mux_sel_i) + + // if force NOP, do not increase PC + if (force_nop_i == 1'b1) begin + instr_rdata_int = { 25'b0, `OPCODE_OPIMM }; // addi x0 = x0 + 0 + next_pc = current_pc_if_o; + end + + if (jump_in_ex_i == 2'b01) begin + next_pc = jump_target_i; + end else if (jump_in_ex_i == 2'b10) begin + if (branch_decision_i == 1'b1) + next_pc = jump_target_i; + else + next_pc = current_pc_if_o;// + 32'd4; // TODO: Check if merged with previous adder (from PC mux) + end + + end + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // IF PC register // @@ -159,24 +181,6 @@ module if_stage end end -`ifdef BRANCH_PREDICTION - ////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // Save branch targets in case of a misprediction // - ////////////////////////////////////////////////////////////////////////////////////////////////////////////// - always_ff @(posedge clk, negedge rst_n) - begin : SAVE_BRANCH_TARGET - if (rst_n == 1'b0) - begin : ASSERT_RESET - correct_branch <= 32'b0; - end - else - begin : DEASSERT_RESET - if (wrong_branch_taken_i) - correct_branch <= (take_branch_i) ? branch_taken : branch_not_taken; - end - end -`endif - ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // IF-ID PIPE: Pipeline that is frozen when the ID stage is stalled // ////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -184,15 +188,15 @@ module if_stage begin : IF_ID_PIPE_REGISTERS if (rst_n == 1'b0) begin : ASSERT_RESET - instr_rdata_id_o <= '0; - current_pc_id_o <= '0; + instr_rdata_id_o <= '0; + current_pc_id_o <= '0; end else begin : DEASSERT_RESET - if((stall_id_i == 1'b0) & (drop_instruction_i == 1'b0)) + if (stall_id_i == 1'b0) begin : ENABLED_PIPE - instr_rdata_id_o <= instr_rdata_int; - current_pc_id_o <= current_pc_if_o; + instr_rdata_id_o <= instr_rdata_int; + current_pc_id_o <= current_pc_if_o; end end end diff --git a/include/defines.sv b/include/defines.sv index 297b1de1..12651ba4 100644 --- a/include/defines.sv +++ b/include/defines.sv @@ -170,6 +170,8 @@ // synopsis translate off +`define TRACE_EXECUTION + function void prettyPrintInstruction(input [31:0] instr, input [31:0] pc); string opcode; begin @@ -268,9 +270,6 @@ 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 @@ -341,32 +340,22 @@ endfunction // prettyPrintInstruction // operand c selection `define OP_C_REGC_OR_FWD 1'b0 -`define OP_C_CURRPC 1'b1 +`define OP_C_JT 1'b1 -// immediate selection -// - `define IMM_5N11 4'b0000 -// - `define IMM_21S 4'b0001 -// - `define IMM_8Z 4'b0010 -// - `define IMM_16Z 4'b0011 -// - `define IMM_16 4'b0100 -// - `define IMM_11S 4'b0101 -// - `define IMM_5N6S 4'b0110 -// - `define IMM_VEC 4'b0111 -// - `define IMM_HEX4 4'b1000 -`define IMM_I 3'b000 -`define IMM_S 3'b010 +// operand b immediate selection +`define IMM_I 2'b00 +`define IMM_S 2'b01 +`define IMM_U 2'b10 +`define IMM_HEX4 2'b11 +/* not used: `define IMM_SB 3'b011 -`define IMM_U 3'b100 `define IMM_UJ 3'b101 `define IMM_C4 3'b110 + */ // PC mux selector defines -`define INCR_PC 3'b000 -`define NO_INCR 3'b001 -//`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_INCR 3'b000 +`define PC_NO_INCR 3'b001 `define PC_EXCEPTION 3'b100 `define EXC_PC_REG 3'b101 `define HWLOOP_ADDR 3'b110 @@ -409,4 +398,4 @@ endfunction // prettyPrintInstruction // TCDM_ADDRES PRE CALCULATION --> Bring part of the alu_adder_o calculation in the ID stage //`define TCDM_ADDR_PRECAL - //`define BRANCH_PREDICTION \ No newline at end of file +//`define BRANCH_PREDICTION \ No newline at end of file diff --git a/riscv_core.sv b/riscv_core.sv index 25907190..582758c6 100644 --- a/riscv_core.sv +++ b/riscv_core.sv @@ -93,8 +93,8 @@ module riscv_core // Jump and branch target and decision (EX->IF) logic [31:0] jump_target; - logic jump_in_ex; - logic branch_in_ex; + logic [1:0] jump_in_id; + logic [1:0] jump_in_ex; logic branch_decision; @@ -289,6 +289,11 @@ module riscv_core .dbg_pc_from_npc ( dbg_npc ), .dbg_set_npc ( dbg_set_npc ), + // Jump and branch target and decision + .jump_in_ex_i ( jump_in_ex ), + .branch_decision_i ( branch_decision ), + .jump_target_i ( jump_target ), + // pipeline stalls .stall_if_i ( stall_if ), .stall_id_i ( stall_id ) @@ -341,6 +346,9 @@ module riscv_core // Processor Enable .fetch_enable_i ( fetch_enable_i ), + .jump_in_id_o ( jump_in_id ), + .jump_in_ex_i ( jump_in_ex ), + .core_busy_o ( core_busy_o ), // Interface to instruction memory @@ -357,7 +365,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 ), //TODO .sr_flag_fw_i ( sr_flag_fw ), .sr_flag_i ( sr_flag ), @@ -535,7 +543,6 @@ module riscv_core .regfile_rb_data_i ( regfile_rb_data_ex ), .sp_we_i ( sp_we_ex ), - // Output of ex stage pipeline .regfile_wdata_wb_o ( result_wb ), .regfile_waddr_wb_o ( regfile_waddr_fw_wb_o ), @@ -553,10 +560,12 @@ module riscv_core .sp_we_wb_o ( sp_we_wb ), .eoc_o ( eoc_wb ), + // From ID: Jump and Branch detection + .jump_in_id_i ( jump_in_id ), + // To IF: Jump and branch target and decision .jump_target_o ( jump_target ), .jump_in_ex_o ( jump_in_ex ), - .branch_in_ex_o ( branch_in_ex ), .branch_decision_o ( branch_decision ), // To ID stage: Forwarding signals @@ -812,7 +821,7 @@ module riscv_core instr = id_stage_i.instr_rdata_i[31:0]; pc = id_stage_i.current_pc_id_i; - if (fetch_enable_i == 1'b1 && id_stage_i.stall_id_o == 1'b0) + if (fetch_enable_i == 1'b1 && id_stage_i.stall_id_o == 1'b0 && id_stage_i.controller_i.ctrl_fsm_cs == id_stage_i.controller_i.DECODE) begin //$display("%h", instr); $fwrite(f, "%t:\t0x%h\t0x%h\t", $time, pc, instr); @@ -883,7 +892,7 @@ module riscv_core function void printRInstr(input string mnemonic); begin - $fdisplay(f, "%s x%0d, x%d (0x%h), x%0d (0x%h)", mnemonic, instr[`REG_D], + $fdisplay(f, "%s\tx%0d, x%d (0x%h), x%0d (0x%h)", mnemonic, instr[`REG_D], instr[`REG_S1], r[instr[`REG_S1]], instr[`REG_S2], r[instr[`REG_S2]]); end endfunction // printRInstr @@ -892,7 +901,7 @@ module riscv_core logic [31:0] i_imm; begin i_imm = { {20 {instr[31]}}, instr[31:20] }; - $fdisplay(f, "%s x%0d, x%0d (0x%h), 0x%0d (imm)", mnemonic, instr[`REG_D], + $fdisplay(f, "%s\tx%0d, x%0d (0x%h), 0x%0d (imm)", mnemonic, instr[`REG_D], instr[`REG_S1], r[instr[`REG_S1]], i_imm); end endfunction // printIInstr @@ -901,7 +910,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%0d (0x%h), 0x%h (imm)", mnemonic, + $fdisplay(f, "%s\tx%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 @@ -911,7 +920,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%0d (0x%h), 0x%h (imm)", mnemonic, + $fdisplay(f, "%s\tx%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 @@ -921,13 +930,13 @@ module riscv_core logic [31:0] uj_imm; begin uj_imm = { {20 {instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0 }; - $fdisplay(f, "%s x%0d, 0x%h", mnemonic, instr[`REG_D], uj_imm); + $fdisplay(f, "%s\tx%0d, 0x%h", mnemonic, instr[`REG_D], uj_imm); end endfunction // printUJInstr function void printRDInstr(input string mnemonic); begin - $fdisplay(f, "%s x%0d", mnemonic, instr[`REG_D]); + $fdisplay(f, "%s\tx%0d", mnemonic, instr[`REG_D]); end endfunction // printRDInstr