// Copyright 2018 ETH Zurich, University of Bologna and Greenwaves Technologies.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
/*icache_controller_private.sv */
`define USE_REQ_BUFFER
`define log2_non_zero(VALUE) ((VALUE) < ( 1 ) ? 1 : (VALUE) < ( 2 ) ? 1 : (VALUE) < ( 4 ) ? 2 : (VALUE)< (8) ? 3:(VALUE) < ( 16 ) ? 4 : (VALUE) < ( 32 ) ? 5 : (VALUE) < ( 64 ) ? 6 : (VALUE) < ( 128 ) ? 7 : (VALUE) < ( 256 ) ? 8 : (VALUE) < ( 512 ) ? 9 : 10)
module icache_controller_private
#(
parameter FETCH_ADDR_WIDTH = 32,
parameter FETCH_DATA_WIDTH = 32,
parameter NB_WAYS = 4,
parameter CACHE_LINE = 4,
parameter SCM_TAG_ADDR_WIDTH = 4,
parameter SCM_DATA_ADDR_WIDTH = 6,
parameter SCM_TAG_WIDTH = 8,
parameter SCM_DATA_WIDTH = 128,
parameter SCM_NUM_ROWS = 2**SCM_TAG_ADDR_WIDTH,
parameter SET_ID_LSB = $clog2(SCM_DATA_WIDTH*CACHE_LINE)-3,
parameter SET_ID_MSB = SET_ID_LSB + SCM_TAG_ADDR_WIDTH - 1,
parameter TAG_LSB = SET_ID_MSB + 1,
parameter TAG_MSB = TAG_LSB + SCM_TAG_WIDTH - 2,
parameter AXI_ID = 4,
parameter AXI_ADDR = FETCH_ADDR_WIDTH,
parameter AXI_USER = 6,
parameter AXI_DATA = 32
)
(
input logic clk,
input logic rst_n,
input logic test_en_i,
input logic bypass_icache_i,
output logic cache_is_bypassed_o,
input logic flush_icache_i,
output logic cache_is_flushed_o,
input logic flush_set_ID_req_i,
input logic [FETCH_ADDR_WIDTH-1:0] flush_set_ID_addr_i,
output logic flush_set_ID_ack_o,
// interface with processor
input logic fetch_req_i,
input logic [FETCH_ADDR_WIDTH-1:0] fetch_addr_i,
output logic fetch_gnt_o,
output logic fetch_rvalid_o,
output logic [FETCH_DATA_WIDTH-1:0] fetch_rdata_o,
// interface with READ PORT --> SCM DATA
output logic [NB_WAYS-1:0] DATA_req_o,
output logic DATA_we_o,
output logic [SCM_DATA_ADDR_WIDTH-1:0] DATA_addr_o,
input logic [NB_WAYS-1:0][SCM_DATA_WIDTH-1:0] DATA_rdata_i,
output logic [FETCH_DATA_WIDTH-1:0] DATA_wdata_o,
input logic [NB_WAYS-1:0] DATA_error_i,
output logic [NB_WAYS-1:0] DATA_need_correct_o,
// interface with READ PORT --> SCM TAG
output logic [NB_WAYS-1:0] TAG_req_o,
output logic [SCM_TAG_ADDR_WIDTH-1:0] TAG_addr_o,
input logic [NB_WAYS-1:0][SCM_TAG_WIDTH-1:0] TAG_rdata_i,
output logic [SCM_TAG_WIDTH-1:0] TAG_wdata_o,
output logic TAG_we_o,
// Interface to cache_controller_to_axi
output logic axi_ar_valid_o,
input logic axi_ar_ready_i,
output logic [AXI_ADDR-1:0] axi_ar_addr_o,
output logic [7:0] axi_ar_len_o,
input logic axi_r_valid_i,
output logic axi_r_ready_o,
input logic [AXI_DATA-1:0] axi_r_data_i,
input logic axi_r_last_i,
output logic [31:0] ctrl_hit_count_icache_o,
output logic [31:0] ctrl_trans_count_icache_o,
output logic [31:0] ctrl_miss_count_icache_o,
input logic ctrl_clear_regs_icache_i,
input logic ctrl_enable_regs_icache_i,
output logic [31:0] ref_count_o,
output logic [31:0] err_count_o,
output logic [31:0] cycle_count_o,
input logic count_enable_i,
input logic count_clr_i,
output logic count_ov_o
);
localparam OFFSET = $clog2(SCM_DATA_WIDTH*CACHE_LINE)-3;//8-3=5
logic [FETCH_ADDR_WIDTH-1:0] fetch_addr_Q;
logic fetch_req_Q;
logic save_pipe_status;
logic clear_pipe;
logic enable_pipe;
logic save_victim_way;
logic [SCM_TAG_ADDR_WIDTH-1:0] counter_FLUSH_NS, counter_FLUSH_CS;
logic [$clog2(CACHE_LINE)-1:0] refill_cnt_d, refill_cnt_q;
logic [NB_WAYS-1:0] DATA_CS, DATA_CS_d;
logic [NB_WAYS-1:0] TAG_CS, TAG_CS_d;
logic is_same_block;
logic in_correcting, in_correcting_d;
logic [NB_WAYS-1:0] way_match;
logic [NB_WAYS-1:0] way_valid;
logic [NB_WAYS-1:0] way_match_bin;
logic [NB_WAYS-1:0] way_valid_Q;
logic [$clog2(NB_WAYS)-1:0] random_way;
logic [$clog2(NB_WAYS)-1:0] first_available_way;
logic [$clog2(NB_WAYS)-1:0] victim_d, victim_q;
logic [$clog2(NB_WAYS)-1:0] HIT_WAY;
logic pending_trans_dis_cache;
logic [FETCH_DATA_WIDTH-1:0] axi_r_data_int;
logic [AXI_DATA-1:0] axi_r_data_i_delay;
// Wait two 64 bits to combine 128 data//
always_comb
begin
case(FETCH_DATA_WIDTH)
32: //##WEI##
begin
axi_r_data_int = axi_r_data_i;
end
64:
begin
axi_r_data_int = axi_r_data_i;
end
128:
begin
axi_r_data_int[127:64] = axi_r_data_i;
axi_r_data_int[63:0] = axi_r_data_i_delay;
end
endcase
end // always_comb
always_ff @(posedge clk, negedge rst_n)
begin
if(~rst_n)
begin
axi_r_data_i_delay <= '0;
end
else
begin
if(axi_r_valid_i & axi_r_ready_o)
axi_r_data_i_delay <= axi_r_data_i;
end
end
enum logic [2:0] { DISABLED_ICACHE,WAIT_REFILL_DONE, OPERATIVE, REQ_REFILL , WAIT_PENDING_TRANS, FLUSH_ICACHE, FLUSH_SET_ID } CS, NS;
int unsigned i,j,index;
logic update_lfsr;
//FSM
always_ff @(posedge clk, negedge rst_n)
begin
if(~rst_n)
CS <= DISABLED_ICACHE;
else
CS <= NS;
end
//Fetch
always_ff @(posedge clk, negedge rst_n)
begin
if(~rst_n)
begin
fetch_addr_Q <= '1;
fetch_req_Q <= 1'b0;
end
else if(enable_pipe)
begin
fetch_req_Q <= 1'b1;
fetch_addr_Q <= fetch_addr_i;
end
else if(clear_pipe)
begin
fetch_req_Q <= '0;
end
end
always_ff @(posedge clk, negedge rst_n)
begin
if(~rst_n)
way_valid_Q <= '0;
else if(save_pipe_status)
way_valid_Q <= way_valid;
end
always_ff @(posedge clk, negedge rst_n)
begin
if(~rst_n)
victim_q <= '0;
else if(save_victim_way)
victim_q <= victim_d;
end
always_ff @(posedge clk, negedge rst_n)
begin
if(~rst_n)
pending_trans_dis_cache <= '0;
//Use this code to be sure thhat there is not apending transaction when enable cache request is asserted
else if( (CS == DISABLED_ICACHE ) || (CS == WAIT_PENDING_TRANS))
begin
case({(axi_ar_valid_o & axi_ar_ready_i), (axi_r_last_i & axi_r_valid_i & axi_r_ready_o)})
2'b00: begin pending_trans_dis_cache <= pending_trans_dis_cache; end
2'b10: begin pending_trans_dis_cache <= 1'b1; end
2'b01: begin pending_trans_dis_cache <= 1'b0; end
2'b11: begin pending_trans_dis_cache <= 1'b1; end
endcase // {(axi_ar_valid_o & axi_ar_ready_i), (axi_r_last_i & axi_r_valid_i & axi_r_ready_o)}
end
else
pending_trans_dis_cache <= 1'b0;
end
always_ff @(posedge clk, negedge rst_n)
begin
if(~rst_n)
counter_FLUSH_CS <= '0;
else
counter_FLUSH_CS <= counter_FLUSH_NS;
end
always_ff @(posedge clk, negedge rst_n)
begin
if(~rst_n)
begin
ctrl_hit_count_icache_o <= '0;
ctrl_trans_count_icache_o <= '0;
ctrl_miss_count_icache_o <= '0;
end
else if(ctrl_clear_regs_icache_i)
begin
ctrl_hit_count_icache_o <= '0;
ctrl_trans_count_icache_o <= '0;
ctrl_miss_count_icache_o <= '0;
end
else if(ctrl_enable_regs_icache_i)
begin
// Count incoming transactions
if(fetch_req_i & fetch_gnt_o)
ctrl_trans_count_icache_o <= ctrl_trans_count_icache_o + 1'b1;
if( (CS == OPERATIVE) & fetch_req_Q & (|way_match))
ctrl_hit_count_icache_o <= ctrl_hit_count_icache_o + 1'b1;
if(axi_ar_valid_o & axi_ar_ready_i)
ctrl_miss_count_icache_o <= ctrl_miss_count_icache_o + 1'b1;
end
end
//DFF
always_ff @(posedge clk, negedge rst_n)
begin
if(~rst_n)
begin
refill_cnt_q <= 0;
DATA_CS <= 0;
TAG_CS <= 0;
in_correcting <= 0;
end
else // else
begin
refill_cnt_q <= refill_cnt_d ;
DATA_CS <= DATA_CS_d ;
TAG_CS <= TAG_CS_d ;
in_correcting <= in_correcting_d;
end
end
// --------------------- //
// TAG CHECK MULTI WAY //
// --------------------- //
genvar k;
generate
for(k=0; k<NB_WAYS; k++)
begin
assign way_match[k] = ((TAG_rdata_i[k][SCM_TAG_WIDTH-1] == 1'b1) && (TAG_rdata_i[k][SCM_TAG_WIDTH-2:0] == fetch_addr_Q[TAG_MSB:TAG_LSB]));
assign way_valid[k] = (TAG_rdata_i[k][SCM_TAG_WIDTH-1] == 1'b1);
end
endgenerate
//TAG RAM
always_comb
begin
if(CS == FLUSH_ICACHE)
begin
TAG_req_o = '1;
TAG_we_o = 1'b1;
TAG_addr_o = counter_FLUSH_CS;
TAG_wdata_o = '0;
end
else if(CS == FLUSH_SET_ID)
begin
TAG_req_o = '1;
TAG_we_o = 1'b1;
TAG_addr_o = flush_set_ID_addr_i[SET_ID_MSB:SET_ID_LSB];
TAG_wdata_o = '0;
end
else if((CS == OPERATIVE) &(~(bypass_icache_i | flush_icache_i | flush_set_ID_req_i ))) //No bypass
begin
//Read the DATA nd TAG
TAG_req_o = TAG_CS;
TAG_we_o = 1'b0;
TAG_addr_o = fetch_addr_Q[SET_ID_MSB:SET_ID_LSB];
TAG_wdata_o = {1'b1,fetch_addr_Q[TAG_MSB:TAG_LSB]};
end
else if(CS == WAIT_REFILL_DONE)
begin
TAG_req_o = '0;
TAG_req_o[victim_q] = (refill_cnt_q == 'b1) | (refill_cnt_q == 'b0);
TAG_we_o = refill_cnt_q == 'b0;
TAG_addr_o = fetch_addr_Q[SET_ID_MSB:SET_ID_LSB];
TAG_wdata_o = {1'b1,fetch_addr_Q[TAG_MSB:TAG_LSB]};
end
else begin
TAG_req_o = '0;
TAG_we_o = 1'b0;
TAG_addr_o = fetch_addr_i[SET_ID_MSB:SET_ID_LSB];
TAG_wdata_o = {1'b1,fetch_addr_Q[TAG_MSB:TAG_LSB]};
end
end
//DATA
always_comb
begin
if((CS == OPERATIVE) &(~(bypass_icache_i | flush_icache_i | flush_set_ID_req_i ))) //No bypass
begin
DATA_req_o = DATA_CS;
DATA_we_o = 1'b0;
DATA_wdata_o = axi_r_data_int;
DATA_addr_o = fetch_addr_Q[SET_ID_MSB:2];
end
else if(CS == WAIT_REFILL_DONE)
begin
DATA_req_o = '0;
DATA_req_o[victim_q] = axi_r_valid_i;
DATA_addr_o = {fetch_addr_Q[SET_ID_MSB:SET_ID_LSB], refill_cnt_q};
DATA_wdata_o = axi_r_data_int;
DATA_we_o = 1'b1;
end
else
begin
DATA_req_o = '0;
DATA_addr_o = fetch_addr_i[SET_ID_MSB:SET_ID_LSB];
DATA_wdata_o = axi_r_data_int;
DATA_we_o = 1'b0;
end
end
//Fetch
always_comb
begin
if(CS == DISABLED_ICACHE)
begin
fetch_rdata_o = axi_r_data_int;
fetch_rvalid_o = axi_r_valid_i & axi_r_last_i; // Must a single beat transaction
if(bypass_icache_i == 1'b1)
fetch_gnt_o = axi_ar_ready_i & fetch_req_i;
else
fetch_gnt_o = 1'b0;
end
else if(CS == WAIT_PENDING_TRANS)
begin
fetch_rdata_o = axi_r_data_int;
fetch_rvalid_o = axi_r_valid_i & axi_r_last_i; // Must a single beat transaction
fetch_gnt_o = 1'b0;
end
else if(CS == OPERATIVE)
begin
if((bypass_icache_i | flush_icache_i | flush_set_ID_req_i ) & fetch_req_Q & (|way_match))
fetch_rvalid_o = 1'b1;
else if(fetch_req_Q & (|way_match))
if(DATA_error_i[HIT_WAY])
fetch_rvalid_o = 1'b0;
else
fetch_rvalid_o = 1'b1;
else
fetch_rvalid_o = 1'b0;
fetch_gnt_o = fetch_req_i & ~(bypass_icache_i | flush_icache_i | flush_set_ID_req_i );
fetch_rdata_o = DATA_rdata_i[HIT_WAY];
end
else if(CS == WAIT_REFILL_DONE)
begin
fetch_gnt_o = 1'b0;
fetch_rdata_o = axi_r_data_int;
fetch_rvalid_o = axi_r_valid_i & (refill_cnt_q == fetch_addr_Q[SET_ID_LSB-1:2]);
end
else
begin
fetch_gnt_o = 1'b0;
fetch_rvalid_o = 1'b0;
fetch_rdata_o = axi_r_data_int; //FIXME ok for AXI 64 and 32bit INSTR
end
end
always_comb
begin
if(CS == OPERATIVE)
DATA_need_correct_o = way_match;
else
DATA_need_correct_o = '0;
end
always_comb
begin
if(CS == DISABLED_ICACHE)
flush_set_ID_ack_o = 1'b1;
else if(CS == WAIT_PENDING_TRANS)
flush_set_ID_ack_o = 1'b1;
else if(CS == FLUSH_ICACHE)
flush_set_ID_ack_o = 1'b1;
else if(CS == FLUSH_SET_ID)
flush_set_ID_ack_o = 1'b1;
else if(CS == OPERATIVE)
flush_set_ID_ack_o = 1'b0;
else if(CS == REQ_REFILL)
flush_set_ID_ack_o = 1'b0;
else if(CS == WAIT_REFILL_DONE)
flush_set_ID_ack_o = 1'b0;
else
flush_set_ID_ack_o = 1'b0;
end
always_comb
begin
if(CS == DISABLED_ICACHE)
if(bypass_icache_i == 1'b1)
NS = DISABLED_ICACHE;
else
NS = WAIT_PENDING_TRANS;
else if(CS == WAIT_PENDING_TRANS)
if(pending_trans_dis_cache == 1'b0)
NS = FLUSH_ICACHE; // Flushing is made in the central controller
else
NS = WAIT_PENDING_TRANS;
else if(CS == FLUSH_ICACHE)
if(counter_FLUSH_CS < 2**SCM_TAG_ADDR_WIDTH-1)
NS = FLUSH_ICACHE;
else
NS = OPERATIVE;
else if(CS == FLUSH_SET_ID)
NS = OPERATIVE;
else if(CS == OPERATIVE)
begin
if((bypass_icache_i | flush_icache_i | flush_set_ID_req_i ))
begin
if(fetch_req_Q)
begin
if(|way_match)
begin
if(bypass_icache_i)
NS = DISABLED_ICACHE;
else if (flush_icache_i)
NS = FLUSH_ICACHE;
else
NS = FLUSH_SET_ID;
end
else
NS = REQ_REFILL;
end
else //~if(fetch_req_Q == 1'b1)
begin
if(bypass_icache_i)
NS = DISABLED_ICACHE;
else if (flush_icache_i)
NS = FLUSH_ICACHE;
else
NS = FLUSH_SET_ID;
end
end
else // NO Bypass request !!
begin
if(fetch_req_Q)
begin
if(|way_match)
NS = OPERATIVE;
else
NS = REQ_REFILL;
end
else //~fetch_req_Q
NS = OPERATIVE;
end
end
else if(CS == REQ_REFILL)
begin
if(axi_ar_ready_i)
NS = WAIT_REFILL_DONE;
else
NS = REQ_REFILL;
end
else if(CS == WAIT_REFILL_DONE)
begin
if(axi_r_valid_i & axi_r_last_i)
begin
//enable_pipe = fetch_req_i;
//clear_pipe = ~fetch_req_i;
NS = OPERATIVE;
end
else
begin
NS = WAIT_REFILL_DONE;
end
end
else
NS = DISABLED_ICACHE;
end
always_comb
begin
if(CS == DISABLED_ICACHE)
axi_ar_len_o = 1; // Single beat trans
else
axi_ar_len_o = (CACHE_LINE*FETCH_DATA_WIDTH)/AXI_DATA-1;
end
always_comb
begin
if(CS == REQ_REFILL)
begin
if(way_valid_Q == '1) // all the lines are valid, invalidate one random line
begin
victim_d = random_way;
update_lfsr = 1'b1;
end
else
begin
victim_d = first_available_way;
update_lfsr = 1'b0;
end
end
else begin
victim_d = '0;
update_lfsr = 1'b0;
end
end
always_comb
begin
if(CS == DISABLED_ICACHE)
counter_FLUSH_NS = '0;
else if(CS == FLUSH_ICACHE)
if(counter_FLUSH_CS < 2**SCM_TAG_ADDR_WIDTH-1)
counter_FLUSH_NS = counter_FLUSH_CS + 1'b1;
else
counter_FLUSH_NS = '0;
else
counter_FLUSH_NS = counter_FLUSH_CS;
end
always_comb
begin
refill_cnt_d = refill_cnt_q;
if(CS == WAIT_REFILL_DONE)
begin
if(axi_r_valid_i) begin
if(axi_r_last_i)
refill_cnt_d = 0;
else
refill_cnt_d = refill_cnt_q + 1'b1;
end
end
else
refill_cnt_d = refill_cnt_q;
end
assign is_same_block = (fetch_addr_i[FETCH_ADDR_WIDTH-1:SET_ID_LSB] ==
fetch_addr_Q[FETCH_ADDR_WIDTH-1:SET_ID_LSB] );
assign save_victim_way = (CS == REQ_REFILL) ;
/*
always_comb
begin
save_pipe_status = 1'b0;
enable_pipe = 1'b0;
clear_pipe = 1'b0;
DATA_CS_d = 'b0;
TAG_CS_d = 'b0;
case(CS)
DISABLED_ICACHE:
begin
clear_pipe = 1'b1;
end
WAIT_PENDING_TRANS:
begin
clear_pipe = 1'b1;
end
OPERATIVE:
begin
if(bypass_icache_i | flush_icache_i | flush_set_ID_req_i ) // first check if the previous fetch has a miss or HIT
begin
if(fetch_req_Q)
begin
if(|way_match)
begin
if(fetch_req_i == 1'b0)
clear_pipe = 1'b1;
end
else
begin
// asks for the last refill, then goes into DISABLED state
save_pipe_status = 1'b1;
end
end //~if(fetch_req_Q == 1'b1)
else
begin
clear_pipe = 1'b1;
end//~else(fetch_req_Q)
end
else // NO Bypass request
begin
enable_pipe = fetch_req_i;
if (fetch_req_i) begin
if(is_same_block) begin
DATA_CS_d = way_match;
TAG_CS_d = 'b0;
end
else begin
DATA_CS_d = 4'b1111;
TAG_CS_d = 4'b1111;
end
end
if(fetch_req_Q)
begin
if(|way_match)
begin
if(DATA_error_i[HIT_WAY]) begin
DATA_CS_d = way_match;
TAG_CS_d = 'b0;
enable_pipe = 0;
end else begin
clear_pipe = ~fetch_req_i;
end
end
else
begin
save_pipe_status = 1'b1;
enable_pipe = 1'b0;
end
end
end
end
REQ_REFILL:
begin
enable_pipe = 1'b0;
end
WAIT_REFILL_DONE:
begin
clear_pipe = axi_r_valid_i & (refill_cnt_q == fetch_addr_Q[SET_ID_LSB-1:2]);
end // case: WAIT_REFILL_DONE
endcase // CS
end
*/
always_comb
begin
save_pipe_status = 1'b0;
if(CS == OPERATIVE)
begin
if((bypass_icache_i | flush_icache_i | flush_set_ID_req_i ))
begin
if(fetch_req_Q)
begin
if(~(|way_match))
save_pipe_status = 1'b1;
end
end
else // NO Bypass request !!
begin
if(fetch_req_Q)
begin
if(~(|way_match))
save_pipe_status = 1'b1;
end
end
end
end
always_comb
begin
//enable_pipe = 1'b0;
if(CS == OPERATIVE)
begin
if(~(bypass_icache_i | flush_icache_i | flush_set_ID_req_i ))
begin
enable_pipe = fetch_req_i;
if(fetch_req_Q)
begin
if(|way_match)
begin
if(DATA_error_i[HIT_WAY])
enable_pipe = 0;
end
else
enable_pipe = 1'b0;
end
end
end
else //if(CS == REQ_REFILL)
enable_pipe = 1'b0;
end
always_comb
begin
if(CS == DISABLED_ICACHE)
clear_pipe = 1'b1;
else if(CS == WAIT_PENDING_TRANS)
clear_pipe = 1'b1;
else if(CS == OPERATIVE)
begin
if((bypass_icache_i | flush_icache_i | flush_set_ID_req_i )) begin
clear_pipe = 1'b0;
if(fetch_req_Q)
if(|way_match) begin
if(fetch_req_i == 1'b0)
clear_pipe = 1'b1;
end
else
clear_pipe = 1'b1;
end
else
begin
clear_pipe = 1'b0;
if(fetch_req_Q)
begin
if(|way_match) begin
if(~DATA_error_i[HIT_WAY])
clear_pipe = ~fetch_req_i;
end
end
end
end
else if(CS == WAIT_REFILL_DONE)
clear_pipe = axi_r_valid_i & (refill_cnt_q == fetch_addr_Q[SET_ID_LSB-1:2]);
else
clear_pipe = 1'b0;
end
always_comb
begin
DATA_CS_d = 'b0;
TAG_CS_d = 'b0;
if(CS == OPERATIVE)
if(~(bypass_icache_i | flush_icache_i | flush_set_ID_req_i ))
if (fetch_req_i) begin
if(is_same_block) begin
DATA_CS_d = way_match;
TAG_CS_d = 'b0;
end
else begin
DATA_CS_d = 4'b1111;
TAG_CS_d = 4'b1111;
end
end
else if(fetch_req_Q)
begin
if(|way_match)
if(DATA_error_i[HIT_WAY]) begin
DATA_CS_d = way_match;
TAG_CS_d = 'b0;
end
end
end
always_comb
begin
axi_ar_valid_o = 1'b0;
axi_r_ready_o = 1'b1;
axi_ar_addr_o = fetch_addr_i;
cache_is_bypassed_o = 1'b0;
cache_is_flushed_o = 1'b0;
in_correcting_d = 0;
case(CS)
DISABLED_ICACHE:
begin
cache_is_bypassed_o = 1'b1;
cache_is_flushed_o = 1'b1;
if(bypass_icache_i == 1'b1) // Already Bypassed
begin
axi_ar_valid_o = fetch_req_i;
axi_ar_addr_o = fetch_addr_i;
end
else
begin // Enable ICache
axi_ar_valid_o = 1'b0;
end
end
WAIT_PENDING_TRANS:
begin
cache_is_bypassed_o = 1'b1;
cache_is_flushed_o = 1'b1;
axi_ar_valid_o = 1'b0;
end
FLUSH_ICACHE:
begin
if(~(counter_FLUSH_CS < 2**SCM_TAG_ADDR_WIDTH-1))
cache_is_flushed_o = 1'b1;
end //~FLUSH_ICACHE
OPERATIVE:
begin
cache_is_bypassed_o = 1'b0;
cache_is_flushed_o = 1'b0;
if(~(bypass_icache_i | flush_icache_i | flush_set_ID_req_i )) // first check if the previous fetch has a miss or HIT
begin
if(fetch_req_Q)
begin
if(|way_match)
begin : HIT
if(DATA_error_i[HIT_WAY])
in_correcting_d = 1;
end
end
end
end
REQ_REFILL:
begin
cache_is_bypassed_o = 1'b0;
cache_is_flushed_o = 1'b0;
axi_ar_valid_o = 1'b1;
axi_ar_addr_o = fetch_addr_Q;
end
WAIT_REFILL_DONE:
begin
cache_is_bypassed_o = 1'b0;
cache_is_flushed_o = 1'b0;
end // case: WAIT_REFILL_DONE
//default: ;
endcase // CS
end
generate
if(NB_WAYS == 1)
begin : DIRECT_MAPPED
assign random_way = 1'b1;
end
else
begin : MULTI_WAY_SET_ASSOCIATIVE
LFSR_8bit
i_LFSR_Way_Repl
(
.data_o ( random_way ),
.enable_i ( update_lfsr ),
.clk ( clk ),
.rst_n ( rst_n )
);
end
endgenerate
logic error_q;
always_ff @(posedge clk, negedge rst_n)
begin
if(~rst_n)
begin
ref_count_o <= 0;
err_count_o <= 0;
cycle_count_o <= 0;
count_ov_o <= 0;
error_q <= 0;
end
else begin
error_q <= DATA_error_i[HIT_WAY];
if(count_clr_i)
begin
ref_count_o <= 0;
err_count_o <= 0;
cycle_count_o <= 0;
count_ov_o <= 0;
end
else if((CS == OPERATIVE) & (|way_match) & count_enable_i)
begin
if(ref_count_o != 20'h00FFF)
begin
if(fetch_rvalid_o) begin
ref_count_o <= ref_count_o + 1'b1;
end
if(~error_q & DATA_error_i[HIT_WAY]) begin
err_count_o <= err_count_o + 1'b1;
end
if(DATA_CS[HIT_WAY]) begin
cycle_count_o <= cycle_count_o + 1'b1;
end
end
else begin
count_ov_o <= 1'b1;
end
end
end
end
always_comb
begin
first_available_way = 0;
for(index=0;index<NB_WAYS;index++)
begin
if(way_valid_Q[index]==0)
first_available_way=index;
end
HIT_WAY = 0;
for(index=0;index<NB_WAYS;index++)
begin
if(way_match[index]==1)
HIT_WAY=index;
end
end
generate
if (NB_WAYS != 1)
begin
onehot_to_bin #( .ONEHOT_WIDTH(NB_WAYS) ) WAY_MATCH_BIN (.onehot(way_match), .bin(way_match_bin[ $clog2(NB_WAYS)-1:0]) );
assign way_match_bin[NB_WAYS-1:$clog2(NB_WAYS)] = 0;
end
else
begin
assign way_match_bin = '0;
end
endgenerate
endmodule // icache_top
module LFSR_8bit(
output logic [1:0] data_o,
input logic enable_i,
input logic clk,
input logic rst_n
);
logic q1,q2,q3,q4,q5,q6,q7,q8;
logic d1,d2,d3,d4,d5,d6,d7,d8;
always_ff @(posedge clk, negedge rst_n) begin
if(~rst_n) begin
q1 <= 1;
q2 <= 1;
q3 <= 1;
q4 <= 1;
q5 <= 1;
q6 <= 1;
q7 <= 1;
q8 <= 1;
end
else begin
if(enable_i) begin
q1 <= d1;
q2 <= d2;
q3 <= d3;
q4 <= d4;
q5 <= d5;
q6 <= d6;
q7 <= d7;
q8 <= d8;
end
end
end
assign d1 = q2^q3^q4^q8;
assign d2 = q1;
assign d3 = q2;
assign d4 = q3;
assign d5 = q4;
assign d6 = q5;
assign d7 = q6;
assign d8 = q7;
assign data_o = {q7,q8};
endmodule