diff --git a/if_stage.sv b/if_stage.sv index 69e6c48a..285b664f 100644 --- a/if_stage.sv +++ b/if_stage.sv @@ -111,9 +111,6 @@ module riscv_if_stage logic [31:0] fetch_rdata; logic [31:0] fetch_addr; - logic fetch_unaligned_valid; - logic [31:0] fetch_unaligned_rdata; - logic [31:0] instr_rdata_int; @@ -129,7 +126,6 @@ module riscv_if_stage if (unaligned) begin current_pc_if_o = {fetch_addr[31:2], 2'b10}; - instr_rdata_int = fetch_unaligned_rdata; end end @@ -195,14 +191,12 @@ module riscv_if_stage .branch_i ( branch_req ), .addr_i ( {fetch_addr_n[31:2], 2'b00} ), + .unaligned_i ( unaligned ), // is the current address unaligned? .ready_i ( fetch_ready ), .valid_o ( fetch_valid ), .rdata_o ( fetch_rdata ), .addr_o ( fetch_addr ), - .unaligned_valid_o ( fetch_unaligned_valid ), - .unaligned_rdata_o ( fetch_unaligned_rdata ), - // goes to instruction memory / instruction cache .instr_req_o ( instr_req_o ), .instr_addr_o ( instr_addr_o ), @@ -224,14 +218,12 @@ module riscv_if_stage .branch_i ( branch_req ), .addr_i ( {fetch_addr_n[31:2], 2'b00} ), + .unaligned_i ( unaligned ), // is the current address unaligned? .ready_i ( fetch_ready ), .valid_o ( fetch_valid ), .rdata_o ( fetch_rdata ), .addr_o ( fetch_addr ), - .unaligned_valid_o ( fetch_unaligned_valid ), - .unaligned_rdata_o ( fetch_unaligned_rdata ), - // goes to instruction memory / instruction cache .instr_req_o ( instr_req_o ), .instr_addr_o ( instr_addr_o ), @@ -304,26 +296,16 @@ module riscv_if_stage unaligned = 1'b1; if (fetch_valid) begin - if (is_compressed[1]) begin - valid = 1'b1; // an instruction is ready for ID stage + valid = 1'b1; // an instruction is ready for ID stage - if (req_i && if_valid_o) begin - // next instruction will be aligned - fetch_ready = 1'b1; + if (req_i && if_valid_o) begin + // next instruction will be aligned + fetch_ready = 1'b1; + + if (is_compressed[1]) offset_fsm_ns = WAIT_ALIGNED; - end - end else begin - // not compressed, we are looking at a 32 bit instruction - - if (fetch_unaligned_valid) begin - valid = 1'b1; // an instruction is ready for ID stage - - if (req_i && if_valid_o) begin - // next instruction will be unaligned - fetch_ready = 1'b1; - offset_fsm_ns = WAIT_UNALIGNED; - end - end + else + offset_fsm_ns = WAIT_UNALIGNED; end end end diff --git a/prefetch_L0_buffer.sv b/prefetch_L0_buffer.sv index 9fffc2d7..46dc0599 100644 --- a/prefetch_L0_buffer.sv +++ b/prefetch_L0_buffer.sv @@ -40,8 +40,7 @@ module riscv_prefetch_L0_buffer output logic [31:0] rdata_o, output logic [31:0] addr_o, - output logic unaligned_valid_o, - output logic [31:0] unaligned_rdata_o, + input logic unaligned_i, // goes to instruction memory / instruction cache output logic instr_req_o, @@ -67,6 +66,10 @@ module riscv_prefetch_L0_buffer logic ready_L0; logic is_prefetch_q, is_prefetch_n; + // prepared data for output + logic [31:0] rdata, unaligned_rdata; + logic valid, unaligned_valid; + assign busy_o = (CS != EMPTY && CS != VALID_L0) || instr_req_o; @@ -112,7 +115,7 @@ module riscv_prefetch_L0_buffer always_comb begin - valid_o = 1'b0; + valid = 1'b0; valid_L0 = 1'b0; pointer_ns = pointer_cs; instr_req_o = 1'b0; @@ -165,7 +168,7 @@ module riscv_prefetch_L0_buffer end else // else (branch_i) begin - valid_o = instr_rvalid_i; + valid = instr_rvalid_i; // prepare address even if we don't need it // this removes the dependency for instr_addr_o on instr_rvalid_i @@ -206,7 +209,7 @@ module riscv_prefetch_L0_buffer VALID_L0: begin - valid_o = 1'b1; + valid = 1'b1; valid_L0 = 1'b1; if (branch_i) @@ -308,41 +311,41 @@ module riscv_prefetch_L0_buffer begin if (is_prefetch_q) begin - rdata_o = previous_chunk; + rdata = previous_chunk; addr_o = { last_address[31:4], 2'b11, 2'b00 }; end else begin if (valid_L0) begin - rdata_o = L0_buffer[pointer_cs]; + rdata = L0_buffer[pointer_cs]; addr_o = { current_address[31:4], pointer_cs, 2'b00 }; end else begin - rdata_o = instr_rdata_i[pointer_cs]; + rdata = instr_rdata_i[pointer_cs]; addr_o = { current_address[31:4], pointer_cs, 2'b00 }; end end end - // the lower part of unaligned_rdata_o is always the higher part of rdata_o - assign unaligned_rdata_o[15:0] = rdata_o[31:16]; + // the lower part of unaligned_rdata is always the higher part of rdata + assign unaligned_rdata[15:0] = rdata[31:16]; always_comb begin if (valid_L0) begin case(addr_o[3:2]) - 2'b00: begin unaligned_rdata_o[31:16] = L0_buffer[1][15:0]; unaligned_valid_o = 1'b1; end - 2'b01: begin unaligned_rdata_o[31:16] = L0_buffer[2][15:0]; unaligned_valid_o = 1'b1; end - 2'b10: begin unaligned_rdata_o[31:16] = L0_buffer[3][15:0]; unaligned_valid_o = 1'b1; end + 2'b00: begin unaligned_rdata[31:16] = L0_buffer[1][15:0]; unaligned_valid = 1'b1; end + 2'b01: begin unaligned_rdata[31:16] = L0_buffer[2][15:0]; unaligned_valid = 1'b1; end + 2'b10: begin unaligned_rdata[31:16] = L0_buffer[3][15:0]; unaligned_valid = 1'b1; end // this state is only interesting if we have already done a prefetch 2'b11: begin - unaligned_rdata_o[31:16] = L0_buffer[0][15:0]; + unaligned_rdata[31:16] = L0_buffer[0][15:0]; if (is_prefetch_q) begin - unaligned_valid_o = 1'b1; + unaligned_valid = 1'b1; end else begin - unaligned_valid_o = 1'b0; + unaligned_valid = 1'b0; end end endcase // addr_o @@ -351,18 +354,18 @@ module riscv_prefetch_L0_buffer // icache case(addr_o[3:2]) - 2'b00: begin unaligned_rdata_o[31:16] = instr_rdata_i[1][15:0]; unaligned_valid_o = instr_rvalid_i; end - 2'b01: begin unaligned_rdata_o[31:16] = instr_rdata_i[2][15:0]; unaligned_valid_o = instr_rvalid_i; end - 2'b10: begin unaligned_rdata_o[31:16] = instr_rdata_i[3][15:0]; unaligned_valid_o = instr_rvalid_i; end + 2'b00: begin unaligned_rdata[31:16] = instr_rdata_i[1][15:0]; unaligned_valid = instr_rvalid_i; end + 2'b01: begin unaligned_rdata[31:16] = instr_rdata_i[2][15:0]; unaligned_valid = instr_rvalid_i; end + 2'b10: begin unaligned_rdata[31:16] = instr_rdata_i[3][15:0]; unaligned_valid = instr_rvalid_i; end 2'b11: begin - unaligned_rdata_o[31:16] = instr_rdata_i[0][15:0]; + unaligned_rdata[31:16] = instr_rdata_i[0][15:0]; if (is_prefetch_q) - unaligned_valid_o = instr_rvalid_i; + unaligned_valid = instr_rvalid_i; else - unaligned_valid_o = 1'b0; + unaligned_valid = 1'b0; end endcase // pointer_cs end @@ -394,4 +397,11 @@ module riscv_prefetch_L0_buffer end end + ////////////////////////////////////////////////////////////////////////////// + // instruction aligner (if unaligned) + ////////////////////////////////////////////////////////////////////////////// + + assign rdata_o = unaligned_i ? unaligned_rdata : rdata; + assign valid_o = unaligned_i ? unaligned_valid : valid; + endmodule // prefetch_L0_buffer diff --git a/prefetch_buffer.sv b/prefetch_buffer.sv index 94e28241..5c0c249e 100644 --- a/prefetch_buffer.sv +++ b/prefetch_buffer.sv @@ -198,6 +198,7 @@ module riscv_prefetch_buffer input logic clk, input logic rst_n, + input logic unaligned_i, input logic req_i, input logic branch_i, input logic ready_i, @@ -207,9 +208,6 @@ module riscv_prefetch_buffer output logic [31:0] rdata_o, output logic [31:0] addr_o, - output logic unaligned_valid_o, - output logic [31:0] unaligned_rdata_o, - // goes to instruction memory / instruction cache output logic instr_req_o, output logic [31:0] instr_addr_o, @@ -232,6 +230,9 @@ module riscv_prefetch_buffer logic fifo_rdata_valid; logic fifo_rdata_ready; + logic [31:0] rdata, unaligned_rdata; + logic valid, unaligned_valid; + ////////////////////////////////////////////////////////////////////////////// // prefetch buffer status ////////////////////////////////////////////////////////////////////////////// @@ -266,15 +267,22 @@ module riscv_prefetch_buffer .in_rdata_ready_o ( fifo_rdata_ready ), .in_rdata_i ( instr_rdata_i ), - .out_valid_o ( valid_o ), + .out_valid_o ( valid ), .out_ready_i ( ready_i ), - .out_rdata_o ( rdata_o ), + .out_rdata_o ( rdata ), .out_addr_o ( addr_o ), - .out_unaligned_valid_o ( unaligned_valid_o ), - .out_unaligned_rdata_o ( unaligned_rdata_o ) + .out_unaligned_valid_o ( unaligned_valid ), + .out_unaligned_rdata_o ( unaligned_rdata ) ); + ////////////////////////////////////////////////////////////////////////////// + // instruction aligner (if unaligned) + ////////////////////////////////////////////////////////////////////////////// + + assign rdata_o = unaligned_i ? unaligned_rdata : rdata; + assign valid_o = unaligned_i ? unaligned_valid : valid; + ////////////////////////////////////////////////////////////////////////////// // instruction fetch FSM