diff --git a/rtl/ibex_core.sv b/rtl/ibex_core.sv index f2eb37a4..56537fbf 100644 --- a/rtl/ibex_core.sv +++ b/rtl/ibex_core.sv @@ -133,7 +133,7 @@ module ibex_core #( logic [31:0] lsu_addr_last; // Jump and branch target and decision (EX->IF) - logic [31:0] jump_target_ex; + logic [31:0] branch_target_ex; logic branch_decision; // Core busy signals @@ -166,8 +166,8 @@ module ibex_core #( logic [31:0] alu_operand_a_ex; logic [31:0] alu_operand_b_ex; - jt_mux_sel_e jt_mux_sel_ex; - logic [11:0] bt_operand_imm_ex; + logic [31:0] bt_a_operand; + logic [31:0] bt_b_operand; logic [31:0] alu_adder_result_ex; // Used to forward computed address to LSU logic [31:0] result_ex; @@ -386,8 +386,8 @@ module ibex_core #( .icache_enable_i ( icache_enable ), .icache_inval_i ( icache_inval ), - // jump targets - .jump_target_ex_i ( jump_target_ex ), + // branch targets + .branch_target_ex_i ( branch_target_ex ), // CSRs .csr_mepc_i ( csr_mepc ), // exception return address @@ -463,8 +463,8 @@ module ibex_core #( .alu_operand_a_ex_o ( alu_operand_a_ex ), .alu_operand_b_ex_o ( alu_operand_b_ex ), - .jt_mux_sel_ex_o ( jt_mux_sel_ex ), - .bt_operand_imm_o ( bt_operand_imm_ex ), + .bt_a_operand_o ( bt_a_operand ), + .bt_b_operand_o ( bt_b_operand ), .mult_en_ex_o ( mult_en_ex ), .div_en_ex_o ( div_en_ex ), @@ -571,9 +571,8 @@ module ibex_core #( .alu_operand_b_i ( alu_operand_b_ex ), // Branch target ALU signal from ID stage - .jt_mux_sel_i ( jt_mux_sel_ex ), - .bt_operand_imm_i ( bt_operand_imm_ex ), - .pc_id_i ( pc_id ), + .bt_a_operand_i ( bt_a_operand ), + .bt_b_operand_i ( bt_b_operand ), // Multipler/Divider signal from ID stage .multdiv_operator_i ( multdiv_operator_ex ), @@ -589,7 +588,7 @@ module ibex_core #( .alu_adder_result_ex_o ( alu_adder_result_ex ), // to LSU .result_ex_o ( result_ex ), // to ID - .jump_target_o ( jump_target_ex ), // to IF + .branch_target_o ( branch_target_ex ), // to IF .branch_decision_o ( branch_decision ), // to ID .ex_valid_o ( ex_valid ) diff --git a/rtl/ibex_decoder.sv b/rtl/ibex_decoder.sv index ae636329..2b1aec26 100644 --- a/rtl/ibex_decoder.sv +++ b/rtl/ibex_decoder.sv @@ -47,7 +47,8 @@ module ibex_decoder #( // immediates output ibex_pkg::imm_a_sel_e imm_a_mux_sel_o, // immediate selection for operand a output ibex_pkg::imm_b_sel_e imm_b_mux_sel_o, // immediate selection for operand b - output ibex_pkg::jt_mux_sel_e jt_mux_sel_o, // jump target selection + output ibex_pkg::op_a_sel_e bt_a_mux_sel_o, // branch target selection operand a + output ibex_pkg::imm_b_sel_e bt_b_mux_sel_o, // branch target selection operand b output logic [31:0] imm_i_type_o, output logic [31:0] imm_s_type_o, output logic [31:0] imm_b_type_o, @@ -212,8 +213,8 @@ module ibex_decoder #( jump_in_dec_o = 1'b1; if (instr_first_cycle_i) begin - // Calculate jump target - rf_we = 1'b0; + // Calculate jump target (and store PC + 4 if BranchTargetALU is configured) + rf_we = BranchTargetALU; jump_set_o = 1'b1; end else begin // Calculate and store PC+4 @@ -225,8 +226,8 @@ module ibex_decoder #( jump_in_dec_o = 1'b1; if (instr_first_cycle_i) begin - // Calculate jump target - rf_we = 1'b0; + // Calculate jump target (and store PC + 4 if BranchTargetALU is configured) + rf_we = BranchTargetALU; jump_set_o = 1'b1; end else begin // Calculate and store PC+4 @@ -548,7 +549,8 @@ module ibex_decoder #( imm_a_mux_sel_o = IMM_A_ZERO; imm_b_mux_sel_o = IMM_B_I; - jt_mux_sel_o = JT_ALU; + bt_a_mux_sel_o = OP_A_CURRPC; + bt_b_mux_sel_o = IMM_B_I; multdiv_sel_o = 1'b0; @@ -562,10 +564,12 @@ module ibex_decoder #( OPCODE_JAL: begin // Jump and Link if (BranchTargetALU) begin - jt_mux_sel_o = JT_ALU; + bt_a_mux_sel_o = OP_A_CURRPC; + bt_b_mux_sel_o = IMM_B_J; end - if (instr_first_cycle_i) begin + // Jumps take two cycles without the BTALU + if (instr_first_cycle_i && !BranchTargetALU) begin // Calculate jump target alu_op_a_mux_sel_o = OP_A_CURRPC; alu_op_b_mux_sel_o = OP_B_IMM; @@ -582,10 +586,12 @@ module ibex_decoder #( OPCODE_JALR: begin // Jump and Link Register if (BranchTargetALU) begin - jt_mux_sel_o = JT_ALU; + bt_a_mux_sel_o = OP_A_REG_A; + bt_b_mux_sel_o = IMM_B_I; end - if (instr_first_cycle_i) begin + // Jumps take two cycles without the BTALU + if (instr_first_cycle_i && !BranchTargetALU) begin // Calculate jump target alu_op_a_mux_sel_o = OP_A_REG_A; alu_op_b_mux_sel_o = OP_B_IMM; @@ -617,7 +623,8 @@ module ibex_decoder #( // target ALU calculates the target (which is controlled in a seperate block below) alu_op_a_mux_sel_o = OP_A_REG_A; alu_op_b_mux_sel_o = OP_B_REG_B; - jt_mux_sel_o = JT_BT_ALU; + bt_a_mux_sel_o = OP_A_CURRPC; + bt_b_mux_sel_o = IMM_B_B; end else begin // Without branch target ALU, a branch is a two-stage operation using the Main ALU in both // stages @@ -757,10 +764,15 @@ module ibex_decoder #( alu_op_b_mux_sel_o = OP_B_IMM; end 3'b001: begin - alu_op_a_mux_sel_o = OP_A_CURRPC; - alu_op_b_mux_sel_o = OP_B_IMM; - imm_b_mux_sel_o = IMM_B_INCR_PC; - alu_operator_o = ALU_ADD; + if (BranchTargetALU) begin + bt_a_mux_sel_o = OP_A_CURRPC; + bt_b_mux_sel_o = IMM_B_INCR_PC; + end else begin + alu_op_a_mux_sel_o = OP_A_CURRPC; + alu_op_b_mux_sel_o = OP_B_IMM; + imm_b_mux_sel_o = IMM_B_INCR_PC; + alu_operator_o = ALU_ADD; + end end default: ; endcase diff --git a/rtl/ibex_ex_block.sv b/rtl/ibex_ex_block.sv index 530561e3..c7672288 100644 --- a/rtl/ibex_ex_block.sv +++ b/rtl/ibex_ex_block.sv @@ -23,9 +23,8 @@ module ibex_ex_block #( // Branch Target ALU // All of these signals are unusued when BranchTargetALU == 0 - input ibex_pkg::jt_mux_sel_e jt_mux_sel_i, - input logic [11:0] bt_operand_imm_i, - input logic [31:0] pc_id_i, + input logic [31:0] bt_a_operand_i, + input logic [31:0] bt_b_operand_i, // Multiplier/Divider input ibex_pkg::md_op_e multdiv_operator_i, @@ -40,7 +39,7 @@ module ibex_ex_block #( // Outputs output logic [31:0] alu_adder_result_ex_o, // to LSU output logic [31:0] result_ex_o, - output logic [31:0] jump_target_o, // to IF + output logic [31:0] branch_target_o, // to IF output logic branch_decision_o, // to ID output logic ex_valid_o // EX has valid output @@ -74,21 +73,20 @@ module ibex_ex_block #( if (BranchTargetALU) begin : g_branch_target_alu logic [32:0] bt_alu_result; + logic unused_bt_carry; - assign bt_alu_result = {{19{bt_operand_imm_i[11]}}, bt_operand_imm_i, 1'b0} + pc_id_i; + assign bt_alu_result = bt_a_operand_i + bt_b_operand_i; - assign jump_target_o = (jt_mux_sel_i == JT_ALU) ? alu_adder_result_ex_o : bt_alu_result[31:0]; + assign unused_bt_carry = bt_alu_result[32]; + assign branch_target_o = bt_alu_result[31:0]; end else begin : g_no_branch_target_alu - // Unused jt_mux_sel_i/bt_operand_imm_i/pc_id_i signals causes lint errors, this avoids them - ibex_pkg::jt_mux_sel_e unused_jt_mux_sel; - logic [11:0] unused_bt_operand_imm; - logic [31:0] unused_pc_id; + // Unused bt_operand signals cause lint errors, this avoids them + logic [31:0] unused_bt_a_operand, unused_bt_b_operand; - assign unused_jt_mux_sel = jt_mux_sel_i; - assign unused_bt_operand_imm = bt_operand_imm_i; - assign unused_pc_id = pc_id_i; + assign unused_bt_a_operand = bt_a_operand_i; + assign unused_bt_b_operand = bt_b_operand_i; - assign jump_target_o = alu_adder_result_ex_o; + assign branch_target_o = alu_adder_result_ex_o; end ///////// diff --git a/rtl/ibex_id_stage.sv b/rtl/ibex_id_stage.sv index e53e3c36..cabb627d 100644 --- a/rtl/ibex_id_stage.sv +++ b/rtl/ibex_id_stage.sv @@ -67,8 +67,8 @@ module ibex_id_stage #( output logic [31:0] alu_operand_b_ex_o, // Branch target ALU - output ibex_pkg::jt_mux_sel_e jt_mux_sel_ex_o, - output logic [11:0] bt_operand_imm_o, + output logic [31:0] bt_a_operand_o, + output logic [31:0] bt_b_operand_o, // MUL, DIV output logic mult_en_ex_o, @@ -224,6 +224,9 @@ module ibex_id_stage #( op_a_sel_e alu_op_a_mux_sel, alu_op_a_mux_sel_dec; op_b_sel_e alu_op_b_mux_sel, alu_op_b_mux_sel_dec; + op_a_sel_e bt_a_mux_sel; + imm_b_sel_e bt_b_mux_sel; + imm_a_sel_e imm_a_mux_sel; imm_b_sel_e imm_b_mux_sel, imm_b_mux_sel_dec; @@ -258,13 +261,13 @@ module ibex_id_stage #( assign imm_b_mux_sel = lsu_addr_incr_req_i ? IMM_B_INCR_ADDR : imm_b_mux_sel_dec; /////////////////// - // Operand A MUX // + // Operand MUXES // /////////////////// - // Immediate MUX for Operand A + // Main ALU immediate MUX for Operand A assign imm_a = (imm_a_mux_sel == IMM_A_Z) ? zimm_rs1_type : '0; - // ALU MUX for Operand A + // Main ALU MUX for Operand A always_comb begin : alu_operand_a_mux unique case (alu_op_a_mux_sel) OP_A_REG_A: alu_operand_a = rf_rdata_a_fwd; @@ -275,22 +278,60 @@ module ibex_id_stage #( endcase end - /////////////////// - // Operand B MUX // - /////////////////// + if (BranchTargetALU) begin : g_btalu_muxes + // Branch target ALU operand A mux + always_comb begin : bt_operand_a_mux + unique case (bt_a_mux_sel) + OP_A_REG_A: bt_a_operand_o = rf_rdata_a_fwd; + OP_A_CURRPC: bt_a_operand_o = pc_id_i; + default: bt_a_operand_o = pc_id_i; + endcase + end - // Immediate MUX for Operand B - always_comb begin : immediate_b_mux - unique case (imm_b_mux_sel) - IMM_B_I: imm_b = imm_i_type; - IMM_B_S: imm_b = imm_s_type; - IMM_B_B: imm_b = imm_b_type; - IMM_B_U: imm_b = imm_u_type; - IMM_B_J: imm_b = imm_j_type; - IMM_B_INCR_PC: imm_b = instr_is_compressed_i ? 32'h2 : 32'h4; - IMM_B_INCR_ADDR: imm_b = 32'h4; - default: imm_b = 32'h4; - endcase + // Branch target ALU operand B mux + always_comb begin : bt_immediate_b_mux + unique case (bt_b_mux_sel) + IMM_B_I: bt_b_operand_o = imm_i_type; + IMM_B_B: bt_b_operand_o = imm_b_type; + IMM_B_J: bt_b_operand_o = imm_j_type; + IMM_B_INCR_PC: bt_b_operand_o = instr_is_compressed_i ? 32'h2 : 32'h4; + default: bt_b_operand_o = instr_is_compressed_i ? 32'h2 : 32'h4; + endcase + end + + // Reduced main ALU immediate MUX for Operand B + always_comb begin : immediate_b_mux + unique case (imm_b_mux_sel) + IMM_B_I: imm_b = imm_i_type; + IMM_B_S: imm_b = imm_s_type; + IMM_B_U: imm_b = imm_u_type; + IMM_B_INCR_PC: imm_b = instr_is_compressed_i ? 32'h2 : 32'h4; + IMM_B_INCR_ADDR: imm_b = 32'h4; + default: imm_b = 32'h4; + endcase + end + end else begin : g_nobtalu + op_a_sel_e unused_a_mux_sel; + imm_b_sel_e unused_b_mux_sel; + + assign unused_a_mux_sel = bt_a_mux_sel; + assign unused_b_mux_sel = bt_b_mux_sel; + assign bt_a_operand_o = '0; + assign bt_b_operand_o = '0; + + // Full main ALU immediate MUX for Operand B + always_comb begin : immediate_b_mux + unique case (imm_b_mux_sel) + IMM_B_I: imm_b = imm_i_type; + IMM_B_S: imm_b = imm_s_type; + IMM_B_B: imm_b = imm_b_type; + IMM_B_U: imm_b = imm_u_type; + IMM_B_J: imm_b = imm_j_type; + IMM_B_INCR_PC: imm_b = instr_is_compressed_i ? 32'h2 : 32'h4; + IMM_B_INCR_ADDR: imm_b = 32'h4; + default: imm_b = 32'h4; + endcase + end end // ALU MUX for Operand B @@ -343,7 +384,8 @@ module ibex_id_stage #( // immediates .imm_a_mux_sel_o ( imm_a_mux_sel ), .imm_b_mux_sel_o ( imm_b_mux_sel_dec ), - .jt_mux_sel_o ( jt_mux_sel_ex_o ), + .bt_a_mux_sel_o ( bt_a_mux_sel ), + .bt_b_mux_sel_o ( bt_b_mux_sel ), .imm_i_type_o ( imm_i_type ), .imm_s_type_o ( imm_s_type ), @@ -529,14 +571,6 @@ module ibex_id_stage #( assign alu_operand_a_ex_o = alu_operand_a; assign alu_operand_b_ex_o = alu_operand_b; - if (BranchTargetALU) begin : g_bt_operand_imm - // Branch target ALU sign-extends and inserts bottom 0 bit so only want the - // 'raw' B-type immediate bits. - assign bt_operand_imm_o = imm_b_type[12:1]; - end else begin : g_no_bt_operand_imm - assign bt_operand_imm_o = '0; - end - assign mult_en_ex_o = mult_en_id; assign div_en_ex_o = div_en_id; assign multdiv_sel_ex_o = multdiv_sel_dec; @@ -637,8 +671,9 @@ module ibex_id_stage #( end jump_in_dec: begin // uncond branch operation - id_fsm_d = MULTI_CYCLE; - stall_jump = 1'b1; + // BTALU means jumps only need one cycle + id_fsm_d = BranchTargetALU ? FIRST_CYCLE : MULTI_CYCLE; + stall_jump = ~BranchTargetALU; end default: begin id_fsm_d = FIRST_CYCLE; @@ -853,14 +888,38 @@ module ibex_id_stage #( // Selectors must be known/valid. `ASSERT_KNOWN(IbexAluOpMuxSelKnown, alu_op_a_mux_sel, clk_i, !rst_ni) - `ASSERT(IbexImmBMuxSelValid, imm_b_mux_sel inside { + `ASSERT(IbexAluAOpMuxSelValid, alu_op_a_mux_sel inside { + OP_A_REG_A, + OP_A_FWD, + OP_A_CURRPC, + OP_A_IMM}) + if (BranchTargetALU) begin : g_btalu_assertions + `ASSERT(IbexImmBMuxSelValid, imm_b_mux_sel inside { + IMM_B_I, + IMM_B_S, + IMM_B_U, + IMM_B_INCR_PC, + IMM_B_INCR_ADDR}) + end else begin : g_nobtalu_assertions + `ASSERT(IbexImmBMuxSelValid, imm_b_mux_sel inside { + IMM_B_I, + IMM_B_S, + IMM_B_B, + IMM_B_U, + IMM_B_J, + IMM_B_INCR_PC, + IMM_B_INCR_ADDR}) + end + `ASSERT_KNOWN(IbexBTAluAOpMuxSelKnown, bt_a_mux_sel, clk_i, !rst_ni) + `ASSERT(IbexBTAluAOpMuxSelValid, bt_a_mux_sel inside { + OP_A_REG_A, + OP_A_CURRPC}) + `ASSERT_KNOWN(IbexBTAluBOpMuxSelKnown, bt_b_mux_sel, clk_i, !rst_ni) + `ASSERT(IbexBTAluBOpMuxSelValid, bt_b_mux_sel inside { IMM_B_I, - IMM_B_S, IMM_B_B, - IMM_B_U, IMM_B_J, - IMM_B_INCR_PC, - IMM_B_INCR_ADDR}) + IMM_B_INCR_PC}) `ASSERT(IbexRegfileWdataSelValid, rf_wdata_sel inside { RF_WD_EX, RF_WD_CSR}) diff --git a/rtl/ibex_if_stage.sv b/rtl/ibex_if_stage.sv index e8da0ad5..fa7a76a5 100644 --- a/rtl/ibex_if_stage.sv +++ b/rtl/ibex_if_stage.sv @@ -62,7 +62,7 @@ module ibex_if_stage #( input logic icache_inval_i, // jump and branch target - input logic [31:0] jump_target_ex_i, // jump target address + input logic [31:0] branch_target_ex_i, // branch/jump target address // CSRs input logic [31:0] csr_mepc_i, // PC to restore after handling @@ -128,7 +128,7 @@ module ibex_if_stage #( always_comb begin : fetch_addr_mux unique case (pc_mux_i) PC_BOOT: fetch_addr_n = { boot_addr_i[31:8], 8'h80 }; - PC_JUMP: fetch_addr_n = jump_target_ex_i; + PC_JUMP: fetch_addr_n = branch_target_ex_i; PC_EXC: fetch_addr_n = exc_pc; // set PC to exception handler PC_ERET: fetch_addr_n = csr_mepc_i; // restore PC when returning from EXC PC_DRET: fetch_addr_n = csr_depc_i; diff --git a/rtl/ibex_pkg.sv b/rtl/ibex_pkg.sv index e08b2328..448db40c 100644 --- a/rtl/ibex_pkg.sv +++ b/rtl/ibex_pkg.sv @@ -142,12 +142,6 @@ typedef enum logic [2:0] { IMM_B_INCR_ADDR } imm_b_sel_e; -// Only used when BranchTargetALU == 1 -typedef enum logic { - JT_ALU, // Jump target from main ALU - JT_BT_ALU // Jump target from specialised branch ALU -} jt_mux_sel_e; - // Regfile write data selection typedef enum logic { RF_WD_EX,