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 69840565 : 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 69840565 : 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 477824 : input el2_lsu_pkt_t lsu_pkt_m, // packet in m
44 477821 : 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 470948 : input logic [pt.DCCM_BITS-1:0] lsu_addr_r, // start address
52 677522 : 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 470950 : input logic [pt.DCCM_BITS-1:0] lsu_addr_m, // start address
67 677524 : 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
|