【随感杂想】Cache优化
// 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