//******************************************************************************** // SPDX-License-Identifier: Apache-2.0 // Copyright 2020 Western Digital Corporation or its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the 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 DATA & TAG MODULE WRAPPER // ///////////////////////////////////////////////////// module ifu_ic_mem //`include "parameter.sv" #( parameter ICACHE_BEAT_BITS, parameter ICACHE_NUM_WAYS, parameter ICACHE_BANK_BITS, parameter ICACHE_BEAT_ADDR_HI, parameter ICACHE_BANKS_WAY, parameter ICACHE_INDEX_HI, parameter ICACHE_BANK_HI, parameter ICACHE_BANK_LO, parameter ICACHE_TAG_LO, parameter ICACHE_DATA_INDEX_LO, parameter ICACHE_ECC, parameter ICACHE_TAG_DEPTH, parameter ICACHE_WAYPACK, parameter ICACHE_TAG_INDEX_LO, parameter ICACHE_DATA_DEPTH, parameter ICACHE_NUM_BYPASS, parameter ICACHE_TAG_NUM_BYPASS, parameter ICACHE_TAG_NUM_BYPASS_WIDTH, parameter ICACHE_TAG_BYPASS_ENABLE, parameter ICACHE_NUM_BYPASS_WIDTH, parameter ICACHE_BYPASS_ENABLE, parameter ICACHE_LN_SZ ) ( input logic clk, // Clock only while core active. Through one clock header. For flops with second clock header built in. Connected to ACTIVE_L2CLK. input logic active_clk, // Clock only while core active. Through two clock headers. For flops without second clock header built in. input logic rst_l, // reset, active low input logic clk_override, // Override non-functional clock gating input logic dec_tlu_core_ecc_disable, // Disable ECC checking input logic [31:1] ic_rw_addr, input logic [ICACHE_NUM_WAYS-1:0] ic_wr_en , // Which way to write input logic ic_rd_en , // Read enable input logic [ICACHE_INDEX_HI:3] ic_debug_addr, // Read/Write addresss to the Icache. input logic ic_debug_rd_en, // Icache debug rd input logic ic_debug_wr_en, // Icache debug wr input logic ic_debug_tag_array, // Debug tag array input logic [ICACHE_NUM_WAYS-1:0] ic_debug_way, // Debug way. Rd or Wr. input logic [63:0] ic_premux_data, // Premux data to be muxed with each way of the Icache. input logic ic_sel_premux_data, // Select the pre_muxed data input logic [70:0] ic_wr_data_0, // Data to fill to the Icache. With ECC input logic [70:0] ic_wr_data_1, // Data to fill to the Icache. With ECC output logic [63:0] ic_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC output logic [70:0] ic_debug_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC output logic [25:0] ic_tag_debug_rd_data,// Debug icache tag. input logic [70:0] ic_debug_wr_data, // Debug wr cache. output logic [ICACHE_BANKS_WAY-1:0] ic_eccerr, // ecc error per bank output logic [ICACHE_BANKS_WAY-1:0] ic_parerr, // ecc error per bank input logic [ICACHE_NUM_WAYS-1:0] ic_tag_valid, // Valid from the I$ tag valid outside (in flops). input ic_data_ext_in_pkt_t [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0] ic_data_ext_in_pkt, // this is being driven by the top level for soc testing/etc input ic_tag_ext_in_pkt_t [ICACHE_NUM_WAYS-1:0] ic_tag_ext_in_pkt, // this is being driven by the top level for soc testing/etc output logic [ICACHE_NUM_WAYS-1:0] ic_rd_hit, // ic_rd_hit[3:0] output logic ic_tag_perr, // Tag Parity error input logic scan_mode // Flop scan mode control ) ; IC_TAG #( .ICACHE_BEAT_BITS(ICACHE_BEAT_BITS), .ICACHE_NUM_WAYS(ICACHE_NUM_WAYS), .ICACHE_TAG_NUM_BYPASS(ICACHE_TAG_NUM_BYPASS), .ICACHE_BEAT_ADDR_HI(ICACHE_BEAT_ADDR_HI), .ICACHE_TAG_NUM_BYPASS_WIDTH(ICACHE_TAG_NUM_BYPASS_WIDTH), .ICACHE_TAG_BYPASS_ENABLE(ICACHE_TAG_BYPASS_ENABLE), .ICACHE_BYPASS_ENABLE(ICACHE_BYPASS_ENABLE), .ICACHE_TAG_LO(ICACHE_TAG_LO), .ICACHE_ECC(ICACHE_ECC), .ICACHE_TAG_DEPTH(ICACHE_TAG_DEPTH), .ICACHE_WAYPACK(ICACHE_WAYPACK), .ICACHE_INDEX_HI(ICACHE_INDEX_HI), .ICACHE_TAG_INDEX_LO(ICACHE_TAG_INDEX_LO)) ic_tag_inst ( .*, .ic_wr_en (ic_wr_en[ICACHE_NUM_WAYS-1:0]), .ic_debug_addr(ic_debug_addr[ICACHE_INDEX_HI:3]), .ic_rw_addr (ic_rw_addr[31:3]) ) ; IC_DATA #(.ICACHE_BEAT_BITS(ICACHE_BEAT_BITS), .ICACHE_NUM_WAYS(ICACHE_NUM_WAYS), .ICACHE_BANK_BITS(ICACHE_BANK_BITS), .ICACHE_BEAT_ADDR_HI(ICACHE_BEAT_ADDR_HI), .ICACHE_BANKS_WAY(ICACHE_BANKS_WAY), .ICACHE_INDEX_HI(ICACHE_INDEX_HI), .ICACHE_BANK_HI(ICACHE_BANK_HI), .ICACHE_BANK_LO(ICACHE_BANK_LO), .ICACHE_TAG_LO(ICACHE_TAG_LO), .ICACHE_DATA_INDEX_LO(ICACHE_DATA_INDEX_LO), .ICACHE_ECC(ICACHE_ECC), .ICACHE_TAG_DEPTH(ICACHE_TAG_DEPTH), .ICACHE_WAYPACK(ICACHE_WAYPACK), .ICACHE_TAG_INDEX_LO(ICACHE_TAG_INDEX_LO), .ICACHE_DATA_DEPTH(ICACHE_DATA_DEPTH), .ICACHE_NUM_BYPASS(ICACHE_NUM_BYPASS), .ICACHE_TAG_NUM_BYPASS(ICACHE_TAG_NUM_BYPASS), .ICACHE_TAG_NUM_BYPASS_WIDTH(ICACHE_TAG_NUM_BYPASS_WIDTH), .ICACHE_TAG_BYPASS_ENABLE(ICACHE_TAG_BYPASS_ENABLE), .ICACHE_NUM_BYPASS_WIDTH(ICACHE_NUM_BYPASS_WIDTH), .ICACHE_BYPASS_ENABLE(ICACHE_BYPASS_ENABLE), .ICACHE_LN_SZ(ICACHE_LN_SZ)) ic_data_inst ( .*, .ic_wr_en (ic_wr_en[ICACHE_NUM_WAYS-1:0]), .ic_debug_addr(ic_debug_addr[ICACHE_INDEX_HI:3]), .ic_rw_addr (ic_rw_addr[31:1]) ) ; endmodule ///////////////////////////////////////////////// ////// ICACHE DATA MODULE //////////////////// ///////////////////////////////////////////////// module IC_DATA //`include "parameter.sv" #( parameter ICACHE_BEAT_BITS, parameter ICACHE_NUM_WAYS, parameter ICACHE_BANK_BITS, parameter ICACHE_BEAT_ADDR_HI, parameter ICACHE_BANKS_WAY, parameter ICACHE_INDEX_HI, parameter ICACHE_BANK_HI, parameter ICACHE_BANK_LO, parameter ICACHE_TAG_LO, parameter ICACHE_DATA_INDEX_LO, parameter ICACHE_ECC, parameter ICACHE_TAG_DEPTH, parameter ICACHE_WAYPACK, parameter ICACHE_TAG_INDEX_LO, parameter ICACHE_DATA_DEPTH, parameter ICACHE_NUM_BYPASS, parameter ICACHE_TAG_NUM_BYPASS, parameter ICACHE_TAG_NUM_BYPASS_WIDTH, parameter ICACHE_TAG_BYPASS_ENABLE, parameter ICACHE_NUM_BYPASS_WIDTH, parameter ICACHE_BYPASS_ENABLE, parameter ICACHE_LN_SZ ) ( input logic clk, input logic active_clk, input logic rst_l, input logic clk_override, input logic [31:1] ic_rw_addr, input logic [ICACHE_NUM_WAYS-1:0]ic_wr_en, input logic ic_rd_en, // Read enable // input logic [ICACHE_BANKS_WAY-1:0][70:0] ic_wr_data, // Data to fill to the Icache. With ECC input logic [70:0] ic_wr_data_0, // Data to fill to the Icache. With ECC input logic [70:0] ic_wr_data_1, // Data to fill to the Icache. With ECC output logic [63:0] ic_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC input logic [70:0] ic_debug_wr_data, // Debug wr cache. output logic [70:0] ic_debug_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC output logic [ICACHE_BANKS_WAY-1:0] ic_parerr, output logic [ICACHE_BANKS_WAY-1:0] ic_eccerr, // ecc error per bank input logic [ICACHE_INDEX_HI:3] ic_debug_addr, // Read/Write addresss to the Icache. input logic ic_debug_rd_en, // Icache debug rd input logic ic_debug_wr_en, // Icache debug wr input logic ic_debug_tag_array, // Debug tag array input logic [ICACHE_NUM_WAYS-1:0] ic_debug_way, // Debug way. Rd or Wr. input logic [63:0] ic_premux_data, // Premux data to be muxed with each way of the Icache. input logic ic_sel_premux_data, // Select the pre_muxed data input logic [ICACHE_NUM_WAYS-1:0]ic_rd_hit, input ic_data_ext_in_pkt_t [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0] ic_data_ext_in_pkt, // this is being driven by the top level for soc testing/etc input logic scan_mode ) ; logic [ICACHE_TAG_INDEX_LO-1:1] ic_rw_addr_ff; logic [ICACHE_BANKS_WAY-1:0][ICACHE_NUM_WAYS-1:0] ic_b_sb_wren; //bank x ways logic [ICACHE_BANKS_WAY-1:0][ICACHE_NUM_WAYS-1:0] ic_b_sb_rden; //bank x ways logic [ICACHE_BANKS_WAY-1:0] ic_b_rden; //bank logic [ICACHE_BANKS_WAY-1:0] ic_b_rden_ff; //bank logic [ICACHE_BANKS_WAY-1:0] ic_debug_sel_sb; logic [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0][70:0] wb_dout ; // ways x bank logic [ICACHE_BANKS_WAY-1:0][70:0] ic_sb_wr_data, ic_bank_wr_data, wb_dout_ecc_bank; logic [ICACHE_NUM_WAYS-1:0] [141:0] wb_dout_way_pre; logic [ICACHE_NUM_WAYS-1:0] [63:0] wb_dout_way, wb_dout_way_with_premux; logic [141:0] wb_dout_ecc; logic [ICACHE_BANKS_WAY-1:0] bank_check_en; logic [ICACHE_BANKS_WAY-1:0][ICACHE_NUM_WAYS-1:0] ic_bank_way_clken; logic [ICACHE_BANKS_WAY-1:0] ic_bank_way_clken_final; logic [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0] ic_bank_way_clken_final_up; logic [ICACHE_NUM_WAYS-1:0] ic_debug_rd_way_en; // debug wr_way logic [ICACHE_NUM_WAYS-1:0] ic_debug_rd_way_en_ff; // debug wr_way logic [ICACHE_NUM_WAYS-1:0] ic_debug_wr_way_en; // debug wr_way logic [ICACHE_INDEX_HI:1] ic_rw_addr_q; logic [ICACHE_BANKS_WAY-1:0] [ICACHE_INDEX_HI : ICACHE_DATA_INDEX_LO] ic_rw_addr_bank_q; logic [ICACHE_TAG_LO-1 : ICACHE_DATA_INDEX_LO] ic_rw_addr_q_inc; logic [ICACHE_NUM_WAYS-1:0] ic_rd_hit_q; logic [ICACHE_BANKS_WAY-1:0] ic_b_sram_en; logic [ICACHE_BANKS_WAY-1:0] ic_b_read_en; logic [ICACHE_BANKS_WAY-1:0] ic_b_write_en; logic [ICACHE_BANKS_WAY-1:0][ICACHE_NUM_BYPASS-1:0] [31 : ICACHE_DATA_INDEX_LO] wb_index_hold; logic [ICACHE_BANKS_WAY-1:0][ICACHE_NUM_BYPASS-1:0] write_bypass_en; //bank logic [ICACHE_BANKS_WAY-1:0][ICACHE_NUM_BYPASS-1:0] write_bypass_en_ff; //bank logic [ICACHE_BANKS_WAY-1:0][ICACHE_NUM_BYPASS-1:0] index_valid; //bank logic [ICACHE_BANKS_WAY-1:0][ICACHE_NUM_BYPASS-1:0] ic_b_clear_en; logic [ICACHE_BANKS_WAY-1:0][ICACHE_NUM_BYPASS-1:0] ic_b_addr_match; logic [ICACHE_BANKS_WAY-1:0][ICACHE_NUM_BYPASS-1:0] ic_b_addr_match_index_only; logic [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0] ic_b_sram_en_up; logic [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0] ic_b_read_en_up; logic [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0] ic_b_write_en_up; logic [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0][ICACHE_NUM_BYPASS-1:0] [31 : ICACHE_DATA_INDEX_LO] wb_index_hold_up; logic [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0][ICACHE_NUM_BYPASS-1:0] write_bypass_en_up; //bank logic [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0][ICACHE_NUM_BYPASS-1:0] write_bypass_en_ff_up; //bank logic [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0][ICACHE_NUM_BYPASS-1:0] index_valid_up; //bank logic [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0][ICACHE_NUM_BYPASS-1:0] ic_b_clear_en_up; logic [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0][ICACHE_NUM_BYPASS-1:0] ic_b_addr_match_up; logic [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0][ICACHE_NUM_BYPASS-1:0] ic_b_addr_match_index_only_up; logic [ICACHE_BANKS_WAY-1:0] [31 : ICACHE_DATA_INDEX_LO] ic_b_rw_addr; logic [ICACHE_BANKS_WAY-1:0] [31 : ICACHE_DATA_INDEX_LO] ic_b_rw_addr_index_only; logic [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0] [31 : ICACHE_DATA_INDEX_LO] ic_b_rw_addr_up; logic [ICACHE_NUM_WAYS-1:0][ICACHE_BANKS_WAY-1:0] [31 : ICACHE_DATA_INDEX_LO] ic_b_rw_addr_index_only_up; logic ic_rd_en_with_debug; logic ic_rw_addr_wrap, ic_cacheline_wrap_ff; logic ic_debug_rd_en_ff; //----------------------------------------------------------- // ----------- Logic section starts here -------------------- //----------------------------------------------------------- assign ic_debug_rd_way_en[ICACHE_NUM_WAYS-1:0] = {ICACHE_NUM_WAYS{ic_debug_rd_en & ~ic_debug_tag_array}} & ic_debug_way[ICACHE_NUM_WAYS-1:0] ; assign ic_debug_wr_way_en[ICACHE_NUM_WAYS-1:0] = {ICACHE_NUM_WAYS{ic_debug_wr_en & ~ic_debug_tag_array}} & ic_debug_way[ICACHE_NUM_WAYS-1:0] ; logic end_of_cache_line; assign end_of_cache_line = (ICACHE_LN_SZ==7'h40) ? (&ic_rw_addr_q[5:4]) : ic_rw_addr_q[4]; always_comb begin : clkens ic_bank_way_clken = '0; for ( int i=0; i