blob: e701819ae7a4ce325add7e835864d52a74b1b118 [file] [log] [blame]
module ibex_icache (
clk_i,
rst_ni,
req_i,
branch_i,
branch_spec_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,
icache_enable_i,
icache_inval_i,
busy_o
);
parameter [31:0] BusWidth = 32;
parameter [31:0] CacheSizeBytes = 4096;
parameter [0:0] ICacheECC = 1'b0;
parameter [31:0] LineSize = 64;
parameter [31:0] NumWays = 2;
parameter [0:0] SpecRequest = 1'b0;
parameter [0:0] BranchCache = 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 [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 [BusWidth - 1:0] instr_rdata_i;
input wire instr_err_i;
input wire instr_pmp_err_i;
input wire instr_rvalid_i;
input wire icache_enable_i;
input wire icache_inval_i;
output wire busy_o;
localparam [31:0] ADDR_W = 32;
localparam [31:0] NUM_FB = 4;
localparam [31:0] FB_THRESHOLD = NUM_FB - 2;
localparam [31:0] LINE_SIZE_ECC = (ICacheECC ? LineSize + 8 : LineSize);
localparam [31:0] LINE_SIZE_BYTES = LineSize / 8;
localparam [31:0] LINE_W = $clog2(LINE_SIZE_BYTES);
localparam [31:0] BUS_BYTES = BusWidth / 8;
localparam [31:0] BUS_W = $clog2(BUS_BYTES);
localparam [31:0] LINE_BEATS = LINE_SIZE_BYTES / BUS_BYTES;
localparam [31:0] LINE_BEATS_W = $clog2(LINE_BEATS);
localparam [31:0] NUM_LINES = (CacheSizeBytes / NumWays) / LINE_SIZE_BYTES;
localparam [31:0] INDEX_W = $clog2(NUM_LINES);
localparam [31:0] INDEX_HI = (INDEX_W + LINE_W) - 1;
localparam [31:0] TAG_SIZE = ((ADDR_W - INDEX_W) - LINE_W) + 1;
localparam [31:0] TAG_SIZE_ECC = (ICacheECC ? TAG_SIZE + 6 : TAG_SIZE);
localparam [31:0] OUTPUT_BEATS = BUS_BYTES / 2;
wire [ADDR_W - 1:0] lookup_addr_aligned;
wire [ADDR_W - 1:0] prefetch_addr_d;
reg [ADDR_W - 1:0] prefetch_addr_q;
wire prefetch_addr_en;
wire branch_suppress;
wire lookup_throttle;
wire lookup_req_ic0;
wire [ADDR_W - 1:0] lookup_addr_ic0;
wire [INDEX_W - 1:0] lookup_index_ic0;
wire fill_req_ic0;
wire [INDEX_W - 1:0] fill_index_ic0;
wire [TAG_SIZE - 1:0] fill_tag_ic0;
wire [LineSize - 1:0] fill_wdata_ic0;
wire lookup_grant_ic0;
wire lookup_actual_ic0;
wire fill_grant_ic0;
wire tag_req_ic0;
wire [INDEX_W - 1:0] tag_index_ic0;
wire [NumWays - 1:0] tag_banks_ic0;
wire tag_write_ic0;
wire [TAG_SIZE_ECC - 1:0] tag_wdata_ic0;
wire data_req_ic0;
wire [INDEX_W - 1:0] data_index_ic0;
wire [NumWays - 1:0] data_banks_ic0;
wire data_write_ic0;
wire [LINE_SIZE_ECC - 1:0] data_wdata_ic0;
wire [TAG_SIZE_ECC - 1:0] tag_rdata_ic1 [0:NumWays - 1];
wire [LINE_SIZE_ECC - 1:0] data_rdata_ic1 [0:NumWays - 1];
reg [LINE_SIZE_ECC - 1:0] hit_data_ic1;
reg lookup_valid_ic1;
reg [ADDR_W - 1:INDEX_HI + 1] lookup_addr_ic1;
wire [NumWays - 1:0] tag_match_ic1;
wire tag_hit_ic1;
wire [NumWays - 1:0] tag_invalid_ic1;
wire [NumWays - 1:0] lowest_invalid_way_ic1;
wire [NumWays - 1:0] round_robin_way_ic1;
reg [NumWays - 1:0] round_robin_way_q;
wire [NumWays - 1:0] sel_way_ic1;
wire ecc_err_ic1;
wire ecc_write_req;
wire [NumWays - 1:0] ecc_write_ways;
wire [INDEX_W - 1:0] ecc_write_index;
wire gnt_or_pmp_err;
wire gnt_not_pmp_err;
reg [1:0] fb_fill_level;
wire fill_cache_new;
wire fill_new_alloc;
wire fill_spec_req;
wire fill_spec_done;
wire fill_spec_hold;
wire [(NUM_FB * NUM_FB) - 1:0] fill_older_d;
reg [(NUM_FB * NUM_FB) - 1:0] fill_older_q;
wire [NUM_FB - 1:0] fill_alloc_sel;
wire [NUM_FB - 1:0] fill_alloc;
wire [NUM_FB - 1:0] fill_busy_d;
reg [NUM_FB - 1:0] fill_busy_q;
wire [NUM_FB - 1:0] fill_done;
reg [NUM_FB - 1:0] fill_in_ic1;
wire [NUM_FB - 1:0] fill_stale_d;
reg [NUM_FB - 1:0] fill_stale_q;
wire [NUM_FB - 1:0] fill_cache_d;
reg [NUM_FB - 1:0] fill_cache_q;
wire [NUM_FB - 1:0] fill_hit_ic1;
wire [NUM_FB - 1:0] fill_hit_d;
reg [NUM_FB - 1:0] fill_hit_q;
wire [(LINE_BEATS_W >= 0 ? (NUM_FB * (LINE_BEATS_W + 1)) - 1 : (NUM_FB * (1 - LINE_BEATS_W)) + (LINE_BEATS_W - 1)):(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W)] fill_ext_cnt_d;
reg [(LINE_BEATS_W >= 0 ? (NUM_FB * (LINE_BEATS_W + 1)) - 1 : (NUM_FB * (1 - LINE_BEATS_W)) + (LINE_BEATS_W - 1)):(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W)] fill_ext_cnt_q;
wire [NUM_FB - 1:0] fill_ext_hold_d;
reg [NUM_FB - 1:0] fill_ext_hold_q;
wire [NUM_FB - 1:0] fill_ext_done;
wire [(LINE_BEATS_W >= 0 ? (NUM_FB * (LINE_BEATS_W + 1)) - 1 : (NUM_FB * (1 - LINE_BEATS_W)) + (LINE_BEATS_W - 1)):(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W)] fill_rvd_cnt_d;
reg [(LINE_BEATS_W >= 0 ? (NUM_FB * (LINE_BEATS_W + 1)) - 1 : (NUM_FB * (1 - LINE_BEATS_W)) + (LINE_BEATS_W - 1)):(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W)] fill_rvd_cnt_q;
wire [NUM_FB - 1:0] fill_rvd_done;
wire [NUM_FB - 1:0] fill_ram_done_d;
reg [NUM_FB - 1:0] fill_ram_done_q;
wire [NUM_FB - 1:0] fill_out_grant;
wire [(LINE_BEATS_W >= 0 ? (NUM_FB * (LINE_BEATS_W + 1)) - 1 : (NUM_FB * (1 - LINE_BEATS_W)) + (LINE_BEATS_W - 1)):(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W)] fill_out_cnt_d;
reg [(LINE_BEATS_W >= 0 ? (NUM_FB * (LINE_BEATS_W + 1)) - 1 : (NUM_FB * (1 - LINE_BEATS_W)) + (LINE_BEATS_W - 1)):(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W)] fill_out_cnt_q;
wire [NUM_FB - 1:0] fill_out_done;
wire [NUM_FB - 1:0] fill_ext_req;
wire [NUM_FB - 1:0] fill_rvd_exp;
wire [NUM_FB - 1:0] fill_ram_req;
wire [NUM_FB - 1:0] fill_out_req;
wire [NUM_FB - 1:0] fill_data_sel;
wire [NUM_FB - 1:0] fill_data_reg;
wire [NUM_FB - 1:0] fill_data_hit;
wire [NUM_FB - 1:0] fill_data_rvd;
wire [(NUM_FB * LINE_BEATS_W) - 1:0] fill_ext_off;
wire [(NUM_FB * LINE_BEATS_W) - 1:0] fill_rvd_off;
wire [(LINE_BEATS_W >= 0 ? (NUM_FB * (LINE_BEATS_W + 1)) - 1 : (NUM_FB * (1 - LINE_BEATS_W)) + (LINE_BEATS_W - 1)):(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W)] fill_rvd_beat;
wire [NUM_FB - 1:0] fill_ext_arb;
wire [NUM_FB - 1:0] fill_ram_arb;
wire [NUM_FB - 1:0] fill_out_arb;
wire [NUM_FB - 1:0] fill_rvd_arb;
wire [NUM_FB - 1:0] fill_entry_en;
wire [NUM_FB - 1:0] fill_addr_en;
wire [NUM_FB - 1:0] fill_way_en;
wire [(NUM_FB * LINE_BEATS) - 1:0] fill_data_en;
wire [(NUM_FB * LINE_BEATS) - 1:0] fill_err_d;
reg [(NUM_FB * LINE_BEATS) - 1:0] fill_err_q;
reg [ADDR_W - 1:0] fill_addr_q [0:NUM_FB - 1];
reg [NumWays - 1:0] fill_way_q [0:NUM_FB - 1];
wire [LineSize - 1:0] fill_data_d [0:NUM_FB - 1];
reg [LineSize - 1:0] fill_data_q [0:NUM_FB - 1];
reg [ADDR_W - 1:BUS_W] fill_ext_req_addr;
reg [ADDR_W - 1:0] fill_ram_req_addr;
reg [NumWays - 1:0] fill_ram_req_way;
reg [LineSize - 1:0] fill_ram_req_data;
reg [LineSize - 1:0] fill_out_data;
reg [LINE_BEATS - 1:0] fill_out_err;
wire instr_req;
wire [ADDR_W - 1:BUS_W] instr_addr;
wire skid_complete_instr;
wire skid_ready;
wire output_compressed;
wire skid_valid_d;
reg skid_valid_q;
wire skid_en;
wire [15:0] skid_data_d;
reg [15:0] skid_data_q;
reg skid_err_q;
wire output_valid;
wire addr_incr_two;
wire output_addr_en;
wire [ADDR_W - 1:1] output_addr_d;
reg [ADDR_W - 1:1] output_addr_q;
reg [15:0] output_data_lo;
reg [15:0] output_data_hi;
wire data_valid;
wire output_ready;
wire [LineSize - 1:0] line_data;
wire [LINE_BEATS - 1:0] line_err;
reg [31:0] line_data_muxed;
reg line_err_muxed;
wire [31:0] output_data;
wire output_err;
wire start_inval;
wire inval_done;
reg reset_inval_q;
wire inval_prog_d;
reg inval_prog_q;
wire [INDEX_W - 1:0] inval_index_d;
reg [INDEX_W - 1:0] inval_index_q;
assign lookup_addr_aligned = {lookup_addr_ic0[ADDR_W - 1:LINE_W], {LINE_W {1'b0}}};
assign prefetch_addr_d = (lookup_grant_ic0 ? lookup_addr_aligned + {{(ADDR_W - LINE_W) - 1 {1'b0}}, 1'b1, {LINE_W {1'b0}}} : addr_i);
assign prefetch_addr_en = branch_i | lookup_grant_ic0;
always @(posedge clk_i)
if (prefetch_addr_en)
prefetch_addr_q <= prefetch_addr_d;
assign lookup_throttle = fb_fill_level > FB_THRESHOLD[1:0];
assign lookup_req_ic0 = ((req_i & ~&fill_busy_q) & (branch_i | ~lookup_throttle)) & ~ecc_write_req;
assign lookup_addr_ic0 = (branch_spec_i ? addr_i : prefetch_addr_q);
assign lookup_index_ic0 = lookup_addr_ic0[INDEX_HI:LINE_W];
assign fill_req_ic0 = |fill_ram_req;
assign fill_index_ic0 = fill_ram_req_addr[INDEX_HI:LINE_W];
assign fill_tag_ic0 = {~inval_prog_q & ~ecc_write_req, fill_ram_req_addr[ADDR_W - 1:INDEX_HI + 1]};
assign fill_wdata_ic0 = fill_ram_req_data;
assign branch_suppress = branch_spec_i & ~branch_i;
assign lookup_grant_ic0 = lookup_req_ic0 & ~branch_suppress;
assign fill_grant_ic0 = ((fill_req_ic0 & (~lookup_req_ic0 | branch_suppress)) & ~inval_prog_q) & ~ecc_write_req;
assign lookup_actual_ic0 = ((lookup_grant_ic0 & icache_enable_i) & ~inval_prog_q) & ~start_inval;
assign tag_req_ic0 = ((lookup_req_ic0 | fill_req_ic0) | inval_prog_q) | ecc_write_req;
assign tag_index_ic0 = (inval_prog_q ? inval_index_q : (ecc_write_req ? ecc_write_index : (fill_grant_ic0 ? fill_index_ic0 : lookup_index_ic0)));
assign tag_banks_ic0 = (ecc_write_req ? ecc_write_ways : (fill_grant_ic0 ? fill_ram_req_way : {NumWays {1'b1}}));
assign tag_write_ic0 = (fill_grant_ic0 | inval_prog_q) | ecc_write_req;
assign data_req_ic0 = lookup_req_ic0 | fill_req_ic0;
assign data_index_ic0 = tag_index_ic0;
assign data_banks_ic0 = tag_banks_ic0;
assign data_write_ic0 = tag_write_ic0;
generate
if (ICacheECC) begin : gen_ecc_wdata
wire [21:0] tag_ecc_input_padded;
wire [27:0] tag_ecc_output_padded;
wire [22 - TAG_SIZE:0] tag_ecc_output_unused;
assign tag_ecc_input_padded = {{22 - TAG_SIZE {1'b0}}, fill_tag_ic0};
assign tag_ecc_output_unused = tag_ecc_output_padded[21:TAG_SIZE - 1];
prim_secded_28_22_enc tag_ecc_enc(
.in(tag_ecc_input_padded),
.out(tag_ecc_output_padded)
);
assign tag_wdata_ic0 = {tag_ecc_output_padded[27:22], tag_ecc_output_padded[TAG_SIZE - 1:0]};
prim_secded_72_64_enc data_ecc_enc(
.in(fill_wdata_ic0),
.out(data_wdata_ic0)
);
end
else begin : gen_noecc_wdata
assign tag_wdata_ic0 = fill_tag_ic0;
assign data_wdata_ic0 = fill_wdata_ic0;
end
endgenerate
generate
genvar way;
for (way = 0; way < NumWays; way = way + 1) begin : gen_rams
prim_ram_1p #(
.Width(TAG_SIZE_ECC),
.Depth(NUM_LINES),
.DataBitsPerMask(TAG_SIZE_ECC)
) tag_bank(
.clk_i(clk_i),
.req_i(tag_req_ic0 & tag_banks_ic0[way]),
.write_i(tag_write_ic0),
.wmask_i({TAG_SIZE_ECC {1'b1}}),
.addr_i(tag_index_ic0),
.wdata_i(tag_wdata_ic0),
.rdata_o(tag_rdata_ic1[way])
);
prim_ram_1p #(
.Width(LINE_SIZE_ECC),
.Depth(NUM_LINES),
.DataBitsPerMask(LINE_SIZE_ECC)
) data_bank(
.clk_i(clk_i),
.req_i(data_req_ic0 & data_banks_ic0[way]),
.write_i(data_write_ic0),
.wmask_i({LINE_SIZE_ECC {1'b1}}),
.addr_i(data_index_ic0),
.wdata_i(data_wdata_ic0),
.rdata_o(data_rdata_ic1[way])
);
end
endgenerate
always @(posedge clk_i or negedge rst_ni)
if (!rst_ni)
lookup_valid_ic1 <= 1'b0;
else
lookup_valid_ic1 <= lookup_actual_ic0;
always @(posedge clk_i)
if (lookup_grant_ic0) begin
lookup_addr_ic1 <= lookup_addr_ic0[ADDR_W - 1:INDEX_HI + 1];
fill_in_ic1 <= fill_alloc_sel;
end
generate
for (way = 0; way < NumWays; way = way + 1) begin : gen_tag_match
assign tag_match_ic1[way] = tag_rdata_ic1[way][TAG_SIZE - 1:0] == {1'b1, lookup_addr_ic1[ADDR_W - 1:INDEX_HI + 1]};
assign tag_invalid_ic1[way] = ~tag_rdata_ic1[way][TAG_SIZE - 1];
end
endgenerate
assign tag_hit_ic1 = |tag_match_ic1;
always @(*) begin
hit_data_ic1 = 'b0;
begin : sv2v_autoblock_1
reg signed [31:0] way;
for (way = 0; way < NumWays; way = way + 1)
if (tag_match_ic1[way])
hit_data_ic1 = hit_data_ic1 | data_rdata_ic1[way];
end
end
assign lowest_invalid_way_ic1[0] = tag_invalid_ic1[0];
assign round_robin_way_ic1[0] = round_robin_way_q[NumWays - 1];
generate
for (way = 1; way < NumWays; way = way + 1) begin : gen_lowest_way
assign lowest_invalid_way_ic1[way] = tag_invalid_ic1[way] & ~|tag_invalid_ic1[way - 1:0];
assign round_robin_way_ic1[way] = round_robin_way_q[way - 1];
end
endgenerate
always @(posedge clk_i or negedge rst_ni)
if (!rst_ni)
round_robin_way_q <= {{NumWays - 1 {1'b0}}, 1'b1};
else if (lookup_valid_ic1)
round_robin_way_q <= round_robin_way_ic1;
assign sel_way_ic1 = (|tag_invalid_ic1 ? lowest_invalid_way_ic1 : round_robin_way_q);
generate
if (ICacheECC) begin : gen_data_ecc_checking
wire [NumWays - 1:0] tag_err_ic1;
wire [1:0] data_err_ic1;
wire ecc_correction_write_d;
reg ecc_correction_write_q;
wire [NumWays - 1:0] ecc_correction_ways_d;
reg [NumWays - 1:0] ecc_correction_ways_q;
reg [INDEX_W - 1:0] lookup_index_ic1;
reg [INDEX_W - 1:0] ecc_correction_index_q;
for (way = 0; way < NumWays; way = way + 1) begin : gen_tag_ecc
wire [1:0] tag_err_bank_ic1;
wire [27:0] tag_rdata_padded_ic1;
assign tag_rdata_padded_ic1 = {tag_rdata_ic1[way][TAG_SIZE_ECC - 1-:6], {22 - TAG_SIZE {1'b0}}, tag_rdata_ic1[way][TAG_SIZE - 1:0]};
prim_secded_28_22_dec data_ecc_dec(
.in(tag_rdata_padded_ic1),
.d_o(),
.syndrome_o(),
.err_o(tag_err_bank_ic1)
);
assign tag_err_ic1[way] = |tag_err_bank_ic1;
end
prim_secded_72_64_dec data_ecc_dec(
.in(hit_data_ic1),
.d_o(),
.syndrome_o(),
.err_o(data_err_ic1)
);
assign ecc_err_ic1 = lookup_valid_ic1 & (|data_err_ic1 | |tag_err_ic1);
assign ecc_correction_ways_d = {NumWays {|tag_err_ic1}} | (tag_match_ic1 & {NumWays {|data_err_ic1}});
assign ecc_correction_write_d = ecc_err_ic1;
always @(posedge clk_i or negedge rst_ni)
if (!rst_ni)
ecc_correction_write_q <= 1'b0;
else
ecc_correction_write_q <= ecc_correction_write_d;
always @(posedge clk_i)
if (lookup_grant_ic0)
lookup_index_ic1 <= lookup_addr_ic0[INDEX_HI-:INDEX_W];
always @(posedge clk_i)
if (ecc_err_ic1) begin
ecc_correction_ways_q <= ecc_correction_ways_d;
ecc_correction_index_q <= lookup_index_ic1;
end
assign ecc_write_req = ecc_correction_write_q;
assign ecc_write_ways = ecc_correction_ways_q;
assign ecc_write_index = ecc_correction_index_q;
end
else begin : gen_no_data_ecc
assign ecc_err_ic1 = 1'b0;
assign ecc_write_req = 1'b0;
assign ecc_write_ways = {NumWays {1'sb0}};
assign ecc_write_index = {INDEX_W {1'sb0}};
end
endgenerate
generate
if (BranchCache) begin : gen_caching_logic
localparam [31:0] CACHE_AHEAD = 2;
localparam [31:0] CACHE_CNT_W = 2;
wire cache_cnt_dec;
wire [CACHE_CNT_W - 1:0] cache_cnt_d;
reg [CACHE_CNT_W - 1:0] cache_cnt_q;
assign cache_cnt_dec = lookup_grant_ic0 & |cache_cnt_q;
assign cache_cnt_d = (branch_i ? CACHE_AHEAD[CACHE_CNT_W - 1:0] : cache_cnt_q - {{CACHE_CNT_W - 1 {1'b0}}, cache_cnt_dec});
always @(posedge clk_i or negedge rst_ni)
if (!rst_ni)
cache_cnt_q <= {CACHE_CNT_W {1'sb0}};
else
cache_cnt_q <= cache_cnt_d;
assign fill_cache_new = (((branch_i | |cache_cnt_q) & icache_enable_i) & ~icache_inval_i) & ~inval_prog_q;
end
else begin : gen_cache_all
assign fill_cache_new = (icache_enable_i & ~start_inval) & ~inval_prog_q;
end
endgenerate
always @(*) begin
fb_fill_level = {2 {1'sb0}};
begin : sv2v_autoblock_2
reg signed [31:0] i;
for (i = 0; i < NUM_FB; i = i + 1)
if (fill_busy_q[i] & ~fill_stale_q[i])
fb_fill_level = fb_fill_level + {1'b0, 1'b1};
end
end
assign gnt_or_pmp_err = instr_gnt_i | instr_pmp_err_i;
assign gnt_not_pmp_err = instr_gnt_i & ~instr_pmp_err_i;
assign fill_new_alloc = lookup_grant_ic0;
assign fill_spec_req = (SpecRequest | branch_i) & ~|fill_ext_req;
assign fill_spec_done = fill_spec_req & gnt_not_pmp_err;
assign fill_spec_hold = fill_spec_req & ~gnt_or_pmp_err;
generate
genvar fb;
for (fb = 0; fb < NUM_FB; fb = fb + 1) begin : gen_fbs
if (fb == 0) begin : gen_fb_zero
assign fill_alloc_sel[fb] = ~fill_busy_q[fb];
end
else begin : gen_fb_rest
assign fill_alloc_sel[fb] = ~fill_busy_q[fb] & &fill_busy_q[fb - 1:0];
end
assign fill_alloc[fb] = fill_alloc_sel[fb] & fill_new_alloc;
assign fill_busy_d[fb] = fill_alloc[fb] | (fill_busy_q[fb] & ~fill_done[fb]);
assign fill_older_d[fb * NUM_FB+:NUM_FB] = (fill_alloc[fb] ? fill_busy_q : fill_older_q[fb * NUM_FB+:NUM_FB]) & ~fill_done;
assign fill_done[fb] = ((((fill_ram_done_q[fb] | fill_hit_q[fb]) | ~fill_cache_q[fb]) | |fill_err_q[fb * LINE_BEATS+:LINE_BEATS]) & ((fill_out_done[fb] | fill_stale_q[fb]) | branch_i)) & fill_rvd_done[fb];
assign fill_stale_d[fb] = fill_busy_q[fb] & (branch_i | fill_stale_q[fb]);
assign fill_cache_d[fb] = (fill_alloc[fb] & fill_cache_new) | (((fill_cache_q[fb] & fill_busy_q[fb]) & icache_enable_i) & ~icache_inval_i);
assign fill_hit_ic1[fb] = ((lookup_valid_ic1 & fill_in_ic1[fb]) & tag_hit_ic1) & ~ecc_err_ic1;
assign fill_hit_d[fb] = fill_hit_ic1[fb] | (fill_hit_q[fb] & fill_busy_q[fb]);
assign fill_ext_req[fb] = fill_busy_q[fb] & ~fill_ext_done[fb];
assign fill_ext_cnt_d[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] = (fill_alloc[fb] ? {{LINE_BEATS_W {1'b0}}, fill_spec_done} : fill_ext_cnt_q[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] + {{LINE_BEATS_W {1'b0}}, fill_ext_arb[fb] & gnt_not_pmp_err});
assign fill_ext_hold_d[fb] = (fill_alloc[fb] & fill_spec_hold) | (fill_ext_arb[fb] & ~gnt_or_pmp_err);
assign fill_ext_done[fb] = ((((fill_ext_cnt_q[(fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)) + (LINE_BEATS_W >= 0 ? LINE_BEATS_W : LINE_BEATS_W - LINE_BEATS_W)] | fill_hit_ic1[fb]) | fill_hit_q[fb]) | fill_err_q[(fb * LINE_BEATS) + fill_ext_off[fb * LINE_BEATS_W+:LINE_BEATS_W]]) | (~fill_cache_q[fb] & (branch_i | fill_stale_q[fb]))) & ~fill_ext_hold_q[fb];
assign fill_rvd_exp[fb] = fill_busy_q[fb] & ~fill_rvd_done[fb];
assign fill_rvd_cnt_d[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] = (fill_alloc[fb] ? {(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W) {1'sb0}} : fill_rvd_cnt_q[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] + {{LINE_BEATS_W {1'b0}}, fill_rvd_arb[fb]});
assign fill_rvd_done[fb] = fill_ext_done[fb] & (fill_rvd_cnt_q[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] == fill_ext_cnt_q[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)]);
assign fill_out_req[fb] = ((fill_busy_q[fb] & ~fill_stale_q[fb]) & ~fill_out_done[fb]) & ((((fill_hit_ic1[fb] | fill_hit_q[fb]) | fill_err_q[(fb * LINE_BEATS) + fill_out_cnt_q[(LINE_BEATS_W >= 0 ? (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)) + (LINE_BEATS_W >= 0 ? LINE_BEATS_W - 1 : LINE_BEATS_W - (LINE_BEATS_W - 1)) : (((fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)) + (LINE_BEATS_W >= 0 ? LINE_BEATS_W - 1 : LINE_BEATS_W - (LINE_BEATS_W - 1))) + LINE_BEATS_W) - 1)-:LINE_BEATS_W]]) | (fill_rvd_beat[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] > fill_out_cnt_q[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)])) | fill_rvd_arb[fb]);
assign fill_out_grant[fb] = fill_out_arb[fb] & output_ready;
assign fill_out_cnt_d[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] = (fill_alloc[fb] ? {1'b0, lookup_addr_ic0[LINE_W - 1:BUS_W]} : fill_out_cnt_q[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] + {{LINE_BEATS_W {1'b0}}, fill_out_grant[fb]});
assign fill_out_done[fb] = fill_out_cnt_q[(fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)) + (LINE_BEATS_W >= 0 ? LINE_BEATS_W : LINE_BEATS_W - LINE_BEATS_W)];
assign fill_ram_req[fb] = ((((fill_busy_q[fb] & fill_rvd_cnt_q[(fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)) + (LINE_BEATS_W >= 0 ? LINE_BEATS_W : LINE_BEATS_W - LINE_BEATS_W)]) & ~fill_hit_q[fb]) & fill_cache_q[fb]) & ~|fill_err_q[fb * LINE_BEATS+:LINE_BEATS]) & ~fill_ram_done_q[fb];
assign fill_ram_done_d[fb] = fill_ram_arb[fb] | (fill_ram_done_q[fb] & fill_busy_q[fb]);
assign fill_rvd_beat[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] = {1'b0, fill_addr_q[fb][LINE_W - 1:BUS_W]} + fill_rvd_cnt_q[(LINE_BEATS_W >= 0 ? (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)) + (LINE_BEATS_W >= 0 ? (LINE_BEATS_W >= 0 ? LINE_BEATS_W : (LINE_BEATS_W + (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)) - 1) : LINE_BEATS_W - (LINE_BEATS_W >= 0 ? LINE_BEATS_W : (LINE_BEATS_W + (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)) - 1)) : (((fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)) + (LINE_BEATS_W >= 0 ? (LINE_BEATS_W >= 0 ? LINE_BEATS_W : (LINE_BEATS_W + (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)) - 1) : LINE_BEATS_W - (LINE_BEATS_W >= 0 ? LINE_BEATS_W : (LINE_BEATS_W + (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)) - 1))) + (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)) - 1)-:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)];
assign fill_ext_off[fb * LINE_BEATS_W+:LINE_BEATS_W] = fill_addr_q[fb][LINE_W - 1:BUS_W] + fill_ext_cnt_q[(LINE_BEATS_W >= 0 ? (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)) + (LINE_BEATS_W >= 0 ? LINE_BEATS_W - 1 : LINE_BEATS_W - (LINE_BEATS_W - 1)) : (((fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)) + (LINE_BEATS_W >= 0 ? LINE_BEATS_W - 1 : LINE_BEATS_W - (LINE_BEATS_W - 1))) + LINE_BEATS_W) - 1)-:LINE_BEATS_W];
assign fill_rvd_off[fb * LINE_BEATS_W+:LINE_BEATS_W] = fill_rvd_beat[(LINE_BEATS_W >= 0 ? (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)) + (LINE_BEATS_W >= 0 ? LINE_BEATS_W - 1 : LINE_BEATS_W - (LINE_BEATS_W - 1)) : (((fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)) + (LINE_BEATS_W >= 0 ? LINE_BEATS_W - 1 : LINE_BEATS_W - (LINE_BEATS_W - 1))) + LINE_BEATS_W) - 1)-:LINE_BEATS_W];
assign fill_ext_arb[fb] = fill_ext_req[fb] & ~|(fill_ext_req & fill_older_q[fb * NUM_FB+:NUM_FB]);
assign fill_ram_arb[fb] = (fill_ram_req[fb] & fill_grant_ic0) & ~|(fill_ram_req & fill_older_q[fb * NUM_FB+:NUM_FB]);
assign fill_data_sel[fb] = ~|(((fill_busy_q & ~fill_out_done) & ~fill_stale_q) & fill_older_q[fb * NUM_FB+:NUM_FB]);
assign fill_out_arb[fb] = fill_out_req[fb] & fill_data_sel[fb];
assign fill_rvd_arb[fb] = (instr_rvalid_i & fill_rvd_exp[fb]) & ~|(fill_rvd_exp & fill_older_q[fb * NUM_FB+:NUM_FB]);
assign fill_data_reg[fb] = (((fill_busy_q[fb] & ~fill_stale_q[fb]) & ~fill_out_done[fb]) & fill_data_sel[fb]) & (((fill_rvd_beat[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] > fill_out_cnt_q[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)]) | fill_hit_q[fb]) | |fill_err_q[fb * LINE_BEATS+:LINE_BEATS]);
assign fill_data_hit[fb] = (fill_busy_q[fb] & fill_hit_ic1[fb]) & fill_data_sel[fb];
assign fill_data_rvd[fb] = ((((((fill_busy_q[fb] & fill_rvd_arb[fb]) & ~fill_hit_q[fb]) & ~fill_hit_ic1[fb]) & ~fill_stale_q[fb]) & ~fill_out_done[fb]) & (fill_rvd_beat[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] == fill_out_cnt_q[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)])) & fill_data_sel[fb];
assign fill_entry_en[fb] = fill_alloc[fb] | fill_busy_q[fb];
always @(posedge clk_i or negedge rst_ni)
if (!rst_ni) begin
fill_busy_q[fb] <= 1'b0;
fill_older_q[fb * NUM_FB+:NUM_FB] <= {NUM_FB {1'sb0}};
fill_stale_q[fb] <= 1'b0;
fill_cache_q[fb] <= 1'b0;
fill_hit_q[fb] <= 1'b0;
fill_ext_cnt_q[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] <= {(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W) {1'sb0}};
fill_ext_hold_q[fb] <= 1'b0;
fill_rvd_cnt_q[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] <= {(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W) {1'sb0}};
fill_ram_done_q[fb] <= 1'b0;
fill_out_cnt_q[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] <= {(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W) {1'sb0}};
end
else if (fill_entry_en[fb]) begin
fill_busy_q[fb] <= fill_busy_d[fb];
fill_older_q[fb * NUM_FB+:NUM_FB] <= fill_older_d[fb * NUM_FB+:NUM_FB];
fill_stale_q[fb] <= fill_stale_d[fb];
fill_cache_q[fb] <= fill_cache_d[fb];
fill_hit_q[fb] <= fill_hit_d[fb];
fill_ext_cnt_q[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] <= fill_ext_cnt_d[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)];
fill_ext_hold_q[fb] <= fill_ext_hold_d[fb];
fill_rvd_cnt_q[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] <= fill_rvd_cnt_d[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)];
fill_ram_done_q[fb] <= fill_ram_done_d[fb];
fill_out_cnt_q[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)] <= fill_out_cnt_d[(LINE_BEATS_W >= 0 ? 0 : LINE_BEATS_W) + (fb * (LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W))+:(LINE_BEATS_W >= 0 ? LINE_BEATS_W + 1 : 1 - LINE_BEATS_W)];
end
assign fill_addr_en[fb] = fill_alloc[fb];
assign fill_way_en[fb] = lookup_valid_ic1 & fill_in_ic1[fb];
always @(posedge clk_i)
if (fill_addr_en[fb])
fill_addr_q[fb] <= lookup_addr_ic0;
always @(posedge clk_i)
if (fill_way_en[fb])
fill_way_q[fb] <= sel_way_ic1;
assign fill_data_d[fb] = (fill_hit_ic1[fb] ? hit_data_ic1[LineSize - 1:0] : {LINE_BEATS {instr_rdata_i}});
genvar b;
for (b = 0; b < LINE_BEATS; b = b + 1) begin : gen_data_buf
assign fill_err_d[(fb * LINE_BEATS) + b] = (((((instr_pmp_err_i & fill_alloc[fb]) & fill_spec_req) & (lookup_addr_ic0[LINE_W - 1:BUS_W] == b[LINE_BEATS_W - 1:0])) | ((instr_pmp_err_i & fill_ext_arb[fb]) & (fill_ext_off[fb * LINE_BEATS_W+:LINE_BEATS_W] == b[LINE_BEATS_W - 1:0]))) | ((fill_rvd_arb[fb] & instr_err_i) & (fill_rvd_off[fb * LINE_BEATS_W+:LINE_BEATS_W] == b[LINE_BEATS_W - 1:0]))) | (fill_busy_q[fb] & fill_err_q[(fb * LINE_BEATS) + b]);
always @(posedge clk_i or negedge rst_ni)
if (!rst_ni)
fill_err_q[(fb * LINE_BEATS) + b] <= 1'sb0;
else if (fill_entry_en[fb])
fill_err_q[(fb * LINE_BEATS) + b] <= fill_err_d[(fb * LINE_BEATS) + b];
assign fill_data_en[(fb * LINE_BEATS) + b] = fill_hit_ic1[fb] | ((fill_rvd_arb[fb] & ~fill_hit_q[fb]) & (fill_rvd_off[fb * LINE_BEATS_W+:LINE_BEATS_W] == b[LINE_BEATS_W - 1:0]));
always @(posedge clk_i)
if (fill_data_en[(fb * LINE_BEATS) + b])
fill_data_q[fb][b * BusWidth+:BusWidth] <= fill_data_d[fb][b * BusWidth+:BusWidth];
end
end
endgenerate
always @(*) begin
fill_ext_req_addr = {(31 >= BUS_W ? ((ADDR_W - 1) - BUS_W) + 1 : (BUS_W - (ADDR_W - 1)) + 1) {1'sb0}};
begin : sv2v_autoblock_3
reg signed [31:0] i;
for (i = 0; i < NUM_FB; i = i + 1)
if (fill_ext_arb[i])
fill_ext_req_addr = fill_ext_req_addr | {fill_addr_q[i][ADDR_W - 1:LINE_W], fill_ext_off[i * LINE_BEATS_W+:LINE_BEATS_W]};
end
end
always @(*) begin
fill_ram_req_addr = {ADDR_W {1'sb0}};
fill_ram_req_way = {NumWays {1'sb0}};
fill_ram_req_data = {LineSize {1'sb0}};
begin : sv2v_autoblock_4
reg signed [31:0] i;
for (i = 0; i < NUM_FB; i = i + 1)
if (fill_ram_arb[i]) begin
fill_ram_req_addr = fill_ram_req_addr | fill_addr_q[i];
fill_ram_req_way = fill_ram_req_way | fill_way_q[i];
fill_ram_req_data = fill_ram_req_data | fill_data_q[i];
end
end
end
always @(*) begin
fill_out_data = {LineSize {1'sb0}};
fill_out_err = {LINE_BEATS {1'sb0}};
begin : sv2v_autoblock_5
reg signed [31:0] i;
for (i = 0; i < NUM_FB; i = i + 1)
if (fill_data_reg[i]) begin
fill_out_data = fill_out_data | fill_data_q[i];
fill_out_err = fill_out_err | (fill_err_q[i * LINE_BEATS+:LINE_BEATS] & ~{LINE_BEATS {fill_hit_q[i]}});
end
end
end
assign instr_req = ((SpecRequest | branch_i) & lookup_grant_ic0) | |fill_ext_req;
assign instr_addr = (|fill_ext_req ? fill_ext_req_addr : lookup_addr_ic0[ADDR_W - 1:BUS_W]);
assign instr_req_o = instr_req;
assign instr_addr_o = {instr_addr[ADDR_W - 1:BUS_W], {BUS_W {1'b0}}};
assign line_data = (|fill_data_hit ? hit_data_ic1[LineSize - 1:0] : fill_out_data);
assign line_err = (|fill_data_hit ? {LINE_BEATS {1'b0}} : fill_out_err);
always @(*) begin
line_data_muxed = {32 {1'sb0}};
line_err_muxed = 1'b0;
begin : sv2v_autoblock_6
reg signed [31:0] i;
for (i = 0; i < LINE_BEATS; i = i + 1)
if ((output_addr_q[LINE_W - 1:BUS_W] + {{LINE_BEATS_W - 1 {1'b0}}, skid_valid_q}) == i[LINE_BEATS_W - 1:0]) begin
line_data_muxed = line_data_muxed | line_data[i * 32+:32];
line_err_muxed = line_err_muxed | line_err[i];
end
end
end
assign output_data = (|fill_data_rvd ? instr_rdata_i : line_data_muxed);
assign output_err = (|fill_data_rvd ? instr_err_i : line_err_muxed);
assign data_valid = |fill_out_arb;
assign skid_data_d = output_data[31:16];
assign skid_en = data_valid & (ready_i | skid_ready);
always @(posedge clk_i)
if (skid_en) begin
skid_data_q <= skid_data_d;
skid_err_q <= output_err;
end
assign skid_complete_instr = skid_valid_q & ((skid_data_q[1:0] != 2'b11) | skid_err_q);
assign skid_ready = (output_addr_q[1] & ~skid_valid_q) & (~output_compressed | output_err);
assign output_ready = (ready_i | skid_ready) & ~skid_complete_instr;
assign output_compressed = rdata_o[1:0] != 2'b11;
assign skid_valid_d = (branch_i ? 1'b0 : (skid_valid_q ? ~(ready_i & ((skid_data_q[1:0] != 2'b11) | skid_err_q)) : ((output_addr_q[1] & (~output_compressed | output_err)) | (((~output_addr_q[1] & output_compressed) & ~output_err) & ready_i)) & data_valid));
always @(posedge clk_i or negedge rst_ni)
if (!rst_ni)
skid_valid_q <= 1'b0;
else
skid_valid_q <= skid_valid_d;
assign output_valid = skid_complete_instr | (data_valid & (((~output_addr_q[1] | skid_valid_q) | output_err) | (output_data[17:16] != 2'b11)));
assign output_addr_en = branch_i | (ready_i & valid_o);
assign addr_incr_two = output_compressed & ~err_o;
assign output_addr_d = (branch_i ? addr_i[31:1] : output_addr_q[31:1] + {29'd0, ~addr_incr_two, addr_incr_two});
always @(posedge clk_i)
if (output_addr_en)
output_addr_q <= output_addr_d;
always @(*) begin
output_data_lo = {16 {1'sb0}};
begin : sv2v_autoblock_7
reg signed [31:0] i;
for (i = 0; i < OUTPUT_BEATS; i = i + 1)
if (output_addr_q[BUS_W - 1:1] == i[BUS_W - 2:0])
output_data_lo = output_data_lo | output_data[i * 16+:16];
end
end
always @(*) begin
output_data_hi = {16 {1'sb0}};
begin : sv2v_autoblock_8
reg signed [31:0] i;
for (i = 0; i < (OUTPUT_BEATS - 1); i = i + 1)
if (output_addr_q[BUS_W - 1:1] == i[BUS_W - 2:0])
output_data_hi = output_data_hi | output_data[(i + 1) * 16+:16];
end
if (&output_addr_q[BUS_W - 1:1])
output_data_hi = output_data_hi | output_data[15:0];
end
assign valid_o = output_valid;
assign rdata_o = {output_data_hi, (skid_valid_q ? skid_data_q : output_data_lo)};
assign addr_o = {output_addr_q, 1'b0};
assign err_o = (skid_valid_q & skid_err_q) | (~skid_complete_instr & output_err);
assign err_plus2_o = skid_valid_q & ~skid_err_q;
assign start_inval = (~reset_inval_q | icache_inval_i) & ~inval_prog_q;
assign inval_prog_d = start_inval | (inval_prog_q & ~inval_done);
assign inval_done = &inval_index_q;
assign inval_index_d = (start_inval ? {INDEX_W {1'sb0}} : inval_index_q + {{INDEX_W - 1 {1'b0}}, 1'b1});
always @(posedge clk_i or negedge rst_ni)
if (!rst_ni) begin
inval_prog_q <= 1'b0;
reset_inval_q <= 1'b0;
end
else begin
inval_prog_q <= inval_prog_d;
reset_inval_q <= 1'b1;
end
always @(posedge clk_i)
if (inval_prog_d)
inval_index_q <= inval_index_d;
assign busy_o = inval_prog_q | |(fill_busy_q & ~fill_rvd_done);
endmodule