`define OP0 31:28 `define IM0 19:16 `define SB0 19 `define OP1 15:12 `define IM1 7:0 `define IM1_4 3:0 `define SB1 7 `define BLZ 4'd7 `define BNE 4'd7 `define ADDI 4'd1 `define Z32 32'bZ // // BRANCH PREDICTOR // // logic: // - if IFID.instr uses a large immediate // - if it contains a branch, predict it (backward taken, forward taken) // - if it contains no branch, predict pc+1 // - if IFID.instr has no large immediate // - if the incoming fetched instruction has a branch with a small immediate, predict it (backward taken, forward taken) // - otherwise, predict pc+1 // module branch_prediction ( pc, instr, pcPrev, instrPrev, pred ); input [31:0] pc; input [31:0] pcPrev; input [31:0] instr; input [31:0] instrPrev; output [31:0] pred; wire prev0_br = (instrPrev[`OP0] == `BNE); wire prev0_addi = (instrPrev[`OP0] == `ADDI); wire prev1_br = (instrPrev[`OP1] == `BLZ); wire prev1_addi = (instrPrev[`OP1] == `ADDI); wire instr0_br = (instr[`OP0] == `BNE); wire instr0_addi = (instr[`OP0] == `ADDI); wire instr1_br = (instr[`OP1] == `BLZ); wire instr1_addi = (instr[`OP1] == `ADDI); wire [31:0] pc1 = pc + 1; wire prev0_brlgim = prev0_br & (instrPrev[`IM0] == 4'd0); wire prev0_br_sb = prev0_br & instrPrev[`SB0]; wire prev0_addilgim = prev0_addi & (instrPrev[`IM0] == 4'd0); wire prev1_brlgim = prev1_br & (instrPrev[`IM1] == 8'd0); wire prev1_br_sb = prev1_br & instrPrev[`SB1]; wire prev1_addilgim = prev1_addi & (instrPrev[`IM1_4] == 4'd0); wire instr0_brlgim = instr0_br & (instr[`IM0] == 4'd0); wire instr0_br_sb = instr0_br & instr[`SB0]; wire instr0_addilgim = instr0_addi & (instr[`IM0] == 4'd0); wire instr1_brlgim = instr1_br & (instr[`IM1] == 8'd0); wire instr1_br_sb = instr1_br & instr[`SB1]; wire instr1_addilgim = instr1_addi & (instr[`IM1_4] == 4'd0); wire instrPrev_lgImm = prev0_brlgim | prev0_addilgim | prev1_brlgim | prev1_addilgim; wire prev_br_lgim_sb = (prev0_brlgim | prev1_brlgim) & instr[31]; wire instrPrev_br_back = prev0_br_sb | prev1_br_sb | prev_br_lgim_sb; wire instr_lgImm = instr0_brlgim | instr0_addilgim | instr1_brlgim | instr1_addilgim; wire instr_br_sb = instr0_br_sb | instr1_br_sb; wire instr_br_back = ~instr_lgImm & instr_br_sb; wire [31:0] prev_disp = prev0_br_sb ? { {28{instrPrev[`SB0]}}, instrPrev[`IM0] } : prev1_br_sb ? { {24{instrPrev[`SB1]}}, instrPrev[`IM1] } : instr; wire [31:0] disp = instr0_br_sb ? { {28{instr[`SB0]}}, instr[`IM0] } : { {24{instr[`SB1]}}, instr[`IM1] }; assign pred = instrPrev_lgImm ? (instrPrev_br_back ? (pcPrev + prev_disp) : pc1) : (instr_br_back ? (pc + disp) : pc1); endmodule // // BRANCH PREDICTOR // // This is currently a bit of a mess. I'm sure there is a better way to code it up. // module old_branch_prediction ( pc, instr, pcPrev, instrPrev, pred ); input [31:0] pc; input [31:0] pcPrev; input [31:0] instr; input [31:0] instrPrev; output [31:0] pred; // previous instruction has one or more branch opcodes wire prev0_br = (instrPrev[`OP0] == `BNE); wire prev0_addi = (instrPrev[`OP0] == `ADDI); wire prev1_br = (instrPrev[`OP1] == `BLZ); wire prev1_addi = (instrPrev[`OP1] == `ADDI); // previous instruction has a branch or ADDI that uses large immediate wire prev0_brlgim = prev0_br & (instrPrev[`IM0] == 4'd0); wire prev0_addilgim = prev0_addi & (instrPrev[`IM0] == 4'd0); wire prev1_brlgim = prev1_br & (instrPrev[`IM1] == 8'd0); wire prev1_addilgim = prev1_addi & (instrPrev[`IM1_4] == 4'd0); wire prev_brlgim = prev0_brlgim | prev0_addilgim | prev1_brlgim | prev1_addilgim; // previous instruction's sign bit (will determine branch direction) wire prev0_sb = (prev0_brlgim) ? instr[31] : instrPrev[`SB0]; wire prev1_sb = (prev1_brlgim) ? instr[31] : instrPrev[`SB1]; // previous instruction is a backwards branch wire prev0_backwards = prev0_br & prev0_sb; wire prev1_backwards = prev1_br & prev1_sb; // previous instruction displacement (prefer slot0 if pred-taken, otherwise use slot1) wire [31:0] prev_smdisp = (prev0_backwards) ? { {28{instrPrev[`SB0]}}, instrPrev[`IM0] } : { {24{instrPrev[`SB1]}}, instrPrev[`IM1] }; // previous instruction taken/non-taken PC offsets wire [31:0] prev_taken_disp = (prev_brlgim) ? instr : prev_smdisp; wire [31:0] prev_nontaken_disp = (prev_brlgim) ? 32'd2 : 32'd1; // predicted displacement for previous instruction wire [31:0] prev_pred_disp = (prev0_backwards | prev1_backwards) ? prev_taken_disp : prev_nontaken_disp; // present instruction has one or more branch opcodes wire instr0_br = (instr[`OP0] == `BNE); wire instr0_addi = (instr[`OP0] == `ADDI); wire instr1_br = (instr[`OP1] == `BLZ); wire instr1_addi = (instr[`OP1] == `ADDI); // present instruction has a branch that uses large immediate wire instr0_brlgim = instr0_br & (instr[`IM0] == 4'd0); wire instr1_brlgim = instr1_br & (instr[`IM1] == 8'd0); wire instr_brlgim = instr0_brlgim | instr1_brlgim; // present instruction's sign bit (will determine branch direction) wire instr0_sb = instr[`SB0]; wire instr1_sb = instr[`SB1]; // present instruction is a backwards branch wire instr0_backwards = instr0_br & instr0_sb; wire instr1_backwards = instr1_br & instr1_sb; // present instruction displacement (prefer slot0 if pred-taken, otherwise use slot1) wire [31:0] instr_smdisp = (instr0_backwards) ? { {28{instr[`SB0]}}, instr[`IM0] } : { {24{instr[`SB1]}}, instr[`IM1] }; // previous instruction taken/non-taken PC offsets wire [31:0] instr_taken_disp = (instr_brlgim) ? 32'd1 : instr_smdisp; wire [31:0] instr_nontaken_disp = 32'd1; // even if it uses a large immediate don't branch over it // predicted displacement for present instruction wire [31:0] instr_pred_disp = (instr0_backwards | instr1_backwards) ? instr_taken_disp : instr_nontaken_disp; // branch predition: this is a single line of code ... I did all the hard work above for you assign pred = (prev_brlgim) ? pcPrev + prev_pred_disp : pc + instr_pred_disp; endmodule