Project Full coverage report
Current view: Cores-VeeR-EL2—Cores-VeeR-EL2—design—lsu—el2_lsu_ecc.sv Coverage Hit Total
Test Date: 14-11-2024 Toggle 81.0% 47 58
Test: all Branch 0.0% 0 0

            Line data    Source code
       1              : // SPDX-License-Identifier: Apache-2.0
       2              : // Copyright 2020 Western Digital Corporation or its affiliates.
       3              : //
       4              : // Licensed under the Apache License, Version 2.0 (the "License");
       5              : // you may not use this file except in compliance with the License.
       6              : // You may obtain a copy of the License at
       7              : //
       8              : // http://www.apache.org/licenses/LICENSE-2.0
       9              : //
      10              : // Unless required by applicable law or agreed to in writing, software
      11              : // distributed under the License is distributed on an "AS IS" BASIS,
      12              : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13              : // See the License for the specific language governing permissions and
      14              : // limitations under the License.
      15              : 
      16              : //********************************************************************************
      17              : // $Id$
      18              : //
      19              : //
      20              : // Owner:
      21              : // Function: Top level file for load store unit
      22              : // Comments:
      23              : //
      24              : //
      25              : // DC1 -> DC2 -> DC3 -> DC4 (Commit)
      26              : //
      27              : //********************************************************************************
      28              : module el2_lsu_ecc
      29              : import el2_pkg::*;
      30              : #(
      31              : `include "el2_param.vh"
      32              :  )
      33              : (
      34     69830461 :    input logic                           clk,                // Clock only while core active.  Through one clock header.  For flops with    second clock header built in.  Connected to ACTIVE_L2CLK.
      35     69830461 :    input logic                           lsu_c2_r_clk,       // clock
      36            2 :    input logic                           clk_override,       // Override non-functional clock gating
      37          338 :    input logic                           rst_l,              // reset, active low
      38              :    // Excluding scan_mode from coverage as its usage is determined by the integrator of the VeeR core.
      39              :    /*verilator coverage_off*/
      40              :    input logic                           scan_mode,          // scan mode
      41              :    /*verilator coverage_on*/
      42              : 
      43       477978 :    input el2_lsu_pkt_t                  lsu_pkt_m,          // packet in m
      44       477975 :    input el2_lsu_pkt_t                  lsu_pkt_r,          // packet in r
      45         7576 :    input logic [pt.DCCM_DATA_WIDTH-1:0]  stbuf_data_any,
      46              : 
      47            8 :    input logic                           dec_tlu_core_ecc_disable,  // disables the ecc computation and error flagging
      48              : 
      49       561000 :    input logic                           lsu_dccm_rden_r,          // dccm rden
      50       614422 :    input logic                           addr_in_dccm_r,           // address in dccm
      51       471426 :    input logic  [pt.DCCM_BITS-1:0]       lsu_addr_r,               // start address
      52       678000 :    input logic  [pt.DCCM_BITS-1:0]       end_addr_r,               // end address
      53            0 :    input logic  [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_hi_r,          // data from the dccm
      54            0 :    input logic  [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_lo_r,          // data from the dccm
      55            0 :    input logic  [pt.DCCM_ECC_WIDTH-1:0]  dccm_data_ecc_hi_r,       // data from the dccm + ecc
      56            0 :    input logic  [pt.DCCM_ECC_WIDTH-1:0]  dccm_data_ecc_lo_r,       // data from the dccm + ecc
      57            2 :    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_hi_r,            // corrected dccm data R-stage
      58            2 :    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_lo_r,            // corrected dccm data R-stage
      59            2 :    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_hi_r_ff,         // corrected dccm data R+1 stage
      60            2 :    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_lo_r_ff,         // corrected dccm data R+1 stage
      61              : 
      62            4 :    input logic                           ld_single_ecc_error_r,     // ld has a single ecc error
      63            4 :    input logic                           ld_single_ecc_error_r_ff,  // ld has a single ecc error
      64       561000 :    input logic                           lsu_dccm_rden_m,           // dccm rden
      65       614422 :    input logic                           addr_in_dccm_m,            // address in dccm
      66       471428 :    input logic  [pt.DCCM_BITS-1:0]       lsu_addr_m,                // start address
      67       678002 :    input logic  [pt.DCCM_BITS-1:0]       end_addr_m,                // end address
      68        47176 :    input logic  [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_hi_m,           // raw data from mem
      69        47176 :    input logic  [pt.DCCM_DATA_WIDTH-1:0] dccm_rdata_lo_m,           // raw data from mem
      70       154095 :    input logic  [pt.DCCM_ECC_WIDTH-1:0]  dccm_data_ecc_hi_m,        // ecc read out from mem
      71       154095 :    input logic  [pt.DCCM_ECC_WIDTH-1:0]  dccm_data_ecc_lo_m,        // ecc read out from mem
      72        47176 :    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_hi_m,             // corrected dccm data M-stage
      73        47176 :    output logic [pt.DCCM_DATA_WIDTH-1:0] sec_data_lo_m,             // corrected dccm data M-stage
      74              : 
      75            0 :    input logic                           dma_dccm_wen,              // Perform DMA writes only for word/dword
      76           12 :    input logic  [31:0]                   dma_dccm_wdata_lo,         // Shifted dma data to lower bits to make it consistent to lsu stores
      77            0 :    input logic  [31:0]                   dma_dccm_wdata_hi,         // Shifted dma data to lower bits to make it consistent to lsu stores
      78            0 :    output logic [pt.DCCM_ECC_WIDTH-1:0]  dma_dccm_wdata_ecc_hi,     // ECC bits for the DMA wdata
      79        50849 :    output logic [pt.DCCM_ECC_WIDTH-1:0]  dma_dccm_wdata_ecc_lo,     // ECC bits for the DMA wdata
      80              : 
      81        50849 :    output logic [pt.DCCM_ECC_WIDTH-1:0]  stbuf_ecc_any,             // Encoded data with ECC bits
      82            0 :    output logic [pt.DCCM_ECC_WIDTH-1:0]  sec_data_ecc_hi_r_ff,      // Encoded data with ECC bits
      83        50849 :    output logic [pt.DCCM_ECC_WIDTH-1:0]  sec_data_ecc_lo_r_ff,      // Encoded data with ECC bits
      84              : 
      85            0 :    output logic                          single_ecc_error_hi_r,                   // sec detected
      86            4 :    output logic                          single_ecc_error_lo_r,                   // sec detected on lower dccm bank
      87            4 :    output logic                          lsu_single_ecc_error_r,                  // or of the 2
      88            4 :    output logic                          lsu_double_ecc_error_r,                   // double error detected
      89              : 
      90            4 :    output logic                          lsu_single_ecc_error_m,                  // or of the 2
      91            4 :    output logic                          lsu_double_ecc_error_m                   // double error detected
      92              : 
      93              :  );
      94              : 
      95            0 :    logic                           is_ldst_r;
      96       557884 :    logic                           is_ldst_hi_any, is_ldst_lo_any;
      97         7378 :    logic [pt.DCCM_DATA_WIDTH-1:0]  dccm_wdata_hi_any, dccm_wdata_lo_any;
      98        50849 :    logic [pt.DCCM_ECC_WIDTH-1:0]  dccm_wdata_ecc_hi_any, dccm_wdata_ecc_lo_any;
      99        47176 :    logic [pt.DCCM_DATA_WIDTH-1:0]  dccm_rdata_hi_any, dccm_rdata_lo_any;
     100       154095 :    logic [pt.DCCM_ECC_WIDTH-1:0]   dccm_data_ecc_hi_any, dccm_data_ecc_lo_any;
     101        47176 :    logic [pt.DCCM_DATA_WIDTH-1:0]  sec_data_hi_any, sec_data_lo_any;
     102            4 :    logic                           single_ecc_error_hi_any, single_ecc_error_lo_any;
     103            4 :    logic                           double_ecc_error_hi_any, double_ecc_error_lo_any;
     104              : 
     105            4 :    logic                           double_ecc_error_hi_m, double_ecc_error_lo_m;
     106            0 :    logic                           double_ecc_error_hi_r, double_ecc_error_lo_r;
     107              : 
     108       154095 :    logic [6:0]                     ecc_out_hi_nc, ecc_out_lo_nc;
     109              : 
     110              : 
     111              :    if (pt.LOAD_TO_USE_PLUS1 == 1) begin: L2U_Plus1_1
     112              :       logic        ldst_dual_m, ldst_dual_r;
     113              :       logic        is_ldst_m;
     114              :       logic        is_ldst_hi_r, is_ldst_lo_r;
     115              : 
     116              :       assign ldst_dual_r                                 = (lsu_addr_r[2] != end_addr_r[2]);
     117              :       assign is_ldst_r                                   = lsu_pkt_r.valid & (lsu_pkt_r.load | lsu_pkt_r.store) & addr_in_dccm_r & lsu_dccm_rden_r;
     118              :       assign is_ldst_lo_r                                = is_ldst_r & ~dec_tlu_core_ecc_disable;
     119              :       assign is_ldst_hi_r                                = is_ldst_r & ldst_dual_r & ~dec_tlu_core_ecc_disable;   // Always check the ECC Hi/Lo for DMA since we don't align for DMA
     120              : 
     121              :       assign is_ldst_hi_any                              = is_ldst_hi_r;
     122              :       assign dccm_rdata_hi_any[pt.DCCM_DATA_WIDTH-1:0]   = dccm_rdata_hi_r[pt.DCCM_DATA_WIDTH-1:0];
     123              :       assign dccm_data_ecc_hi_any[pt.DCCM_ECC_WIDTH-1:0] = dccm_data_ecc_hi_r[pt.DCCM_ECC_WIDTH-1:0];
     124              :       assign is_ldst_lo_any                              = is_ldst_lo_r;
     125              :       assign dccm_rdata_lo_any[pt.DCCM_DATA_WIDTH-1:0]   = dccm_rdata_lo_r[pt.DCCM_DATA_WIDTH-1:0];
     126              :       assign dccm_data_ecc_lo_any[pt.DCCM_ECC_WIDTH-1:0] = dccm_data_ecc_lo_r[pt.DCCM_ECC_WIDTH-1:0];
     127              : 
     128              :       assign sec_data_hi_r[pt.DCCM_DATA_WIDTH-1:0]       = sec_data_hi_any[pt.DCCM_DATA_WIDTH-1:0];
     129              :       assign single_ecc_error_hi_r                       = single_ecc_error_hi_any;
     130              :       assign double_ecc_error_hi_r                       = double_ecc_error_hi_any;
     131              :       assign sec_data_lo_r[pt.DCCM_DATA_WIDTH-1:0]       = sec_data_lo_any[pt.DCCM_DATA_WIDTH-1:0];
     132              :       assign single_ecc_error_lo_r                       = single_ecc_error_lo_any;
     133              :       assign double_ecc_error_lo_r                       = double_ecc_error_lo_any;
     134              : 
     135              :       assign lsu_single_ecc_error_r                      = single_ecc_error_hi_r | single_ecc_error_lo_r;
     136              :       assign lsu_double_ecc_error_r                      = double_ecc_error_hi_r | double_ecc_error_lo_r;
     137              : 
     138              :    end else begin: L2U_Plus1_0
     139              : 
     140              :       logic        ldst_dual_m;
     141              :       logic        is_ldst_m;
     142              :       logic        is_ldst_hi_m, is_ldst_lo_m;
     143              : 
     144              :       assign ldst_dual_m                                 = (lsu_addr_m[2] != end_addr_m[2]);
     145              :       assign is_ldst_m                                   = lsu_pkt_m.valid & (lsu_pkt_m.load | lsu_pkt_m.store) & addr_in_dccm_m & lsu_dccm_rden_m;
     146              :       assign is_ldst_lo_m                                = is_ldst_m & ~dec_tlu_core_ecc_disable;
     147              :       assign is_ldst_hi_m                                = is_ldst_m & (ldst_dual_m | lsu_pkt_m.dma) & ~dec_tlu_core_ecc_disable;   // Always check the ECC Hi/Lo for DMA since we don't align for DMA
     148              : 
     149              :       assign is_ldst_hi_any                              = is_ldst_hi_m;
     150              :       assign dccm_rdata_hi_any[pt.DCCM_DATA_WIDTH-1:0]   = dccm_rdata_hi_m[pt.DCCM_DATA_WIDTH-1:0];
     151              :       assign dccm_data_ecc_hi_any[pt.DCCM_ECC_WIDTH-1:0] = dccm_data_ecc_hi_m[pt.DCCM_ECC_WIDTH-1:0];
     152              :       assign is_ldst_lo_any                              = is_ldst_lo_m;
     153              :       assign dccm_rdata_lo_any[pt.DCCM_DATA_WIDTH-1:0]   = dccm_rdata_lo_m[pt.DCCM_DATA_WIDTH-1:0];
     154              :       assign dccm_data_ecc_lo_any[pt.DCCM_ECC_WIDTH-1:0] = dccm_data_ecc_lo_m[pt.DCCM_ECC_WIDTH-1:0];
     155              : 
     156              :       assign sec_data_hi_m[pt.DCCM_DATA_WIDTH-1:0]       = sec_data_hi_any[pt.DCCM_DATA_WIDTH-1:0];
     157              :       assign double_ecc_error_hi_m                       = double_ecc_error_hi_any;
     158              :       assign sec_data_lo_m[pt.DCCM_DATA_WIDTH-1:0]       = sec_data_lo_any[pt.DCCM_DATA_WIDTH-1:0];
     159              :       assign double_ecc_error_lo_m                       = double_ecc_error_lo_any;
     160              : 
     161              :       assign lsu_single_ecc_error_m                      = single_ecc_error_hi_any | single_ecc_error_lo_any;
     162              :       assign lsu_double_ecc_error_m                      = double_ecc_error_hi_m   | double_ecc_error_lo_m;
     163              : 
     164              :       // Flops
     165              :       rvdff  #(1) lsu_single_ecc_err_r    (.din(lsu_single_ecc_error_m), .dout(lsu_single_ecc_error_r), .clk(lsu_c2_r_clk), .*);
     166              :       rvdff  #(1) lsu_double_ecc_err_r    (.din(lsu_double_ecc_error_m), .dout(lsu_double_ecc_error_r), .clk(lsu_c2_r_clk), .*);
     167              :       rvdff  #(.WIDTH(1)) ldst_sec_lo_rff (.din(single_ecc_error_lo_any),  .dout(single_ecc_error_lo_r),  .clk(lsu_c2_r_clk), .*);
     168              :       rvdff  #(.WIDTH(1)) ldst_sec_hi_rff (.din(single_ecc_error_hi_any),  .dout(single_ecc_error_hi_r),  .clk(lsu_c2_r_clk), .*);
     169              :       rvdffe #(.WIDTH(pt.DCCM_DATA_WIDTH)) sec_data_hi_rff (.din(sec_data_hi_m[pt.DCCM_DATA_WIDTH-1:0]), .dout(sec_data_hi_r[pt.DCCM_DATA_WIDTH-1:0]), .en(lsu_single_ecc_error_m | clk_override), .*);
     170              :       rvdffe #(.WIDTH(pt.DCCM_DATA_WIDTH)) sec_data_lo_rff (.din(sec_data_lo_m[pt.DCCM_DATA_WIDTH-1:0]), .dout(sec_data_lo_r[pt.DCCM_DATA_WIDTH-1:0]), .en(lsu_single_ecc_error_m | clk_override), .*);
     171              : 
     172              :    end
     173              : 
     174              :    // Logic for ECC generation during write
     175              :    assign dccm_wdata_lo_any[pt.DCCM_DATA_WIDTH-1:0] = ld_single_ecc_error_r_ff ? sec_data_lo_r_ff[pt.DCCM_DATA_WIDTH-1:0] : (dma_dccm_wen ? dma_dccm_wdata_lo[pt.DCCM_DATA_WIDTH-1:0] : stbuf_data_any[pt.DCCM_DATA_WIDTH-1:0]);
     176              :    assign dccm_wdata_hi_any[pt.DCCM_DATA_WIDTH-1:0] = ld_single_ecc_error_r_ff ? sec_data_hi_r_ff[pt.DCCM_DATA_WIDTH-1:0] : (dma_dccm_wen ? dma_dccm_wdata_hi[pt.DCCM_DATA_WIDTH-1:0] : 32'h0);
     177              : 
     178              :    assign sec_data_ecc_hi_r_ff[pt.DCCM_ECC_WIDTH-1:0]  = dccm_wdata_ecc_hi_any[pt.DCCM_ECC_WIDTH-1:0];
     179              :    assign sec_data_ecc_lo_r_ff[pt.DCCM_ECC_WIDTH-1:0]  = dccm_wdata_ecc_lo_any[pt.DCCM_ECC_WIDTH-1:0];
     180              :    assign stbuf_ecc_any[pt.DCCM_ECC_WIDTH-1:0]         = dccm_wdata_ecc_lo_any[pt.DCCM_ECC_WIDTH-1:0];
     181              :    assign dma_dccm_wdata_ecc_hi[pt.DCCM_ECC_WIDTH-1:0] = dccm_wdata_ecc_hi_any[pt.DCCM_ECC_WIDTH-1:0];
     182              :    assign dma_dccm_wdata_ecc_lo[pt.DCCM_ECC_WIDTH-1:0] = dccm_wdata_ecc_lo_any[pt.DCCM_ECC_WIDTH-1:0];
     183              : 
     184              :    // Instantiate ECC blocks
     185              :    if (pt.DCCM_ENABLE == 1) begin: Gen_dccm_enable
     186              : 
     187              :       //Detect/Repair for Hi
     188              :       rvecc_decode lsu_ecc_decode_hi (
     189              :          // Inputs
     190              :          .en(is_ldst_hi_any),
     191              :          .sed_ded (1'b0),    // 1 : means only detection
     192              :          .din(dccm_rdata_hi_any[pt.DCCM_DATA_WIDTH-1:0]),
     193              :          .ecc_in(dccm_data_ecc_hi_any[pt.DCCM_ECC_WIDTH-1:0]),
     194              :          // Outputs
     195              :          .dout(sec_data_hi_any[pt.DCCM_DATA_WIDTH-1:0]),
     196              :          .ecc_out (ecc_out_hi_nc[6:0]),
     197              :          .single_ecc_error(single_ecc_error_hi_any),
     198              :          .double_ecc_error(double_ecc_error_hi_any),
     199              :          .*
     200              :       );
     201              : 
     202              :       //Detect/Repair for Lo
     203              :       rvecc_decode lsu_ecc_decode_lo (
     204              :          // Inputs
     205              :          .en(is_ldst_lo_any),
     206              :          .sed_ded (1'b0),    // 1 : means only detection
     207              :          .din(dccm_rdata_lo_any[pt.DCCM_DATA_WIDTH-1:0] ),
     208              :          .ecc_in(dccm_data_ecc_lo_any[pt.DCCM_ECC_WIDTH-1:0]),
     209              :          // Outputs
     210              :          .dout(sec_data_lo_any[pt.DCCM_DATA_WIDTH-1:0]),
     211              :          .ecc_out (ecc_out_lo_nc[6:0]),
     212              :          .single_ecc_error(single_ecc_error_lo_any),
     213              :          .double_ecc_error(double_ecc_error_lo_any),
     214              :          .*
     215              :       );
     216              : 
     217              :       rvecc_encode lsu_ecc_encode_hi (
     218              :          //Inputs
     219              :          .din(dccm_wdata_hi_any[pt.DCCM_DATA_WIDTH-1:0]),
     220              :          //Outputs
     221              :          .ecc_out(dccm_wdata_ecc_hi_any[pt.DCCM_ECC_WIDTH-1:0]),
     222              :          .*
     223              :       );
     224              :       rvecc_encode lsu_ecc_encode_lo (
     225              :          //Inputs
     226              :          .din(dccm_wdata_lo_any[pt.DCCM_DATA_WIDTH-1:0]),
     227              :          //Outputs
     228              :          .ecc_out(dccm_wdata_ecc_lo_any[pt.DCCM_ECC_WIDTH-1:0]),
     229              :          .*
     230              :       );
     231              :    end else begin: Gen_dccm_disable // block: Gen_dccm_enable
     232              :       assign sec_data_hi_any[pt.DCCM_DATA_WIDTH-1:0] = '0;
     233              :       assign sec_data_lo_any[pt.DCCM_DATA_WIDTH-1:0] = '0;
     234              :       assign single_ecc_error_hi_any = '0;
     235              :       assign double_ecc_error_hi_any = '0;
     236              :       assign single_ecc_error_lo_any = '0;
     237              :       assign double_ecc_error_lo_any = '0;
     238              :    end
     239              : 
     240              :    rvdffe #(.WIDTH(pt.DCCM_DATA_WIDTH)) sec_data_hi_rplus1ff (.din(sec_data_hi_r[pt.DCCM_DATA_WIDTH-1:0]), .dout(sec_data_hi_r_ff[pt.DCCM_DATA_WIDTH-1:0]), .en(ld_single_ecc_error_r | clk_override), .clk(clk), .*);
     241              :    rvdffe #(.WIDTH(pt.DCCM_DATA_WIDTH)) sec_data_lo_rplus1ff (.din(sec_data_lo_r[pt.DCCM_DATA_WIDTH-1:0]), .dout(sec_data_lo_r_ff[pt.DCCM_DATA_WIDTH-1:0]), .en(ld_single_ecc_error_r | clk_override), .clk(clk), .*);
     242              : 
     243              : 
     244              : endmodule // el2_lsu_ecc