【随感杂想】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_bank_private.sv*/ module icache_bank_private #( parameter FETCH_ADDR_WIDTH = 32, parameter FETCH_DATA_WIDTH = 32, parameter NB_WAYS = 4, parameter CACHE_SIZE = 4096, // in Byte parameter CACHE_LINE = 8, // in word of [FETCH_DATA_WIDTH] parameter USE_REDUCED_TAG = "FALSE", parameter TAG_BITS = 9, parameter AXI_ID = 10, parameter AXI_ADDR = 32, parameter AXI_USER = 1, parameter AXI_DATA = 32 ) ( input logic clk, input logic rst_n, input logic test_en_i, // 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, //AXI read address bus ------------------------------------------- output logic [AXI_ID-1:0] axi_master_arid_o, output logic [AXI_ADDR-1:0] axi_master_araddr_o, output logic [ 7:0] axi_master_arlen_o, //burst length - 1 to 16 output logic [ 2:0] axi_master_arsize_o, //size of each transfer in burst output logic [ 1:0] axi_master_arburst_o, //for bursts>1, accept only incr burst=01 output logic axi_master_arlock_o, //only normal access supported axs_awlock=00 output logic [ 3:0] axi_master_arcache_o, output logic [ 2:0] axi_master_arprot_o, output logic [ 3:0] axi_master_arregion_o, // output logic [ AXI_USER-1:0] axi_master_aruser_o, // output logic [ 3:0] axi_master_arqos_o, // output logic axi_master_arvalid_o, //master addr valid input logic axi_master_arready_i, //slave ready to accept // --------------------------------------------------------------- //AXI BACKWARD read data bus ---------------------------------------------- input logic [AXI_ID-1:0] axi_master_rid_i, input logic [AXI_DATA-1:0] axi_master_rdata_i, input logic [1:0] axi_master_rresp_i, input logic axi_master_rlast_i, //last transfer in burst input logic [AXI_USER-1:0] axi_master_ruser_i, input logic axi_master_rvalid_i, //slave data valid output logic axi_master_rready_o, //master ready to accept // NOT USED ---------------------------------------------- output logic [AXI_ID-1:0] axi_master_awid_o, output logic [AXI_ADDR-1:0] axi_master_awaddr_o, output logic [ 7:0] axi_master_awlen_o, output logic [ 2:0] axi_master_awsize_o, output logic [ 1:0] axi_master_awburst_o, output logic axi_master_awlock_o, output logic [ 3:0] axi_master_awcache_o, output logic [ 2:0] axi_master_awprot_o, output logic [ 3:0] axi_master_awregion_o, output logic [ AXI_USER-1:0] axi_master_awuser_o, output logic [ 3:0] axi_master_awqos_o, output logic axi_master_awvalid_o, input logic axi_master_awready_i, // NOT USED ---------------------------------------------- output logic [AXI_DATA-1:0] axi_master_wdata_o, output logic [AXI_DATA/8-1:0] axi_master_wstrb_o, output logic axi_master_wlast_o, output logic [ AXI_USER-1:0] axi_master_wuser_o, output logic axi_master_wvalid_o, input logic axi_master_wready_i, // --------------------------------------------------------------- // NOT USED ---------------------------------------------- input logic [AXI_ID-1:0] axi_master_bid_i, input logic [ 1:0] axi_master_bresp_i, input logic [ AXI_USER-1:0] axi_master_buser_i, input logic axi_master_bvalid_i, output logic axi_master_bready_o, // --------------------------------------------------------------- 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, 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, input logic [31:0] cache_config_i, input logic cache_stat_start_i, input logic cache_stat_clr_i, output logic cache_stat_ov_o, output logic [31:0] cache_ref_cnt_o, output logic [31:0] cache_err_cnt_o, output logic [31:0] cache_cycle_cnt_o ); localparam OFFSET = $clog2(FETCH_DATA_WIDTH)-3;//5-3=2 localparam WAY_SIZE = CACHE_SIZE/NB_WAYS;//4096/4=1024 localparam SCM_NUM_ROWS = WAY_SIZE/(CACHE_LINE*FETCH_DATA_WIDTH/8); // TAG 1024/(8*32/8) = 32 localparam SCM_TAG_ADDR_WIDTH = (SCM_NUM_ROWS == 1 ) ? 1 : $clog2(SCM_NUM_ROWS);//log(32) = 5 localparam LRU_BITS = 2; localparam TAG_WIDTH = (USE_REDUCED_TAG == "TRUE") ? (TAG_BITS + 1) : (FETCH_ADDR_WIDTH - $clog2(SCM_NUM_ROWS) - $clog2(CACHE_LINE) - OFFSET + 1 + LRU_BITS);//32 - 5 - 3 - 2 + 1 = 23 localparam RC_WIDTH = 17;//32 localparam DATA_WIDTH = FETCH_DATA_WIDTH;//32 localparam SCM_DATA_ADDR_WIDTH = $clog2(SCM_NUM_ROWS)+$clog2(CACHE_LINE); //5 + 3 = 8 Because of 32 Access localparam SET_ID_LSB = $clog2(DATA_WIDTH*CACHE_LINE)-3;//8 - 3 = 5 localparam SET_ID_MSB = (SCM_NUM_ROWS == 1) ? SET_ID_LSB : SET_ID_LSB + SCM_TAG_ADDR_WIDTH - 1;//10 localparam TAG_LSB = (SCM_NUM_ROWS == 1) ? SET_ID_LSB : SET_ID_MSB + 1;//11 localparam TAG_MSB = TAG_LSB + TAG_WIDTH - 2 ; //11 + 23 - 2 = 32 1 bit is count for valid logic [AXI_ID-1:0] axi_master_arid_int; logic [AXI_ADDR-1:0] axi_master_araddr_int; logic [ 7:0] axi_master_arlen_int; logic [ 2:0] axi_master_arsize_int; logic [ 1:0] axi_master_arburst_int; logic axi_master_arlock_int; logic [ 3:0] axi_master_arcache_int; logic [ 2:0] axi_master_arprot_int; logic [ 3:0] axi_master_arregion_int; logic [ AXI_USER-1:0] axi_master_aruser_int; logic [ 3:0] axi_master_arqos_int; logic axi_master_arvalid_int; logic axi_master_arready_int; logic [AXI_ID-1:0] axi_master_rid_int; logic [AXI_DATA-1:0] axi_master_rdata_int; logic [1:0] axi_master_rresp_int; logic axi_master_rlast_int; logic [AXI_USER-1:0] axi_master_ruser_int; logic axi_master_rvalid_int; logic axi_master_rready_int; logic clk_rbl; // interface with READ PORT --> SCM DATA logic [NB_WAYS-1:0] DATA_req_int; logic DATA_we_int; logic [SCM_DATA_ADDR_WIDTH-1:0] DATA_addr_int; logic [NB_WAYS-1:0][DATA_WIDTH-1:0] DATA_rdata_int; logic [DATA_WIDTH-1:0] DATA_wdata_int; logic [NB_WAYS-1:0] DATA_error_int; logic [NB_WAYS-1:0] DATA_need_correct_int; // interface with READ PORT --> SCM TAG logic [NB_WAYS-1:0] TAG_req_int; logic TAG_we_int; logic [SCM_TAG_ADDR_WIDTH-1:0] TAG_addr_int; logic [NB_WAYS-1:0][TAG_WIDTH-1:0] TAG_rdata_int; logic [TAG_WIDTH-1:0] TAG_wdata_int; logic [NB_WAYS-1:0] DATA_read_enable; logic [NB_WAYS-1:0] DATA_write_enable; logic [NB_WAYS-1:0] TAG_read_enable; logic [NB_WAYS-1:0] TAG_write_enable; // ██╗ ██████╗ █████╗ ██████╗██╗ ██╗███████╗ ██████╗████████╗██████╗ ██╗ // ██║██╔════╝██╔══██╗██╔════╝██║ ██║██╔════╝ ██╔════╝╚══██╔══╝██╔══██╗██║ // ██║██║ ███████║██║ ███████║█████╗ ██║ ██║ ██████╔╝██║ // ██║██║ ██╔══██║██║ ██╔══██║██╔══╝ ██║ ██║ ██╔══██╗██║ // ██║╚██████╗██║ ██║╚██████╗██║ ██║███████╗███████╗╚██████╗ ██║ ██║ ██║███████╗ // ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝ icache_controller_private #( .FETCH_ADDR_WIDTH ( FETCH_ADDR_WIDTH ), .FETCH_DATA_WIDTH ( FETCH_DATA_WIDTH ), .NB_WAYS ( NB_WAYS ), .CACHE_LINE ( CACHE_LINE ), .SCM_TAG_ADDR_WIDTH ( SCM_TAG_ADDR_WIDTH ), .SCM_DATA_ADDR_WIDTH ( SCM_DATA_ADDR_WIDTH ), .SCM_TAG_WIDTH ( TAG_WIDTH ), .SCM_DATA_WIDTH ( DATA_WIDTH ), .SCM_NUM_ROWS ( SCM_NUM_ROWS ), .SET_ID_LSB ( SET_ID_LSB ), .SET_ID_MSB ( SET_ID_MSB ), .TAG_LSB ( TAG_LSB ), .TAG_MSB ( TAG_MSB ), .AXI_ID ( AXI_ID ), .AXI_ADDR ( AXI_ADDR ), .AXI_USER ( AXI_USER ), .AXI_DATA ( AXI_DATA ) ) i_icache_controller_private ( .clk ( clk ), .rst_n ( rst_n ), .test_en_i ( test_en_i ), .bypass_icache_i ( bypass_icache_i ), .cache_is_bypassed_o ( cache_is_bypassed_o ), .flush_icache_i ( flush_icache_i ), .cache_is_flushed_o ( cache_is_flushed_o ), .flush_set_ID_req_i ( flush_set_ID_req_i ), .flush_set_ID_addr_i ( flush_set_ID_addr_i ), .flush_set_ID_ack_o ( flush_set_ID_ack_o ), // interface with processor .fetch_req_i ( fetch_req_i ), .fetch_addr_i ( fetch_addr_i ), .fetch_gnt_o ( fetch_gnt_o ), .fetch_rvalid_o ( fetch_rvalid_o ), .fetch_rdata_o ( fetch_rdata_o ), // interface with READ PORT --> SCM DATA .DATA_req_o ( DATA_req_int ), .DATA_we_o ( DATA_we_int ), .DATA_addr_o ( DATA_addr_int ), .DATA_rdata_i ( DATA_rdata_int ), .DATA_wdata_o ( DATA_wdata_int ), .DATA_error_i ( DATA_error_int ), .DATA_need_correct_o ( DATA_need_correct_int), // interface with READ PORT --> SCM TAG .TAG_req_o ( TAG_req_int ), .TAG_addr_o ( TAG_addr_int ), .TAG_rdata_i ( TAG_rdata_int ), .TAG_wdata_o ( TAG_wdata_int ), .TAG_we_o ( TAG_we_int ), // Interface to cache_controller_to_axi .axi_ar_valid_o ( axi_master_arvalid_int ), .axi_ar_ready_i ( axi_master_arready_int ), .axi_ar_addr_o ( axi_master_araddr_int ), .axi_ar_len_o ( axi_master_arlen_int ), .axi_r_valid_i ( axi_master_rvalid_int ), .axi_r_ready_o ( axi_master_rready_int ), .axi_r_data_i ( axi_master_rdata_int ), .axi_r_last_i ( axi_master_rlast_int ), .ctrl_hit_count_icache_o (ctrl_hit_count_icache_o ), .ctrl_trans_count_icache_o(ctrl_trans_count_icache_o ), .ctrl_miss_count_icache_o (ctrl_miss_count_icache_o ), .ctrl_clear_regs_icache_i (ctrl_clear_regs_icache_i ), .ctrl_enable_regs_icache_i(ctrl_enable_regs_icache_i ), .ref_count_o ( cache_ref_cnt_o ), .err_count_o ( cache_err_cnt_o ), .cycle_count_o ( cache_cycle_cnt_o ), .count_enable_i ( cache_stat_start_i ), .count_clr_i ( cache_stat_clr_i ), .count_ov_o ( cache_stat_ov_o ) ); rbl #(.CK_PERIOD(0.19)) rbl_i( .CLK_RBL(clk_rbl) ); genvar i; generate // ████████╗ █████╗ ██████╗ ██████╗ █████╗ ███╗ ██╗██╗ ██╗ // ╚══██╔══╝██╔══██╗██╔════╝ ██╔══██╗██╔══██╗████╗ ██║██║ ██╔╝ // ██║ ███████║██║ ███╗ ██████╔╝███████║██╔██╗ ██║█████╔╝ // ██║ ██╔══██║██║ ██║ ██╔══██╗██╔══██║██║╚██╗██║██╔═██╗ // ██║ ██║ ██║╚██████╔╝███████╗██████╔╝██║ ██║██║ ╚████║██║ ██╗ // ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝ for(i=0; i<NB_WAYS; i++) begin : _TAG_WAY_ assign TAG_read_enable[i] = TAG_req_int[i]; assign TAG_write_enable[i] = TAG_req_int[i] & TAG_we_int; tag_ram #( .TAG_WIDTH ( TAG_WIDTH ), .ADDR_WIDTH ( SCM_TAG_ADDR_WIDTH ) ) tag_array ( .clk ( clk ), .rst_n ( rst_n ), .en_i ( TAG_read_enable[i] ), .addr_i ( TAG_addr_int ), .we_i ( TAG_write_enable[i] ), .wdata_i ( TAG_wdata_int ), .rdata_o ( TAG_rdata_int[i] ) ); end rc_ram #( .RC_WIDTH (RC_WIDTH ), .ADDR_WIDTH(SCM_TAG_ADDR_WIDTH), .INIT_FILE ("../testbench/rc0.dat") ) rc_array0 ( .clk ( clk ), .rst_n ( rst_n ), .en_i ( TAG_read_enable[0] ), .addr_i ( TAG_addr_int ), .we_i ( 0 ), .wdata_i ( 0 ), .rdata_o ( RC_rdata_int[0] ) ); rc_ram #( .RC_WIDTH (RC_WIDTH ), .ADDR_WIDTH(SCM_TAG_ADDR_WIDTH), .INIT_FILE("../testbench/rc1.dat") ) rc_array1 ( .clk ( clk ), .rst_n ( rst_n ), .en_i ( TAG_read_enable[1] ), .addr_i ( TAG_addr_int ), .we_i ( 0 ), .wdata_i ( 0 ), .rdata_o ( RC_rdata_int[1] ) ); rc_ram #( .RC_WIDTH (RC_WIDTH ), .ADDR_WIDTH(SCM_TAG_ADDR_WIDTH), .INIT_FILE("../testbench/rc2.dat") ) rc_array2 ( .clk ( clk ), .rst_n ( rst_n ), .en_i ( TAG_read_enable[2] ), .addr_i ( TAG_addr_int ), .we_i ( 0 ), .wdata_i ( 0 ), .rdata_o ( RC_rdata_int[2] ) ); rc_ram #( .RC_WIDTH (RC_WIDTH ), .ADDR_WIDTH(SCM_TAG_ADDR_WIDTH), .INIT_FILE("../testbench/rc3.dat") ) rc_array3 ( .clk ( clk ), .rst_n ( rst_n ), .en_i ( TAG_read_enable[3] ), .addr_i ( TAG_addr_int ), .we_i ( 0 ), .wdata_i ( 0 ), .rdata_o ( RC_rdata_int[3] ) ); // ██████╗ █████╗ ████████╗ █████╗ ██████╗ █████╗ ███╗ ██╗██╗ ██╗ // ██╔══██╗██╔══██╗╚══██╔══╝██╔══██╗ ██╔══██╗██╔══██╗████╗ ██║██║ ██╔╝ // ██║ ██║███████║ ██║ ███████║ ██████╔╝███████║██╔██╗ ██║█████╔╝ // ██║ ██║██╔══██║ ██║ ██╔══██║ ██╔══██╗██╔══██║██║╚██╗██║██╔═██╗ // ██████╔╝██║ ██║ ██║ ██║ ██║███████╗██████╔╝██║ ██║██║ ╚████║██║ ██╗ // ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝ for(i=0; i<NB_WAYS; i++) begin : _DATA_WAY_ assign DATA_read_enable[i] = DATA_req_int[i] ; assign DATA_write_enable[i] = DATA_req_int[i] & DATA_we_int; end ssram #( .TBL_FILE("../testbench/tbl0.dat") ) data_array0( .SLEEP ( 1'b0 ), .rst_n ( rst_n ), .CLK ( clk ), .CLK_G ( 1'b0 ), .CLK_RBL ( clk_rbl ), .MODE ( DATA_need_correct_int[0]), .BOOST_EN ( 1'b0 ), .CEN ( ~DATA_read_enable[0] ), .WEN ( ~DATA_write_enable[0] ), .FLAG ( DATA_error_int[0] ), .EN ( cache_config_i ), .BRS ( DATA_addr_int ), .WL_IN ( 256'b0 ), .D ( DATA_wdata_int ), .Q ( DATA_rdata_int[0] ) ); ssram #( .TBL_FILE("../testbench/tbl1.dat") ) data_array1( .SLEEP ( 1'b0 ), .rst_n ( rst_n ), .CLK ( clk ), .CLK_G ( 1'b0 ), .CLK_RBL ( clk_rbl ), .MODE ( DATA_need_correct_int[1]), .BOOST_EN ( 1'b0 ), .CEN ( ~DATA_read_enable[1] ), .WEN ( ~DATA_write_enable[1] ), .FLAG ( DATA_error_int[1] ), .EN ( cache_config_i ), .BRS ( DATA_addr_int ), .WL_IN ( 256'b0 ), .D ( DATA_wdata_int ), .Q ( DATA_rdata_int[1] ) ); ssram #( .TBL_FILE("../testbench/tbl2.dat") ) data_array2( .SLEEP ( 1'b0 ), .rst_n ( rst_n ), .CLK ( clk ), .CLK_G ( 1'b0 ), .CLK_RBL ( clk_rbl ), .MODE ( DATA_need_correct_int[2]), .BOOST_EN ( 1'b0 ), .CEN ( ~DATA_read_enable[2] ), .WEN ( ~DATA_write_enable[2] ), .FLAG ( DATA_error_int[2] ), .EN ( cache_config_i ), .BRS ( DATA_addr_int ), .WL_IN ( 256'b0 ), .D ( DATA_wdata_int ), .Q ( DATA_rdata_int[2] ) ); ssram #( .TBL_FILE("../testbench/tbl3.dat") ) data_array3( .SLEEP ( 1'b0 ), .rst_n ( rst_n ), .CLK ( clk ), .CLK_G ( 1'b0 ), .CLK_RBL ( clk_rbl ), .MODE ( DATA_need_correct_int[3]), .BOOST_EN ( 1'b0 ), .CEN ( ~DATA_read_enable[3] ), .WEN ( ~DATA_write_enable[3] ), .FLAG ( DATA_error_int[3] ), .EN ( cache_config_i ), .BRS ( DATA_addr_int ), .WL_IN ( 256'b0 ), .D ( DATA_wdata_int ), .Q ( DATA_rdata_int[3] ) ); endgenerate assign axi_master_arid_int = {AXI_ID{1'b0}}; assign axi_master_arsize_int = 3'b011; //64 bits -> 8 bytes assign axi_master_arburst_int = 2'b01; //INCR assign axi_master_arlock_int = 1'b0; assign axi_master_arcache_int = 4'b0000; assign axi_master_arprot_int = 3'b000; assign axi_master_arregion_int = 4'b0000; assign axi_master_aruser_int = {AXI_USER{1'b0}}; assign axi_master_arqos_int = 4'b0000; assign axi_master_arvalid_o = axi_master_arvalid_int; assign axi_master_araddr_o = axi_master_araddr_int; assign axi_master_arprot_o = axi_master_arprot_int; assign axi_master_arregion_o = axi_master_arregion_int; assign axi_master_arlen_o = axi_master_arlen_int; assign axi_master_arsize_o = axi_master_arsize_int; assign axi_master_arburst_o = axi_master_arburst_int; assign axi_master_arlock_o = axi_master_arlock_int; assign axi_master_arcache_o = axi_master_arcache_int; assign axi_master_arqos_o = axi_master_arqos_int; assign axi_master_arid_o[AXI_ID-1:0] = axi_master_arid_int[AXI_ID-1:0]; assign axi_master_aruser_o = axi_master_aruser_int; assign axi_master_arready_int = axi_master_arready_i; assign axi_master_rvalid_int = axi_master_rvalid_i; assign axi_master_rdata_int = axi_master_rdata_i; assign axi_master_rresp_int = axi_master_rresp_i; assign axi_master_ruser_int = axi_master_ruser_i; assign axi_master_rid_int[AXI_ID-1:0] = axi_master_rid_i[AXI_ID-1:0]; assign axi_master_rlast_int = axi_master_rlast_i; assign axi_master_rready_o = axi_master_rready_int; // █████╗ ██╗ ██╗██╗ █████╗ ██████╗ ██████╗ ██╗ ██╗███████╗███████╗ // ██╔══██╗╚██╗██╔╝██║ ██╔══██╗██╔══██╗ ██╔══██╗██║ ██║██╔════╝██╔════╝ // ███████║ ╚███╔╝ ██║ ███████║██████╔╝ ██████╔╝██║ ██║█████╗ █████╗ // ██╔══██║ ██╔██╗ ██║ ██╔══██║██╔══██╗ ██╔══██╗██║ ██║██╔══╝ ██╔══╝ // ██║ ██║██╔╝ ██╗██║███████╗██║ ██║██║ ██║███████╗██████╔╝╚██████╔╝██║ ██║ // ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═════╝ ╚═════╝ ╚═╝ ╚═╝ /*axi_ar_buffer #( .ID_WIDTH ( AXI_ID ), .ADDR_WIDTH ( AXI_ADDR ), .USER_WIDTH ( AXI_USER ), .BUFFER_DEPTH ( 2 ) ) i_AXI_AR_BUFFER ( .clk_i ( clk ), .rst_ni ( rst_n ), .test_en_i ( test_en_i ), .slave_valid_i ( axi_master_arvalid_int ), .slave_addr_i ( axi_master_araddr_int ), .slave_prot_i ( axi_master_arprot_int ), .slave_region_i ( axi_master_arregion_int ), .slave_len_i ( axi_master_arlen_int ), .slave_size_i ( axi_master_arsize_int ), .slave_burst_i ( axi_master_arburst_int ), .slave_lock_i ( axi_master_arlock_int ), .slave_cache_i ( axi_master_arcache_int ), .slave_qos_i ( axi_master_arqos_int ), .slave_id_i ( axi_master_arid_int[AXI_ID-1:0] ), .slave_user_i ( axi_master_aruser_int ), .slave_ready_o ( axi_master_arready_int ), .master_valid_o ( axi_master_arvalid_o ), .master_addr_o ( axi_master_araddr_o ), .master_prot_o ( axi_master_arprot_o ), .master_region_o ( axi_master_arregion_o ), .master_len_o ( axi_master_arlen_o ), .master_size_o ( axi_master_arsize_o ), .master_burst_o ( axi_master_arburst_o ), .master_lock_o ( axi_master_arlock_o ), .master_cache_o ( axi_master_arcache_o ), .master_qos_o ( axi_master_arqos_o ), .master_id_o ( axi_master_arid_o[AXI_ID-1:0] ), .master_user_o ( axi_master_aruser_o ), .master_ready_i ( axi_master_arready_i ) ); // █████╗ ██╗ ██╗██╗ ██████╗ ██████╗ ██╗ ██╗███████╗███████╗ // ██╔══██╗╚██╗██╔╝██║ ██╔══██╗ ██╔══██╗██║ ██║██╔════╝██╔════╝ // ███████║ ╚███╔╝ ██║ ██████╔╝ ██████╔╝██║ ██║█████╗ █████╗ // ██╔══██║ ██╔██╗ ██║ ██╔══██╗ ██╔══██╗██║ ██║██╔══╝ ██╔══╝ // ██║ ██║██╔╝ ██╗██║███████╗██║ ██║███████╗██████╔╝╚██████╔╝██║ ██║ // ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚══════╝╚═╝ ╚═╝╚══════╝╚═════╝ ╚═════╝ ╚═╝ ╚═╝ axi_r_buffer #( .ID_WIDTH ( AXI_ID ), .DATA_WIDTH ( AXI_DATA ), .USER_WIDTH ( AXI_USER ), .BUFFER_DEPTH ( 2 ) ) i_AXI_R_BUFFER ( .clk_i ( clk ), .rst_ni ( rst_n ), .test_en_i ( test_en_i ), .slave_valid_i ( axi_master_rvalid_i ), .slave_data_i ( axi_master_rdata_i ), .slave_resp_i ( axi_master_rresp_i ), .slave_user_i ( axi_master_ruser_i ), .slave_id_i ( axi_master_rid_i[AXI_ID-1:0] ), .slave_last_i ( axi_master_rlast_i ), .slave_ready_o ( axi_master_rready_o ), .master_valid_o ( axi_master_rvalid_int ), .master_data_o ( axi_master_rdata_int ), .master_resp_o ( axi_master_rresp_int ), .master_user_o ( axi_master_ruser_int ), .master_id_o ( axi_master_rid_int[AXI_ID-1:0] ), .master_last_o ( axi_master_rlast_int ), .master_ready_i ( axi_master_rready_int ) );*/ assign axi_master_awid_o = {AXI_ID{1'b0}}; assign axi_master_awaddr_o = {AXI_ADDR{1'b0}}; assign axi_master_awlen_o = 8'b0000_0000; assign axi_master_awsize_o = 3'b000; assign axi_master_awburst_o = 2'b00; assign axi_master_awlock_o = 1'b0; assign axi_master_awcache_o = 4'b0000; assign axi_master_awprot_o = 3'b000; assign axi_master_awregion_o = 4'b0000; assign axi_master_awuser_o = {AXI_USER{1'b0}}; assign axi_master_awqos_o = 4'b0000; assign axi_master_awvalid_o = 1'b0; assign axi_master_wdata_o = {AXI_DATA{1'b0}}; assign axi_master_wstrb_o = {AXI_DATA/8{1'b0}};; assign axi_master_wlast_o = 1'b0; assign axi_master_wuser_o = {AXI_USER{1'b0}}; assign axi_master_wvalid_o = 1'b0; assign axi_master_bready_o = 1'b0; endmodule // top_icache_bank
// 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 dcache_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, input logic fetch_we_i, input logic [FETCH_DATA_WIDTH-1:0] fetch_wdata_i, // 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 [AXI_ADDR-1:0] axi_aw_addr_o, output logic [ 7:0] axi_aw_len_o, output logic axi_aw_valid_o, input logic axi_aw_ready_i, output logic [AXI_DATA-1:0] axi_w_data_o, output logic axi_w_last_o, output logic axi_w_valid_o, input logic axi_w_ready_i, input logic axi_b_valid_i, output logic axi_b_ready_o, 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_WIDTH = $clog2(CACHE_LINE); 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 [OFFSET_WIDTH-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 [NB_WAYS-1:0 ] TAG_WE, TAG_WE_d; logic [SCM_TAG_WIDTH-1:0] TAG_WDATA, TAG_WDATA_d; logic DATA_WE, DATA_WE_d; logic [SCM_DATA_WIDTH-1:0] DATA_WDATA, DATA_WDATA_d; logic is_same_block; logic in_correcting, in_correcting_d; logic fetch_we_q; logic [SCM_DATA_WIDTH-1:0] fetch_wdata_q; 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] HIT_WAY; logic [$clog2(NB_WAYS)-1:0] victim_d, victim_q; 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) axi_r_data_i_delay <= '0; else if(axi_r_valid_i & axi_r_ready_o) axi_r_data_i_delay <= axi_r_data_i; end enum logic [2:0] { DISABLED_ICACHE, WAIT_REFILL_DONE, OPERATIVE, REQ_REFILL, WRITE_BACK, 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 <= '0; fetch_req_Q <= 1'b0; fetch_we_q <= 0; fetch_wdata_q <= 'b0; end else if(enable_pipe) begin fetch_req_Q <= 1'b1; fetch_addr_Q <= fetch_addr_i; fetch_we_q <= fetch_we_i; fetch_wdata_q <= fetch_wdata_i; end else if(clear_pipe) begin fetch_req_Q <= '0; fetch_we_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; DATA_WE <= 0; DATA_WDATA <= 0; TAG_WE <= 0; TAG_WDATA <= 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; TAG_WE <= TAG_WE_d ; DATA_WE <= DATA_WE_d ; TAG_WDATA <= TAG_WDATA_d ; DATA_WDATA <= DATA_WDATA_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-2] == 1'b1) && (TAG_rdata_i[k][SCM_TAG_WIDTH-3:0] == fetch_addr_Q[TAG_MSB:TAG_LSB])); assign way_valid[k] = (TAG_rdata_i[k][SCM_TAG_WIDTH-2] == 1'b1); end endgenerate //TAG RAM always_comb begin if(CS == FLUSH_ICACHE) begin TAG_req_o = 4'b1111; 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 = {fetch_we_q,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 = (fetch_we_q & (refill_cnt_q == fetch_addr_Q[SET_ID_LSB-1:2])) ? fetch_wdata_q : 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 case(CS) DISABLED_ICACHE: begin if(bypass_icache_i == 1'b1) NS = DISABLED_ICACHE; else NS = WAIT_PENDING_TRANS; end WAIT_PENDING_TRANS: begin if(pending_trans_dis_cache == 1'b0) NS = FLUSH_ICACHE; // Flushing is made in the central controller else NS = WAIT_PENDING_TRANS; end FLUSH_ICACHE: begin if(counter_FLUSH_CS < 2**SCM_TAG_ADDR_WIDTH-1) NS = FLUSH_ICACHE; else NS = OPERATIVE; end FLUSH_SET_ID: begin NS = OPERATIVE; end 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 !! force on this case!! begin if(fetch_req_Q) begin if(|way_match) NS = OPERATIVE; else NS = REQ_REFILL; end else //~fetch_req_Q NS = OPERATIVE; end end REQ_REFILL: begin if(TAG_rdata_i[victim_d][SCM_TAG_WIDTH-1] & axi_aw_ready_i) NS = WRITE_BACK; else if(axi_ar_ready_i) NS = WAIT_REFILL_DONE; else NS = REQ_REFILL; end WRITE_BACK: begin if((refill_cnt_q == '1) & axi_ar_ready_i) NS = WAIT_REFILL_DONE; else NS = WRITE_BACK; end 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 default: begin NS = DISABLED_ICACHE; end endcase 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; 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 if(fetch_req_Q &(|way_match)&DATA_error_i[HIT_WAY]) enable_pipe = 0; else if(fetch_req_Q &(~(|way_match))) enable_pipe = 0; else enable_pipe = fetch_req_i; end else enable_pipe = 1'b0; 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 & (|way_match) &(fetch_req_i == 1'b0)) clear_pipe = 1'b1; else if(~fetch_req_Q) clear_pipe = 1'b1; else clear_pipe = 1'b0; end else begin if(fetch_req_Q & (|way_match) & (~DATA_error_i[HIT_WAY])) clear_pipe = ~fetch_req_i; else clear_pipe = 1'b0; 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 if((CS == OPERATIVE) & (~(bypass_icache_i | flush_icache_i | flush_set_ID_req_i ))) begin if(fetch_req_Q & (|way_match) & fetch_we_q & (~DATA_WE)) begin TAG_CS_d = way_match & ~{NB_WAYS{TAG_rdata_i[HIT_WAY][SCM_TAG_WIDTH-1]}}; TAG_WE_d = way_match & ~{NB_WAYS{TAG_rdata_i[HIT_WAY][SCM_TAG_WIDTH-1]}}; DATA_CS_d = way_match; DATA_WE_d = |way_match; end else if(fetch_req_Q & (|way_match) & (~fetch_we_q) & DATA_error_i[HIT_WAY]) begin DATA_WE_d = 'b0; TAG_WE_d = 'b0; DATA_CS_d = way_match; TAG_CS_d = 'b0; end else if(fetch_req_i) begin if(is_same_block) begin if(fetch_we_i) begin DATA_WE_d = 1'b1; TAG_WE_d = way_match & ~{NB_WAYS{TAG_rdata_i[HIT_WAY][SCM_TAG_WIDTH-1]}}; DATA_CS_d = way_match; TAG_CS_d = way_match & ~{NB_WAYS{TAG_rdata_i[HIT_WAY][SCM_TAG_WIDTH-1]}}; end else begin DATA_WE_d = 'b0; TAG_WE_d = 'b0; DATA_CS_d = way_match; TAG_CS_d = 'b0; end end else //not the same block begin if(fetch_we_i) begin DATA_WE_d = 'b0; TAG_WE_d = 'b0; DATA_CS_d = 'b0; TAG_CS_d = 4'b1111; end else begin DATA_WE_d = 'b0; TAG_WE_d = 'b0; TAG_CS_d = 4'b1111; DATA_CS_d = 4'b1111; end end end //~if(fetch_req_i) else begin DATA_WE_d = 'b0; TAG_WE_d = 'b0; DATA_CS_d = 'b0; TAG_CS_d = 'b0; end end else begin DATA_WE_d = 'b0; TAG_WE_d = 'b0; DATA_CS_d = 'b0; TAG_CS_d = 'b0; end end always_comb begin axi_ar_valid_o = 1'b0; axi_r_ready_o = 1'b1; axi_ar_addr_o = fetch_addr_i; axi_aw_addr_o = 0; axi_aw_valid_o = 0; axi_w_data_o = 0; axi_w_valid_o = 0; axi_w_last_o = 0; if(CS == DISABLED_ICACHE) begin 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 else if (CS == WAIT_PENDING_TRANS) axi_ar_valid_o = 1'b0; else if (CS == REQ_REFILL) begin if(TAG_rdata_i[victim_d][SCM_TAG_WIDTH-1]) begin axi_aw_valid_o = 1; axi_aw_addr_o = {TAG_rdata_i[victim_d][SCM_TAG_WIDTH-3:0],fetch_addr_Q[SET_ID_MSB:SET_ID_LSB],5'b0}; end else begin axi_ar_valid_o = 1'b1; axi_ar_addr_o = fetch_addr_Q; end end else if (CS == WRITE_BACK) begin axi_w_data_o = DATA_rdata_i[victim_q]; axi_w_valid_o = ~DATA_error_i[victim_q]; if(refill_cnt_q == '1) begin axi_w_last_o = axi_w_ready_i ? 1 : 0; axi_ar_valid_o = 1; axi_ar_addr_o = fetch_addr_Q; end end end always_comb begin if(CS == OPERATIVE) begin if(~(bypass_icache_i | flush_icache_i | flush_set_ID_req_i )) begin if(fetch_req_Q &(|way_match)& DATA_error_i[HIT_WAY]) in_correcting_d = 1 ; else in_correcting_d = 0 ; end else in_correcting_d = 0 ; end else in_correcting_d = 0 ; end //always_comb //begin // if((CS == OPERATIVE) & (~(bypass_icache_i | flush_icache_i | flush_set_ID_req_i ))) // begin // TAG_wdata_o = {1'b1, 1'b1, TAG_rdata_i[HIT_WAY][SCM_TAG_WIDTH-3:0]}; // DATA_wdata_o = fetch_wdata_q; // end always_comb begin if(CS == DISABLED_ICACHE) begin cache_is_bypassed_o = 1'b1; cache_is_flushed_o = 1'b1; end else if(CS == WAIT_PENDING_TRANS) begin cache_is_bypassed_o = 1'b1; cache_is_flushed_o = 1'b1; end else if(CS == FLUSH_ICACHE) begin cache_is_flushed_o = (~(counter_FLUSH_CS < 2**SCM_TAG_ADDR_WIDTH-1)); cache_is_bypassed_o = 1'b0; end //~FLUSH_ICACHE else begin cache_is_bypassed_o = 1'b0; cache_is_flushed_o = 1'b0; end end generate if(NB_WAYS == 1) begin : DIRECT_MAPPED assign random_way = 1'b0; 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) & (~fetch_we_q) & 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