//******************************************************************************** // SPDX-License-Identifier: Apache-2.0 // Copyright 2019 Western Digital Corporation or it's 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 ( input logic clk, input logic rst_l, input logic clk_override, input logic dec_tlu_core_ecc_disable, input logic [31:3] ic_rw_addr, input logic [3:0] ic_wr_en , // Which way to write input logic ic_rd_en , // Read enable input logic [15:2] 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 [3:0] ic_debug_way, // Debug way. Rd or Wr. input logic [127: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 `ifdef RV_ICACHE_ECC input logic [83:0] ic_wr_data, // Data to fill to the Icache. With ECC output logic [167:0] ic_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC output logic [24:0] ictag_debug_rd_data,// Debug icache tag. input logic [41:0] ic_debug_wr_data, // Debug wr cache. `else input logic [67:0] ic_wr_data, // Data to fill to the Icache. With Parity output logic [135:0] ic_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With Parity output logic [20:0] ictag_debug_rd_data,// Debug icache tag. input logic [33:0] ic_debug_wr_data, // Debug wr cache. `endif input logic [3:0] ic_tag_valid, // Valid from the I$ tag valid outside (in flops). output logic [3:0] ic_rd_hit, // ic_rd_hit[3:0] output logic ic_tag_perr, // Tag Parity error input logic scan_mode ) ; `include "global.h" IC_TAG #( .ICACHE_TAG_HIGH(ICACHE_TAG_HIGH) , .ICACHE_TAG_LOW(ICACHE_TAG_LOW) , .ICACHE_TAG_DEPTH(ICACHE_TAG_DEPTH) ) ic_tag_inst ( .*, .ic_wr_en (ic_wr_en[3:0]), .ic_debug_addr(ic_debug_addr[ICACHE_TAG_HIGH-1:2]), .ic_rw_addr (ic_rw_addr[31:3]) ) ; IC_DATA #( .ICACHE_TAG_HIGH(ICACHE_TAG_HIGH) , .ICACHE_TAG_LOW(ICACHE_TAG_LOW) , .ICACHE_IC_DEPTH(ICACHE_IC_DEPTH) ) ic_data_inst ( .*, .ic_wr_en (ic_wr_en[3:0]), .ic_debug_addr(ic_debug_addr[ICACHE_TAG_HIGH-1:2]), .ic_rw_addr (ic_rw_addr[ICACHE_TAG_HIGH-1:3]) ) ; endmodule ///////////////////////////////////////////////// ////// ICACHE DATA MODULE //////////////////// ///////////////////////////////////////////////// module IC_DATA #(parameter ICACHE_TAG_HIGH = 16 , ICACHE_TAG_LOW=6 , ICACHE_IC_DEPTH=1024 ) ( input logic clk, input logic rst_l, input logic clk_override, input logic [ICACHE_TAG_HIGH-1:3] ic_rw_addr, input logic [3:0] ic_wr_en, input logic ic_rd_en, // Read enable `ifdef RV_ICACHE_ECC input logic [83:0] ic_wr_data, // Data to fill to the Icache. With ECC output logic [167:0] ic_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With ECC input logic [41:0] ic_debug_wr_data, // Debug wr cache. `else input logic [67:0] ic_wr_data, // Data to fill to the Icache. With Parity output logic [135:0] ic_rd_data , // Data read from Icache. 2x64bits + parity bits. F2 stage. With Parity input logic [33:0] ic_debug_wr_data, // Debug wr cache. `endif input logic [ICACHE_TAG_HIGH-1:2] 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 [3:0] ic_debug_way, // Debug way. Rd or Wr. input logic [127: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 [3:0] ic_rd_hit, input logic scan_mode ) ; logic [5:4] ic_rw_addr_ff; logic [3:0][3:0] ic_b_sb_wren; // way, bank logic ic_debug_sel_sb0 ; logic ic_debug_sel_sb1 ; logic ic_debug_sel_sb2 ; logic ic_debug_sel_sb3 ; `ifdef RV_ICACHE_ECC logic [3:0] [167:0] bank_set_dout; logic [3:0][167:0] wb_dout ; // logic [3:0][41:0] ic_sb_wr_data; `else logic [3:0] [135:0] bank_set_dout; logic [3:0] [135:0] wb_dout ; // bank , way , size logic [3:0] [33:0] ic_sb_wr_data; `endif logic [3:0] ic_bank_way_clken; // bank , way logic [3:0] ic_bank_way_clk ; // bank , way logic ic_b_rden; logic [3:0] ic_debug_rd_way_en; // debug wr_way logic [3:0] ic_debug_rd_way_en_ff; // debug wr_way logic [3:0] ic_debug_wr_way_en; // debug wr_way logic [ICACHE_TAG_HIGH-1:4] ic_rw_addr_q; assign ic_debug_rd_way_en[3:0] = {4{ic_debug_rd_en & ~ic_debug_tag_array}} & ic_debug_way[3:0] ; assign ic_debug_wr_way_en[3:0] = {4{ic_debug_wr_en & ~ic_debug_tag_array}} & ic_debug_way[3:0] ; assign ic_b_sb_wren[0][3:0] = (ic_wr_en[3:0] & {4{~ic_rw_addr[3]}} ) | (ic_debug_wr_way_en[3:0] & {4{ic_debug_addr[3:2] == 2'b00}}) ; assign ic_b_sb_wren[1][3:0] = (ic_wr_en[3:0] & {4{~ic_rw_addr[3]}} ) | (ic_debug_wr_way_en[3:0] & {4{ic_debug_addr[3:2] == 2'b01}}) ; assign ic_b_sb_wren[2][3:0] = (ic_wr_en[3:0] & {4{ic_rw_addr[3]}} ) | (ic_debug_wr_way_en[3:0] & {4{ic_debug_addr[3:2] == 2'b10}}) ; assign ic_b_sb_wren[3][3:0] = (ic_wr_en[3:0] & {4{ic_rw_addr[3]}} ) | (ic_debug_wr_way_en[3:0] & {4{ic_debug_addr[3:2] == 2'b11}}) ; assign ic_debug_sel_sb0 = (ic_debug_addr[3:2] == 2'b00 ) ; assign ic_debug_sel_sb1 = (ic_debug_addr[3:2] == 2'b01 ) ; assign ic_debug_sel_sb2 = (ic_debug_addr[3:2] == 2'b10 ) ; assign ic_debug_sel_sb3 = (ic_debug_addr[3:2] == 2'b11 ) ; `ifdef RV_ICACHE_ECC assign ic_sb_wr_data[0][41:0] = (ic_debug_sel_sb0 & ic_debug_wr_en) ? {ic_debug_wr_data[41:0]} : ic_wr_data[41:0] ; assign ic_sb_wr_data[1][41:0] = (ic_debug_sel_sb1 & ic_debug_wr_en) ? {ic_debug_wr_data[41:0]} : ic_wr_data[83:42] ; assign ic_sb_wr_data[2][41:0] = (ic_debug_sel_sb2 & ic_debug_wr_en) ? {ic_debug_wr_data[41:0]} : ic_wr_data[41:0] ; assign ic_sb_wr_data[3][41:0] = (ic_debug_sel_sb3 & ic_debug_wr_en) ? {ic_debug_wr_data[41:0]} : ic_wr_data[83:42] ; `else assign ic_sb_wr_data[0][33:0] = (ic_debug_sel_sb0 & ic_debug_wr_en) ? ic_debug_wr_data[33:0] : ic_wr_data[33:0] ; assign ic_sb_wr_data[1][33:0] = (ic_debug_sel_sb1 & ic_debug_wr_en) ? ic_debug_wr_data[33:0] : ic_wr_data[67:34] ; assign ic_sb_wr_data[2][33:0] = (ic_debug_sel_sb2 & ic_debug_wr_en) ? ic_debug_wr_data[33:0] : ic_wr_data[33:0] ; assign ic_sb_wr_data[3][33:0] = (ic_debug_sel_sb3 & ic_debug_wr_en) ? ic_debug_wr_data[33:0] : ic_wr_data[67:34] ; `endif // bank read enables assign ic_b_rden = (ic_rd_en | ic_debug_rd_en ); assign ic_bank_way_clken[3:0] = ({4{ic_b_rden | clk_override }}) | ic_b_sb_wren[0][3:0] | ic_b_sb_wren[1][3:0] | ic_b_sb_wren[2][3:0] | ic_b_sb_wren[3][3:0] ; assign ic_rw_addr_q[ICACHE_TAG_HIGH-1:4] = (ic_debug_rd_en | ic_debug_wr_en) ? ic_debug_addr[ICACHE_TAG_HIGH-1:4] : ic_rw_addr[ICACHE_TAG_HIGH-1:4] ; logic ic_debug_rd_en_ff; rvdff #(2) adr_ff (.*, .din ({ic_rw_addr_q[5:4]}), .dout({ic_rw_addr_ff[5:4]})); rvdff #(5) debug_rd_wy_ff (.*, .din ({ic_debug_rd_way_en[3:0], ic_debug_rd_en}), .dout({ic_debug_rd_way_en_ff[3:0], ic_debug_rd_en_ff})); localparam NUM_WAYS=4 ; localparam NUM_SUBBANKS=4 ; for (genvar i=0; i