blob: 8919dec10eaf3b442e149faa33caf6272dfbe275 [file] [log] [blame]
module flexbex_ibex_prefetch_buffer (
clk,
rst_n,
req_i,
branch_i,
addr_i,
ready_i,
valid_o,
rdata_o,
addr_o,
instr_req_o,
instr_gnt_i,
instr_addr_o,
instr_rdata_i,
instr_rvalid_i,
busy_o
);
input wire clk;
input wire rst_n;
input wire req_i;
input wire branch_i;
input wire [31:0] addr_i;
input wire ready_i;
output wire valid_o;
output wire [31:0] rdata_o;
output wire [31:0] addr_o;
output reg instr_req_o;
input wire instr_gnt_i;
output reg [31:0] instr_addr_o;
input wire [31:0] instr_rdata_i;
input wire instr_rvalid_i;
output wire busy_o;
reg [1:0] CS;
reg [1:0] NS;
reg [31:0] instr_addr_q;
wire [31:0] fetch_addr;
reg addr_valid;
reg fifo_valid;
wire fifo_ready;
wire fifo_clear;
assign busy_o = (CS != 2'd0) | instr_req_o;
flexbex_ibex_fetch_fifo fifo_i(
.clk(clk),
.rst_n(rst_n),
.clear_i(fifo_clear),
.in_addr_i(instr_addr_q),
.in_rdata_i(instr_rdata_i),
.in_valid_i(fifo_valid),
.in_ready_o(fifo_ready),
.out_valid_o(valid_o),
.out_ready_i(ready_i),
.out_rdata_o(rdata_o),
.out_addr_o(addr_o),
.out_valid_stored_o()
);
assign fetch_addr = {instr_addr_q[31:2], 2'b00} + 32'd4;
assign fifo_clear = branch_i;
always @(*) begin
instr_req_o = 1'b0;
instr_addr_o = fetch_addr;
fifo_valid = 1'b0;
addr_valid = 1'b0;
NS = CS;
case (CS)
2'd0: begin
instr_addr_o = fetch_addr;
instr_req_o = 1'b0;
if (branch_i)
instr_addr_o = addr_i;
if (req_i && (fifo_ready || branch_i)) begin
instr_req_o = 1'b1;
addr_valid = 1'b1;
NS = (instr_gnt_i ? 2'd2 : 2'd1);
end
end
2'd1: begin
instr_addr_o = instr_addr_q;
instr_req_o = 1'b1;
if (branch_i) begin
instr_addr_o = addr_i;
addr_valid = 1'b1;
end
NS = (instr_gnt_i ? 2'd2 : 2'd1);
end
2'd2: begin
instr_addr_o = fetch_addr;
if (branch_i)
instr_addr_o = addr_i;
if (req_i && (fifo_ready || branch_i)) begin
if (instr_rvalid_i) begin
instr_req_o = 1'b1;
fifo_valid = 1'b1;
addr_valid = 1'b1;
NS = (instr_gnt_i ? 2'd2 : 2'd1);
end
else if (branch_i) begin
addr_valid = 1'b1;
NS = 2'd3;
end
end
else if (instr_rvalid_i) begin
fifo_valid = 1'b1;
NS = 2'd0;
end
end
2'd3: begin
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
instr_req_o = 1'b1;
NS = (instr_gnt_i ? 2'd2 : 2'd1);
end
end
default:
;
endcase
end
always @(posedge clk or negedge rst_n)
if (!rst_n) begin
CS <= 2'd0;
instr_addr_q <= 1'sb0;
end
else begin
CS <= NS;
if (addr_valid)
instr_addr_q <= instr_addr_o;
end
endmodule