| module ibex_prefetch_buffer ( |
| clk_i, |
| rst_ni, |
| req_i, |
| branch_i, |
| branch_spec_i, |
| branch_mispredict_i, |
| mispredict_addr_i, |
| addr_i, |
| ready_i, |
| valid_o, |
| rdata_o, |
| addr_o, |
| err_o, |
| err_plus2_o, |
| instr_req_o, |
| instr_gnt_i, |
| instr_addr_o, |
| instr_rdata_i, |
| instr_err_i, |
| instr_pmp_err_i, |
| instr_rvalid_i, |
| busy_o |
| ); |
| parameter [0:0] ResetAll = 1'b0; |
| input wire clk_i; |
| input wire rst_ni; |
| input wire req_i; |
| input wire branch_i; |
| input wire branch_spec_i; |
| input wire branch_mispredict_i; |
| input wire [31:0] mispredict_addr_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 wire err_o; |
| output wire err_plus2_o; |
| output wire instr_req_o; |
| input wire instr_gnt_i; |
| output wire [31:0] instr_addr_o; |
| input wire [31:0] instr_rdata_i; |
| input wire instr_err_i; |
| input wire instr_pmp_err_i; |
| input wire instr_rvalid_i; |
| output wire busy_o; |
| localparam [31:0] NUM_REQS = 2; |
| wire branch_suppress; |
| wire valid_new_req; |
| wire valid_req; |
| wire valid_req_d; |
| reg valid_req_q; |
| wire discard_req_d; |
| reg discard_req_q; |
| wire gnt_or_pmp_err; |
| wire rvalid_or_pmp_err; |
| wire [1:0] rdata_outstanding_n; |
| wire [1:0] rdata_outstanding_s; |
| reg [1:0] rdata_outstanding_q; |
| wire [1:0] branch_discard_n; |
| wire [1:0] branch_discard_s; |
| reg [1:0] branch_discard_q; |
| wire [1:0] rdata_pmp_err_n; |
| wire [1:0] rdata_pmp_err_s; |
| reg [1:0] rdata_pmp_err_q; |
| wire [1:0] rdata_outstanding_rev; |
| wire [31:0] stored_addr_d; |
| reg [31:0] stored_addr_q; |
| wire stored_addr_en; |
| wire [31:0] fetch_addr_d; |
| reg [31:0] fetch_addr_q; |
| wire fetch_addr_en; |
| wire [31:0] instr_addr; |
| wire [31:0] instr_addr_w_aligned; |
| wire instr_or_pmp_err; |
| wire fifo_valid; |
| wire [31:0] fifo_addr; |
| wire fifo_ready; |
| wire fifo_clear; |
| wire [1:0] fifo_busy; |
| wire valid_raw; |
| wire branch_or_mispredict; |
| assign busy_o = |rdata_outstanding_q | instr_req_o; |
| assign branch_or_mispredict = branch_i | branch_mispredict_i; |
| assign instr_or_pmp_err = instr_err_i | rdata_pmp_err_q[0]; |
| assign fifo_clear = branch_or_mispredict; |
| genvar i; |
| generate |
| for (i = 0; i < NUM_REQS; i = i + 1) begin : gen_rd_rev |
| assign rdata_outstanding_rev[i] = rdata_outstanding_q[1 - i]; |
| end |
| endgenerate |
| assign fifo_ready = ~&(fifo_busy | rdata_outstanding_rev); |
| ibex_fetch_fifo #( |
| .NUM_REQS(NUM_REQS), |
| .ResetAll(ResetAll) |
| ) fifo_i( |
| .clk_i(clk_i), |
| .rst_ni(rst_ni), |
| .clear_i(fifo_clear), |
| .busy_o(fifo_busy), |
| .in_valid_i(fifo_valid), |
| .in_addr_i(fifo_addr), |
| .in_rdata_i(instr_rdata_i), |
| .in_err_i(instr_or_pmp_err), |
| .out_valid_o(valid_raw), |
| .out_ready_i(ready_i), |
| .out_rdata_o(rdata_o), |
| .out_addr_o(addr_o), |
| .out_err_o(err_o), |
| .out_err_plus2_o(err_plus2_o) |
| ); |
| assign branch_suppress = branch_spec_i & ~branch_i; |
| assign valid_new_req = ((~branch_suppress & req_i) & (fifo_ready | branch_or_mispredict)) & ~rdata_outstanding_q[1]; |
| assign valid_req = valid_req_q | valid_new_req; |
| assign gnt_or_pmp_err = instr_gnt_i | instr_pmp_err_i; |
| assign rvalid_or_pmp_err = rdata_outstanding_q[0] & (instr_rvalid_i | rdata_pmp_err_q[0]); |
| assign valid_req_d = valid_req & ~gnt_or_pmp_err; |
| assign discard_req_d = valid_req_q & (branch_or_mispredict | discard_req_q); |
| assign stored_addr_en = (valid_new_req & ~valid_req_q) & ~gnt_or_pmp_err; |
| assign stored_addr_d = instr_addr; |
| generate |
| if (ResetAll) begin : g_stored_addr_ra |
| always @(posedge clk_i or negedge rst_ni) |
| if (!rst_ni) |
| stored_addr_q <= 1'sb0; |
| else if (stored_addr_en) |
| stored_addr_q <= stored_addr_d; |
| end |
| else begin : g_stored_addr_nr |
| always @(posedge clk_i) |
| if (stored_addr_en) |
| stored_addr_q <= stored_addr_d; |
| end |
| endgenerate |
| assign fetch_addr_en = branch_or_mispredict | (valid_new_req & ~valid_req_q); |
| assign fetch_addr_d = (branch_i ? addr_i : (branch_mispredict_i ? {mispredict_addr_i[31:2], 2'b00} : {fetch_addr_q[31:2], 2'b00})) + {{29 {1'b0}}, valid_new_req & ~valid_req_q, 2'b00}; |
| generate |
| if (ResetAll) begin : g_fetch_addr_ra |
| always @(posedge clk_i or negedge rst_ni) |
| if (!rst_ni) |
| fetch_addr_q <= 1'sb0; |
| else if (fetch_addr_en) |
| fetch_addr_q <= fetch_addr_d; |
| end |
| else begin : g_fetch_addr_nr |
| always @(posedge clk_i) |
| if (fetch_addr_en) |
| fetch_addr_q <= fetch_addr_d; |
| end |
| endgenerate |
| assign instr_addr = (valid_req_q ? stored_addr_q : (branch_spec_i ? addr_i : (branch_mispredict_i ? mispredict_addr_i : fetch_addr_q))); |
| assign instr_addr_w_aligned = {instr_addr[31:2], 2'b00}; |
| generate |
| for (i = 0; i < NUM_REQS; i = i + 1) begin : g_outstanding_reqs |
| if (i == 0) begin : g_req0 |
| assign rdata_outstanding_n[i] = (valid_req & gnt_or_pmp_err) | rdata_outstanding_q[i]; |
| assign branch_discard_n[i] = (((valid_req & gnt_or_pmp_err) & discard_req_d) | (branch_or_mispredict & rdata_outstanding_q[i])) | branch_discard_q[i]; |
| assign rdata_pmp_err_n[i] = ((valid_req & ~rdata_outstanding_q[i]) & instr_pmp_err_i) | rdata_pmp_err_q[i]; |
| end |
| else begin : g_reqtop |
| assign rdata_outstanding_n[i] = ((valid_req & gnt_or_pmp_err) & rdata_outstanding_q[i - 1]) | rdata_outstanding_q[i]; |
| assign branch_discard_n[i] = ((((valid_req & gnt_or_pmp_err) & discard_req_d) & rdata_outstanding_q[i - 1]) | (branch_or_mispredict & rdata_outstanding_q[i])) | branch_discard_q[i]; |
| assign rdata_pmp_err_n[i] = (((valid_req & ~rdata_outstanding_q[i]) & instr_pmp_err_i) & rdata_outstanding_q[i - 1]) | rdata_pmp_err_q[i]; |
| end |
| end |
| endgenerate |
| assign rdata_outstanding_s = (rvalid_or_pmp_err ? {1'b0, rdata_outstanding_n[1:1]} : rdata_outstanding_n); |
| assign branch_discard_s = (rvalid_or_pmp_err ? {1'b0, branch_discard_n[1:1]} : branch_discard_n); |
| assign rdata_pmp_err_s = (rvalid_or_pmp_err ? {1'b0, rdata_pmp_err_n[1:1]} : rdata_pmp_err_n); |
| assign fifo_valid = rvalid_or_pmp_err & ~branch_discard_q[0]; |
| assign fifo_addr = (branch_i ? addr_i : mispredict_addr_i); |
| always @(posedge clk_i or negedge rst_ni) |
| if (!rst_ni) begin |
| valid_req_q <= 1'b0; |
| discard_req_q <= 1'b0; |
| rdata_outstanding_q <= 'b0; |
| branch_discard_q <= 'b0; |
| rdata_pmp_err_q <= 'b0; |
| end |
| else begin |
| valid_req_q <= valid_req_d; |
| discard_req_q <= discard_req_d; |
| rdata_outstanding_q <= rdata_outstanding_s; |
| branch_discard_q <= branch_discard_s; |
| rdata_pmp_err_q <= rdata_pmp_err_s; |
| end |
| assign instr_req_o = valid_req; |
| assign instr_addr_o = instr_addr_w_aligned; |
| assign valid_o = valid_raw & ~branch_mispredict_i; |
| endmodule |