diff --git a/doc/instruction_fetch.rst b/doc/instruction_fetch.rst index afd76908..4ab6a368 100644 --- a/doc/instruction_fetch.rst +++ b/doc/instruction_fetch.rst @@ -4,10 +4,7 @@ Instruction Fetch ================= The Instruction-Fetch (IF) stage of the core is able to supply one instruction to the Instruction-Decode (ID) stage per cycle if the instruction cache or the instruction memory is able to serve one instruction per cycle. -The instruction address must be half-word-aligned due to the support of compressed instructions. -It is not possible to jump to instruction addresses that have the LSB bit set. - -For optimal performance and timing closure reasons, a prefetcher is used which fetches instruction from the instruction memory, or instruction cache. +For optimal performance and timing closure reasons, a prefetcher is used which fetches instructions from the instruction memory, or instruction cache. The following table describes the signals that are used to fetch instructions. This interface is a simplified version of the interface used on the data interface as described in :ref:`load-store-unit`. @@ -21,7 +18,7 @@ The main difference is that the instruction interface does not allow for writes | ``instr_req_o`` | output | Request valid, must stay high until | | | | ``instr_gnt_i`` is high for one cycle | +-------------------------+-----------+-----------------------------------------------+ -| ``instr_addr_o[31:0]`` | output | Address | +| ``instr_addr_o[31:0]`` | output | Address, word aligned | +-------------------------+-----------+-----------------------------------------------+ | ``instr_gnt_i`` | input | The other side accepted the request. | | | | ``instr_req_o`` may be deasserted in the next | @@ -35,6 +32,15 @@ The main difference is that the instruction interface does not allow for writes +-------------------------+-----------+-----------------------------------------------+ +Misaligned Accesses +------------------- + +Externally, the IF interface performs word-aligned instruction fetches only. +Misaligned instruction fetches are handled by performing two separate word-aligned instruction fetches. +Internally, the core can deal with both word- and half-word-aligned instruction addresses to support compressed instructions. +The LSB of the instruction address is ignored internally. + + Protocol -------- diff --git a/rtl/ibex_prefetch_buffer.sv b/rtl/ibex_prefetch_buffer.sv index b1b928ba..bef2d17b 100644 --- a/rtl/ibex_prefetch_buffer.sv +++ b/rtl/ibex_prefetch_buffer.sv @@ -54,6 +54,7 @@ module ibex_prefetch_buffer ( pf_fsm_e pf_fsm_cs, pf_fsm_ns; logic [31:0] instr_addr_q, fetch_addr; + logic [31:0] instr_addr, instr_addr_w_aligned; logic addr_valid; logic fifo_valid; @@ -103,20 +104,20 @@ module ibex_prefetch_buffer ( ////////////////////////////////////////////////////////////////////////////// always_comb begin - instr_req_o = 1'b0; - instr_addr_o = fetch_addr; - fifo_valid = 1'b0; - addr_valid = 1'b0; - pf_fsm_ns = pf_fsm_cs; + instr_req_o = 1'b0; + instr_addr = fetch_addr; + fifo_valid = 1'b0; + addr_valid = 1'b0; + pf_fsm_ns = pf_fsm_cs; unique case(pf_fsm_cs) // default state, not waiting for requested data IDLE: begin - instr_addr_o = fetch_addr; - instr_req_o = 1'b0; + instr_addr = fetch_addr; + instr_req_o = 1'b0; if (branch_i) begin - instr_addr_o = addr_i; + instr_addr = addr_i; end if (req_i && (fifo_ready || branch_i )) begin @@ -131,12 +132,12 @@ module ibex_prefetch_buffer ( // we sent a request but did not yet get a grant WAIT_GNT: begin - instr_addr_o = instr_addr_q; - instr_req_o = 1'b1; + instr_addr = instr_addr_q; + instr_req_o = 1'b1; if (branch_i) begin - instr_addr_o = addr_i; - addr_valid = 1'b1; + instr_addr = addr_i; + addr_valid = 1'b1; end //~> granted request or not @@ -145,10 +146,10 @@ module ibex_prefetch_buffer ( // we wait for rvalid, after that we are ready to serve a new request WAIT_RVALID: begin - instr_addr_o = fetch_addr; + instr_addr = fetch_addr; if (branch_i) begin - instr_addr_o = addr_i; + instr_addr = addr_i; end if (req_i && (fifo_ready || branch_i)) begin @@ -183,15 +184,15 @@ module ibex_prefetch_buffer ( // there was no new request sent yet // we assume that req_i is set to high WAIT_ABORTED: begin - instr_addr_o = instr_addr_q; + instr_addr = instr_addr_q; if (branch_i) begin - instr_addr_o = addr_i; - addr_valid = 1'b1; + instr_addr = addr_i; + addr_valid = 1'b1; end if (instr_rvalid_i) begin - instr_req_o = 1'b1; + instr_req_o = 1'b1; // no need to send address, already done in WAIT_RVALID //~> granted request or not @@ -217,9 +218,15 @@ module ibex_prefetch_buffer ( pf_fsm_cs <= pf_fsm_ns; if (addr_valid) begin - instr_addr_q <= instr_addr_o; + instr_addr_q <= instr_addr; end end end + ///////////////// + // Output Addr // + ///////////////// + assign instr_addr_w_aligned = {instr_addr[31:2], 2'b00}; + assign instr_addr_o = instr_addr_w_aligned; + endmodule