`timescale 1ns / 1ps `default_nettype none // ----------------------------------------------------------------------------- // EX 级控制流裁决单元。 // // 条件分支的实际方向与目标都在 EX 级解析;JAL/JALR 的目标也只在 EX 级 // 得到,因此它们总是需要重定向。条件分支仅在预测方向/目标与实际不符时 // 才重定向,这样预测正确时不会产生气泡。 // ----------------------------------------------------------------------------- module cpu21_riscv_branch_unit ( input wire valid_i, input wire [31:0] pc_i, input wire [31:0] imm_i, input wire [31:0] src1_i, input wire [31:0] src2_i, input wire branch_i, input wire beq_i, input wire bne_i, input wire blt_i, input wire bltu_i, input wire jal_i, input wire jalr_i, // IF 级携带过来的预测信息 input wire pred_taken_i, input wire [31:0] pred_target_i, // 裁决结果 output wire branch_taken_o, output wire controlflow_o, output wire [31:0] target_o, output wire redirect_valid_o, output wire [31:0] redirect_pc_o ); // 条件分支裁决:beq 相等、bne 不等、blt 有符号小于、bltu 无符号小于。 assign branch_taken_o = branch_i && ((beq_i && (src1_i == src2_i)) || (bne_i && (src1_i != src2_i)) || (blt_i && ($signed( src1_i ) < $signed( src2_i ))) || (bltu_i && (src1_i < src2_i))); // 跳转目标:jalr 为 (rs1+imm) 且最低位清零;jal 为 PC+imm。 assign target_o = jalr_i ? ((src1_i + imm_i) & 32'hffff_fffe) : (pc_i + imm_i); // EX 级存在需要裁决的控制流指令。 assign controlflow_o = valid_i && (branch_i || jal_i || jalr_i); // 条件分支的预测方向/目标与实际不符,或 JAL/JALR 必须重定向。 assign redirect_valid_o = controlflow_o && (branch_i ? ((pred_taken_i != branch_taken_o) || (pred_taken_i && branch_taken_o && (pred_target_i != target_o))) : 1'b1); // 预测了跳转但实际不跳转时,回到顺序地址继续取指。 assign redirect_pc_o = (branch_i && !branch_taken_o) ? (pc_i + 32'd4) : target_o; endmodule `default_nettype wire