Make sure the prefetcher works with any kind of stalls on data and

instruction RAM access
This commit is contained in:
Andreas Traber 2016-02-19 10:41:55 +01:00
parent f46dbaefad
commit cc82192e45

View file

@ -29,62 +29,58 @@ module riscv_fetch_fifo
input logic rst_n, input logic rst_n,
// control signals // control signals
input logic branch_i, // clears the contents of the fifo input logic clear_i, // clears the contents of the fifo
input logic [31:0] addr_i,
input logic hwlp_i, // tries to insert an entry above the first one
input logic [31:0] hwlp_target_i,
// input port // input port
input logic in_addr_valid_i, input logic [31:0] in_addr_i,
output logic in_addr_ready_o,
output logic [31:0] in_fetch_addr_o,
input logic in_wait_gnt_i,
input logic in_rdata_valid_i,
output logic in_rdata_ready_o,
input logic [31:0] in_rdata_i, input logic [31:0] in_rdata_i,
input logic in_valid_i,
output logic in_ready_o,
input logic in_replace2_i, // replaces second entry if there is one: "to be served after this instr"
input logic in_is_hwlp_i,
// output port // output port
output logic out_valid_o, output logic out_valid_o,
input logic out_ready_i, input logic out_ready_i,
output logic [31:0] out_rdata_o, output logic [31:0] out_rdata_o,
output logic [31:0] out_addr_o, output logic [31:0] out_addr_o,
output logic out_valid_stored_o, // same as out_valid_o, except that if something is incoming now it is not included. This signal is available immediately as it comes directly out of FFs
output logic out_is_hwlp_o output logic out_is_hwlp_o
); );
localparam DEPTH = 3; // must be 2 or greater localparam DEPTH = 4; // must be 3 or greater
// index 0 is used for output // index 0 is used for output
logic [0:DEPTH-1] [31:0] addr_n, addr_int, addr_Q; logic [0:DEPTH-1] [31:0] addr_n, addr_int, addr_Q;
logic [0:DEPTH-1] addr_valid_n, addr_valid_int, addr_valid_Q; logic [0:DEPTH-1] [31:0] rdata_n, rdata_int, rdata_Q;
logic [0:DEPTH-1] [31:0] rdata_n, rdata_int, rdata_Q; logic [0:DEPTH-1] valid_n, valid_int, valid_Q;
logic [0:DEPTH-1] rdata_valid_n, rdata_valid_int, rdata_valid_Q; logic [0:1 ] is_hwlp_n, is_hwlp_int, is_hwlp_Q;
logic [0:1 ] is_hwlp_n, is_hwlp_int, is_hwlp_Q;
logic [31:0] addr_next;
logic [31:0] rdata, rdata_unaligned; logic [31:0] rdata, rdata_unaligned;
logic valid, valid_unaligned; logic valid, valid_unaligned;
logic aligned_is_compressed, unaligned_is_compressed; logic aligned_is_compressed, unaligned_is_compressed;
logic aligned_is_compressed_st, unaligned_is_compressed_st;
logic [31:0] fifo_last_addr;
logic hwlp_inbound;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// output port // output port
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
assign rdata = (rdata_valid_Q[0]) ? rdata_Q[0] : in_rdata_i; assign rdata = (valid_Q[0]) ? rdata_Q[0] : in_rdata_i;
assign valid = (rdata_valid_Q[0] || (addr_valid_Q[0] && in_rdata_valid_i)); assign valid = valid_Q[0] || in_valid_i || is_hwlp_Q[1];
assign rdata_unaligned = (rdata_valid_Q[1]) ? {rdata_Q[1][15:0], rdata[31:16]} : {in_rdata_i[15:0], rdata[31:16]}; assign rdata_unaligned = (valid_Q[1]) ? {rdata_Q[1][15:0], rdata[31:16]} : {in_rdata_i[15:0], rdata[31:16]};
// it is implied that rdata_valid_Q[0] is set // it is implied that rdata_valid_Q[0] is set
assign valid_unaligned = (rdata_valid_Q[1] || (addr_valid_Q[1] && in_rdata_valid_i)); assign valid_unaligned = (valid_Q[1] || (valid_Q[0] && in_valid_i));
assign unaligned_is_compressed = rdata[17:16] != 2'b11; assign unaligned_is_compressed = rdata[17:16] != 2'b11;
assign aligned_is_compressed = rdata[1:0] != 2'b11; assign aligned_is_compressed = rdata[1:0] != 2'b11;
assign unaligned_is_compressed_st = rdata_Q[0][17:16] != 2'b11;
assign aligned_is_compressed_st = rdata_Q[0][1:0] != 2'b11;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// instruction aligner (if unaligned) // instruction aligner (if unaligned)
@ -110,60 +106,35 @@ module riscv_fetch_fifo
end end
end end
assign out_addr_o = addr_Q[0]; // always output addr directly since we sent it one cycle earlier to the FIFO assign out_addr_o = (valid_Q[0]) ? addr_Q[0] : in_addr_i;
assign out_is_hwlp_o = is_hwlp_Q[0]; assign out_is_hwlp_o = (valid_Q[0]) ? is_hwlp_Q[0] : in_is_hwlp_i;
// this valid signal must not depend on signals from outside!
always_comb
begin
out_valid_stored_o = 1'b1;
if (out_addr_o[1] && (~is_hwlp_Q[1])) begin
if (unaligned_is_compressed_st)
out_valid_stored_o = 1'b1;
else
out_valid_stored_o = valid_Q[1];
end else begin
out_valid_stored_o = valid_Q[0];
end
end
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// input port // input port
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// we accept addresses as long as our fifo is not full or we encounter
// a branch or hwloop
assign in_addr_ready_o = branch_i || (hwlp_i & (~is_hwlp_Q[1])) || (~addr_valid_Q[DEPTH-1]);
// we accept data as long as our fifo is not full // we accept data as long as our fifo is not full
// we don't care about clear here as the data will be received one cycle // we don't care about clear here as the data will be received one cycle
// later anyway // later anyway
assign in_rdata_ready_o = ~rdata_valid_Q[DEPTH-1]; assign in_ready_o = ~valid_Q[DEPTH-2];
// output the latest valid address we got
int i;
always_comb
begin
fifo_last_addr = addr_Q[0];
for(i = 1; i < DEPTH; i++) begin
if (addr_valid_Q[i])
fifo_last_addr = addr_Q[i];
end
end
always_comb
begin
in_fetch_addr_o = {fifo_last_addr[31:2], 2'b00} + 32'd4;
if (in_wait_gnt_i) begin
in_fetch_addr_o = {fifo_last_addr[31:2], 2'b00};
if (hwlp_i & (~is_hwlp_Q[1]) & rdata_valid_Q[0])
in_fetch_addr_o = hwlp_target_i;
end else begin
if (hwlp_i & (~is_hwlp_Q[1]))
in_fetch_addr_o = hwlp_target_i;
end
// branches have priority since the fifo is cleared
if (branch_i)
in_fetch_addr_o = addr_i;
end
// accept hwloop input as long as our second entry is not already one and we
// are valid, otherwise we might loose a part of an instruction
assign hwlp_inbound = hwlp_i & (~is_hwlp_Q[1]) & out_valid_o;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// FIFO management // FIFO management
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -171,106 +142,82 @@ module riscv_fetch_fifo
int j; int j;
always_comb always_comb
begin begin
addr_int = addr_Q; addr_int = addr_Q;
addr_valid_int = addr_valid_Q; rdata_int = rdata_Q;
is_hwlp_int = is_hwlp_Q; valid_int = valid_Q;
is_hwlp_int = is_hwlp_Q;
if (in_addr_valid_i && in_addr_ready_o) begin if (in_valid_i) begin
for(j = 0; j < DEPTH; j++) begin for(j = 0; j < DEPTH; j++) begin
if (~addr_valid_Q[j]) begin if (~valid_Q[j]) begin
addr_int[j] = in_fetch_addr_o; addr_int[j] = in_addr_i;
addr_valid_int[j] = 1'b1; rdata_int[j] = in_rdata_i;
valid_int[j] = 1'b1;
break; break;
end end
end end
end
// on a hardware loop invalidate everything starting from the second entry // replace 2nd entry
if (hwlp_inbound) begin if (in_replace2_i) begin
addr_int[1] = in_fetch_addr_o; if (valid_Q[0]) begin
addr_valid_int[1] = 1'b1; addr_int[1] = in_addr_i;
addr_valid_int[2:DEPTH-1] = '0;
is_hwlp_int[1] = 1'b1;
end
end
int k; // if we replace the 2nd entry, let's cache the output word in case we
always_comb // still need it and it would span two words in the FIFO
begin rdata_int[0] = out_rdata_o;
rdata_int = rdata_Q; rdata_int[1] = in_rdata_i;
rdata_valid_int = rdata_valid_Q; valid_int[1] = 1'b1;
valid_int[2:DEPTH-1] = '0;
if (in_rdata_valid_i && in_rdata_ready_o) begin // hardware loop incoming?
for(k = 0; k < DEPTH; k++) begin is_hwlp_int[1] = in_is_hwlp_i;
if (~rdata_valid_Q[k]) begin end else begin
rdata_int[k] = in_rdata_i; is_hwlp_int[0] = in_is_hwlp_i;
rdata_valid_int[k] = 1'b1;
break;
end end
end end
end end
// on a hardware loop invalidate everything starting from the second entry
if (hwlp_inbound) begin
rdata_int[0] = out_rdata_o; // save current output in rdata_int[0], so that we have it available even though we override entry #1
rdata_valid_int[1:DEPTH-1] = '0;
end
end end
assign addr_next = {addr_int[0][31:2], 2'b00} + 32'h4;
// move everything by one step // move everything by one step
always_comb always_comb
begin begin
addr_n = addr_int; addr_n = addr_int;
addr_valid_n = addr_valid_int; rdata_n = rdata_int;
rdata_n = rdata_int; valid_n = valid_int;
rdata_valid_n = rdata_valid_int; is_hwlp_n = is_hwlp_int;
is_hwlp_n = is_hwlp_int;
if (out_ready_i && out_valid_o) begin if (out_ready_i && out_valid_o) begin
is_hwlp_n = {is_hwlp_int[1], 1'b0};
// now take care of the addresses
if (is_hwlp_int[1]) begin if (is_hwlp_int[1]) begin
// hardware loop found in second entry addr_n[0] = addr_int[1][31:0];
addr_n = {addr_int[1][31:0], addr_int[2:DEPTH-1], 32'b0}; rdata_n = {rdata_int[1:DEPTH-1], 32'b0};
addr_valid_n = {addr_valid_int[1:DEPTH-1], 1'b0}; valid_n = {valid_int[1:DEPTH-1], 1'b0};
rdata_n = {rdata_int[1:DEPTH-1], 32'b0};
rdata_valid_n = {rdata_valid_int[1:DEPTH-1], 1'b0};
is_hwlp_n = {is_hwlp_int[1], 1'b0};
end else begin end else begin
// no hardware loop found if (addr_int[0][1]) begin
if (addr_Q[0][1]) begin
// unaligned case // unaligned case
if (unaligned_is_compressed) begin if (unaligned_is_compressed) begin
addr_n = {{addr_int[1][31:2], 2'b00}, addr_int[2:DEPTH-1], 32'b0}; addr_n[0] = {addr_next[31:2], 2'b00};
end else begin end else begin
addr_n = {{addr_int[1][31:2], 2'b10}, addr_int[2:DEPTH-1], 32'b0}; addr_n[0] = {addr_next[31:2], 2'b10};
end end
addr_valid_n = {addr_valid_int[1:DEPTH-1], 1'b0}; rdata_n = {rdata_int[1:DEPTH-1], 32'b0};
rdata_n = {rdata_int[1:DEPTH-1], 32'b0}; valid_n = {valid_int[1:DEPTH-1], 1'b0};
rdata_valid_n = {rdata_valid_int[1:DEPTH-1], 1'b0};
is_hwlp_n = {is_hwlp_int[1], 1'b0};
end else begin end else begin
// aligned case // aligned case
if (aligned_is_compressed) begin if (aligned_is_compressed) begin
// just increase address, do not move to next entry in FIFO // just increase address, do not move to next entry in FIFO
addr_n[0] = {addr_int[0][31:2], 2'b10}; addr_n[0] = {addr_int[0][31:2], 2'b10};
is_hwlp_n[0] = 1'b0; // invalidate hwlp bit for current address
end else begin end else begin
// move to next entry in FIFO // move to next entry in FIFO
addr_n = {{addr_int[1][31:2], 2'b00}, addr_int[2:DEPTH-1], 32'b0}; addr_n[0] = {addr_next[31:2], 2'b00};
addr_valid_n = {addr_valid_int[1:DEPTH-1], 1'b0}; rdata_n = {rdata_int[1:DEPTH-1], 32'b0};
rdata_n = {rdata_int[1:DEPTH-1], 32'b0}; valid_n = {valid_int[1:DEPTH-1], 1'b0};
rdata_valid_n = {rdata_valid_int[1:DEPTH-1], 1'b0};
is_hwlp_n = {is_hwlp_int[1], 1'b0};
end end
end end
end end
end end
@ -284,35 +231,38 @@ module riscv_fetch_fifo
begin begin
if(rst_n == 1'b0) if(rst_n == 1'b0)
begin begin
addr_Q <= '{default: '0}; addr_Q <= '{default: '0};
addr_valid_Q <= '0; rdata_Q <= '{default: '0};
rdata_Q <= '{default: '0}; valid_Q <= '0;
rdata_valid_Q <= '0; is_hwlp_Q <= '0;
is_hwlp_Q <= '0;
end end
else else
begin begin
// on a clear signal from outside we invalidate the content of the FIFO // on a clear signal from outside we invalidate the content of the FIFO
// completely and start from an empty state // completely and start from an empty state
if (branch_i) begin if (clear_i) begin
addr_Q[0] <= in_fetch_addr_o; valid_Q <= '0;
addr_valid_Q <= {in_addr_valid_i, {DEPTH-1{1'b0}}}; is_hwlp_Q <= '0;
rdata_valid_Q <= '0;
is_hwlp_Q <= '0;
end else begin end else begin
addr_Q <= addr_n; addr_Q <= addr_n;
addr_valid_Q <= addr_valid_n; rdata_Q <= rdata_n;
rdata_Q <= rdata_n; valid_Q <= valid_n;
rdata_valid_Q <= rdata_valid_n; is_hwlp_Q <= is_hwlp_n;
is_hwlp_Q <= is_hwlp_n;
end end
end end
end end
//----------------------------------------------------------------------------
// Assertions
//----------------------------------------------------------------------------
// check for FIFO overflows
assert property (
@(posedge clk) (in_valid_i) |-> ((valid_Q[DEPTH-1] == 1'b0) || (clear_i == 1'b1) || (in_replace2_i == 1'b1)) );
endmodule endmodule
// branch_i deletes everything up to now, i.e. it assumes that addr_i now has
// the correct state and uses the current cycle's addr_i to fetch new data
module riscv_prefetch_buffer module riscv_prefetch_buffer
( (
input logic clk, input logic clk,
@ -334,26 +284,29 @@ module riscv_prefetch_buffer
// goes to instruction memory / instruction cache // goes to instruction memory / instruction cache
output logic instr_req_o, output logic instr_req_o,
output logic [31:0] instr_addr_o,
input logic instr_gnt_i, input logic instr_gnt_i,
input logic instr_rvalid_i, output logic [31:0] instr_addr_o,
input logic [31:0] instr_rdata_i, input logic [31:0] instr_rdata_i,
input logic instr_rvalid_i,
// Prefetch Buffer Status // Prefetch Buffer Status
output logic busy_o output logic busy_o
); );
enum logic [1:0] {IDLE, WAIT_GNT, WAIT_RVALID, WAIT_ABORTED } CS, NS; enum logic [1:0] {IDLE, WAIT_GNT, WAIT_RVALID, WAIT_ABORTED } CS, NS;
enum logic [1:0] {HWLP_NONE, HWLP_IN, HWLP_FETCHING, HWLP_DONE } hwlp_CS, hwlp_NS;
logic [31:0] fetch_addr; logic [31:0] instr_addr_q, fetch_addr;
logic fetch_is_hwlp;
logic addr_valid;
logic fifo_addr_valid; logic fifo_valid;
logic fifo_addr_ready; logic fifo_ready;
logic fifo_clear;
logic fifo_hwlp;
logic fifo_rdata_valid; logic valid_stored;
logic fifo_rdata_ready; logic hwlp_masked;
logic wait_gnt;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -372,29 +325,95 @@ module riscv_prefetch_buffer
.clk ( clk ), .clk ( clk ),
.rst_n ( rst_n ), .rst_n ( rst_n ),
.branch_i ( branch_i ), .clear_i ( fifo_clear ),
.addr_i ( addr_i ),
.hwlp_i ( hwloop_i ), .in_addr_i ( instr_addr_q ),
.hwlp_target_i ( hwloop_target_i ),
.in_addr_valid_i ( fifo_addr_valid ),
.in_addr_ready_o ( fifo_addr_ready ),
.in_fetch_addr_o ( fetch_addr ),
.in_wait_gnt_i ( wait_gnt ),
.in_rdata_valid_i ( fifo_rdata_valid ),
.in_rdata_ready_o ( fifo_rdata_ready ),
.in_rdata_i ( instr_rdata_i ), .in_rdata_i ( instr_rdata_i ),
.in_valid_i ( fifo_valid ),
.in_ready_o ( fifo_ready ),
.in_replace2_i ( fifo_hwlp ),
.in_is_hwlp_i ( fifo_hwlp ),
.out_valid_o ( valid_o ), .out_valid_o ( valid_o ),
.out_ready_i ( ready_i ), .out_ready_i ( ready_i ),
.out_rdata_o ( rdata_o ), .out_rdata_o ( rdata_o ),
.out_addr_o ( addr_o ), .out_addr_o ( addr_o ),
.out_valid_stored_o ( valid_stored ),
.out_is_hwlp_o ( is_hwlp_o ) .out_is_hwlp_o ( is_hwlp_o )
); );
//////////////////////////////////////////////////////////////////////////////
// fetch addr
//////////////////////////////////////////////////////////////////////////////
assign fetch_addr = {instr_addr_q[31:2], 2'b00} + 32'd4;
always_comb
begin
hwlp_NS = hwlp_CS;
fifo_hwlp = 1'b0;
hwlp_masked = 1'b0;
fifo_clear = 1'b0;
unique case (hwlp_CS)
HWLP_NONE: begin
if (hwloop_i) begin
hwlp_masked = 1'b1;
if (fetch_is_hwlp)
hwlp_NS = HWLP_FETCHING;
else
hwlp_NS = HWLP_IN;
if (ready_i)
fifo_clear = 1'b1;
end
end
HWLP_IN: begin
hwlp_masked = 1'b1;
if (fetch_is_hwlp)
hwlp_NS = HWLP_FETCHING;
if (ready_i)
fifo_clear = 1'b1;
end
// just waiting for rvalid really
HWLP_FETCHING: begin
fifo_hwlp = 1'b1;
if (instr_rvalid_i & (CS != WAIT_ABORTED)) begin
if (valid_o & is_hwlp_o)
hwlp_NS = HWLP_NONE;
else
hwlp_NS = HWLP_DONE;
end else begin
if (ready_i)
fifo_clear = 1'b1;
end
end
HWLP_DONE: begin
if (valid_o & is_hwlp_o)
hwlp_NS = HWLP_NONE;
end
default: begin
hwlp_NS = HWLP_NONE;
end
endcase
if (branch_i) begin
hwlp_NS = HWLP_NONE;
fifo_clear = 1'b1;
end
end
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// instruction fetch FSM // instruction fetch FSM
// deals with instruction memory / instruction cache // deals with instruction memory / instruction cache
@ -402,28 +421,37 @@ module riscv_prefetch_buffer
always_comb always_comb
begin begin
wait_gnt = 1'b0; instr_req_o = 1'b0;
instr_req_o = 1'b0; instr_addr_o = fetch_addr;
instr_addr_o = fetch_addr; fifo_valid = 1'b0;
fifo_addr_valid = 1'b0; addr_valid = 1'b0;
fifo_rdata_valid = 1'b0; fetch_is_hwlp = 1'b0;
NS = CS; NS = CS;
unique case(CS) unique case(CS)
// default state, not waiting for requested data // default state, not waiting for requested data
IDLE: IDLE:
begin begin
instr_req_o = 1'b0; instr_addr_o = fetch_addr;
instr_req_o = 1'b0;
if ((req_i && fifo_addr_ready) || branch_i) begin if (branch_i)
instr_addr_o = addr_i;
else if(hwlp_masked & valid_stored)
instr_addr_o = hwloop_target_i;
if (req_i & (fifo_ready | branch_i | (hwlp_masked & valid_stored))) begin
instr_req_o = 1'b1; instr_req_o = 1'b1;
addr_valid = 1'b1;
fifo_addr_valid = 1'b1; if (hwlp_masked & valid_stored) begin
fetch_is_hwlp = 1'b1;
end
if(instr_gnt_i) //~> granted request if(instr_gnt_i) //~> granted request
NS = WAIT_RVALID; NS = WAIT_RVALID;
else begin //~> got a request but no grant else begin //~> got a request but no grant
NS = WAIT_GNT; NS = WAIT_GNT;
end end
end end
end // case: IDLE end // case: IDLE
@ -431,11 +459,16 @@ module riscv_prefetch_buffer
// we sent a request but did not yet get a grant // we sent a request but did not yet get a grant
WAIT_GNT: WAIT_GNT:
begin begin
wait_gnt = 1'b1; instr_addr_o = instr_addr_q;
instr_req_o = 1'b1; instr_req_o = 1'b1;
if (branch_i) begin if (branch_i) begin
fifo_addr_valid = 1'b1; instr_addr_o = addr_i;
addr_valid = 1'b1;
end else if (hwlp_masked & valid_stored) begin
instr_addr_o = hwloop_target_i;
addr_valid = 1'b1;
fetch_is_hwlp = 1'b1;
end end
if(instr_gnt_i) if(instr_gnt_i)
@ -446,36 +479,48 @@ module riscv_prefetch_buffer
// we wait for rvalid, after that we are ready to serve a new request // we wait for rvalid, after that we are ready to serve a new request
WAIT_RVALID: begin WAIT_RVALID: begin
instr_addr_o = fetch_addr;
if ((req_i && fifo_addr_ready) || branch_i) begin if (branch_i)
instr_addr_o = addr_i;
else if (hwlp_masked)
instr_addr_o = hwloop_target_i;
if (req_i & (fifo_ready | branch_i | hwlp_masked)) begin
// prepare for next request // prepare for next request
if (instr_rvalid_i) begin if (instr_rvalid_i) begin
instr_req_o = 1'b1; instr_req_o = 1'b1;
fifo_rdata_valid = 1'b1; fifo_valid = 1'b1;
fifo_addr_valid = 1'b1; addr_valid = 1'b1;
if (hwlp_masked) begin
fetch_is_hwlp = 1'b1;
end
if (instr_gnt_i) begin if (instr_gnt_i) begin
NS = WAIT_RVALID; NS = WAIT_RVALID;
end else begin end else begin
NS = WAIT_GNT; NS = WAIT_GNT;
end end
end else begin end else begin
// we are requested to abort our current request // we are requested to abort our current request
// we didn't get an rvalid yet, so wait for it // we didn't get an rvalid yet, so wait for it
if (branch_i) begin if (branch_i) begin
fifo_addr_valid = 1'b1; addr_valid = 1'b1;
NS = WAIT_ABORTED; NS = WAIT_ABORTED;
end else if (hwloop_i & valid_o) begin end else if (hwlp_masked & valid_o) begin
NS = WAIT_ABORTED; addr_valid = 1'b1;
fetch_is_hwlp = 1'b1;
NS = WAIT_ABORTED;
end end
end end
end else begin end else begin
// just wait for rvalid and go back to IDLE, no new request // just wait for rvalid and go back to IDLE, no new request
if (instr_rvalid_i) begin if (instr_rvalid_i) begin
fifo_rdata_valid = 1'b1; fifo_valid = 1'b1;
NS = IDLE; NS = IDLE;
end end
end end
end // case: WAIT_RVALID end // case: WAIT_RVALID
@ -484,16 +529,21 @@ module riscv_prefetch_buffer
// there was no new request sent yet // there was no new request sent yet
// we assume that req_i is set to high // we assume that req_i is set to high
WAIT_ABORTED: begin WAIT_ABORTED: begin
wait_gnt = 1'b1; instr_addr_o = instr_addr_q;
if (branch_i) begin
instr_addr_o = addr_i;
addr_valid = 1'b1;
end
if (instr_rvalid_i) begin 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 // no need to send address, already done in WAIT_RVALID
if (instr_gnt_i) begin if (instr_gnt_i) begin
NS = WAIT_RVALID; NS = WAIT_RVALID;
end else begin end else begin
NS = WAIT_GNT; NS = WAIT_GNT;
end end
end end
end end
@ -514,11 +564,18 @@ module riscv_prefetch_buffer
begin begin
if(rst_n == 1'b0) if(rst_n == 1'b0)
begin begin
CS <= IDLE; CS <= IDLE;
hwlp_CS <= HWLP_NONE;
instr_addr_q <= '0;
end end
else else
begin begin
CS <= NS; CS <= NS;
hwlp_CS <= hwlp_NS;
if (addr_valid) begin
instr_addr_q <= instr_addr_o;
end
end end
end end