diff --git a/rv32.sv b/rv32.sv index 8c35342..251db6d 100644 --- a/rv32.sv +++ b/rv32.sv @@ -41,6 +41,9 @@ module rv32 ( logic mem_stall; logic mem_flush; + /* fetch -> decode control */ + logic fetch_branch_predicted_taken; + /* fetch -> decode data */ logic [31:0] fetch_pc; logic [31:0] fetch_instr; @@ -53,6 +56,7 @@ module rv32 ( logic decode_mem_fence_unreg; /* decode -> execute control */ + logic decode_branch_predicted_taken; logic decode_valid; logic [4:0] decode_rs1; logic [4:0] decode_rs2; @@ -82,6 +86,7 @@ module rv32 ( logic [11:0] decode_csr; /* execute -> mem control */ + logic execute_branch_predicted_taken; logic execute_valid; logic execute_mem_read; logic execute_mem_write; @@ -103,7 +108,7 @@ module rv32 ( logic mem_rd_write; /* mem -> fetch control */ - logic mem_branch_taken; + logic mem_branch_mispredicted; /* mem -> writeback data */ logic [31:0] mem_rd_value; @@ -126,7 +131,7 @@ module rv32 ( .execute_mem_fence_in(execute_mem_fence), - .mem_branch_taken_in(mem_branch_taken), + .mem_branch_mispredicted_in(mem_branch_mispredicted), .instr_read_in(instr_read_out), .instr_ready_in(instr_ready_in), @@ -157,11 +162,14 @@ module rv32 ( .flush_in(fetch_flush), /* control in (from mem) */ - .branch_taken_in(mem_branch_taken), + .branch_mispredicted_in(mem_branch_mispredicted), /* control out (to memory bus) */ .instr_read_out(instr_read_out), + /* control out */ + .branch_predicted_taken_out(fetch_branch_predicted_taken), + /* data in (from mem) */ .branch_pc_in(mem_branch_pc), @@ -183,6 +191,9 @@ module rv32 ( .stall_in(decode_stall), .flush_in(decode_flush), + /* control in (from fetch) */ + .branch_predicted_taken_in(fetch_branch_predicted_taken), + /* control in (from writeback) */ .rd_in(mem_rd), .rd_write_in(mem_rd_write), @@ -202,6 +213,7 @@ module rv32 ( .mem_fence_unreg_out(decode_mem_fence_unreg), /* control out */ + .branch_predicted_taken_out(decode_branch_predicted_taken), .valid_out(decode_valid), .rs1_out(decode_rs1), .rs2_out(decode_rs2), @@ -239,6 +251,7 @@ module rv32 ( .flush_in(execute_flush), /* control in */ + .branch_predicted_taken_in(decode_branch_predicted_taken), .valid_in(decode_valid), .rs1_in(decode_rs1), .rs2_in(decode_rs2), @@ -276,6 +289,7 @@ module rv32 ( .writeback_rd_value_in(mem_rd_value), /* control out */ + .branch_predicted_taken_out(execute_branch_predicted_taken), .valid_out(execute_valid), .mem_read_out(execute_mem_read), .mem_write_out(execute_mem_write), @@ -300,6 +314,7 @@ module rv32 ( .flush_in(mem_flush), /* control in */ + .branch_predicted_taken_in(execute_branch_predicted_taken), .valid_in(execute_valid), .read_in(execute_mem_read), .write_in(execute_mem_write), @@ -319,7 +334,7 @@ module rv32 ( /* control out */ .valid_out(mem_valid), - .branch_taken_out(mem_branch_taken), + .branch_mispredicted_out(mem_branch_mispredicted), .rd_out(mem_rd), .rd_write_out(mem_rd_write), diff --git a/rv32_branch.sv b/rv32_branch.sv index a68bd03..b15d042 100644 --- a/rv32_branch.sv +++ b/rv32_branch.sv @@ -29,26 +29,30 @@ endmodule module rv32_branch_unit ( /* control in */ + input predicted_taken_in, input [1:0] op_in, /* data in */ input [31:0] result_in, /* control out */ - output logic taken_out + output logic mispredicted_out ); logic non_zero; + logic taken; assign non_zero = |result_in; always_comb begin case (op_in) - `RV32_BRANCH_OP_NEVER: taken_out = 0; - `RV32_BRANCH_OP_ZERO: taken_out = ~non_zero; - `RV32_BRANCH_OP_NON_ZERO: taken_out = non_zero; - `RV32_BRANCH_OP_ALWAYS: taken_out = 1; + `RV32_BRANCH_OP_NEVER: taken = 0; + `RV32_BRANCH_OP_ZERO: taken = ~non_zero; + `RV32_BRANCH_OP_NON_ZERO: taken = non_zero; + `RV32_BRANCH_OP_ALWAYS: taken = 1; endcase end + + assign mispredicted_out = taken != predicted_taken_in; endmodule `endif diff --git a/rv32_decode.sv b/rv32_decode.sv index 94f17f8..003a311 100644 --- a/rv32_decode.sv +++ b/rv32_decode.sv @@ -11,6 +11,9 @@ module rv32_decode ( input stall_in, input flush_in, + /* control in (from fetch) */ + input branch_predicted_taken_in, + /* control in (from writeback) */ input [4:0] rd_in, input rd_write_in, @@ -30,6 +33,7 @@ module rv32_decode ( output logic mem_fence_unreg_out, /* control out */ + output logic branch_predicted_taken_out, output logic valid_out, output logic [4:0] rs1_out, output logic [4:0] rs2_out, @@ -161,6 +165,7 @@ module rv32_decode ( always_ff @(posedge clk) begin if (!stall_in) begin + branch_predicted_taken_out <= branch_predicted_taken_in; valid_out <= valid; rs1_out <= rs1; rs2_out <= rs2; diff --git a/rv32_execute.sv b/rv32_execute.sv index 655abc7..1c5c18b 100644 --- a/rv32_execute.sv +++ b/rv32_execute.sv @@ -13,6 +13,7 @@ module rv32_execute ( input flush_in, /* control in */ + input branch_predicted_taken_in, input valid_in, input [4:0] rs1_in, input [4:0] rs2_in, @@ -50,6 +51,7 @@ module rv32_execute ( input [31:0] writeback_rd_value_in, /* control out */ + output logic branch_predicted_taken_out, output logic valid_out, output logic mem_read_out, output logic mem_write_out, @@ -147,6 +149,7 @@ module rv32_execute ( always_ff @(posedge clk) begin if (!stall_in) begin + branch_predicted_taken_out <= branch_predicted_taken_in; valid_out <= valid_in; mem_read_out <= mem_read_in; mem_write_out <= mem_write_in; diff --git a/rv32_fetch.sv b/rv32_fetch.sv index 4aeaecd..f2864ec 100644 --- a/rv32_fetch.sv +++ b/rv32_fetch.sv @@ -11,7 +11,7 @@ module rv32_fetch ( input flush_in, /* control in (from mem) */ - input branch_taken_in, + input branch_mispredicted_in, /* data in (from mem) */ input [31:0] branch_pc_in, @@ -19,9 +19,12 @@ module rv32_fetch ( /* data in (from memory bus) */ input [31:0] instr_read_value_in, - /* control out */ + /* control out (to memory bus) */ output logic instr_read_out, + /* control out */ + output logic branch_predicted_taken_out, + /* data out */ output logic [31:0] pc_out, output logic [31:0] instr_out, @@ -32,14 +35,45 @@ module rv32_fetch ( logic [31:0] next_pc; logic [31:0] pc; - assign pc = branch_taken_in ? branch_pc_in : next_pc; + logic sign; + logic [31:0] imm_j; + logic [31:0] imm_b; + logic [7:0] opcode; + + logic branch_predicted_taken; + logic [31:0] branch_offset; + + assign pc = branch_mispredicted_in ? branch_pc_in : next_pc; assign instr_read_out = 1; assign instr_address_out = pc; + assign sign = instr_read_value_in[31]; + assign imm_j = {{12{sign}}, instr_read_value_in[19:12], instr_read_value_in[20], instr_read_value_in[30:25], instr_read_value_in[24:21], 1'b0}; + assign imm_b = {{20{sign}}, instr_read_value_in[7], instr_read_value_in[30:25], instr_read_value_in[11:8], 1'b0}; + assign opcode = instr_read_value_in[7:0]; + + always_comb begin + case ({opcode, sign}) + {`RV32_OPCODE_JAL, 1'bx}: begin + branch_predicted_taken = 1; + branch_offset = imm_j; + end + {`RV32_OPCODE_BRANCH, 1'b1}: begin + branch_predicted_taken = 1; + branch_offset = imm_b; + end + default: begin + branch_predicted_taken = 0; + branch_offset = 32'd4; + end + endcase + end + always_ff @(posedge clk) begin if (!stall_in) begin + branch_predicted_taken_out <= branch_predicted_taken; instr_out <= instr_read_value_in; - next_pc <= pc + 4; + next_pc <= pc + branch_offset; pc_out <= pc; if (flush_in) diff --git a/rv32_hazard.sv b/rv32_hazard.sv index 6889080..826b60b 100644 --- a/rv32_hazard.sv +++ b/rv32_hazard.sv @@ -16,7 +16,7 @@ module rv32_hazard_unit ( input execute_mem_fence_in, - input mem_branch_taken_in, + input mem_branch_mispredicted_in, input instr_read_in, input instr_ready_in, @@ -56,10 +56,10 @@ module rv32_hazard_unit ( assign fetch_flush_out = 0; assign decode_stall_out = execute_stall_out; - assign decode_flush_out = fetch_stall_out || mem_branch_taken_in; + assign decode_flush_out = fetch_stall_out || mem_branch_mispredicted_in; assign execute_stall_out = mem_stall_out; - assign execute_flush_out = decode_stall_out || mem_branch_taken_in; + assign execute_flush_out = decode_stall_out || mem_branch_mispredicted_in; assign mem_stall_out = mem_wait_for_bus; assign mem_flush_out = execute_stall_out; diff --git a/rv32_mem.sv b/rv32_mem.sv index d522a31..9ddf7ab 100644 --- a/rv32_mem.sv +++ b/rv32_mem.sv @@ -15,6 +15,7 @@ module rv32_mem ( input flush_in, /* control in */ + input branch_predicted_taken_in, input valid_in, input read_in, input write_in, @@ -34,7 +35,7 @@ module rv32_mem ( /* control out */ output logic valid_out, - output logic branch_taken_out, + output logic branch_mispredicted_out, output logic [4:0] rd_out, output logic rd_write_out, @@ -54,13 +55,14 @@ module rv32_mem ( /* branch unit */ rv32_branch_unit branch_unit ( /* control in */ + .predicted_taken_in(branch_predicted_taken_in), .op_in(branch_op_in), /* data in */ .result_in(result_in), /* control out */ - .taken_out(branch_taken_out) + .mispredicted_out(branch_mispredicted_out) ); assign branch_pc_out = branch_pc_in; diff --git a/rv32_opcodes.sv b/rv32_opcodes.sv index e5f6462..1a23f8e 100644 --- a/rv32_opcodes.sv +++ b/rv32_opcodes.sv @@ -54,4 +54,7 @@ `define RV32_INSTR_NOP 32'bxxxxxxx_xxxxx_00000_xxx_00000_0010011 +`define RV32_OPCODE_JAL 7'b1101111 +`define RV32_OPCODE_BRANCH 7'b1100011 + `endif