//******************************************************************************** // 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<NUM_WAYS; i++) begin: WAYS rvoclkhdr bank_way_c1_cgc ( .en(ic_bank_way_clken[i]), .l1clk(ic_bank_way_clk[i]), .* ); for (genvar k=0; k<NUM_SUBBANKS; k++) begin: SUBBANKS // 16B subbank `ifdef RV_ICACHE_ECC `RV_ICACHE_DATA_CELL ic_bank_sb_way_data ( .CLK(ic_bank_way_clk[i]), .WE (ic_b_sb_wren[k][i]), .D (ic_sb_wr_data[k][41:0]), .ADR(ic_rw_addr_q[ICACHE_TAG_HIGH-1:4]), .Q (wb_dout[i][(k+1)*42-1:k*42]) ); `else `RV_ICACHE_DATA_CELL ic_bank_sb_way_data ( .CLK(ic_bank_way_clk[i]), .WE (ic_b_sb_wren[k][i]), .D (ic_sb_wr_data[k][33:0]), .ADR(ic_rw_addr_q[ICACHE_TAG_HIGH-1:4]), .Q (wb_dout[i][(k+1)*34-1:k*34]) ); `endif end // block: SUBBANKS end logic [3:0] ic_rd_hit_q; assign ic_rd_hit_q[3:0] = ic_debug_rd_en_ff ? ic_debug_rd_way_en_ff[3:0] : ic_rd_hit[3:0] ; // set mux `ifdef RV_ICACHE_ECC logic [167:0] ic_premux_data_ext; logic [3:0] [167:0] wb_dout_way; logic [3:0] [167:0] wb_dout_way_with_premux; assign ic_premux_data_ext[167:0] = {10'b0,ic_premux_data[127:96],10'b0,ic_premux_data[95:64] ,10'b0,ic_premux_data[63:32],10'b0,ic_premux_data[31:0]}; assign wb_dout_way[0][167:0] = wb_dout[0][167:0]; assign wb_dout_way[1][167:0] = wb_dout[1][167:0]; assign wb_dout_way[2][167:0] = wb_dout[2][167:0]; assign wb_dout_way[3][167:0] = wb_dout[3][167:0]; assign wb_dout_way_with_premux[0][167:0] = ic_sel_premux_data ? ic_premux_data_ext[167:0] : wb_dout_way[0][167:0] ; assign wb_dout_way_with_premux[1][167:0] = ic_sel_premux_data ? ic_premux_data_ext[167:0] : wb_dout_way[1][167:0] ; assign wb_dout_way_with_premux[2][167:0] = ic_sel_premux_data ? ic_premux_data_ext[167:0] : wb_dout_way[2][167:0] ; assign wb_dout_way_with_premux[3][167:0] = ic_sel_premux_data ? ic_premux_data_ext[167:0] : wb_dout_way[3][167:0] ; assign ic_rd_data[167:0] = ({168{ic_rd_hit_q[0] | ic_sel_premux_data}} & wb_dout_way_with_premux[0][167:0]) | ({168{ic_rd_hit_q[1] | ic_sel_premux_data}} & wb_dout_way_with_premux[1][167:0]) | ({168{ic_rd_hit_q[2] | ic_sel_premux_data}} & wb_dout_way_with_premux[2][167:0]) | ({168{ic_rd_hit_q[3] | ic_sel_premux_data}} & wb_dout_way_with_premux[3][167:0]) ; `else logic [135:0] ic_premux_data_ext; logic [3:0] [135:0] wb_dout_way; logic [3:0] [135:0] wb_dout_way_with_premux; assign ic_premux_data_ext[135:0] = {2'b0,ic_premux_data[127:96],2'b0,ic_premux_data[95:64] ,2'b0,ic_premux_data[63:32],2'b0,ic_premux_data[31:0]}; assign wb_dout_way[0][135:0] = wb_dout[0][135:0]; assign wb_dout_way[1][135:0] = wb_dout[1][135:0]; assign wb_dout_way[2][135:0] = wb_dout[2][135:0]; assign wb_dout_way[3][135:0] = wb_dout[3][135:0]; assign wb_dout_way_with_premux[0][135:0] = ic_sel_premux_data ? ic_premux_data_ext[135:0] : wb_dout_way[0][135:0] ; assign wb_dout_way_with_premux[1][135:0] = ic_sel_premux_data ? ic_premux_data_ext[135:0] : wb_dout_way[1][135:0] ; assign wb_dout_way_with_premux[2][135:0] = ic_sel_premux_data ? ic_premux_data_ext[135:0] : wb_dout_way[2][135:0] ; assign wb_dout_way_with_premux[3][135:0] = ic_sel_premux_data ? ic_premux_data_ext[135:0] : wb_dout_way[3][135:0] ; assign ic_rd_data[135:0] = ({136{ic_rd_hit_q[0] | ic_sel_premux_data}} & wb_dout_way_with_premux[0][135:0]) | ({136{ic_rd_hit_q[1] | ic_sel_premux_data}} & wb_dout_way_with_premux[1][135:0]) | ({136{ic_rd_hit_q[2] | ic_sel_premux_data}} & wb_dout_way_with_premux[2][135:0]) | ({136{ic_rd_hit_q[3] | ic_sel_premux_data}} & wb_dout_way_with_premux[3][135:0]) ; `endif endmodule ///////////////////////////////////////////////// ////// ICACHE TAG MODULE //////////////////// ///////////////////////////////////////////////// module IC_TAG #(parameter ICACHE_TAG_HIGH = 16 , ICACHE_TAG_LOW=6 , ICACHE_TAG_DEPTH=1024 ) ( 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, // way input logic [3:0] ic_tag_valid, input logic ic_rd_en, 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. `ifdef RV_ICACHE_ECC output logic [24:0] ictag_debug_rd_data, input logic [41:0] ic_debug_wr_data, // Debug wr cache. `else output logic [20:0] ictag_debug_rd_data, input logic [33:0] ic_debug_wr_data, // Debug wr cache. `endif output logic [3:0] ic_rd_hit, output logic ic_tag_perr, input logic scan_mode ) ; `ifdef RV_ICACHE_ECC logic [3:0] [24:0] ic_tag_data_raw; logic [3:0] [37:ICACHE_TAG_HIGH] w_tout; logic [24:0] ic_tag_wr_data ; logic [3:0] [31:0] ic_tag_corrected_data_unc; logic [3:0] [06:0] ic_tag_corrected_ecc_unc; logic [3:0] ic_tag_single_ecc_error; logic [3:0] ic_tag_double_ecc_error; `else logic [3:0] [20:0] ic_tag_data_raw; logic [3:0] [32:ICACHE_TAG_HIGH] w_tout; logic [20:0] ic_tag_wr_data ; `endif logic [3:0] ic_tag_way_perr ; logic [3:0] ic_debug_rd_way_en ; logic [3:0] ic_debug_rd_way_en_ff ; logic [ICACHE_TAG_HIGH-1:6] ic_rw_addr_q; logic [31:4] ic_rw_addr_ff; logic [3:0] ic_tag_wren ; // way logic [3:0] ic_tag_wren_q ; // way logic [3:0] ic_tag_clk ; logic [3:0] ic_tag_clken ; logic [3:0] ic_debug_wr_way_en; // debug wr_way assign ic_tag_wren [3:0] = ic_wr_en[3:0] & {4{ic_rw_addr[5:3] == 3'b111}} ; assign ic_tag_clken[3:0] = {4{ic_rd_en | clk_override}} | ic_wr_en[3:0] | ic_debug_wr_way_en[3:0] | ic_debug_rd_way_en[3:0]; rvdff #(32-ICACHE_TAG_HIGH) adr_ff (.*, .din ({ic_rw_addr[31:ICACHE_TAG_HIGH]}), .dout({ic_rw_addr_ff[31:ICACHE_TAG_HIGH]})); localparam TOP_BITS = 21+ICACHE_TAG_HIGH-33 ; localparam NUM_WAYS=4 ; // tags 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_tag_wren_q[3:0] = ic_tag_wren[3:0] | ic_debug_wr_way_en[3:0] ; if (ICACHE_TAG_HIGH == 12) begin: SMALLEST `ifdef RV_ICACHE_ECC logic [6:0] ic_tag_ecc; rvecc_encode tag_ecc_encode ( .din ({{ICACHE_TAG_HIGH{1'b0}}, ic_rw_addr[31:ICACHE_TAG_HIGH]}), .ecc_out({ ic_tag_ecc[6:0]})); assign ic_tag_wr_data[24:0] = (ic_debug_wr_en & ic_debug_tag_array) ? {ic_debug_wr_data[36:32], ic_debug_wr_data[31:12]} : {ic_tag_ecc[4:0], ic_rw_addr[31:ICACHE_TAG_HIGH]} ; `else logic ic_tag_parity ; rveven_paritygen #(32-ICACHE_TAG_HIGH) pargen (.data_in (ic_rw_addr[31:ICACHE_TAG_HIGH]), .parity_out(ic_tag_parity)); assign ic_tag_wr_data[20:0] = (ic_debug_wr_en & ic_debug_tag_array) ? {ic_debug_wr_data[32], ic_debug_wr_data[31:12]} : {ic_tag_parity, ic_rw_addr[31:ICACHE_TAG_HIGH]} ; `endif end else begin: OTHERS `ifdef RV_ICACHE_ECC logic [6:0] ic_tag_ecc; rvecc_encode tag_ecc_encode ( .din ({{ICACHE_TAG_HIGH{1'b0}}, ic_rw_addr[31:ICACHE_TAG_HIGH]}), .ecc_out({ ic_tag_ecc[6:0]})); assign ic_tag_wr_data[24:0] = (ic_debug_wr_en & ic_debug_tag_array) ? {ic_debug_wr_data[36:32], ic_debug_wr_data[31:12]} : {ic_tag_ecc[4:0], {TOP_BITS{1'b0}},ic_rw_addr[31:ICACHE_TAG_HIGH]} ; `else logic ic_tag_parity ; rveven_paritygen #(32-ICACHE_TAG_HIGH) pargen (.data_in (ic_rw_addr[31:ICACHE_TAG_HIGH]), .parity_out(ic_tag_parity)); assign ic_tag_wr_data[20:0] = (ic_debug_wr_en & ic_debug_tag_array) ? {ic_debug_wr_data[32], ic_debug_wr_data[31:12]} : {ic_tag_parity, {TOP_BITS{1'b0}},ic_rw_addr[31:ICACHE_TAG_HIGH]} ; `endif end assign ic_rw_addr_q[ICACHE_TAG_HIGH-1:6] = (ic_debug_rd_en | ic_debug_wr_en) ? ic_debug_addr[ICACHE_TAG_HIGH-1:6] : ic_rw_addr[ICACHE_TAG_HIGH-1:6] ; rvdff #(4) tag_rd_wy_ff (.*, .din ({ic_debug_rd_way_en[3:0]}), .dout({ic_debug_rd_way_en_ff[3:0]})); for (genvar i=0; i<NUM_WAYS; i++) begin: WAYS rvclkhdr ic_tag_c1_cgc ( .en(ic_tag_clken[i]), .l1clk(ic_tag_clk[i]), .* ); if (ICACHE_TAG_DEPTH == 64 ) begin : ICACHE_SZ_16 `ifdef RV_ICACHE_ECC ram_64x25 ic_way_tag ( .CLK(ic_tag_clk[i]), .WE (ic_tag_wren_q[i]), .D (ic_tag_wr_data[24:0]), .ADR(ic_rw_addr_q[ICACHE_TAG_HIGH-1:ICACHE_TAG_LOW]), .Q (ic_tag_data_raw[i][24:0]) ); assign w_tout[i][31:ICACHE_TAG_HIGH] = ic_tag_data_raw[i][31-ICACHE_TAG_HIGH:0] ; assign w_tout[i][36:32] = ic_tag_data_raw[i][24:20] ; rvecc_decode ecc_decode ( .en(~dec_tlu_core_ecc_disable), .sed_ded ( 1'b1 ), // 1 : means only detection .din({12'b0,ic_tag_data_raw[i][19:0]}), .ecc_in({2'b0, ic_tag_data_raw[i][24:20]}), .dout(ic_tag_corrected_data_unc[i][31:0]), .ecc_out(ic_tag_corrected_ecc_unc[i][6:0]), .single_ecc_error(ic_tag_single_ecc_error[i]), .double_ecc_error(ic_tag_double_ecc_error[i])); assign ic_tag_way_perr[i]= ic_tag_single_ecc_error[i] | ic_tag_double_ecc_error[i] ; `else ram_64x21 ic_way_tag ( .CLK(ic_tag_clk[i]), .WE (ic_tag_wren_q[i]), .D (ic_tag_wr_data[20:0]), .ADR(ic_rw_addr_q[ICACHE_TAG_HIGH-1:ICACHE_TAG_LOW]), .Q (ic_tag_data_raw[i][20:0]) ); assign w_tout[i][31:ICACHE_TAG_HIGH] = ic_tag_data_raw[i][31-ICACHE_TAG_HIGH:0] ; assign w_tout[i][32] = ic_tag_data_raw[i][20] ; rveven_paritycheck #(32-ICACHE_TAG_HIGH) parcheck(.data_in (w_tout[i][31:ICACHE_TAG_HIGH]), .parity_in (w_tout[i][32]), .parity_err(ic_tag_way_perr[i])); `endif end // block: ICACHE_SZ_16 else begin : tag_not_64 `ifdef RV_ICACHE_ECC `RV_ICACHE_TAG_CELL ic_way_tag ( .CLK(ic_tag_clk[i]), .WE (ic_tag_wren_q[i]), .D (ic_tag_wr_data[24:0]), .ADR(ic_rw_addr_q[ICACHE_TAG_HIGH-1:ICACHE_TAG_LOW]), .Q (ic_tag_data_raw[i][24:0]) ); assign w_tout[i][31:ICACHE_TAG_HIGH] = ic_tag_data_raw[i][31-ICACHE_TAG_HIGH:0] ; assign w_tout[i][36:32] = ic_tag_data_raw[i][24:20] ; rvecc_decode ecc_decode ( .en(~dec_tlu_core_ecc_disable), .sed_ded ( 1'b1 ), // 1 : if only need detection .din({12'b0,ic_tag_data_raw[i][19:0]}), .ecc_in({2'b0, ic_tag_data_raw[i][24:20]}), .dout(ic_tag_corrected_data_unc[i][31:0]), .ecc_out(ic_tag_corrected_ecc_unc[i][6:0]), .single_ecc_error(ic_tag_single_ecc_error[i]), .double_ecc_error(ic_tag_double_ecc_error[i])); assign ic_tag_way_perr[i]= ic_tag_single_ecc_error[i] | ic_tag_double_ecc_error[i] ; `else `RV_ICACHE_TAG_CELL ic_way_tag ( .CLK(ic_tag_clk[i]), .WE (ic_tag_wren_q[i]), .D (ic_tag_wr_data[20:0]), .ADR(ic_rw_addr_q[ICACHE_TAG_HIGH-1:ICACHE_TAG_LOW]), .Q ({ic_tag_data_raw[i][20:0]}) ); assign w_tout[i][31:ICACHE_TAG_HIGH] = ic_tag_data_raw[i][31-ICACHE_TAG_HIGH:0] ; assign w_tout[i][32] = ic_tag_data_raw[i][20] ; rveven_paritycheck #(32-ICACHE_TAG_HIGH) parcheck(.data_in (w_tout[i][31:ICACHE_TAG_HIGH]), .parity_in (w_tout[i][32]), .parity_err(ic_tag_way_perr[i])); `endif end // block: tag_not_64 end // block: WAYS `ifdef RV_ICACHE_ECC assign ictag_debug_rd_data[24:0] = ({25{ic_debug_rd_way_en_ff[0]}} & ic_tag_data_raw[0] ) | ({25{ic_debug_rd_way_en_ff[1]}} & ic_tag_data_raw[1] ) | ({25{ic_debug_rd_way_en_ff[2]}} & ic_tag_data_raw[2] ) | ({25{ic_debug_rd_way_en_ff[3]}} & ic_tag_data_raw[3] ) ; `else assign ictag_debug_rd_data[20:0] = ({21{ic_debug_rd_way_en_ff[0]}} & ic_tag_data_raw[0] ) | ({21{ic_debug_rd_way_en_ff[1]}} & ic_tag_data_raw[1] ) | ({21{ic_debug_rd_way_en_ff[2]}} & ic_tag_data_raw[2] ) | ({21{ic_debug_rd_way_en_ff[3]}} & ic_tag_data_raw[3] ) ; `endif assign ic_rd_hit[0] = (w_tout[0][31:ICACHE_TAG_HIGH] == ic_rw_addr_ff[31:ICACHE_TAG_HIGH]) & ic_tag_valid[0]; assign ic_rd_hit[1] = (w_tout[1][31:ICACHE_TAG_HIGH] == ic_rw_addr_ff[31:ICACHE_TAG_HIGH]) & ic_tag_valid[1]; assign ic_rd_hit[2] = (w_tout[2][31:ICACHE_TAG_HIGH] == ic_rw_addr_ff[31:ICACHE_TAG_HIGH]) & ic_tag_valid[2]; assign ic_rd_hit[3] = (w_tout[3][31:ICACHE_TAG_HIGH] == ic_rw_addr_ff[31:ICACHE_TAG_HIGH]) & ic_tag_valid[3]; assign ic_tag_perr = | (ic_tag_way_perr[3:0] & ic_tag_valid[3:0] ) ; endmodule