Line Coverage for Module :
flash_phy_rd
| Line No. | Total | Covered | Percent |
TOTAL | | 133 | 133 | 100.00 |
CONT_ASSIGN | 137 | 1 | 1 | 100.00 |
CONT_ASSIGN | 140 | 1 | 1 | 100.00 |
CONT_ASSIGN | 140 | 1 | 1 | 100.00 |
CONT_ASSIGN | 140 | 1 | 1 | 100.00 |
CONT_ASSIGN | 140 | 1 | 1 | 100.00 |
CONT_ASSIGN | 141 | 1 | 1 | 100.00 |
CONT_ASSIGN | 141 | 1 | 1 | 100.00 |
CONT_ASSIGN | 141 | 1 | 1 | 100.00 |
CONT_ASSIGN | 141 | 1 | 1 | 100.00 |
CONT_ASSIGN | 146 | 1 | 1 | 100.00 |
CONT_ASSIGN | 146 | 1 | 1 | 100.00 |
CONT_ASSIGN | 146 | 1 | 1 | 100.00 |
CONT_ASSIGN | 146 | 1 | 1 | 100.00 |
CONT_ASSIGN | 152 | 1 | 1 | 100.00 |
CONT_ASSIGN | 154 | 1 | 1 | 100.00 |
CONT_ASSIGN | 154 | 1 | 1 | 100.00 |
CONT_ASSIGN | 154 | 1 | 1 | 100.00 |
CONT_ASSIGN | 186 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
CONT_ASSIGN | 194 | 1 | 1 | 100.00 |
CONT_ASSIGN | 194 | 1 | 1 | 100.00 |
CONT_ASSIGN | 194 | 1 | 1 | 100.00 |
CONT_ASSIGN | 194 | 1 | 1 | 100.00 |
CONT_ASSIGN | 196 | 1 | 1 | 100.00 |
CONT_ASSIGN | 196 | 1 | 1 | 100.00 |
CONT_ASSIGN | 196 | 1 | 1 | 100.00 |
CONT_ASSIGN | 196 | 1 | 1 | 100.00 |
CONT_ASSIGN | 212 | 1 | 1 | 100.00 |
CONT_ASSIGN | 212 | 1 | 1 | 100.00 |
CONT_ASSIGN | 212 | 1 | 1 | 100.00 |
CONT_ASSIGN | 212 | 1 | 1 | 100.00 |
CONT_ASSIGN | 218 | 1 | 1 | 100.00 |
CONT_ASSIGN | 218 | 1 | 1 | 100.00 |
CONT_ASSIGN | 218 | 1 | 1 | 100.00 |
CONT_ASSIGN | 218 | 1 | 1 | 100.00 |
CONT_ASSIGN | 222 | 1 | 1 | 100.00 |
CONT_ASSIGN | 222 | 1 | 1 | 100.00 |
CONT_ASSIGN | 222 | 1 | 1 | 100.00 |
CONT_ASSIGN | 222 | 1 | 1 | 100.00 |
CONT_ASSIGN | 229 | 1 | 1 | 100.00 |
CONT_ASSIGN | 232 | 1 | 1 | 100.00 |
ALWAYS | 257 | 4 | 4 | 100.00 |
CONT_ASSIGN | 291 | 1 | 1 | 100.00 |
CONT_ASSIGN | 292 | 1 | 1 | 100.00 |
CONT_ASSIGN | 302 | 1 | 1 | 100.00 |
CONT_ASSIGN | 305 | 1 | 1 | 100.00 |
CONT_ASSIGN | 308 | 1 | 1 | 100.00 |
CONT_ASSIGN | 326 | 1 | 1 | 100.00 |
CONT_ASSIGN | 331 | 1 | 1 | 100.00 |
ALWAYS | 360 | 12 | 12 | 100.00 |
CONT_ASSIGN | 377 | 1 | 1 | 100.00 |
CONT_ASSIGN | 382 | 1 | 1 | 100.00 |
CONT_ASSIGN | 393 | 1 | 1 | 100.00 |
CONT_ASSIGN | 399 | 1 | 1 | 100.00 |
CONT_ASSIGN | 407 | 1 | 1 | 100.00 |
CONT_ASSIGN | 428 | 1 | 1 | 100.00 |
CONT_ASSIGN | 432 | 1 | 1 | 100.00 |
CONT_ASSIGN | 442 | 1 | 1 | 100.00 |
CONT_ASSIGN | 445 | 1 | 1 | 100.00 |
CONT_ASSIGN | 451 | 1 | 1 | 100.00 |
CONT_ASSIGN | 456 | 1 | 1 | 100.00 |
CONT_ASSIGN | 459 | 1 | 1 | 100.00 |
CONT_ASSIGN | 491 | 1 | 1 | 100.00 |
CONT_ASSIGN | 494 | 1 | 1 | 100.00 |
CONT_ASSIGN | 497 | 1 | 1 | 100.00 |
CONT_ASSIGN | 501 | 1 | 1 | 100.00 |
CONT_ASSIGN | 503 | 1 | 1 | 100.00 |
CONT_ASSIGN | 504 | 1 | 1 | 100.00 |
CONT_ASSIGN | 505 | 1 | 1 | 100.00 |
CONT_ASSIGN | 513 | 1 | 1 | 100.00 |
CONT_ASSIGN | 521 | 1 | 1 | 100.00 |
CONT_ASSIGN | 523 | 1 | 1 | 100.00 |
CONT_ASSIGN | 597 | 1 | 1 | 100.00 |
CONT_ASSIGN | 598 | 1 | 1 | 100.00 |
ALWAYS | 600 | 6 | 6 | 100.00 |
CONT_ASSIGN | 610 | 1 | 1 | 100.00 |
CONT_ASSIGN | 614 | 1 | 1 | 100.00 |
CONT_ASSIGN | 617 | 1 | 1 | 100.00 |
CONT_ASSIGN | 624 | 1 | 1 | 100.00 |
CONT_ASSIGN | 628 | 1 | 1 | 100.00 |
CONT_ASSIGN | 636 | 1 | 1 | 100.00 |
CONT_ASSIGN | 654 | 1 | 1 | 100.00 |
CONT_ASSIGN | 659 | 1 | 1 | 100.00 |
CONT_ASSIGN | 664 | 1 | 1 | 100.00 |
CONT_ASSIGN | 664 | 1 | 1 | 100.00 |
CONT_ASSIGN | 664 | 1 | 1 | 100.00 |
CONT_ASSIGN | 664 | 1 | 1 | 100.00 |
ALWAYS | 670 | 8 | 8 | 100.00 |
CONT_ASSIGN | 683 | 1 | 1 | 100.00 |
CONT_ASSIGN | 704 | 1 | 1 | 100.00 |
CONT_ASSIGN | 724 | 1 | 1 | 100.00 |
CONT_ASSIGN | 736 | 1 | 1 | 100.00 |
CONT_ASSIGN | 738 | 1 | 1 | 100.00 |
CONT_ASSIGN | 744 | 1 | 1 | 100.00 |
CONT_ASSIGN | 745 | 1 | 1 | 100.00 |
CONT_ASSIGN | 747 | 1 | 1 | 100.00 |
CONT_ASSIGN | 751 | 1 | 1 | 100.00 |
CONT_ASSIGN | 762 | 1 | 1 | 100.00 |
CONT_ASSIGN | 775 | 1 | 1 | 100.00 |
CONT_ASSIGN | 787 | 1 | 1 | 100.00 |
CONT_ASSIGN | 790 | 1 | 1 | 100.00 |
CONT_ASSIGN | 794 | 1 | 1 | 100.00 |
CONT_ASSIGN | 797 | 1 | 1 | 100.00 |
CONT_ASSIGN | 800 | 1 | 1 | 100.00 |
136 logic [BankAddrW-1:0] flash_word_addr;
137 1/1 assign flash_word_addr = addr_i[BusBankAddrW-1:LsbAddrBit];
Tests: T1 T2 T3
138
139 for (genvar i = 0; i < NumBuf; i++) begin: gen_buf_states
140 4/4 assign buf_valid[i] = read_buf[i].attr == Valid;
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
141 4/4 assign buf_wip[i] = read_buf[i].attr == Wip;
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
142
143 // if a buffer is valid and contains an error, it should be considered
144 // invalid as long as there are no pending responses already waiting
145 // on that buffer.
146 4/4 assign buf_invalid[i] = (read_buf[i].attr == Invalid) |
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
147 (read_buf[i].attr == Valid &
148 read_buf[i].err &
149 ~buf_dependency[i]);
150 end
151
152 1/1 assign buf_invalid_alloc[0] = buf_invalid[0];
Tests: T1 T2 T3
153 for (genvar i = 1; i < NumBuf; i++) begin: gen_inv_alloc_bufs
154 3/3 assign buf_invalid_alloc[i] = buf_invalid[i] & ~|buf_invalid[i-1:0];
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3
155 end
156
157 // a prim arbiter is used to somewhat fairly select among the valid buffers
158 logic [1:0] dummy_data [NumBuf];
159 for (genvar i = 0; i < NumBuf; i++) begin: gen_dummy
160 assign dummy_data[i] = '0;
161 end
162
163 prim_arbiter_tree #(
164 .N(NumBuf),
165 .DW(2),
166 .EnDataPort(1'b0)
167 ) u_valid_random (
168 .clk_i,
169 .rst_ni,
170 .req_chk_i(1'b0), // Valid is allowed to drop without ready.
171 // If there is an invalid buffer, always allocate from that one first
172 // If all buffers have a dependency to an in-flight transaction, do not
173 // allocate and wait for the dependencies to end.
174 // If none of the above are true, THEN pick a buffer from the current valid
175 // buffers that DO NOT have an ongoing dependency.
176 .req_i(|buf_invalid_alloc | all_buf_dependency ? '0 : buf_valid & ~buf_dependency),
177 .data_i(dummy_data),
178 .gnt_o(buf_valid_alloc),
179 .idx_o(),
180 .valid_o(),
181 .data_o(),
182 .ready_i(req_o & ack_i & no_match)
183 );
184
185 // which buffer to allocate upon a new transaction
186 1/1 assign buf_alloc = |buf_invalid_alloc ? buf_invalid_alloc : buf_valid_alloc;
Tests: T1 T2 T3
187
188 // do not attempt to generate match unless the transaction is relevant
189 for (genvar i = 0; i < NumBuf; i++) begin: gen_buf_match
190 logic part_match;
191 logic info_sel_match;
192
193 4/4 assign part_match = read_buf[i].part == part_i;
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
194 4/4 assign info_sel_match = read_buf[i].info_sel == info_sel_i;
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
195
196 4/4 assign buf_match[i] = req_i &
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
197 buf_en_q &
198 (buf_valid[i] | buf_wip[i]) &
199 (read_buf[i].addr == flash_word_addr) &
200 ~read_buf[i].err &
201 part_match &
202 info_sel_match;
203
204 // A data hazard should never happen to a wip buffer because it implies
205 // that a read is in progress, so a hazard operation cannot start.
206 // If bank erase, all buffers must be flushed.
207 // If page erase, only if the buffer lands in the same page.
208 // If program, only if it's the same flash word.
209 logic word_addr_match;
210 logic page_addr_match;
211
212 4/4 assign word_addr_match = (read_buf[i].addr == flash_word_addr) &
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
213 part_match &
214 info_sel_match;
215
216 // the read buffer address in on flash word boundary
217 // while the incoming address in on the bus word boundary
218 4/4 assign page_addr_match = (read_buf[i].addr[WordW +: PageW] == addr_i[BusWordW +: PageW]) &
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
219 part_match &
220 info_sel_match;
221
222 4/4 assign data_hazard[i] = buf_valid[i] &
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
223 (bk_erase_i |
224 (prog_i & word_addr_match) |
225 (pg_erase_i & page_addr_match));
226
227 end
228
229 1/1 assign no_match = ~|buf_match;
Tests: T1 T2 T3
230
231 // if new request does not match anything, allocate
232 1/1 assign alloc = no_match ? {NumBuf{req_i & buf_en_q}} & buf_alloc : '0;
Tests: T1 T2 T3
233
234 // read buffers
235 // allocate sets state to Wip
236 // update sets state to valid
237 // wipe sets state to invalid - this comes from prog
238 for (genvar i = 0; i < NumBuf; i++) begin: gen_bufs
239 flash_phy_rd_buffers u_rd_buf (
240 .clk_i,
241 .rst_ni,
242 .en_i(buf_en_q),
243 .alloc_i(rdy_o & alloc[i]),
244 .update_i(update[i]),
245 .err_i(muxed_err),
246 .wipe_i(data_hazard[i]),
247 .addr_i(flash_word_addr),
248 .part_i(part_i),
249 .info_sel_i(info_sel_i),
250 .data_i(muxed_data),
251 .out_o(read_buf[i])
252 );
253 end
254
255 // The buffer enable is allowed to change when the entire read pipeline is idle
256 always_ff @(posedge clk_i or negedge rst_ni) begin
257 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
258 1/1 buf_en_q <= 1'b0;
Tests: T1 T2 T3
259 1/1 end else if (idle_o) begin
Tests: T1 T2 T3
260 1/1 buf_en_q <= buf_en_i;
Tests: T1 T2 T3
261 end
MISSING_ELSE
262 end
263
264 /////////////////////////////////
265 // Flash read stage
266 /////////////////////////////////
267
268 // Flash read stage determines if the transactions are accepted.
269 //
270 // The response fifo is written to when a transaction initiates a flash read OR when a match
271 // is hit. The information written is just the allocated buffer that would have satisfied the
272 // transaction, as well as bits that indicate which part of the buffer is the right return data
273 //
274 // This allows a hit transaction to match in-order, and unblock later transactions to begin
275 // reading from the flash primitive
276
277 rsp_fifo_entry_t rsp_fifo_wdata, rsp_fifo_rdata;
278 logic rsp_fifo_rdy;
279 logic rsp_fifo_vld;
280
281 // saved attributes on flash read
282 logic [NumBuf-1:0] alloc_q;
283 rd_attr_t rd_attrs;
284
285 // read complete
286 // since done is broadcast to all the modules, need to know we are actually active
287 logic rd_start;
288 logic rd_busy;
289 logic rd_done;
290
291 1/1 assign rd_start = req_o & ack_i;
Tests: T1 T2 T3
292 1/1 assign rd_done = rd_busy & done_i;
Tests: T1 T2 T3
293
294 // scramble stage ready
295 logic scramble_stage_rdy;
296
297 // mask calculation done
298 logic calc_req_done;
299
300 // if buffer allocated, that is the return source
301 // if buffer matched, that is the return source
302 1/1 assign rsp_fifo_wdata.buf_sel = |alloc ? buf_alloc : buf_match;
Tests: T1 T2 T3
303
304 logic rsp_order_fifo_wr;
305 1/1 assign rsp_order_fifo_wr = req_i && rdy_o;
Tests: T1 T2 T3
306
307 logic rsp_order_fifo_rd;
308 1/1 assign rsp_order_fifo_rd = rsp_fifo_vld & data_valid_o;
Tests: T1 T2 T3
309
310 flash_phy_rd_buf_dep u_rd_buf_dep (
311 .clk_i,
312 .rst_ni,
313 .en_i(buf_en_q),
314 .fifo_wr_i(rsp_order_fifo_wr),
315 .fifo_rd_i(rsp_order_fifo_rd),
316 .wr_buf_i(rsp_fifo_wdata.buf_sel),
317 .rd_buf_i(rsp_fifo_rdata.buf_sel),
318 .dependency_o(buf_dependency),
319 .all_dependency_o(all_buf_dependency)
320 );
321
322 // If width is the same, word_sel is unused
323 if (WidthMultiple == 1) begin : gen_single_word_sel
324 assign rsp_fifo_wdata.word_sel = '0;
325 end else begin : gen_word_sel
326 1/1 assign rsp_fifo_wdata.word_sel = addr_i[0 +: LsbAddrBit];
Tests: T1 T2 T3
327 end
328
329 // store the ecc configuration for this transaction until
330 // response is ready to be sent.
331 1/1 assign rsp_fifo_wdata.intg_ecc_en = ecc_i;
Tests: T1 T2 T3
332
333 // response order FIFO
334 logic rsp_order_fifo_err;
335 prim_fifo_sync #(
336 .Width (RspOrderFifoWidth),
337 .Pass (0),
338 .Depth (RspOrderDepth),
339 .Secure (1'b1) // SEC_CM: FIFO.CTR.REDUN
340 ) u_rsp_order_fifo (
341 .clk_i,
342 .rst_ni,
343 .clr_i (1'b0),
344 .wvalid_i(rsp_order_fifo_wr),
345 .wready_o(rsp_fifo_rdy),
346 .wdata_i (rsp_fifo_wdata),
347 .depth_o (),
348 .full_o (),
349 .rvalid_o(rsp_fifo_vld),
350 .rready_i(data_valid_o), // pop when a match has been found
351 .rdata_o (rsp_fifo_rdata),
352 .err_o (rsp_order_fifo_err)
353 );
354
355 // Consider converting this to a FIFO for better matching
356 // The rd_busy flag is effectively a "full" flag anyways of a single
357 // entry.
358 logic flash_rdy;
359 always_ff @(posedge clk_i or negedge rst_ni) begin
360 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
361 1/1 alloc_q <= '0;
Tests: T1 T2 T3
362 1/1 rd_attrs <= '0;
Tests: T1 T2 T3
363 1/1 rd_busy <= '0;
Tests: T1 T2 T3
364 1/1 end else if (rd_start) begin
Tests: T1 T2 T3
365 1/1 rd_busy <= 1'b1;
Tests: T1 T2 T3
366 1/1 alloc_q <= alloc;
Tests: T1 T2 T3
367 1/1 rd_attrs.addr <= addr_i[BusBankAddrW-1:LsbAddrBit];
Tests: T1 T2 T3
368 1/1 rd_attrs.descramble <= descramble_i;
Tests: T1 T2 T3
369 1/1 rd_attrs.ecc <= ecc_i;
Tests: T1 T2 T3
370
371 1/1 end else if (rd_done) begin
Tests: T1 T2 T3
372 1/1 rd_busy <= 1'b0;
Tests: T1 T2 T3
373 end
MISSING_ELSE
374 end
375
376 // flash is ready to accept another transaction
377 1/1 assign flash_rdy = ~rd_busy | rd_done;
Tests: T1 T2 T3
378
379 // read stages are ready when both the response fifo and the
380 // data / mask fifos have space for new entries
381 logic rd_stages_rdy;
382 1/1 assign rd_stages_rdy = rsp_fifo_rdy & scramble_stage_rdy;
Tests: T1 T2 T3
383
384 // When buffer enable changes, we want to hold off new requests
385 // until the request is absorbed. buf_en_q is allowed to change
386 // only when the entire read pipeline is idle, however, during that
387 // same cycle there could be a new incoming request.
388 //
389 // We back pressure here instead of waiting for a period of idle + no
390 // request because it potentially means a storm of accesses could
391 // prevent the buffer enable from taking effect.
392 logic no_buf_en_change;
393 1/1 assign no_buf_en_change = (buf_en_q == buf_en_i);
Tests: T1 T2 T3
394
395 // If no buffers matched, accept only if flash is ready and there is space
396 // If buffer is matched, accept as long as there is space in the rsp fifo
397 // If all buffers are currently allocated or have a dependency, wait until
398 // at least 1 dependency has cleared.
399 1/1 assign rdy_o = (no_match ? ack_i & flash_rdy & rd_stages_rdy : rd_stages_rdy) &
Tests: T1 T2 T3
400 ~all_buf_dependency & no_buf_en_change &
401 // If the current read requires descrambling, wait for the
402 // mask calculation to finish before accepting the next request.
403 (calc_req_o ? calc_req_done : 1'b1);
404
405 // issue a transaction to flash only if there is space in read stages,
406 // there is no buffer match and flash is not currently busy.
407 1/1 assign req_o = req_i & no_buf_en_change & flash_rdy & rd_stages_rdy & no_match &
Tests: T1 T2 T3
408 // If the current read requires descrambling, wait for the
409 // mask calculation to finish before accepting the next request.
410 (calc_req_o ? calc_req_done : 1'b1);
411
412 /////////////////////////////////
413 // Handling Reliability ECC
414 /////////////////////////////////
415
416 // only uncorrectable errors are passed on to the fabric
417 logic data_err;
418
419 // scrambled data must pass through ECC first
420 logic valid_ecc;
421 logic ecc_multi_err;
422 logic ecc_single_err;
423 logic [PlainDataWidth-1:0] data_ecc_chk;
424 logic [PlainDataWidth-1:0] data_int;
425 logic data_erased;
426
427 // this ECC check is for reliability ECC
428 1/1 assign valid_ecc = rd_done && rd_attrs.ecc;
Tests: T1 T2 T3
429
430 // When all bits are 1, the data has been erased
431 // This check is only valid when read data returns.
432 1/1 assign data_erased = rd_done & (data_i == {FullDataWidth{1'b1}});
Tests: T1 T2 T3
433
434 prim_secded_hamming_76_68_dec u_dec (
435 .data_i(data_i),
436 .data_o(data_ecc_chk),
437 .syndrome_o(),
438 .err_o({ecc_multi_err, ecc_single_err})
439 );
440
441 // send out error indication when ecc is enabled
442 1/1 assign data_err = valid_ecc & ecc_multi_err;
Tests: T1 T2 T3
443
444 // reliability ECC errors cause both in-band and out-of-band errors
445 1/1 assign relbl_ecc_err_o = data_err;
Tests: T1 T2 T3
446
447 // If there is a detected multi-bit error or a single bit error, always return the
448 // ECC corrected result (even though it is possibly wrong).
449 // There is no data error of any kind (specifically when multi_err is disabled), just
450 // return the raw data so that it can be debugged.
451 1/1 assign data_int = data_err | ecc_single_err_o ?
Tests: T1 T2 T3
452 data_ecc_chk :
453 data_i[PlainDataWidth-1:0];
454
455 // send out error indication when ecc is enabled
456 1/1 assign ecc_single_err_o = valid_ecc & ecc_single_err;
Tests: T1 T2 T3
457
458 // ecc address return is always the full flash word
459 1/1 assign ecc_addr_o = {rd_attrs.addr, {LsbAddrBit{1'b0}}};
Tests: T1 T2 T3
460
461 /////////////////////////////////
462 // De-scrambling stage
463 /////////////////////////////////
464
465 // Even on ECC error, progress through the stage normally
466
467 logic fifo_data_ready;
468 logic fifo_data_valid;
469 logic fifo_forward_pop;
470 logic rd_and_mask_fifo_pop;
471 logic mask_valid;
472 logic [PlainDataWidth-1:0] fifo_data;
473 logic [DataWidth-1:0] mask;
474 logic addr_xor_fifo_rdy;
475 logic [BankAddrW-1:0] fifo_addr_xor;
476 logic data_fifo_rdy;
477 logic mask_fifo_rdy;
478 logic descram;
479 logic dropmsk;
480 logic forward;
481 logic descram_q;
482 logic dropmsk_q;
483 logic forward_q;
484 logic hint_forward;
485 logic hint_dropmsk;
486 logic hint_descram;
487 logic data_err_q;
488 logic [NumBuf-1:0] alloc_q2;
489 logic [1:0] unused_rd_depth, unused_mask_depth, unused_addr_xor_depth;
490
491 1/1 assign scramble_stage_rdy = data_fifo_rdy & mask_fifo_rdy & addr_xor_fifo_rdy;
Tests: T1 T2 T3
492
493 // descramble is only required if the location is scramble enabled AND it is not erased.
494 1/1 assign descram = rd_done & rd_attrs.descramble & ~data_erased;
Tests: T1 T2 T3
495
496 // If the location is scramble enabled but has been erased, we'll need to drop the computed mask.
497 1/1 assign dropmsk = rd_done & rd_attrs.descramble & data_erased;
Tests: T1 T2 T3
498
499 // data is forwarded whenever it does not require descrambling and there are no entries in the
500 // FIFO to ensure the current read cannot run ahead of the descramble.
501 1/1 assign forward = rd_done & ~descram & ~fifo_data_valid;
Tests: T1 T2 T3
502
503 1/1 assign hint_descram = fifo_data_valid & descram_q;
Tests: T1 T2 T3
504 1/1 assign hint_dropmsk = fifo_data_valid & dropmsk_q;
Tests: T1 T2 T3
505 1/1 assign hint_forward = fifo_data_valid & forward_q;
Tests: T1 T2 T3
506
507 // Data is consumed when:
508 // 1. If the location is scramble enabled:
509 // a) When descrambling completes.
510 // b) As soon as the mask computation finishes, in case the mask is to be dropped.
511 // 2. If the location is not scramble enabled:
512 // - As soon as the data is ready from the FIFO. For the forwarding case, see below.
513 1/1 assign fifo_data_ready = hint_descram ? descramble_req_o & descramble_ack_i :
Tests: T1 T2 T3
514 hint_dropmsk ? mask_valid : fifo_data_valid;
515
516 // In the case of forwarding, the storage FIFOs are bypassed but still pushed. Once the forwarded
517 // entries arrive at the output of the read FIFO, we need to drop them. If a mask has been
518 // computed that is not used (e.g. because of erasing a location that is scramble enabled), wait
519 // for the mask computation to be done and then drop the forwarded data together with the
520 // corresponding mask.
521 1/1 assign fifo_forward_pop = hint_forward & (hint_dropmsk ? mask_valid : 1'b1);
Tests: T1 T2 T3
522
523 1/1 assign rd_and_mask_fifo_pop = fifo_data_ready | fifo_forward_pop;
Tests: T1 T2 T3
524
525 // See comment above on how FIFO popping can be improved in the future
526 logic rd_stage_fifo_err;
527 prim_fifo_sync #(
528 .Width (PlainDataWidth + 4 + NumBuf),
529 .Pass (0),
530 .Depth (2),
531 .OutputZeroIfEmpty (1),
532 .Secure (1'b1) // SEC_CM: FIFO.CTR.REDUN
533 ) u_rd_storage (
534 .clk_i,
535 .rst_ni,
536 .clr_i (1'b0),
537 .wvalid_i(rd_done),
538 .wready_o(data_fifo_rdy),
539 .wdata_i ({alloc_q, descram, dropmsk, forward, data_err, data_int}),
540 .depth_o (unused_rd_depth),
541 .full_o (),
542 .rvalid_o(fifo_data_valid),
543 .rready_i(rd_and_mask_fifo_pop),
544 .rdata_o ({alloc_q2, descram_q, dropmsk_q, forward_q, data_err_q, fifo_data}),
545 .err_o (rd_stage_fifo_err)
546 );
547
548 // storage for mask calculations
549 prim_fifo_sync #(
550 .Width (DataWidth),
551 .Pass (0),
552 .Depth (2),
553 .OutputZeroIfEmpty (1)
554 ) u_mask_storage (
555 .clk_i,
556 .rst_ni,
557 .clr_i (1'b0),
558 .wvalid_i(calc_req_done),
559 .wready_o(mask_fifo_rdy),
560 .wdata_i (mask_i),
561 .depth_o (unused_mask_depth),
562 .full_o (),
563 .rvalid_o(mask_valid),
564 .rready_i(rd_and_mask_fifo_pop),
565 .rdata_o (mask),
566 .err_o ()
567 );
568
569 prim_fifo_sync #(
570 .Width (BankAddrW),
571 .Pass (0),
572 .Depth (RspOrderDepth),
573 .OutputZeroIfEmpty (1)
574 ) u_addr_xor_storage (
575 .clk_i,
576 .rst_ni,
577 .clr_i (1'b0),
578 .wvalid_i(rsp_order_fifo_wr),
579 .wready_o(addr_xor_fifo_rdy),
580 .wdata_i (flash_word_addr),
581 .depth_o (unused_addr_xor_depth),
582 .full_o (),
583 .rvalid_o(),
584 .rready_i(data_valid_o),
585 .rdata_o (fifo_addr_xor),
586 .err_o ()
587 );
588
589 // generate the mask calculation request
590 // mask calculation is done in parallel to the read stage
591 // calc_req_o is done after req_o is accepted so that most of the
592 // cycle can be allocated to mask calculation logic. req_o,
593 // unlike calc_req_o, asserts the same cycle the transaction is
594 // received, so much of the timing may have already been lost to
595 // transaction routing.
596 logic calc_req_start;
597 1/1 assign calc_req_start = req_o & ack_i & descramble_i;
Tests: T1 T2 T3
598 1/1 assign calc_req_done = calc_req_o & calc_ack_i;
Tests: T1 T2 T3
599 always_ff @(posedge clk_i or negedge rst_ni) begin
600 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
601 1/1 calc_req_o <= '0;
Tests: T1 T2 T3
602 1/1 end else if (calc_req_start) begin
Tests: T1 T2 T3
603 1/1 calc_req_o <= 1'b1;
Tests: T1 T2 T3
604 1/1 end else if (calc_req_done) begin
Tests: T1 T2 T3
605 1/1 calc_req_o <= 1'b0;
Tests: T1 T2 T3
606 end
MISSING_ELSE
607 end
608
609 // operand to gf_mult
610 1/1 assign calc_addr_o = rd_attrs.addr;
Tests: T1 T2 T3
611
612 // generate the descramble request whenever both stages are available
613 // and there is a need to descramble
614 1/1 assign descramble_req_o = fifo_data_valid & mask_valid & hint_descram;
Tests: T1 T2 T3
615
616 // scrambled data to de-scramble
617 1/1 assign scrambled_data_o = fifo_data[DataWidth-1:0] ^ mask;
Tests: T1 T2 T3
618
619 // muxed responses
620 // When "forward" is true, there is nothing ahead in the pipeline, directly feed data
621 // and error forward.
622 // When "forward" is not true, take the output from the descramble stage, which is
623 // dependent on the scramble hint.
624 1/1 assign muxed_data = forward ? data_int :
Tests: T1 T2 T3
625 hint_descram ? {fifo_data[PlainDataWidth-1 -: PlainIntgWidth],
626 descrambled_data_i ^ mask} :
627 fifo_data;
628 1/1 assign muxed_err = forward ? data_err :
Tests: T1 T2 T3
629 ~hint_forward ? data_err_q : '0;
630
631 // muxed data valid
632 // if no de-scramble required, return data on read complete
633 // if data is all empty (erased), also return data on read complete
634 // if descramble is required, return data when descrambler finishes
635 // if descramble is not required, but there are transactions ahead, return from fifo when ready
636 1/1 assign data_valid = forward | ~hint_forward & fifo_data_ready;
Tests: T1 T2 T3
637
638
639 /////////////////////////////////
640 // Response
641 /////////////////////////////////
642
643 logic flash_rsp_match;
644 logic [NumBuf-1:0] buf_rsp_match;
645 logic [PlainDataWidth-1:0] buf_rsp_data;
646 logic [BankAddrW-1:0] buf_addr_xor;
647 logic buf_rsp_err;
648
649
650 // update buffers
651 // When forwarding, update entry stored in alloc_q
652 // When de-scrambling however, the contents of alloc_q may have already updated to the next read,
653 // so a different pointer is used.
654 1/1 assign update = forward ? alloc_q :
Tests: T1 T2 T3
655 ~hint_forward & fifo_data_ready ? alloc_q2 : '0;
656
657 // match in flash response when allocated buffer is the same as top of response fifo
658 // if read buffers are not enabled, do not check buffer selection
659 1/1 assign flash_rsp_match = rsp_fifo_vld & data_valid &
Tests: T1 T2 T3
660 (~buf_en_q | rsp_fifo_rdata.buf_sel == update);
661
662 // match in buf response when there is a valid buffer that is the same as top of response fifo
663 for (genvar i = 0; i < NumBuf; i++) begin: gen_buf_rsp_match
664 4/4 assign buf_rsp_match[i] = buf_en_q & rsp_fifo_vld &
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
665 (rsp_fifo_rdata.buf_sel[i] & buf_valid[i]);
666 end
667
668 // select among the buffers
669 always_comb begin
670 1/1 buf_rsp_data = muxed_data;
Tests: T1 T2 T3
671 1/1 buf_rsp_err = '0;
Tests: T1 T2 T3
672 1/1 buf_addr_xor = '0;
Tests: T1 T2 T3
673 1/1 for (int i = 0; i < NumBuf; i++) begin
Tests: T1 T2 T3
674 1/1 if (buf_rsp_match[i]) begin
Tests: T1 T2 T3
675 1/1 buf_rsp_data = read_buf[i].data;
Tests: T1 T2 T3
676 1/1 buf_addr_xor = read_buf[i].addr;
Tests: T1 T2 T3
677 1/1 buf_rsp_err = buf_rsp_err | read_buf[i].err;
Tests: T1 T2 T3
678 end
MISSING_ELSE
679 end
680 end
681
682 logic [PlainDataWidth-1:0] data_out_muxed;
683 1/1 assign data_out_muxed = |buf_rsp_match ? buf_rsp_data : muxed_data;
Tests: T1 T2 T3
684
685 logic [BusFullWidth-1:0] data_out_intg;
686 if (WidthMultiple == 1) begin : gen_width_one_rd
687 // When multiple is 1, just pass the read through directly
688 logic unused_word_sel;
689
690 // use the tlul integrity module directly for bus integrity
691 // SEC_CM: MEM.BUS.INTEGRITY
692 tlul_data_integ_enc u_bus_intg (
693 .data_i(data_out_muxed[DataWidth-1:0]),
694 .data_intg_o(data_out_intg)
695 );
696
697 assign unused_word_sel = rsp_fifo_rdata.word_sel;
698
699 end else begin : gen_rd
700 // Re-arrange data into packed array to pick the correct one
701 logic [WidthMultiple-1:0][BusWidth-1:0] bus_words_packed;
702 logic [WidthMultiple-1:0][BusFullWidth-1:0] bus_words_packed_intg;
703 logic [WidthMultiple-1:0][BusFullWidth-1:0] bus_words_packed_intg_buf;
704 1/1 assign bus_words_packed = data_out_muxed[DataWidth-1:0];
Tests: T1 T2 T3
705
706 for (genvar i = 0; i < WidthMultiple; i++) begin: gen_bus_words_intg
707 // use the tlul integrity module directly for bus integrity
708 // SEC_CM: MEM.BUS.INTEGRITY
709 tlul_data_integ_enc u_bus_intg (
710 .data_i(bus_words_packed[i]),
711 .data_intg_o(bus_words_packed_intg[i])
712 );
713
714 // This primitive is used to place a size-only constraint on the
715 // buffers to act as a synthesis optimization barrier.
716 prim_buf #(
717 .Width(BusFullWidth)
718 ) u_prim_buf_intg (
719 .in_i(bus_words_packed_intg[i]),
720 .out_o(bus_words_packed_intg_buf[i])
721 );
722 end
723 // Mux based on selected word.
724 1/1 assign data_out_intg = bus_words_packed_intg_buf[rsp_fifo_rdata.word_sel];
Tests: T1 T2 T3
725
726 end
727
728 // On a data_err_o, send back '1 with data integrity tag on top of this data.
729 logic [BusFullWidth-1:0] inv_data_integ;
730 tlul_data_integ_enc u_bus_inv_data_intg (
731 .data_i({BusWidth{1'b1}}),
732 .data_intg_o(inv_data_integ)
733 );
734
735 logic [BusFullWidth-1:0] data_out_pre_xor;
736 1/1 assign data_out_pre_xor = data_err_o ? inv_data_integ : data_out_intg;
Tests: T1 T2 T3
737
738 1/1 assign data_ctrl_o = data_out_pre_xor;
Tests: T1 T2 T3
739
740 logic [BusBankAddrW-1:0] addr_xor_muxed;
741 logic [BusBankAddrW-1:0] fifo_addr_xor_muxed;
742 logic [BusBankAddrW-1:0] buf_addr_xor_muxed;
743
744 1/1 assign fifo_addr_xor_muxed = {fifo_addr_xor, rsp_fifo_rdata.word_sel};
Tests: T1 T2 T3
745 1/1 assign buf_addr_xor_muxed = {buf_addr_xor, rsp_fifo_rdata.word_sel};
Tests: T1 T2 T3
746
747 1/1 assign addr_xor_muxed = |buf_rsp_match ? buf_addr_xor_muxed : fifo_addr_xor_muxed;
Tests: T1 T2 T3
748
749 logic [BusWidth-1:0] data_out_xor;
750 logic [BusWidth-1:0] data_out_xor_buf;
751 1/1 assign data_out_xor =
Tests: T1 T2 T3
752 data_out_pre_xor[BusWidth-1:0] ^ {{(BusWidth-BusBankAddrW){1'b0}}, addr_xor_muxed};
753
754 // Buffer to ensure that synthesis tool does not optimize the XOR.
755 prim_buf #(
756 .Width(BusWidth)
757 ) u_prim_buf_data_xor_out (
758 .in_i(data_out_xor),
759 .out_o(data_out_xor_buf)
760 );
761
762 1/1 assign data_host_o = {data_out_pre_xor[BusFullWidth-1:BusWidth], data_out_xor_buf};
Tests: T1 T2 T3
763
764 // add plaintext decoding here
765 // plaintext error
766 logic intg_err_pre, intg_err;
767 logic [DataWidth-1:0] unused_data;
768 logic [3:0] unused_intg;
769 logic [3:0] truncated_intg;
770
771 prim_secded_hamming_72_64_enc u_plain_enc (
772 .data_i(data_out_muxed[DataWidth-1:0]),
773 .data_o({unused_intg, truncated_intg, unused_data})
774 );
775 1/1 assign intg_err_pre = rsp_fifo_rdata.intg_ecc_en ?
Tests: T1 T2 T3
776 truncated_intg != data_out_muxed[DataWidth +: PlainIntgWidth] :
777 '0;
778
779 prim_sec_anchor_buf #(
780 .Width(1)
781 ) u_intg_buf (
782 .in_i(intg_err_pre),
783 .out_o(intg_err)
784 );
785
786 // whenever the response is coming from the buffer, the error is never set
787 1/1 assign data_valid_o = flash_rsp_match | (|buf_rsp_match);
Tests: T1 T2 T3
788
789 // integrity and reliability ECC errors always cause in band errors
790 1/1 assign data_err_o = data_valid_o & (muxed_err | intg_err | (|buf_rsp_match & buf_rsp_err)) |
Tests: T1 T2 T3
791 arb_err_i;
792
793 // integrity ECC error can also cause out of band alert
794 1/1 assign intg_ecc_err_o = data_valid_o & intg_err;
Tests: T1 T2 T3
795
796 // the entire read pipeline is idle when there are no responses to return and no
797 1/1 assign idle_o = ~rsp_fifo_vld;
Tests: T1 T2 T3
798
799 // if any fifo shows an integrity error
800 1/1 assign fifo_err_o = |{rsp_order_fifo_err, rd_stage_fifo_err};
Tests: T1 T2 T3
Cond Coverage for Module :
flash_phy_rd
| Total | Covered | Percent |
Conditions | 458 | 417 | 91.05 |
Logical | 458 | 417 | 91.05 |
Non-Logical | 0 | 0 | |
Event | 0 | 0 | |
This module contains a very large number of conditions, so the report has been split into multiple pages, by source line number. Click on the line number range in the table below to see the condition coverage for that section of the module.
Branch Coverage for Module :
flash_phy_rd
| Line No. | Total | Covered | Percent |
Branches |
|
43 |
43 |
100.00 |
TERNARY |
186 |
2 |
2 |
100.00 |
TERNARY |
232 |
2 |
2 |
100.00 |
TERNARY |
302 |
2 |
2 |
100.00 |
TERNARY |
451 |
2 |
2 |
100.00 |
TERNARY |
513 |
3 |
3 |
100.00 |
TERNARY |
624 |
3 |
3 |
100.00 |
TERNARY |
628 |
3 |
3 |
100.00 |
TERNARY |
654 |
3 |
3 |
100.00 |
TERNARY |
683 |
2 |
2 |
100.00 |
TERNARY |
736 |
2 |
2 |
100.00 |
TERNARY |
747 |
2 |
2 |
100.00 |
TERNARY |
775 |
2 |
2 |
100.00 |
TERNARY |
167 |
2 |
2 |
100.00 |
IF |
257 |
3 |
3 |
100.00 |
IF |
360 |
4 |
4 |
100.00 |
IF |
600 |
4 |
4 |
100.00 |
IF |
674 |
2 |
2 |
100.00 |
186 assign buf_alloc = |buf_invalid_alloc ? buf_invalid_alloc : buf_valid_alloc;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
232 assign alloc = no_match ? {NumBuf{req_i & buf_en_q}} & buf_alloc : '0;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
302 assign rsp_fifo_wdata.buf_sel = |alloc ? buf_alloc : buf_match;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
451 assign data_int = data_err | ecc_single_err_o ?
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T41,T42,T25 |
0 |
Covered |
T1,T2,T3 |
513 assign fifo_data_ready = hint_descram ? descramble_req_o & descramble_ack_i :
-1-
==>
514 hint_dropmsk ? mask_valid : fifo_data_valid;
-2-
==>
==>
Branches:
-1- | -2- | Status | Tests |
1 |
- |
Covered |
T1,T2,T3 |
0 |
1 |
Covered |
T52,T27,T24 |
0 |
0 |
Covered |
T1,T2,T3 |
624 assign muxed_data = forward ? data_int :
-1-
==>
625 hint_descram ? {fifo_data[PlainDataWidth-1 -: PlainIntgWidth],
-2-
==>
==>
Branches:
-1- | -2- | Status | Tests |
1 |
- |
Covered |
T1,T2,T3 |
0 |
1 |
Covered |
T1,T2,T3 |
0 |
0 |
Covered |
T1,T2,T3 |
628 assign muxed_err = forward ? data_err :
-1-
==>
629 ~hint_forward ? data_err_q : '0;
-2-
==>
==>
Branches:
-1- | -2- | Status | Tests |
1 |
- |
Covered |
T1,T2,T3 |
0 |
1 |
Covered |
T1,T2,T3 |
0 |
0 |
Covered |
T1,T2,T3 |
654 assign update = forward ? alloc_q :
-1-
==>
655 ~hint_forward & fifo_data_ready ? alloc_q2 : '0;
-2-
==>
==>
Branches:
-1- | -2- | Status | Tests |
1 |
- |
Covered |
T1,T2,T3 |
0 |
1 |
Covered |
T1,T2,T3 |
0 |
0 |
Covered |
T1,T2,T3 |
683 assign data_out_muxed = |buf_rsp_match ? buf_rsp_data : muxed_data;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
736 assign data_out_pre_xor = data_err_o ? inv_data_integ : data_out_intg;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T7,T25,T63 |
0 |
Covered |
T1,T2,T3 |
747 assign addr_xor_muxed = |buf_rsp_match ? buf_addr_xor_muxed : fifo_addr_xor_muxed;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
775 assign intg_err_pre = rsp_fifo_rdata.intg_ecc_en ?
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
167 ) u_valid_random (
168 .clk_i,
169 .rst_ni,
170 .req_chk_i(1'b0), // Valid is allowed to drop without ready.
171 // If there is an invalid buffer, always allocate from that one first
172 // If all buffers have a dependency to an in-flight transaction, do not
173 // allocate and wait for the dependencies to end.
174 // If none of the above are true, THEN pick a buffer from the current valid
175 // buffers that DO NOT have an ongoing dependency.
176 .req_i(|buf_invalid_alloc | all_buf_dependency ? '0 : buf_valid & ~buf_dependency),
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
257 if (!rst_ni) begin
-1-
258 buf_en_q <= 1'b0;
==>
259 end else if (idle_o) begin
-2-
260 buf_en_q <= buf_en_i;
==>
261 end
MISSING_ELSE
==>
Branches:
-1- | -2- | Status | Tests |
1 |
- |
Covered |
T1,T2,T3 |
0 |
1 |
Covered |
T1,T2,T3 |
0 |
0 |
Covered |
T1,T2,T3 |
360 if (!rst_ni) begin
-1-
361 alloc_q <= '0;
==>
362 rd_attrs <= '0;
363 rd_busy <= '0;
364 end else if (rd_start) begin
-2-
365 rd_busy <= 1'b1;
==>
366 alloc_q <= alloc;
367 rd_attrs.addr <= addr_i[BusBankAddrW-1:LsbAddrBit];
368 rd_attrs.descramble <= descramble_i;
369 rd_attrs.ecc <= ecc_i;
370
371 end else if (rd_done) begin
-3-
372 rd_busy <= 1'b0;
==>
373 end
MISSING_ELSE
==>
Branches:
-1- | -2- | -3- | Status | Tests |
1 |
- |
- |
Covered |
T1,T2,T3 |
0 |
1 |
- |
Covered |
T1,T2,T3 |
0 |
0 |
1 |
Covered |
T1,T2,T3 |
0 |
0 |
0 |
Covered |
T1,T2,T3 |
600 if (!rst_ni) begin
-1-
601 calc_req_o <= '0;
==>
602 end else if (calc_req_start) begin
-2-
603 calc_req_o <= 1'b1;
==>
604 end else if (calc_req_done) begin
-3-
605 calc_req_o <= 1'b0;
==>
606 end
MISSING_ELSE
==>
Branches:
-1- | -2- | -3- | Status | Tests |
1 |
- |
- |
Covered |
T1,T2,T3 |
0 |
1 |
- |
Covered |
T1,T2,T3 |
0 |
0 |
1 |
Covered |
T1,T2,T3 |
0 |
0 |
0 |
Covered |
T1,T2,T3 |
674 if (buf_rsp_match[i]) begin
-1-
675 buf_rsp_data = read_buf[i].data;
==>
676 buf_addr_xor = read_buf[i].addr;
677 buf_rsp_err = buf_rsp_err | read_buf[i].err;
678 end
MISSING_ELSE
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
Assert Coverage for Module :
flash_phy_rd
Assertion Details
BufferMatchEcc_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
769728838 |
1572120 |
0 |
0 |
T1 |
1636 |
5 |
0 |
0 |
T2 |
1951 |
10 |
0 |
0 |
T3 |
6764 |
21 |
0 |
0 |
T7 |
8492 |
0 |
0 |
0 |
T13 |
47420 |
306 |
0 |
0 |
T14 |
12492 |
141 |
0 |
0 |
T15 |
6830 |
53 |
0 |
0 |
T18 |
5892 |
11 |
0 |
0 |
T19 |
971822 |
2976 |
0 |
0 |
T20 |
140716 |
88 |
0 |
0 |
T32 |
0 |
549 |
0 |
0 |
T41 |
0 |
633 |
0 |
0 |
T48 |
0 |
1234 |
0 |
0 |
T52 |
0 |
977 |
0 |
0 |
T65 |
1935 |
92 |
0 |
0 |
T66 |
3620 |
0 |
0 |
0 |
T73 |
0 |
80 |
0 |
0 |
ExclusiveOps_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
769728838 |
768061634 |
0 |
0 |
T1 |
3272 |
3124 |
0 |
0 |
T2 |
3902 |
3752 |
0 |
0 |
T3 |
6764 |
6620 |
0 |
0 |
T7 |
8492 |
7188 |
0 |
0 |
T13 |
47420 |
47280 |
0 |
0 |
T14 |
12492 |
12296 |
0 |
0 |
T15 |
6830 |
6714 |
0 |
0 |
T18 |
5892 |
5724 |
0 |
0 |
T19 |
971822 |
935742 |
0 |
0 |
T20 |
140716 |
140562 |
0 |
0 |
ExclusiveProgHazard_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
769728838 |
768061634 |
0 |
0 |
T1 |
3272 |
3124 |
0 |
0 |
T2 |
3902 |
3752 |
0 |
0 |
T3 |
6764 |
6620 |
0 |
0 |
T7 |
8492 |
7188 |
0 |
0 |
T13 |
47420 |
47280 |
0 |
0 |
T14 |
12492 |
12296 |
0 |
0 |
T15 |
6830 |
6714 |
0 |
0 |
T18 |
5892 |
5724 |
0 |
0 |
T19 |
971822 |
935742 |
0 |
0 |
T20 |
140716 |
140562 |
0 |
0 |
ExclusiveState_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
769728838 |
768061634 |
0 |
0 |
T1 |
3272 |
3124 |
0 |
0 |
T2 |
3902 |
3752 |
0 |
0 |
T3 |
6764 |
6620 |
0 |
0 |
T7 |
8492 |
7188 |
0 |
0 |
T13 |
47420 |
47280 |
0 |
0 |
T14 |
12492 |
12296 |
0 |
0 |
T15 |
6830 |
6714 |
0 |
0 |
T18 |
5892 |
5724 |
0 |
0 |
T19 |
971822 |
935742 |
0 |
0 |
T20 |
140716 |
140562 |
0 |
0 |
ForwardCheck_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
769728838 |
3638661 |
0 |
0 |
T1 |
1636 |
5 |
0 |
0 |
T2 |
1951 |
10 |
0 |
0 |
T3 |
6764 |
27 |
0 |
0 |
T7 |
8492 |
0 |
0 |
0 |
T13 |
47420 |
365 |
0 |
0 |
T14 |
12492 |
171 |
0 |
0 |
T15 |
6830 |
64 |
0 |
0 |
T18 |
5892 |
13 |
0 |
0 |
T19 |
971822 |
0 |
0 |
0 |
T20 |
140716 |
102 |
0 |
0 |
T32 |
0 |
556 |
0 |
0 |
T48 |
0 |
1234 |
0 |
0 |
T49 |
0 |
42 |
0 |
0 |
T52 |
0 |
9554 |
0 |
0 |
T65 |
1935 |
54 |
0 |
0 |
T66 |
3620 |
0 |
0 |
0 |
T73 |
0 |
81 |
0 |
0 |
IdleCheck_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
769728838 |
97517772 |
0 |
0 |
T1 |
1636 |
143 |
0 |
0 |
T2 |
1951 |
158 |
0 |
0 |
T3 |
6764 |
203 |
0 |
0 |
T7 |
8492 |
704 |
0 |
0 |
T13 |
47420 |
1164 |
0 |
0 |
T14 |
12492 |
611 |
0 |
0 |
T15 |
6830 |
569 |
0 |
0 |
T18 |
5892 |
165 |
0 |
0 |
T19 |
971822 |
44736 |
0 |
0 |
T20 |
140716 |
420 |
0 |
0 |
T32 |
0 |
1661 |
0 |
0 |
T41 |
0 |
33586 |
0 |
0 |
T48 |
0 |
2226 |
0 |
0 |
T49 |
0 |
44 |
0 |
0 |
T52 |
0 |
20085 |
0 |
0 |
T65 |
1935 |
200 |
0 |
0 |
T66 |
3620 |
0 |
0 |
0 |
MaxBufs_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
2084 |
2084 |
0 |
0 |
T1 |
2 |
2 |
0 |
0 |
T2 |
2 |
2 |
0 |
0 |
T3 |
2 |
2 |
0 |
0 |
T7 |
2 |
2 |
0 |
0 |
T13 |
2 |
2 |
0 |
0 |
T14 |
2 |
2 |
0 |
0 |
T15 |
2 |
2 |
0 |
0 |
T18 |
2 |
2 |
0 |
0 |
T19 |
2 |
2 |
0 |
0 |
T20 |
2 |
2 |
0 |
0 |
OneHotAlloc_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
769728838 |
768061634 |
0 |
0 |
T1 |
3272 |
3124 |
0 |
0 |
T2 |
3902 |
3752 |
0 |
0 |
T3 |
6764 |
6620 |
0 |
0 |
T7 |
8492 |
7188 |
0 |
0 |
T13 |
47420 |
47280 |
0 |
0 |
T14 |
12492 |
12296 |
0 |
0 |
T15 |
6830 |
6714 |
0 |
0 |
T18 |
5892 |
5724 |
0 |
0 |
T19 |
971822 |
935742 |
0 |
0 |
T20 |
140716 |
140562 |
0 |
0 |
OneHotMatch_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
769728838 |
768061634 |
0 |
0 |
T1 |
3272 |
3124 |
0 |
0 |
T2 |
3902 |
3752 |
0 |
0 |
T3 |
6764 |
6620 |
0 |
0 |
T7 |
8492 |
7188 |
0 |
0 |
T13 |
47420 |
47280 |
0 |
0 |
T14 |
12492 |
12296 |
0 |
0 |
T15 |
6830 |
6714 |
0 |
0 |
T18 |
5892 |
5724 |
0 |
0 |
T19 |
971822 |
935742 |
0 |
0 |
T20 |
140716 |
140562 |
0 |
0 |
OneHotRspMatch_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
769728838 |
768061634 |
0 |
0 |
T1 |
3272 |
3124 |
0 |
0 |
T2 |
3902 |
3752 |
0 |
0 |
T3 |
6764 |
6620 |
0 |
0 |
T7 |
8492 |
7188 |
0 |
0 |
T13 |
47420 |
47280 |
0 |
0 |
T14 |
12492 |
12296 |
0 |
0 |
T15 |
6830 |
6714 |
0 |
0 |
T18 |
5892 |
5724 |
0 |
0 |
T19 |
971822 |
935742 |
0 |
0 |
T20 |
140716 |
140562 |
0 |
0 |
OneHotUpdate_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
769728838 |
768061634 |
0 |
0 |
T1 |
3272 |
3124 |
0 |
0 |
T2 |
3902 |
3752 |
0 |
0 |
T3 |
6764 |
6620 |
0 |
0 |
T7 |
8492 |
7188 |
0 |
0 |
T13 |
47420 |
47280 |
0 |
0 |
T14 |
12492 |
12296 |
0 |
0 |
T15 |
6830 |
6714 |
0 |
0 |
T18 |
5892 |
5724 |
0 |
0 |
T19 |
971822 |
935742 |
0 |
0 |
T20 |
140716 |
140562 |
0 |
0 |
Line Coverage for Instance : tb.dut.u_eflash.gen_flash_cores[0].u_core.u_rd
| Line No. | Total | Covered | Percent |
TOTAL | | 133 | 133 | 100.00 |
CONT_ASSIGN | 137 | 1 | 1 | 100.00 |
CONT_ASSIGN | 140 | 1 | 1 | 100.00 |
CONT_ASSIGN | 140 | 1 | 1 | 100.00 |
CONT_ASSIGN | 140 | 1 | 1 | 100.00 |
CONT_ASSIGN | 140 | 1 | 1 | 100.00 |
CONT_ASSIGN | 141 | 1 | 1 | 100.00 |
CONT_ASSIGN | 141 | 1 | 1 | 100.00 |
CONT_ASSIGN | 141 | 1 | 1 | 100.00 |
CONT_ASSIGN | 141 | 1 | 1 | 100.00 |
CONT_ASSIGN | 146 | 1 | 1 | 100.00 |
CONT_ASSIGN | 146 | 1 | 1 | 100.00 |
CONT_ASSIGN | 146 | 1 | 1 | 100.00 |
CONT_ASSIGN | 146 | 1 | 1 | 100.00 |
CONT_ASSIGN | 152 | 1 | 1 | 100.00 |
CONT_ASSIGN | 154 | 1 | 1 | 100.00 |
CONT_ASSIGN | 154 | 1 | 1 | 100.00 |
CONT_ASSIGN | 154 | 1 | 1 | 100.00 |
CONT_ASSIGN | 186 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
CONT_ASSIGN | 194 | 1 | 1 | 100.00 |
CONT_ASSIGN | 194 | 1 | 1 | 100.00 |
CONT_ASSIGN | 194 | 1 | 1 | 100.00 |
CONT_ASSIGN | 194 | 1 | 1 | 100.00 |
CONT_ASSIGN | 196 | 1 | 1 | 100.00 |
CONT_ASSIGN | 196 | 1 | 1 | 100.00 |
CONT_ASSIGN | 196 | 1 | 1 | 100.00 |
CONT_ASSIGN | 196 | 1 | 1 | 100.00 |
CONT_ASSIGN | 212 | 1 | 1 | 100.00 |
CONT_ASSIGN | 212 | 1 | 1 | 100.00 |
CONT_ASSIGN | 212 | 1 | 1 | 100.00 |
CONT_ASSIGN | 212 | 1 | 1 | 100.00 |
CONT_ASSIGN | 218 | 1 | 1 | 100.00 |
CONT_ASSIGN | 218 | 1 | 1 | 100.00 |
CONT_ASSIGN | 218 | 1 | 1 | 100.00 |
CONT_ASSIGN | 218 | 1 | 1 | 100.00 |
CONT_ASSIGN | 222 | 1 | 1 | 100.00 |
CONT_ASSIGN | 222 | 1 | 1 | 100.00 |
CONT_ASSIGN | 222 | 1 | 1 | 100.00 |
CONT_ASSIGN | 222 | 1 | 1 | 100.00 |
CONT_ASSIGN | 229 | 1 | 1 | 100.00 |
CONT_ASSIGN | 232 | 1 | 1 | 100.00 |
ALWAYS | 257 | 4 | 4 | 100.00 |
CONT_ASSIGN | 291 | 1 | 1 | 100.00 |
CONT_ASSIGN | 292 | 1 | 1 | 100.00 |
CONT_ASSIGN | 302 | 1 | 1 | 100.00 |
CONT_ASSIGN | 305 | 1 | 1 | 100.00 |
CONT_ASSIGN | 308 | 1 | 1 | 100.00 |
CONT_ASSIGN | 326 | 1 | 1 | 100.00 |
CONT_ASSIGN | 331 | 1 | 1 | 100.00 |
ALWAYS | 360 | 12 | 12 | 100.00 |
CONT_ASSIGN | 377 | 1 | 1 | 100.00 |
CONT_ASSIGN | 382 | 1 | 1 | 100.00 |
CONT_ASSIGN | 393 | 1 | 1 | 100.00 |
CONT_ASSIGN | 399 | 1 | 1 | 100.00 |
CONT_ASSIGN | 407 | 1 | 1 | 100.00 |
CONT_ASSIGN | 428 | 1 | 1 | 100.00 |
CONT_ASSIGN | 432 | 1 | 1 | 100.00 |
CONT_ASSIGN | 442 | 1 | 1 | 100.00 |
CONT_ASSIGN | 445 | 1 | 1 | 100.00 |
CONT_ASSIGN | 451 | 1 | 1 | 100.00 |
CONT_ASSIGN | 456 | 1 | 1 | 100.00 |
CONT_ASSIGN | 459 | 1 | 1 | 100.00 |
CONT_ASSIGN | 491 | 1 | 1 | 100.00 |
CONT_ASSIGN | 494 | 1 | 1 | 100.00 |
CONT_ASSIGN | 497 | 1 | 1 | 100.00 |
CONT_ASSIGN | 501 | 1 | 1 | 100.00 |
CONT_ASSIGN | 503 | 1 | 1 | 100.00 |
CONT_ASSIGN | 504 | 1 | 1 | 100.00 |
CONT_ASSIGN | 505 | 1 | 1 | 100.00 |
CONT_ASSIGN | 513 | 1 | 1 | 100.00 |
CONT_ASSIGN | 521 | 1 | 1 | 100.00 |
CONT_ASSIGN | 523 | 1 | 1 | 100.00 |
CONT_ASSIGN | 597 | 1 | 1 | 100.00 |
CONT_ASSIGN | 598 | 1 | 1 | 100.00 |
ALWAYS | 600 | 6 | 6 | 100.00 |
CONT_ASSIGN | 610 | 1 | 1 | 100.00 |
CONT_ASSIGN | 614 | 1 | 1 | 100.00 |
CONT_ASSIGN | 617 | 1 | 1 | 100.00 |
CONT_ASSIGN | 624 | 1 | 1 | 100.00 |
CONT_ASSIGN | 628 | 1 | 1 | 100.00 |
CONT_ASSIGN | 636 | 1 | 1 | 100.00 |
CONT_ASSIGN | 654 | 1 | 1 | 100.00 |
CONT_ASSIGN | 659 | 1 | 1 | 100.00 |
CONT_ASSIGN | 664 | 1 | 1 | 100.00 |
CONT_ASSIGN | 664 | 1 | 1 | 100.00 |
CONT_ASSIGN | 664 | 1 | 1 | 100.00 |
CONT_ASSIGN | 664 | 1 | 1 | 100.00 |
ALWAYS | 670 | 8 | 8 | 100.00 |
CONT_ASSIGN | 683 | 1 | 1 | 100.00 |
CONT_ASSIGN | 704 | 1 | 1 | 100.00 |
CONT_ASSIGN | 724 | 1 | 1 | 100.00 |
CONT_ASSIGN | 736 | 1 | 1 | 100.00 |
CONT_ASSIGN | 738 | 1 | 1 | 100.00 |
CONT_ASSIGN | 744 | 1 | 1 | 100.00 |
CONT_ASSIGN | 745 | 1 | 1 | 100.00 |
CONT_ASSIGN | 747 | 1 | 1 | 100.00 |
CONT_ASSIGN | 751 | 1 | 1 | 100.00 |
CONT_ASSIGN | 762 | 1 | 1 | 100.00 |
CONT_ASSIGN | 775 | 1 | 1 | 100.00 |
CONT_ASSIGN | 787 | 1 | 1 | 100.00 |
CONT_ASSIGN | 790 | 1 | 1 | 100.00 |
CONT_ASSIGN | 794 | 1 | 1 | 100.00 |
CONT_ASSIGN | 797 | 1 | 1 | 100.00 |
CONT_ASSIGN | 800 | 1 | 1 | 100.00 |
136 logic [BankAddrW-1:0] flash_word_addr;
137 1/1 assign flash_word_addr = addr_i[BusBankAddrW-1:LsbAddrBit];
Tests: T1 T2 T3
138
139 for (genvar i = 0; i < NumBuf; i++) begin: gen_buf_states
140 4/4 assign buf_valid[i] = read_buf[i].attr == Valid;
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
141 4/4 assign buf_wip[i] = read_buf[i].attr == Wip;
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
142
143 // if a buffer is valid and contains an error, it should be considered
144 // invalid as long as there are no pending responses already waiting
145 // on that buffer.
146 4/4 assign buf_invalid[i] = (read_buf[i].attr == Invalid) |
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
147 (read_buf[i].attr == Valid &
148 read_buf[i].err &
149 ~buf_dependency[i]);
150 end
151
152 1/1 assign buf_invalid_alloc[0] = buf_invalid[0];
Tests: T1 T2 T3
153 for (genvar i = 1; i < NumBuf; i++) begin: gen_inv_alloc_bufs
154 3/3 assign buf_invalid_alloc[i] = buf_invalid[i] & ~|buf_invalid[i-1:0];
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3
155 end
156
157 // a prim arbiter is used to somewhat fairly select among the valid buffers
158 logic [1:0] dummy_data [NumBuf];
159 for (genvar i = 0; i < NumBuf; i++) begin: gen_dummy
160 assign dummy_data[i] = '0;
161 end
162
163 prim_arbiter_tree #(
164 .N(NumBuf),
165 .DW(2),
166 .EnDataPort(1'b0)
167 ) u_valid_random (
168 .clk_i,
169 .rst_ni,
170 .req_chk_i(1'b0), // Valid is allowed to drop without ready.
171 // If there is an invalid buffer, always allocate from that one first
172 // If all buffers have a dependency to an in-flight transaction, do not
173 // allocate and wait for the dependencies to end.
174 // If none of the above are true, THEN pick a buffer from the current valid
175 // buffers that DO NOT have an ongoing dependency.
176 .req_i(|buf_invalid_alloc | all_buf_dependency ? '0 : buf_valid & ~buf_dependency),
177 .data_i(dummy_data),
178 .gnt_o(buf_valid_alloc),
179 .idx_o(),
180 .valid_o(),
181 .data_o(),
182 .ready_i(req_o & ack_i & no_match)
183 );
184
185 // which buffer to allocate upon a new transaction
186 1/1 assign buf_alloc = |buf_invalid_alloc ? buf_invalid_alloc : buf_valid_alloc;
Tests: T1 T2 T3
187
188 // do not attempt to generate match unless the transaction is relevant
189 for (genvar i = 0; i < NumBuf; i++) begin: gen_buf_match
190 logic part_match;
191 logic info_sel_match;
192
193 4/4 assign part_match = read_buf[i].part == part_i;
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
194 4/4 assign info_sel_match = read_buf[i].info_sel == info_sel_i;
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
195
196 4/4 assign buf_match[i] = req_i &
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
197 buf_en_q &
198 (buf_valid[i] | buf_wip[i]) &
199 (read_buf[i].addr == flash_word_addr) &
200 ~read_buf[i].err &
201 part_match &
202 info_sel_match;
203
204 // A data hazard should never happen to a wip buffer because it implies
205 // that a read is in progress, so a hazard operation cannot start.
206 // If bank erase, all buffers must be flushed.
207 // If page erase, only if the buffer lands in the same page.
208 // If program, only if it's the same flash word.
209 logic word_addr_match;
210 logic page_addr_match;
211
212 4/4 assign word_addr_match = (read_buf[i].addr == flash_word_addr) &
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
213 part_match &
214 info_sel_match;
215
216 // the read buffer address in on flash word boundary
217 // while the incoming address in on the bus word boundary
218 4/4 assign page_addr_match = (read_buf[i].addr[WordW +: PageW] == addr_i[BusWordW +: PageW]) &
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
219 part_match &
220 info_sel_match;
221
222 4/4 assign data_hazard[i] = buf_valid[i] &
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
223 (bk_erase_i |
224 (prog_i & word_addr_match) |
225 (pg_erase_i & page_addr_match));
226
227 end
228
229 1/1 assign no_match = ~|buf_match;
Tests: T1 T2 T3
230
231 // if new request does not match anything, allocate
232 1/1 assign alloc = no_match ? {NumBuf{req_i & buf_en_q}} & buf_alloc : '0;
Tests: T1 T2 T3
233
234 // read buffers
235 // allocate sets state to Wip
236 // update sets state to valid
237 // wipe sets state to invalid - this comes from prog
238 for (genvar i = 0; i < NumBuf; i++) begin: gen_bufs
239 flash_phy_rd_buffers u_rd_buf (
240 .clk_i,
241 .rst_ni,
242 .en_i(buf_en_q),
243 .alloc_i(rdy_o & alloc[i]),
244 .update_i(update[i]),
245 .err_i(muxed_err),
246 .wipe_i(data_hazard[i]),
247 .addr_i(flash_word_addr),
248 .part_i(part_i),
249 .info_sel_i(info_sel_i),
250 .data_i(muxed_data),
251 .out_o(read_buf[i])
252 );
253 end
254
255 // The buffer enable is allowed to change when the entire read pipeline is idle
256 always_ff @(posedge clk_i or negedge rst_ni) begin
257 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
258 1/1 buf_en_q <= 1'b0;
Tests: T1 T2 T3
259 1/1 end else if (idle_o) begin
Tests: T1 T2 T3
260 1/1 buf_en_q <= buf_en_i;
Tests: T1 T2 T3
261 end
MISSING_ELSE
262 end
263
264 /////////////////////////////////
265 // Flash read stage
266 /////////////////////////////////
267
268 // Flash read stage determines if the transactions are accepted.
269 //
270 // The response fifo is written to when a transaction initiates a flash read OR when a match
271 // is hit. The information written is just the allocated buffer that would have satisfied the
272 // transaction, as well as bits that indicate which part of the buffer is the right return data
273 //
274 // This allows a hit transaction to match in-order, and unblock later transactions to begin
275 // reading from the flash primitive
276
277 rsp_fifo_entry_t rsp_fifo_wdata, rsp_fifo_rdata;
278 logic rsp_fifo_rdy;
279 logic rsp_fifo_vld;
280
281 // saved attributes on flash read
282 logic [NumBuf-1:0] alloc_q;
283 rd_attr_t rd_attrs;
284
285 // read complete
286 // since done is broadcast to all the modules, need to know we are actually active
287 logic rd_start;
288 logic rd_busy;
289 logic rd_done;
290
291 1/1 assign rd_start = req_o & ack_i;
Tests: T1 T2 T3
292 1/1 assign rd_done = rd_busy & done_i;
Tests: T1 T2 T3
293
294 // scramble stage ready
295 logic scramble_stage_rdy;
296
297 // mask calculation done
298 logic calc_req_done;
299
300 // if buffer allocated, that is the return source
301 // if buffer matched, that is the return source
302 1/1 assign rsp_fifo_wdata.buf_sel = |alloc ? buf_alloc : buf_match;
Tests: T1 T2 T3
303
304 logic rsp_order_fifo_wr;
305 1/1 assign rsp_order_fifo_wr = req_i && rdy_o;
Tests: T1 T2 T3
306
307 logic rsp_order_fifo_rd;
308 1/1 assign rsp_order_fifo_rd = rsp_fifo_vld & data_valid_o;
Tests: T1 T2 T3
309
310 flash_phy_rd_buf_dep u_rd_buf_dep (
311 .clk_i,
312 .rst_ni,
313 .en_i(buf_en_q),
314 .fifo_wr_i(rsp_order_fifo_wr),
315 .fifo_rd_i(rsp_order_fifo_rd),
316 .wr_buf_i(rsp_fifo_wdata.buf_sel),
317 .rd_buf_i(rsp_fifo_rdata.buf_sel),
318 .dependency_o(buf_dependency),
319 .all_dependency_o(all_buf_dependency)
320 );
321
322 // If width is the same, word_sel is unused
323 if (WidthMultiple == 1) begin : gen_single_word_sel
324 assign rsp_fifo_wdata.word_sel = '0;
325 end else begin : gen_word_sel
326 1/1 assign rsp_fifo_wdata.word_sel = addr_i[0 +: LsbAddrBit];
Tests: T1 T2 T3
327 end
328
329 // store the ecc configuration for this transaction until
330 // response is ready to be sent.
331 1/1 assign rsp_fifo_wdata.intg_ecc_en = ecc_i;
Tests: T1 T2 T3
332
333 // response order FIFO
334 logic rsp_order_fifo_err;
335 prim_fifo_sync #(
336 .Width (RspOrderFifoWidth),
337 .Pass (0),
338 .Depth (RspOrderDepth),
339 .Secure (1'b1) // SEC_CM: FIFO.CTR.REDUN
340 ) u_rsp_order_fifo (
341 .clk_i,
342 .rst_ni,
343 .clr_i (1'b0),
344 .wvalid_i(rsp_order_fifo_wr),
345 .wready_o(rsp_fifo_rdy),
346 .wdata_i (rsp_fifo_wdata),
347 .depth_o (),
348 .full_o (),
349 .rvalid_o(rsp_fifo_vld),
350 .rready_i(data_valid_o), // pop when a match has been found
351 .rdata_o (rsp_fifo_rdata),
352 .err_o (rsp_order_fifo_err)
353 );
354
355 // Consider converting this to a FIFO for better matching
356 // The rd_busy flag is effectively a "full" flag anyways of a single
357 // entry.
358 logic flash_rdy;
359 always_ff @(posedge clk_i or negedge rst_ni) begin
360 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
361 1/1 alloc_q <= '0;
Tests: T1 T2 T3
362 1/1 rd_attrs <= '0;
Tests: T1 T2 T3
363 1/1 rd_busy <= '0;
Tests: T1 T2 T3
364 1/1 end else if (rd_start) begin
Tests: T1 T2 T3
365 1/1 rd_busy <= 1'b1;
Tests: T1 T2 T3
366 1/1 alloc_q <= alloc;
Tests: T1 T2 T3
367 1/1 rd_attrs.addr <= addr_i[BusBankAddrW-1:LsbAddrBit];
Tests: T1 T2 T3
368 1/1 rd_attrs.descramble <= descramble_i;
Tests: T1 T2 T3
369 1/1 rd_attrs.ecc <= ecc_i;
Tests: T1 T2 T3
370
371 1/1 end else if (rd_done) begin
Tests: T1 T2 T3
372 1/1 rd_busy <= 1'b0;
Tests: T1 T2 T3
373 end
MISSING_ELSE
374 end
375
376 // flash is ready to accept another transaction
377 1/1 assign flash_rdy = ~rd_busy | rd_done;
Tests: T1 T2 T3
378
379 // read stages are ready when both the response fifo and the
380 // data / mask fifos have space for new entries
381 logic rd_stages_rdy;
382 1/1 assign rd_stages_rdy = rsp_fifo_rdy & scramble_stage_rdy;
Tests: T1 T2 T3
383
384 // When buffer enable changes, we want to hold off new requests
385 // until the request is absorbed. buf_en_q is allowed to change
386 // only when the entire read pipeline is idle, however, during that
387 // same cycle there could be a new incoming request.
388 //
389 // We back pressure here instead of waiting for a period of idle + no
390 // request because it potentially means a storm of accesses could
391 // prevent the buffer enable from taking effect.
392 logic no_buf_en_change;
393 1/1 assign no_buf_en_change = (buf_en_q == buf_en_i);
Tests: T1 T2 T3
394
395 // If no buffers matched, accept only if flash is ready and there is space
396 // If buffer is matched, accept as long as there is space in the rsp fifo
397 // If all buffers are currently allocated or have a dependency, wait until
398 // at least 1 dependency has cleared.
399 1/1 assign rdy_o = (no_match ? ack_i & flash_rdy & rd_stages_rdy : rd_stages_rdy) &
Tests: T1 T2 T3
400 ~all_buf_dependency & no_buf_en_change &
401 // If the current read requires descrambling, wait for the
402 // mask calculation to finish before accepting the next request.
403 (calc_req_o ? calc_req_done : 1'b1);
404
405 // issue a transaction to flash only if there is space in read stages,
406 // there is no buffer match and flash is not currently busy.
407 1/1 assign req_o = req_i & no_buf_en_change & flash_rdy & rd_stages_rdy & no_match &
Tests: T1 T2 T3
408 // If the current read requires descrambling, wait for the
409 // mask calculation to finish before accepting the next request.
410 (calc_req_o ? calc_req_done : 1'b1);
411
412 /////////////////////////////////
413 // Handling Reliability ECC
414 /////////////////////////////////
415
416 // only uncorrectable errors are passed on to the fabric
417 logic data_err;
418
419 // scrambled data must pass through ECC first
420 logic valid_ecc;
421 logic ecc_multi_err;
422 logic ecc_single_err;
423 logic [PlainDataWidth-1:0] data_ecc_chk;
424 logic [PlainDataWidth-1:0] data_int;
425 logic data_erased;
426
427 // this ECC check is for reliability ECC
428 1/1 assign valid_ecc = rd_done && rd_attrs.ecc;
Tests: T1 T2 T3
429
430 // When all bits are 1, the data has been erased
431 // This check is only valid when read data returns.
432 1/1 assign data_erased = rd_done & (data_i == {FullDataWidth{1'b1}});
Tests: T1 T2 T3
433
434 prim_secded_hamming_76_68_dec u_dec (
435 .data_i(data_i),
436 .data_o(data_ecc_chk),
437 .syndrome_o(),
438 .err_o({ecc_multi_err, ecc_single_err})
439 );
440
441 // send out error indication when ecc is enabled
442 1/1 assign data_err = valid_ecc & ecc_multi_err;
Tests: T1 T2 T3
443
444 // reliability ECC errors cause both in-band and out-of-band errors
445 1/1 assign relbl_ecc_err_o = data_err;
Tests: T1 T2 T3
446
447 // If there is a detected multi-bit error or a single bit error, always return the
448 // ECC corrected result (even though it is possibly wrong).
449 // There is no data error of any kind (specifically when multi_err is disabled), just
450 // return the raw data so that it can be debugged.
451 1/1 assign data_int = data_err | ecc_single_err_o ?
Tests: T1 T2 T3
452 data_ecc_chk :
453 data_i[PlainDataWidth-1:0];
454
455 // send out error indication when ecc is enabled
456 1/1 assign ecc_single_err_o = valid_ecc & ecc_single_err;
Tests: T1 T2 T3
457
458 // ecc address return is always the full flash word
459 1/1 assign ecc_addr_o = {rd_attrs.addr, {LsbAddrBit{1'b0}}};
Tests: T1 T2 T3
460
461 /////////////////////////////////
462 // De-scrambling stage
463 /////////////////////////////////
464
465 // Even on ECC error, progress through the stage normally
466
467 logic fifo_data_ready;
468 logic fifo_data_valid;
469 logic fifo_forward_pop;
470 logic rd_and_mask_fifo_pop;
471 logic mask_valid;
472 logic [PlainDataWidth-1:0] fifo_data;
473 logic [DataWidth-1:0] mask;
474 logic addr_xor_fifo_rdy;
475 logic [BankAddrW-1:0] fifo_addr_xor;
476 logic data_fifo_rdy;
477 logic mask_fifo_rdy;
478 logic descram;
479 logic dropmsk;
480 logic forward;
481 logic descram_q;
482 logic dropmsk_q;
483 logic forward_q;
484 logic hint_forward;
485 logic hint_dropmsk;
486 logic hint_descram;
487 logic data_err_q;
488 logic [NumBuf-1:0] alloc_q2;
489 logic [1:0] unused_rd_depth, unused_mask_depth, unused_addr_xor_depth;
490
491 1/1 assign scramble_stage_rdy = data_fifo_rdy & mask_fifo_rdy & addr_xor_fifo_rdy;
Tests: T1 T2 T3
492
493 // descramble is only required if the location is scramble enabled AND it is not erased.
494 1/1 assign descram = rd_done & rd_attrs.descramble & ~data_erased;
Tests: T1 T2 T3
495
496 // If the location is scramble enabled but has been erased, we'll need to drop the computed mask.
497 1/1 assign dropmsk = rd_done & rd_attrs.descramble & data_erased;
Tests: T1 T2 T3
498
499 // data is forwarded whenever it does not require descrambling and there are no entries in the
500 // FIFO to ensure the current read cannot run ahead of the descramble.
501 1/1 assign forward = rd_done & ~descram & ~fifo_data_valid;
Tests: T1 T2 T3
502
503 1/1 assign hint_descram = fifo_data_valid & descram_q;
Tests: T1 T2 T3
504 1/1 assign hint_dropmsk = fifo_data_valid & dropmsk_q;
Tests: T1 T2 T3
505 1/1 assign hint_forward = fifo_data_valid & forward_q;
Tests: T1 T2 T3
506
507 // Data is consumed when:
508 // 1. If the location is scramble enabled:
509 // a) When descrambling completes.
510 // b) As soon as the mask computation finishes, in case the mask is to be dropped.
511 // 2. If the location is not scramble enabled:
512 // - As soon as the data is ready from the FIFO. For the forwarding case, see below.
513 1/1 assign fifo_data_ready = hint_descram ? descramble_req_o & descramble_ack_i :
Tests: T1 T2 T3
514 hint_dropmsk ? mask_valid : fifo_data_valid;
515
516 // In the case of forwarding, the storage FIFOs are bypassed but still pushed. Once the forwarded
517 // entries arrive at the output of the read FIFO, we need to drop them. If a mask has been
518 // computed that is not used (e.g. because of erasing a location that is scramble enabled), wait
519 // for the mask computation to be done and then drop the forwarded data together with the
520 // corresponding mask.
521 1/1 assign fifo_forward_pop = hint_forward & (hint_dropmsk ? mask_valid : 1'b1);
Tests: T1 T2 T3
522
523 1/1 assign rd_and_mask_fifo_pop = fifo_data_ready | fifo_forward_pop;
Tests: T1 T2 T3
524
525 // See comment above on how FIFO popping can be improved in the future
526 logic rd_stage_fifo_err;
527 prim_fifo_sync #(
528 .Width (PlainDataWidth + 4 + NumBuf),
529 .Pass (0),
530 .Depth (2),
531 .OutputZeroIfEmpty (1),
532 .Secure (1'b1) // SEC_CM: FIFO.CTR.REDUN
533 ) u_rd_storage (
534 .clk_i,
535 .rst_ni,
536 .clr_i (1'b0),
537 .wvalid_i(rd_done),
538 .wready_o(data_fifo_rdy),
539 .wdata_i ({alloc_q, descram, dropmsk, forward, data_err, data_int}),
540 .depth_o (unused_rd_depth),
541 .full_o (),
542 .rvalid_o(fifo_data_valid),
543 .rready_i(rd_and_mask_fifo_pop),
544 .rdata_o ({alloc_q2, descram_q, dropmsk_q, forward_q, data_err_q, fifo_data}),
545 .err_o (rd_stage_fifo_err)
546 );
547
548 // storage for mask calculations
549 prim_fifo_sync #(
550 .Width (DataWidth),
551 .Pass (0),
552 .Depth (2),
553 .OutputZeroIfEmpty (1)
554 ) u_mask_storage (
555 .clk_i,
556 .rst_ni,
557 .clr_i (1'b0),
558 .wvalid_i(calc_req_done),
559 .wready_o(mask_fifo_rdy),
560 .wdata_i (mask_i),
561 .depth_o (unused_mask_depth),
562 .full_o (),
563 .rvalid_o(mask_valid),
564 .rready_i(rd_and_mask_fifo_pop),
565 .rdata_o (mask),
566 .err_o ()
567 );
568
569 prim_fifo_sync #(
570 .Width (BankAddrW),
571 .Pass (0),
572 .Depth (RspOrderDepth),
573 .OutputZeroIfEmpty (1)
574 ) u_addr_xor_storage (
575 .clk_i,
576 .rst_ni,
577 .clr_i (1'b0),
578 .wvalid_i(rsp_order_fifo_wr),
579 .wready_o(addr_xor_fifo_rdy),
580 .wdata_i (flash_word_addr),
581 .depth_o (unused_addr_xor_depth),
582 .full_o (),
583 .rvalid_o(),
584 .rready_i(data_valid_o),
585 .rdata_o (fifo_addr_xor),
586 .err_o ()
587 );
588
589 // generate the mask calculation request
590 // mask calculation is done in parallel to the read stage
591 // calc_req_o is done after req_o is accepted so that most of the
592 // cycle can be allocated to mask calculation logic. req_o,
593 // unlike calc_req_o, asserts the same cycle the transaction is
594 // received, so much of the timing may have already been lost to
595 // transaction routing.
596 logic calc_req_start;
597 1/1 assign calc_req_start = req_o & ack_i & descramble_i;
Tests: T1 T2 T3
598 1/1 assign calc_req_done = calc_req_o & calc_ack_i;
Tests: T1 T2 T3
599 always_ff @(posedge clk_i or negedge rst_ni) begin
600 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
601 1/1 calc_req_o <= '0;
Tests: T1 T2 T3
602 1/1 end else if (calc_req_start) begin
Tests: T1 T2 T3
603 1/1 calc_req_o <= 1'b1;
Tests: T1 T2 T3
604 1/1 end else if (calc_req_done) begin
Tests: T1 T2 T3
605 1/1 calc_req_o <= 1'b0;
Tests: T1 T2 T3
606 end
MISSING_ELSE
607 end
608
609 // operand to gf_mult
610 1/1 assign calc_addr_o = rd_attrs.addr;
Tests: T1 T2 T3
611
612 // generate the descramble request whenever both stages are available
613 // and there is a need to descramble
614 1/1 assign descramble_req_o = fifo_data_valid & mask_valid & hint_descram;
Tests: T1 T2 T3
615
616 // scrambled data to de-scramble
617 1/1 assign scrambled_data_o = fifo_data[DataWidth-1:0] ^ mask;
Tests: T1 T2 T3
618
619 // muxed responses
620 // When "forward" is true, there is nothing ahead in the pipeline, directly feed data
621 // and error forward.
622 // When "forward" is not true, take the output from the descramble stage, which is
623 // dependent on the scramble hint.
624 1/1 assign muxed_data = forward ? data_int :
Tests: T1 T2 T3
625 hint_descram ? {fifo_data[PlainDataWidth-1 -: PlainIntgWidth],
626 descrambled_data_i ^ mask} :
627 fifo_data;
628 1/1 assign muxed_err = forward ? data_err :
Tests: T1 T2 T3
629 ~hint_forward ? data_err_q : '0;
630
631 // muxed data valid
632 // if no de-scramble required, return data on read complete
633 // if data is all empty (erased), also return data on read complete
634 // if descramble is required, return data when descrambler finishes
635 // if descramble is not required, but there are transactions ahead, return from fifo when ready
636 1/1 assign data_valid = forward | ~hint_forward & fifo_data_ready;
Tests: T1 T2 T3
637
638
639 /////////////////////////////////
640 // Response
641 /////////////////////////////////
642
643 logic flash_rsp_match;
644 logic [NumBuf-1:0] buf_rsp_match;
645 logic [PlainDataWidth-1:0] buf_rsp_data;
646 logic [BankAddrW-1:0] buf_addr_xor;
647 logic buf_rsp_err;
648
649
650 // update buffers
651 // When forwarding, update entry stored in alloc_q
652 // When de-scrambling however, the contents of alloc_q may have already updated to the next read,
653 // so a different pointer is used.
654 1/1 assign update = forward ? alloc_q :
Tests: T1 T2 T3
655 ~hint_forward & fifo_data_ready ? alloc_q2 : '0;
656
657 // match in flash response when allocated buffer is the same as top of response fifo
658 // if read buffers are not enabled, do not check buffer selection
659 1/1 assign flash_rsp_match = rsp_fifo_vld & data_valid &
Tests: T1 T2 T3
660 (~buf_en_q | rsp_fifo_rdata.buf_sel == update);
661
662 // match in buf response when there is a valid buffer that is the same as top of response fifo
663 for (genvar i = 0; i < NumBuf; i++) begin: gen_buf_rsp_match
664 4/4 assign buf_rsp_match[i] = buf_en_q & rsp_fifo_vld &
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
665 (rsp_fifo_rdata.buf_sel[i] & buf_valid[i]);
666 end
667
668 // select among the buffers
669 always_comb begin
670 1/1 buf_rsp_data = muxed_data;
Tests: T1 T2 T3
671 1/1 buf_rsp_err = '0;
Tests: T1 T2 T3
672 1/1 buf_addr_xor = '0;
Tests: T1 T2 T3
673 1/1 for (int i = 0; i < NumBuf; i++) begin
Tests: T1 T2 T3
674 1/1 if (buf_rsp_match[i]) begin
Tests: T1 T2 T3
675 1/1 buf_rsp_data = read_buf[i].data;
Tests: T1 T2 T3
676 1/1 buf_addr_xor = read_buf[i].addr;
Tests: T1 T2 T3
677 1/1 buf_rsp_err = buf_rsp_err | read_buf[i].err;
Tests: T1 T2 T3
678 end
MISSING_ELSE
679 end
680 end
681
682 logic [PlainDataWidth-1:0] data_out_muxed;
683 1/1 assign data_out_muxed = |buf_rsp_match ? buf_rsp_data : muxed_data;
Tests: T1 T2 T3
684
685 logic [BusFullWidth-1:0] data_out_intg;
686 if (WidthMultiple == 1) begin : gen_width_one_rd
687 // When multiple is 1, just pass the read through directly
688 logic unused_word_sel;
689
690 // use the tlul integrity module directly for bus integrity
691 // SEC_CM: MEM.BUS.INTEGRITY
692 tlul_data_integ_enc u_bus_intg (
693 .data_i(data_out_muxed[DataWidth-1:0]),
694 .data_intg_o(data_out_intg)
695 );
696
697 assign unused_word_sel = rsp_fifo_rdata.word_sel;
698
699 end else begin : gen_rd
700 // Re-arrange data into packed array to pick the correct one
701 logic [WidthMultiple-1:0][BusWidth-1:0] bus_words_packed;
702 logic [WidthMultiple-1:0][BusFullWidth-1:0] bus_words_packed_intg;
703 logic [WidthMultiple-1:0][BusFullWidth-1:0] bus_words_packed_intg_buf;
704 1/1 assign bus_words_packed = data_out_muxed[DataWidth-1:0];
Tests: T1 T2 T3
705
706 for (genvar i = 0; i < WidthMultiple; i++) begin: gen_bus_words_intg
707 // use the tlul integrity module directly for bus integrity
708 // SEC_CM: MEM.BUS.INTEGRITY
709 tlul_data_integ_enc u_bus_intg (
710 .data_i(bus_words_packed[i]),
711 .data_intg_o(bus_words_packed_intg[i])
712 );
713
714 // This primitive is used to place a size-only constraint on the
715 // buffers to act as a synthesis optimization barrier.
716 prim_buf #(
717 .Width(BusFullWidth)
718 ) u_prim_buf_intg (
719 .in_i(bus_words_packed_intg[i]),
720 .out_o(bus_words_packed_intg_buf[i])
721 );
722 end
723 // Mux based on selected word.
724 1/1 assign data_out_intg = bus_words_packed_intg_buf[rsp_fifo_rdata.word_sel];
Tests: T1 T2 T3
725
726 end
727
728 // On a data_err_o, send back '1 with data integrity tag on top of this data.
729 logic [BusFullWidth-1:0] inv_data_integ;
730 tlul_data_integ_enc u_bus_inv_data_intg (
731 .data_i({BusWidth{1'b1}}),
732 .data_intg_o(inv_data_integ)
733 );
734
735 logic [BusFullWidth-1:0] data_out_pre_xor;
736 1/1 assign data_out_pre_xor = data_err_o ? inv_data_integ : data_out_intg;
Tests: T1 T2 T3
737
738 1/1 assign data_ctrl_o = data_out_pre_xor;
Tests: T1 T2 T3
739
740 logic [BusBankAddrW-1:0] addr_xor_muxed;
741 logic [BusBankAddrW-1:0] fifo_addr_xor_muxed;
742 logic [BusBankAddrW-1:0] buf_addr_xor_muxed;
743
744 1/1 assign fifo_addr_xor_muxed = {fifo_addr_xor, rsp_fifo_rdata.word_sel};
Tests: T1 T2 T3
745 1/1 assign buf_addr_xor_muxed = {buf_addr_xor, rsp_fifo_rdata.word_sel};
Tests: T1 T2 T3
746
747 1/1 assign addr_xor_muxed = |buf_rsp_match ? buf_addr_xor_muxed : fifo_addr_xor_muxed;
Tests: T1 T2 T3
748
749 logic [BusWidth-1:0] data_out_xor;
750 logic [BusWidth-1:0] data_out_xor_buf;
751 1/1 assign data_out_xor =
Tests: T1 T2 T3
752 data_out_pre_xor[BusWidth-1:0] ^ {{(BusWidth-BusBankAddrW){1'b0}}, addr_xor_muxed};
753
754 // Buffer to ensure that synthesis tool does not optimize the XOR.
755 prim_buf #(
756 .Width(BusWidth)
757 ) u_prim_buf_data_xor_out (
758 .in_i(data_out_xor),
759 .out_o(data_out_xor_buf)
760 );
761
762 1/1 assign data_host_o = {data_out_pre_xor[BusFullWidth-1:BusWidth], data_out_xor_buf};
Tests: T1 T2 T3
763
764 // add plaintext decoding here
765 // plaintext error
766 logic intg_err_pre, intg_err;
767 logic [DataWidth-1:0] unused_data;
768 logic [3:0] unused_intg;
769 logic [3:0] truncated_intg;
770
771 prim_secded_hamming_72_64_enc u_plain_enc (
772 .data_i(data_out_muxed[DataWidth-1:0]),
773 .data_o({unused_intg, truncated_intg, unused_data})
774 );
775 1/1 assign intg_err_pre = rsp_fifo_rdata.intg_ecc_en ?
Tests: T1 T2 T3
776 truncated_intg != data_out_muxed[DataWidth +: PlainIntgWidth] :
777 '0;
778
779 prim_sec_anchor_buf #(
780 .Width(1)
781 ) u_intg_buf (
782 .in_i(intg_err_pre),
783 .out_o(intg_err)
784 );
785
786 // whenever the response is coming from the buffer, the error is never set
787 1/1 assign data_valid_o = flash_rsp_match | (|buf_rsp_match);
Tests: T1 T2 T3
788
789 // integrity and reliability ECC errors always cause in band errors
790 1/1 assign data_err_o = data_valid_o & (muxed_err | intg_err | (|buf_rsp_match & buf_rsp_err)) |
Tests: T1 T2 T3
791 arb_err_i;
792
793 // integrity ECC error can also cause out of band alert
794 1/1 assign intg_ecc_err_o = data_valid_o & intg_err;
Tests: T1 T2 T3
795
796 // the entire read pipeline is idle when there are no responses to return and no
797 1/1 assign idle_o = ~rsp_fifo_vld;
Tests: T1 T2 T3
798
799 // if any fifo shows an integrity error
800 1/1 assign fifo_err_o = |{rsp_order_fifo_err, rd_stage_fifo_err};
Tests: T1 T2 T3
Cond Coverage for Instance : tb.dut.u_eflash.gen_flash_cores[0].u_core.u_rd
| Total | Covered | Percent |
Conditions | 458 | 414 | 90.39 |
Logical | 458 | 414 | 90.39 |
Non-Logical | 0 | 0 | |
Event | 0 | 0 | |
This module contains a very large number of conditions, so the report has been split into multiple pages, by source line number. Click on the line number range in the table below to see the condition coverage for that section of the module.
Branch Coverage for Instance : tb.dut.u_eflash.gen_flash_cores[0].u_core.u_rd
| Line No. | Total | Covered | Percent |
Branches |
|
43 |
43 |
100.00 |
TERNARY |
186 |
2 |
2 |
100.00 |
TERNARY |
232 |
2 |
2 |
100.00 |
TERNARY |
302 |
2 |
2 |
100.00 |
TERNARY |
451 |
2 |
2 |
100.00 |
TERNARY |
513 |
3 |
3 |
100.00 |
TERNARY |
624 |
3 |
3 |
100.00 |
TERNARY |
628 |
3 |
3 |
100.00 |
TERNARY |
654 |
3 |
3 |
100.00 |
TERNARY |
683 |
2 |
2 |
100.00 |
TERNARY |
736 |
2 |
2 |
100.00 |
TERNARY |
747 |
2 |
2 |
100.00 |
TERNARY |
775 |
2 |
2 |
100.00 |
TERNARY |
167 |
2 |
2 |
100.00 |
IF |
257 |
3 |
3 |
100.00 |
IF |
360 |
4 |
4 |
100.00 |
IF |
600 |
4 |
4 |
100.00 |
IF |
674 |
2 |
2 |
100.00 |
186 assign buf_alloc = |buf_invalid_alloc ? buf_invalid_alloc : buf_valid_alloc;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
232 assign alloc = no_match ? {NumBuf{req_i & buf_en_q}} & buf_alloc : '0;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
302 assign rsp_fifo_wdata.buf_sel = |alloc ? buf_alloc : buf_match;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
451 assign data_int = data_err | ecc_single_err_o ?
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T41,T42,T25 |
0 |
Covered |
T1,T2,T3 |
513 assign fifo_data_ready = hint_descram ? descramble_req_o & descramble_ack_i :
-1-
==>
514 hint_dropmsk ? mask_valid : fifo_data_valid;
-2-
==>
==>
Branches:
-1- | -2- | Status | Tests |
1 |
- |
Covered |
T1,T2,T3 |
0 |
1 |
Covered |
T52,T27,T24 |
0 |
0 |
Covered |
T1,T2,T3 |
624 assign muxed_data = forward ? data_int :
-1-
==>
625 hint_descram ? {fifo_data[PlainDataWidth-1 -: PlainIntgWidth],
-2-
==>
==>
Branches:
-1- | -2- | Status | Tests |
1 |
- |
Covered |
T1,T2,T3 |
0 |
1 |
Covered |
T1,T2,T3 |
0 |
0 |
Covered |
T1,T2,T3 |
628 assign muxed_err = forward ? data_err :
-1-
==>
629 ~hint_forward ? data_err_q : '0;
-2-
==>
==>
Branches:
-1- | -2- | Status | Tests |
1 |
- |
Covered |
T1,T2,T3 |
0 |
1 |
Covered |
T1,T2,T3 |
0 |
0 |
Covered |
T1,T2,T3 |
654 assign update = forward ? alloc_q :
-1-
==>
655 ~hint_forward & fifo_data_ready ? alloc_q2 : '0;
-2-
==>
==>
Branches:
-1- | -2- | Status | Tests |
1 |
- |
Covered |
T1,T2,T3 |
0 |
1 |
Covered |
T1,T2,T3 |
0 |
0 |
Covered |
T1,T2,T3 |
683 assign data_out_muxed = |buf_rsp_match ? buf_rsp_data : muxed_data;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
736 assign data_out_pre_xor = data_err_o ? inv_data_integ : data_out_intg;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T7,T25,T63 |
0 |
Covered |
T1,T2,T3 |
747 assign addr_xor_muxed = |buf_rsp_match ? buf_addr_xor_muxed : fifo_addr_xor_muxed;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
775 assign intg_err_pre = rsp_fifo_rdata.intg_ecc_en ?
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
167 ) u_valid_random (
168 .clk_i,
169 .rst_ni,
170 .req_chk_i(1'b0), // Valid is allowed to drop without ready.
171 // If there is an invalid buffer, always allocate from that one first
172 // If all buffers have a dependency to an in-flight transaction, do not
173 // allocate and wait for the dependencies to end.
174 // If none of the above are true, THEN pick a buffer from the current valid
175 // buffers that DO NOT have an ongoing dependency.
176 .req_i(|buf_invalid_alloc | all_buf_dependency ? '0 : buf_valid & ~buf_dependency),
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
257 if (!rst_ni) begin
-1-
258 buf_en_q <= 1'b0;
==>
259 end else if (idle_o) begin
-2-
260 buf_en_q <= buf_en_i;
==>
261 end
MISSING_ELSE
==>
Branches:
-1- | -2- | Status | Tests |
1 |
- |
Covered |
T1,T2,T3 |
0 |
1 |
Covered |
T1,T2,T3 |
0 |
0 |
Covered |
T1,T2,T3 |
360 if (!rst_ni) begin
-1-
361 alloc_q <= '0;
==>
362 rd_attrs <= '0;
363 rd_busy <= '0;
364 end else if (rd_start) begin
-2-
365 rd_busy <= 1'b1;
==>
366 alloc_q <= alloc;
367 rd_attrs.addr <= addr_i[BusBankAddrW-1:LsbAddrBit];
368 rd_attrs.descramble <= descramble_i;
369 rd_attrs.ecc <= ecc_i;
370
371 end else if (rd_done) begin
-3-
372 rd_busy <= 1'b0;
==>
373 end
MISSING_ELSE
==>
Branches:
-1- | -2- | -3- | Status | Tests |
1 |
- |
- |
Covered |
T1,T2,T3 |
0 |
1 |
- |
Covered |
T1,T2,T3 |
0 |
0 |
1 |
Covered |
T1,T2,T3 |
0 |
0 |
0 |
Covered |
T1,T2,T3 |
600 if (!rst_ni) begin
-1-
601 calc_req_o <= '0;
==>
602 end else if (calc_req_start) begin
-2-
603 calc_req_o <= 1'b1;
==>
604 end else if (calc_req_done) begin
-3-
605 calc_req_o <= 1'b0;
==>
606 end
MISSING_ELSE
==>
Branches:
-1- | -2- | -3- | Status | Tests |
1 |
- |
- |
Covered |
T1,T2,T3 |
0 |
1 |
- |
Covered |
T1,T2,T3 |
0 |
0 |
1 |
Covered |
T1,T2,T3 |
0 |
0 |
0 |
Covered |
T1,T2,T3 |
674 if (buf_rsp_match[i]) begin
-1-
675 buf_rsp_data = read_buf[i].data;
==>
676 buf_addr_xor = read_buf[i].addr;
677 buf_rsp_err = buf_rsp_err | read_buf[i].err;
678 end
MISSING_ELSE
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
Assert Coverage for Instance : tb.dut.u_eflash.gen_flash_cores[0].u_core.u_rd
Assertion Details
BufferMatchEcc_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
684754 |
0 |
0 |
T1 |
1636 |
5 |
0 |
0 |
T2 |
1951 |
10 |
0 |
0 |
T3 |
3382 |
16 |
0 |
0 |
T7 |
4246 |
0 |
0 |
0 |
T13 |
23710 |
113 |
0 |
0 |
T14 |
6246 |
77 |
0 |
0 |
T15 |
3415 |
43 |
0 |
0 |
T18 |
2946 |
11 |
0 |
0 |
T19 |
485911 |
2976 |
0 |
0 |
T20 |
70358 |
88 |
0 |
0 |
T48 |
0 |
492 |
0 |
0 |
ExclusiveOps_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
384030817 |
0 |
0 |
T1 |
1636 |
1562 |
0 |
0 |
T2 |
1951 |
1876 |
0 |
0 |
T3 |
3382 |
3310 |
0 |
0 |
T7 |
4246 |
3594 |
0 |
0 |
T13 |
23710 |
23640 |
0 |
0 |
T14 |
6246 |
6148 |
0 |
0 |
T15 |
3415 |
3357 |
0 |
0 |
T18 |
2946 |
2862 |
0 |
0 |
T19 |
485911 |
467871 |
0 |
0 |
T20 |
70358 |
70281 |
0 |
0 |
ExclusiveProgHazard_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
384030817 |
0 |
0 |
T1 |
1636 |
1562 |
0 |
0 |
T2 |
1951 |
1876 |
0 |
0 |
T3 |
3382 |
3310 |
0 |
0 |
T7 |
4246 |
3594 |
0 |
0 |
T13 |
23710 |
23640 |
0 |
0 |
T14 |
6246 |
6148 |
0 |
0 |
T15 |
3415 |
3357 |
0 |
0 |
T18 |
2946 |
2862 |
0 |
0 |
T19 |
485911 |
467871 |
0 |
0 |
T20 |
70358 |
70281 |
0 |
0 |
ExclusiveState_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
384030817 |
0 |
0 |
T1 |
1636 |
1562 |
0 |
0 |
T2 |
1951 |
1876 |
0 |
0 |
T3 |
3382 |
3310 |
0 |
0 |
T7 |
4246 |
3594 |
0 |
0 |
T13 |
23710 |
23640 |
0 |
0 |
T14 |
6246 |
6148 |
0 |
0 |
T15 |
3415 |
3357 |
0 |
0 |
T18 |
2946 |
2862 |
0 |
0 |
T19 |
485911 |
467871 |
0 |
0 |
T20 |
70358 |
70281 |
0 |
0 |
ForwardCheck_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
1727845 |
0 |
0 |
T1 |
1636 |
5 |
0 |
0 |
T2 |
1951 |
10 |
0 |
0 |
T3 |
3382 |
20 |
0 |
0 |
T7 |
4246 |
0 |
0 |
0 |
T13 |
23710 |
135 |
0 |
0 |
T14 |
6246 |
97 |
0 |
0 |
T15 |
3415 |
51 |
0 |
0 |
T18 |
2946 |
13 |
0 |
0 |
T19 |
485911 |
0 |
0 |
0 |
T20 |
70358 |
102 |
0 |
0 |
T48 |
0 |
492 |
0 |
0 |
T49 |
0 |
20 |
0 |
0 |
IdleCheck_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
50066738 |
0 |
0 |
T1 |
1636 |
143 |
0 |
0 |
T2 |
1951 |
158 |
0 |
0 |
T3 |
3382 |
184 |
0 |
0 |
T7 |
4246 |
704 |
0 |
0 |
T13 |
23710 |
511 |
0 |
0 |
T14 |
6246 |
399 |
0 |
0 |
T15 |
3415 |
533 |
0 |
0 |
T18 |
2946 |
165 |
0 |
0 |
T19 |
485911 |
44736 |
0 |
0 |
T20 |
70358 |
420 |
0 |
0 |
MaxBufs_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
1042 |
1042 |
0 |
0 |
T1 |
1 |
1 |
0 |
0 |
T2 |
1 |
1 |
0 |
0 |
T3 |
1 |
1 |
0 |
0 |
T7 |
1 |
1 |
0 |
0 |
T13 |
1 |
1 |
0 |
0 |
T14 |
1 |
1 |
0 |
0 |
T15 |
1 |
1 |
0 |
0 |
T18 |
1 |
1 |
0 |
0 |
T19 |
1 |
1 |
0 |
0 |
T20 |
1 |
1 |
0 |
0 |
OneHotAlloc_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
384030817 |
0 |
0 |
T1 |
1636 |
1562 |
0 |
0 |
T2 |
1951 |
1876 |
0 |
0 |
T3 |
3382 |
3310 |
0 |
0 |
T7 |
4246 |
3594 |
0 |
0 |
T13 |
23710 |
23640 |
0 |
0 |
T14 |
6246 |
6148 |
0 |
0 |
T15 |
3415 |
3357 |
0 |
0 |
T18 |
2946 |
2862 |
0 |
0 |
T19 |
485911 |
467871 |
0 |
0 |
T20 |
70358 |
70281 |
0 |
0 |
OneHotMatch_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
384030817 |
0 |
0 |
T1 |
1636 |
1562 |
0 |
0 |
T2 |
1951 |
1876 |
0 |
0 |
T3 |
3382 |
3310 |
0 |
0 |
T7 |
4246 |
3594 |
0 |
0 |
T13 |
23710 |
23640 |
0 |
0 |
T14 |
6246 |
6148 |
0 |
0 |
T15 |
3415 |
3357 |
0 |
0 |
T18 |
2946 |
2862 |
0 |
0 |
T19 |
485911 |
467871 |
0 |
0 |
T20 |
70358 |
70281 |
0 |
0 |
OneHotRspMatch_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
384030817 |
0 |
0 |
T1 |
1636 |
1562 |
0 |
0 |
T2 |
1951 |
1876 |
0 |
0 |
T3 |
3382 |
3310 |
0 |
0 |
T7 |
4246 |
3594 |
0 |
0 |
T13 |
23710 |
23640 |
0 |
0 |
T14 |
6246 |
6148 |
0 |
0 |
T15 |
3415 |
3357 |
0 |
0 |
T18 |
2946 |
2862 |
0 |
0 |
T19 |
485911 |
467871 |
0 |
0 |
T20 |
70358 |
70281 |
0 |
0 |
OneHotUpdate_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
384030817 |
0 |
0 |
T1 |
1636 |
1562 |
0 |
0 |
T2 |
1951 |
1876 |
0 |
0 |
T3 |
3382 |
3310 |
0 |
0 |
T7 |
4246 |
3594 |
0 |
0 |
T13 |
23710 |
23640 |
0 |
0 |
T14 |
6246 |
6148 |
0 |
0 |
T15 |
3415 |
3357 |
0 |
0 |
T18 |
2946 |
2862 |
0 |
0 |
T19 |
485911 |
467871 |
0 |
0 |
T20 |
70358 |
70281 |
0 |
0 |
Line Coverage for Instance : tb.dut.u_eflash.gen_flash_cores[1].u_core.u_rd
| Line No. | Total | Covered | Percent |
TOTAL | | 133 | 133 | 100.00 |
CONT_ASSIGN | 137 | 1 | 1 | 100.00 |
CONT_ASSIGN | 140 | 1 | 1 | 100.00 |
CONT_ASSIGN | 140 | 1 | 1 | 100.00 |
CONT_ASSIGN | 140 | 1 | 1 | 100.00 |
CONT_ASSIGN | 140 | 1 | 1 | 100.00 |
CONT_ASSIGN | 141 | 1 | 1 | 100.00 |
CONT_ASSIGN | 141 | 1 | 1 | 100.00 |
CONT_ASSIGN | 141 | 1 | 1 | 100.00 |
CONT_ASSIGN | 141 | 1 | 1 | 100.00 |
CONT_ASSIGN | 146 | 1 | 1 | 100.00 |
CONT_ASSIGN | 146 | 1 | 1 | 100.00 |
CONT_ASSIGN | 146 | 1 | 1 | 100.00 |
CONT_ASSIGN | 146 | 1 | 1 | 100.00 |
CONT_ASSIGN | 152 | 1 | 1 | 100.00 |
CONT_ASSIGN | 154 | 1 | 1 | 100.00 |
CONT_ASSIGN | 154 | 1 | 1 | 100.00 |
CONT_ASSIGN | 154 | 1 | 1 | 100.00 |
CONT_ASSIGN | 186 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
CONT_ASSIGN | 194 | 1 | 1 | 100.00 |
CONT_ASSIGN | 194 | 1 | 1 | 100.00 |
CONT_ASSIGN | 194 | 1 | 1 | 100.00 |
CONT_ASSIGN | 194 | 1 | 1 | 100.00 |
CONT_ASSIGN | 196 | 1 | 1 | 100.00 |
CONT_ASSIGN | 196 | 1 | 1 | 100.00 |
CONT_ASSIGN | 196 | 1 | 1 | 100.00 |
CONT_ASSIGN | 196 | 1 | 1 | 100.00 |
CONT_ASSIGN | 212 | 1 | 1 | 100.00 |
CONT_ASSIGN | 212 | 1 | 1 | 100.00 |
CONT_ASSIGN | 212 | 1 | 1 | 100.00 |
CONT_ASSIGN | 212 | 1 | 1 | 100.00 |
CONT_ASSIGN | 218 | 1 | 1 | 100.00 |
CONT_ASSIGN | 218 | 1 | 1 | 100.00 |
CONT_ASSIGN | 218 | 1 | 1 | 100.00 |
CONT_ASSIGN | 218 | 1 | 1 | 100.00 |
CONT_ASSIGN | 222 | 1 | 1 | 100.00 |
CONT_ASSIGN | 222 | 1 | 1 | 100.00 |
CONT_ASSIGN | 222 | 1 | 1 | 100.00 |
CONT_ASSIGN | 222 | 1 | 1 | 100.00 |
CONT_ASSIGN | 229 | 1 | 1 | 100.00 |
CONT_ASSIGN | 232 | 1 | 1 | 100.00 |
ALWAYS | 257 | 4 | 4 | 100.00 |
CONT_ASSIGN | 291 | 1 | 1 | 100.00 |
CONT_ASSIGN | 292 | 1 | 1 | 100.00 |
CONT_ASSIGN | 302 | 1 | 1 | 100.00 |
CONT_ASSIGN | 305 | 1 | 1 | 100.00 |
CONT_ASSIGN | 308 | 1 | 1 | 100.00 |
CONT_ASSIGN | 326 | 1 | 1 | 100.00 |
CONT_ASSIGN | 331 | 1 | 1 | 100.00 |
ALWAYS | 360 | 12 | 12 | 100.00 |
CONT_ASSIGN | 377 | 1 | 1 | 100.00 |
CONT_ASSIGN | 382 | 1 | 1 | 100.00 |
CONT_ASSIGN | 393 | 1 | 1 | 100.00 |
CONT_ASSIGN | 399 | 1 | 1 | 100.00 |
CONT_ASSIGN | 407 | 1 | 1 | 100.00 |
CONT_ASSIGN | 428 | 1 | 1 | 100.00 |
CONT_ASSIGN | 432 | 1 | 1 | 100.00 |
CONT_ASSIGN | 442 | 1 | 1 | 100.00 |
CONT_ASSIGN | 445 | 1 | 1 | 100.00 |
CONT_ASSIGN | 451 | 1 | 1 | 100.00 |
CONT_ASSIGN | 456 | 1 | 1 | 100.00 |
CONT_ASSIGN | 459 | 1 | 1 | 100.00 |
CONT_ASSIGN | 491 | 1 | 1 | 100.00 |
CONT_ASSIGN | 494 | 1 | 1 | 100.00 |
CONT_ASSIGN | 497 | 1 | 1 | 100.00 |
CONT_ASSIGN | 501 | 1 | 1 | 100.00 |
CONT_ASSIGN | 503 | 1 | 1 | 100.00 |
CONT_ASSIGN | 504 | 1 | 1 | 100.00 |
CONT_ASSIGN | 505 | 1 | 1 | 100.00 |
CONT_ASSIGN | 513 | 1 | 1 | 100.00 |
CONT_ASSIGN | 521 | 1 | 1 | 100.00 |
CONT_ASSIGN | 523 | 1 | 1 | 100.00 |
CONT_ASSIGN | 597 | 1 | 1 | 100.00 |
CONT_ASSIGN | 598 | 1 | 1 | 100.00 |
ALWAYS | 600 | 6 | 6 | 100.00 |
CONT_ASSIGN | 610 | 1 | 1 | 100.00 |
CONT_ASSIGN | 614 | 1 | 1 | 100.00 |
CONT_ASSIGN | 617 | 1 | 1 | 100.00 |
CONT_ASSIGN | 624 | 1 | 1 | 100.00 |
CONT_ASSIGN | 628 | 1 | 1 | 100.00 |
CONT_ASSIGN | 636 | 1 | 1 | 100.00 |
CONT_ASSIGN | 654 | 1 | 1 | 100.00 |
CONT_ASSIGN | 659 | 1 | 1 | 100.00 |
CONT_ASSIGN | 664 | 1 | 1 | 100.00 |
CONT_ASSIGN | 664 | 1 | 1 | 100.00 |
CONT_ASSIGN | 664 | 1 | 1 | 100.00 |
CONT_ASSIGN | 664 | 1 | 1 | 100.00 |
ALWAYS | 670 | 8 | 8 | 100.00 |
CONT_ASSIGN | 683 | 1 | 1 | 100.00 |
CONT_ASSIGN | 704 | 1 | 1 | 100.00 |
CONT_ASSIGN | 724 | 1 | 1 | 100.00 |
CONT_ASSIGN | 736 | 1 | 1 | 100.00 |
CONT_ASSIGN | 738 | 1 | 1 | 100.00 |
CONT_ASSIGN | 744 | 1 | 1 | 100.00 |
CONT_ASSIGN | 745 | 1 | 1 | 100.00 |
CONT_ASSIGN | 747 | 1 | 1 | 100.00 |
CONT_ASSIGN | 751 | 1 | 1 | 100.00 |
CONT_ASSIGN | 762 | 1 | 1 | 100.00 |
CONT_ASSIGN | 775 | 1 | 1 | 100.00 |
CONT_ASSIGN | 787 | 1 | 1 | 100.00 |
CONT_ASSIGN | 790 | 1 | 1 | 100.00 |
CONT_ASSIGN | 794 | 1 | 1 | 100.00 |
CONT_ASSIGN | 797 | 1 | 1 | 100.00 |
CONT_ASSIGN | 800 | 1 | 1 | 100.00 |
136 logic [BankAddrW-1:0] flash_word_addr;
137 1/1 assign flash_word_addr = addr_i[BusBankAddrW-1:LsbAddrBit];
Tests: T1 T2 T3
138
139 for (genvar i = 0; i < NumBuf; i++) begin: gen_buf_states
140 4/4 assign buf_valid[i] = read_buf[i].attr == Valid;
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
141 4/4 assign buf_wip[i] = read_buf[i].attr == Wip;
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
142
143 // if a buffer is valid and contains an error, it should be considered
144 // invalid as long as there are no pending responses already waiting
145 // on that buffer.
146 4/4 assign buf_invalid[i] = (read_buf[i].attr == Invalid) |
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
147 (read_buf[i].attr == Valid &
148 read_buf[i].err &
149 ~buf_dependency[i]);
150 end
151
152 1/1 assign buf_invalid_alloc[0] = buf_invalid[0];
Tests: T1 T2 T3
153 for (genvar i = 1; i < NumBuf; i++) begin: gen_inv_alloc_bufs
154 3/3 assign buf_invalid_alloc[i] = buf_invalid[i] & ~|buf_invalid[i-1:0];
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3
155 end
156
157 // a prim arbiter is used to somewhat fairly select among the valid buffers
158 logic [1:0] dummy_data [NumBuf];
159 for (genvar i = 0; i < NumBuf; i++) begin: gen_dummy
160 assign dummy_data[i] = '0;
161 end
162
163 prim_arbiter_tree #(
164 .N(NumBuf),
165 .DW(2),
166 .EnDataPort(1'b0)
167 ) u_valid_random (
168 .clk_i,
169 .rst_ni,
170 .req_chk_i(1'b0), // Valid is allowed to drop without ready.
171 // If there is an invalid buffer, always allocate from that one first
172 // If all buffers have a dependency to an in-flight transaction, do not
173 // allocate and wait for the dependencies to end.
174 // If none of the above are true, THEN pick a buffer from the current valid
175 // buffers that DO NOT have an ongoing dependency.
176 .req_i(|buf_invalid_alloc | all_buf_dependency ? '0 : buf_valid & ~buf_dependency),
177 .data_i(dummy_data),
178 .gnt_o(buf_valid_alloc),
179 .idx_o(),
180 .valid_o(),
181 .data_o(),
182 .ready_i(req_o & ack_i & no_match)
183 );
184
185 // which buffer to allocate upon a new transaction
186 1/1 assign buf_alloc = |buf_invalid_alloc ? buf_invalid_alloc : buf_valid_alloc;
Tests: T1 T2 T3
187
188 // do not attempt to generate match unless the transaction is relevant
189 for (genvar i = 0; i < NumBuf; i++) begin: gen_buf_match
190 logic part_match;
191 logic info_sel_match;
192
193 4/4 assign part_match = read_buf[i].part == part_i;
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
194 4/4 assign info_sel_match = read_buf[i].info_sel == info_sel_i;
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
195
196 4/4 assign buf_match[i] = req_i &
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
197 buf_en_q &
198 (buf_valid[i] | buf_wip[i]) &
199 (read_buf[i].addr == flash_word_addr) &
200 ~read_buf[i].err &
201 part_match &
202 info_sel_match;
203
204 // A data hazard should never happen to a wip buffer because it implies
205 // that a read is in progress, so a hazard operation cannot start.
206 // If bank erase, all buffers must be flushed.
207 // If page erase, only if the buffer lands in the same page.
208 // If program, only if it's the same flash word.
209 logic word_addr_match;
210 logic page_addr_match;
211
212 4/4 assign word_addr_match = (read_buf[i].addr == flash_word_addr) &
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
213 part_match &
214 info_sel_match;
215
216 // the read buffer address in on flash word boundary
217 // while the incoming address in on the bus word boundary
218 4/4 assign page_addr_match = (read_buf[i].addr[WordW +: PageW] == addr_i[BusWordW +: PageW]) &
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
219 part_match &
220 info_sel_match;
221
222 4/4 assign data_hazard[i] = buf_valid[i] &
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
223 (bk_erase_i |
224 (prog_i & word_addr_match) |
225 (pg_erase_i & page_addr_match));
226
227 end
228
229 1/1 assign no_match = ~|buf_match;
Tests: T1 T2 T3
230
231 // if new request does not match anything, allocate
232 1/1 assign alloc = no_match ? {NumBuf{req_i & buf_en_q}} & buf_alloc : '0;
Tests: T1 T2 T3
233
234 // read buffers
235 // allocate sets state to Wip
236 // update sets state to valid
237 // wipe sets state to invalid - this comes from prog
238 for (genvar i = 0; i < NumBuf; i++) begin: gen_bufs
239 flash_phy_rd_buffers u_rd_buf (
240 .clk_i,
241 .rst_ni,
242 .en_i(buf_en_q),
243 .alloc_i(rdy_o & alloc[i]),
244 .update_i(update[i]),
245 .err_i(muxed_err),
246 .wipe_i(data_hazard[i]),
247 .addr_i(flash_word_addr),
248 .part_i(part_i),
249 .info_sel_i(info_sel_i),
250 .data_i(muxed_data),
251 .out_o(read_buf[i])
252 );
253 end
254
255 // The buffer enable is allowed to change when the entire read pipeline is idle
256 always_ff @(posedge clk_i or negedge rst_ni) begin
257 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
258 1/1 buf_en_q <= 1'b0;
Tests: T1 T2 T3
259 1/1 end else if (idle_o) begin
Tests: T1 T2 T3
260 1/1 buf_en_q <= buf_en_i;
Tests: T1 T2 T3
261 end
MISSING_ELSE
262 end
263
264 /////////////////////////////////
265 // Flash read stage
266 /////////////////////////////////
267
268 // Flash read stage determines if the transactions are accepted.
269 //
270 // The response fifo is written to when a transaction initiates a flash read OR when a match
271 // is hit. The information written is just the allocated buffer that would have satisfied the
272 // transaction, as well as bits that indicate which part of the buffer is the right return data
273 //
274 // This allows a hit transaction to match in-order, and unblock later transactions to begin
275 // reading from the flash primitive
276
277 rsp_fifo_entry_t rsp_fifo_wdata, rsp_fifo_rdata;
278 logic rsp_fifo_rdy;
279 logic rsp_fifo_vld;
280
281 // saved attributes on flash read
282 logic [NumBuf-1:0] alloc_q;
283 rd_attr_t rd_attrs;
284
285 // read complete
286 // since done is broadcast to all the modules, need to know we are actually active
287 logic rd_start;
288 logic rd_busy;
289 logic rd_done;
290
291 1/1 assign rd_start = req_o & ack_i;
Tests: T1 T2 T3
292 1/1 assign rd_done = rd_busy & done_i;
Tests: T1 T2 T3
293
294 // scramble stage ready
295 logic scramble_stage_rdy;
296
297 // mask calculation done
298 logic calc_req_done;
299
300 // if buffer allocated, that is the return source
301 // if buffer matched, that is the return source
302 1/1 assign rsp_fifo_wdata.buf_sel = |alloc ? buf_alloc : buf_match;
Tests: T1 T2 T3
303
304 logic rsp_order_fifo_wr;
305 1/1 assign rsp_order_fifo_wr = req_i && rdy_o;
Tests: T1 T2 T3
306
307 logic rsp_order_fifo_rd;
308 1/1 assign rsp_order_fifo_rd = rsp_fifo_vld & data_valid_o;
Tests: T1 T2 T3
309
310 flash_phy_rd_buf_dep u_rd_buf_dep (
311 .clk_i,
312 .rst_ni,
313 .en_i(buf_en_q),
314 .fifo_wr_i(rsp_order_fifo_wr),
315 .fifo_rd_i(rsp_order_fifo_rd),
316 .wr_buf_i(rsp_fifo_wdata.buf_sel),
317 .rd_buf_i(rsp_fifo_rdata.buf_sel),
318 .dependency_o(buf_dependency),
319 .all_dependency_o(all_buf_dependency)
320 );
321
322 // If width is the same, word_sel is unused
323 if (WidthMultiple == 1) begin : gen_single_word_sel
324 assign rsp_fifo_wdata.word_sel = '0;
325 end else begin : gen_word_sel
326 1/1 assign rsp_fifo_wdata.word_sel = addr_i[0 +: LsbAddrBit];
Tests: T1 T2 T3
327 end
328
329 // store the ecc configuration for this transaction until
330 // response is ready to be sent.
331 1/1 assign rsp_fifo_wdata.intg_ecc_en = ecc_i;
Tests: T1 T2 T3
332
333 // response order FIFO
334 logic rsp_order_fifo_err;
335 prim_fifo_sync #(
336 .Width (RspOrderFifoWidth),
337 .Pass (0),
338 .Depth (RspOrderDepth),
339 .Secure (1'b1) // SEC_CM: FIFO.CTR.REDUN
340 ) u_rsp_order_fifo (
341 .clk_i,
342 .rst_ni,
343 .clr_i (1'b0),
344 .wvalid_i(rsp_order_fifo_wr),
345 .wready_o(rsp_fifo_rdy),
346 .wdata_i (rsp_fifo_wdata),
347 .depth_o (),
348 .full_o (),
349 .rvalid_o(rsp_fifo_vld),
350 .rready_i(data_valid_o), // pop when a match has been found
351 .rdata_o (rsp_fifo_rdata),
352 .err_o (rsp_order_fifo_err)
353 );
354
355 // Consider converting this to a FIFO for better matching
356 // The rd_busy flag is effectively a "full" flag anyways of a single
357 // entry.
358 logic flash_rdy;
359 always_ff @(posedge clk_i or negedge rst_ni) begin
360 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
361 1/1 alloc_q <= '0;
Tests: T1 T2 T3
362 1/1 rd_attrs <= '0;
Tests: T1 T2 T3
363 1/1 rd_busy <= '0;
Tests: T1 T2 T3
364 1/1 end else if (rd_start) begin
Tests: T1 T2 T3
365 1/1 rd_busy <= 1'b1;
Tests: T3 T13 T14
366 1/1 alloc_q <= alloc;
Tests: T3 T13 T14
367 1/1 rd_attrs.addr <= addr_i[BusBankAddrW-1:LsbAddrBit];
Tests: T3 T13 T14
368 1/1 rd_attrs.descramble <= descramble_i;
Tests: T3 T13 T14
369 1/1 rd_attrs.ecc <= ecc_i;
Tests: T3 T13 T14
370
371 1/1 end else if (rd_done) begin
Tests: T1 T2 T3
372 1/1 rd_busy <= 1'b0;
Tests: T3 T13 T14
373 end
MISSING_ELSE
374 end
375
376 // flash is ready to accept another transaction
377 1/1 assign flash_rdy = ~rd_busy | rd_done;
Tests: T1 T2 T3
378
379 // read stages are ready when both the response fifo and the
380 // data / mask fifos have space for new entries
381 logic rd_stages_rdy;
382 1/1 assign rd_stages_rdy = rsp_fifo_rdy & scramble_stage_rdy;
Tests: T1 T2 T3
383
384 // When buffer enable changes, we want to hold off new requests
385 // until the request is absorbed. buf_en_q is allowed to change
386 // only when the entire read pipeline is idle, however, during that
387 // same cycle there could be a new incoming request.
388 //
389 // We back pressure here instead of waiting for a period of idle + no
390 // request because it potentially means a storm of accesses could
391 // prevent the buffer enable from taking effect.
392 logic no_buf_en_change;
393 1/1 assign no_buf_en_change = (buf_en_q == buf_en_i);
Tests: T1 T2 T3
394
395 // If no buffers matched, accept only if flash is ready and there is space
396 // If buffer is matched, accept as long as there is space in the rsp fifo
397 // If all buffers are currently allocated or have a dependency, wait until
398 // at least 1 dependency has cleared.
399 1/1 assign rdy_o = (no_match ? ack_i & flash_rdy & rd_stages_rdy : rd_stages_rdy) &
Tests: T1 T2 T3
400 ~all_buf_dependency & no_buf_en_change &
401 // If the current read requires descrambling, wait for the
402 // mask calculation to finish before accepting the next request.
403 (calc_req_o ? calc_req_done : 1'b1);
404
405 // issue a transaction to flash only if there is space in read stages,
406 // there is no buffer match and flash is not currently busy.
407 1/1 assign req_o = req_i & no_buf_en_change & flash_rdy & rd_stages_rdy & no_match &
Tests: T1 T2 T3
408 // If the current read requires descrambling, wait for the
409 // mask calculation to finish before accepting the next request.
410 (calc_req_o ? calc_req_done : 1'b1);
411
412 /////////////////////////////////
413 // Handling Reliability ECC
414 /////////////////////////////////
415
416 // only uncorrectable errors are passed on to the fabric
417 logic data_err;
418
419 // scrambled data must pass through ECC first
420 logic valid_ecc;
421 logic ecc_multi_err;
422 logic ecc_single_err;
423 logic [PlainDataWidth-1:0] data_ecc_chk;
424 logic [PlainDataWidth-1:0] data_int;
425 logic data_erased;
426
427 // this ECC check is for reliability ECC
428 1/1 assign valid_ecc = rd_done && rd_attrs.ecc;
Tests: T1 T2 T3
429
430 // When all bits are 1, the data has been erased
431 // This check is only valid when read data returns.
432 1/1 assign data_erased = rd_done & (data_i == {FullDataWidth{1'b1}});
Tests: T1 T2 T3
433
434 prim_secded_hamming_76_68_dec u_dec (
435 .data_i(data_i),
436 .data_o(data_ecc_chk),
437 .syndrome_o(),
438 .err_o({ecc_multi_err, ecc_single_err})
439 );
440
441 // send out error indication when ecc is enabled
442 1/1 assign data_err = valid_ecc & ecc_multi_err;
Tests: T1 T2 T3
443
444 // reliability ECC errors cause both in-band and out-of-band errors
445 1/1 assign relbl_ecc_err_o = data_err;
Tests: T1 T2 T3
446
447 // If there is a detected multi-bit error or a single bit error, always return the
448 // ECC corrected result (even though it is possibly wrong).
449 // There is no data error of any kind (specifically when multi_err is disabled), just
450 // return the raw data so that it can be debugged.
451 1/1 assign data_int = data_err | ecc_single_err_o ?
Tests: T1 T2 T3
452 data_ecc_chk :
453 data_i[PlainDataWidth-1:0];
454
455 // send out error indication when ecc is enabled
456 1/1 assign ecc_single_err_o = valid_ecc & ecc_single_err;
Tests: T1 T2 T3
457
458 // ecc address return is always the full flash word
459 1/1 assign ecc_addr_o = {rd_attrs.addr, {LsbAddrBit{1'b0}}};
Tests: T1 T2 T3
460
461 /////////////////////////////////
462 // De-scrambling stage
463 /////////////////////////////////
464
465 // Even on ECC error, progress through the stage normally
466
467 logic fifo_data_ready;
468 logic fifo_data_valid;
469 logic fifo_forward_pop;
470 logic rd_and_mask_fifo_pop;
471 logic mask_valid;
472 logic [PlainDataWidth-1:0] fifo_data;
473 logic [DataWidth-1:0] mask;
474 logic addr_xor_fifo_rdy;
475 logic [BankAddrW-1:0] fifo_addr_xor;
476 logic data_fifo_rdy;
477 logic mask_fifo_rdy;
478 logic descram;
479 logic dropmsk;
480 logic forward;
481 logic descram_q;
482 logic dropmsk_q;
483 logic forward_q;
484 logic hint_forward;
485 logic hint_dropmsk;
486 logic hint_descram;
487 logic data_err_q;
488 logic [NumBuf-1:0] alloc_q2;
489 logic [1:0] unused_rd_depth, unused_mask_depth, unused_addr_xor_depth;
490
491 1/1 assign scramble_stage_rdy = data_fifo_rdy & mask_fifo_rdy & addr_xor_fifo_rdy;
Tests: T1 T2 T3
492
493 // descramble is only required if the location is scramble enabled AND it is not erased.
494 1/1 assign descram = rd_done & rd_attrs.descramble & ~data_erased;
Tests: T1 T2 T3
495
496 // If the location is scramble enabled but has been erased, we'll need to drop the computed mask.
497 1/1 assign dropmsk = rd_done & rd_attrs.descramble & data_erased;
Tests: T1 T2 T3
498
499 // data is forwarded whenever it does not require descrambling and there are no entries in the
500 // FIFO to ensure the current read cannot run ahead of the descramble.
501 1/1 assign forward = rd_done & ~descram & ~fifo_data_valid;
Tests: T1 T2 T3
502
503 1/1 assign hint_descram = fifo_data_valid & descram_q;
Tests: T1 T2 T3
504 1/1 assign hint_dropmsk = fifo_data_valid & dropmsk_q;
Tests: T1 T2 T3
505 1/1 assign hint_forward = fifo_data_valid & forward_q;
Tests: T1 T2 T3
506
507 // Data is consumed when:
508 // 1. If the location is scramble enabled:
509 // a) When descrambling completes.
510 // b) As soon as the mask computation finishes, in case the mask is to be dropped.
511 // 2. If the location is not scramble enabled:
512 // - As soon as the data is ready from the FIFO. For the forwarding case, see below.
513 1/1 assign fifo_data_ready = hint_descram ? descramble_req_o & descramble_ack_i :
Tests: T1 T2 T3
514 hint_dropmsk ? mask_valid : fifo_data_valid;
515
516 // In the case of forwarding, the storage FIFOs are bypassed but still pushed. Once the forwarded
517 // entries arrive at the output of the read FIFO, we need to drop them. If a mask has been
518 // computed that is not used (e.g. because of erasing a location that is scramble enabled), wait
519 // for the mask computation to be done and then drop the forwarded data together with the
520 // corresponding mask.
521 1/1 assign fifo_forward_pop = hint_forward & (hint_dropmsk ? mask_valid : 1'b1);
Tests: T1 T2 T3
522
523 1/1 assign rd_and_mask_fifo_pop = fifo_data_ready | fifo_forward_pop;
Tests: T1 T2 T3
524
525 // See comment above on how FIFO popping can be improved in the future
526 logic rd_stage_fifo_err;
527 prim_fifo_sync #(
528 .Width (PlainDataWidth + 4 + NumBuf),
529 .Pass (0),
530 .Depth (2),
531 .OutputZeroIfEmpty (1),
532 .Secure (1'b1) // SEC_CM: FIFO.CTR.REDUN
533 ) u_rd_storage (
534 .clk_i,
535 .rst_ni,
536 .clr_i (1'b0),
537 .wvalid_i(rd_done),
538 .wready_o(data_fifo_rdy),
539 .wdata_i ({alloc_q, descram, dropmsk, forward, data_err, data_int}),
540 .depth_o (unused_rd_depth),
541 .full_o (),
542 .rvalid_o(fifo_data_valid),
543 .rready_i(rd_and_mask_fifo_pop),
544 .rdata_o ({alloc_q2, descram_q, dropmsk_q, forward_q, data_err_q, fifo_data}),
545 .err_o (rd_stage_fifo_err)
546 );
547
548 // storage for mask calculations
549 prim_fifo_sync #(
550 .Width (DataWidth),
551 .Pass (0),
552 .Depth (2),
553 .OutputZeroIfEmpty (1)
554 ) u_mask_storage (
555 .clk_i,
556 .rst_ni,
557 .clr_i (1'b0),
558 .wvalid_i(calc_req_done),
559 .wready_o(mask_fifo_rdy),
560 .wdata_i (mask_i),
561 .depth_o (unused_mask_depth),
562 .full_o (),
563 .rvalid_o(mask_valid),
564 .rready_i(rd_and_mask_fifo_pop),
565 .rdata_o (mask),
566 .err_o ()
567 );
568
569 prim_fifo_sync #(
570 .Width (BankAddrW),
571 .Pass (0),
572 .Depth (RspOrderDepth),
573 .OutputZeroIfEmpty (1)
574 ) u_addr_xor_storage (
575 .clk_i,
576 .rst_ni,
577 .clr_i (1'b0),
578 .wvalid_i(rsp_order_fifo_wr),
579 .wready_o(addr_xor_fifo_rdy),
580 .wdata_i (flash_word_addr),
581 .depth_o (unused_addr_xor_depth),
582 .full_o (),
583 .rvalid_o(),
584 .rready_i(data_valid_o),
585 .rdata_o (fifo_addr_xor),
586 .err_o ()
587 );
588
589 // generate the mask calculation request
590 // mask calculation is done in parallel to the read stage
591 // calc_req_o is done after req_o is accepted so that most of the
592 // cycle can be allocated to mask calculation logic. req_o,
593 // unlike calc_req_o, asserts the same cycle the transaction is
594 // received, so much of the timing may have already been lost to
595 // transaction routing.
596 logic calc_req_start;
597 1/1 assign calc_req_start = req_o & ack_i & descramble_i;
Tests: T1 T2 T3
598 1/1 assign calc_req_done = calc_req_o & calc_ack_i;
Tests: T1 T2 T3
599 always_ff @(posedge clk_i or negedge rst_ni) begin
600 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
601 1/1 calc_req_o <= '0;
Tests: T1 T2 T3
602 1/1 end else if (calc_req_start) begin
Tests: T1 T2 T3
603 1/1 calc_req_o <= 1'b1;
Tests: T52 T41 T42
604 1/1 end else if (calc_req_done) begin
Tests: T1 T2 T3
605 1/1 calc_req_o <= 1'b0;
Tests: T52 T41 T42
606 end
MISSING_ELSE
607 end
608
609 // operand to gf_mult
610 1/1 assign calc_addr_o = rd_attrs.addr;
Tests: T1 T2 T3
611
612 // generate the descramble request whenever both stages are available
613 // and there is a need to descramble
614 1/1 assign descramble_req_o = fifo_data_valid & mask_valid & hint_descram;
Tests: T1 T2 T3
615
616 // scrambled data to de-scramble
617 1/1 assign scrambled_data_o = fifo_data[DataWidth-1:0] ^ mask;
Tests: T1 T2 T3
618
619 // muxed responses
620 // When "forward" is true, there is nothing ahead in the pipeline, directly feed data
621 // and error forward.
622 // When "forward" is not true, take the output from the descramble stage, which is
623 // dependent on the scramble hint.
624 1/1 assign muxed_data = forward ? data_int :
Tests: T1 T2 T3
625 hint_descram ? {fifo_data[PlainDataWidth-1 -: PlainIntgWidth],
626 descrambled_data_i ^ mask} :
627 fifo_data;
628 1/1 assign muxed_err = forward ? data_err :
Tests: T1 T2 T3
629 ~hint_forward ? data_err_q : '0;
630
631 // muxed data valid
632 // if no de-scramble required, return data on read complete
633 // if data is all empty (erased), also return data on read complete
634 // if descramble is required, return data when descrambler finishes
635 // if descramble is not required, but there are transactions ahead, return from fifo when ready
636 1/1 assign data_valid = forward | ~hint_forward & fifo_data_ready;
Tests: T1 T2 T3
637
638
639 /////////////////////////////////
640 // Response
641 /////////////////////////////////
642
643 logic flash_rsp_match;
644 logic [NumBuf-1:0] buf_rsp_match;
645 logic [PlainDataWidth-1:0] buf_rsp_data;
646 logic [BankAddrW-1:0] buf_addr_xor;
647 logic buf_rsp_err;
648
649
650 // update buffers
651 // When forwarding, update entry stored in alloc_q
652 // When de-scrambling however, the contents of alloc_q may have already updated to the next read,
653 // so a different pointer is used.
654 1/1 assign update = forward ? alloc_q :
Tests: T1 T2 T3
655 ~hint_forward & fifo_data_ready ? alloc_q2 : '0;
656
657 // match in flash response when allocated buffer is the same as top of response fifo
658 // if read buffers are not enabled, do not check buffer selection
659 1/1 assign flash_rsp_match = rsp_fifo_vld & data_valid &
Tests: T1 T2 T3
660 (~buf_en_q | rsp_fifo_rdata.buf_sel == update);
661
662 // match in buf response when there is a valid buffer that is the same as top of response fifo
663 for (genvar i = 0; i < NumBuf; i++) begin: gen_buf_rsp_match
664 4/4 assign buf_rsp_match[i] = buf_en_q & rsp_fifo_vld &
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3 | T1 T2 T3
665 (rsp_fifo_rdata.buf_sel[i] & buf_valid[i]);
666 end
667
668 // select among the buffers
669 always_comb begin
670 1/1 buf_rsp_data = muxed_data;
Tests: T1 T2 T3
671 1/1 buf_rsp_err = '0;
Tests: T1 T2 T3
672 1/1 buf_addr_xor = '0;
Tests: T1 T2 T3
673 1/1 for (int i = 0; i < NumBuf; i++) begin
Tests: T1 T2 T3
674 1/1 if (buf_rsp_match[i]) begin
Tests: T1 T2 T3
675 1/1 buf_rsp_data = read_buf[i].data;
Tests: T3 T13 T14
676 1/1 buf_addr_xor = read_buf[i].addr;
Tests: T3 T13 T14
677 1/1 buf_rsp_err = buf_rsp_err | read_buf[i].err;
Tests: T3 T13 T14
678 end
MISSING_ELSE
679 end
680 end
681
682 logic [PlainDataWidth-1:0] data_out_muxed;
683 1/1 assign data_out_muxed = |buf_rsp_match ? buf_rsp_data : muxed_data;
Tests: T1 T2 T3
684
685 logic [BusFullWidth-1:0] data_out_intg;
686 if (WidthMultiple == 1) begin : gen_width_one_rd
687 // When multiple is 1, just pass the read through directly
688 logic unused_word_sel;
689
690 // use the tlul integrity module directly for bus integrity
691 // SEC_CM: MEM.BUS.INTEGRITY
692 tlul_data_integ_enc u_bus_intg (
693 .data_i(data_out_muxed[DataWidth-1:0]),
694 .data_intg_o(data_out_intg)
695 );
696
697 assign unused_word_sel = rsp_fifo_rdata.word_sel;
698
699 end else begin : gen_rd
700 // Re-arrange data into packed array to pick the correct one
701 logic [WidthMultiple-1:0][BusWidth-1:0] bus_words_packed;
702 logic [WidthMultiple-1:0][BusFullWidth-1:0] bus_words_packed_intg;
703 logic [WidthMultiple-1:0][BusFullWidth-1:0] bus_words_packed_intg_buf;
704 1/1 assign bus_words_packed = data_out_muxed[DataWidth-1:0];
Tests: T1 T2 T3
705
706 for (genvar i = 0; i < WidthMultiple; i++) begin: gen_bus_words_intg
707 // use the tlul integrity module directly for bus integrity
708 // SEC_CM: MEM.BUS.INTEGRITY
709 tlul_data_integ_enc u_bus_intg (
710 .data_i(bus_words_packed[i]),
711 .data_intg_o(bus_words_packed_intg[i])
712 );
713
714 // This primitive is used to place a size-only constraint on the
715 // buffers to act as a synthesis optimization barrier.
716 prim_buf #(
717 .Width(BusFullWidth)
718 ) u_prim_buf_intg (
719 .in_i(bus_words_packed_intg[i]),
720 .out_o(bus_words_packed_intg_buf[i])
721 );
722 end
723 // Mux based on selected word.
724 1/1 assign data_out_intg = bus_words_packed_intg_buf[rsp_fifo_rdata.word_sel];
Tests: T1 T2 T3
725
726 end
727
728 // On a data_err_o, send back '1 with data integrity tag on top of this data.
729 logic [BusFullWidth-1:0] inv_data_integ;
730 tlul_data_integ_enc u_bus_inv_data_intg (
731 .data_i({BusWidth{1'b1}}),
732 .data_intg_o(inv_data_integ)
733 );
734
735 logic [BusFullWidth-1:0] data_out_pre_xor;
736 1/1 assign data_out_pre_xor = data_err_o ? inv_data_integ : data_out_intg;
Tests: T1 T2 T3
737
738 1/1 assign data_ctrl_o = data_out_pre_xor;
Tests: T1 T2 T3
739
740 logic [BusBankAddrW-1:0] addr_xor_muxed;
741 logic [BusBankAddrW-1:0] fifo_addr_xor_muxed;
742 logic [BusBankAddrW-1:0] buf_addr_xor_muxed;
743
744 1/1 assign fifo_addr_xor_muxed = {fifo_addr_xor, rsp_fifo_rdata.word_sel};
Tests: T1 T2 T3
745 1/1 assign buf_addr_xor_muxed = {buf_addr_xor, rsp_fifo_rdata.word_sel};
Tests: T1 T2 T3
746
747 1/1 assign addr_xor_muxed = |buf_rsp_match ? buf_addr_xor_muxed : fifo_addr_xor_muxed;
Tests: T1 T2 T3
748
749 logic [BusWidth-1:0] data_out_xor;
750 logic [BusWidth-1:0] data_out_xor_buf;
751 1/1 assign data_out_xor =
Tests: T1 T2 T3
752 data_out_pre_xor[BusWidth-1:0] ^ {{(BusWidth-BusBankAddrW){1'b0}}, addr_xor_muxed};
753
754 // Buffer to ensure that synthesis tool does not optimize the XOR.
755 prim_buf #(
756 .Width(BusWidth)
757 ) u_prim_buf_data_xor_out (
758 .in_i(data_out_xor),
759 .out_o(data_out_xor_buf)
760 );
761
762 1/1 assign data_host_o = {data_out_pre_xor[BusFullWidth-1:BusWidth], data_out_xor_buf};
Tests: T1 T2 T3
763
764 // add plaintext decoding here
765 // plaintext error
766 logic intg_err_pre, intg_err;
767 logic [DataWidth-1:0] unused_data;
768 logic [3:0] unused_intg;
769 logic [3:0] truncated_intg;
770
771 prim_secded_hamming_72_64_enc u_plain_enc (
772 .data_i(data_out_muxed[DataWidth-1:0]),
773 .data_o({unused_intg, truncated_intg, unused_data})
774 );
775 1/1 assign intg_err_pre = rsp_fifo_rdata.intg_ecc_en ?
Tests: T1 T2 T3
776 truncated_intg != data_out_muxed[DataWidth +: PlainIntgWidth] :
777 '0;
778
779 prim_sec_anchor_buf #(
780 .Width(1)
781 ) u_intg_buf (
782 .in_i(intg_err_pre),
783 .out_o(intg_err)
784 );
785
786 // whenever the response is coming from the buffer, the error is never set
787 1/1 assign data_valid_o = flash_rsp_match | (|buf_rsp_match);
Tests: T1 T2 T3
788
789 // integrity and reliability ECC errors always cause in band errors
790 1/1 assign data_err_o = data_valid_o & (muxed_err | intg_err | (|buf_rsp_match & buf_rsp_err)) |
Tests: T1 T2 T3
791 arb_err_i;
792
793 // integrity ECC error can also cause out of band alert
794 1/1 assign intg_ecc_err_o = data_valid_o & intg_err;
Tests: T1 T2 T3
795
796 // the entire read pipeline is idle when there are no responses to return and no
797 1/1 assign idle_o = ~rsp_fifo_vld;
Tests: T1 T2 T3
798
799 // if any fifo shows an integrity error
800 1/1 assign fifo_err_o = |{rsp_order_fifo_err, rd_stage_fifo_err};
Tests: T1 T2 T3
Cond Coverage for Instance : tb.dut.u_eflash.gen_flash_cores[1].u_core.u_rd
| Total | Covered | Percent |
Conditions | 458 | 415 | 90.61 |
Logical | 458 | 415 | 90.61 |
Non-Logical | 0 | 0 | |
Event | 0 | 0 | |
This module contains a very large number of conditions, so the report has been split into multiple pages, by source line number. Click on the line number range in the table below to see the condition coverage for that section of the module.
Branch Coverage for Instance : tb.dut.u_eflash.gen_flash_cores[1].u_core.u_rd
| Line No. | Total | Covered | Percent |
Branches |
|
43 |
43 |
100.00 |
TERNARY |
186 |
2 |
2 |
100.00 |
TERNARY |
232 |
2 |
2 |
100.00 |
TERNARY |
302 |
2 |
2 |
100.00 |
TERNARY |
451 |
2 |
2 |
100.00 |
TERNARY |
513 |
3 |
3 |
100.00 |
TERNARY |
624 |
3 |
3 |
100.00 |
TERNARY |
628 |
3 |
3 |
100.00 |
TERNARY |
654 |
3 |
3 |
100.00 |
TERNARY |
683 |
2 |
2 |
100.00 |
TERNARY |
736 |
2 |
2 |
100.00 |
TERNARY |
747 |
2 |
2 |
100.00 |
TERNARY |
775 |
2 |
2 |
100.00 |
TERNARY |
167 |
2 |
2 |
100.00 |
IF |
257 |
3 |
3 |
100.00 |
IF |
360 |
4 |
4 |
100.00 |
IF |
600 |
4 |
4 |
100.00 |
IF |
674 |
2 |
2 |
100.00 |
186 assign buf_alloc = |buf_invalid_alloc ? buf_invalid_alloc : buf_valid_alloc;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T3,T13,T14 |
232 assign alloc = no_match ? {NumBuf{req_i & buf_en_q}} & buf_alloc : '0;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T3,T13,T14 |
302 assign rsp_fifo_wdata.buf_sel = |alloc ? buf_alloc : buf_match;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T3,T13,T14 |
0 |
Covered |
T1,T2,T3 |
451 assign data_int = data_err | ecc_single_err_o ?
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T41,T42,T63 |
0 |
Covered |
T1,T2,T3 |
513 assign fifo_data_ready = hint_descram ? descramble_req_o & descramble_ack_i :
-1-
==>
514 hint_dropmsk ? mask_valid : fifo_data_valid;
-2-
==>
==>
Branches:
-1- | -2- | Status | Tests |
1 |
- |
Covered |
T41,T42,T25 |
0 |
1 |
Covered |
T52,T24,T78 |
0 |
0 |
Covered |
T1,T2,T3 |
624 assign muxed_data = forward ? data_int :
-1-
==>
625 hint_descram ? {fifo_data[PlainDataWidth-1 -: PlainIntgWidth],
-2-
==>
==>
Branches:
-1- | -2- | Status | Tests |
1 |
- |
Covered |
T3,T13,T14 |
0 |
1 |
Covered |
T41,T42,T25 |
0 |
0 |
Covered |
T1,T2,T3 |
628 assign muxed_err = forward ? data_err :
-1-
==>
629 ~hint_forward ? data_err_q : '0;
-2-
==>
==>
Branches:
-1- | -2- | Status | Tests |
1 |
- |
Covered |
T3,T13,T14 |
0 |
1 |
Covered |
T1,T2,T3 |
0 |
0 |
Covered |
T3,T13,T14 |
654 assign update = forward ? alloc_q :
-1-
==>
655 ~hint_forward & fifo_data_ready ? alloc_q2 : '0;
-2-
==>
==>
Branches:
-1- | -2- | Status | Tests |
1 |
- |
Covered |
T3,T13,T14 |
0 |
1 |
Covered |
T41,T42,T25 |
0 |
0 |
Covered |
T1,T2,T3 |
683 assign data_out_muxed = |buf_rsp_match ? buf_rsp_data : muxed_data;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T3,T13,T14 |
0 |
Covered |
T1,T2,T3 |
736 assign data_out_pre_xor = data_err_o ? inv_data_integ : data_out_intg;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T63,T64,T56 |
0 |
Covered |
T1,T2,T3 |
747 assign addr_xor_muxed = |buf_rsp_match ? buf_addr_xor_muxed : fifo_addr_xor_muxed;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T3,T13,T14 |
0 |
Covered |
T1,T2,T3 |
775 assign intg_err_pre = rsp_fifo_rdata.intg_ecc_en ?
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T52,T41,T73 |
0 |
Covered |
T1,T2,T3 |
167 ) u_valid_random (
168 .clk_i,
169 .rst_ni,
170 .req_chk_i(1'b0), // Valid is allowed to drop without ready.
171 // If there is an invalid buffer, always allocate from that one first
172 // If all buffers have a dependency to an in-flight transaction, do not
173 // allocate and wait for the dependencies to end.
174 // If none of the above are true, THEN pick a buffer from the current valid
175 // buffers that DO NOT have an ongoing dependency.
176 .req_i(|buf_invalid_alloc | all_buf_dependency ? '0 : buf_valid & ~buf_dependency),
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T3,T13,T14 |
257 if (!rst_ni) begin
-1-
258 buf_en_q <= 1'b0;
==>
259 end else if (idle_o) begin
-2-
260 buf_en_q <= buf_en_i;
==>
261 end
MISSING_ELSE
==>
Branches:
-1- | -2- | Status | Tests |
1 |
- |
Covered |
T1,T2,T3 |
0 |
1 |
Covered |
T1,T2,T3 |
0 |
0 |
Covered |
T3,T13,T14 |
360 if (!rst_ni) begin
-1-
361 alloc_q <= '0;
==>
362 rd_attrs <= '0;
363 rd_busy <= '0;
364 end else if (rd_start) begin
-2-
365 rd_busy <= 1'b1;
==>
366 alloc_q <= alloc;
367 rd_attrs.addr <= addr_i[BusBankAddrW-1:LsbAddrBit];
368 rd_attrs.descramble <= descramble_i;
369 rd_attrs.ecc <= ecc_i;
370
371 end else if (rd_done) begin
-3-
372 rd_busy <= 1'b0;
==>
373 end
MISSING_ELSE
==>
Branches:
-1- | -2- | -3- | Status | Tests |
1 |
- |
- |
Covered |
T1,T2,T3 |
0 |
1 |
- |
Covered |
T3,T13,T14 |
0 |
0 |
1 |
Covered |
T3,T13,T14 |
0 |
0 |
0 |
Covered |
T1,T2,T3 |
600 if (!rst_ni) begin
-1-
601 calc_req_o <= '0;
==>
602 end else if (calc_req_start) begin
-2-
603 calc_req_o <= 1'b1;
==>
604 end else if (calc_req_done) begin
-3-
605 calc_req_o <= 1'b0;
==>
606 end
MISSING_ELSE
==>
Branches:
-1- | -2- | -3- | Status | Tests |
1 |
- |
- |
Covered |
T1,T2,T3 |
0 |
1 |
- |
Covered |
T52,T41,T42 |
0 |
0 |
1 |
Covered |
T52,T41,T42 |
0 |
0 |
0 |
Covered |
T1,T2,T3 |
674 if (buf_rsp_match[i]) begin
-1-
675 buf_rsp_data = read_buf[i].data;
==>
676 buf_addr_xor = read_buf[i].addr;
677 buf_rsp_err = buf_rsp_err | read_buf[i].err;
678 end
MISSING_ELSE
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T3,T13,T14 |
0 |
Covered |
T1,T2,T3 |
Assert Coverage for Instance : tb.dut.u_eflash.gen_flash_cores[1].u_core.u_rd
Assertion Details
BufferMatchEcc_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
887366 |
0 |
0 |
T3 |
3382 |
5 |
0 |
0 |
T7 |
4246 |
0 |
0 |
0 |
T13 |
23710 |
193 |
0 |
0 |
T14 |
6246 |
64 |
0 |
0 |
T15 |
3415 |
10 |
0 |
0 |
T18 |
2946 |
0 |
0 |
0 |
T19 |
485911 |
0 |
0 |
0 |
T20 |
70358 |
0 |
0 |
0 |
T32 |
0 |
549 |
0 |
0 |
T41 |
0 |
633 |
0 |
0 |
T48 |
0 |
742 |
0 |
0 |
T52 |
0 |
977 |
0 |
0 |
T65 |
1935 |
92 |
0 |
0 |
T66 |
3620 |
0 |
0 |
0 |
T73 |
0 |
80 |
0 |
0 |
ExclusiveOps_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
384030817 |
0 |
0 |
T1 |
1636 |
1562 |
0 |
0 |
T2 |
1951 |
1876 |
0 |
0 |
T3 |
3382 |
3310 |
0 |
0 |
T7 |
4246 |
3594 |
0 |
0 |
T13 |
23710 |
23640 |
0 |
0 |
T14 |
6246 |
6148 |
0 |
0 |
T15 |
3415 |
3357 |
0 |
0 |
T18 |
2946 |
2862 |
0 |
0 |
T19 |
485911 |
467871 |
0 |
0 |
T20 |
70358 |
70281 |
0 |
0 |
ExclusiveProgHazard_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
384030817 |
0 |
0 |
T1 |
1636 |
1562 |
0 |
0 |
T2 |
1951 |
1876 |
0 |
0 |
T3 |
3382 |
3310 |
0 |
0 |
T7 |
4246 |
3594 |
0 |
0 |
T13 |
23710 |
23640 |
0 |
0 |
T14 |
6246 |
6148 |
0 |
0 |
T15 |
3415 |
3357 |
0 |
0 |
T18 |
2946 |
2862 |
0 |
0 |
T19 |
485911 |
467871 |
0 |
0 |
T20 |
70358 |
70281 |
0 |
0 |
ExclusiveState_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
384030817 |
0 |
0 |
T1 |
1636 |
1562 |
0 |
0 |
T2 |
1951 |
1876 |
0 |
0 |
T3 |
3382 |
3310 |
0 |
0 |
T7 |
4246 |
3594 |
0 |
0 |
T13 |
23710 |
23640 |
0 |
0 |
T14 |
6246 |
6148 |
0 |
0 |
T15 |
3415 |
3357 |
0 |
0 |
T18 |
2946 |
2862 |
0 |
0 |
T19 |
485911 |
467871 |
0 |
0 |
T20 |
70358 |
70281 |
0 |
0 |
ForwardCheck_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
1910816 |
0 |
0 |
T3 |
3382 |
7 |
0 |
0 |
T7 |
4246 |
0 |
0 |
0 |
T13 |
23710 |
230 |
0 |
0 |
T14 |
6246 |
74 |
0 |
0 |
T15 |
3415 |
13 |
0 |
0 |
T18 |
2946 |
0 |
0 |
0 |
T19 |
485911 |
0 |
0 |
0 |
T20 |
70358 |
0 |
0 |
0 |
T32 |
0 |
556 |
0 |
0 |
T48 |
0 |
742 |
0 |
0 |
T49 |
0 |
22 |
0 |
0 |
T52 |
0 |
9554 |
0 |
0 |
T65 |
1935 |
54 |
0 |
0 |
T66 |
3620 |
0 |
0 |
0 |
T73 |
0 |
81 |
0 |
0 |
IdleCheck_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
47451034 |
0 |
0 |
T3 |
3382 |
19 |
0 |
0 |
T7 |
4246 |
0 |
0 |
0 |
T13 |
23710 |
653 |
0 |
0 |
T14 |
6246 |
212 |
0 |
0 |
T15 |
3415 |
36 |
0 |
0 |
T18 |
2946 |
0 |
0 |
0 |
T19 |
485911 |
0 |
0 |
0 |
T20 |
70358 |
0 |
0 |
0 |
T32 |
0 |
1661 |
0 |
0 |
T41 |
0 |
33586 |
0 |
0 |
T48 |
0 |
2226 |
0 |
0 |
T49 |
0 |
44 |
0 |
0 |
T52 |
0 |
20085 |
0 |
0 |
T65 |
1935 |
200 |
0 |
0 |
T66 |
3620 |
0 |
0 |
0 |
MaxBufs_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
1042 |
1042 |
0 |
0 |
T1 |
1 |
1 |
0 |
0 |
T2 |
1 |
1 |
0 |
0 |
T3 |
1 |
1 |
0 |
0 |
T7 |
1 |
1 |
0 |
0 |
T13 |
1 |
1 |
0 |
0 |
T14 |
1 |
1 |
0 |
0 |
T15 |
1 |
1 |
0 |
0 |
T18 |
1 |
1 |
0 |
0 |
T19 |
1 |
1 |
0 |
0 |
T20 |
1 |
1 |
0 |
0 |
OneHotAlloc_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
384030817 |
0 |
0 |
T1 |
1636 |
1562 |
0 |
0 |
T2 |
1951 |
1876 |
0 |
0 |
T3 |
3382 |
3310 |
0 |
0 |
T7 |
4246 |
3594 |
0 |
0 |
T13 |
23710 |
23640 |
0 |
0 |
T14 |
6246 |
6148 |
0 |
0 |
T15 |
3415 |
3357 |
0 |
0 |
T18 |
2946 |
2862 |
0 |
0 |
T19 |
485911 |
467871 |
0 |
0 |
T20 |
70358 |
70281 |
0 |
0 |
OneHotMatch_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
384030817 |
0 |
0 |
T1 |
1636 |
1562 |
0 |
0 |
T2 |
1951 |
1876 |
0 |
0 |
T3 |
3382 |
3310 |
0 |
0 |
T7 |
4246 |
3594 |
0 |
0 |
T13 |
23710 |
23640 |
0 |
0 |
T14 |
6246 |
6148 |
0 |
0 |
T15 |
3415 |
3357 |
0 |
0 |
T18 |
2946 |
2862 |
0 |
0 |
T19 |
485911 |
467871 |
0 |
0 |
T20 |
70358 |
70281 |
0 |
0 |
OneHotRspMatch_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
384030817 |
0 |
0 |
T1 |
1636 |
1562 |
0 |
0 |
T2 |
1951 |
1876 |
0 |
0 |
T3 |
3382 |
3310 |
0 |
0 |
T7 |
4246 |
3594 |
0 |
0 |
T13 |
23710 |
23640 |
0 |
0 |
T14 |
6246 |
6148 |
0 |
0 |
T15 |
3415 |
3357 |
0 |
0 |
T18 |
2946 |
2862 |
0 |
0 |
T19 |
485911 |
467871 |
0 |
0 |
T20 |
70358 |
70281 |
0 |
0 |
OneHotUpdate_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
384864419 |
384030817 |
0 |
0 |
T1 |
1636 |
1562 |
0 |
0 |
T2 |
1951 |
1876 |
0 |
0 |
T3 |
3382 |
3310 |
0 |
0 |
T7 |
4246 |
3594 |
0 |
0 |
T13 |
23710 |
23640 |
0 |
0 |
T14 |
6246 |
6148 |
0 |
0 |
T15 |
3415 |
3357 |
0 |
0 |
T18 |
2946 |
2862 |
0 |
0 |
T19 |
485911 |
467871 |
0 |
0 |
T20 |
70358 |
70281 |
0 |
0 |