Line Coverage for Module :
otp_ctrl_part_buf ( parameter Info=-1,CntWidth=4,DigestOffset=1720,StateWidth=12 )
Line Coverage for Module self-instances :
| Line No. | Total | Covered | Percent |
TOTAL | | 160 | 124 | 77.50 |
CONT_ASSIGN | 182 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
ALWAYS | 206 | 140 | 104 | 74.29 |
CONT_ASSIGN | 636 | 1 | 1 | 100.00 |
CONT_ASSIGN | 641 | 1 | 1 | 100.00 |
CONT_ASSIGN | 642 | 1 | 1 | 100.00 |
CONT_ASSIGN | 646 | 1 | 1 | 100.00 |
CONT_ASSIGN | 652 | 1 | 1 | 100.00 |
CONT_ASSIGN | 675 | 1 | 1 | 100.00 |
CONT_ASSIGN | 678 | 1 | 1 | 100.00 |
CONT_ASSIGN | 680 | 1 | 1 | 100.00 |
CONT_ASSIGN | 709 | 1 | 1 | 100.00 |
CONT_ASSIGN | 743 | 1 | 1 | 100.00 |
ALWAYS | 750 | 3 | 3 | 100.00 |
ALWAYS | 753 | 5 | 5 | 100.00 |
181 // Output partition error state.
182 1/1 assign error_o = error_q;
Tests: T1 T2 T3
183
184 // This partition cannot do any write accesses, hence we tie this
185 // constantly off.
186 assign otp_wdata_o = '0;
187 // Depending on the partition configuration, the wrapper is instructed to ignore integrity
188 // calculations and checks. To be on the safe side, the partition filters error responses at this
189 // point and does not report any integrity errors if integrity is disabled.
190 otp_err_e otp_err;
191 if (Info.integrity) begin : gen_integrity
192 assign otp_cmd_o = prim_otp_pkg::Read;
193 1/1 assign otp_err = otp_err_e'(otp_err_i);
Tests: T1 T2 T3
194 end else begin : gen_no_integrity
195 assign otp_cmd_o = prim_otp_pkg::ReadRaw;
196 always_comb begin
197 if (otp_err_e'(otp_err_i) inside {MacroEccCorrError, MacroEccUncorrError}) begin
198 otp_err = NoError;
199 end else begin
200 otp_err = otp_err_e'(otp_err_i);
201 end
202 end
203 end
204
205 always_comb begin : p_fsm
206 1/1 state_d = state_q;
Tests: T1 T2 T3
207
208 // Redundantly encoded lock signal for buffer regs.
209 1/1 dout_locked_d = dout_locked_q;
Tests: T1 T2 T3
210
211 // OTP signals
212 1/1 otp_req_o = 1'b0;
Tests: T1 T2 T3
213
214 // Scrambling mutex
215 1/1 scrmbl_mtx_req_o = 1'b0;
Tests: T1 T2 T3
216
217 // Scrambling datapath
218 1/1 scrmbl_cmd_o = LoadShadow;
Tests: T1 T2 T3
219 1/1 scrmbl_sel_o = CnstyDigest;
Tests: T1 T2 T3
220 1/1 scrmbl_mode_o = StandardMode;
Tests: T1 T2 T3
221 1/1 scrmbl_valid_o = 1'b0;
Tests: T1 T2 T3
222
223 // Counter
224 1/1 cnt_en = 1'b0;
Tests: T1 T2 T3
225 1/1 cnt_clr = 1'b0;
Tests: T1 T2 T3
226 1/1 base_sel = PartOffset;
Tests: T1 T2 T3
227
228 // Buffer register
229 1/1 buffer_reg_en = 1'b0;
Tests: T1 T2 T3
230 1/1 data_sel = OtpData;
Tests: T1 T2 T3
231
232 // Error Register
233 1/1 error_d = error_q;
Tests: T1 T2 T3
234 1/1 fsm_err_o = 1'b0;
Tests: T1 T2 T3
235
236 // Integrity/Consistency check responses
237 1/1 cnsty_chk_ack_o = 1'b0;
Tests: T1 T2 T3
238 1/1 integ_chk_ack_o = 1'b0;
Tests: T1 T2 T3
239
240 1/1 unique case (state_q)
Tests: T1 T2 T3
241 ///////////////////////////////////////////////////////////////////
242 // State right after reset. Wait here until we get a an
243 // initialization request.
244 ResetSt: begin
245 1/1 if (init_req_i) begin
Tests: T1 T2 T3
246 1/1 state_d = InitSt;
Tests: T1 T2 T3
247 end
MISSING_ELSE
248 end
249 ///////////////////////////////////////////////////////////////////
250 // Initialization reads out the digest only in unbuffered
251 // partitions. Wait here until the OTP request has been granted.
252 // And then wait until the OTP word comes back.
253 InitSt: begin
254 1/1 otp_req_o = 1'b1;
Tests: T1 T2 T3
255 1/1 if (otp_gnt_i) begin
Tests: T1 T2 T3
256 1/1 state_d = InitWaitSt;
Tests: T1 T2 T3
257 end
MISSING_ELSE
258 end
259 ///////////////////////////////////////////////////////////////////
260 // Wait for OTP response and write to buffer register, then go to
261 // descrambling state. In case an OTP transaction fails, latch the
262 // OTP error code and jump to a
263 // terminal error state.
264 InitWaitSt: begin
265 1/1 if (otp_rvalid_i) begin
Tests: T1 T2 T3
266 1/1 buffer_reg_en = 1'b1;
Tests: T1 T2 T3
267 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin
Tests: T1 T2 T3
268 // Once we've read and descrambled the whole partition, we can go to integrity
269 // verification. Note that the last block is the digest value, which does not
270 // have to be descrambled.
271 1/1 if (cnt == LastScrmblBlock) begin
Tests: T1 T2 T3
272 1/1 state_d = IntegDigClrSt;
Tests: T1 T2 T3
273 // Only need to descramble if this is a scrambled partition.
274 // Otherwise, we can just go back to InitSt and read the next block.
275 1/1 end else if (Info.secret) begin
Tests: T1 T2 T3
276 unreachable state_d = InitDescrSt;
277 end else begin
278 1/1 state_d = InitSt;
Tests: T1 T2 T3
279 1/1 cnt_en = 1'b1;
Tests: T1 T2 T3
280 end
281 // At this point the only error that we could have gotten are correctable ECC errors.
282 1/1 if (otp_err != NoError) begin
Tests: T1 T2 T3
283 1/1 error_d = MacroEccCorrError;
Tests: T28 T29 T30
284 end
MISSING_ELSE
285 end else begin
286 1/1 state_d = ErrorSt;
Tests: T31 T32 T33
287 1/1 error_d = otp_err;
Tests: T31 T32 T33
288 end
289 end
MISSING_ELSE
290 end
291 ///////////////////////////////////////////////////////////////////
292 // Descrambling state. This first acquires the scrambling
293 // datapath mutex. Note that once the mutex is acquired, we have
294 // exclusive access to the scrambling datapath until we release
295 // the mutex by deasserting scrmbl_mtx_req_o.
296 // SEC_CM: SECRET.MEM.SCRAMBLE
297 InitDescrSt: begin
298 0/1 ==> scrmbl_mtx_req_o = 1'b1;
299 0/1 ==> scrmbl_valid_o = 1'b1;
300 0/1 ==> scrmbl_cmd_o = Decrypt;
301 0/1 ==> scrmbl_sel_o = Info.key_sel;
302 0/1 ==> if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
303 0/1 ==> state_d = InitDescrWaitSt;
304 end
==> MISSING_ELSE
305 end
306 ///////////////////////////////////////////////////////////////////
307 // Wait for the descrambled data to return. Note that we release
308 // the mutex lock upon leaving this state.
309 // SEC_CM: SECRET.MEM.SCRAMBLE
310 InitDescrWaitSt: begin
311 0/1 ==> scrmbl_mtx_req_o = 1'b1;
312 0/1 ==> scrmbl_sel_o = Info.key_sel;
313 0/1 ==> data_sel = ScrmblData;
314 0/1 ==> if (scrmbl_valid_i) begin
315 0/1 ==> state_d = InitSt;
316 0/1 ==> buffer_reg_en = 1'b1;
317 0/1 ==> cnt_en = 1'b1;
318 end
==> MISSING_ELSE
319 end
320 ///////////////////////////////////////////////////////////////////
321 // Idle state. We basically wait for integrity and consistency check
322 // triggers in this state.
323 IdleSt: begin
324 1/1 if (integ_chk_req_i) begin
Tests: T1 T2 T3
325 1/1 if (Info.hw_digest) begin
Tests: T3 T5 T24
326 1/1 state_d = IntegDigClrSt;
Tests: T3 T5 T24
327 // In case there is nothing to check we can just
328 // acknowledge the request right away, without going to the
329 // integrity check.
330 end else begin
331 unreachable integ_chk_ack_o = 1'b1;
332 end
333 1/1 end else if (cnsty_chk_req_i) begin
Tests: T1 T2 T3
334 1/1 state_d = CnstyReadSt;
Tests: T4 T6 T5
335 1/1 cnt_clr = 1'b1;
Tests: T4 T6 T5
336 end
MISSING_ELSE
337 end
338 ///////////////////////////////////////////////////////////////////
339 // Read the digest. Wait here until the OTP request has been granted.
340 // And then wait until the OTP word comes back.
341 // SEC_CM: PART.DATA_REG.BKGN_CHK
342 CnstyReadSt: begin
343 1/1 otp_req_o = 1'b1;
Tests: T4 T6 T5
344 // In case this partition has a hardware digest, we only have to read
345 // and compare the digest value. In that case we select the digest offset here.
346 // Otherwise we have to read and compare the whole partition, in which case we
347 // select the partition offset, which is the default assignment of base_sel.
348 1/1 if (Info.hw_digest) begin
Tests: T4 T6 T5
349 1/1 base_sel = DigOffset;
Tests: T4 T6 T5
350 end
==> MISSING_ELSE
351 1/1 if (otp_gnt_i) begin
Tests: T4 T6 T5
352 1/1 state_d = CnstyReadWaitSt;
Tests: T4 T6 T5
353 end
MISSING_ELSE
354 end
355 ///////////////////////////////////////////////////////////////////
356 // Wait for OTP response and compare the digest. In case there is
357 // a mismatch, lock down the partition and go into the terminal error
358 // state. In case an OTP transaction fails, latch the OTP error code
359 // and jump to a terminal error state.
360 // SEC_CM: PART.DATA_REG.BKGN_CHK
361 CnstyReadWaitSt: begin
362 1/1 if (otp_rvalid_i) begin
Tests: T4 T6 T5
363 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin
Tests: T6 T5 T24
364 // Check whether we need to compare the digest or the full partition
365 // contents here.
366 1/1 if (Info.hw_digest) begin
Tests: T6 T5 T24
367 // Note that we ignore this check if the digest is still blank.
368 1/1 if (digest_o == data_mux || digest_o == '0) begin
Tests: T6 T5 T24
369 1/1 state_d = IdleSt;
Tests: T6 T5 T24
370 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T6 T5 T24
371 // Error out and lock the partition if this check fails.
372 end else begin
373 0/1 ==> state_d = ErrorSt;
374 0/1 ==> error_d = CheckFailError;
375 // The check has finished and found an error.
376 0/1 ==> cnsty_chk_ack_o = 1'b1;
377 end
378 end else begin
379 // Check whether the read data corresponds with the data buffered in regs.
380 // Note that this particular check can be bypassed in case a transition is ongoing.
381 unreachable if (scrmbl_data_o == data_mux ||
382 lc_ctrl_pkg::lc_tx_test_true_strict(check_byp_en_i)) begin
383 // Can go back to idle and acknowledge the
384 // request if this is the last block.
385 unreachable if (cnt == LastScrmblBlock) begin
386 unreachable state_d = IdleSt;
387 unreachable cnsty_chk_ack_o = 1'b1;
388 // Need to go back and read out more blocks.
389 end else begin
390 unreachable state_d = CnstyReadSt;
391 unreachable cnt_en = 1'b1;
392 end
393 end else begin
394 unreachable state_d = ErrorSt;
395 unreachable error_d = CheckFailError;
396 // The check has finished and found an error.
397 unreachable cnsty_chk_ack_o = 1'b1;
398 end
399 end
400 // At this point the only error that we could have gotten are correctable ECC errors.
401 1/1 if (otp_err != NoError) begin
Tests: T6 T5 T24
402 1/1 error_d = MacroEccCorrError;
Tests: T34 T35
403 end
MISSING_ELSE
404 end else begin
405 1/1 state_d = ErrorSt;
Tests: T36 T37 T38
406 1/1 error_d = otp_err;
Tests: T36 T37 T38
407 // The check has finished and found an error.
408 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T36 T37 T38
409 end
410 end
MISSING_ELSE
411 end
412 ///////////////////////////////////////////////////////////////////
413 // First, acquire the mutex for the digest and clear the digest state.
414 // SEC_CM: PART.DATA_REG.BKGN_CHK
415 IntegDigClrSt: begin
416 // Check whether this partition requires checking at all.
417 1/1 if (Info.hw_digest) begin
Tests: T1 T2 T3
418 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
419 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
420 1/1 cnt_clr = 1'b1;
Tests: T1 T2 T3
421 // Need to reset the digest state and set it to chained
422 // mode if this partition is scrambled.
423 1/1 scrmbl_cmd_o = DigestInit;
Tests: T1 T2 T3
424 1/1 if (Info.secret) begin
Tests: T1 T2 T3
425 unreachable scrmbl_mode_o = ChainedMode;
426 unreachable if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
427 unreachable state_d = IntegScrSt;
428 end
==> MISSING_ELSE
429 // If this partition is not scrambled, we can just directly
430 // jump to the digest state.
431 end else begin
432 1/1 scrmbl_mode_o = StandardMode;
Tests: T1 T2 T3
433 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
Tests: T1 T2 T3
434 1/1 state_d = IntegDigSt;
Tests: T1 T2 T3
435 end
MISSING_ELSE
436 end
437 // Otherwise, if this partition is not digest protected,
438 // we can just go to idle, since there is nothing to check.
439 // Note that we do not come back to this state in case there is no
440 // digest, and hence it is safe to unlock the buffer regs at this point.
441 // This is the only way the buffer regs can get unlocked.
442 end else begin
443 unreachable state_d = IdleSt;
444 unreachable if (mubi8_test_true_strict(dout_locked_q)) begin
445 unreachable dout_locked_d = MuBi8False;
446 end
==> MISSING_ELSE
447 end
448 end
449 ///////////////////////////////////////////////////////////////////
450 // Scramble buffered data (which is held in plaintext form).
451 // This moves the previous scrambling result into the shadow reg
452 // for later use.
453 // SEC_CM: PART.DATA_REG.BKGN_CHK
454 IntegScrSt: begin
455 0/1 ==> scrmbl_mtx_req_o = 1'b1;
456 0/1 ==> scrmbl_valid_o = 1'b1;
457 0/1 ==> scrmbl_cmd_o = Encrypt;
458 0/1 ==> scrmbl_sel_o = Info.key_sel;
459 0/1 ==> if (scrmbl_ready_i) begin
460 0/1 ==> state_d = IntegScrWaitSt;
461 end
==> MISSING_ELSE
462 end
463 ///////////////////////////////////////////////////////////////////
464 // Wait for the scrambled data to return.
465 // SEC_CM: PART.DATA_REG.BKGN_CHK
466 IntegScrWaitSt: begin
467 0/1 ==> scrmbl_mtx_req_o = 1'b1;
468 0/1 ==> scrmbl_sel_o = Info.key_sel;
469 0/1 ==> if (scrmbl_valid_i) begin
470 0/1 ==> state_d = IntegDigSt;
471 end
==> MISSING_ELSE
472 end
473 ///////////////////////////////////////////////////////////////////
474 // Push the word read into the scrambling datapath. The last
475 // block is repeated in case the number blocks in this partition
476 // is odd.
477 // SEC_CM: PART.MEM.DIGEST
478 // SEC_CM: PART.DATA_REG.BKGN_CHK
479 IntegDigSt: begin
480 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
481 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
482 1/1 if (scrmbl_ready_i) begin
Tests: T1 T2 T3
483 1/1 cnt_en = 1'b1;
Tests: T1 T2 T3
484 // No need to digest the digest value itself
485 1/1 if (cnt == PenultimateScrmblBlock) begin
Tests: T1 T2 T3
486 // Note that the digest operates on 128bit blocks since the data is fed in via the
487 // PRESENT key input. Therefore, we only trigger a digest update on every second
488 // 64bit block that is pushed into the scrambling datapath.
489 1/1 if (cnt[0]) begin
Tests: T1 T2 T3
490 1/1 scrmbl_cmd_o = Digest;
Tests: T1 T2 T3
491 1/1 state_d = IntegDigFinSt;
Tests: T1 T2 T3
492 end else begin
493 0/1 ==> state_d = IntegDigPadSt;
494 0/1 ==> cnt_en = 1'b0;
495 end
496 end else begin
497 // Trigger digest round in case this is the second block in a row.
498 1/1 if (cnt[0]) begin
Tests: T1 T2 T3
499 1/1 scrmbl_cmd_o = Digest;
Tests: T1 T2 T3
500 end
MISSING_ELSE
501 // Go back and scramble the next data block if this is
502 // a scrambled partition. Otherwise just stay here.
503 1/1 if (Info.secret) begin
Tests: T1 T2 T3
504 unreachable state_d = IntegScrSt;
505 end
MISSING_ELSE
506 end
507 end
MISSING_ELSE
508 end
509 ///////////////////////////////////////////////////////////////////
510 // Padding state. When we get here, we've copied the last encryption
511 // result into the shadow register such that we've effectively
512 // repeated the last block twice in order to pad the data to 128bit.
513 // SEC_CM: PART.MEM.DIGEST
514 // SEC_CM: PART.DATA_REG.BKGN_CHK
515 IntegDigPadSt: begin
516 0/1 ==> scrmbl_mtx_req_o = 1'b1;
517 0/1 ==> scrmbl_valid_o = 1'b1;
518 0/1 ==> scrmbl_cmd_o = Digest;
519 0/1 ==> if (scrmbl_ready_i) begin
520 0/1 ==> state_d = IntegDigFinSt;
521 end
==> MISSING_ELSE
522 end
523 ///////////////////////////////////////////////////////////////////
524 // Trigger digest finalization and go wait for the result.
525 // SEC_CM: PART.MEM.DIGEST
526 // SEC_CM: PART.DATA_REG.BKGN_CHK
527 IntegDigFinSt: begin
528 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
529 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
530 1/1 scrmbl_cmd_o = DigestFinalize;
Tests: T1 T2 T3
531 1/1 if (scrmbl_ready_i) begin
Tests: T1 T2 T3
532 1/1 state_d = IntegDigWaitSt;
Tests: T1 T2 T3
533 end
MISSING_ELSE
534 end
535 ///////////////////////////////////////////////////////////////////
536 // Wait for the digest to return, and double check whether the digest
537 // matches. If yes, unlock the partition. Otherwise, go into the terminal
538 // error state, where the partition will be locked down.
539 // SEC_CM: PART.MEM.DIGEST
540 // SEC_CM: PART.DATA_REG.BKGN_CHK
541 IntegDigWaitSt: begin
542 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
543 1/1 data_sel = ScrmblData;
Tests: T1 T2 T3
544 1/1 if (scrmbl_valid_i) begin
Tests: T1 T2 T3
545 // This is the only way the buffer regs can get unlocked.
546 // Note that we ignore this check if the digest is still blank.
547 1/1 if (digest_o == data_mux || digest_o == '0) begin
Tests: T1 T2 T3
548 1/1 state_d = IdleSt;
Tests: T1 T2 T3
549 // If the partition is still locked, this is the first integrity check after
550 // initialization. This is the only way the buffer regs can get unlocked.
551 1/1 if (mubi8_test_true_strict(dout_locked_q)) begin
Tests: T1 T2 T3
552 1/1 dout_locked_d = MuBi8False;
Tests: T1 T2 T3
553 // Otherwise, this integrity check has requested by the LFSR timer, and we have
554 // to acknowledge its completion.
555 end else begin
556 1/1 integ_chk_ack_o = 1'b1;
Tests: T3 T5 T24
557 end
558 // Error out and lock the partition if this check fails.
559 end else begin
560 1/1 state_d = ErrorSt;
Tests: T39 T40 T41
561 1/1 error_d = CheckFailError;
Tests: T39 T40 T41
562 // The check has finished and found an error.
563 1/1 integ_chk_ack_o = 1'b1;
Tests: T39 T40 T41
564 end
565 end
MISSING_ELSE
566 end
567 ///////////////////////////////////////////////////////////////////
568 // Terminal Error State. This locks access to the partition.
569 // Make sure the partition signals an error state if no error
570 // code has been latched so far, and lock the buffer regs down.
571 ErrorSt: begin
572 1/1 dout_locked_d = MuBi8True;
Tests: T2 T4 T6
573 1/1 if (error_q == NoError) begin
Tests: T2 T4 T6
574 1/1 error_d = FsmStateError;
Tests: T19 T20 T21
575 end
MISSING_ELSE
576 // If we are in error state, we cannot execute the checks anymore.
577 // Hence the acknowledgements are returned immediately.
578 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T2 T4 T6
579 1/1 integ_chk_ack_o = 1'b1;
Tests: T2 T4 T6
580 end
581 ///////////////////////////////////////////////////////////////////
582 // We should never get here. If we do (e.g. via a malicious
583 // glitch), error out immediately.
584 default: begin
585 state_d = ErrorSt;
586 fsm_err_o = 1'b1;
587 end
588 ///////////////////////////////////////////////////////////////////
589 endcase // state_q
590
591
592 // Unconditionally jump into the terminal error state in case of
593 // an ECC error or escalation, and lock access to the partition down.
594 // SEC_CM: PART.FSM.LOCAL_ESC
595 1/1 if (ecc_err) begin
Tests: T1 T2 T3
596 0/1 ==> state_d = ErrorSt;
597 0/1 ==> if (state_q != ErrorSt) begin
598 0/1 ==> error_d = CheckFailError;
599 end
==> MISSING_ELSE
600 end
MISSING_ELSE
601 // SEC_CM: PART.FSM.LOCAL_ESC, PART.FSM.GLOBAL_ESC
602 1/1 if (lc_ctrl_pkg::lc_tx_test_true_loose(escalate_en_i) || cnt_err) begin
Tests: T1 T2 T3
603 1/1 state_d = ErrorSt;
Tests: T2 T4 T6
604 1/1 fsm_err_o = 1'b1;
Tests: T2 T4 T6
605 1/1 if (state_q != ErrorSt) begin
Tests: T2 T4 T6
606 1/1 error_d = FsmStateError;
Tests: T2 T4 T6
607 end
MISSING_ELSE
608 end
MISSING_ELSE
609 end
610
611 ////////////////////////////
612 // Address Calc and Muxes //
613 ////////////////////////////
614
615 // Address counter - this is only used for computing a digest, hence the increment is
616 // fixed to 8 byte.
617 // SEC_CM: PART.CTR.REDUN
618 prim_count #(
619 .Width(CntWidth)
620 ) u_prim_count (
621 .clk_i,
622 .rst_ni,
623 .clr_i(cnt_clr),
624 .set_i(1'b0),
625 .set_cnt_i('0),
626 .incr_en_i(cnt_en),
627 .decr_en_i(1'b0),
628 .step_i(CntWidth'(1)),
629 .commit_i(1'b1),
630 .cnt_o(cnt),
631 .cnt_after_commit_o(),
632 .err_o(cnt_err)
633 );
634
635 logic [OtpByteAddrWidth-1:0] addr_base;
636 1/1 assign addr_base = (base_sel == DigOffset) ? DigestOffset : Info.offset;
Tests: T1 T2 T3
637
638 // Note that OTP works on halfword (16bit) addresses, hence need to
639 // shift the addresses appropriately.
640 logic [OtpByteAddrWidth-1:0] addr_calc;
641 1/1 assign addr_calc = OtpByteAddrWidth'({cnt, {$clog2(ScrmblBlockWidth/8){1'b0}}}) + addr_base;
Tests: T1 T2 T3
642 1/1 assign otp_addr_o = addr_calc[OtpByteAddrWidth-1:OtpAddrShift];
Tests: T1 T2 T3
643
644 if (OtpAddrShift > 0) begin : gen_unused
645 logic unused_bits;
646 1/1 assign unused_bits = ^addr_calc[OtpAddrShift-1:0];
Tests: T1 T2 T3
647 end
648
649 // Always transfer 64bit blocks.
650 assign otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth) - 1);
651
652 1/1 assign data_mux = (data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i;
Tests: T1 T2 T3
653
654 /////////////////
655 // Buffer Regs //
656 /////////////////
657
658 // SEC_CM: PART.DATA_REG.INTEGRITY
659 logic [Info.size*8-1:0] data;
660 otp_ctrl_ecc_reg #(
661 .Width ( ScrmblBlockWidth ),
662 .Depth ( NumScrmblBlocks )
663 ) u_otp_ctrl_ecc_reg (
664 .clk_i,
665 .rst_ni,
666 .wren_i ( buffer_reg_en ),
667 .addr_i ( cnt ),
668 .wdata_i ( data_mux ),
669 .rdata_o ( scrmbl_data_o ),
670 .data_o ( data ),
671 .ecc_err_o ( ecc_err )
672 );
673
674 // We have successfully initialized the partition once it has been unlocked.
675 1/1 assign init_done_o = mubi8_test_false_strict(dout_locked_q);
Tests: T1 T2 T3
676 // Hardware output gating.
677 // Note that this is decoupled from the DAI access rules further below.
678 1/1 assign data_o = (init_done_o) ? data : DataDefault;
Tests: T1 T2 T3
679 // The digest does not have to be gated.
680 1/1 assign digest_o = data[$high(data_o) -: ScrmblBlockWidth];
Tests: T1 T2 T3
681
682 ////////////////////////
683 // DAI Access Control //
684 ////////////////////////
685
686 // Aggregate all possible DAI write /readlocks. The partition is also locked when uninitialized.
687 // Note that the locks are redundantly encoded values.
688 part_access_t access_pre;
689 prim_mubi8_sender #(
690 .AsyncOn(0)
691 ) u_prim_mubi8_sender_write_lock_pre (
692 .clk_i,
693 .rst_ni,
694 .mubi_i(mubi8_and_lo(dout_locked_q, access_i.write_lock)),
695 .mubi_o(access_pre.write_lock)
696 );
697 prim_mubi8_sender #(
698 .AsyncOn(0)
699 ) u_prim_mubi8_sender_read_lock_pre (
700 .clk_i,
701 .rst_ni,
702 .mubi_i(mubi8_and_lo(dout_locked_q, access_i.read_lock)),
703 .mubi_o(access_pre.read_lock)
704 );
705
706 // SEC_CM: PART.MEM.SW_UNWRITABLE
707 if (Info.write_lock) begin : gen_digest_write_lock
708 mubi8_t digest_locked;
709 1/1 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False;
Tests: T1 T2 T3
710
711 // This prevents the synthesis tool from optimizing the multibit signal.
712 prim_mubi8_sender #(
713 .AsyncOn(0)
714 ) u_prim_mubi8_sender_write_lock (
715 .clk_i,
716 .rst_ni,
717 .mubi_i(mubi8_and_lo(access_pre.write_lock, digest_locked)),
718 .mubi_o(access_o.write_lock)
719 );
720
721 `ASSERT(DigestWriteLocksPartition_A, digest_o |-> mubi8_test_true_loose(access_o.write_lock))
722 end else begin : gen_no_digest_write_lock
723 assign access_o.write_lock = access_pre.write_lock;
724 end
725
726 // SEC_CM: PART.MEM.SW_UNREADABLE
727 if (Info.read_lock) begin : gen_digest_read_lock
728 mubi8_t digest_locked;
729 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False;
730
731 // This prevents the synthesis tool from optimizing the multibit signal.
732 prim_mubi8_sender #(
733 .AsyncOn(0)
734 ) u_prim_mubi8_sender_read_lock (
735 .clk_i,
736 .rst_ni,
737 .mubi_i(mubi8_and_lo(access_pre.read_lock, digest_locked)),
738 .mubi_o(access_o.read_lock)
739 );
740
741 `ASSERT(DigestReadLocksPartition_A, digest_o |-> mubi8_test_true_loose(access_o.read_lock))
742 end else begin : gen_no_digest_read_lock
743 1/1 assign access_o.read_lock = access_pre.read_lock;
Tests: T1 T2 T3
744 end
745
746 ///////////////
747 // Registers //
748 ///////////////
749
750 3/3 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt)
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3
PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt):
750.1 `ifdef SIMULATION
750.2 prim_sparse_fsm_flop #(
750.3 .StateEnumT(state_e),
750.4 .Width($bits(state_e)),
750.5 .ResetValue($bits(state_e)'(ResetSt)),
750.6 .EnableAlertTriggerSVA(1),
750.7 .CustomForceName("state_q")
750.8 ) u_state_regs (
750.9 .clk_i ( clk_i ),
750.10 .rst_ni ( rst_ni ),
750.11 .state_i ( state_d ),
750.12 .state_o ( )
750.13 );
750.14 always_ff @(posedge clk_i or negedge rst_ni) begin
750.15 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
750.16 1/1 state_q <= ResetSt;
Tests: T1 T2 T3
750.17 end else begin
750.18 1/1 state_q <= state_d;
Tests: T1 T2 T3
750.19 end
750.20 end
750.21 u_state_regs_A: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (state_q === u_state_regs.state_o))
750.22 else begin
750.23 `ifdef UVM
750.24 uvm_pkg::uvm_report_error("ASSERT FAILED", "u_state_regs_A", uvm_pkg::UVM_NONE,
750.25 "../src/lowrisc_ip_otp_ctrl_1.0/rtl/otp_ctrl_part_buf.sv", 750, "", 1);
750.26 `else
750.27 $error("%0t: (%0s:%0d) [%m] [ASSERT FAILED] %0s", $time, `__FILE__, `__LINE__,
750.28 `PRIM_STRINGIFY(u_state_regs_A));
750.29 `endif
750.30 end
750.31 `else
750.32 prim_sparse_fsm_flop #(
750.33 .StateEnumT(state_e),
750.34 .Width($bits(state_e)),
750.35 .ResetValue($bits(state_e)'(ResetSt)),
750.36 .EnableAlertTriggerSVA(1)
750.37 ) u_state_regs (
750.38 .clk_i ( `PRIM_FLOP_CLK ),
750.39 .rst_ni ( `PRIM_FLOP_RST ),
750.40 .state_i ( state_d ),
750.41 .state_o ( state_q )
750.42 );
750.43 `endif751
752 always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
753 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
754 1/1 error_q <= NoError;
Tests: T1 T2 T3
755 // data output is locked by default
756 1/1 dout_locked_q <= MuBi8True;
Tests: T1 T2 T3
757 end else begin
758 1/1 error_q <= error_d;
Tests: T1 T2 T3
759 1/1 dout_locked_q <= dout_locked_d;
Tests: T1 T2 T3
Line Coverage for Module :
otp_ctrl_part_buf ( parameter Info=-1,CntWidth=1,DigestOffset=1736,StateWidth=12 )
Line Coverage for Module self-instances :
| Line No. | Total | Covered | Percent |
TOTAL | | 160 | 126 | 78.75 |
CONT_ASSIGN | 182 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
ALWAYS | 206 | 140 | 106 | 75.71 |
CONT_ASSIGN | 636 | 1 | 1 | 100.00 |
CONT_ASSIGN | 641 | 1 | 1 | 100.00 |
CONT_ASSIGN | 642 | 1 | 1 | 100.00 |
CONT_ASSIGN | 646 | 1 | 1 | 100.00 |
CONT_ASSIGN | 652 | 1 | 1 | 100.00 |
CONT_ASSIGN | 675 | 1 | 1 | 100.00 |
CONT_ASSIGN | 678 | 1 | 1 | 100.00 |
CONT_ASSIGN | 680 | 1 | 1 | 100.00 |
CONT_ASSIGN | 709 | 1 | 1 | 100.00 |
CONT_ASSIGN | 743 | 1 | 1 | 100.00 |
ALWAYS | 750 | 3 | 3 | 100.00 |
ALWAYS | 753 | 5 | 5 | 100.00 |
181 // Output partition error state.
182 1/1 assign error_o = error_q;
Tests: T1 T2 T3
183
184 // This partition cannot do any write accesses, hence we tie this
185 // constantly off.
186 assign otp_wdata_o = '0;
187 // Depending on the partition configuration, the wrapper is instructed to ignore integrity
188 // calculations and checks. To be on the safe side, the partition filters error responses at this
189 // point and does not report any integrity errors if integrity is disabled.
190 otp_err_e otp_err;
191 if (Info.integrity) begin : gen_integrity
192 assign otp_cmd_o = prim_otp_pkg::Read;
193 1/1 assign otp_err = otp_err_e'(otp_err_i);
Tests: T1 T2 T3
194 end else begin : gen_no_integrity
195 assign otp_cmd_o = prim_otp_pkg::ReadRaw;
196 always_comb begin
197 if (otp_err_e'(otp_err_i) inside {MacroEccCorrError, MacroEccUncorrError}) begin
198 otp_err = NoError;
199 end else begin
200 otp_err = otp_err_e'(otp_err_i);
201 end
202 end
203 end
204
205 always_comb begin : p_fsm
206 1/1 state_d = state_q;
Tests: T1 T2 T3
207
208 // Redundantly encoded lock signal for buffer regs.
209 1/1 dout_locked_d = dout_locked_q;
Tests: T1 T2 T3
210
211 // OTP signals
212 1/1 otp_req_o = 1'b0;
Tests: T1 T2 T3
213
214 // Scrambling mutex
215 1/1 scrmbl_mtx_req_o = 1'b0;
Tests: T1 T2 T3
216
217 // Scrambling datapath
218 1/1 scrmbl_cmd_o = LoadShadow;
Tests: T1 T2 T3
219 1/1 scrmbl_sel_o = CnstyDigest;
Tests: T1 T2 T3
220 1/1 scrmbl_mode_o = StandardMode;
Tests: T1 T2 T3
221 1/1 scrmbl_valid_o = 1'b0;
Tests: T1 T2 T3
222
223 // Counter
224 1/1 cnt_en = 1'b0;
Tests: T1 T2 T3
225 1/1 cnt_clr = 1'b0;
Tests: T1 T2 T3
226 1/1 base_sel = PartOffset;
Tests: T1 T2 T3
227
228 // Buffer register
229 1/1 buffer_reg_en = 1'b0;
Tests: T1 T2 T3
230 1/1 data_sel = OtpData;
Tests: T1 T2 T3
231
232 // Error Register
233 1/1 error_d = error_q;
Tests: T1 T2 T3
234 1/1 fsm_err_o = 1'b0;
Tests: T1 T2 T3
235
236 // Integrity/Consistency check responses
237 1/1 cnsty_chk_ack_o = 1'b0;
Tests: T1 T2 T3
238 1/1 integ_chk_ack_o = 1'b0;
Tests: T1 T2 T3
239
240 1/1 unique case (state_q)
Tests: T1 T2 T3
241 ///////////////////////////////////////////////////////////////////
242 // State right after reset. Wait here until we get a an
243 // initialization request.
244 ResetSt: begin
245 1/1 if (init_req_i) begin
Tests: T1 T2 T3
246 1/1 state_d = InitSt;
Tests: T1 T2 T3
247 end
MISSING_ELSE
248 end
249 ///////////////////////////////////////////////////////////////////
250 // Initialization reads out the digest only in unbuffered
251 // partitions. Wait here until the OTP request has been granted.
252 // And then wait until the OTP word comes back.
253 InitSt: begin
254 1/1 otp_req_o = 1'b1;
Tests: T1 T2 T3
255 1/1 if (otp_gnt_i) begin
Tests: T1 T2 T3
256 1/1 state_d = InitWaitSt;
Tests: T1 T2 T3
257 end
MISSING_ELSE
258 end
259 ///////////////////////////////////////////////////////////////////
260 // Wait for OTP response and write to buffer register, then go to
261 // descrambling state. In case an OTP transaction fails, latch the
262 // OTP error code and jump to a
263 // terminal error state.
264 InitWaitSt: begin
265 1/1 if (otp_rvalid_i) begin
Tests: T1 T2 T3
266 1/1 buffer_reg_en = 1'b1;
Tests: T1 T2 T3
267 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin
Tests: T1 T2 T3
268 // Once we've read and descrambled the whole partition, we can go to integrity
269 // verification. Note that the last block is the digest value, which does not
270 // have to be descrambled.
271 1/1 if (cnt == LastScrmblBlock) begin
Tests: T1 T2 T3
272 1/1 state_d = IntegDigClrSt;
Tests: T1 T2 T3
273 // Only need to descramble if this is a scrambled partition.
274 // Otherwise, we can just go back to InitSt and read the next block.
275 1/1 end else if (Info.secret) begin
Tests: T1 T2 T3
276 unreachable state_d = InitDescrSt;
277 end else begin
278 1/1 state_d = InitSt;
Tests: T1 T2 T3
279 1/1 cnt_en = 1'b1;
Tests: T1 T2 T3
280 end
281 // At this point the only error that we could have gotten are correctable ECC errors.
282 1/1 if (otp_err != NoError) begin
Tests: T1 T2 T3
283 1/1 error_d = MacroEccCorrError;
Tests: T42 T43 T32
284 end
MISSING_ELSE
285 end else begin
286 1/1 state_d = ErrorSt;
Tests: T2 T44 T45
287 1/1 error_d = otp_err;
Tests: T2 T44 T45
288 end
289 end
MISSING_ELSE
290 end
291 ///////////////////////////////////////////////////////////////////
292 // Descrambling state. This first acquires the scrambling
293 // datapath mutex. Note that once the mutex is acquired, we have
294 // exclusive access to the scrambling datapath until we release
295 // the mutex by deasserting scrmbl_mtx_req_o.
296 // SEC_CM: SECRET.MEM.SCRAMBLE
297 InitDescrSt: begin
298 0/1 ==> scrmbl_mtx_req_o = 1'b1;
299 0/1 ==> scrmbl_valid_o = 1'b1;
300 0/1 ==> scrmbl_cmd_o = Decrypt;
301 0/1 ==> scrmbl_sel_o = Info.key_sel;
302 0/1 ==> if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
303 0/1 ==> state_d = InitDescrWaitSt;
304 end
==> MISSING_ELSE
305 end
306 ///////////////////////////////////////////////////////////////////
307 // Wait for the descrambled data to return. Note that we release
308 // the mutex lock upon leaving this state.
309 // SEC_CM: SECRET.MEM.SCRAMBLE
310 InitDescrWaitSt: begin
311 0/1 ==> scrmbl_mtx_req_o = 1'b1;
312 0/1 ==> scrmbl_sel_o = Info.key_sel;
313 0/1 ==> data_sel = ScrmblData;
314 0/1 ==> if (scrmbl_valid_i) begin
315 0/1 ==> state_d = InitSt;
316 0/1 ==> buffer_reg_en = 1'b1;
317 0/1 ==> cnt_en = 1'b1;
318 end
==> MISSING_ELSE
319 end
320 ///////////////////////////////////////////////////////////////////
321 // Idle state. We basically wait for integrity and consistency check
322 // triggers in this state.
323 IdleSt: begin
324 1/1 if (integ_chk_req_i) begin
Tests: T1 T2 T3
325 1/1 if (Info.hw_digest) begin
Tests: T3 T5 T24
326 1/1 state_d = IntegDigClrSt;
Tests: T3 T5 T24
327 // In case there is nothing to check we can just
328 // acknowledge the request right away, without going to the
329 // integrity check.
330 end else begin
331 unreachable integ_chk_ack_o = 1'b1;
332 end
333 1/1 end else if (cnsty_chk_req_i) begin
Tests: T1 T2 T3
334 1/1 state_d = CnstyReadSt;
Tests: T4 T6 T5
335 1/1 cnt_clr = 1'b1;
Tests: T4 T6 T5
336 end
MISSING_ELSE
337 end
338 ///////////////////////////////////////////////////////////////////
339 // Read the digest. Wait here until the OTP request has been granted.
340 // And then wait until the OTP word comes back.
341 // SEC_CM: PART.DATA_REG.BKGN_CHK
342 CnstyReadSt: begin
343 1/1 otp_req_o = 1'b1;
Tests: T4 T6 T5
344 // In case this partition has a hardware digest, we only have to read
345 // and compare the digest value. In that case we select the digest offset here.
346 // Otherwise we have to read and compare the whole partition, in which case we
347 // select the partition offset, which is the default assignment of base_sel.
348 1/1 if (Info.hw_digest) begin
Tests: T4 T6 T5
349 1/1 base_sel = DigOffset;
Tests: T4 T6 T5
350 end
==> MISSING_ELSE
351 1/1 if (otp_gnt_i) begin
Tests: T4 T6 T5
352 1/1 state_d = CnstyReadWaitSt;
Tests: T6 T5 T24
353 end
MISSING_ELSE
354 end
355 ///////////////////////////////////////////////////////////////////
356 // Wait for OTP response and compare the digest. In case there is
357 // a mismatch, lock down the partition and go into the terminal error
358 // state. In case an OTP transaction fails, latch the OTP error code
359 // and jump to a terminal error state.
360 // SEC_CM: PART.DATA_REG.BKGN_CHK
361 CnstyReadWaitSt: begin
362 1/1 if (otp_rvalid_i) begin
Tests: T6 T5 T24
363 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin
Tests: T6 T5 T24
364 // Check whether we need to compare the digest or the full partition
365 // contents here.
366 1/1 if (Info.hw_digest) begin
Tests: T6 T5 T24
367 // Note that we ignore this check if the digest is still blank.
368 1/1 if (digest_o == data_mux || digest_o == '0) begin
Tests: T6 T5 T24
369 1/1 state_d = IdleSt;
Tests: T6 T5 T24
370 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T6 T5 T24
371 // Error out and lock the partition if this check fails.
372 end else begin
373 0/1 ==> state_d = ErrorSt;
374 0/1 ==> error_d = CheckFailError;
375 // The check has finished and found an error.
376 0/1 ==> cnsty_chk_ack_o = 1'b1;
377 end
378 end else begin
379 // Check whether the read data corresponds with the data buffered in regs.
380 // Note that this particular check can be bypassed in case a transition is ongoing.
381 unreachable if (scrmbl_data_o == data_mux ||
382 lc_ctrl_pkg::lc_tx_test_true_strict(check_byp_en_i)) begin
383 // Can go back to idle and acknowledge the
384 // request if this is the last block.
385 unreachable if (cnt == LastScrmblBlock) begin
386 unreachable state_d = IdleSt;
387 unreachable cnsty_chk_ack_o = 1'b1;
388 // Need to go back and read out more blocks.
389 end else begin
390 unreachable state_d = CnstyReadSt;
391 unreachable cnt_en = 1'b1;
392 end
393 end else begin
394 unreachable state_d = ErrorSt;
395 unreachable error_d = CheckFailError;
396 // The check has finished and found an error.
397 unreachable cnsty_chk_ack_o = 1'b1;
398 end
399 end
400 // At this point the only error that we could have gotten are correctable ECC errors.
401 1/1 if (otp_err != NoError) begin
Tests: T6 T5 T24
402 1/1 error_d = MacroEccCorrError;
Tests: T46
403 end
MISSING_ELSE
404 end else begin
405 1/1 state_d = ErrorSt;
Tests: T34 T47 T48
406 1/1 error_d = otp_err;
Tests: T34 T47 T48
407 // The check has finished and found an error.
408 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T34 T47 T48
409 end
410 end
MISSING_ELSE
411 end
412 ///////////////////////////////////////////////////////////////////
413 // First, acquire the mutex for the digest and clear the digest state.
414 // SEC_CM: PART.DATA_REG.BKGN_CHK
415 IntegDigClrSt: begin
416 // Check whether this partition requires checking at all.
417 1/1 if (Info.hw_digest) begin
Tests: T1 T2 T3
418 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
419 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
420 1/1 cnt_clr = 1'b1;
Tests: T1 T2 T3
421 // Need to reset the digest state and set it to chained
422 // mode if this partition is scrambled.
423 1/1 scrmbl_cmd_o = DigestInit;
Tests: T1 T2 T3
424 1/1 if (Info.secret) begin
Tests: T1 T2 T3
425 unreachable scrmbl_mode_o = ChainedMode;
426 unreachable if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
427 unreachable state_d = IntegScrSt;
428 end
==> MISSING_ELSE
429 // If this partition is not scrambled, we can just directly
430 // jump to the digest state.
431 end else begin
432 1/1 scrmbl_mode_o = StandardMode;
Tests: T1 T2 T3
433 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
Tests: T1 T2 T3
434 1/1 state_d = IntegDigSt;
Tests: T1 T2 T3
435 end
MISSING_ELSE
436 end
437 // Otherwise, if this partition is not digest protected,
438 // we can just go to idle, since there is nothing to check.
439 // Note that we do not come back to this state in case there is no
440 // digest, and hence it is safe to unlock the buffer regs at this point.
441 // This is the only way the buffer regs can get unlocked.
442 end else begin
443 unreachable state_d = IdleSt;
444 unreachable if (mubi8_test_true_strict(dout_locked_q)) begin
445 unreachable dout_locked_d = MuBi8False;
446 end
==> MISSING_ELSE
447 end
448 end
449 ///////////////////////////////////////////////////////////////////
450 // Scramble buffered data (which is held in plaintext form).
451 // This moves the previous scrambling result into the shadow reg
452 // for later use.
453 // SEC_CM: PART.DATA_REG.BKGN_CHK
454 IntegScrSt: begin
455 0/1 ==> scrmbl_mtx_req_o = 1'b1;
456 0/1 ==> scrmbl_valid_o = 1'b1;
457 0/1 ==> scrmbl_cmd_o = Encrypt;
458 0/1 ==> scrmbl_sel_o = Info.key_sel;
459 0/1 ==> if (scrmbl_ready_i) begin
460 0/1 ==> state_d = IntegScrWaitSt;
461 end
==> MISSING_ELSE
462 end
463 ///////////////////////////////////////////////////////////////////
464 // Wait for the scrambled data to return.
465 // SEC_CM: PART.DATA_REG.BKGN_CHK
466 IntegScrWaitSt: begin
467 0/1 ==> scrmbl_mtx_req_o = 1'b1;
468 0/1 ==> scrmbl_sel_o = Info.key_sel;
469 0/1 ==> if (scrmbl_valid_i) begin
470 0/1 ==> state_d = IntegDigSt;
471 end
==> MISSING_ELSE
472 end
473 ///////////////////////////////////////////////////////////////////
474 // Push the word read into the scrambling datapath. The last
475 // block is repeated in case the number blocks in this partition
476 // is odd.
477 // SEC_CM: PART.MEM.DIGEST
478 // SEC_CM: PART.DATA_REG.BKGN_CHK
479 IntegDigSt: begin
480 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
481 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
482 1/1 if (scrmbl_ready_i) begin
Tests: T1 T2 T3
483 1/1 cnt_en = 1'b1;
Tests: T1 T2 T3
484 // No need to digest the digest value itself
485 1/1 if (cnt == PenultimateScrmblBlock) begin
Tests: T1 T2 T3
486 // Note that the digest operates on 128bit blocks since the data is fed in via the
487 // PRESENT key input. Therefore, we only trigger a digest update on every second
488 // 64bit block that is pushed into the scrambling datapath.
489 1/1 if (cnt[0]) begin
Tests: T1 T2 T3
490 0/1 ==> scrmbl_cmd_o = Digest;
491 0/1 ==> state_d = IntegDigFinSt;
492 end else begin
493 1/1 state_d = IntegDigPadSt;
Tests: T1 T2 T3
494 1/1 cnt_en = 1'b0;
Tests: T1 T2 T3
495 end
496 end else begin
497 // Trigger digest round in case this is the second block in a row.
498 0/1 ==> if (cnt[0]) begin
499 0/1 ==> scrmbl_cmd_o = Digest;
500 end
==> MISSING_ELSE
501 // Go back and scramble the next data block if this is
502 // a scrambled partition. Otherwise just stay here.
503 0/1 ==> if (Info.secret) begin
504 unreachable state_d = IntegScrSt;
505 end
==> MISSING_ELSE
506 end
507 end
==> MISSING_ELSE
508 end
509 ///////////////////////////////////////////////////////////////////
510 // Padding state. When we get here, we've copied the last encryption
511 // result into the shadow register such that we've effectively
512 // repeated the last block twice in order to pad the data to 128bit.
513 // SEC_CM: PART.MEM.DIGEST
514 // SEC_CM: PART.DATA_REG.BKGN_CHK
515 IntegDigPadSt: begin
516 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
517 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
518 1/1 scrmbl_cmd_o = Digest;
Tests: T1 T2 T3
519 1/1 if (scrmbl_ready_i) begin
Tests: T1 T2 T3
520 1/1 state_d = IntegDigFinSt;
Tests: T1 T2 T3
521 end
==> MISSING_ELSE
522 end
523 ///////////////////////////////////////////////////////////////////
524 // Trigger digest finalization and go wait for the result.
525 // SEC_CM: PART.MEM.DIGEST
526 // SEC_CM: PART.DATA_REG.BKGN_CHK
527 IntegDigFinSt: begin
528 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
529 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
530 1/1 scrmbl_cmd_o = DigestFinalize;
Tests: T1 T2 T3
531 1/1 if (scrmbl_ready_i) begin
Tests: T1 T2 T3
532 1/1 state_d = IntegDigWaitSt;
Tests: T1 T2 T3
533 end
MISSING_ELSE
534 end
535 ///////////////////////////////////////////////////////////////////
536 // Wait for the digest to return, and double check whether the digest
537 // matches. If yes, unlock the partition. Otherwise, go into the terminal
538 // error state, where the partition will be locked down.
539 // SEC_CM: PART.MEM.DIGEST
540 // SEC_CM: PART.DATA_REG.BKGN_CHK
541 IntegDigWaitSt: begin
542 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
543 1/1 data_sel = ScrmblData;
Tests: T1 T2 T3
544 1/1 if (scrmbl_valid_i) begin
Tests: T1 T2 T3
545 // This is the only way the buffer regs can get unlocked.
546 // Note that we ignore this check if the digest is still blank.
547 1/1 if (digest_o == data_mux || digest_o == '0) begin
Tests: T1 T2 T3
548 1/1 state_d = IdleSt;
Tests: T1 T2 T3
549 // If the partition is still locked, this is the first integrity check after
550 // initialization. This is the only way the buffer regs can get unlocked.
551 1/1 if (mubi8_test_true_strict(dout_locked_q)) begin
Tests: T1 T2 T3
552 1/1 dout_locked_d = MuBi8False;
Tests: T1 T2 T3
553 // Otherwise, this integrity check has requested by the LFSR timer, and we have
554 // to acknowledge its completion.
555 end else begin
556 1/1 integ_chk_ack_o = 1'b1;
Tests: T3 T5 T24
557 end
558 // Error out and lock the partition if this check fails.
559 end else begin
560 1/1 state_d = ErrorSt;
Tests: T49 T50 T51
561 1/1 error_d = CheckFailError;
Tests: T49 T50 T51
562 // The check has finished and found an error.
563 1/1 integ_chk_ack_o = 1'b1;
Tests: T49 T50 T51
564 end
565 end
MISSING_ELSE
566 end
567 ///////////////////////////////////////////////////////////////////
568 // Terminal Error State. This locks access to the partition.
569 // Make sure the partition signals an error state if no error
570 // code has been latched so far, and lock the buffer regs down.
571 ErrorSt: begin
572 1/1 dout_locked_d = MuBi8True;
Tests: T2 T4 T6
573 1/1 if (error_q == NoError) begin
Tests: T2 T4 T6
574 1/1 error_d = FsmStateError;
Tests: T19 T20 T21
575 end
MISSING_ELSE
576 // If we are in error state, we cannot execute the checks anymore.
577 // Hence the acknowledgements are returned immediately.
578 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T2 T4 T6
579 1/1 integ_chk_ack_o = 1'b1;
Tests: T2 T4 T6
580 end
581 ///////////////////////////////////////////////////////////////////
582 // We should never get here. If we do (e.g. via a malicious
583 // glitch), error out immediately.
584 default: begin
585 state_d = ErrorSt;
586 fsm_err_o = 1'b1;
587 end
588 ///////////////////////////////////////////////////////////////////
589 endcase // state_q
590
591
592 // Unconditionally jump into the terminal error state in case of
593 // an ECC error or escalation, and lock access to the partition down.
594 // SEC_CM: PART.FSM.LOCAL_ESC
595 1/1 if (ecc_err) begin
Tests: T1 T2 T3
596 0/1 ==> state_d = ErrorSt;
597 0/1 ==> if (state_q != ErrorSt) begin
598 0/1 ==> error_d = CheckFailError;
599 end
==> MISSING_ELSE
600 end
MISSING_ELSE
601 // SEC_CM: PART.FSM.LOCAL_ESC, PART.FSM.GLOBAL_ESC
602 1/1 if (lc_ctrl_pkg::lc_tx_test_true_loose(escalate_en_i) || cnt_err) begin
Tests: T1 T2 T3
603 1/1 state_d = ErrorSt;
Tests: T2 T4 T6
604 1/1 fsm_err_o = 1'b1;
Tests: T2 T4 T6
605 1/1 if (state_q != ErrorSt) begin
Tests: T2 T4 T6
606 1/1 error_d = FsmStateError;
Tests: T4 T6 T23
607 end
MISSING_ELSE
608 end
MISSING_ELSE
609 end
610
611 ////////////////////////////
612 // Address Calc and Muxes //
613 ////////////////////////////
614
615 // Address counter - this is only used for computing a digest, hence the increment is
616 // fixed to 8 byte.
617 // SEC_CM: PART.CTR.REDUN
618 prim_count #(
619 .Width(CntWidth)
620 ) u_prim_count (
621 .clk_i,
622 .rst_ni,
623 .clr_i(cnt_clr),
624 .set_i(1'b0),
625 .set_cnt_i('0),
626 .incr_en_i(cnt_en),
627 .decr_en_i(1'b0),
628 .step_i(CntWidth'(1)),
629 .commit_i(1'b1),
630 .cnt_o(cnt),
631 .cnt_after_commit_o(),
632 .err_o(cnt_err)
633 );
634
635 logic [OtpByteAddrWidth-1:0] addr_base;
636 1/1 assign addr_base = (base_sel == DigOffset) ? DigestOffset : Info.offset;
Tests: T1 T2 T3
637
638 // Note that OTP works on halfword (16bit) addresses, hence need to
639 // shift the addresses appropriately.
640 logic [OtpByteAddrWidth-1:0] addr_calc;
641 1/1 assign addr_calc = OtpByteAddrWidth'({cnt, {$clog2(ScrmblBlockWidth/8){1'b0}}}) + addr_base;
Tests: T1 T2 T3
642 1/1 assign otp_addr_o = addr_calc[OtpByteAddrWidth-1:OtpAddrShift];
Tests: T1 T2 T3
643
644 if (OtpAddrShift > 0) begin : gen_unused
645 logic unused_bits;
646 1/1 assign unused_bits = ^addr_calc[OtpAddrShift-1:0];
Tests: T1 T2 T3
647 end
648
649 // Always transfer 64bit blocks.
650 assign otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth) - 1);
651
652 1/1 assign data_mux = (data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i;
Tests: T1 T2 T3
653
654 /////////////////
655 // Buffer Regs //
656 /////////////////
657
658 // SEC_CM: PART.DATA_REG.INTEGRITY
659 logic [Info.size*8-1:0] data;
660 otp_ctrl_ecc_reg #(
661 .Width ( ScrmblBlockWidth ),
662 .Depth ( NumScrmblBlocks )
663 ) u_otp_ctrl_ecc_reg (
664 .clk_i,
665 .rst_ni,
666 .wren_i ( buffer_reg_en ),
667 .addr_i ( cnt ),
668 .wdata_i ( data_mux ),
669 .rdata_o ( scrmbl_data_o ),
670 .data_o ( data ),
671 .ecc_err_o ( ecc_err )
672 );
673
674 // We have successfully initialized the partition once it has been unlocked.
675 1/1 assign init_done_o = mubi8_test_false_strict(dout_locked_q);
Tests: T1 T2 T3
676 // Hardware output gating.
677 // Note that this is decoupled from the DAI access rules further below.
678 1/1 assign data_o = (init_done_o) ? data : DataDefault;
Tests: T1 T2 T3
679 // The digest does not have to be gated.
680 1/1 assign digest_o = data[$high(data_o) -: ScrmblBlockWidth];
Tests: T1 T2 T3
681
682 ////////////////////////
683 // DAI Access Control //
684 ////////////////////////
685
686 // Aggregate all possible DAI write /readlocks. The partition is also locked when uninitialized.
687 // Note that the locks are redundantly encoded values.
688 part_access_t access_pre;
689 prim_mubi8_sender #(
690 .AsyncOn(0)
691 ) u_prim_mubi8_sender_write_lock_pre (
692 .clk_i,
693 .rst_ni,
694 .mubi_i(mubi8_and_lo(dout_locked_q, access_i.write_lock)),
695 .mubi_o(access_pre.write_lock)
696 );
697 prim_mubi8_sender #(
698 .AsyncOn(0)
699 ) u_prim_mubi8_sender_read_lock_pre (
700 .clk_i,
701 .rst_ni,
702 .mubi_i(mubi8_and_lo(dout_locked_q, access_i.read_lock)),
703 .mubi_o(access_pre.read_lock)
704 );
705
706 // SEC_CM: PART.MEM.SW_UNWRITABLE
707 if (Info.write_lock) begin : gen_digest_write_lock
708 mubi8_t digest_locked;
709 1/1 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False;
Tests: T1 T2 T3
710
711 // This prevents the synthesis tool from optimizing the multibit signal.
712 prim_mubi8_sender #(
713 .AsyncOn(0)
714 ) u_prim_mubi8_sender_write_lock (
715 .clk_i,
716 .rst_ni,
717 .mubi_i(mubi8_and_lo(access_pre.write_lock, digest_locked)),
718 .mubi_o(access_o.write_lock)
719 );
720
721 `ASSERT(DigestWriteLocksPartition_A, digest_o |-> mubi8_test_true_loose(access_o.write_lock))
722 end else begin : gen_no_digest_write_lock
723 assign access_o.write_lock = access_pre.write_lock;
724 end
725
726 // SEC_CM: PART.MEM.SW_UNREADABLE
727 if (Info.read_lock) begin : gen_digest_read_lock
728 mubi8_t digest_locked;
729 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False;
730
731 // This prevents the synthesis tool from optimizing the multibit signal.
732 prim_mubi8_sender #(
733 .AsyncOn(0)
734 ) u_prim_mubi8_sender_read_lock (
735 .clk_i,
736 .rst_ni,
737 .mubi_i(mubi8_and_lo(access_pre.read_lock, digest_locked)),
738 .mubi_o(access_o.read_lock)
739 );
740
741 `ASSERT(DigestReadLocksPartition_A, digest_o |-> mubi8_test_true_loose(access_o.read_lock))
742 end else begin : gen_no_digest_read_lock
743 1/1 assign access_o.read_lock = access_pre.read_lock;
Tests: T1 T2 T3
744 end
745
746 ///////////////
747 // Registers //
748 ///////////////
749
750 3/3 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt)
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3
PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt):
750.1 `ifdef SIMULATION
750.2 prim_sparse_fsm_flop #(
750.3 .StateEnumT(state_e),
750.4 .Width($bits(state_e)),
750.5 .ResetValue($bits(state_e)'(ResetSt)),
750.6 .EnableAlertTriggerSVA(1),
750.7 .CustomForceName("state_q")
750.8 ) u_state_regs (
750.9 .clk_i ( clk_i ),
750.10 .rst_ni ( rst_ni ),
750.11 .state_i ( state_d ),
750.12 .state_o ( )
750.13 );
750.14 always_ff @(posedge clk_i or negedge rst_ni) begin
750.15 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
750.16 1/1 state_q <= ResetSt;
Tests: T1 T2 T3
750.17 end else begin
750.18 1/1 state_q <= state_d;
Tests: T1 T2 T3
750.19 end
750.20 end
750.21 u_state_regs_A: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (state_q === u_state_regs.state_o))
750.22 else begin
750.23 `ifdef UVM
750.24 uvm_pkg::uvm_report_error("ASSERT FAILED", "u_state_regs_A", uvm_pkg::UVM_NONE,
750.25 "../src/lowrisc_ip_otp_ctrl_1.0/rtl/otp_ctrl_part_buf.sv", 750, "", 1);
750.26 `else
750.27 $error("%0t: (%0s:%0d) [%m] [ASSERT FAILED] %0s", $time, `__FILE__, `__LINE__,
750.28 `PRIM_STRINGIFY(u_state_regs_A));
750.29 `endif
750.30 end
750.31 `else
750.32 prim_sparse_fsm_flop #(
750.33 .StateEnumT(state_e),
750.34 .Width($bits(state_e)),
750.35 .ResetValue($bits(state_e)'(ResetSt)),
750.36 .EnableAlertTriggerSVA(1)
750.37 ) u_state_regs (
750.38 .clk_i ( `PRIM_FLOP_CLK ),
750.39 .rst_ni ( `PRIM_FLOP_RST ),
750.40 .state_i ( state_d ),
750.41 .state_o ( state_q )
750.42 );
750.43 `endif751
752 always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
753 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
754 1/1 error_q <= NoError;
Tests: T1 T2 T3
755 // data output is locked by default
756 1/1 dout_locked_q <= MuBi8True;
Tests: T1 T2 T3
757 end else begin
758 1/1 error_q <= error_d;
Tests: T1 T2 T3
759 1/1 dout_locked_q <= dout_locked_d;
Tests: T1 T2 T3
Line Coverage for Module :
otp_ctrl_part_buf ( parameter Info=-1,CntWidth=3,DigestOffset=1776,StateWidth=12 )
Line Coverage for Module self-instances :
| Line No. | Total | Covered | Percent |
TOTAL | | 160 | 147 | 91.88 |
CONT_ASSIGN | 182 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
ALWAYS | 206 | 140 | 127 | 90.71 |
CONT_ASSIGN | 636 | 1 | 1 | 100.00 |
CONT_ASSIGN | 641 | 1 | 1 | 100.00 |
CONT_ASSIGN | 642 | 1 | 1 | 100.00 |
CONT_ASSIGN | 646 | 1 | 1 | 100.00 |
CONT_ASSIGN | 652 | 1 | 1 | 100.00 |
CONT_ASSIGN | 675 | 1 | 1 | 100.00 |
CONT_ASSIGN | 678 | 1 | 1 | 100.00 |
CONT_ASSIGN | 680 | 1 | 1 | 100.00 |
CONT_ASSIGN | 709 | 1 | 1 | 100.00 |
CONT_ASSIGN | 729 | 1 | 1 | 100.00 |
ALWAYS | 750 | 3 | 3 | 100.00 |
ALWAYS | 753 | 5 | 5 | 100.00 |
181 // Output partition error state.
182 1/1 assign error_o = error_q;
Tests: T1 T2 T3
183
184 // This partition cannot do any write accesses, hence we tie this
185 // constantly off.
186 assign otp_wdata_o = '0;
187 // Depending on the partition configuration, the wrapper is instructed to ignore integrity
188 // calculations and checks. To be on the safe side, the partition filters error responses at this
189 // point and does not report any integrity errors if integrity is disabled.
190 otp_err_e otp_err;
191 if (Info.integrity) begin : gen_integrity
192 assign otp_cmd_o = prim_otp_pkg::Read;
193 1/1 assign otp_err = otp_err_e'(otp_err_i);
Tests: T1 T2 T3
194 end else begin : gen_no_integrity
195 assign otp_cmd_o = prim_otp_pkg::ReadRaw;
196 always_comb begin
197 if (otp_err_e'(otp_err_i) inside {MacroEccCorrError, MacroEccUncorrError}) begin
198 otp_err = NoError;
199 end else begin
200 otp_err = otp_err_e'(otp_err_i);
201 end
202 end
203 end
204
205 always_comb begin : p_fsm
206 1/1 state_d = state_q;
Tests: T1 T2 T3
207
208 // Redundantly encoded lock signal for buffer regs.
209 1/1 dout_locked_d = dout_locked_q;
Tests: T1 T2 T3
210
211 // OTP signals
212 1/1 otp_req_o = 1'b0;
Tests: T1 T2 T3
213
214 // Scrambling mutex
215 1/1 scrmbl_mtx_req_o = 1'b0;
Tests: T1 T2 T3
216
217 // Scrambling datapath
218 1/1 scrmbl_cmd_o = LoadShadow;
Tests: T1 T2 T3
219 1/1 scrmbl_sel_o = CnstyDigest;
Tests: T1 T2 T3
220 1/1 scrmbl_mode_o = StandardMode;
Tests: T1 T2 T3
221 1/1 scrmbl_valid_o = 1'b0;
Tests: T1 T2 T3
222
223 // Counter
224 1/1 cnt_en = 1'b0;
Tests: T1 T2 T3
225 1/1 cnt_clr = 1'b0;
Tests: T1 T2 T3
226 1/1 base_sel = PartOffset;
Tests: T1 T2 T3
227
228 // Buffer register
229 1/1 buffer_reg_en = 1'b0;
Tests: T1 T2 T3
230 1/1 data_sel = OtpData;
Tests: T1 T2 T3
231
232 // Error Register
233 1/1 error_d = error_q;
Tests: T1 T2 T3
234 1/1 fsm_err_o = 1'b0;
Tests: T1 T2 T3
235
236 // Integrity/Consistency check responses
237 1/1 cnsty_chk_ack_o = 1'b0;
Tests: T1 T2 T3
238 1/1 integ_chk_ack_o = 1'b0;
Tests: T1 T2 T3
239
240 1/1 unique case (state_q)
Tests: T1 T2 T3
241 ///////////////////////////////////////////////////////////////////
242 // State right after reset. Wait here until we get a an
243 // initialization request.
244 ResetSt: begin
245 1/1 if (init_req_i) begin
Tests: T1 T2 T3
246 1/1 state_d = InitSt;
Tests: T1 T2 T3
247 end
MISSING_ELSE
248 end
249 ///////////////////////////////////////////////////////////////////
250 // Initialization reads out the digest only in unbuffered
251 // partitions. Wait here until the OTP request has been granted.
252 // And then wait until the OTP word comes back.
253 InitSt: begin
254 1/1 otp_req_o = 1'b1;
Tests: T1 T2 T3
255 1/1 if (otp_gnt_i) begin
Tests: T1 T2 T3
256 1/1 state_d = InitWaitSt;
Tests: T1 T2 T3
257 end
MISSING_ELSE
258 end
259 ///////////////////////////////////////////////////////////////////
260 // Wait for OTP response and write to buffer register, then go to
261 // descrambling state. In case an OTP transaction fails, latch the
262 // OTP error code and jump to a
263 // terminal error state.
264 InitWaitSt: begin
265 1/1 if (otp_rvalid_i) begin
Tests: T1 T2 T3
266 1/1 buffer_reg_en = 1'b1;
Tests: T1 T2 T3
267 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin
Tests: T1 T2 T3
268 // Once we've read and descrambled the whole partition, we can go to integrity
269 // verification. Note that the last block is the digest value, which does not
270 // have to be descrambled.
271 1/1 if (cnt == LastScrmblBlock) begin
Tests: T1 T2 T3
272 1/1 state_d = IntegDigClrSt;
Tests: T1 T2 T3
273 // Only need to descramble if this is a scrambled partition.
274 // Otherwise, we can just go back to InitSt and read the next block.
275 1/1 end else if (Info.secret) begin
Tests: T1 T2 T3
276 1/1 state_d = InitDescrSt;
Tests: T1 T2 T3
277 end else begin
278 unreachable state_d = InitSt;
279 unreachable cnt_en = 1'b1;
280 end
281 // At this point the only error that we could have gotten are correctable ECC errors.
282 1/1 if (otp_err != NoError) begin
Tests: T1 T2 T3
283 1/1 error_d = MacroEccCorrError;
Tests: T52 T31 T53
284 end
MISSING_ELSE
285 end else begin
286 1/1 state_d = ErrorSt;
Tests: T43 T54 T55
287 1/1 error_d = otp_err;
Tests: T43 T54 T55
288 end
289 end
MISSING_ELSE
290 end
291 ///////////////////////////////////////////////////////////////////
292 // Descrambling state. This first acquires the scrambling
293 // datapath mutex. Note that once the mutex is acquired, we have
294 // exclusive access to the scrambling datapath until we release
295 // the mutex by deasserting scrmbl_mtx_req_o.
296 // SEC_CM: SECRET.MEM.SCRAMBLE
297 InitDescrSt: begin
298 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
299 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
300 1/1 scrmbl_cmd_o = Decrypt;
Tests: T1 T2 T3
301 1/1 scrmbl_sel_o = Info.key_sel;
Tests: T1 T2 T3
302 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
Tests: T1 T2 T3
303 1/1 state_d = InitDescrWaitSt;
Tests: T1 T2 T3
304 end
MISSING_ELSE
305 end
306 ///////////////////////////////////////////////////////////////////
307 // Wait for the descrambled data to return. Note that we release
308 // the mutex lock upon leaving this state.
309 // SEC_CM: SECRET.MEM.SCRAMBLE
310 InitDescrWaitSt: begin
311 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
312 1/1 scrmbl_sel_o = Info.key_sel;
Tests: T1 T2 T3
313 1/1 data_sel = ScrmblData;
Tests: T1 T2 T3
314 1/1 if (scrmbl_valid_i) begin
Tests: T1 T2 T3
315 1/1 state_d = InitSt;
Tests: T1 T2 T3
316 1/1 buffer_reg_en = 1'b1;
Tests: T1 T2 T3
317 1/1 cnt_en = 1'b1;
Tests: T1 T2 T3
318 end
MISSING_ELSE
319 end
320 ///////////////////////////////////////////////////////////////////
321 // Idle state. We basically wait for integrity and consistency check
322 // triggers in this state.
323 IdleSt: begin
324 1/1 if (integ_chk_req_i) begin
Tests: T1 T2 T3
325 1/1 if (Info.hw_digest) begin
Tests: T3 T5 T24
326 1/1 state_d = IntegDigClrSt;
Tests: T3 T5 T24
327 // In case there is nothing to check we can just
328 // acknowledge the request right away, without going to the
329 // integrity check.
330 end else begin
331 unreachable integ_chk_ack_o = 1'b1;
332 end
333 1/1 end else if (cnsty_chk_req_i) begin
Tests: T1 T2 T3
334 1/1 state_d = CnstyReadSt;
Tests: T4 T6 T5
335 1/1 cnt_clr = 1'b1;
Tests: T4 T6 T5
336 end
MISSING_ELSE
337 end
338 ///////////////////////////////////////////////////////////////////
339 // Read the digest. Wait here until the OTP request has been granted.
340 // And then wait until the OTP word comes back.
341 // SEC_CM: PART.DATA_REG.BKGN_CHK
342 CnstyReadSt: begin
343 1/1 otp_req_o = 1'b1;
Tests: T4 T6 T5
344 // In case this partition has a hardware digest, we only have to read
345 // and compare the digest value. In that case we select the digest offset here.
346 // Otherwise we have to read and compare the whole partition, in which case we
347 // select the partition offset, which is the default assignment of base_sel.
348 1/1 if (Info.hw_digest) begin
Tests: T4 T6 T5
349 1/1 base_sel = DigOffset;
Tests: T4 T6 T5
350 end
==> MISSING_ELSE
351 1/1 if (otp_gnt_i) begin
Tests: T4 T6 T5
352 1/1 state_d = CnstyReadWaitSt;
Tests: T6 T5 T24
353 end
MISSING_ELSE
354 end
355 ///////////////////////////////////////////////////////////////////
356 // Wait for OTP response and compare the digest. In case there is
357 // a mismatch, lock down the partition and go into the terminal error
358 // state. In case an OTP transaction fails, latch the OTP error code
359 // and jump to a terminal error state.
360 // SEC_CM: PART.DATA_REG.BKGN_CHK
361 CnstyReadWaitSt: begin
362 1/1 if (otp_rvalid_i) begin
Tests: T6 T5 T24
363 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin
Tests: T6 T5 T24
364 // Check whether we need to compare the digest or the full partition
365 // contents here.
366 1/1 if (Info.hw_digest) begin
Tests: T6 T5 T24
367 // Note that we ignore this check if the digest is still blank.
368 1/1 if (digest_o == data_mux || digest_o == '0) begin
Tests: T6 T5 T24
369 1/1 state_d = IdleSt;
Tests: T6 T5 T24
370 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T6 T5 T24
371 // Error out and lock the partition if this check fails.
372 end else begin
373 0/1 ==> state_d = ErrorSt;
374 0/1 ==> error_d = CheckFailError;
375 // The check has finished and found an error.
376 0/1 ==> cnsty_chk_ack_o = 1'b1;
377 end
378 end else begin
379 // Check whether the read data corresponds with the data buffered in regs.
380 // Note that this particular check can be bypassed in case a transition is ongoing.
381 unreachable if (scrmbl_data_o == data_mux ||
382 lc_ctrl_pkg::lc_tx_test_true_strict(check_byp_en_i)) begin
383 // Can go back to idle and acknowledge the
384 // request if this is the last block.
385 unreachable if (cnt == LastScrmblBlock) begin
386 unreachable state_d = IdleSt;
387 unreachable cnsty_chk_ack_o = 1'b1;
388 // Need to go back and read out more blocks.
389 end else begin
390 unreachable state_d = CnstyReadSt;
391 unreachable cnt_en = 1'b1;
392 end
393 end else begin
394 unreachable state_d = ErrorSt;
395 unreachable error_d = CheckFailError;
396 // The check has finished and found an error.
397 unreachable cnsty_chk_ack_o = 1'b1;
398 end
399 end
400 // At this point the only error that we could have gotten are correctable ECC errors.
401 1/1 if (otp_err != NoError) begin
Tests: T6 T5 T24
402 1/1 error_d = MacroEccCorrError;
Tests: T35 T56
403 end
MISSING_ELSE
404 end else begin
405 1/1 state_d = ErrorSt;
Tests: T57 T46 T48
406 1/1 error_d = otp_err;
Tests: T57 T46 T48
407 // The check has finished and found an error.
408 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T57 T46 T48
409 end
410 end
MISSING_ELSE
411 end
412 ///////////////////////////////////////////////////////////////////
413 // First, acquire the mutex for the digest and clear the digest state.
414 // SEC_CM: PART.DATA_REG.BKGN_CHK
415 IntegDigClrSt: begin
416 // Check whether this partition requires checking at all.
417 1/1 if (Info.hw_digest) begin
Tests: T1 T2 T3
418 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
419 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
420 1/1 cnt_clr = 1'b1;
Tests: T1 T2 T3
421 // Need to reset the digest state and set it to chained
422 // mode if this partition is scrambled.
423 1/1 scrmbl_cmd_o = DigestInit;
Tests: T1 T2 T3
424 1/1 if (Info.secret) begin
Tests: T1 T2 T3
425 1/1 scrmbl_mode_o = ChainedMode;
Tests: T1 T2 T3
426 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
Tests: T1 T2 T3
427 1/1 state_d = IntegScrSt;
Tests: T1 T2 T3
428 end
MISSING_ELSE
429 // If this partition is not scrambled, we can just directly
430 // jump to the digest state.
431 end else begin
432 unreachable scrmbl_mode_o = StandardMode;
433 unreachable if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
434 unreachable state_d = IntegDigSt;
435 end
==> MISSING_ELSE
436 end
437 // Otherwise, if this partition is not digest protected,
438 // we can just go to idle, since there is nothing to check.
439 // Note that we do not come back to this state in case there is no
440 // digest, and hence it is safe to unlock the buffer regs at this point.
441 // This is the only way the buffer regs can get unlocked.
442 end else begin
443 unreachable state_d = IdleSt;
444 unreachable if (mubi8_test_true_strict(dout_locked_q)) begin
445 unreachable dout_locked_d = MuBi8False;
446 end
==> MISSING_ELSE
447 end
448 end
449 ///////////////////////////////////////////////////////////////////
450 // Scramble buffered data (which is held in plaintext form).
451 // This moves the previous scrambling result into the shadow reg
452 // for later use.
453 // SEC_CM: PART.DATA_REG.BKGN_CHK
454 IntegScrSt: begin
455 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
456 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
457 1/1 scrmbl_cmd_o = Encrypt;
Tests: T1 T2 T3
458 1/1 scrmbl_sel_o = Info.key_sel;
Tests: T1 T2 T3
459 1/1 if (scrmbl_ready_i) begin
Tests: T1 T2 T3
460 1/1 state_d = IntegScrWaitSt;
Tests: T1 T2 T3
461 end
MISSING_ELSE
462 end
463 ///////////////////////////////////////////////////////////////////
464 // Wait for the scrambled data to return.
465 // SEC_CM: PART.DATA_REG.BKGN_CHK
466 IntegScrWaitSt: begin
467 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
468 1/1 scrmbl_sel_o = Info.key_sel;
Tests: T1 T2 T3
469 1/1 if (scrmbl_valid_i) begin
Tests: T1 T2 T3
470 1/1 state_d = IntegDigSt;
Tests: T1 T2 T3
471 end
MISSING_ELSE
472 end
473 ///////////////////////////////////////////////////////////////////
474 // Push the word read into the scrambling datapath. The last
475 // block is repeated in case the number blocks in this partition
476 // is odd.
477 // SEC_CM: PART.MEM.DIGEST
478 // SEC_CM: PART.DATA_REG.BKGN_CHK
479 IntegDigSt: begin
480 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
481 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
482 1/1 if (scrmbl_ready_i) begin
Tests: T1 T2 T3
483 1/1 cnt_en = 1'b1;
Tests: T1 T2 T3
484 // No need to digest the digest value itself
485 1/1 if (cnt == PenultimateScrmblBlock) begin
Tests: T1 T2 T3
486 // Note that the digest operates on 128bit blocks since the data is fed in via the
487 // PRESENT key input. Therefore, we only trigger a digest update on every second
488 // 64bit block that is pushed into the scrambling datapath.
489 1/1 if (cnt[0]) begin
Tests: T1 T2 T3
490 1/1 scrmbl_cmd_o = Digest;
Tests: T1 T2 T3
491 1/1 state_d = IntegDigFinSt;
Tests: T1 T2 T3
492 end else begin
493 0/1 ==> state_d = IntegDigPadSt;
494 0/1 ==> cnt_en = 1'b0;
495 end
496 end else begin
497 // Trigger digest round in case this is the second block in a row.
498 1/1 if (cnt[0]) begin
Tests: T1 T2 T3
499 1/1 scrmbl_cmd_o = Digest;
Tests: T1 T2 T3
500 end
MISSING_ELSE
501 // Go back and scramble the next data block if this is
502 // a scrambled partition. Otherwise just stay here.
503 1/1 if (Info.secret) begin
Tests: T1 T2 T3
504 1/1 state_d = IntegScrSt;
Tests: T1 T2 T3
505 end
==> MISSING_ELSE
506 end
507 end
==> MISSING_ELSE
508 end
509 ///////////////////////////////////////////////////////////////////
510 // Padding state. When we get here, we've copied the last encryption
511 // result into the shadow register such that we've effectively
512 // repeated the last block twice in order to pad the data to 128bit.
513 // SEC_CM: PART.MEM.DIGEST
514 // SEC_CM: PART.DATA_REG.BKGN_CHK
515 IntegDigPadSt: begin
516 0/1 ==> scrmbl_mtx_req_o = 1'b1;
517 0/1 ==> scrmbl_valid_o = 1'b1;
518 0/1 ==> scrmbl_cmd_o = Digest;
519 0/1 ==> if (scrmbl_ready_i) begin
520 0/1 ==> state_d = IntegDigFinSt;
521 end
==> MISSING_ELSE
522 end
523 ///////////////////////////////////////////////////////////////////
524 // Trigger digest finalization and go wait for the result.
525 // SEC_CM: PART.MEM.DIGEST
526 // SEC_CM: PART.DATA_REG.BKGN_CHK
527 IntegDigFinSt: begin
528 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
529 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
530 1/1 scrmbl_cmd_o = DigestFinalize;
Tests: T1 T2 T3
531 1/1 if (scrmbl_ready_i) begin
Tests: T1 T2 T3
532 1/1 state_d = IntegDigWaitSt;
Tests: T1 T2 T3
533 end
MISSING_ELSE
534 end
535 ///////////////////////////////////////////////////////////////////
536 // Wait for the digest to return, and double check whether the digest
537 // matches. If yes, unlock the partition. Otherwise, go into the terminal
538 // error state, where the partition will be locked down.
539 // SEC_CM: PART.MEM.DIGEST
540 // SEC_CM: PART.DATA_REG.BKGN_CHK
541 IntegDigWaitSt: begin
542 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
543 1/1 data_sel = ScrmblData;
Tests: T1 T2 T3
544 1/1 if (scrmbl_valid_i) begin
Tests: T1 T2 T3
545 // This is the only way the buffer regs can get unlocked.
546 // Note that we ignore this check if the digest is still blank.
547 1/1 if (digest_o == data_mux || digest_o == '0) begin
Tests: T1 T2 T3
548 1/1 state_d = IdleSt;
Tests: T1 T2 T3
549 // If the partition is still locked, this is the first integrity check after
550 // initialization. This is the only way the buffer regs can get unlocked.
551 1/1 if (mubi8_test_true_strict(dout_locked_q)) begin
Tests: T1 T2 T3
552 1/1 dout_locked_d = MuBi8False;
Tests: T1 T2 T3
553 // Otherwise, this integrity check has requested by the LFSR timer, and we have
554 // to acknowledge its completion.
555 end else begin
556 1/1 integ_chk_ack_o = 1'b1;
Tests: T3 T5 T24
557 end
558 // Error out and lock the partition if this check fails.
559 end else begin
560 1/1 state_d = ErrorSt;
Tests: T58 T59 T60
561 1/1 error_d = CheckFailError;
Tests: T58 T59 T60
562 // The check has finished and found an error.
563 1/1 integ_chk_ack_o = 1'b1;
Tests: T58 T59 T60
564 end
565 end
MISSING_ELSE
566 end
567 ///////////////////////////////////////////////////////////////////
568 // Terminal Error State. This locks access to the partition.
569 // Make sure the partition signals an error state if no error
570 // code has been latched so far, and lock the buffer regs down.
571 ErrorSt: begin
572 1/1 dout_locked_d = MuBi8True;
Tests: T2 T4 T6
573 1/1 if (error_q == NoError) begin
Tests: T2 T4 T6
574 1/1 error_d = FsmStateError;
Tests: T19 T20 T21
575 end
MISSING_ELSE
576 // If we are in error state, we cannot execute the checks anymore.
577 // Hence the acknowledgements are returned immediately.
578 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T2 T4 T6
579 1/1 integ_chk_ack_o = 1'b1;
Tests: T2 T4 T6
580 end
581 ///////////////////////////////////////////////////////////////////
582 // We should never get here. If we do (e.g. via a malicious
583 // glitch), error out immediately.
584 default: begin
585 state_d = ErrorSt;
586 fsm_err_o = 1'b1;
587 end
588 ///////////////////////////////////////////////////////////////////
589 endcase // state_q
590
591
592 // Unconditionally jump into the terminal error state in case of
593 // an ECC error or escalation, and lock access to the partition down.
594 // SEC_CM: PART.FSM.LOCAL_ESC
595 1/1 if (ecc_err) begin
Tests: T1 T2 T3
596 0/1 ==> state_d = ErrorSt;
597 0/1 ==> if (state_q != ErrorSt) begin
598 0/1 ==> error_d = CheckFailError;
599 end
==> MISSING_ELSE
600 end
MISSING_ELSE
601 // SEC_CM: PART.FSM.LOCAL_ESC, PART.FSM.GLOBAL_ESC
602 1/1 if (lc_ctrl_pkg::lc_tx_test_true_loose(escalate_en_i) || cnt_err) begin
Tests: T1 T2 T3
603 1/1 state_d = ErrorSt;
Tests: T2 T4 T6
604 1/1 fsm_err_o = 1'b1;
Tests: T2 T4 T6
605 1/1 if (state_q != ErrorSt) begin
Tests: T2 T4 T6
606 1/1 error_d = FsmStateError;
Tests: T2 T4 T6
607 end
MISSING_ELSE
608 end
MISSING_ELSE
609 end
610
611 ////////////////////////////
612 // Address Calc and Muxes //
613 ////////////////////////////
614
615 // Address counter - this is only used for computing a digest, hence the increment is
616 // fixed to 8 byte.
617 // SEC_CM: PART.CTR.REDUN
618 prim_count #(
619 .Width(CntWidth)
620 ) u_prim_count (
621 .clk_i,
622 .rst_ni,
623 .clr_i(cnt_clr),
624 .set_i(1'b0),
625 .set_cnt_i('0),
626 .incr_en_i(cnt_en),
627 .decr_en_i(1'b0),
628 .step_i(CntWidth'(1)),
629 .commit_i(1'b1),
630 .cnt_o(cnt),
631 .cnt_after_commit_o(),
632 .err_o(cnt_err)
633 );
634
635 logic [OtpByteAddrWidth-1:0] addr_base;
636 1/1 assign addr_base = (base_sel == DigOffset) ? DigestOffset : Info.offset;
Tests: T1 T2 T3
637
638 // Note that OTP works on halfword (16bit) addresses, hence need to
639 // shift the addresses appropriately.
640 logic [OtpByteAddrWidth-1:0] addr_calc;
641 1/1 assign addr_calc = OtpByteAddrWidth'({cnt, {$clog2(ScrmblBlockWidth/8){1'b0}}}) + addr_base;
Tests: T1 T2 T3
642 1/1 assign otp_addr_o = addr_calc[OtpByteAddrWidth-1:OtpAddrShift];
Tests: T1 T2 T3
643
644 if (OtpAddrShift > 0) begin : gen_unused
645 logic unused_bits;
646 1/1 assign unused_bits = ^addr_calc[OtpAddrShift-1:0];
Tests: T1 T2 T3
647 end
648
649 // Always transfer 64bit blocks.
650 assign otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth) - 1);
651
652 1/1 assign data_mux = (data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i;
Tests: T1 T2 T3
653
654 /////////////////
655 // Buffer Regs //
656 /////////////////
657
658 // SEC_CM: PART.DATA_REG.INTEGRITY
659 logic [Info.size*8-1:0] data;
660 otp_ctrl_ecc_reg #(
661 .Width ( ScrmblBlockWidth ),
662 .Depth ( NumScrmblBlocks )
663 ) u_otp_ctrl_ecc_reg (
664 .clk_i,
665 .rst_ni,
666 .wren_i ( buffer_reg_en ),
667 .addr_i ( cnt ),
668 .wdata_i ( data_mux ),
669 .rdata_o ( scrmbl_data_o ),
670 .data_o ( data ),
671 .ecc_err_o ( ecc_err )
672 );
673
674 // We have successfully initialized the partition once it has been unlocked.
675 1/1 assign init_done_o = mubi8_test_false_strict(dout_locked_q);
Tests: T1 T2 T3
676 // Hardware output gating.
677 // Note that this is decoupled from the DAI access rules further below.
678 1/1 assign data_o = (init_done_o) ? data : DataDefault;
Tests: T1 T2 T3
679 // The digest does not have to be gated.
680 1/1 assign digest_o = data[$high(data_o) -: ScrmblBlockWidth];
Tests: T1 T2 T3
681
682 ////////////////////////
683 // DAI Access Control //
684 ////////////////////////
685
686 // Aggregate all possible DAI write /readlocks. The partition is also locked when uninitialized.
687 // Note that the locks are redundantly encoded values.
688 part_access_t access_pre;
689 prim_mubi8_sender #(
690 .AsyncOn(0)
691 ) u_prim_mubi8_sender_write_lock_pre (
692 .clk_i,
693 .rst_ni,
694 .mubi_i(mubi8_and_lo(dout_locked_q, access_i.write_lock)),
695 .mubi_o(access_pre.write_lock)
696 );
697 prim_mubi8_sender #(
698 .AsyncOn(0)
699 ) u_prim_mubi8_sender_read_lock_pre (
700 .clk_i,
701 .rst_ni,
702 .mubi_i(mubi8_and_lo(dout_locked_q, access_i.read_lock)),
703 .mubi_o(access_pre.read_lock)
704 );
705
706 // SEC_CM: PART.MEM.SW_UNWRITABLE
707 if (Info.write_lock) begin : gen_digest_write_lock
708 mubi8_t digest_locked;
709 1/1 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False;
Tests: T1 T2 T3
710
711 // This prevents the synthesis tool from optimizing the multibit signal.
712 prim_mubi8_sender #(
713 .AsyncOn(0)
714 ) u_prim_mubi8_sender_write_lock (
715 .clk_i,
716 .rst_ni,
717 .mubi_i(mubi8_and_lo(access_pre.write_lock, digest_locked)),
718 .mubi_o(access_o.write_lock)
719 );
720
721 `ASSERT(DigestWriteLocksPartition_A, digest_o |-> mubi8_test_true_loose(access_o.write_lock))
722 end else begin : gen_no_digest_write_lock
723 assign access_o.write_lock = access_pre.write_lock;
724 end
725
726 // SEC_CM: PART.MEM.SW_UNREADABLE
727 if (Info.read_lock) begin : gen_digest_read_lock
728 mubi8_t digest_locked;
729 1/1 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False;
Tests: T1 T2 T3
730
731 // This prevents the synthesis tool from optimizing the multibit signal.
732 prim_mubi8_sender #(
733 .AsyncOn(0)
734 ) u_prim_mubi8_sender_read_lock (
735 .clk_i,
736 .rst_ni,
737 .mubi_i(mubi8_and_lo(access_pre.read_lock, digest_locked)),
738 .mubi_o(access_o.read_lock)
739 );
740
741 `ASSERT(DigestReadLocksPartition_A, digest_o |-> mubi8_test_true_loose(access_o.read_lock))
742 end else begin : gen_no_digest_read_lock
743 assign access_o.read_lock = access_pre.read_lock;
744 end
745
746 ///////////////
747 // Registers //
748 ///////////////
749
750 3/3 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt)
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3
PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt):
750.1 `ifdef SIMULATION
750.2 prim_sparse_fsm_flop #(
750.3 .StateEnumT(state_e),
750.4 .Width($bits(state_e)),
750.5 .ResetValue($bits(state_e)'(ResetSt)),
750.6 .EnableAlertTriggerSVA(1),
750.7 .CustomForceName("state_q")
750.8 ) u_state_regs (
750.9 .clk_i ( clk_i ),
750.10 .rst_ni ( rst_ni ),
750.11 .state_i ( state_d ),
750.12 .state_o ( )
750.13 );
750.14 always_ff @(posedge clk_i or negedge rst_ni) begin
750.15 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
750.16 1/1 state_q <= ResetSt;
Tests: T1 T2 T3
750.17 end else begin
750.18 1/1 state_q <= state_d;
Tests: T1 T2 T3
750.19 end
750.20 end
750.21 u_state_regs_A: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (state_q === u_state_regs.state_o))
750.22 else begin
750.23 `ifdef UVM
750.24 uvm_pkg::uvm_report_error("ASSERT FAILED", "u_state_regs_A", uvm_pkg::UVM_NONE,
750.25 "../src/lowrisc_ip_otp_ctrl_1.0/rtl/otp_ctrl_part_buf.sv", 750, "", 1);
750.26 `else
750.27 $error("%0t: (%0s:%0d) [%m] [ASSERT FAILED] %0s", $time, `__FILE__, `__LINE__,
750.28 `PRIM_STRINGIFY(u_state_regs_A));
750.29 `endif
750.30 end
750.31 `else
750.32 prim_sparse_fsm_flop #(
750.33 .StateEnumT(state_e),
750.34 .Width($bits(state_e)),
750.35 .ResetValue($bits(state_e)'(ResetSt)),
750.36 .EnableAlertTriggerSVA(1)
750.37 ) u_state_regs (
750.38 .clk_i ( `PRIM_FLOP_CLK ),
750.39 .rst_ni ( `PRIM_FLOP_RST ),
750.40 .state_i ( state_d ),
750.41 .state_o ( state_q )
750.42 );
750.43 `endif751
752 always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
753 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
754 1/1 error_q <= NoError;
Tests: T1 T2 T3
755 // data output is locked by default
756 1/1 dout_locked_q <= MuBi8True;
Tests: T1 T2 T3
757 end else begin
758 1/1 error_q <= error_d;
Tests: T1 T2 T3
759 1/1 dout_locked_q <= dout_locked_d;
Tests: T1 T2 T3
Line Coverage for Module :
otp_ctrl_part_buf ( parameter Info=-1,CntWidth=4,DigestOffset=1864,StateWidth=12 )
Line Coverage for Module self-instances :
| Line No. | Total | Covered | Percent |
TOTAL | | 160 | 147 | 91.88 |
CONT_ASSIGN | 182 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
ALWAYS | 206 | 140 | 127 | 90.71 |
CONT_ASSIGN | 636 | 1 | 1 | 100.00 |
CONT_ASSIGN | 641 | 1 | 1 | 100.00 |
CONT_ASSIGN | 642 | 1 | 1 | 100.00 |
CONT_ASSIGN | 646 | 1 | 1 | 100.00 |
CONT_ASSIGN | 652 | 1 | 1 | 100.00 |
CONT_ASSIGN | 675 | 1 | 1 | 100.00 |
CONT_ASSIGN | 678 | 1 | 1 | 100.00 |
CONT_ASSIGN | 680 | 1 | 1 | 100.00 |
CONT_ASSIGN | 709 | 1 | 1 | 100.00 |
CONT_ASSIGN | 729 | 1 | 1 | 100.00 |
ALWAYS | 750 | 3 | 3 | 100.00 |
ALWAYS | 753 | 5 | 5 | 100.00 |
181 // Output partition error state.
182 1/1 assign error_o = error_q;
Tests: T1 T2 T3
183
184 // This partition cannot do any write accesses, hence we tie this
185 // constantly off.
186 assign otp_wdata_o = '0;
187 // Depending on the partition configuration, the wrapper is instructed to ignore integrity
188 // calculations and checks. To be on the safe side, the partition filters error responses at this
189 // point and does not report any integrity errors if integrity is disabled.
190 otp_err_e otp_err;
191 if (Info.integrity) begin : gen_integrity
192 assign otp_cmd_o = prim_otp_pkg::Read;
193 1/1 assign otp_err = otp_err_e'(otp_err_i);
Tests: T1 T2 T3
194 end else begin : gen_no_integrity
195 assign otp_cmd_o = prim_otp_pkg::ReadRaw;
196 always_comb begin
197 if (otp_err_e'(otp_err_i) inside {MacroEccCorrError, MacroEccUncorrError}) begin
198 otp_err = NoError;
199 end else begin
200 otp_err = otp_err_e'(otp_err_i);
201 end
202 end
203 end
204
205 always_comb begin : p_fsm
206 1/1 state_d = state_q;
Tests: T1 T2 T3
207
208 // Redundantly encoded lock signal for buffer regs.
209 1/1 dout_locked_d = dout_locked_q;
Tests: T1 T2 T3
210
211 // OTP signals
212 1/1 otp_req_o = 1'b0;
Tests: T1 T2 T3
213
214 // Scrambling mutex
215 1/1 scrmbl_mtx_req_o = 1'b0;
Tests: T1 T2 T3
216
217 // Scrambling datapath
218 1/1 scrmbl_cmd_o = LoadShadow;
Tests: T1 T2 T3
219 1/1 scrmbl_sel_o = CnstyDigest;
Tests: T1 T2 T3
220 1/1 scrmbl_mode_o = StandardMode;
Tests: T1 T2 T3
221 1/1 scrmbl_valid_o = 1'b0;
Tests: T1 T2 T3
222
223 // Counter
224 1/1 cnt_en = 1'b0;
Tests: T1 T2 T3
225 1/1 cnt_clr = 1'b0;
Tests: T1 T2 T3
226 1/1 base_sel = PartOffset;
Tests: T1 T2 T3
227
228 // Buffer register
229 1/1 buffer_reg_en = 1'b0;
Tests: T1 T2 T3
230 1/1 data_sel = OtpData;
Tests: T1 T2 T3
231
232 // Error Register
233 1/1 error_d = error_q;
Tests: T1 T2 T3
234 1/1 fsm_err_o = 1'b0;
Tests: T1 T2 T3
235
236 // Integrity/Consistency check responses
237 1/1 cnsty_chk_ack_o = 1'b0;
Tests: T1 T2 T3
238 1/1 integ_chk_ack_o = 1'b0;
Tests: T1 T2 T3
239
240 1/1 unique case (state_q)
Tests: T1 T2 T3
241 ///////////////////////////////////////////////////////////////////
242 // State right after reset. Wait here until we get a an
243 // initialization request.
244 ResetSt: begin
245 1/1 if (init_req_i) begin
Tests: T1 T2 T3
246 1/1 state_d = InitSt;
Tests: T1 T2 T3
247 end
MISSING_ELSE
248 end
249 ///////////////////////////////////////////////////////////////////
250 // Initialization reads out the digest only in unbuffered
251 // partitions. Wait here until the OTP request has been granted.
252 // And then wait until the OTP word comes back.
253 InitSt: begin
254 1/1 otp_req_o = 1'b1;
Tests: T1 T2 T3
255 1/1 if (otp_gnt_i) begin
Tests: T1 T2 T3
256 1/1 state_d = InitWaitSt;
Tests: T1 T2 T3
257 end
MISSING_ELSE
258 end
259 ///////////////////////////////////////////////////////////////////
260 // Wait for OTP response and write to buffer register, then go to
261 // descrambling state. In case an OTP transaction fails, latch the
262 // OTP error code and jump to a
263 // terminal error state.
264 InitWaitSt: begin
265 1/1 if (otp_rvalid_i) begin
Tests: T1 T2 T3
266 1/1 buffer_reg_en = 1'b1;
Tests: T1 T2 T3
267 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin
Tests: T1 T2 T3
268 // Once we've read and descrambled the whole partition, we can go to integrity
269 // verification. Note that the last block is the digest value, which does not
270 // have to be descrambled.
271 1/1 if (cnt == LastScrmblBlock) begin
Tests: T1 T2 T3
272 1/1 state_d = IntegDigClrSt;
Tests: T1 T2 T3
273 // Only need to descramble if this is a scrambled partition.
274 // Otherwise, we can just go back to InitSt and read the next block.
275 1/1 end else if (Info.secret) begin
Tests: T1 T2 T3
276 1/1 state_d = InitDescrSt;
Tests: T1 T2 T3
277 end else begin
278 unreachable state_d = InitSt;
279 unreachable cnt_en = 1'b1;
280 end
281 // At this point the only error that we could have gotten are correctable ECC errors.
282 1/1 if (otp_err != NoError) begin
Tests: T1 T2 T3
283 1/1 error_d = MacroEccCorrError;
Tests: T61 T62 T63
284 end
MISSING_ELSE
285 end else begin
286 1/1 state_d = ErrorSt;
Tests: T42 T64 T29
287 1/1 error_d = otp_err;
Tests: T42 T64 T29
288 end
289 end
MISSING_ELSE
290 end
291 ///////////////////////////////////////////////////////////////////
292 // Descrambling state. This first acquires the scrambling
293 // datapath mutex. Note that once the mutex is acquired, we have
294 // exclusive access to the scrambling datapath until we release
295 // the mutex by deasserting scrmbl_mtx_req_o.
296 // SEC_CM: SECRET.MEM.SCRAMBLE
297 InitDescrSt: begin
298 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
299 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
300 1/1 scrmbl_cmd_o = Decrypt;
Tests: T1 T2 T3
301 1/1 scrmbl_sel_o = Info.key_sel;
Tests: T1 T2 T3
302 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
Tests: T1 T2 T3
303 1/1 state_d = InitDescrWaitSt;
Tests: T1 T2 T3
304 end
MISSING_ELSE
305 end
306 ///////////////////////////////////////////////////////////////////
307 // Wait for the descrambled data to return. Note that we release
308 // the mutex lock upon leaving this state.
309 // SEC_CM: SECRET.MEM.SCRAMBLE
310 InitDescrWaitSt: begin
311 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
312 1/1 scrmbl_sel_o = Info.key_sel;
Tests: T1 T2 T3
313 1/1 data_sel = ScrmblData;
Tests: T1 T2 T3
314 1/1 if (scrmbl_valid_i) begin
Tests: T1 T2 T3
315 1/1 state_d = InitSt;
Tests: T1 T2 T3
316 1/1 buffer_reg_en = 1'b1;
Tests: T1 T2 T3
317 1/1 cnt_en = 1'b1;
Tests: T1 T2 T3
318 end
MISSING_ELSE
319 end
320 ///////////////////////////////////////////////////////////////////
321 // Idle state. We basically wait for integrity and consistency check
322 // triggers in this state.
323 IdleSt: begin
324 1/1 if (integ_chk_req_i) begin
Tests: T1 T2 T3
325 1/1 if (Info.hw_digest) begin
Tests: T3 T5 T24
326 1/1 state_d = IntegDigClrSt;
Tests: T3 T5 T24
327 // In case there is nothing to check we can just
328 // acknowledge the request right away, without going to the
329 // integrity check.
330 end else begin
331 unreachable integ_chk_ack_o = 1'b1;
332 end
333 1/1 end else if (cnsty_chk_req_i) begin
Tests: T1 T2 T3
334 1/1 state_d = CnstyReadSt;
Tests: T4 T6 T5
335 1/1 cnt_clr = 1'b1;
Tests: T4 T6 T5
336 end
MISSING_ELSE
337 end
338 ///////////////////////////////////////////////////////////////////
339 // Read the digest. Wait here until the OTP request has been granted.
340 // And then wait until the OTP word comes back.
341 // SEC_CM: PART.DATA_REG.BKGN_CHK
342 CnstyReadSt: begin
343 1/1 otp_req_o = 1'b1;
Tests: T4 T6 T5
344 // In case this partition has a hardware digest, we only have to read
345 // and compare the digest value. In that case we select the digest offset here.
346 // Otherwise we have to read and compare the whole partition, in which case we
347 // select the partition offset, which is the default assignment of base_sel.
348 1/1 if (Info.hw_digest) begin
Tests: T4 T6 T5
349 1/1 base_sel = DigOffset;
Tests: T4 T6 T5
350 end
==> MISSING_ELSE
351 1/1 if (otp_gnt_i) begin
Tests: T4 T6 T5
352 1/1 state_d = CnstyReadWaitSt;
Tests: T6 T5 T24
353 end
MISSING_ELSE
354 end
355 ///////////////////////////////////////////////////////////////////
356 // Wait for OTP response and compare the digest. In case there is
357 // a mismatch, lock down the partition and go into the terminal error
358 // state. In case an OTP transaction fails, latch the OTP error code
359 // and jump to a terminal error state.
360 // SEC_CM: PART.DATA_REG.BKGN_CHK
361 CnstyReadWaitSt: begin
362 1/1 if (otp_rvalid_i) begin
Tests: T6 T5 T24
363 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin
Tests: T6 T5 T24
364 // Check whether we need to compare the digest or the full partition
365 // contents here.
366 1/1 if (Info.hw_digest) begin
Tests: T6 T5 T24
367 // Note that we ignore this check if the digest is still blank.
368 1/1 if (digest_o == data_mux || digest_o == '0) begin
Tests: T6 T5 T24
369 1/1 state_d = IdleSt;
Tests: T6 T5 T24
370 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T6 T5 T24
371 // Error out and lock the partition if this check fails.
372 end else begin
373 0/1 ==> state_d = ErrorSt;
374 0/1 ==> error_d = CheckFailError;
375 // The check has finished and found an error.
376 0/1 ==> cnsty_chk_ack_o = 1'b1;
377 end
378 end else begin
379 // Check whether the read data corresponds with the data buffered in regs.
380 // Note that this particular check can be bypassed in case a transition is ongoing.
381 unreachable if (scrmbl_data_o == data_mux ||
382 lc_ctrl_pkg::lc_tx_test_true_strict(check_byp_en_i)) begin
383 // Can go back to idle and acknowledge the
384 // request if this is the last block.
385 unreachable if (cnt == LastScrmblBlock) begin
386 unreachable state_d = IdleSt;
387 unreachable cnsty_chk_ack_o = 1'b1;
388 // Need to go back and read out more blocks.
389 end else begin
390 unreachable state_d = CnstyReadSt;
391 unreachable cnt_en = 1'b1;
392 end
393 end else begin
394 unreachable state_d = ErrorSt;
395 unreachable error_d = CheckFailError;
396 // The check has finished and found an error.
397 unreachable cnsty_chk_ack_o = 1'b1;
398 end
399 end
400 // At this point the only error that we could have gotten are correctable ECC errors.
401 1/1 if (otp_err != NoError) begin
Tests: T6 T5 T24
402 1/1 error_d = MacroEccCorrError;
Tests: T34 T65 T66
403 end
MISSING_ELSE
404 end else begin
405 1/1 state_d = ErrorSt;
Tests: T38 T67 T68
406 1/1 error_d = otp_err;
Tests: T38 T67 T68
407 // The check has finished and found an error.
408 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T38 T67 T68
409 end
410 end
MISSING_ELSE
411 end
412 ///////////////////////////////////////////////////////////////////
413 // First, acquire the mutex for the digest and clear the digest state.
414 // SEC_CM: PART.DATA_REG.BKGN_CHK
415 IntegDigClrSt: begin
416 // Check whether this partition requires checking at all.
417 1/1 if (Info.hw_digest) begin
Tests: T1 T2 T3
418 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
419 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
420 1/1 cnt_clr = 1'b1;
Tests: T1 T2 T3
421 // Need to reset the digest state and set it to chained
422 // mode if this partition is scrambled.
423 1/1 scrmbl_cmd_o = DigestInit;
Tests: T1 T2 T3
424 1/1 if (Info.secret) begin
Tests: T1 T2 T3
425 1/1 scrmbl_mode_o = ChainedMode;
Tests: T1 T2 T3
426 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
Tests: T1 T2 T3
427 1/1 state_d = IntegScrSt;
Tests: T1 T2 T3
428 end
MISSING_ELSE
429 // If this partition is not scrambled, we can just directly
430 // jump to the digest state.
431 end else begin
432 unreachable scrmbl_mode_o = StandardMode;
433 unreachable if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
434 unreachable state_d = IntegDigSt;
435 end
==> MISSING_ELSE
436 end
437 // Otherwise, if this partition is not digest protected,
438 // we can just go to idle, since there is nothing to check.
439 // Note that we do not come back to this state in case there is no
440 // digest, and hence it is safe to unlock the buffer regs at this point.
441 // This is the only way the buffer regs can get unlocked.
442 end else begin
443 unreachable state_d = IdleSt;
444 unreachable if (mubi8_test_true_strict(dout_locked_q)) begin
445 unreachable dout_locked_d = MuBi8False;
446 end
==> MISSING_ELSE
447 end
448 end
449 ///////////////////////////////////////////////////////////////////
450 // Scramble buffered data (which is held in plaintext form).
451 // This moves the previous scrambling result into the shadow reg
452 // for later use.
453 // SEC_CM: PART.DATA_REG.BKGN_CHK
454 IntegScrSt: begin
455 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
456 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
457 1/1 scrmbl_cmd_o = Encrypt;
Tests: T1 T2 T3
458 1/1 scrmbl_sel_o = Info.key_sel;
Tests: T1 T2 T3
459 1/1 if (scrmbl_ready_i) begin
Tests: T1 T2 T3
460 1/1 state_d = IntegScrWaitSt;
Tests: T1 T2 T3
461 end
MISSING_ELSE
462 end
463 ///////////////////////////////////////////////////////////////////
464 // Wait for the scrambled data to return.
465 // SEC_CM: PART.DATA_REG.BKGN_CHK
466 IntegScrWaitSt: begin
467 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
468 1/1 scrmbl_sel_o = Info.key_sel;
Tests: T1 T2 T3
469 1/1 if (scrmbl_valid_i) begin
Tests: T1 T2 T3
470 1/1 state_d = IntegDigSt;
Tests: T1 T2 T3
471 end
MISSING_ELSE
472 end
473 ///////////////////////////////////////////////////////////////////
474 // Push the word read into the scrambling datapath. The last
475 // block is repeated in case the number blocks in this partition
476 // is odd.
477 // SEC_CM: PART.MEM.DIGEST
478 // SEC_CM: PART.DATA_REG.BKGN_CHK
479 IntegDigSt: begin
480 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
481 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
482 1/1 if (scrmbl_ready_i) begin
Tests: T1 T2 T3
483 1/1 cnt_en = 1'b1;
Tests: T1 T2 T3
484 // No need to digest the digest value itself
485 1/1 if (cnt == PenultimateScrmblBlock) begin
Tests: T1 T2 T3
486 // Note that the digest operates on 128bit blocks since the data is fed in via the
487 // PRESENT key input. Therefore, we only trigger a digest update on every second
488 // 64bit block that is pushed into the scrambling datapath.
489 1/1 if (cnt[0]) begin
Tests: T1 T2 T3
490 1/1 scrmbl_cmd_o = Digest;
Tests: T1 T2 T3
491 1/1 state_d = IntegDigFinSt;
Tests: T1 T2 T3
492 end else begin
493 0/1 ==> state_d = IntegDigPadSt;
494 0/1 ==> cnt_en = 1'b0;
495 end
496 end else begin
497 // Trigger digest round in case this is the second block in a row.
498 1/1 if (cnt[0]) begin
Tests: T1 T2 T3
499 1/1 scrmbl_cmd_o = Digest;
Tests: T1 T2 T3
500 end
MISSING_ELSE
501 // Go back and scramble the next data block if this is
502 // a scrambled partition. Otherwise just stay here.
503 1/1 if (Info.secret) begin
Tests: T1 T2 T3
504 1/1 state_d = IntegScrSt;
Tests: T1 T2 T3
505 end
==> MISSING_ELSE
506 end
507 end
==> MISSING_ELSE
508 end
509 ///////////////////////////////////////////////////////////////////
510 // Padding state. When we get here, we've copied the last encryption
511 // result into the shadow register such that we've effectively
512 // repeated the last block twice in order to pad the data to 128bit.
513 // SEC_CM: PART.MEM.DIGEST
514 // SEC_CM: PART.DATA_REG.BKGN_CHK
515 IntegDigPadSt: begin
516 0/1 ==> scrmbl_mtx_req_o = 1'b1;
517 0/1 ==> scrmbl_valid_o = 1'b1;
518 0/1 ==> scrmbl_cmd_o = Digest;
519 0/1 ==> if (scrmbl_ready_i) begin
520 0/1 ==> state_d = IntegDigFinSt;
521 end
==> MISSING_ELSE
522 end
523 ///////////////////////////////////////////////////////////////////
524 // Trigger digest finalization and go wait for the result.
525 // SEC_CM: PART.MEM.DIGEST
526 // SEC_CM: PART.DATA_REG.BKGN_CHK
527 IntegDigFinSt: begin
528 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
529 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
530 1/1 scrmbl_cmd_o = DigestFinalize;
Tests: T1 T2 T3
531 1/1 if (scrmbl_ready_i) begin
Tests: T1 T2 T3
532 1/1 state_d = IntegDigWaitSt;
Tests: T1 T2 T3
533 end
MISSING_ELSE
534 end
535 ///////////////////////////////////////////////////////////////////
536 // Wait for the digest to return, and double check whether the digest
537 // matches. If yes, unlock the partition. Otherwise, go into the terminal
538 // error state, where the partition will be locked down.
539 // SEC_CM: PART.MEM.DIGEST
540 // SEC_CM: PART.DATA_REG.BKGN_CHK
541 IntegDigWaitSt: begin
542 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
543 1/1 data_sel = ScrmblData;
Tests: T1 T2 T3
544 1/1 if (scrmbl_valid_i) begin
Tests: T1 T2 T3
545 // This is the only way the buffer regs can get unlocked.
546 // Note that we ignore this check if the digest is still blank.
547 1/1 if (digest_o == data_mux || digest_o == '0) begin
Tests: T1 T2 T3
548 1/1 state_d = IdleSt;
Tests: T1 T2 T3
549 // If the partition is still locked, this is the first integrity check after
550 // initialization. This is the only way the buffer regs can get unlocked.
551 1/1 if (mubi8_test_true_strict(dout_locked_q)) begin
Tests: T1 T2 T3
552 1/1 dout_locked_d = MuBi8False;
Tests: T1 T2 T3
553 // Otherwise, this integrity check has requested by the LFSR timer, and we have
554 // to acknowledge its completion.
555 end else begin
556 1/1 integ_chk_ack_o = 1'b1;
Tests: T3 T5 T24
557 end
558 // Error out and lock the partition if this check fails.
559 end else begin
560 1/1 state_d = ErrorSt;
Tests: T69 T70 T71
561 1/1 error_d = CheckFailError;
Tests: T69 T70 T71
562 // The check has finished and found an error.
563 1/1 integ_chk_ack_o = 1'b1;
Tests: T69 T70 T71
564 end
565 end
MISSING_ELSE
566 end
567 ///////////////////////////////////////////////////////////////////
568 // Terminal Error State. This locks access to the partition.
569 // Make sure the partition signals an error state if no error
570 // code has been latched so far, and lock the buffer regs down.
571 ErrorSt: begin
572 1/1 dout_locked_d = MuBi8True;
Tests: T2 T4 T6
573 1/1 if (error_q == NoError) begin
Tests: T2 T4 T6
574 1/1 error_d = FsmStateError;
Tests: T19 T20 T21
575 end
MISSING_ELSE
576 // If we are in error state, we cannot execute the checks anymore.
577 // Hence the acknowledgements are returned immediately.
578 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T2 T4 T6
579 1/1 integ_chk_ack_o = 1'b1;
Tests: T2 T4 T6
580 end
581 ///////////////////////////////////////////////////////////////////
582 // We should never get here. If we do (e.g. via a malicious
583 // glitch), error out immediately.
584 default: begin
585 state_d = ErrorSt;
586 fsm_err_o = 1'b1;
587 end
588 ///////////////////////////////////////////////////////////////////
589 endcase // state_q
590
591
592 // Unconditionally jump into the terminal error state in case of
593 // an ECC error or escalation, and lock access to the partition down.
594 // SEC_CM: PART.FSM.LOCAL_ESC
595 1/1 if (ecc_err) begin
Tests: T1 T2 T3
596 0/1 ==> state_d = ErrorSt;
597 0/1 ==> if (state_q != ErrorSt) begin
598 0/1 ==> error_d = CheckFailError;
599 end
==> MISSING_ELSE
600 end
MISSING_ELSE
601 // SEC_CM: PART.FSM.LOCAL_ESC, PART.FSM.GLOBAL_ESC
602 1/1 if (lc_ctrl_pkg::lc_tx_test_true_loose(escalate_en_i) || cnt_err) begin
Tests: T1 T2 T3
603 1/1 state_d = ErrorSt;
Tests: T2 T4 T6
604 1/1 fsm_err_o = 1'b1;
Tests: T2 T4 T6
605 1/1 if (state_q != ErrorSt) begin
Tests: T2 T4 T6
606 1/1 error_d = FsmStateError;
Tests: T2 T4 T6
607 end
MISSING_ELSE
608 end
MISSING_ELSE
609 end
610
611 ////////////////////////////
612 // Address Calc and Muxes //
613 ////////////////////////////
614
615 // Address counter - this is only used for computing a digest, hence the increment is
616 // fixed to 8 byte.
617 // SEC_CM: PART.CTR.REDUN
618 prim_count #(
619 .Width(CntWidth)
620 ) u_prim_count (
621 .clk_i,
622 .rst_ni,
623 .clr_i(cnt_clr),
624 .set_i(1'b0),
625 .set_cnt_i('0),
626 .incr_en_i(cnt_en),
627 .decr_en_i(1'b0),
628 .step_i(CntWidth'(1)),
629 .commit_i(1'b1),
630 .cnt_o(cnt),
631 .cnt_after_commit_o(),
632 .err_o(cnt_err)
633 );
634
635 logic [OtpByteAddrWidth-1:0] addr_base;
636 1/1 assign addr_base = (base_sel == DigOffset) ? DigestOffset : Info.offset;
Tests: T1 T2 T3
637
638 // Note that OTP works on halfword (16bit) addresses, hence need to
639 // shift the addresses appropriately.
640 logic [OtpByteAddrWidth-1:0] addr_calc;
641 1/1 assign addr_calc = OtpByteAddrWidth'({cnt, {$clog2(ScrmblBlockWidth/8){1'b0}}}) + addr_base;
Tests: T1 T2 T3
642 1/1 assign otp_addr_o = addr_calc[OtpByteAddrWidth-1:OtpAddrShift];
Tests: T1 T2 T3
643
644 if (OtpAddrShift > 0) begin : gen_unused
645 logic unused_bits;
646 1/1 assign unused_bits = ^addr_calc[OtpAddrShift-1:0];
Tests: T1 T2 T3
647 end
648
649 // Always transfer 64bit blocks.
650 assign otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth) - 1);
651
652 1/1 assign data_mux = (data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i;
Tests: T1 T2 T3
653
654 /////////////////
655 // Buffer Regs //
656 /////////////////
657
658 // SEC_CM: PART.DATA_REG.INTEGRITY
659 logic [Info.size*8-1:0] data;
660 otp_ctrl_ecc_reg #(
661 .Width ( ScrmblBlockWidth ),
662 .Depth ( NumScrmblBlocks )
663 ) u_otp_ctrl_ecc_reg (
664 .clk_i,
665 .rst_ni,
666 .wren_i ( buffer_reg_en ),
667 .addr_i ( cnt ),
668 .wdata_i ( data_mux ),
669 .rdata_o ( scrmbl_data_o ),
670 .data_o ( data ),
671 .ecc_err_o ( ecc_err )
672 );
673
674 // We have successfully initialized the partition once it has been unlocked.
675 1/1 assign init_done_o = mubi8_test_false_strict(dout_locked_q);
Tests: T1 T2 T3
676 // Hardware output gating.
677 // Note that this is decoupled from the DAI access rules further below.
678 1/1 assign data_o = (init_done_o) ? data : DataDefault;
Tests: T1 T2 T3
679 // The digest does not have to be gated.
680 1/1 assign digest_o = data[$high(data_o) -: ScrmblBlockWidth];
Tests: T1 T2 T3
681
682 ////////////////////////
683 // DAI Access Control //
684 ////////////////////////
685
686 // Aggregate all possible DAI write /readlocks. The partition is also locked when uninitialized.
687 // Note that the locks are redundantly encoded values.
688 part_access_t access_pre;
689 prim_mubi8_sender #(
690 .AsyncOn(0)
691 ) u_prim_mubi8_sender_write_lock_pre (
692 .clk_i,
693 .rst_ni,
694 .mubi_i(mubi8_and_lo(dout_locked_q, access_i.write_lock)),
695 .mubi_o(access_pre.write_lock)
696 );
697 prim_mubi8_sender #(
698 .AsyncOn(0)
699 ) u_prim_mubi8_sender_read_lock_pre (
700 .clk_i,
701 .rst_ni,
702 .mubi_i(mubi8_and_lo(dout_locked_q, access_i.read_lock)),
703 .mubi_o(access_pre.read_lock)
704 );
705
706 // SEC_CM: PART.MEM.SW_UNWRITABLE
707 if (Info.write_lock) begin : gen_digest_write_lock
708 mubi8_t digest_locked;
709 1/1 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False;
Tests: T1 T2 T3
710
711 // This prevents the synthesis tool from optimizing the multibit signal.
712 prim_mubi8_sender #(
713 .AsyncOn(0)
714 ) u_prim_mubi8_sender_write_lock (
715 .clk_i,
716 .rst_ni,
717 .mubi_i(mubi8_and_lo(access_pre.write_lock, digest_locked)),
718 .mubi_o(access_o.write_lock)
719 );
720
721 `ASSERT(DigestWriteLocksPartition_A, digest_o |-> mubi8_test_true_loose(access_o.write_lock))
722 end else begin : gen_no_digest_write_lock
723 assign access_o.write_lock = access_pre.write_lock;
724 end
725
726 // SEC_CM: PART.MEM.SW_UNREADABLE
727 if (Info.read_lock) begin : gen_digest_read_lock
728 mubi8_t digest_locked;
729 1/1 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False;
Tests: T1 T2 T3
730
731 // This prevents the synthesis tool from optimizing the multibit signal.
732 prim_mubi8_sender #(
733 .AsyncOn(0)
734 ) u_prim_mubi8_sender_read_lock (
735 .clk_i,
736 .rst_ni,
737 .mubi_i(mubi8_and_lo(access_pre.read_lock, digest_locked)),
738 .mubi_o(access_o.read_lock)
739 );
740
741 `ASSERT(DigestReadLocksPartition_A, digest_o |-> mubi8_test_true_loose(access_o.read_lock))
742 end else begin : gen_no_digest_read_lock
743 assign access_o.read_lock = access_pre.read_lock;
744 end
745
746 ///////////////
747 // Registers //
748 ///////////////
749
750 3/3 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt)
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3
PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt):
750.1 `ifdef SIMULATION
750.2 prim_sparse_fsm_flop #(
750.3 .StateEnumT(state_e),
750.4 .Width($bits(state_e)),
750.5 .ResetValue($bits(state_e)'(ResetSt)),
750.6 .EnableAlertTriggerSVA(1),
750.7 .CustomForceName("state_q")
750.8 ) u_state_regs (
750.9 .clk_i ( clk_i ),
750.10 .rst_ni ( rst_ni ),
750.11 .state_i ( state_d ),
750.12 .state_o ( )
750.13 );
750.14 always_ff @(posedge clk_i or negedge rst_ni) begin
750.15 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
750.16 1/1 state_q <= ResetSt;
Tests: T1 T2 T3
750.17 end else begin
750.18 1/1 state_q <= state_d;
Tests: T1 T2 T3
750.19 end
750.20 end
750.21 u_state_regs_A: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (state_q === u_state_regs.state_o))
750.22 else begin
750.23 `ifdef UVM
750.24 uvm_pkg::uvm_report_error("ASSERT FAILED", "u_state_regs_A", uvm_pkg::UVM_NONE,
750.25 "../src/lowrisc_ip_otp_ctrl_1.0/rtl/otp_ctrl_part_buf.sv", 750, "", 1);
750.26 `else
750.27 $error("%0t: (%0s:%0d) [%m] [ASSERT FAILED] %0s", $time, `__FILE__, `__LINE__,
750.28 `PRIM_STRINGIFY(u_state_regs_A));
750.29 `endif
750.30 end
750.31 `else
750.32 prim_sparse_fsm_flop #(
750.33 .StateEnumT(state_e),
750.34 .Width($bits(state_e)),
750.35 .ResetValue($bits(state_e)'(ResetSt)),
750.36 .EnableAlertTriggerSVA(1)
750.37 ) u_state_regs (
750.38 .clk_i ( `PRIM_FLOP_CLK ),
750.39 .rst_ni ( `PRIM_FLOP_RST ),
750.40 .state_i ( state_d ),
750.41 .state_o ( state_q )
750.42 );
750.43 `endif751
752 always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
753 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
754 1/1 error_q <= NoError;
Tests: T1 T2 T3
755 // data output is locked by default
756 1/1 dout_locked_q <= MuBi8True;
Tests: T1 T2 T3
757 end else begin
758 1/1 error_q <= error_d;
Tests: T1 T2 T3
759 1/1 dout_locked_q <= dout_locked_d;
Tests: T1 T2 T3
Line Coverage for Module :
otp_ctrl_part_buf ( parameter Info=-1,CntWidth=4,DigestOffset=1952,StateWidth=12 )
Line Coverage for Module self-instances :
| Line No. | Total | Covered | Percent |
TOTAL | | 160 | 147 | 91.88 |
CONT_ASSIGN | 182 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
ALWAYS | 206 | 140 | 127 | 90.71 |
CONT_ASSIGN | 636 | 1 | 1 | 100.00 |
CONT_ASSIGN | 641 | 1 | 1 | 100.00 |
CONT_ASSIGN | 642 | 1 | 1 | 100.00 |
CONT_ASSIGN | 646 | 1 | 1 | 100.00 |
CONT_ASSIGN | 652 | 1 | 1 | 100.00 |
CONT_ASSIGN | 675 | 1 | 1 | 100.00 |
CONT_ASSIGN | 678 | 1 | 1 | 100.00 |
CONT_ASSIGN | 680 | 1 | 1 | 100.00 |
CONT_ASSIGN | 709 | 1 | 1 | 100.00 |
CONT_ASSIGN | 729 | 1 | 1 | 100.00 |
ALWAYS | 750 | 3 | 3 | 100.00 |
ALWAYS | 753 | 5 | 5 | 100.00 |
181 // Output partition error state.
182 1/1 assign error_o = error_q;
Tests: T1 T2 T3
183
184 // This partition cannot do any write accesses, hence we tie this
185 // constantly off.
186 assign otp_wdata_o = '0;
187 // Depending on the partition configuration, the wrapper is instructed to ignore integrity
188 // calculations and checks. To be on the safe side, the partition filters error responses at this
189 // point and does not report any integrity errors if integrity is disabled.
190 otp_err_e otp_err;
191 if (Info.integrity) begin : gen_integrity
192 assign otp_cmd_o = prim_otp_pkg::Read;
193 1/1 assign otp_err = otp_err_e'(otp_err_i);
Tests: T1 T2 T3
194 end else begin : gen_no_integrity
195 assign otp_cmd_o = prim_otp_pkg::ReadRaw;
196 always_comb begin
197 if (otp_err_e'(otp_err_i) inside {MacroEccCorrError, MacroEccUncorrError}) begin
198 otp_err = NoError;
199 end else begin
200 otp_err = otp_err_e'(otp_err_i);
201 end
202 end
203 end
204
205 always_comb begin : p_fsm
206 1/1 state_d = state_q;
Tests: T1 T2 T3
207
208 // Redundantly encoded lock signal for buffer regs.
209 1/1 dout_locked_d = dout_locked_q;
Tests: T1 T2 T3
210
211 // OTP signals
212 1/1 otp_req_o = 1'b0;
Tests: T1 T2 T3
213
214 // Scrambling mutex
215 1/1 scrmbl_mtx_req_o = 1'b0;
Tests: T1 T2 T3
216
217 // Scrambling datapath
218 1/1 scrmbl_cmd_o = LoadShadow;
Tests: T1 T2 T3
219 1/1 scrmbl_sel_o = CnstyDigest;
Tests: T1 T2 T3
220 1/1 scrmbl_mode_o = StandardMode;
Tests: T1 T2 T3
221 1/1 scrmbl_valid_o = 1'b0;
Tests: T1 T2 T3
222
223 // Counter
224 1/1 cnt_en = 1'b0;
Tests: T1 T2 T3
225 1/1 cnt_clr = 1'b0;
Tests: T1 T2 T3
226 1/1 base_sel = PartOffset;
Tests: T1 T2 T3
227
228 // Buffer register
229 1/1 buffer_reg_en = 1'b0;
Tests: T1 T2 T3
230 1/1 data_sel = OtpData;
Tests: T1 T2 T3
231
232 // Error Register
233 1/1 error_d = error_q;
Tests: T1 T2 T3
234 1/1 fsm_err_o = 1'b0;
Tests: T1 T2 T3
235
236 // Integrity/Consistency check responses
237 1/1 cnsty_chk_ack_o = 1'b0;
Tests: T1 T2 T3
238 1/1 integ_chk_ack_o = 1'b0;
Tests: T1 T2 T3
239
240 1/1 unique case (state_q)
Tests: T1 T2 T3
241 ///////////////////////////////////////////////////////////////////
242 // State right after reset. Wait here until we get a an
243 // initialization request.
244 ResetSt: begin
245 1/1 if (init_req_i) begin
Tests: T1 T2 T3
246 1/1 state_d = InitSt;
Tests: T1 T2 T3
247 end
MISSING_ELSE
248 end
249 ///////////////////////////////////////////////////////////////////
250 // Initialization reads out the digest only in unbuffered
251 // partitions. Wait here until the OTP request has been granted.
252 // And then wait until the OTP word comes back.
253 InitSt: begin
254 1/1 otp_req_o = 1'b1;
Tests: T1 T2 T3
255 1/1 if (otp_gnt_i) begin
Tests: T1 T2 T3
256 1/1 state_d = InitWaitSt;
Tests: T1 T2 T3
257 end
MISSING_ELSE
258 end
259 ///////////////////////////////////////////////////////////////////
260 // Wait for OTP response and write to buffer register, then go to
261 // descrambling state. In case an OTP transaction fails, latch the
262 // OTP error code and jump to a
263 // terminal error state.
264 InitWaitSt: begin
265 1/1 if (otp_rvalid_i) begin
Tests: T1 T2 T3
266 1/1 buffer_reg_en = 1'b1;
Tests: T1 T2 T3
267 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin
Tests: T1 T2 T3
268 // Once we've read and descrambled the whole partition, we can go to integrity
269 // verification. Note that the last block is the digest value, which does not
270 // have to be descrambled.
271 1/1 if (cnt == LastScrmblBlock) begin
Tests: T1 T2 T3
272 1/1 state_d = IntegDigClrSt;
Tests: T1 T2 T3
273 // Only need to descramble if this is a scrambled partition.
274 // Otherwise, we can just go back to InitSt and read the next block.
275 1/1 end else if (Info.secret) begin
Tests: T1 T2 T3
276 1/1 state_d = InitDescrSt;
Tests: T1 T2 T3
277 end else begin
278 unreachable state_d = InitSt;
279 unreachable cnt_en = 1'b1;
280 end
281 // At this point the only error that we could have gotten are correctable ECC errors.
282 1/1 if (otp_err != NoError) begin
Tests: T1 T2 T3
283 1/1 error_d = MacroEccCorrError;
Tests: T72 T73 T74
284 end
MISSING_ELSE
285 end else begin
286 1/1 state_d = ErrorSt;
Tests: T61 T28 T30
287 1/1 error_d = otp_err;
Tests: T61 T28 T30
288 end
289 end
MISSING_ELSE
290 end
291 ///////////////////////////////////////////////////////////////////
292 // Descrambling state. This first acquires the scrambling
293 // datapath mutex. Note that once the mutex is acquired, we have
294 // exclusive access to the scrambling datapath until we release
295 // the mutex by deasserting scrmbl_mtx_req_o.
296 // SEC_CM: SECRET.MEM.SCRAMBLE
297 InitDescrSt: begin
298 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
299 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
300 1/1 scrmbl_cmd_o = Decrypt;
Tests: T1 T2 T3
301 1/1 scrmbl_sel_o = Info.key_sel;
Tests: T1 T2 T3
302 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
Tests: T1 T2 T3
303 1/1 state_d = InitDescrWaitSt;
Tests: T1 T2 T3
304 end
MISSING_ELSE
305 end
306 ///////////////////////////////////////////////////////////////////
307 // Wait for the descrambled data to return. Note that we release
308 // the mutex lock upon leaving this state.
309 // SEC_CM: SECRET.MEM.SCRAMBLE
310 InitDescrWaitSt: begin
311 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
312 1/1 scrmbl_sel_o = Info.key_sel;
Tests: T1 T2 T3
313 1/1 data_sel = ScrmblData;
Tests: T1 T2 T3
314 1/1 if (scrmbl_valid_i) begin
Tests: T1 T2 T3
315 1/1 state_d = InitSt;
Tests: T1 T2 T3
316 1/1 buffer_reg_en = 1'b1;
Tests: T1 T2 T3
317 1/1 cnt_en = 1'b1;
Tests: T1 T2 T3
318 end
MISSING_ELSE
319 end
320 ///////////////////////////////////////////////////////////////////
321 // Idle state. We basically wait for integrity and consistency check
322 // triggers in this state.
323 IdleSt: begin
324 1/1 if (integ_chk_req_i) begin
Tests: T1 T2 T3
325 1/1 if (Info.hw_digest) begin
Tests: T3 T5 T24
326 1/1 state_d = IntegDigClrSt;
Tests: T3 T5 T24
327 // In case there is nothing to check we can just
328 // acknowledge the request right away, without going to the
329 // integrity check.
330 end else begin
331 unreachable integ_chk_ack_o = 1'b1;
332 end
333 1/1 end else if (cnsty_chk_req_i) begin
Tests: T1 T2 T3
334 1/1 state_d = CnstyReadSt;
Tests: T4 T6 T5
335 1/1 cnt_clr = 1'b1;
Tests: T4 T6 T5
336 end
MISSING_ELSE
337 end
338 ///////////////////////////////////////////////////////////////////
339 // Read the digest. Wait here until the OTP request has been granted.
340 // And then wait until the OTP word comes back.
341 // SEC_CM: PART.DATA_REG.BKGN_CHK
342 CnstyReadSt: begin
343 1/1 otp_req_o = 1'b1;
Tests: T4 T6 T5
344 // In case this partition has a hardware digest, we only have to read
345 // and compare the digest value. In that case we select the digest offset here.
346 // Otherwise we have to read and compare the whole partition, in which case we
347 // select the partition offset, which is the default assignment of base_sel.
348 1/1 if (Info.hw_digest) begin
Tests: T4 T6 T5
349 1/1 base_sel = DigOffset;
Tests: T4 T6 T5
350 end
==> MISSING_ELSE
351 1/1 if (otp_gnt_i) begin
Tests: T4 T6 T5
352 1/1 state_d = CnstyReadWaitSt;
Tests: T6 T5 T24
353 end
MISSING_ELSE
354 end
355 ///////////////////////////////////////////////////////////////////
356 // Wait for OTP response and compare the digest. In case there is
357 // a mismatch, lock down the partition and go into the terminal error
358 // state. In case an OTP transaction fails, latch the OTP error code
359 // and jump to a terminal error state.
360 // SEC_CM: PART.DATA_REG.BKGN_CHK
361 CnstyReadWaitSt: begin
362 1/1 if (otp_rvalid_i) begin
Tests: T6 T5 T24
363 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin
Tests: T6 T5 T24
364 // Check whether we need to compare the digest or the full partition
365 // contents here.
366 1/1 if (Info.hw_digest) begin
Tests: T6 T5 T24
367 // Note that we ignore this check if the digest is still blank.
368 1/1 if (digest_o == data_mux || digest_o == '0) begin
Tests: T6 T5 T24
369 1/1 state_d = IdleSt;
Tests: T6 T5 T24
370 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T6 T5 T24
371 // Error out and lock the partition if this check fails.
372 end else begin
373 0/1 ==> state_d = ErrorSt;
374 0/1 ==> error_d = CheckFailError;
375 // The check has finished and found an error.
376 0/1 ==> cnsty_chk_ack_o = 1'b1;
377 end
378 end else begin
379 // Check whether the read data corresponds with the data buffered in regs.
380 // Note that this particular check can be bypassed in case a transition is ongoing.
381 unreachable if (scrmbl_data_o == data_mux ||
382 lc_ctrl_pkg::lc_tx_test_true_strict(check_byp_en_i)) begin
383 // Can go back to idle and acknowledge the
384 // request if this is the last block.
385 unreachable if (cnt == LastScrmblBlock) begin
386 unreachable state_d = IdleSt;
387 unreachable cnsty_chk_ack_o = 1'b1;
388 // Need to go back and read out more blocks.
389 end else begin
390 unreachable state_d = CnstyReadSt;
391 unreachable cnt_en = 1'b1;
392 end
393 end else begin
394 unreachable state_d = ErrorSt;
395 unreachable error_d = CheckFailError;
396 // The check has finished and found an error.
397 unreachable cnsty_chk_ack_o = 1'b1;
398 end
399 end
400 // At this point the only error that we could have gotten are correctable ECC errors.
401 1/1 if (otp_err != NoError) begin
Tests: T6 T5 T24
402 1/1 error_d = MacroEccCorrError;
Tests: T48 T75
403 end
MISSING_ELSE
404 end else begin
405 1/1 state_d = ErrorSt;
Tests: T36 T76 T77
406 1/1 error_d = otp_err;
Tests: T36 T76 T77
407 // The check has finished and found an error.
408 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T36 T76 T77
409 end
410 end
MISSING_ELSE
411 end
412 ///////////////////////////////////////////////////////////////////
413 // First, acquire the mutex for the digest and clear the digest state.
414 // SEC_CM: PART.DATA_REG.BKGN_CHK
415 IntegDigClrSt: begin
416 // Check whether this partition requires checking at all.
417 1/1 if (Info.hw_digest) begin
Tests: T1 T2 T3
418 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
419 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
420 1/1 cnt_clr = 1'b1;
Tests: T1 T2 T3
421 // Need to reset the digest state and set it to chained
422 // mode if this partition is scrambled.
423 1/1 scrmbl_cmd_o = DigestInit;
Tests: T1 T2 T3
424 1/1 if (Info.secret) begin
Tests: T1 T2 T3
425 1/1 scrmbl_mode_o = ChainedMode;
Tests: T1 T2 T3
426 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
Tests: T1 T2 T3
427 1/1 state_d = IntegScrSt;
Tests: T1 T2 T3
428 end
MISSING_ELSE
429 // If this partition is not scrambled, we can just directly
430 // jump to the digest state.
431 end else begin
432 unreachable scrmbl_mode_o = StandardMode;
433 unreachable if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
434 unreachable state_d = IntegDigSt;
435 end
==> MISSING_ELSE
436 end
437 // Otherwise, if this partition is not digest protected,
438 // we can just go to idle, since there is nothing to check.
439 // Note that we do not come back to this state in case there is no
440 // digest, and hence it is safe to unlock the buffer regs at this point.
441 // This is the only way the buffer regs can get unlocked.
442 end else begin
443 unreachable state_d = IdleSt;
444 unreachable if (mubi8_test_true_strict(dout_locked_q)) begin
445 unreachable dout_locked_d = MuBi8False;
446 end
==> MISSING_ELSE
447 end
448 end
449 ///////////////////////////////////////////////////////////////////
450 // Scramble buffered data (which is held in plaintext form).
451 // This moves the previous scrambling result into the shadow reg
452 // for later use.
453 // SEC_CM: PART.DATA_REG.BKGN_CHK
454 IntegScrSt: begin
455 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
456 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
457 1/1 scrmbl_cmd_o = Encrypt;
Tests: T1 T2 T3
458 1/1 scrmbl_sel_o = Info.key_sel;
Tests: T1 T2 T3
459 1/1 if (scrmbl_ready_i) begin
Tests: T1 T2 T3
460 1/1 state_d = IntegScrWaitSt;
Tests: T1 T2 T3
461 end
MISSING_ELSE
462 end
463 ///////////////////////////////////////////////////////////////////
464 // Wait for the scrambled data to return.
465 // SEC_CM: PART.DATA_REG.BKGN_CHK
466 IntegScrWaitSt: begin
467 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
468 1/1 scrmbl_sel_o = Info.key_sel;
Tests: T1 T2 T3
469 1/1 if (scrmbl_valid_i) begin
Tests: T1 T2 T3
470 1/1 state_d = IntegDigSt;
Tests: T1 T2 T3
471 end
MISSING_ELSE
472 end
473 ///////////////////////////////////////////////////////////////////
474 // Push the word read into the scrambling datapath. The last
475 // block is repeated in case the number blocks in this partition
476 // is odd.
477 // SEC_CM: PART.MEM.DIGEST
478 // SEC_CM: PART.DATA_REG.BKGN_CHK
479 IntegDigSt: begin
480 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
481 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
482 1/1 if (scrmbl_ready_i) begin
Tests: T1 T2 T3
483 1/1 cnt_en = 1'b1;
Tests: T1 T2 T3
484 // No need to digest the digest value itself
485 1/1 if (cnt == PenultimateScrmblBlock) begin
Tests: T1 T2 T3
486 // Note that the digest operates on 128bit blocks since the data is fed in via the
487 // PRESENT key input. Therefore, we only trigger a digest update on every second
488 // 64bit block that is pushed into the scrambling datapath.
489 1/1 if (cnt[0]) begin
Tests: T1 T2 T3
490 1/1 scrmbl_cmd_o = Digest;
Tests: T1 T2 T3
491 1/1 state_d = IntegDigFinSt;
Tests: T1 T2 T3
492 end else begin
493 0/1 ==> state_d = IntegDigPadSt;
494 0/1 ==> cnt_en = 1'b0;
495 end
496 end else begin
497 // Trigger digest round in case this is the second block in a row.
498 1/1 if (cnt[0]) begin
Tests: T1 T2 T3
499 1/1 scrmbl_cmd_o = Digest;
Tests: T1 T2 T3
500 end
MISSING_ELSE
501 // Go back and scramble the next data block if this is
502 // a scrambled partition. Otherwise just stay here.
503 1/1 if (Info.secret) begin
Tests: T1 T2 T3
504 1/1 state_d = IntegScrSt;
Tests: T1 T2 T3
505 end
==> MISSING_ELSE
506 end
507 end
==> MISSING_ELSE
508 end
509 ///////////////////////////////////////////////////////////////////
510 // Padding state. When we get here, we've copied the last encryption
511 // result into the shadow register such that we've effectively
512 // repeated the last block twice in order to pad the data to 128bit.
513 // SEC_CM: PART.MEM.DIGEST
514 // SEC_CM: PART.DATA_REG.BKGN_CHK
515 IntegDigPadSt: begin
516 0/1 ==> scrmbl_mtx_req_o = 1'b1;
517 0/1 ==> scrmbl_valid_o = 1'b1;
518 0/1 ==> scrmbl_cmd_o = Digest;
519 0/1 ==> if (scrmbl_ready_i) begin
520 0/1 ==> state_d = IntegDigFinSt;
521 end
==> MISSING_ELSE
522 end
523 ///////////////////////////////////////////////////////////////////
524 // Trigger digest finalization and go wait for the result.
525 // SEC_CM: PART.MEM.DIGEST
526 // SEC_CM: PART.DATA_REG.BKGN_CHK
527 IntegDigFinSt: begin
528 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
529 1/1 scrmbl_valid_o = 1'b1;
Tests: T1 T2 T3
530 1/1 scrmbl_cmd_o = DigestFinalize;
Tests: T1 T2 T3
531 1/1 if (scrmbl_ready_i) begin
Tests: T1 T2 T3
532 1/1 state_d = IntegDigWaitSt;
Tests: T1 T2 T3
533 end
MISSING_ELSE
534 end
535 ///////////////////////////////////////////////////////////////////
536 // Wait for the digest to return, and double check whether the digest
537 // matches. If yes, unlock the partition. Otherwise, go into the terminal
538 // error state, where the partition will be locked down.
539 // SEC_CM: PART.MEM.DIGEST
540 // SEC_CM: PART.DATA_REG.BKGN_CHK
541 IntegDigWaitSt: begin
542 1/1 scrmbl_mtx_req_o = 1'b1;
Tests: T1 T2 T3
543 1/1 data_sel = ScrmblData;
Tests: T1 T2 T3
544 1/1 if (scrmbl_valid_i) begin
Tests: T1 T2 T3
545 // This is the only way the buffer regs can get unlocked.
546 // Note that we ignore this check if the digest is still blank.
547 1/1 if (digest_o == data_mux || digest_o == '0) begin
Tests: T1 T2 T3
548 1/1 state_d = IdleSt;
Tests: T1 T2 T3
549 // If the partition is still locked, this is the first integrity check after
550 // initialization. This is the only way the buffer regs can get unlocked.
551 1/1 if (mubi8_test_true_strict(dout_locked_q)) begin
Tests: T1 T2 T3
552 1/1 dout_locked_d = MuBi8False;
Tests: T1 T2 T3
553 // Otherwise, this integrity check has requested by the LFSR timer, and we have
554 // to acknowledge its completion.
555 end else begin
556 1/1 integ_chk_ack_o = 1'b1;
Tests: T3 T5 T24
557 end
558 // Error out and lock the partition if this check fails.
559 end else begin
560 1/1 state_d = ErrorSt;
Tests: T78
561 1/1 error_d = CheckFailError;
Tests: T78
562 // The check has finished and found an error.
563 1/1 integ_chk_ack_o = 1'b1;
Tests: T78
564 end
565 end
MISSING_ELSE
566 end
567 ///////////////////////////////////////////////////////////////////
568 // Terminal Error State. This locks access to the partition.
569 // Make sure the partition signals an error state if no error
570 // code has been latched so far, and lock the buffer regs down.
571 ErrorSt: begin
572 1/1 dout_locked_d = MuBi8True;
Tests: T2 T4 T6
573 1/1 if (error_q == NoError) begin
Tests: T2 T4 T6
574 1/1 error_d = FsmStateError;
Tests: T19 T20 T21
575 end
MISSING_ELSE
576 // If we are in error state, we cannot execute the checks anymore.
577 // Hence the acknowledgements are returned immediately.
578 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T2 T4 T6
579 1/1 integ_chk_ack_o = 1'b1;
Tests: T2 T4 T6
580 end
581 ///////////////////////////////////////////////////////////////////
582 // We should never get here. If we do (e.g. via a malicious
583 // glitch), error out immediately.
584 default: begin
585 state_d = ErrorSt;
586 fsm_err_o = 1'b1;
587 end
588 ///////////////////////////////////////////////////////////////////
589 endcase // state_q
590
591
592 // Unconditionally jump into the terminal error state in case of
593 // an ECC error or escalation, and lock access to the partition down.
594 // SEC_CM: PART.FSM.LOCAL_ESC
595 1/1 if (ecc_err) begin
Tests: T1 T2 T3
596 0/1 ==> state_d = ErrorSt;
597 0/1 ==> if (state_q != ErrorSt) begin
598 0/1 ==> error_d = CheckFailError;
599 end
==> MISSING_ELSE
600 end
MISSING_ELSE
601 // SEC_CM: PART.FSM.LOCAL_ESC, PART.FSM.GLOBAL_ESC
602 1/1 if (lc_ctrl_pkg::lc_tx_test_true_loose(escalate_en_i) || cnt_err) begin
Tests: T1 T2 T3
603 1/1 state_d = ErrorSt;
Tests: T2 T4 T6
604 1/1 fsm_err_o = 1'b1;
Tests: T2 T4 T6
605 1/1 if (state_q != ErrorSt) begin
Tests: T2 T4 T6
606 1/1 error_d = FsmStateError;
Tests: T2 T4 T6
607 end
MISSING_ELSE
608 end
MISSING_ELSE
609 end
610
611 ////////////////////////////
612 // Address Calc and Muxes //
613 ////////////////////////////
614
615 // Address counter - this is only used for computing a digest, hence the increment is
616 // fixed to 8 byte.
617 // SEC_CM: PART.CTR.REDUN
618 prim_count #(
619 .Width(CntWidth)
620 ) u_prim_count (
621 .clk_i,
622 .rst_ni,
623 .clr_i(cnt_clr),
624 .set_i(1'b0),
625 .set_cnt_i('0),
626 .incr_en_i(cnt_en),
627 .decr_en_i(1'b0),
628 .step_i(CntWidth'(1)),
629 .commit_i(1'b1),
630 .cnt_o(cnt),
631 .cnt_after_commit_o(),
632 .err_o(cnt_err)
633 );
634
635 logic [OtpByteAddrWidth-1:0] addr_base;
636 1/1 assign addr_base = (base_sel == DigOffset) ? DigestOffset : Info.offset;
Tests: T1 T2 T3
637
638 // Note that OTP works on halfword (16bit) addresses, hence need to
639 // shift the addresses appropriately.
640 logic [OtpByteAddrWidth-1:0] addr_calc;
641 1/1 assign addr_calc = OtpByteAddrWidth'({cnt, {$clog2(ScrmblBlockWidth/8){1'b0}}}) + addr_base;
Tests: T1 T2 T3
642 1/1 assign otp_addr_o = addr_calc[OtpByteAddrWidth-1:OtpAddrShift];
Tests: T1 T2 T3
643
644 if (OtpAddrShift > 0) begin : gen_unused
645 logic unused_bits;
646 1/1 assign unused_bits = ^addr_calc[OtpAddrShift-1:0];
Tests: T1 T2 T3
647 end
648
649 // Always transfer 64bit blocks.
650 assign otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth) - 1);
651
652 1/1 assign data_mux = (data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i;
Tests: T1 T2 T3
653
654 /////////////////
655 // Buffer Regs //
656 /////////////////
657
658 // SEC_CM: PART.DATA_REG.INTEGRITY
659 logic [Info.size*8-1:0] data;
660 otp_ctrl_ecc_reg #(
661 .Width ( ScrmblBlockWidth ),
662 .Depth ( NumScrmblBlocks )
663 ) u_otp_ctrl_ecc_reg (
664 .clk_i,
665 .rst_ni,
666 .wren_i ( buffer_reg_en ),
667 .addr_i ( cnt ),
668 .wdata_i ( data_mux ),
669 .rdata_o ( scrmbl_data_o ),
670 .data_o ( data ),
671 .ecc_err_o ( ecc_err )
672 );
673
674 // We have successfully initialized the partition once it has been unlocked.
675 1/1 assign init_done_o = mubi8_test_false_strict(dout_locked_q);
Tests: T1 T2 T3
676 // Hardware output gating.
677 // Note that this is decoupled from the DAI access rules further below.
678 1/1 assign data_o = (init_done_o) ? data : DataDefault;
Tests: T1 T2 T3
679 // The digest does not have to be gated.
680 1/1 assign digest_o = data[$high(data_o) -: ScrmblBlockWidth];
Tests: T1 T2 T3
681
682 ////////////////////////
683 // DAI Access Control //
684 ////////////////////////
685
686 // Aggregate all possible DAI write /readlocks. The partition is also locked when uninitialized.
687 // Note that the locks are redundantly encoded values.
688 part_access_t access_pre;
689 prim_mubi8_sender #(
690 .AsyncOn(0)
691 ) u_prim_mubi8_sender_write_lock_pre (
692 .clk_i,
693 .rst_ni,
694 .mubi_i(mubi8_and_lo(dout_locked_q, access_i.write_lock)),
695 .mubi_o(access_pre.write_lock)
696 );
697 prim_mubi8_sender #(
698 .AsyncOn(0)
699 ) u_prim_mubi8_sender_read_lock_pre (
700 .clk_i,
701 .rst_ni,
702 .mubi_i(mubi8_and_lo(dout_locked_q, access_i.read_lock)),
703 .mubi_o(access_pre.read_lock)
704 );
705
706 // SEC_CM: PART.MEM.SW_UNWRITABLE
707 if (Info.write_lock) begin : gen_digest_write_lock
708 mubi8_t digest_locked;
709 1/1 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False;
Tests: T1 T2 T3
710
711 // This prevents the synthesis tool from optimizing the multibit signal.
712 prim_mubi8_sender #(
713 .AsyncOn(0)
714 ) u_prim_mubi8_sender_write_lock (
715 .clk_i,
716 .rst_ni,
717 .mubi_i(mubi8_and_lo(access_pre.write_lock, digest_locked)),
718 .mubi_o(access_o.write_lock)
719 );
720
721 `ASSERT(DigestWriteLocksPartition_A, digest_o |-> mubi8_test_true_loose(access_o.write_lock))
722 end else begin : gen_no_digest_write_lock
723 assign access_o.write_lock = access_pre.write_lock;
724 end
725
726 // SEC_CM: PART.MEM.SW_UNREADABLE
727 if (Info.read_lock) begin : gen_digest_read_lock
728 mubi8_t digest_locked;
729 1/1 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False;
Tests: T1 T2 T3
730
731 // This prevents the synthesis tool from optimizing the multibit signal.
732 prim_mubi8_sender #(
733 .AsyncOn(0)
734 ) u_prim_mubi8_sender_read_lock (
735 .clk_i,
736 .rst_ni,
737 .mubi_i(mubi8_and_lo(access_pre.read_lock, digest_locked)),
738 .mubi_o(access_o.read_lock)
739 );
740
741 `ASSERT(DigestReadLocksPartition_A, digest_o |-> mubi8_test_true_loose(access_o.read_lock))
742 end else begin : gen_no_digest_read_lock
743 assign access_o.read_lock = access_pre.read_lock;
744 end
745
746 ///////////////
747 // Registers //
748 ///////////////
749
750 3/3 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt)
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3
PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt):
750.1 `ifdef SIMULATION
750.2 prim_sparse_fsm_flop #(
750.3 .StateEnumT(state_e),
750.4 .Width($bits(state_e)),
750.5 .ResetValue($bits(state_e)'(ResetSt)),
750.6 .EnableAlertTriggerSVA(1),
750.7 .CustomForceName("state_q")
750.8 ) u_state_regs (
750.9 .clk_i ( clk_i ),
750.10 .rst_ni ( rst_ni ),
750.11 .state_i ( state_d ),
750.12 .state_o ( )
750.13 );
750.14 always_ff @(posedge clk_i or negedge rst_ni) begin
750.15 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
750.16 1/1 state_q <= ResetSt;
Tests: T1 T2 T3
750.17 end else begin
750.18 1/1 state_q <= state_d;
Tests: T1 T2 T3
750.19 end
750.20 end
750.21 u_state_regs_A: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (state_q === u_state_regs.state_o))
750.22 else begin
750.23 `ifdef UVM
750.24 uvm_pkg::uvm_report_error("ASSERT FAILED", "u_state_regs_A", uvm_pkg::UVM_NONE,
750.25 "../src/lowrisc_ip_otp_ctrl_1.0/rtl/otp_ctrl_part_buf.sv", 750, "", 1);
750.26 `else
750.27 $error("%0t: (%0s:%0d) [%m] [ASSERT FAILED] %0s", $time, `__FILE__, `__LINE__,
750.28 `PRIM_STRINGIFY(u_state_regs_A));
750.29 `endif
750.30 end
750.31 `else
750.32 prim_sparse_fsm_flop #(
750.33 .StateEnumT(state_e),
750.34 .Width($bits(state_e)),
750.35 .ResetValue($bits(state_e)'(ResetSt)),
750.36 .EnableAlertTriggerSVA(1)
750.37 ) u_state_regs (
750.38 .clk_i ( `PRIM_FLOP_CLK ),
750.39 .rst_ni ( `PRIM_FLOP_RST ),
750.40 .state_i ( state_d ),
750.41 .state_o ( state_q )
750.42 );
750.43 `endif751
752 always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
753 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
754 1/1 error_q <= NoError;
Tests: T1 T2 T3
755 // data output is locked by default
756 1/1 dout_locked_q <= MuBi8True;
Tests: T1 T2 T3
757 end else begin
758 1/1 error_q <= error_d;
Tests: T1 T2 T3
759 1/1 dout_locked_q <= dout_locked_d;
Tests: T1 T2 T3
Line Coverage for Module :
otp_ctrl_part_buf ( parameter Info=-1,CntWidth=4,DigestOffset=2040,StateWidth=12 )
Line Coverage for Module self-instances :
| Line No. | Total | Covered | Percent |
TOTAL | | 131 | 93 | 70.99 |
CONT_ASSIGN | 182 | 1 | 1 | 100.00 |
CONT_ASSIGN | 193 | 1 | 1 | 100.00 |
ALWAYS | 206 | 111 | 76 | 68.47 |
CONT_ASSIGN | 636 | 1 | 0 | 0.00 |
CONT_ASSIGN | 641 | 1 | 1 | 100.00 |
CONT_ASSIGN | 642 | 1 | 1 | 100.00 |
CONT_ASSIGN | 646 | 1 | 1 | 100.00 |
CONT_ASSIGN | 652 | 1 | 1 | 100.00 |
CONT_ASSIGN | 675 | 1 | 1 | 100.00 |
CONT_ASSIGN | 678 | 1 | 1 | 100.00 |
CONT_ASSIGN | 680 | 1 | 1 | 100.00 |
CONT_ASSIGN | 723 | 1 | 0 | 0.00 |
CONT_ASSIGN | 743 | 1 | 0 | 0.00 |
ALWAYS | 750 | 3 | 3 | 100.00 |
ALWAYS | 753 | 5 | 5 | 100.00 |
181 // Output partition error state.
182 1/1 assign error_o = error_q;
Tests: T1 T2 T3
183
184 // This partition cannot do any write accesses, hence we tie this
185 // constantly off.
186 assign otp_wdata_o = '0;
187 // Depending on the partition configuration, the wrapper is instructed to ignore integrity
188 // calculations and checks. To be on the safe side, the partition filters error responses at this
189 // point and does not report any integrity errors if integrity is disabled.
190 otp_err_e otp_err;
191 if (Info.integrity) begin : gen_integrity
192 assign otp_cmd_o = prim_otp_pkg::Read;
193 1/1 assign otp_err = otp_err_e'(otp_err_i);
Tests: T1 T2 T3
194 end else begin : gen_no_integrity
195 assign otp_cmd_o = prim_otp_pkg::ReadRaw;
196 always_comb begin
197 if (otp_err_e'(otp_err_i) inside {MacroEccCorrError, MacroEccUncorrError}) begin
198 otp_err = NoError;
199 end else begin
200 otp_err = otp_err_e'(otp_err_i);
201 end
202 end
203 end
204
205 always_comb begin : p_fsm
206 1/1 state_d = state_q;
Tests: T1 T2 T3
207
208 // Redundantly encoded lock signal for buffer regs.
209 1/1 dout_locked_d = dout_locked_q;
Tests: T1 T2 T3
210
211 // OTP signals
212 1/1 otp_req_o = 1'b0;
Tests: T1 T2 T3
213
214 // Scrambling mutex
215 1/1 scrmbl_mtx_req_o = 1'b0;
Tests: T1 T2 T3
216
217 // Scrambling datapath
218 1/1 scrmbl_cmd_o = LoadShadow;
Tests: T1 T2 T3
219 1/1 scrmbl_sel_o = CnstyDigest;
Tests: T1 T2 T3
220 1/1 scrmbl_mode_o = StandardMode;
Tests: T1 T2 T3
221 1/1 scrmbl_valid_o = 1'b0;
Tests: T1 T2 T3
222
223 // Counter
224 1/1 cnt_en = 1'b0;
Tests: T1 T2 T3
225 1/1 cnt_clr = 1'b0;
Tests: T1 T2 T3
226 1/1 base_sel = PartOffset;
Tests: T1 T2 T3
227
228 // Buffer register
229 1/1 buffer_reg_en = 1'b0;
Tests: T1 T2 T3
230 1/1 data_sel = OtpData;
Tests: T1 T2 T3
231
232 // Error Register
233 1/1 error_d = error_q;
Tests: T1 T2 T3
234 1/1 fsm_err_o = 1'b0;
Tests: T1 T2 T3
235
236 // Integrity/Consistency check responses
237 1/1 cnsty_chk_ack_o = 1'b0;
Tests: T1 T2 T3
238 1/1 integ_chk_ack_o = 1'b0;
Tests: T1 T2 T3
239
240 1/1 unique case (state_q)
Tests: T1 T2 T3
241 ///////////////////////////////////////////////////////////////////
242 // State right after reset. Wait here until we get a an
243 // initialization request.
244 ResetSt: begin
245 1/1 if (init_req_i) begin
Tests: T1 T2 T3
246 1/1 state_d = InitSt;
Tests: T1 T2 T3
247 end
MISSING_ELSE
248 end
249 ///////////////////////////////////////////////////////////////////
250 // Initialization reads out the digest only in unbuffered
251 // partitions. Wait here until the OTP request has been granted.
252 // And then wait until the OTP word comes back.
253 InitSt: begin
254 1/1 otp_req_o = 1'b1;
Tests: T1 T2 T3
255 1/1 if (otp_gnt_i) begin
Tests: T1 T2 T3
256 1/1 state_d = InitWaitSt;
Tests: T1 T2 T3
257 end
MISSING_ELSE
258 end
259 ///////////////////////////////////////////////////////////////////
260 // Wait for OTP response and write to buffer register, then go to
261 // descrambling state. In case an OTP transaction fails, latch the
262 // OTP error code and jump to a
263 // terminal error state.
264 InitWaitSt: begin
265 1/1 if (otp_rvalid_i) begin
Tests: T1 T2 T3
266 1/1 buffer_reg_en = 1'b1;
Tests: T1 T2 T3
267 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin
Tests: T1 T2 T3
268 // Once we've read and descrambled the whole partition, we can go to integrity
269 // verification. Note that the last block is the digest value, which does not
270 // have to be descrambled.
271 1/1 if (cnt == LastScrmblBlock) begin
Tests: T1 T2 T3
272 1/1 state_d = IntegDigClrSt;
Tests: T1 T2 T3
273 // Only need to descramble if this is a scrambled partition.
274 // Otherwise, we can just go back to InitSt and read the next block.
275 1/1 end else if (Info.secret) begin
Tests: T1 T2 T3
276 unreachable state_d = InitDescrSt;
277 end else begin
278 1/1 state_d = InitSt;
Tests: T1 T2 T3
279 1/1 cnt_en = 1'b1;
Tests: T1 T2 T3
280 end
281 // At this point the only error that we could have gotten are correctable ECC errors.
282 1/1 if (otp_err != NoError) begin
Tests: T1 T2 T3
283 1/1 error_d = MacroEccCorrError;
Tests: T61 T33 T28
284 end
MISSING_ELSE
285 end else begin
286 1/1 state_d = ErrorSt;
Tests: T52 T53 T79
287 1/1 error_d = otp_err;
Tests: T52 T53 T79
288 end
289 end
MISSING_ELSE
290 end
291 ///////////////////////////////////////////////////////////////////
292 // Descrambling state. This first acquires the scrambling
293 // datapath mutex. Note that once the mutex is acquired, we have
294 // exclusive access to the scrambling datapath until we release
295 // the mutex by deasserting scrmbl_mtx_req_o.
296 // SEC_CM: SECRET.MEM.SCRAMBLE
297 InitDescrSt: begin
298 0/1 ==> scrmbl_mtx_req_o = 1'b1;
299 0/1 ==> scrmbl_valid_o = 1'b1;
300 0/1 ==> scrmbl_cmd_o = Decrypt;
301 0/1 ==> scrmbl_sel_o = Info.key_sel;
302 0/1 ==> if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
303 unreachable state_d = InitDescrWaitSt;
304 end
==> MISSING_ELSE
305 end
306 ///////////////////////////////////////////////////////////////////
307 // Wait for the descrambled data to return. Note that we release
308 // the mutex lock upon leaving this state.
309 // SEC_CM: SECRET.MEM.SCRAMBLE
310 InitDescrWaitSt: begin
311 0/1 ==> scrmbl_mtx_req_o = 1'b1;
312 0/1 ==> scrmbl_sel_o = Info.key_sel;
313 0/1 ==> data_sel = ScrmblData;
314 0/1 ==> if (scrmbl_valid_i) begin
315 unreachable state_d = InitSt;
316 unreachable buffer_reg_en = 1'b1;
317 unreachable cnt_en = 1'b1;
318 end
==> MISSING_ELSE
319 end
320 ///////////////////////////////////////////////////////////////////
321 // Idle state. We basically wait for integrity and consistency check
322 // triggers in this state.
323 IdleSt: begin
324 1/1 if (integ_chk_req_i) begin
Tests: T1 T2 T3
325 1/1 if (Info.hw_digest) begin
Tests: T3 T5 T24
326 unreachable state_d = IntegDigClrSt;
327 // In case there is nothing to check we can just
328 // acknowledge the request right away, without going to the
329 // integrity check.
330 end else begin
331 1/1 integ_chk_ack_o = 1'b1;
Tests: T3 T5 T24
332 end
333 1/1 end else if (cnsty_chk_req_i) begin
Tests: T1 T2 T3
334 1/1 state_d = CnstyReadSt;
Tests: T4 T6 T5
335 1/1 cnt_clr = 1'b1;
Tests: T4 T6 T5
336 end
MISSING_ELSE
337 end
338 ///////////////////////////////////////////////////////////////////
339 // Read the digest. Wait here until the OTP request has been granted.
340 // And then wait until the OTP word comes back.
341 // SEC_CM: PART.DATA_REG.BKGN_CHK
342 CnstyReadSt: begin
343 1/1 otp_req_o = 1'b1;
Tests: T4 T6 T5
344 // In case this partition has a hardware digest, we only have to read
345 // and compare the digest value. In that case we select the digest offset here.
346 // Otherwise we have to read and compare the whole partition, in which case we
347 // select the partition offset, which is the default assignment of base_sel.
348 1/1 if (Info.hw_digest) begin
Tests: T4 T6 T5
349 unreachable base_sel = DigOffset;
350 end
MISSING_ELSE
351 1/1 if (otp_gnt_i) begin
Tests: T4 T6 T5
352 1/1 state_d = CnstyReadWaitSt;
Tests: T4 T6 T5
353 end
MISSING_ELSE
354 end
355 ///////////////////////////////////////////////////////////////////
356 // Wait for OTP response and compare the digest. In case there is
357 // a mismatch, lock down the partition and go into the terminal error
358 // state. In case an OTP transaction fails, latch the OTP error code
359 // and jump to a terminal error state.
360 // SEC_CM: PART.DATA_REG.BKGN_CHK
361 CnstyReadWaitSt: begin
362 1/1 if (otp_rvalid_i) begin
Tests: T4 T6 T5
363 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin
Tests: T4 T6 T5
364 // Check whether we need to compare the digest or the full partition
365 // contents here.
366 1/1 if (Info.hw_digest) begin
Tests: T4 T6 T5
367 // Note that we ignore this check if the digest is still blank.
368 unreachable if (digest_o == data_mux || digest_o == '0) begin
369 unreachable state_d = IdleSt;
370 unreachable cnsty_chk_ack_o = 1'b1;
371 // Error out and lock the partition if this check fails.
372 end else begin
373 unreachable state_d = ErrorSt;
374 unreachable error_d = CheckFailError;
375 // The check has finished and found an error.
376 unreachable cnsty_chk_ack_o = 1'b1;
377 end
378 end else begin
379 // Check whether the read data corresponds with the data buffered in regs.
380 // Note that this particular check can be bypassed in case a transition is ongoing.
381 1/1 if (scrmbl_data_o == data_mux ||
Tests: T4 T6 T5
382 lc_ctrl_pkg::lc_tx_test_true_strict(check_byp_en_i)) begin
383 // Can go back to idle and acknowledge the
384 // request if this is the last block.
385 1/1 if (cnt == LastScrmblBlock) begin
Tests: T4 T6 T5
386 1/1 state_d = IdleSt;
Tests: T6 T5 T24
387 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T6 T5 T24
388 // Need to go back and read out more blocks.
389 end else begin
390 1/1 state_d = CnstyReadSt;
Tests: T4 T6 T5
391 1/1 cnt_en = 1'b1;
Tests: T4 T6 T5
392 end
393 end else begin
394 1/1 state_d = ErrorSt;
Tests: T72 T80 T81
395 1/1 error_d = CheckFailError;
Tests: T72 T80 T81
396 // The check has finished and found an error.
397 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T72 T80 T81
398 end
399 end
400 // At this point the only error that we could have gotten are correctable ECC errors.
401 1/1 if (otp_err != NoError) begin
Tests: T4 T6 T5
402 0/1 ==> error_d = MacroEccCorrError;
403 end
MISSING_ELSE
404 end else begin
405 1/1 state_d = ErrorSt;
Tests: T82 T83
406 1/1 error_d = otp_err;
Tests: T82 T83
407 // The check has finished and found an error.
408 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T82 T83
409 end
410 end
MISSING_ELSE
411 end
412 ///////////////////////////////////////////////////////////////////
413 // First, acquire the mutex for the digest and clear the digest state.
414 // SEC_CM: PART.DATA_REG.BKGN_CHK
415 IntegDigClrSt: begin
416 // Check whether this partition requires checking at all.
417 1/1 if (Info.hw_digest) begin
Tests: T1 T2 T3
418 unreachable scrmbl_mtx_req_o = 1'b1;
419 unreachable scrmbl_valid_o = 1'b1;
420 unreachable cnt_clr = 1'b1;
421 // Need to reset the digest state and set it to chained
422 // mode if this partition is scrambled.
423 unreachable scrmbl_cmd_o = DigestInit;
424 unreachable if (Info.secret) begin
425 unreachable scrmbl_mode_o = ChainedMode;
426 unreachable if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
427 unreachable state_d = IntegScrSt;
428 end
==> MISSING_ELSE
429 // If this partition is not scrambled, we can just directly
430 // jump to the digest state.
431 end else begin
432 unreachable scrmbl_mode_o = StandardMode;
433 unreachable if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
434 unreachable state_d = IntegDigSt;
435 end
==> MISSING_ELSE
436 end
437 // Otherwise, if this partition is not digest protected,
438 // we can just go to idle, since there is nothing to check.
439 // Note that we do not come back to this state in case there is no
440 // digest, and hence it is safe to unlock the buffer regs at this point.
441 // This is the only way the buffer regs can get unlocked.
442 end else begin
443 1/1 state_d = IdleSt;
Tests: T1 T2 T3
444 1/1 if (mubi8_test_true_strict(dout_locked_q)) begin
Tests: T1 T2 T3
445 1/1 dout_locked_d = MuBi8False;
Tests: T1 T2 T3
446 end
==> MISSING_ELSE
447 end
448 end
449 ///////////////////////////////////////////////////////////////////
450 // Scramble buffered data (which is held in plaintext form).
451 // This moves the previous scrambling result into the shadow reg
452 // for later use.
453 // SEC_CM: PART.DATA_REG.BKGN_CHK
454 IntegScrSt: begin
455 0/1 ==> scrmbl_mtx_req_o = 1'b1;
456 0/1 ==> scrmbl_valid_o = 1'b1;
457 0/1 ==> scrmbl_cmd_o = Encrypt;
458 0/1 ==> scrmbl_sel_o = Info.key_sel;
459 0/1 ==> if (scrmbl_ready_i) begin
460 unreachable state_d = IntegScrWaitSt;
461 end
==> MISSING_ELSE
462 end
463 ///////////////////////////////////////////////////////////////////
464 // Wait for the scrambled data to return.
465 // SEC_CM: PART.DATA_REG.BKGN_CHK
466 IntegScrWaitSt: begin
467 0/1 ==> scrmbl_mtx_req_o = 1'b1;
468 0/1 ==> scrmbl_sel_o = Info.key_sel;
469 0/1 ==> if (scrmbl_valid_i) begin
470 unreachable state_d = IntegDigSt;
471 end
==> MISSING_ELSE
472 end
473 ///////////////////////////////////////////////////////////////////
474 // Push the word read into the scrambling datapath. The last
475 // block is repeated in case the number blocks in this partition
476 // is odd.
477 // SEC_CM: PART.MEM.DIGEST
478 // SEC_CM: PART.DATA_REG.BKGN_CHK
479 IntegDigSt: begin
480 0/1 ==> scrmbl_mtx_req_o = 1'b1;
481 0/1 ==> scrmbl_valid_o = 1'b1;
482 0/1 ==> if (scrmbl_ready_i) begin
483 unreachable cnt_en = 1'b1;
484 // No need to digest the digest value itself
485 unreachable if (cnt == PenultimateScrmblBlock) begin
486 // Note that the digest operates on 128bit blocks since the data is fed in via the
487 // PRESENT key input. Therefore, we only trigger a digest update on every second
488 // 64bit block that is pushed into the scrambling datapath.
489 unreachable if (cnt[0]) begin
490 unreachable scrmbl_cmd_o = Digest;
491 unreachable state_d = IntegDigFinSt;
492 end else begin
493 unreachable state_d = IntegDigPadSt;
494 unreachable cnt_en = 1'b0;
495 end
496 end else begin
497 // Trigger digest round in case this is the second block in a row.
498 unreachable if (cnt[0]) begin
499 unreachable scrmbl_cmd_o = Digest;
500 end
==> MISSING_ELSE
501 // Go back and scramble the next data block if this is
502 // a scrambled partition. Otherwise just stay here.
503 unreachable if (Info.secret) begin
504 unreachable state_d = IntegScrSt;
505 end
==> MISSING_ELSE
506 end
507 end
==> MISSING_ELSE
508 end
509 ///////////////////////////////////////////////////////////////////
510 // Padding state. When we get here, we've copied the last encryption
511 // result into the shadow register such that we've effectively
512 // repeated the last block twice in order to pad the data to 128bit.
513 // SEC_CM: PART.MEM.DIGEST
514 // SEC_CM: PART.DATA_REG.BKGN_CHK
515 IntegDigPadSt: begin
516 0/1 ==> scrmbl_mtx_req_o = 1'b1;
517 0/1 ==> scrmbl_valid_o = 1'b1;
518 0/1 ==> scrmbl_cmd_o = Digest;
519 0/1 ==> if (scrmbl_ready_i) begin
520 unreachable state_d = IntegDigFinSt;
521 end
==> MISSING_ELSE
522 end
523 ///////////////////////////////////////////////////////////////////
524 // Trigger digest finalization and go wait for the result.
525 // SEC_CM: PART.MEM.DIGEST
526 // SEC_CM: PART.DATA_REG.BKGN_CHK
527 IntegDigFinSt: begin
528 0/1 ==> scrmbl_mtx_req_o = 1'b1;
529 0/1 ==> scrmbl_valid_o = 1'b1;
530 0/1 ==> scrmbl_cmd_o = DigestFinalize;
531 0/1 ==> if (scrmbl_ready_i) begin
532 unreachable state_d = IntegDigWaitSt;
533 end
==> MISSING_ELSE
534 end
535 ///////////////////////////////////////////////////////////////////
536 // Wait for the digest to return, and double check whether the digest
537 // matches. If yes, unlock the partition. Otherwise, go into the terminal
538 // error state, where the partition will be locked down.
539 // SEC_CM: PART.MEM.DIGEST
540 // SEC_CM: PART.DATA_REG.BKGN_CHK
541 IntegDigWaitSt: begin
542 0/1 ==> scrmbl_mtx_req_o = 1'b1;
543 0/1 ==> data_sel = ScrmblData;
544 0/1 ==> if (scrmbl_valid_i) begin
545 // This is the only way the buffer regs can get unlocked.
546 // Note that we ignore this check if the digest is still blank.
547 unreachable if (digest_o == data_mux || digest_o == '0) begin
548 unreachable state_d = IdleSt;
549 // If the partition is still locked, this is the first integrity check after
550 // initialization. This is the only way the buffer regs can get unlocked.
551 unreachable if (mubi8_test_true_strict(dout_locked_q)) begin
552 unreachable dout_locked_d = MuBi8False;
553 // Otherwise, this integrity check has requested by the LFSR timer, and we have
554 // to acknowledge its completion.
555 end else begin
556 unreachable integ_chk_ack_o = 1'b1;
557 end
558 // Error out and lock the partition if this check fails.
559 end else begin
560 unreachable state_d = ErrorSt;
561 unreachable error_d = CheckFailError;
562 // The check has finished and found an error.
563 unreachable integ_chk_ack_o = 1'b1;
564 end
565 end
==> MISSING_ELSE
566 end
567 ///////////////////////////////////////////////////////////////////
568 // Terminal Error State. This locks access to the partition.
569 // Make sure the partition signals an error state if no error
570 // code has been latched so far, and lock the buffer regs down.
571 ErrorSt: begin
572 1/1 dout_locked_d = MuBi8True;
Tests: T2 T4 T6
573 1/1 if (error_q == NoError) begin
Tests: T2 T4 T6
574 1/1 error_d = FsmStateError;
Tests: T19 T20 T21
575 end
MISSING_ELSE
576 // If we are in error state, we cannot execute the checks anymore.
577 // Hence the acknowledgements are returned immediately.
578 1/1 cnsty_chk_ack_o = 1'b1;
Tests: T2 T4 T6
579 1/1 integ_chk_ack_o = 1'b1;
Tests: T2 T4 T6
580 end
581 ///////////////////////////////////////////////////////////////////
582 // We should never get here. If we do (e.g. via a malicious
583 // glitch), error out immediately.
584 default: begin
585 state_d = ErrorSt;
586 fsm_err_o = 1'b1;
587 end
588 ///////////////////////////////////////////////////////////////////
589 endcase // state_q
590
591
592 // Unconditionally jump into the terminal error state in case of
593 // an ECC error or escalation, and lock access to the partition down.
594 // SEC_CM: PART.FSM.LOCAL_ESC
595 1/1 if (ecc_err) begin
Tests: T1 T2 T3
596 0/1 ==> state_d = ErrorSt;
597 0/1 ==> if (state_q != ErrorSt) begin
598 0/1 ==> error_d = CheckFailError;
599 end
==> MISSING_ELSE
600 end
MISSING_ELSE
601 // SEC_CM: PART.FSM.LOCAL_ESC, PART.FSM.GLOBAL_ESC
602 1/1 if (lc_ctrl_pkg::lc_tx_test_true_loose(escalate_en_i) || cnt_err) begin
Tests: T1 T2 T3
603 1/1 state_d = ErrorSt;
Tests: T2 T4 T6
604 1/1 fsm_err_o = 1'b1;
Tests: T2 T4 T6
605 1/1 if (state_q != ErrorSt) begin
Tests: T2 T4 T6
606 1/1 error_d = FsmStateError;
Tests: T2 T4 T6
607 end
MISSING_ELSE
608 end
MISSING_ELSE
609 end
610
611 ////////////////////////////
612 // Address Calc and Muxes //
613 ////////////////////////////
614
615 // Address counter - this is only used for computing a digest, hence the increment is
616 // fixed to 8 byte.
617 // SEC_CM: PART.CTR.REDUN
618 prim_count #(
619 .Width(CntWidth)
620 ) u_prim_count (
621 .clk_i,
622 .rst_ni,
623 .clr_i(cnt_clr),
624 .set_i(1'b0),
625 .set_cnt_i('0),
626 .incr_en_i(cnt_en),
627 .decr_en_i(1'b0),
628 .step_i(CntWidth'(1)),
629 .commit_i(1'b1),
630 .cnt_o(cnt),
631 .cnt_after_commit_o(),
632 .err_o(cnt_err)
633 );
634
635 logic [OtpByteAddrWidth-1:0] addr_base;
636 0/1 ==> assign addr_base = (base_sel == DigOffset) ? DigestOffset : Info.offset;
637
638 // Note that OTP works on halfword (16bit) addresses, hence need to
639 // shift the addresses appropriately.
640 logic [OtpByteAddrWidth-1:0] addr_calc;
641 1/1 assign addr_calc = OtpByteAddrWidth'({cnt, {$clog2(ScrmblBlockWidth/8){1'b0}}}) + addr_base;
Tests: T1 T2 T3
642 1/1 assign otp_addr_o = addr_calc[OtpByteAddrWidth-1:OtpAddrShift];
Tests: T1 T2 T3
643
644 if (OtpAddrShift > 0) begin : gen_unused
645 logic unused_bits;
646 1/1 assign unused_bits = ^addr_calc[OtpAddrShift-1:0];
Tests: T1 T2 T3
647 end
648
649 // Always transfer 64bit blocks.
650 assign otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth) - 1);
651
652 1/1 assign data_mux = (data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i;
Tests: T1 T2 T3
653
654 /////////////////
655 // Buffer Regs //
656 /////////////////
657
658 // SEC_CM: PART.DATA_REG.INTEGRITY
659 logic [Info.size*8-1:0] data;
660 otp_ctrl_ecc_reg #(
661 .Width ( ScrmblBlockWidth ),
662 .Depth ( NumScrmblBlocks )
663 ) u_otp_ctrl_ecc_reg (
664 .clk_i,
665 .rst_ni,
666 .wren_i ( buffer_reg_en ),
667 .addr_i ( cnt ),
668 .wdata_i ( data_mux ),
669 .rdata_o ( scrmbl_data_o ),
670 .data_o ( data ),
671 .ecc_err_o ( ecc_err )
672 );
673
674 // We have successfully initialized the partition once it has been unlocked.
675 1/1 assign init_done_o = mubi8_test_false_strict(dout_locked_q);
Tests: T1 T2 T3
676 // Hardware output gating.
677 // Note that this is decoupled from the DAI access rules further below.
678 1/1 assign data_o = (init_done_o) ? data : DataDefault;
Tests: T1 T2 T3
679 // The digest does not have to be gated.
680 1/1 assign digest_o = data[$high(data_o) -: ScrmblBlockWidth];
Tests: T1 T2 T3
681
682 ////////////////////////
683 // DAI Access Control //
684 ////////////////////////
685
686 // Aggregate all possible DAI write /readlocks. The partition is also locked when uninitialized.
687 // Note that the locks are redundantly encoded values.
688 part_access_t access_pre;
689 prim_mubi8_sender #(
690 .AsyncOn(0)
691 ) u_prim_mubi8_sender_write_lock_pre (
692 .clk_i,
693 .rst_ni,
694 .mubi_i(mubi8_and_lo(dout_locked_q, access_i.write_lock)),
695 .mubi_o(access_pre.write_lock)
696 );
697 prim_mubi8_sender #(
698 .AsyncOn(0)
699 ) u_prim_mubi8_sender_read_lock_pre (
700 .clk_i,
701 .rst_ni,
702 .mubi_i(mubi8_and_lo(dout_locked_q, access_i.read_lock)),
703 .mubi_o(access_pre.read_lock)
704 );
705
706 // SEC_CM: PART.MEM.SW_UNWRITABLE
707 if (Info.write_lock) begin : gen_digest_write_lock
708 mubi8_t digest_locked;
709 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False;
710
711 // This prevents the synthesis tool from optimizing the multibit signal.
712 prim_mubi8_sender #(
713 .AsyncOn(0)
714 ) u_prim_mubi8_sender_write_lock (
715 .clk_i,
716 .rst_ni,
717 .mubi_i(mubi8_and_lo(access_pre.write_lock, digest_locked)),
718 .mubi_o(access_o.write_lock)
719 );
720
721 `ASSERT(DigestWriteLocksPartition_A, digest_o |-> mubi8_test_true_loose(access_o.write_lock))
722 end else begin : gen_no_digest_write_lock
723 0/1 ==> assign access_o.write_lock = access_pre.write_lock;
724 end
725
726 // SEC_CM: PART.MEM.SW_UNREADABLE
727 if (Info.read_lock) begin : gen_digest_read_lock
728 mubi8_t digest_locked;
729 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False;
730
731 // This prevents the synthesis tool from optimizing the multibit signal.
732 prim_mubi8_sender #(
733 .AsyncOn(0)
734 ) u_prim_mubi8_sender_read_lock (
735 .clk_i,
736 .rst_ni,
737 .mubi_i(mubi8_and_lo(access_pre.read_lock, digest_locked)),
738 .mubi_o(access_o.read_lock)
739 );
740
741 `ASSERT(DigestReadLocksPartition_A, digest_o |-> mubi8_test_true_loose(access_o.read_lock))
742 end else begin : gen_no_digest_read_lock
743 0/1 ==> assign access_o.read_lock = access_pre.read_lock;
744 end
745
746 ///////////////
747 // Registers //
748 ///////////////
749
750 3/3 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt)
Tests: T1 T2 T3 | T1 T2 T3 | T1 T2 T3
PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt):
750.1 `ifdef SIMULATION
750.2 prim_sparse_fsm_flop #(
750.3 .StateEnumT(state_e),
750.4 .Width($bits(state_e)),
750.5 .ResetValue($bits(state_e)'(ResetSt)),
750.6 .EnableAlertTriggerSVA(1),
750.7 .CustomForceName("state_q")
750.8 ) u_state_regs (
750.9 .clk_i ( clk_i ),
750.10 .rst_ni ( rst_ni ),
750.11 .state_i ( state_d ),
750.12 .state_o ( )
750.13 );
750.14 always_ff @(posedge clk_i or negedge rst_ni) begin
750.15 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
750.16 1/1 state_q <= ResetSt;
Tests: T1 T2 T3
750.17 end else begin
750.18 1/1 state_q <= state_d;
Tests: T1 T2 T3
750.19 end
750.20 end
750.21 u_state_regs_A: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (state_q === u_state_regs.state_o))
750.22 else begin
750.23 `ifdef UVM
750.24 uvm_pkg::uvm_report_error("ASSERT FAILED", "u_state_regs_A", uvm_pkg::UVM_NONE,
750.25 "../src/lowrisc_ip_otp_ctrl_1.0/rtl/otp_ctrl_part_buf.sv", 750, "", 1);
750.26 `else
750.27 $error("%0t: (%0s:%0d) [%m] [ASSERT FAILED] %0s", $time, `__FILE__, `__LINE__,
750.28 `PRIM_STRINGIFY(u_state_regs_A));
750.29 `endif
750.30 end
750.31 `else
750.32 prim_sparse_fsm_flop #(
750.33 .StateEnumT(state_e),
750.34 .Width($bits(state_e)),
750.35 .ResetValue($bits(state_e)'(ResetSt)),
750.36 .EnableAlertTriggerSVA(1)
750.37 ) u_state_regs (
750.38 .clk_i ( `PRIM_FLOP_CLK ),
750.39 .rst_ni ( `PRIM_FLOP_RST ),
750.40 .state_i ( state_d ),
750.41 .state_o ( state_q )
750.42 );
750.43 `endif751
752 always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
753 1/1 if (!rst_ni) begin
Tests: T1 T2 T3
754 1/1 error_q <= NoError;
Tests: T1 T2 T3
755 // data output is locked by default
756 1/1 dout_locked_q <= MuBi8True;
Tests: T1 T2 T3
757 end else begin
758 1/1 error_q <= error_d;
Tests: T1 T2 T3
759 1/1 dout_locked_q <= dout_locked_d;
Tests: T1 T2 T3
Cond Coverage for Module :
otp_ctrl_part_buf ( parameter Info=-1,CntWidth=4,DigestOffset=1720,StateWidth=12 )
Cond Coverage for Module self-instances :
| Total | Covered | Percent |
Conditions | 48 | 40 | 83.33 |
Logical | 48 | 40 | 83.33 |
Non-Logical | 0 | 0 | |
Event | 0 | 0 | |
LINE 271
EXPRESSION (cnt == LastScrmblBlock)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 282
EXPRESSION (otp_err != NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T28,T29,T30 |
LINE 302
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Not Covered | |
1 | 0 | Not Covered | |
1 | 1 | Not Covered | |
LINE 368
EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
-----------1---------- --------2-------
-1- | -2- | Status | Tests |
0 | 0 | Not Covered | |
0 | 1 | Covered | T11,T13,T84 |
1 | 0 | Covered | T5,T15,T85 |
LINE 368
SUB-EXPRESSION (digest_o == data_mux)
-----------1----------
-1- | Status | Tests |
0 | Covered | T11,T13,T84 |
1 | Covered | T6,T5,T24 |
LINE 368
SUB-EXPRESSION (digest_o == '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T5,T15,T85 |
1 | Covered | T6,T24,T14 |
LINE 385
EXPRESSION (cnt == LastScrmblBlock)
------------1-----------
-1- | Status | Tests |
0 | Unreachable | |
1 | Unreachable | |
LINE 401
EXPRESSION (otp_err != NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T6,T5,T24 |
1 | Covered | T34,T35 |
LINE 426
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Unreachable | |
1 | 0 | Unreachable | |
1 | 1 | Unreachable | |
LINE 433
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Not Covered | |
1 | 0 | Not Covered | |
1 | 1 | Covered | T1,T2,T3 |
LINE 485
EXPRESSION (cnt == PenultimateScrmblBlock)
---------------1---------------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 547
EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
-----------1---------- --------2-------
-1- | -2- | Status | Tests |
0 | 0 | Covered | T39,T40,T41 |
0 | 1 | Covered | T1,T2,T3 |
1 | 0 | Covered | T4,T5,T24 |
LINE 547
SUB-EXPRESSION (digest_o == data_mux)
-----------1----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T4,T5,T24 |
LINE 547
SUB-EXPRESSION (digest_o == '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T4,T5,T24 |
1 | Covered | T1,T2,T3 |
LINE 573
EXPRESSION (error_q == NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T2,T4,T6 |
1 | Covered | T19,T20,T21 |
LINE 597
EXPRESSION (state_q != ErrorSt)
----------1---------
-1- | Status | Tests |
0 | Not Covered | |
1 | Not Covered | |
LINE 605
EXPRESSION (state_q != ErrorSt)
----------1---------
-1- | Status | Tests |
0 | Covered | T2,T4,T6 |
1 | Covered | T2,T4,T6 |
LINE 636
EXPRESSION ((base_sel == DigOffset) ? DigestOffset : 11'b11001111000)
-----------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T4,T6,T5 |
LINE 636
SUB-EXPRESSION (base_sel == DigOffset)
-----------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T4,T6,T5 |
LINE 652
EXPRESSION ((data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 652
SUB-EXPRESSION (data_sel == ScrmblData)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 678
EXPRESSION (init_done_o ? data : DataDefault)
-----1-----
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 709
EXPRESSION ((digest_o != '0) ? MuBi8True : MuBi8False)
--------1-------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T4,T5,T24 |
LINE 709
SUB-EXPRESSION (digest_o != '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T4,T5,T24 |
Cond Coverage for Module :
otp_ctrl_part_buf ( parameter Info=-1,CntWidth=4,DigestOffset=1952,StateWidth=12 )
Cond Coverage for Module self-instances :
| Total | Covered | Percent |
Conditions | 52 | 45 | 86.54 |
Logical | 52 | 45 | 86.54 |
Non-Logical | 0 | 0 | |
Event | 0 | 0 | |
LINE 271
EXPRESSION (cnt == LastScrmblBlock)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 282
EXPRESSION (otp_err != NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T72,T73,T74 |
LINE 302
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Not Covered | |
1 | 0 | Not Covered | |
1 | 1 | Covered | T1,T2,T3 |
LINE 368
EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
-----------1---------- --------2-------
-1- | -2- | Status | Tests |
0 | 0 | Not Covered | |
0 | 1 | Covered | T11,T86,T87 |
1 | 0 | Covered | T5,T85,T88 |
LINE 368
SUB-EXPRESSION (digest_o == data_mux)
-----------1----------
-1- | Status | Tests |
0 | Covered | T11,T86,T87 |
1 | Covered | T6,T5,T24 |
LINE 368
SUB-EXPRESSION (digest_o == '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T5,T85,T88 |
1 | Covered | T6,T24,T14 |
LINE 385
EXPRESSION (cnt == LastScrmblBlock)
------------1-----------
-1- | Status | Tests |
0 | Unreachable | |
1 | Unreachable | |
LINE 401
EXPRESSION (otp_err != NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T6,T5,T24 |
1 | Covered | T48,T75 |
LINE 426
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Not Covered | |
1 | 0 | Not Covered | |
1 | 1 | Covered | T1,T2,T3 |
LINE 433
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Unreachable | |
1 | 0 | Unreachable | |
1 | 1 | Unreachable | |
LINE 485
EXPRESSION (cnt == PenultimateScrmblBlock)
---------------1---------------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 547
EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
-----------1---------- --------2-------
-1- | -2- | Status | Tests |
0 | 0 | Covered | T78 |
0 | 1 | Covered | T1,T2,T3 |
1 | 0 | Covered | T3,T5,T85 |
LINE 547
SUB-EXPRESSION (digest_o == data_mux)
-----------1----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T3,T5,T85 |
LINE 547
SUB-EXPRESSION (digest_o == '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T3,T5,T85 |
1 | Covered | T1,T2,T3 |
LINE 573
EXPRESSION (error_q == NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T2,T4,T6 |
1 | Covered | T19,T20,T21 |
LINE 597
EXPRESSION (state_q != ErrorSt)
----------1---------
-1- | Status | Tests |
0 | Not Covered | |
1 | Not Covered | |
LINE 605
EXPRESSION (state_q != ErrorSt)
----------1---------
-1- | Status | Tests |
0 | Covered | T2,T4,T6 |
1 | Covered | T2,T4,T6 |
LINE 636
EXPRESSION ((base_sel == DigOffset) ? DigestOffset : 11'b11101010000)
-----------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T4,T6,T5 |
LINE 636
SUB-EXPRESSION (base_sel == DigOffset)
-----------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T4,T6,T5 |
LINE 652
EXPRESSION ((data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 652
SUB-EXPRESSION (data_sel == ScrmblData)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 678
EXPRESSION (init_done_o ? data : DataDefault)
-----1-----
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 709
EXPRESSION ((digest_o != '0) ? MuBi8True : MuBi8False)
--------1-------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T3,T5,T85 |
LINE 709
SUB-EXPRESSION (digest_o != '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T3,T5,T85 |
LINE 729
EXPRESSION ((digest_o != '0) ? MuBi8True : MuBi8False)
--------1-------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T3,T5,T85 |
LINE 729
SUB-EXPRESSION (digest_o != '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T3,T5,T85 |
Cond Coverage for Module :
otp_ctrl_part_buf ( parameter Info=-1,CntWidth=1,DigestOffset=1736,StateWidth=12 )
Cond Coverage for Module self-instances :
| Total | Covered | Percent |
Conditions | 48 | 39 | 81.25 |
Logical | 48 | 39 | 81.25 |
Non-Logical | 0 | 0 | |
Event | 0 | 0 | |
LINE 271
EXPRESSION (cnt == LastScrmblBlock)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 282
EXPRESSION (otp_err != NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T42,T43,T32 |
LINE 302
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Not Covered | |
1 | 0 | Not Covered | |
1 | 1 | Not Covered | |
LINE 368
EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
-----------1---------- --------2-------
-1- | -2- | Status | Tests |
0 | 0 | Not Covered | |
0 | 1 | Covered | T11,T13,T84 |
1 | 0 | Covered | T5,T15,T85 |
LINE 368
SUB-EXPRESSION (digest_o == data_mux)
-----------1----------
-1- | Status | Tests |
0 | Covered | T11,T13,T84 |
1 | Covered | T6,T5,T24 |
LINE 368
SUB-EXPRESSION (digest_o == '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T5,T15,T85 |
1 | Covered | T6,T24,T14 |
LINE 385
EXPRESSION (cnt == LastScrmblBlock)
------------1-----------
-1- | Status | Tests |
0 | Unreachable | |
1 | Unreachable | |
LINE 401
EXPRESSION (otp_err != NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T6,T5,T24 |
1 | Covered | T46 |
LINE 426
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Unreachable | |
1 | 0 | Unreachable | |
1 | 1 | Unreachable | |
LINE 433
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Not Covered | |
1 | 0 | Not Covered | |
1 | 1 | Covered | T1,T2,T3 |
LINE 485
EXPRESSION (cnt == PenultimateScrmblBlock)
---------------1---------------
-1- | Status | Tests |
0 | Not Covered | |
1 | Covered | T1,T2,T3 |
LINE 547
EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
-----------1---------- --------2-------
-1- | -2- | Status | Tests |
0 | 0 | Covered | T49,T50,T51 |
0 | 1 | Covered | T1,T2,T3 |
1 | 0 | Covered | T3,T5,T15 |
LINE 547
SUB-EXPRESSION (digest_o == data_mux)
-----------1----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T3,T5,T15 |
LINE 547
SUB-EXPRESSION (digest_o == '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T3,T5,T15 |
1 | Covered | T1,T2,T3 |
LINE 573
EXPRESSION (error_q == NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T2,T4,T6 |
1 | Covered | T19,T20,T21 |
LINE 597
EXPRESSION (state_q != ErrorSt)
----------1---------
-1- | Status | Tests |
0 | Not Covered | |
1 | Not Covered | |
LINE 605
EXPRESSION (state_q != ErrorSt)
----------1---------
-1- | Status | Tests |
0 | Covered | T2,T4,T6 |
1 | Covered | T4,T6,T23 |
LINE 636
EXPRESSION ((base_sel == DigOffset) ? DigestOffset : 11'b11011000000)
-----------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T4,T6,T5 |
LINE 636
SUB-EXPRESSION (base_sel == DigOffset)
-----------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T4,T6,T5 |
LINE 652
EXPRESSION ((data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 652
SUB-EXPRESSION (data_sel == ScrmblData)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 678
EXPRESSION (init_done_o ? data : DataDefault)
-----1-----
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 709
EXPRESSION ((digest_o != '0) ? MuBi8True : MuBi8False)
--------1-------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T2,T3,T5 |
LINE 709
SUB-EXPRESSION (digest_o != '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T2,T3,T5 |
Cond Coverage for Module :
otp_ctrl_part_buf ( parameter Info=-1,CntWidth=3,DigestOffset=1776,StateWidth=12 )
Cond Coverage for Module self-instances :
| Total | Covered | Percent |
Conditions | 52 | 45 | 86.54 |
Logical | 52 | 45 | 86.54 |
Non-Logical | 0 | 0 | |
Event | 0 | 0 | |
LINE 271
EXPRESSION (cnt == LastScrmblBlock)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 282
EXPRESSION (otp_err != NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T52,T31,T53 |
LINE 302
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Not Covered | |
1 | 0 | Not Covered | |
1 | 1 | Covered | T1,T2,T3 |
LINE 368
EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
-----------1---------- --------2-------
-1- | -2- | Status | Tests |
0 | 0 | Not Covered | |
0 | 1 | Covered | T13,T84,T89 |
1 | 0 | Covered | T15,T88,T9 |
LINE 368
SUB-EXPRESSION (digest_o == data_mux)
-----------1----------
-1- | Status | Tests |
0 | Covered | T13,T84,T89 |
1 | Covered | T6,T5,T24 |
LINE 368
SUB-EXPRESSION (digest_o == '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T15,T88,T9 |
1 | Covered | T6,T5,T24 |
LINE 385
EXPRESSION (cnt == LastScrmblBlock)
------------1-----------
-1- | Status | Tests |
0 | Unreachable | |
1 | Unreachable | |
LINE 401
EXPRESSION (otp_err != NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T6,T5,T24 |
1 | Covered | T35,T56 |
LINE 426
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Not Covered | |
1 | 0 | Not Covered | |
1 | 1 | Covered | T1,T2,T3 |
LINE 433
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Unreachable | |
1 | 0 | Unreachable | |
1 | 1 | Unreachable | |
LINE 485
EXPRESSION (cnt == PenultimateScrmblBlock)
---------------1---------------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 547
EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
-----------1---------- --------2-------
-1- | -2- | Status | Tests |
0 | 0 | Covered | T58,T59,T60 |
0 | 1 | Covered | T1,T2,T3 |
1 | 0 | Covered | T3,T4,T6 |
LINE 547
SUB-EXPRESSION (digest_o == data_mux)
-----------1----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T3,T4,T6 |
LINE 547
SUB-EXPRESSION (digest_o == '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T3,T4,T6 |
1 | Covered | T1,T2,T3 |
LINE 573
EXPRESSION (error_q == NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T2,T4,T6 |
1 | Covered | T19,T20,T21 |
LINE 597
EXPRESSION (state_q != ErrorSt)
----------1---------
-1- | Status | Tests |
0 | Not Covered | |
1 | Not Covered | |
LINE 605
EXPRESSION (state_q != ErrorSt)
----------1---------
-1- | Status | Tests |
0 | Covered | T2,T4,T6 |
1 | Covered | T2,T4,T6 |
LINE 636
EXPRESSION ((base_sel == DigOffset) ? DigestOffset : 11'b11011010000)
-----------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T4,T6,T5 |
LINE 636
SUB-EXPRESSION (base_sel == DigOffset)
-----------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T4,T6,T5 |
LINE 652
EXPRESSION ((data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 652
SUB-EXPRESSION (data_sel == ScrmblData)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 678
EXPRESSION (init_done_o ? data : DataDefault)
-----1-----
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 709
EXPRESSION ((digest_o != '0) ? MuBi8True : MuBi8False)
--------1-------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T3,T4,T6 |
LINE 709
SUB-EXPRESSION (digest_o != '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T3,T4,T6 |
LINE 729
EXPRESSION ((digest_o != '0) ? MuBi8True : MuBi8False)
--------1-------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T3,T4,T6 |
LINE 729
SUB-EXPRESSION (digest_o != '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T3,T4,T6 |
Cond Coverage for Module :
otp_ctrl_part_buf ( parameter Info=-1,CntWidth=4,DigestOffset=2040,StateWidth=12 )
Cond Coverage for Module self-instances :
| Total | Covered | Percent |
Conditions | 24 | 17 | 70.83 |
Logical | 24 | 17 | 70.83 |
Non-Logical | 0 | 0 | |
Event | 0 | 0 | |
LINE 271
EXPRESSION (cnt == LastScrmblBlock)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 282
EXPRESSION (otp_err != NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T61,T33,T28 |
LINE 302
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Unreachable | |
1 | 0 | Unreachable | |
1 | 1 | Unreachable | |
LINE 368
EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
-----------1---------- --------2-------
-1- | -2- | Status | Tests |
0 | 0 | Unreachable | |
0 | 1 | Unreachable | |
1 | 0 | Unreachable | |
LINE 368
SUB-EXPRESSION (digest_o == data_mux)
-----------1----------
-1- | Status | Tests |
0 | Unreachable | |
1 | Unreachable | |
LINE 368
SUB-EXPRESSION (digest_o == '0)
--------1-------
-1- | Status | Tests |
0 | Unreachable | |
1 | Unreachable | |
LINE 385
EXPRESSION (cnt == LastScrmblBlock)
------------1-----------
-1- | Status | Tests |
0 | Covered | T4,T6,T5 |
1 | Covered | T6,T5,T24 |
LINE 401
EXPRESSION (otp_err != NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T4,T6,T5 |
1 | Not Covered | |
LINE 426
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Unreachable | |
1 | 0 | Unreachable | |
1 | 1 | Unreachable | |
LINE 433
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Unreachable | |
1 | 0 | Unreachable | |
1 | 1 | Unreachable | |
LINE 485
EXPRESSION (cnt == PenultimateScrmblBlock)
---------------1---------------
-1- | Status | Tests |
0 | Unreachable | |
1 | Unreachable | |
LINE 547
EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
-----------1---------- --------2-------
-1- | -2- | Status | Tests |
0 | 0 | Unreachable | |
0 | 1 | Unreachable | |
1 | 0 | Unreachable | |
LINE 547
SUB-EXPRESSION (digest_o == data_mux)
-----------1----------
-1- | Status | Tests |
0 | Unreachable | |
1 | Unreachable | |
LINE 547
SUB-EXPRESSION (digest_o == '0)
--------1-------
-1- | Status | Tests |
0 | Unreachable | |
1 | Unreachable | |
LINE 573
EXPRESSION (error_q == NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T2,T4,T6 |
1 | Covered | T19,T20,T21 |
LINE 597
EXPRESSION (state_q != ErrorSt)
----------1---------
-1- | Status | Tests |
0 | Not Covered | |
1 | Not Covered | |
LINE 605
EXPRESSION (state_q != ErrorSt)
----------1---------
-1- | Status | Tests |
0 | Covered | T2,T4,T6 |
1 | Covered | T2,T4,T6 |
LINE 636
EXPRESSION ((base_sel == DigOffset) ? DigestOffset : 11'b11110101000)
-----------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Not Covered | |
LINE 636
SUB-EXPRESSION (base_sel == DigOffset)
-----------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Not Covered | |
LINE 652
EXPRESSION ((data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Not Covered | |
LINE 652
SUB-EXPRESSION (data_sel == ScrmblData)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Not Covered | |
LINE 678
EXPRESSION (init_done_o ? data : DataDefault)
-----1-----
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
Cond Coverage for Module :
otp_ctrl_part_buf ( parameter Info=-1,CntWidth=4,DigestOffset=1864,StateWidth=12 )
Cond Coverage for Module self-instances :
| Total | Covered | Percent |
Conditions | 52 | 45 | 86.54 |
Logical | 52 | 45 | 86.54 |
Non-Logical | 0 | 0 | |
Event | 0 | 0 | |
LINE 271
EXPRESSION (cnt == LastScrmblBlock)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 282
EXPRESSION (otp_err != NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T61,T62,T63 |
LINE 302
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Not Covered | |
1 | 0 | Not Covered | |
1 | 1 | Covered | T1,T2,T3 |
LINE 368
EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
-----------1---------- --------2-------
-1- | -2- | Status | Tests |
0 | 0 | Not Covered | |
0 | 1 | Covered | T11,T13,T84 |
1 | 0 | Covered | T5,T15,T85 |
LINE 368
SUB-EXPRESSION (digest_o == data_mux)
-----------1----------
-1- | Status | Tests |
0 | Covered | T11,T13,T84 |
1 | Covered | T6,T5,T24 |
LINE 368
SUB-EXPRESSION (digest_o == '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T5,T15,T85 |
1 | Covered | T6,T24,T14 |
LINE 385
EXPRESSION (cnt == LastScrmblBlock)
------------1-----------
-1- | Status | Tests |
0 | Unreachable | |
1 | Unreachable | |
LINE 401
EXPRESSION (otp_err != NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T6,T5,T24 |
1 | Covered | T34,T65,T66 |
LINE 426
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Not Covered | |
1 | 0 | Not Covered | |
1 | 1 | Covered | T1,T2,T3 |
LINE 433
EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
--------1------- -------2------
-1- | -2- | Status | Tests |
0 | 1 | Unreachable | |
1 | 0 | Unreachable | |
1 | 1 | Unreachable | |
LINE 485
EXPRESSION (cnt == PenultimateScrmblBlock)
---------------1---------------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 547
EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
-----------1---------- --------2-------
-1- | -2- | Status | Tests |
0 | 0 | Covered | T69,T70,T71 |
0 | 1 | Covered | T1,T2,T3 |
1 | 0 | Covered | T3,T6,T5 |
LINE 547
SUB-EXPRESSION (digest_o == data_mux)
-----------1----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T3,T6,T5 |
LINE 547
SUB-EXPRESSION (digest_o == '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T3,T6,T5 |
1 | Covered | T1,T2,T3 |
LINE 573
EXPRESSION (error_q == NoError)
----------1---------
-1- | Status | Tests |
0 | Covered | T2,T4,T6 |
1 | Covered | T19,T20,T21 |
LINE 597
EXPRESSION (state_q != ErrorSt)
----------1---------
-1- | Status | Tests |
0 | Not Covered | |
1 | Not Covered | |
LINE 605
EXPRESSION (state_q != ErrorSt)
----------1---------
-1- | Status | Tests |
0 | Covered | T2,T4,T6 |
1 | Covered | T2,T4,T6 |
LINE 636
EXPRESSION ((base_sel == DigOffset) ? DigestOffset : 11'b11011111000)
-----------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T4,T6,T5 |
LINE 636
SUB-EXPRESSION (base_sel == DigOffset)
-----------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T4,T6,T5 |
LINE 652
EXPRESSION ((data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 652
SUB-EXPRESSION (data_sel == ScrmblData)
------------1-----------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 678
EXPRESSION (init_done_o ? data : DataDefault)
-----1-----
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T1,T2,T3 |
LINE 709
EXPRESSION ((digest_o != '0) ? MuBi8True : MuBi8False)
--------1-------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T3,T6,T5 |
LINE 709
SUB-EXPRESSION (digest_o != '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T3,T6,T5 |
LINE 729
EXPRESSION ((digest_o != '0) ? MuBi8True : MuBi8False)
--------1-------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T3,T6,T5 |
LINE 729
SUB-EXPRESSION (digest_o != '0)
--------1-------
-1- | Status | Tests |
0 | Covered | T1,T2,T3 |
1 | Covered | T3,T6,T5 |
FSM Coverage for Module :
otp_ctrl_part_buf
Summary for FSM :: state_q
| Total | Covered | Percent | |
States |
16 |
16 |
100.00 |
(Not included in score) |
Transitions |
38 |
37 |
97.37 |
|
Sequences |
0 |
0 |
|
|
State, Transition and Sequence Details for FSM :: state_q
states | Line No. | Covered | Tests |
CnstyReadSt |
334 |
Covered |
T4,T6,T5 |
CnstyReadWaitSt |
352 |
Covered |
T4,T6,T5 |
ErrorSt |
286 |
Covered |
T2,T4,T6 |
IdleSt |
369 |
Covered |
T1,T2,T3 |
InitDescrSt |
276 |
Covered |
T1,T2,T3 |
InitDescrWaitSt |
303 |
Covered |
T1,T2,T3 |
InitSt |
246 |
Covered |
T1,T2,T3 |
InitWaitSt |
256 |
Covered |
T1,T2,T3 |
IntegDigClrSt |
272 |
Covered |
T1,T2,T3 |
IntegDigFinSt |
491 |
Covered |
T1,T2,T3 |
IntegDigPadSt |
493 |
Covered |
T1,T2,T3 |
IntegDigSt |
434 |
Covered |
T1,T2,T3 |
IntegDigWaitSt |
532 |
Covered |
T1,T2,T3 |
IntegScrSt |
427 |
Covered |
T1,T2,T3 |
IntegScrWaitSt |
460 |
Covered |
T1,T2,T3 |
ResetSt |
244 |
Covered |
T1,T2,T3 |
transitions | Line No. | Covered | Tests |
CnstyReadSt->CnstyReadWaitSt |
352 |
Covered |
T4,T6,T5 |
CnstyReadSt->ErrorSt |
596 |
Covered |
T4,T90,T36 |
CnstyReadWaitSt->CnstyReadSt |
390 |
Covered |
T4,T6,T5 |
CnstyReadWaitSt->ErrorSt |
373 |
Covered |
T4,T90,T36 |
CnstyReadWaitSt->IdleSt |
369 |
Covered |
T6,T5,T24 |
IdleSt->CnstyReadSt |
334 |
Covered |
T4,T6,T5 |
IdleSt->ErrorSt |
596 |
Covered |
T6,T91,T92 |
IdleSt->IntegDigClrSt |
326 |
Covered |
T3,T5,T24 |
InitDescrSt->ErrorSt |
596 |
Covered |
T6,T58,T49 |
InitDescrSt->InitDescrWaitSt |
303 |
Covered |
T1,T2,T3 |
InitDescrWaitSt->ErrorSt |
596 |
Covered |
T2,T6,T58 |
InitDescrWaitSt->InitSt |
315 |
Covered |
T1,T2,T3 |
InitSt->ErrorSt |
596 |
Covered |
T2,T6,T23 |
InitSt->InitWaitSt |
256 |
Covered |
T1,T2,T3 |
InitWaitSt->ErrorSt |
286 |
Covered |
T2,T6,T49 |
InitWaitSt->InitDescrSt |
276 |
Covered |
T1,T2,T3 |
InitWaitSt->InitSt |
278 |
Covered |
T1,T2,T3 |
InitWaitSt->IntegDigClrSt |
272 |
Covered |
T1,T2,T3 |
IntegDigClrSt->ErrorSt |
596 |
Covered |
T93,T94,T36 |
IntegDigClrSt->IdleSt |
443 |
Covered |
T1,T2,T3 |
IntegDigClrSt->IntegDigSt |
434 |
Covered |
T1,T2,T3 |
IntegDigClrSt->IntegScrSt |
427 |
Covered |
T1,T2,T3 |
IntegDigFinSt->ErrorSt |
596 |
Covered |
T42,T95,T96 |
IntegDigFinSt->IntegDigWaitSt |
532 |
Covered |
T1,T2,T3 |
IntegDigPadSt->ErrorSt |
596 |
Not Covered |
|
IntegDigPadSt->IntegDigFinSt |
520 |
Covered |
T1,T2,T3 |
IntegDigSt->ErrorSt |
596 |
Covered |
T37,T38,T82 |
IntegDigSt->IntegDigFinSt |
491 |
Covered |
T1,T2,T3 |
IntegDigSt->IntegDigPadSt |
493 |
Covered |
T1,T2,T3 |
IntegDigSt->IntegScrSt |
504 |
Covered |
T1,T2,T3 |
IntegDigWaitSt->ErrorSt |
560 |
Covered |
T58,T49,T59 |
IntegDigWaitSt->IdleSt |
548 |
Covered |
T1,T2,T3 |
IntegScrSt->ErrorSt |
596 |
Covered |
T97,T69,T98 |
IntegScrSt->IntegScrWaitSt |
460 |
Covered |
T1,T2,T3 |
IntegScrWaitSt->ErrorSt |
596 |
Covered |
T93,T94,T36 |
IntegScrWaitSt->IntegDigSt |
470 |
Covered |
T1,T2,T3 |
ResetSt->ErrorSt |
596 |
Covered |
T99,T100,T101 |
ResetSt->InitSt |
246 |
Covered |
T1,T2,T3 |
Summary for FSM :: error_q
| Total | Covered | Percent | |
States |
4 |
4 |
100.00 |
(Not included in score) |
Transitions |
9 |
5 |
55.56 |
|
Sequences |
0 |
0 |
|
|
State, Transition and Sequence Details for FSM :: error_q
states | Line No. | Covered | Tests |
CheckFailError |
374 |
Covered |
T58,T49,T59 |
FsmStateError |
574 |
Covered |
T2,T4,T6 |
MacroEccCorrError |
283 |
Covered |
T34,T52,T35 |
NoError |
573 |
Covered |
T1,T2,T3 |
transitions | Line No. | Covered | Tests |
CheckFailError->FsmStateError |
606 |
Not Covered |
|
CheckFailError->MacroEccCorrError |
283 |
Not Covered |
|
FsmStateError->CheckFailError |
374 |
Not Covered |
|
FsmStateError->MacroEccCorrError |
283 |
Not Covered |
|
MacroEccCorrError->CheckFailError |
374 |
Covered |
T72 |
MacroEccCorrError->FsmStateError |
606 |
Covered |
T52,T42,T43 |
NoError->CheckFailError |
374 |
Covered |
T58,T49,T59 |
NoError->FsmStateError |
574 |
Covered |
T2,T4,T6 |
NoError->MacroEccCorrError |
283 |
Covered |
T34,T52,T35 |
Branch Coverage for Module :
otp_ctrl_part_buf ( parameter Info=-1,CntWidth=3,DigestOffset=1776,StateWidth=12 + Info=-1,CntWidth=4,DigestOffset=1864,StateWidth=12 + Info=-1,CntWidth=4,DigestOffset=1952,StateWidth=12 )
Branch Coverage for Module self-instances :
| Line No. | Total | Covered | Percent |
Branches |
|
73 |
62 |
84.93 |
TERNARY |
636 |
2 |
2 |
100.00 |
TERNARY |
652 |
2 |
2 |
100.00 |
TERNARY |
678 |
2 |
2 |
100.00 |
TERNARY |
709 |
2 |
2 |
100.00 |
TERNARY |
729 |
2 |
2 |
100.00 |
CASE |
240 |
53 |
44 |
83.02 |
IF |
595 |
3 |
1 |
33.33 |
IF |
602 |
3 |
3 |
100.00 |
IF |
750 |
2 |
2 |
100.00 |
IF |
753 |
2 |
2 |
100.00 |
636 assign addr_base = (base_sel == DigOffset) ? DigestOffset : Info.offset;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T4,T6,T5 |
0 |
Covered |
T1,T2,T3 |
652 assign data_mux = (data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
678 assign data_o = (init_done_o) ? data : DataDefault;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
709 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T3,T4,T6 |
0 |
Covered |
T1,T2,T3 |
729 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T3,T4,T6 |
0 |
Covered |
T1,T2,T3 |
240 unique case (state_q)
-1-
241 ///////////////////////////////////////////////////////////////////
242 // State right after reset. Wait here until we get a an
243 // initialization request.
244 ResetSt: begin
245 if (init_req_i) begin
-2-
246 state_d = InitSt;
==>
247 end
MISSING_ELSE
==>
248 end
249 ///////////////////////////////////////////////////////////////////
250 // Initialization reads out the digest only in unbuffered
251 // partitions. Wait here until the OTP request has been granted.
252 // And then wait until the OTP word comes back.
253 InitSt: begin
254 otp_req_o = 1'b1;
255 if (otp_gnt_i) begin
-3-
256 state_d = InitWaitSt;
==>
257 end
MISSING_ELSE
==>
258 end
259 ///////////////////////////////////////////////////////////////////
260 // Wait for OTP response and write to buffer register, then go to
261 // descrambling state. In case an OTP transaction fails, latch the
262 // OTP error code and jump to a
263 // terminal error state.
264 InitWaitSt: begin
265 if (otp_rvalid_i) begin
-4-
266 buffer_reg_en = 1'b1;
267 if (otp_err inside {NoError, MacroEccCorrError}) begin
-5-
268 // Once we've read and descrambled the whole partition, we can go to integrity
269 // verification. Note that the last block is the digest value, which does not
270 // have to be descrambled.
271 if (cnt == LastScrmblBlock) begin
-6-
272 state_d = IntegDigClrSt;
==>
273 // Only need to descramble if this is a scrambled partition.
274 // Otherwise, we can just go back to InitSt and read the next block.
275 end else if (Info.secret) begin
-7-
276 state_d = InitDescrSt;
==>
277 end else begin
278 state_d = InitSt;
==> (Unreachable)
279 cnt_en = 1'b1;
280 end
281 // At this point the only error that we could have gotten are correctable ECC errors.
282 if (otp_err != NoError) begin
-8-
283 error_d = MacroEccCorrError;
==>
284 end
MISSING_ELSE
==>
285 end else begin
286 state_d = ErrorSt;
==>
287 error_d = otp_err;
288 end
289 end
MISSING_ELSE
==>
290 end
291 ///////////////////////////////////////////////////////////////////
292 // Descrambling state. This first acquires the scrambling
293 // datapath mutex. Note that once the mutex is acquired, we have
294 // exclusive access to the scrambling datapath until we release
295 // the mutex by deasserting scrmbl_mtx_req_o.
296 // SEC_CM: SECRET.MEM.SCRAMBLE
297 InitDescrSt: begin
298 scrmbl_mtx_req_o = 1'b1;
299 scrmbl_valid_o = 1'b1;
300 scrmbl_cmd_o = Decrypt;
301 scrmbl_sel_o = Info.key_sel;
302 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
-9-
303 state_d = InitDescrWaitSt;
==>
304 end
MISSING_ELSE
==>
305 end
306 ///////////////////////////////////////////////////////////////////
307 // Wait for the descrambled data to return. Note that we release
308 // the mutex lock upon leaving this state.
309 // SEC_CM: SECRET.MEM.SCRAMBLE
310 InitDescrWaitSt: begin
311 scrmbl_mtx_req_o = 1'b1;
312 scrmbl_sel_o = Info.key_sel;
313 data_sel = ScrmblData;
314 if (scrmbl_valid_i) begin
-10-
315 state_d = InitSt;
==>
316 buffer_reg_en = 1'b1;
317 cnt_en = 1'b1;
318 end
MISSING_ELSE
==>
319 end
320 ///////////////////////////////////////////////////////////////////
321 // Idle state. We basically wait for integrity and consistency check
322 // triggers in this state.
323 IdleSt: begin
324 if (integ_chk_req_i) begin
-11-
325 if (Info.hw_digest) begin
-12-
326 state_d = IntegDigClrSt;
==>
327 // In case there is nothing to check we can just
328 // acknowledge the request right away, without going to the
329 // integrity check.
330 end else begin
331 integ_chk_ack_o = 1'b1;
==> (Unreachable)
332 end
333 end else if (cnsty_chk_req_i) begin
-13-
334 state_d = CnstyReadSt;
==>
335 cnt_clr = 1'b1;
336 end
MISSING_ELSE
==>
337 end
338 ///////////////////////////////////////////////////////////////////
339 // Read the digest. Wait here until the OTP request has been granted.
340 // And then wait until the OTP word comes back.
341 // SEC_CM: PART.DATA_REG.BKGN_CHK
342 CnstyReadSt: begin
343 otp_req_o = 1'b1;
344 // In case this partition has a hardware digest, we only have to read
345 // and compare the digest value. In that case we select the digest offset here.
346 // Otherwise we have to read and compare the whole partition, in which case we
347 // select the partition offset, which is the default assignment of base_sel.
348 if (Info.hw_digest) begin
-14-
349 base_sel = DigOffset;
==>
350 end
MISSING_ELSE
==>
351 if (otp_gnt_i) begin
-15-
352 state_d = CnstyReadWaitSt;
==>
353 end
MISSING_ELSE
==>
354 end
355 ///////////////////////////////////////////////////////////////////
356 // Wait for OTP response and compare the digest. In case there is
357 // a mismatch, lock down the partition and go into the terminal error
358 // state. In case an OTP transaction fails, latch the OTP error code
359 // and jump to a terminal error state.
360 // SEC_CM: PART.DATA_REG.BKGN_CHK
361 CnstyReadWaitSt: begin
362 if (otp_rvalid_i) begin
-16-
363 if (otp_err inside {NoError, MacroEccCorrError}) begin
-17-
364 // Check whether we need to compare the digest or the full partition
365 // contents here.
366 if (Info.hw_digest) begin
-18-
367 // Note that we ignore this check if the digest is still blank.
368 if (digest_o == data_mux || digest_o == '0) begin
-19-
369 state_d = IdleSt;
==>
370 cnsty_chk_ack_o = 1'b1;
371 // Error out and lock the partition if this check fails.
372 end else begin
373 state_d = ErrorSt;
==>
374 error_d = CheckFailError;
375 // The check has finished and found an error.
376 cnsty_chk_ack_o = 1'b1;
377 end
378 end else begin
379 // Check whether the read data corresponds with the data buffered in regs.
380 // Note that this particular check can be bypassed in case a transition is ongoing.
381 if (scrmbl_data_o == data_mux ||
-20-
382 lc_ctrl_pkg::lc_tx_test_true_strict(check_byp_en_i)) begin
383 // Can go back to idle and acknowledge the
384 // request if this is the last block.
385 if (cnt == LastScrmblBlock) begin
-21-
386 state_d = IdleSt;
==> (Unreachable)
387 cnsty_chk_ack_o = 1'b1;
388 // Need to go back and read out more blocks.
389 end else begin
390 state_d = CnstyReadSt;
==> (Unreachable)
391 cnt_en = 1'b1;
392 end
393 end else begin
394 state_d = ErrorSt;
==> (Unreachable)
395 error_d = CheckFailError;
396 // The check has finished and found an error.
397 cnsty_chk_ack_o = 1'b1;
398 end
399 end
400 // At this point the only error that we could have gotten are correctable ECC errors.
401 if (otp_err != NoError) begin
-22-
402 error_d = MacroEccCorrError;
==>
403 end
MISSING_ELSE
==>
404 end else begin
405 state_d = ErrorSt;
==>
406 error_d = otp_err;
407 // The check has finished and found an error.
408 cnsty_chk_ack_o = 1'b1;
409 end
410 end
MISSING_ELSE
==>
411 end
412 ///////////////////////////////////////////////////////////////////
413 // First, acquire the mutex for the digest and clear the digest state.
414 // SEC_CM: PART.DATA_REG.BKGN_CHK
415 IntegDigClrSt: begin
416 // Check whether this partition requires checking at all.
417 if (Info.hw_digest) begin
-23-
418 scrmbl_mtx_req_o = 1'b1;
419 scrmbl_valid_o = 1'b1;
420 cnt_clr = 1'b1;
421 // Need to reset the digest state and set it to chained
422 // mode if this partition is scrambled.
423 scrmbl_cmd_o = DigestInit;
424 if (Info.secret) begin
-24-
425 scrmbl_mode_o = ChainedMode;
426 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
-25-
427 state_d = IntegScrSt;
==>
428 end
MISSING_ELSE
==>
429 // If this partition is not scrambled, we can just directly
430 // jump to the digest state.
431 end else begin
432 scrmbl_mode_o = StandardMode;
433 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
-26-
434 state_d = IntegDigSt;
==> (Unreachable)
435 end
MISSING_ELSE
==>
436 end
437 // Otherwise, if this partition is not digest protected,
438 // we can just go to idle, since there is nothing to check.
439 // Note that we do not come back to this state in case there is no
440 // digest, and hence it is safe to unlock the buffer regs at this point.
441 // This is the only way the buffer regs can get unlocked.
442 end else begin
443 state_d = IdleSt;
444 if (mubi8_test_true_strict(dout_locked_q)) begin
-27-
445 dout_locked_d = MuBi8False;
==> (Unreachable)
446 end
MISSING_ELSE
==>
447 end
448 end
449 ///////////////////////////////////////////////////////////////////
450 // Scramble buffered data (which is held in plaintext form).
451 // This moves the previous scrambling result into the shadow reg
452 // for later use.
453 // SEC_CM: PART.DATA_REG.BKGN_CHK
454 IntegScrSt: begin
455 scrmbl_mtx_req_o = 1'b1;
456 scrmbl_valid_o = 1'b1;
457 scrmbl_cmd_o = Encrypt;
458 scrmbl_sel_o = Info.key_sel;
459 if (scrmbl_ready_i) begin
-28-
460 state_d = IntegScrWaitSt;
==>
461 end
MISSING_ELSE
==>
462 end
463 ///////////////////////////////////////////////////////////////////
464 // Wait for the scrambled data to return.
465 // SEC_CM: PART.DATA_REG.BKGN_CHK
466 IntegScrWaitSt: begin
467 scrmbl_mtx_req_o = 1'b1;
468 scrmbl_sel_o = Info.key_sel;
469 if (scrmbl_valid_i) begin
-29-
470 state_d = IntegDigSt;
==>
471 end
MISSING_ELSE
==>
472 end
473 ///////////////////////////////////////////////////////////////////
474 // Push the word read into the scrambling datapath. The last
475 // block is repeated in case the number blocks in this partition
476 // is odd.
477 // SEC_CM: PART.MEM.DIGEST
478 // SEC_CM: PART.DATA_REG.BKGN_CHK
479 IntegDigSt: begin
480 scrmbl_mtx_req_o = 1'b1;
481 scrmbl_valid_o = 1'b1;
482 if (scrmbl_ready_i) begin
-30-
483 cnt_en = 1'b1;
484 // No need to digest the digest value itself
485 if (cnt == PenultimateScrmblBlock) begin
-31-
486 // Note that the digest operates on 128bit blocks since the data is fed in via the
487 // PRESENT key input. Therefore, we only trigger a digest update on every second
488 // 64bit block that is pushed into the scrambling datapath.
489 if (cnt[0]) begin
-32-
490 scrmbl_cmd_o = Digest;
==>
491 state_d = IntegDigFinSt;
492 end else begin
493 state_d = IntegDigPadSt;
==>
494 cnt_en = 1'b0;
495 end
496 end else begin
497 // Trigger digest round in case this is the second block in a row.
498 if (cnt[0]) begin
-33-
499 scrmbl_cmd_o = Digest;
==>
500 end
MISSING_ELSE
==>
501 // Go back and scramble the next data block if this is
502 // a scrambled partition. Otherwise just stay here.
503 if (Info.secret) begin
-34-
504 state_d = IntegScrSt;
==>
505 end
MISSING_ELSE
==>
506 end
507 end
MISSING_ELSE
==>
508 end
509 ///////////////////////////////////////////////////////////////////
510 // Padding state. When we get here, we've copied the last encryption
511 // result into the shadow register such that we've effectively
512 // repeated the last block twice in order to pad the data to 128bit.
513 // SEC_CM: PART.MEM.DIGEST
514 // SEC_CM: PART.DATA_REG.BKGN_CHK
515 IntegDigPadSt: begin
516 scrmbl_mtx_req_o = 1'b1;
517 scrmbl_valid_o = 1'b1;
518 scrmbl_cmd_o = Digest;
519 if (scrmbl_ready_i) begin
-35-
520 state_d = IntegDigFinSt;
==>
521 end
MISSING_ELSE
==>
522 end
523 ///////////////////////////////////////////////////////////////////
524 // Trigger digest finalization and go wait for the result.
525 // SEC_CM: PART.MEM.DIGEST
526 // SEC_CM: PART.DATA_REG.BKGN_CHK
527 IntegDigFinSt: begin
528 scrmbl_mtx_req_o = 1'b1;
529 scrmbl_valid_o = 1'b1;
530 scrmbl_cmd_o = DigestFinalize;
531 if (scrmbl_ready_i) begin
-36-
532 state_d = IntegDigWaitSt;
==>
533 end
MISSING_ELSE
==>
534 end
535 ///////////////////////////////////////////////////////////////////
536 // Wait for the digest to return, and double check whether the digest
537 // matches. If yes, unlock the partition. Otherwise, go into the terminal
538 // error state, where the partition will be locked down.
539 // SEC_CM: PART.MEM.DIGEST
540 // SEC_CM: PART.DATA_REG.BKGN_CHK
541 IntegDigWaitSt: begin
542 scrmbl_mtx_req_o = 1'b1;
543 data_sel = ScrmblData;
544 if (scrmbl_valid_i) begin
-37-
545 // This is the only way the buffer regs can get unlocked.
546 // Note that we ignore this check if the digest is still blank.
547 if (digest_o == data_mux || digest_o == '0) begin
-38-
548 state_d = IdleSt;
549 // If the partition is still locked, this is the first integrity check after
550 // initialization. This is the only way the buffer regs can get unlocked.
551 if (mubi8_test_true_strict(dout_locked_q)) begin
-39-
552 dout_locked_d = MuBi8False;
==>
553 // Otherwise, this integrity check has requested by the LFSR timer, and we have
554 // to acknowledge its completion.
555 end else begin
556 integ_chk_ack_o = 1'b1;
==>
557 end
558 // Error out and lock the partition if this check fails.
559 end else begin
560 state_d = ErrorSt;
==>
561 error_d = CheckFailError;
562 // The check has finished and found an error.
563 integ_chk_ack_o = 1'b1;
564 end
565 end
MISSING_ELSE
==>
566 end
567 ///////////////////////////////////////////////////////////////////
568 // Terminal Error State. This locks access to the partition.
569 // Make sure the partition signals an error state if no error
570 // code has been latched so far, and lock the buffer regs down.
571 ErrorSt: begin
572 dout_locked_d = MuBi8True;
573 if (error_q == NoError) begin
-40-
574 error_d = FsmStateError;
==>
575 end
MISSING_ELSE
==>
576 // If we are in error state, we cannot execute the checks anymore.
577 // Hence the acknowledgements are returned immediately.
578 cnsty_chk_ack_o = 1'b1;
579 integ_chk_ack_o = 1'b1;
580 end
581 ///////////////////////////////////////////////////////////////////
582 // We should never get here. If we do (e.g. via a malicious
583 // glitch), error out immediately.
584 default: begin
585 state_d = ErrorSt;
==>
Branches:
-1- | -2- | -3- | -4- | -5- | -6- | -7- | -8- | -9- | -10- | -11- | -12- | -13- | -14- | -15- | -16- | -17- | -18- | -19- | -20- | -21- | -22- | -23- | -24- | -25- | -26- | -27- | -28- | -29- | -30- | -31- | -32- | -33- | -34- | -35- | -36- | -37- | -38- | -39- | -40- | Status | Tests |
ResetSt |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
ResetSt |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitSt |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitSt |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitWaitSt |
- |
- |
1 |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitWaitSt |
- |
- |
1 |
1 |
0 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitWaitSt |
- |
- |
1 |
1 |
0 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
InitWaitSt |
- |
- |
1 |
1 |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T61,T52,T31 |
InitWaitSt |
- |
- |
1 |
1 |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitWaitSt |
- |
- |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T61,T42,T43 |
InitWaitSt |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitDescrSt |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitDescrSt |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitDescrWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitDescrWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IdleSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T3,T5,T24 |
IdleSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
IdleSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T4,T6,T5 |
IdleSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
CnstyReadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T4,T6,T5 |
CnstyReadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
CnstyReadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T6,T5,T24 |
CnstyReadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T4,T6,T5 |
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T6,T5,T24 |
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T34,T65,T66 |
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T6,T5,T24 |
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T36,T38,T76 |
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T6,T5,T24 |
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegScrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegScrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegScrWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegScrWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegDigPadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
Not Covered |
|
IntegDigPadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
Not Covered |
|
IntegDigFinSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigFinSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
1 |
- |
Covered |
T1,T2,T3 |
IntegDigWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
Covered |
T3,T5,T24 |
IntegDigWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
- |
Covered |
T58,T59,T60 |
IntegDigWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
Covered |
T1,T2,T3 |
ErrorSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
Covered |
T19,T20,T21 |
ErrorSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
Covered |
T2,T4,T6 |
default |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T19,T20,T21 |
595 if (ecc_err) begin
-1-
596 state_d = ErrorSt;
597 if (state_q != ErrorSt) begin
-2-
598 error_d = CheckFailError;
==>
599 end
MISSING_ELSE
==>
600 end
MISSING_ELSE
==>
Branches:
-1- | -2- | Status | Tests |
1 |
1 |
Not Covered |
|
1 |
0 |
Not Covered |
|
0 |
- |
Covered |
T1,T2,T3 |
602 if (lc_ctrl_pkg::lc_tx_test_true_loose(escalate_en_i) || cnt_err) begin
-1-
603 state_d = ErrorSt;
604 fsm_err_o = 1'b1;
605 if (state_q != ErrorSt) begin
-2-
606 error_d = FsmStateError;
==>
607 end
MISSING_ELSE
==>
608 end
MISSING_ELSE
==>
Branches:
-1- | -2- | Status | Tests |
1 |
1 |
Covered |
T2,T4,T6 |
1 |
0 |
Covered |
T2,T4,T6 |
0 |
- |
Covered |
T1,T2,T3 |
750 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt)
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
753 if (!rst_ni) begin
-1-
754 error_q <= NoError;
==>
755 // data output is locked by default
756 dout_locked_q <= MuBi8True;
757 end else begin
758 error_q <= error_d;
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
Branch Coverage for Module :
otp_ctrl_part_buf ( parameter Info=-1,CntWidth=4,DigestOffset=1720,StateWidth=12 + Info=-1,CntWidth=1,DigestOffset=1736,StateWidth=12 )
Branch Coverage for Module self-instances :
| Line No. | Total | Covered | Percent |
Branches |
|
70 |
55 |
78.57 |
TERNARY |
636 |
2 |
2 |
100.00 |
TERNARY |
652 |
2 |
2 |
100.00 |
TERNARY |
678 |
2 |
2 |
100.00 |
TERNARY |
709 |
2 |
2 |
100.00 |
CASE |
240 |
52 |
39 |
75.00 |
IF |
595 |
3 |
1 |
33.33 |
IF |
602 |
3 |
3 |
100.00 |
IF |
750 |
2 |
2 |
100.00 |
IF |
753 |
2 |
2 |
100.00 |
636 assign addr_base = (base_sel == DigOffset) ? DigestOffset : Info.offset;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T4,T6,T5 |
0 |
Covered |
T1,T2,T3 |
652 assign data_mux = (data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
678 assign data_o = (init_done_o) ? data : DataDefault;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
709 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T2,T3,T4 |
0 |
Covered |
T1,T2,T3 |
240 unique case (state_q)
-1-
241 ///////////////////////////////////////////////////////////////////
242 // State right after reset. Wait here until we get a an
243 // initialization request.
244 ResetSt: begin
245 if (init_req_i) begin
-2-
246 state_d = InitSt;
==>
247 end
MISSING_ELSE
==>
248 end
249 ///////////////////////////////////////////////////////////////////
250 // Initialization reads out the digest only in unbuffered
251 // partitions. Wait here until the OTP request has been granted.
252 // And then wait until the OTP word comes back.
253 InitSt: begin
254 otp_req_o = 1'b1;
255 if (otp_gnt_i) begin
-3-
256 state_d = InitWaitSt;
==>
257 end
MISSING_ELSE
==>
258 end
259 ///////////////////////////////////////////////////////////////////
260 // Wait for OTP response and write to buffer register, then go to
261 // descrambling state. In case an OTP transaction fails, latch the
262 // OTP error code and jump to a
263 // terminal error state.
264 InitWaitSt: begin
265 if (otp_rvalid_i) begin
-4-
266 buffer_reg_en = 1'b1;
267 if (otp_err inside {NoError, MacroEccCorrError}) begin
-5-
268 // Once we've read and descrambled the whole partition, we can go to integrity
269 // verification. Note that the last block is the digest value, which does not
270 // have to be descrambled.
271 if (cnt == LastScrmblBlock) begin
-6-
272 state_d = IntegDigClrSt;
==>
273 // Only need to descramble if this is a scrambled partition.
274 // Otherwise, we can just go back to InitSt and read the next block.
275 end else if (Info.secret) begin
-7-
276 state_d = InitDescrSt;
==> (Unreachable)
277 end else begin
278 state_d = InitSt;
==>
279 cnt_en = 1'b1;
280 end
281 // At this point the only error that we could have gotten are correctable ECC errors.
282 if (otp_err != NoError) begin
-8-
283 error_d = MacroEccCorrError;
==>
284 end
MISSING_ELSE
==>
285 end else begin
286 state_d = ErrorSt;
==>
287 error_d = otp_err;
288 end
289 end
MISSING_ELSE
==>
290 end
291 ///////////////////////////////////////////////////////////////////
292 // Descrambling state. This first acquires the scrambling
293 // datapath mutex. Note that once the mutex is acquired, we have
294 // exclusive access to the scrambling datapath until we release
295 // the mutex by deasserting scrmbl_mtx_req_o.
296 // SEC_CM: SECRET.MEM.SCRAMBLE
297 InitDescrSt: begin
298 scrmbl_mtx_req_o = 1'b1;
299 scrmbl_valid_o = 1'b1;
300 scrmbl_cmd_o = Decrypt;
301 scrmbl_sel_o = Info.key_sel;
302 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
-9-
303 state_d = InitDescrWaitSt;
==>
304 end
MISSING_ELSE
==>
305 end
306 ///////////////////////////////////////////////////////////////////
307 // Wait for the descrambled data to return. Note that we release
308 // the mutex lock upon leaving this state.
309 // SEC_CM: SECRET.MEM.SCRAMBLE
310 InitDescrWaitSt: begin
311 scrmbl_mtx_req_o = 1'b1;
312 scrmbl_sel_o = Info.key_sel;
313 data_sel = ScrmblData;
314 if (scrmbl_valid_i) begin
-10-
315 state_d = InitSt;
==>
316 buffer_reg_en = 1'b1;
317 cnt_en = 1'b1;
318 end
MISSING_ELSE
==>
319 end
320 ///////////////////////////////////////////////////////////////////
321 // Idle state. We basically wait for integrity and consistency check
322 // triggers in this state.
323 IdleSt: begin
324 if (integ_chk_req_i) begin
-11-
325 if (Info.hw_digest) begin
-12-
326 state_d = IntegDigClrSt;
==>
327 // In case there is nothing to check we can just
328 // acknowledge the request right away, without going to the
329 // integrity check.
330 end else begin
331 integ_chk_ack_o = 1'b1;
==> (Unreachable)
332 end
333 end else if (cnsty_chk_req_i) begin
-13-
334 state_d = CnstyReadSt;
==>
335 cnt_clr = 1'b1;
336 end
MISSING_ELSE
==>
337 end
338 ///////////////////////////////////////////////////////////////////
339 // Read the digest. Wait here until the OTP request has been granted.
340 // And then wait until the OTP word comes back.
341 // SEC_CM: PART.DATA_REG.BKGN_CHK
342 CnstyReadSt: begin
343 otp_req_o = 1'b1;
344 // In case this partition has a hardware digest, we only have to read
345 // and compare the digest value. In that case we select the digest offset here.
346 // Otherwise we have to read and compare the whole partition, in which case we
347 // select the partition offset, which is the default assignment of base_sel.
348 if (Info.hw_digest) begin
-14-
349 base_sel = DigOffset;
==>
350 end
MISSING_ELSE
==>
351 if (otp_gnt_i) begin
-15-
352 state_d = CnstyReadWaitSt;
==>
353 end
MISSING_ELSE
==>
354 end
355 ///////////////////////////////////////////////////////////////////
356 // Wait for OTP response and compare the digest. In case there is
357 // a mismatch, lock down the partition and go into the terminal error
358 // state. In case an OTP transaction fails, latch the OTP error code
359 // and jump to a terminal error state.
360 // SEC_CM: PART.DATA_REG.BKGN_CHK
361 CnstyReadWaitSt: begin
362 if (otp_rvalid_i) begin
-16-
363 if (otp_err inside {NoError, MacroEccCorrError}) begin
-17-
364 // Check whether we need to compare the digest or the full partition
365 // contents here.
366 if (Info.hw_digest) begin
-18-
367 // Note that we ignore this check if the digest is still blank.
368 if (digest_o == data_mux || digest_o == '0) begin
-19-
369 state_d = IdleSt;
==>
370 cnsty_chk_ack_o = 1'b1;
371 // Error out and lock the partition if this check fails.
372 end else begin
373 state_d = ErrorSt;
==>
374 error_d = CheckFailError;
375 // The check has finished and found an error.
376 cnsty_chk_ack_o = 1'b1;
377 end
378 end else begin
379 // Check whether the read data corresponds with the data buffered in regs.
380 // Note that this particular check can be bypassed in case a transition is ongoing.
381 if (scrmbl_data_o == data_mux ||
-20-
382 lc_ctrl_pkg::lc_tx_test_true_strict(check_byp_en_i)) begin
383 // Can go back to idle and acknowledge the
384 // request if this is the last block.
385 if (cnt == LastScrmblBlock) begin
-21-
386 state_d = IdleSt;
==> (Unreachable)
387 cnsty_chk_ack_o = 1'b1;
388 // Need to go back and read out more blocks.
389 end else begin
390 state_d = CnstyReadSt;
==> (Unreachable)
391 cnt_en = 1'b1;
392 end
393 end else begin
394 state_d = ErrorSt;
==> (Unreachable)
395 error_d = CheckFailError;
396 // The check has finished and found an error.
397 cnsty_chk_ack_o = 1'b1;
398 end
399 end
400 // At this point the only error that we could have gotten are correctable ECC errors.
401 if (otp_err != NoError) begin
-22-
402 error_d = MacroEccCorrError;
==>
403 end
MISSING_ELSE
==>
404 end else begin
405 state_d = ErrorSt;
==>
406 error_d = otp_err;
407 // The check has finished and found an error.
408 cnsty_chk_ack_o = 1'b1;
409 end
410 end
MISSING_ELSE
==>
411 end
412 ///////////////////////////////////////////////////////////////////
413 // First, acquire the mutex for the digest and clear the digest state.
414 // SEC_CM: PART.DATA_REG.BKGN_CHK
415 IntegDigClrSt: begin
416 // Check whether this partition requires checking at all.
417 if (Info.hw_digest) begin
-23-
418 scrmbl_mtx_req_o = 1'b1;
419 scrmbl_valid_o = 1'b1;
420 cnt_clr = 1'b1;
421 // Need to reset the digest state and set it to chained
422 // mode if this partition is scrambled.
423 scrmbl_cmd_o = DigestInit;
424 if (Info.secret) begin
-24-
425 scrmbl_mode_o = ChainedMode;
426 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
-25-
427 state_d = IntegScrSt;
==> (Unreachable)
428 end
MISSING_ELSE
==>
429 // If this partition is not scrambled, we can just directly
430 // jump to the digest state.
431 end else begin
432 scrmbl_mode_o = StandardMode;
433 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
-26-
434 state_d = IntegDigSt;
==>
435 end
MISSING_ELSE
==>
436 end
437 // Otherwise, if this partition is not digest protected,
438 // we can just go to idle, since there is nothing to check.
439 // Note that we do not come back to this state in case there is no
440 // digest, and hence it is safe to unlock the buffer regs at this point.
441 // This is the only way the buffer regs can get unlocked.
442 end else begin
443 state_d = IdleSt;
444 if (mubi8_test_true_strict(dout_locked_q)) begin
-27-
445 dout_locked_d = MuBi8False;
==> (Unreachable)
446 end
MISSING_ELSE
==>
447 end
448 end
449 ///////////////////////////////////////////////////////////////////
450 // Scramble buffered data (which is held in plaintext form).
451 // This moves the previous scrambling result into the shadow reg
452 // for later use.
453 // SEC_CM: PART.DATA_REG.BKGN_CHK
454 IntegScrSt: begin
455 scrmbl_mtx_req_o = 1'b1;
456 scrmbl_valid_o = 1'b1;
457 scrmbl_cmd_o = Encrypt;
458 scrmbl_sel_o = Info.key_sel;
459 if (scrmbl_ready_i) begin
-28-
460 state_d = IntegScrWaitSt;
==>
461 end
MISSING_ELSE
==>
462 end
463 ///////////////////////////////////////////////////////////////////
464 // Wait for the scrambled data to return.
465 // SEC_CM: PART.DATA_REG.BKGN_CHK
466 IntegScrWaitSt: begin
467 scrmbl_mtx_req_o = 1'b1;
468 scrmbl_sel_o = Info.key_sel;
469 if (scrmbl_valid_i) begin
-29-
470 state_d = IntegDigSt;
==>
471 end
MISSING_ELSE
==>
472 end
473 ///////////////////////////////////////////////////////////////////
474 // Push the word read into the scrambling datapath. The last
475 // block is repeated in case the number blocks in this partition
476 // is odd.
477 // SEC_CM: PART.MEM.DIGEST
478 // SEC_CM: PART.DATA_REG.BKGN_CHK
479 IntegDigSt: begin
480 scrmbl_mtx_req_o = 1'b1;
481 scrmbl_valid_o = 1'b1;
482 if (scrmbl_ready_i) begin
-30-
483 cnt_en = 1'b1;
484 // No need to digest the digest value itself
485 if (cnt == PenultimateScrmblBlock) begin
-31-
486 // Note that the digest operates on 128bit blocks since the data is fed in via the
487 // PRESENT key input. Therefore, we only trigger a digest update on every second
488 // 64bit block that is pushed into the scrambling datapath.
489 if (cnt[0]) begin
-32-
490 scrmbl_cmd_o = Digest;
==>
491 state_d = IntegDigFinSt;
492 end else begin
493 state_d = IntegDigPadSt;
==>
494 cnt_en = 1'b0;
495 end
496 end else begin
497 // Trigger digest round in case this is the second block in a row.
498 if (cnt[0]) begin
-33-
499 scrmbl_cmd_o = Digest;
==>
500 end
MISSING_ELSE
==>
501 // Go back and scramble the next data block if this is
502 // a scrambled partition. Otherwise just stay here.
503 if (Info.secret) begin
-34-
504 state_d = IntegScrSt;
==> (Unreachable)
505 end
MISSING_ELSE
==>
506 end
507 end
MISSING_ELSE
==>
508 end
509 ///////////////////////////////////////////////////////////////////
510 // Padding state. When we get here, we've copied the last encryption
511 // result into the shadow register such that we've effectively
512 // repeated the last block twice in order to pad the data to 128bit.
513 // SEC_CM: PART.MEM.DIGEST
514 // SEC_CM: PART.DATA_REG.BKGN_CHK
515 IntegDigPadSt: begin
516 scrmbl_mtx_req_o = 1'b1;
517 scrmbl_valid_o = 1'b1;
518 scrmbl_cmd_o = Digest;
519 if (scrmbl_ready_i) begin
-35-
520 state_d = IntegDigFinSt;
==>
521 end
MISSING_ELSE
==>
522 end
523 ///////////////////////////////////////////////////////////////////
524 // Trigger digest finalization and go wait for the result.
525 // SEC_CM: PART.MEM.DIGEST
526 // SEC_CM: PART.DATA_REG.BKGN_CHK
527 IntegDigFinSt: begin
528 scrmbl_mtx_req_o = 1'b1;
529 scrmbl_valid_o = 1'b1;
530 scrmbl_cmd_o = DigestFinalize;
531 if (scrmbl_ready_i) begin
-36-
532 state_d = IntegDigWaitSt;
==>
533 end
MISSING_ELSE
==>
534 end
535 ///////////////////////////////////////////////////////////////////
536 // Wait for the digest to return, and double check whether the digest
537 // matches. If yes, unlock the partition. Otherwise, go into the terminal
538 // error state, where the partition will be locked down.
539 // SEC_CM: PART.MEM.DIGEST
540 // SEC_CM: PART.DATA_REG.BKGN_CHK
541 IntegDigWaitSt: begin
542 scrmbl_mtx_req_o = 1'b1;
543 data_sel = ScrmblData;
544 if (scrmbl_valid_i) begin
-37-
545 // This is the only way the buffer regs can get unlocked.
546 // Note that we ignore this check if the digest is still blank.
547 if (digest_o == data_mux || digest_o == '0) begin
-38-
548 state_d = IdleSt;
549 // If the partition is still locked, this is the first integrity check after
550 // initialization. This is the only way the buffer regs can get unlocked.
551 if (mubi8_test_true_strict(dout_locked_q)) begin
-39-
552 dout_locked_d = MuBi8False;
==>
553 // Otherwise, this integrity check has requested by the LFSR timer, and we have
554 // to acknowledge its completion.
555 end else begin
556 integ_chk_ack_o = 1'b1;
==>
557 end
558 // Error out and lock the partition if this check fails.
559 end else begin
560 state_d = ErrorSt;
==>
561 error_d = CheckFailError;
562 // The check has finished and found an error.
563 integ_chk_ack_o = 1'b1;
564 end
565 end
MISSING_ELSE
==>
566 end
567 ///////////////////////////////////////////////////////////////////
568 // Terminal Error State. This locks access to the partition.
569 // Make sure the partition signals an error state if no error
570 // code has been latched so far, and lock the buffer regs down.
571 ErrorSt: begin
572 dout_locked_d = MuBi8True;
573 if (error_q == NoError) begin
-40-
574 error_d = FsmStateError;
==>
575 end
MISSING_ELSE
==>
576 // If we are in error state, we cannot execute the checks anymore.
577 // Hence the acknowledgements are returned immediately.
578 cnsty_chk_ack_o = 1'b1;
579 integ_chk_ack_o = 1'b1;
580 end
581 ///////////////////////////////////////////////////////////////////
582 // We should never get here. If we do (e.g. via a malicious
583 // glitch), error out immediately.
584 default: begin
585 state_d = ErrorSt;
==>
Branches:
-1- | -2- | -3- | -4- | -5- | -6- | -7- | -8- | -9- | -10- | -11- | -12- | -13- | -14- | -15- | -16- | -17- | -18- | -19- | -20- | -21- | -22- | -23- | -24- | -25- | -26- | -27- | -28- | -29- | -30- | -31- | -32- | -33- | -34- | -35- | -36- | -37- | -38- | -39- | -40- | Status | Tests |
ResetSt |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
ResetSt |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitSt |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitSt |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitWaitSt |
- |
- |
1 |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitWaitSt |
- |
- |
1 |
1 |
0 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
InitWaitSt |
- |
- |
1 |
1 |
0 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitWaitSt |
- |
- |
1 |
1 |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T42,T43,T32 |
InitWaitSt |
- |
- |
1 |
1 |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitWaitSt |
- |
- |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T2,T44,T31 |
InitWaitSt |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitDescrSt |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
InitDescrSt |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
InitDescrWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
InitDescrWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IdleSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T3,T5,T24 |
IdleSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
IdleSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T4,T6,T5 |
IdleSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
CnstyReadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T4,T6,T5 |
CnstyReadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
CnstyReadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T4,T6,T5 |
CnstyReadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T4,T6,T5 |
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T6,T5,T24 |
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T34,T35,T46 |
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T6,T5,T24 |
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T36,T34,T37 |
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T4,T6,T5 |
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegScrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegScrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegScrWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegScrWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
Unreachable |
|
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigPadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigPadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
Not Covered |
|
IntegDigFinSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigFinSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
1 |
- |
Covered |
T1,T2,T3 |
IntegDigWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
Covered |
T3,T5,T24 |
IntegDigWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
- |
Covered |
T49,T39,T50 |
IntegDigWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
Covered |
T1,T2,T3 |
ErrorSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
Covered |
T19,T20,T21 |
ErrorSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
Covered |
T2,T4,T6 |
default |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T19,T20,T21 |
595 if (ecc_err) begin
-1-
596 state_d = ErrorSt;
597 if (state_q != ErrorSt) begin
-2-
598 error_d = CheckFailError;
==>
599 end
MISSING_ELSE
==>
600 end
MISSING_ELSE
==>
Branches:
-1- | -2- | Status | Tests |
1 |
1 |
Not Covered |
|
1 |
0 |
Not Covered |
|
0 |
- |
Covered |
T1,T2,T3 |
602 if (lc_ctrl_pkg::lc_tx_test_true_loose(escalate_en_i) || cnt_err) begin
-1-
603 state_d = ErrorSt;
604 fsm_err_o = 1'b1;
605 if (state_q != ErrorSt) begin
-2-
606 error_d = FsmStateError;
==>
607 end
MISSING_ELSE
==>
608 end
MISSING_ELSE
==>
Branches:
-1- | -2- | Status | Tests |
1 |
1 |
Covered |
T2,T4,T6 |
1 |
0 |
Covered |
T2,T4,T6 |
0 |
- |
Covered |
T1,T2,T3 |
750 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt)
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
753 if (!rst_ni) begin
-1-
754 error_q <= NoError;
==>
755 // data output is locked by default
756 dout_locked_q <= MuBi8True;
757 end else begin
758 error_q <= error_d;
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
Branch Coverage for Module :
otp_ctrl_part_buf ( parameter Info=-1,CntWidth=4,DigestOffset=2040,StateWidth=12 )
Branch Coverage for Module self-instances :
| Line No. | Total | Covered | Percent |
Branches |
|
56 |
38 |
67.86 |
TERNARY |
636 |
2 |
1 |
50.00 |
TERNARY |
652 |
2 |
1 |
50.00 |
TERNARY |
678 |
2 |
2 |
100.00 |
CASE |
240 |
40 |
26 |
65.00 |
IF |
595 |
3 |
1 |
33.33 |
IF |
602 |
3 |
3 |
100.00 |
IF |
750 |
2 |
2 |
100.00 |
IF |
753 |
2 |
2 |
100.00 |
636 assign addr_base = (base_sel == DigOffset) ? DigestOffset : Info.offset;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Not Covered |
|
0 |
Covered |
T1,T2,T3 |
652 assign data_mux = (data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Not Covered |
|
0 |
Covered |
T1,T2,T3 |
678 assign data_o = (init_done_o) ? data : DataDefault;
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
240 unique case (state_q)
-1-
241 ///////////////////////////////////////////////////////////////////
242 // State right after reset. Wait here until we get a an
243 // initialization request.
244 ResetSt: begin
245 if (init_req_i) begin
-2-
246 state_d = InitSt;
==>
247 end
MISSING_ELSE
==>
248 end
249 ///////////////////////////////////////////////////////////////////
250 // Initialization reads out the digest only in unbuffered
251 // partitions. Wait here until the OTP request has been granted.
252 // And then wait until the OTP word comes back.
253 InitSt: begin
254 otp_req_o = 1'b1;
255 if (otp_gnt_i) begin
-3-
256 state_d = InitWaitSt;
==>
257 end
MISSING_ELSE
==>
258 end
259 ///////////////////////////////////////////////////////////////////
260 // Wait for OTP response and write to buffer register, then go to
261 // descrambling state. In case an OTP transaction fails, latch the
262 // OTP error code and jump to a
263 // terminal error state.
264 InitWaitSt: begin
265 if (otp_rvalid_i) begin
-4-
266 buffer_reg_en = 1'b1;
267 if (otp_err inside {NoError, MacroEccCorrError}) begin
-5-
268 // Once we've read and descrambled the whole partition, we can go to integrity
269 // verification. Note that the last block is the digest value, which does not
270 // have to be descrambled.
271 if (cnt == LastScrmblBlock) begin
-6-
272 state_d = IntegDigClrSt;
==>
273 // Only need to descramble if this is a scrambled partition.
274 // Otherwise, we can just go back to InitSt and read the next block.
275 end else if (Info.secret) begin
-7-
276 state_d = InitDescrSt;
==> (Unreachable)
277 end else begin
278 state_d = InitSt;
==>
279 cnt_en = 1'b1;
280 end
281 // At this point the only error that we could have gotten are correctable ECC errors.
282 if (otp_err != NoError) begin
-8-
283 error_d = MacroEccCorrError;
==>
284 end
MISSING_ELSE
==>
285 end else begin
286 state_d = ErrorSt;
==>
287 error_d = otp_err;
288 end
289 end
MISSING_ELSE
==>
290 end
291 ///////////////////////////////////////////////////////////////////
292 // Descrambling state. This first acquires the scrambling
293 // datapath mutex. Note that once the mutex is acquired, we have
294 // exclusive access to the scrambling datapath until we release
295 // the mutex by deasserting scrmbl_mtx_req_o.
296 // SEC_CM: SECRET.MEM.SCRAMBLE
297 InitDescrSt: begin
298 scrmbl_mtx_req_o = 1'b1;
299 scrmbl_valid_o = 1'b1;
300 scrmbl_cmd_o = Decrypt;
301 scrmbl_sel_o = Info.key_sel;
302 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
-9-
303 state_d = InitDescrWaitSt;
==> (Unreachable)
304 end
MISSING_ELSE
==>
305 end
306 ///////////////////////////////////////////////////////////////////
307 // Wait for the descrambled data to return. Note that we release
308 // the mutex lock upon leaving this state.
309 // SEC_CM: SECRET.MEM.SCRAMBLE
310 InitDescrWaitSt: begin
311 scrmbl_mtx_req_o = 1'b1;
312 scrmbl_sel_o = Info.key_sel;
313 data_sel = ScrmblData;
314 if (scrmbl_valid_i) begin
-10-
315 state_d = InitSt;
==> (Unreachable)
316 buffer_reg_en = 1'b1;
317 cnt_en = 1'b1;
318 end
MISSING_ELSE
==>
319 end
320 ///////////////////////////////////////////////////////////////////
321 // Idle state. We basically wait for integrity and consistency check
322 // triggers in this state.
323 IdleSt: begin
324 if (integ_chk_req_i) begin
-11-
325 if (Info.hw_digest) begin
-12-
326 state_d = IntegDigClrSt;
==> (Unreachable)
327 // In case there is nothing to check we can just
328 // acknowledge the request right away, without going to the
329 // integrity check.
330 end else begin
331 integ_chk_ack_o = 1'b1;
==>
332 end
333 end else if (cnsty_chk_req_i) begin
-13-
334 state_d = CnstyReadSt;
==>
335 cnt_clr = 1'b1;
336 end
MISSING_ELSE
==>
337 end
338 ///////////////////////////////////////////////////////////////////
339 // Read the digest. Wait here until the OTP request has been granted.
340 // And then wait until the OTP word comes back.
341 // SEC_CM: PART.DATA_REG.BKGN_CHK
342 CnstyReadSt: begin
343 otp_req_o = 1'b1;
344 // In case this partition has a hardware digest, we only have to read
345 // and compare the digest value. In that case we select the digest offset here.
346 // Otherwise we have to read and compare the whole partition, in which case we
347 // select the partition offset, which is the default assignment of base_sel.
348 if (Info.hw_digest) begin
-14-
349 base_sel = DigOffset;
==> (Unreachable)
350 end
MISSING_ELSE
==>
351 if (otp_gnt_i) begin
-15-
352 state_d = CnstyReadWaitSt;
==>
353 end
MISSING_ELSE
==>
354 end
355 ///////////////////////////////////////////////////////////////////
356 // Wait for OTP response and compare the digest. In case there is
357 // a mismatch, lock down the partition and go into the terminal error
358 // state. In case an OTP transaction fails, latch the OTP error code
359 // and jump to a terminal error state.
360 // SEC_CM: PART.DATA_REG.BKGN_CHK
361 CnstyReadWaitSt: begin
362 if (otp_rvalid_i) begin
-16-
363 if (otp_err inside {NoError, MacroEccCorrError}) begin
-17-
364 // Check whether we need to compare the digest or the full partition
365 // contents here.
366 if (Info.hw_digest) begin
-18-
367 // Note that we ignore this check if the digest is still blank.
368 if (digest_o == data_mux || digest_o == '0) begin
-19-
369 state_d = IdleSt;
==> (Unreachable)
370 cnsty_chk_ack_o = 1'b1;
371 // Error out and lock the partition if this check fails.
372 end else begin
373 state_d = ErrorSt;
==> (Unreachable)
374 error_d = CheckFailError;
375 // The check has finished and found an error.
376 cnsty_chk_ack_o = 1'b1;
377 end
378 end else begin
379 // Check whether the read data corresponds with the data buffered in regs.
380 // Note that this particular check can be bypassed in case a transition is ongoing.
381 if (scrmbl_data_o == data_mux ||
-20-
382 lc_ctrl_pkg::lc_tx_test_true_strict(check_byp_en_i)) begin
383 // Can go back to idle and acknowledge the
384 // request if this is the last block.
385 if (cnt == LastScrmblBlock) begin
-21-
386 state_d = IdleSt;
==>
387 cnsty_chk_ack_o = 1'b1;
388 // Need to go back and read out more blocks.
389 end else begin
390 state_d = CnstyReadSt;
==>
391 cnt_en = 1'b1;
392 end
393 end else begin
394 state_d = ErrorSt;
==>
395 error_d = CheckFailError;
396 // The check has finished and found an error.
397 cnsty_chk_ack_o = 1'b1;
398 end
399 end
400 // At this point the only error that we could have gotten are correctable ECC errors.
401 if (otp_err != NoError) begin
-22-
402 error_d = MacroEccCorrError;
==>
403 end
MISSING_ELSE
==>
404 end else begin
405 state_d = ErrorSt;
==>
406 error_d = otp_err;
407 // The check has finished and found an error.
408 cnsty_chk_ack_o = 1'b1;
409 end
410 end
MISSING_ELSE
==>
411 end
412 ///////////////////////////////////////////////////////////////////
413 // First, acquire the mutex for the digest and clear the digest state.
414 // SEC_CM: PART.DATA_REG.BKGN_CHK
415 IntegDigClrSt: begin
416 // Check whether this partition requires checking at all.
417 if (Info.hw_digest) begin
-23-
418 scrmbl_mtx_req_o = 1'b1;
419 scrmbl_valid_o = 1'b1;
420 cnt_clr = 1'b1;
421 // Need to reset the digest state and set it to chained
422 // mode if this partition is scrambled.
423 scrmbl_cmd_o = DigestInit;
424 if (Info.secret) begin
-24-
425 scrmbl_mode_o = ChainedMode;
426 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
-25-
427 state_d = IntegScrSt;
==> (Unreachable)
428 end
MISSING_ELSE
==>
429 // If this partition is not scrambled, we can just directly
430 // jump to the digest state.
431 end else begin
432 scrmbl_mode_o = StandardMode;
433 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin
-26-
434 state_d = IntegDigSt;
==> (Unreachable)
435 end
MISSING_ELSE
==>
436 end
437 // Otherwise, if this partition is not digest protected,
438 // we can just go to idle, since there is nothing to check.
439 // Note that we do not come back to this state in case there is no
440 // digest, and hence it is safe to unlock the buffer regs at this point.
441 // This is the only way the buffer regs can get unlocked.
442 end else begin
443 state_d = IdleSt;
444 if (mubi8_test_true_strict(dout_locked_q)) begin
-27-
445 dout_locked_d = MuBi8False;
==>
446 end
MISSING_ELSE
==>
447 end
448 end
449 ///////////////////////////////////////////////////////////////////
450 // Scramble buffered data (which is held in plaintext form).
451 // This moves the previous scrambling result into the shadow reg
452 // for later use.
453 // SEC_CM: PART.DATA_REG.BKGN_CHK
454 IntegScrSt: begin
455 scrmbl_mtx_req_o = 1'b1;
456 scrmbl_valid_o = 1'b1;
457 scrmbl_cmd_o = Encrypt;
458 scrmbl_sel_o = Info.key_sel;
459 if (scrmbl_ready_i) begin
-28-
460 state_d = IntegScrWaitSt;
==> (Unreachable)
461 end
MISSING_ELSE
==>
462 end
463 ///////////////////////////////////////////////////////////////////
464 // Wait for the scrambled data to return.
465 // SEC_CM: PART.DATA_REG.BKGN_CHK
466 IntegScrWaitSt: begin
467 scrmbl_mtx_req_o = 1'b1;
468 scrmbl_sel_o = Info.key_sel;
469 if (scrmbl_valid_i) begin
-29-
470 state_d = IntegDigSt;
==> (Unreachable)
471 end
MISSING_ELSE
==>
472 end
473 ///////////////////////////////////////////////////////////////////
474 // Push the word read into the scrambling datapath. The last
475 // block is repeated in case the number blocks in this partition
476 // is odd.
477 // SEC_CM: PART.MEM.DIGEST
478 // SEC_CM: PART.DATA_REG.BKGN_CHK
479 IntegDigSt: begin
480 scrmbl_mtx_req_o = 1'b1;
481 scrmbl_valid_o = 1'b1;
482 if (scrmbl_ready_i) begin
-30-
483 cnt_en = 1'b1;
484 // No need to digest the digest value itself
485 if (cnt == PenultimateScrmblBlock) begin
-31-
486 // Note that the digest operates on 128bit blocks since the data is fed in via the
487 // PRESENT key input. Therefore, we only trigger a digest update on every second
488 // 64bit block that is pushed into the scrambling datapath.
489 if (cnt[0]) begin
-32-
490 scrmbl_cmd_o = Digest;
==> (Unreachable)
491 state_d = IntegDigFinSt;
492 end else begin
493 state_d = IntegDigPadSt;
==> (Unreachable)
494 cnt_en = 1'b0;
495 end
496 end else begin
497 // Trigger digest round in case this is the second block in a row.
498 if (cnt[0]) begin
-33-
499 scrmbl_cmd_o = Digest;
==> (Unreachable)
500 end
MISSING_ELSE
==>
501 // Go back and scramble the next data block if this is
502 // a scrambled partition. Otherwise just stay here.
503 if (Info.secret) begin
-34-
504 state_d = IntegScrSt;
==> (Unreachable)
505 end
MISSING_ELSE
==>
506 end
507 end
MISSING_ELSE
==>
508 end
509 ///////////////////////////////////////////////////////////////////
510 // Padding state. When we get here, we've copied the last encryption
511 // result into the shadow register such that we've effectively
512 // repeated the last block twice in order to pad the data to 128bit.
513 // SEC_CM: PART.MEM.DIGEST
514 // SEC_CM: PART.DATA_REG.BKGN_CHK
515 IntegDigPadSt: begin
516 scrmbl_mtx_req_o = 1'b1;
517 scrmbl_valid_o = 1'b1;
518 scrmbl_cmd_o = Digest;
519 if (scrmbl_ready_i) begin
-35-
520 state_d = IntegDigFinSt;
==> (Unreachable)
521 end
MISSING_ELSE
==>
522 end
523 ///////////////////////////////////////////////////////////////////
524 // Trigger digest finalization and go wait for the result.
525 // SEC_CM: PART.MEM.DIGEST
526 // SEC_CM: PART.DATA_REG.BKGN_CHK
527 IntegDigFinSt: begin
528 scrmbl_mtx_req_o = 1'b1;
529 scrmbl_valid_o = 1'b1;
530 scrmbl_cmd_o = DigestFinalize;
531 if (scrmbl_ready_i) begin
-36-
532 state_d = IntegDigWaitSt;
==> (Unreachable)
533 end
MISSING_ELSE
==>
534 end
535 ///////////////////////////////////////////////////////////////////
536 // Wait for the digest to return, and double check whether the digest
537 // matches. If yes, unlock the partition. Otherwise, go into the terminal
538 // error state, where the partition will be locked down.
539 // SEC_CM: PART.MEM.DIGEST
540 // SEC_CM: PART.DATA_REG.BKGN_CHK
541 IntegDigWaitSt: begin
542 scrmbl_mtx_req_o = 1'b1;
543 data_sel = ScrmblData;
544 if (scrmbl_valid_i) begin
-37-
545 // This is the only way the buffer regs can get unlocked.
546 // Note that we ignore this check if the digest is still blank.
547 if (digest_o == data_mux || digest_o == '0) begin
-38-
548 state_d = IdleSt;
549 // If the partition is still locked, this is the first integrity check after
550 // initialization. This is the only way the buffer regs can get unlocked.
551 if (mubi8_test_true_strict(dout_locked_q)) begin
-39-
552 dout_locked_d = MuBi8False;
==> (Unreachable)
553 // Otherwise, this integrity check has requested by the LFSR timer, and we have
554 // to acknowledge its completion.
555 end else begin
556 integ_chk_ack_o = 1'b1;
==> (Unreachable)
557 end
558 // Error out and lock the partition if this check fails.
559 end else begin
560 state_d = ErrorSt;
==> (Unreachable)
561 error_d = CheckFailError;
562 // The check has finished and found an error.
563 integ_chk_ack_o = 1'b1;
564 end
565 end
MISSING_ELSE
==>
566 end
567 ///////////////////////////////////////////////////////////////////
568 // Terminal Error State. This locks access to the partition.
569 // Make sure the partition signals an error state if no error
570 // code has been latched so far, and lock the buffer regs down.
571 ErrorSt: begin
572 dout_locked_d = MuBi8True;
573 if (error_q == NoError) begin
-40-
574 error_d = FsmStateError;
==>
575 end
MISSING_ELSE
==>
576 // If we are in error state, we cannot execute the checks anymore.
577 // Hence the acknowledgements are returned immediately.
578 cnsty_chk_ack_o = 1'b1;
579 integ_chk_ack_o = 1'b1;
580 end
581 ///////////////////////////////////////////////////////////////////
582 // We should never get here. If we do (e.g. via a malicious
583 // glitch), error out immediately.
584 default: begin
585 state_d = ErrorSt;
==>
Branches:
-1- | -2- | -3- | -4- | -5- | -6- | -7- | -8- | -9- | -10- | -11- | -12- | -13- | -14- | -15- | -16- | -17- | -18- | -19- | -20- | -21- | -22- | -23- | -24- | -25- | -26- | -27- | -28- | -29- | -30- | -31- | -32- | -33- | -34- | -35- | -36- | -37- | -38- | -39- | -40- | Status | Tests |
ResetSt |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
ResetSt |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitSt |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitSt |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitWaitSt |
- |
- |
1 |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitWaitSt |
- |
- |
1 |
1 |
0 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
InitWaitSt |
- |
- |
1 |
1 |
0 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitWaitSt |
- |
- |
1 |
1 |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T61,T33,T28 |
InitWaitSt |
- |
- |
1 |
1 |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitWaitSt |
- |
- |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T52,T53,T79 |
InitWaitSt |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
InitDescrSt |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
InitDescrSt |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
InitDescrWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
InitDescrWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IdleSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
IdleSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T3,T5,T24 |
IdleSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T4,T6,T5 |
IdleSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
CnstyReadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
CnstyReadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T4,T6,T5 |
CnstyReadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T4,T6,T5 |
CnstyReadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T4,T6,T5 |
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T6,T5,T24 |
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T4,T6,T5 |
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T72,T80,T81 |
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T4,T6,T5 |
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T82,T83 |
CnstyReadWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T4,T6,T5 |
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T1,T2,T3 |
IntegDigClrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegScrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
IntegScrSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegScrWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
IntegScrWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
1 |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
1 |
- |
- |
- |
- |
- |
- |
- |
Unreachable |
|
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
- |
1 |
- |
- |
- |
- |
- |
- |
Unreachable |
|
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegDigSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Not Covered |
|
IntegDigPadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
- |
Unreachable |
|
IntegDigPadSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
- |
Not Covered |
|
IntegDigFinSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
- |
- |
- |
- |
Unreachable |
|
IntegDigFinSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
- |
Not Covered |
|
IntegDigWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
1 |
- |
Unreachable |
|
IntegDigWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
1 |
0 |
- |
Unreachable |
|
IntegDigWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
0 |
- |
- |
Unreachable |
|
IntegDigWaitSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
- |
- |
- |
Not Covered |
|
ErrorSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
1 |
Covered |
T19,T20,T21 |
ErrorSt |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
0 |
Covered |
T2,T4,T6 |
default |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
Covered |
T19,T20,T21 |
595 if (ecc_err) begin
-1-
596 state_d = ErrorSt;
597 if (state_q != ErrorSt) begin
-2-
598 error_d = CheckFailError;
==>
599 end
MISSING_ELSE
==>
600 end
MISSING_ELSE
==>
Branches:
-1- | -2- | Status | Tests |
1 |
1 |
Not Covered |
|
1 |
0 |
Not Covered |
|
0 |
- |
Covered |
T1,T2,T3 |
602 if (lc_ctrl_pkg::lc_tx_test_true_loose(escalate_en_i) || cnt_err) begin
-1-
603 state_d = ErrorSt;
604 fsm_err_o = 1'b1;
605 if (state_q != ErrorSt) begin
-2-
606 error_d = FsmStateError;
==>
607 end
MISSING_ELSE
==>
608 end
MISSING_ELSE
==>
Branches:
-1- | -2- | Status | Tests |
1 |
1 |
Covered |
T2,T4,T6 |
1 |
0 |
Covered |
T2,T4,T6 |
0 |
- |
Covered |
T1,T2,T3 |
750 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt)
-1-
==>
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
753 if (!rst_ni) begin
-1-
754 error_q <= NoError;
==>
755 // data output is locked by default
756 dout_locked_q <= MuBi8True;
757 end else begin
758 error_q <= error_d;
==>
Branches:
-1- | Status | Tests |
1 |
Covered |
T1,T2,T3 |
0 |
Covered |
T1,T2,T3 |
Assert Coverage for Module :
otp_ctrl_part_buf
Assertion Details
AccessKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
BypassEnable0_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
288187074 |
0 |
0 |
T1 |
14415 |
14226 |
0 |
0 |
T2 |
28146 |
27399 |
0 |
0 |
T3 |
77289 |
75918 |
0 |
0 |
T4 |
58353 |
57111 |
0 |
0 |
T5 |
90660 |
89577 |
0 |
0 |
T6 |
103059 |
101913 |
0 |
0 |
T7 |
10200 |
9930 |
0 |
0 |
T22 |
64467 |
64284 |
0 |
0 |
T23 |
32946 |
32112 |
0 |
0 |
T24 |
49362 |
48852 |
0 |
0 |
BypassEnable1_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
480311790 |
0 |
0 |
T1 |
24025 |
23710 |
0 |
0 |
T2 |
46910 |
45665 |
0 |
0 |
T3 |
128815 |
126530 |
0 |
0 |
T4 |
97255 |
95185 |
0 |
0 |
T5 |
151100 |
149295 |
0 |
0 |
T6 |
171765 |
169855 |
0 |
0 |
T7 |
17000 |
16550 |
0 |
0 |
T22 |
107445 |
107140 |
0 |
0 |
T23 |
54910 |
53520 |
0 |
0 |
T24 |
82270 |
81420 |
0 |
0 |
CnstyChkAckKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
DataKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
DigestKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
DigestOffsetMustBeRepresentable_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
6654 |
6654 |
0 |
0 |
T1 |
6 |
6 |
0 |
0 |
T2 |
6 |
6 |
0 |
0 |
T3 |
6 |
6 |
0 |
0 |
T4 |
6 |
6 |
0 |
0 |
T5 |
6 |
6 |
0 |
0 |
T6 |
6 |
6 |
0 |
0 |
T7 |
6 |
6 |
0 |
0 |
T22 |
6 |
6 |
0 |
0 |
T23 |
6 |
6 |
0 |
0 |
T24 |
6 |
6 |
0 |
0 |
EccErrorState_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
0 |
0 |
0 |
ErrorKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
InitDoneKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
InitReadLocksPartition_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
161455166 |
0 |
0 |
T1 |
28830 |
7674 |
0 |
0 |
T2 |
56292 |
37260 |
0 |
0 |
T3 |
154578 |
36299 |
0 |
0 |
T4 |
116706 |
41253 |
0 |
0 |
T5 |
181320 |
29928 |
0 |
0 |
T6 |
206118 |
156470 |
0 |
0 |
T7 |
20400 |
7476 |
0 |
0 |
T22 |
128934 |
13650 |
0 |
0 |
T23 |
65892 |
32184 |
0 |
0 |
T24 |
98724 |
19626 |
0 |
0 |
InitWriteLocksPartition_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
161455166 |
0 |
0 |
T1 |
28830 |
7674 |
0 |
0 |
T2 |
56292 |
37260 |
0 |
0 |
T3 |
154578 |
36299 |
0 |
0 |
T4 |
116706 |
41253 |
0 |
0 |
T5 |
181320 |
29928 |
0 |
0 |
T6 |
206118 |
156470 |
0 |
0 |
T7 |
20400 |
7476 |
0 |
0 |
T22 |
128934 |
13650 |
0 |
0 |
T23 |
65892 |
32184 |
0 |
0 |
T24 |
98724 |
19626 |
0 |
0 |
IntegChkAckKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
OffsetMustBeBlockAligned_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
6654 |
6654 |
0 |
0 |
T1 |
6 |
6 |
0 |
0 |
T2 |
6 |
6 |
0 |
0 |
T3 |
6 |
6 |
0 |
0 |
T4 |
6 |
6 |
0 |
0 |
T5 |
6 |
6 |
0 |
0 |
T6 |
6 |
6 |
0 |
0 |
T7 |
6 |
6 |
0 |
0 |
T22 |
6 |
6 |
0 |
0 |
T23 |
6 |
6 |
0 |
0 |
T24 |
6 |
6 |
0 |
0 |
OtpAddrKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
OtpCmdKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
OtpErrorState_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
96891327 |
8 |
0 |
0 |
T52 |
0 |
1 |
0 |
0 |
T53 |
0 |
1 |
0 |
0 |
T79 |
0 |
1 |
0 |
0 |
T82 |
544427 |
1 |
0 |
0 |
T83 |
0 |
1 |
0 |
0 |
T102 |
0 |
1 |
0 |
0 |
T103 |
0 |
1 |
0 |
0 |
T104 |
0 |
1 |
0 |
0 |
T105 |
198436 |
0 |
0 |
0 |
T106 |
5321 |
0 |
0 |
0 |
T107 |
44665 |
0 |
0 |
0 |
T108 |
34288 |
0 |
0 |
0 |
T109 |
53235 |
0 |
0 |
0 |
T110 |
135026 |
0 |
0 |
0 |
T111 |
59892 |
0 |
0 |
0 |
T112 |
15207 |
0 |
0 |
0 |
T113 |
14598 |
0 |
0 |
0 |
OtpPartBufSize_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
6654 |
6654 |
0 |
0 |
T1 |
6 |
6 |
0 |
0 |
T2 |
6 |
6 |
0 |
0 |
T3 |
6 |
6 |
0 |
0 |
T4 |
6 |
6 |
0 |
0 |
T5 |
6 |
6 |
0 |
0 |
T6 |
6 |
6 |
0 |
0 |
T7 |
6 |
6 |
0 |
0 |
T22 |
6 |
6 |
0 |
0 |
T23 |
6 |
6 |
0 |
0 |
T24 |
6 |
6 |
0 |
0 |
OtpReqKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
OtpSizeKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
OtpWdataKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
ReadLockImpliesDigest_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
480311790 |
0 |
0 |
T1 |
24025 |
23710 |
0 |
0 |
T2 |
46910 |
45665 |
0 |
0 |
T3 |
128815 |
126530 |
0 |
0 |
T4 |
97255 |
95185 |
0 |
0 |
T5 |
151100 |
149295 |
0 |
0 |
T6 |
171765 |
169855 |
0 |
0 |
T7 |
17000 |
16550 |
0 |
0 |
T22 |
107445 |
107140 |
0 |
0 |
T23 |
54910 |
53520 |
0 |
0 |
T24 |
82270 |
81420 |
0 |
0 |
ReadLockPropagation_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
138352524 |
0 |
0 |
T1 |
9610 |
4742 |
0 |
0 |
T2 |
18764 |
9133 |
0 |
0 |
T3 |
51526 |
25306 |
0 |
0 |
T4 |
38902 |
19037 |
0 |
0 |
T5 |
60440 |
29859 |
0 |
0 |
T6 |
68706 |
33971 |
0 |
0 |
T7 |
6800 |
3310 |
0 |
0 |
T8 |
9556 |
0 |
0 |
0 |
T10 |
0 |
11484 |
0 |
0 |
T15 |
137950 |
9181 |
0 |
0 |
T22 |
42978 |
21428 |
0 |
0 |
T23 |
21964 |
10704 |
0 |
0 |
T24 |
32908 |
16284 |
0 |
0 |
T25 |
44990 |
0 |
0 |
0 |
T36 |
0 |
17299 |
0 |
0 |
T85 |
81380 |
0 |
0 |
0 |
T88 |
0 |
1379 |
0 |
0 |
T90 |
0 |
5976 |
0 |
0 |
T91 |
57332 |
0 |
0 |
0 |
T92 |
67206 |
0 |
0 |
0 |
T94 |
0 |
7137 |
0 |
0 |
T114 |
46554 |
5186 |
0 |
0 |
T115 |
0 |
7692 |
0 |
0 |
T116 |
0 |
13459 |
0 |
0 |
T117 |
0 |
75863 |
0 |
0 |
T118 |
0 |
3569 |
0 |
0 |
T119 |
17512 |
0 |
0 |
0 |
T120 |
61024 |
0 |
0 |
0 |
T121 |
178608 |
0 |
0 |
0 |
ScrambledImpliesDigest_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
288187074 |
0 |
0 |
T1 |
14415 |
14226 |
0 |
0 |
T2 |
28146 |
27399 |
0 |
0 |
T3 |
77289 |
75918 |
0 |
0 |
T4 |
58353 |
57111 |
0 |
0 |
T5 |
90660 |
89577 |
0 |
0 |
T6 |
103059 |
101913 |
0 |
0 |
T7 |
10200 |
9930 |
0 |
0 |
T22 |
64467 |
64284 |
0 |
0 |
T23 |
32946 |
32112 |
0 |
0 |
T24 |
49362 |
48852 |
0 |
0 |
ScrmblCmdKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
ScrmblDataKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
577649902 |
572762392 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
ScrmblModeKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
ScrmblMtxReqKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
ScrmblSelKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
ScrmblValidKnown_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |
SizeMustBeBlockAligned_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
6654 |
6654 |
0 |
0 |
T1 |
6 |
6 |
0 |
0 |
T2 |
6 |
6 |
0 |
0 |
T3 |
6 |
6 |
0 |
0 |
T4 |
6 |
6 |
0 |
0 |
T5 |
6 |
6 |
0 |
0 |
T6 |
6 |
6 |
0 |
0 |
T7 |
6 |
6 |
0 |
0 |
T22 |
6 |
6 |
0 |
0 |
T23 |
6 |
6 |
0 |
0 |
T24 |
6 |
6 |
0 |
0 |
WriteLockImpliesDigest_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
288187074 |
0 |
0 |
T1 |
14415 |
14226 |
0 |
0 |
T2 |
28146 |
27399 |
0 |
0 |
T3 |
77289 |
75918 |
0 |
0 |
T4 |
58353 |
57111 |
0 |
0 |
T5 |
90660 |
89577 |
0 |
0 |
T6 |
103059 |
101913 |
0 |
0 |
T7 |
10200 |
9930 |
0 |
0 |
T22 |
64467 |
64284 |
0 |
0 |
T23 |
32946 |
32112 |
0 |
0 |
T24 |
49362 |
48852 |
0 |
0 |
WriteLockPropagation_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
145747696 |
0 |
0 |
T1 |
4805 |
4742 |
0 |
0 |
T2 |
9382 |
9133 |
0 |
0 |
T3 |
25763 |
25306 |
0 |
0 |
T4 |
19451 |
19037 |
0 |
0 |
T5 |
30220 |
29859 |
0 |
0 |
T6 |
34353 |
33971 |
0 |
0 |
T7 |
3400 |
3310 |
0 |
0 |
T8 |
14334 |
0 |
0 |
0 |
T9 |
0 |
13803 |
0 |
0 |
T10 |
0 |
5503 |
0 |
0 |
T15 |
137950 |
7288 |
0 |
0 |
T22 |
21489 |
21428 |
0 |
0 |
T23 |
10982 |
10704 |
0 |
0 |
T24 |
16454 |
16284 |
0 |
0 |
T25 |
67485 |
0 |
0 |
0 |
T85 |
122070 |
2574 |
0 |
0 |
T88 |
0 |
8974 |
0 |
0 |
T91 |
57332 |
0 |
0 |
0 |
T92 |
100809 |
0 |
0 |
0 |
T94 |
0 |
20553 |
0 |
0 |
T114 |
69831 |
5186 |
0 |
0 |
T117 |
0 |
117173 |
0 |
0 |
T119 |
26268 |
0 |
0 |
0 |
T120 |
91536 |
0 |
0 |
0 |
T121 |
267912 |
0 |
0 |
0 |
T122 |
0 |
3087 |
0 |
0 |
T123 |
0 |
12669 |
0 |
0 |
T124 |
0 |
12746 |
0 |
0 |
T125 |
19001 |
0 |
0 |
0 |
gen_digest_read_lock.DigestReadLocksPartition_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
290673981 |
87911400 |
0 |
0 |
T3 |
77289 |
9111 |
0 |
0 |
T4 |
58353 |
5010 |
0 |
0 |
T5 |
90660 |
30398 |
0 |
0 |
T6 |
103059 |
3707 |
0 |
0 |
T7 |
10200 |
0 |
0 |
0 |
T9 |
0 |
36776 |
0 |
0 |
T14 |
53997 |
0 |
0 |
0 |
T15 |
206925 |
86455 |
0 |
0 |
T22 |
64467 |
0 |
0 |
0 |
T23 |
32946 |
0 |
0 |
0 |
T24 |
49362 |
8205 |
0 |
0 |
T36 |
0 |
60861 |
0 |
0 |
T85 |
0 |
36932 |
0 |
0 |
T88 |
0 |
121350 |
0 |
0 |
T90 |
0 |
63887 |
0 |
0 |
T94 |
0 |
33630 |
0 |
0 |
T114 |
0 |
15841 |
0 |
0 |
T115 |
0 |
2443 |
0 |
0 |
T126 |
0 |
5618 |
0 |
0 |
T127 |
0 |
19764 |
0 |
0 |
gen_digest_write_lock.DigestWriteLocksPartition_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
484456635 |
162777799 |
0 |
0 |
T2 |
9382 |
3606 |
0 |
0 |
T3 |
103052 |
11931 |
0 |
0 |
T4 |
97255 |
9969 |
0 |
0 |
T5 |
151100 |
64680 |
0 |
0 |
T6 |
171765 |
3707 |
0 |
0 |
T7 |
17000 |
0 |
0 |
0 |
T9 |
0 |
58758 |
0 |
0 |
T14 |
89995 |
4465 |
0 |
0 |
T15 |
275900 |
196010 |
0 |
0 |
T22 |
107445 |
0 |
0 |
0 |
T23 |
54910 |
0 |
0 |
0 |
T24 |
82270 |
12653 |
0 |
0 |
T36 |
0 |
60861 |
0 |
0 |
T85 |
0 |
87779 |
0 |
0 |
T88 |
0 |
218770 |
0 |
0 |
T90 |
0 |
72229 |
0 |
0 |
T91 |
28666 |
0 |
0 |
0 |
T94 |
0 |
33630 |
0 |
0 |
T114 |
0 |
32696 |
0 |
0 |
T115 |
0 |
2443 |
0 |
0 |
T119 |
0 |
7480 |
0 |
0 |
T126 |
0 |
8063 |
0 |
0 |
T127 |
0 |
19764 |
0 |
0 |
u_state_regs_A
Name | Attempts | Real Successes | Failures | Incomplete |
Total |
581347962 |
576374148 |
0 |
0 |
T1 |
28830 |
28452 |
0 |
0 |
T2 |
56292 |
54798 |
0 |
0 |
T3 |
154578 |
151836 |
0 |
0 |
T4 |
116706 |
114222 |
0 |
0 |
T5 |
181320 |
179154 |
0 |
0 |
T6 |
206118 |
203826 |
0 |
0 |
T7 |
20400 |
19860 |
0 |
0 |
T22 |
128934 |
128568 |
0 |
0 |
T23 |
65892 |
64224 |
0 |
0 |
T24 |
98724 |
97704 |
0 |
0 |