Module Definition
dashboard | hierarchy | modlist | groups | tests | asserts

Line Coverage for Module : otp_ctrl_part_buf ( parameter Info=-1,CntWidth=4,DigestOffset=1720,StateWidth=12 )
Line Coverage for Module self-instances :
SCORELINE
93.18 97.64
tb.dut.gen_partitions[5].gen_buffered.u_part_buf

Line No.TotalCoveredPercent
TOTAL16012477.50
CONT_ASSIGN18211100.00
CONT_ASSIGN19311100.00
ALWAYS20614010474.29
CONT_ASSIGN63611100.00
CONT_ASSIGN64111100.00
CONT_ASSIGN64211100.00
CONT_ASSIGN64611100.00
CONT_ASSIGN65211100.00
CONT_ASSIGN67511100.00
CONT_ASSIGN67811100.00
CONT_ASSIGN68011100.00
CONT_ASSIGN70911100.00
CONT_ASSIGN74311100.00
ALWAYS75033100.00
ALWAYS75355100.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 T24 T34  326 1/1 state_d = IntegDigClrSt; Tests: T3 T24 T34  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 T5 T24  335 1/1 cnt_clr = 1'b1; Tests: T4 T5 T24  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 T5 T24  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 T5 T24  349 1/1 base_sel = DigOffset; Tests: T4 T5 T24  350 end ==> MISSING_ELSE 351 1/1 if (otp_gnt_i) begin Tests: T4 T5 T24  352 1/1 state_d = CnstyReadWaitSt; Tests: T4 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: T4 T5 T24  363 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin Tests: T4 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: T4 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: T4 T5 T24  369 1/1 state_d = IdleSt; Tests: T4 T5 T24  370 1/1 cnsty_chk_ack_o = 1'b1; Tests: T4 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: T4 T5 T24  402 1/1 error_d = MacroEccCorrError; Tests: T35 T36 T37  403 end MISSING_ELSE 404 end else begin 405 1/1 state_d = ErrorSt; Tests: T38 T39 T40  406 1/1 error_d = otp_err; Tests: T38 T39 T40  407 // The check has finished and found an error. 408 1/1 cnsty_chk_ack_o = 1'b1; Tests: T38 T39 T40  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 T24 T34  557 end 558 // Error out and lock the partition if this check fails. 559 end else begin 560 1/1 state_d = ErrorSt; Tests: T41 T42 T43  561 1/1 error_d = CheckFailError; Tests: T41 T42 T43  562 // The check has finished and found an error. 563 1/1 integ_chk_ack_o = 1'b1; Tests: T41 T42 T43  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 T44  573 1/1 if (error_q == NoError) begin Tests: T2 T4 T44  574 1/1 error_d = FsmStateError; Tests: T25 T26 T27  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 T44  579 1/1 integ_chk_ack_o = 1'b1; Tests: T2 T4 T44  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 T44  604 1/1 fsm_err_o = 1'b1; Tests: T2 T4 T44  605 1/1 if (state_q != ErrorSt) begin Tests: T2 T4 T44  606 1/1 error_d = FsmStateError; Tests: T2 T4 T44  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 :
SCORELINE
90.75 95.45
tb.dut.gen_partitions[6].gen_buffered.u_part_buf

Line No.TotalCoveredPercent
TOTAL16012678.75
CONT_ASSIGN18211100.00
CONT_ASSIGN19311100.00
ALWAYS20614010675.71
CONT_ASSIGN63611100.00
CONT_ASSIGN64111100.00
CONT_ASSIGN64211100.00
CONT_ASSIGN64611100.00
CONT_ASSIGN65211100.00
CONT_ASSIGN67511100.00
CONT_ASSIGN67811100.00
CONT_ASSIGN68011100.00
CONT_ASSIGN70911100.00
CONT_ASSIGN74311100.00
ALWAYS75033100.00
ALWAYS75355100.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: T31 T28 T29  284 end MISSING_ELSE 285 end else begin 286 1/1 state_d = ErrorSt; Tests: T45 T46 T47  287 1/1 error_d = otp_err; Tests: T45 T46 T47  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 T24 T34  326 1/1 state_d = IntegDigClrSt; Tests: T3 T24 T34  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 T5 T24  335 1/1 cnt_clr = 1'b1; Tests: T4 T5 T24  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 T5 T24  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 T5 T24  349 1/1 base_sel = DigOffset; Tests: T4 T5 T24  350 end ==> MISSING_ELSE 351 1/1 if (otp_gnt_i) begin Tests: T4 T5 T24  352 1/1 state_d = CnstyReadWaitSt; Tests: T4 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: T4 T5 T24  363 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin Tests: T4 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: T4 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: T4 T5 T24  369 1/1 state_d = IdleSt; Tests: T4 T5 T24  370 1/1 cnsty_chk_ack_o = 1'b1; Tests: T4 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: T4 T5 T24  402 1/1 error_d = MacroEccCorrError; Tests: T48 T49  403 end MISSING_ELSE 404 end else begin 405 1/1 state_d = ErrorSt; Tests: T50 T51 T52  406 1/1 error_d = otp_err; Tests: T50 T51 T52  407 // The check has finished and found an error. 408 1/1 cnsty_chk_ack_o = 1'b1; Tests: T50 T51 T52  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 T24 T34  557 end 558 // Error out and lock the partition if this check fails. 559 end else begin 560 1/1 state_d = ErrorSt; Tests: T53 T54 T55  561 1/1 error_d = CheckFailError; Tests: T53 T54 T55  562 // The check has finished and found an error. 563 1/1 integ_chk_ack_o = 1'b1; Tests: T53 T54 T55  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 T44  573 1/1 if (error_q == NoError) begin Tests: T2 T4 T44  574 1/1 error_d = FsmStateError; Tests: T25 T26 T27  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 T44  579 1/1 integ_chk_ack_o = 1'b1; Tests: T2 T4 T44  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 T44  604 1/1 fsm_err_o = 1'b1; Tests: T2 T4 T44  605 1/1 if (state_q != ErrorSt) begin Tests: T2 T4 T44  606 1/1 error_d = FsmStateError; Tests: T2 T4 T44  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 :
SCORELINE
96.06 98.00
tb.dut.gen_partitions[7].gen_buffered.u_part_buf

Line No.TotalCoveredPercent
TOTAL16014791.88
CONT_ASSIGN18211100.00
CONT_ASSIGN19311100.00
ALWAYS20614012790.71
CONT_ASSIGN63611100.00
CONT_ASSIGN64111100.00
CONT_ASSIGN64211100.00
CONT_ASSIGN64611100.00
CONT_ASSIGN65211100.00
CONT_ASSIGN67511100.00
CONT_ASSIGN67811100.00
CONT_ASSIGN68011100.00
CONT_ASSIGN70911100.00
CONT_ASSIGN72911100.00
ALWAYS75033100.00
ALWAYS75355100.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: T29 T30 T56  284 end MISSING_ELSE 285 end else begin 286 1/1 state_d = ErrorSt; Tests: T57 T58 T59  287 1/1 error_d = otp_err; Tests: T57 T58 T59  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 T24 T34  326 1/1 state_d = IntegDigClrSt; Tests: T3 T24 T34  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 T5 T24  335 1/1 cnt_clr = 1'b1; Tests: T4 T5 T24  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 T5 T24  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 T5 T24  349 1/1 base_sel = DigOffset; Tests: T4 T5 T24  350 end ==> MISSING_ELSE 351 1/1 if (otp_gnt_i) begin Tests: T4 T5 T24  352 1/1 state_d = CnstyReadWaitSt; Tests: T4 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: T4 T5 T24  363 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin Tests: T4 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: T4 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: T4 T5 T24  369 1/1 state_d = IdleSt; Tests: T4 T5 T24  370 1/1 cnsty_chk_ack_o = 1'b1; Tests: T4 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: T4 T5 T24  402 1/1 error_d = MacroEccCorrError; Tests: T60 T61 T62  403 end MISSING_ELSE 404 end else begin 405 1/1 state_d = ErrorSt; Tests: T40  406 1/1 error_d = otp_err; Tests: T40  407 // The check has finished and found an error. 408 1/1 cnsty_chk_ack_o = 1'b1; Tests: T40  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 T24 T34  557 end 558 // Error out and lock the partition if this check fails. 559 end else begin 560 1/1 state_d = ErrorSt; Tests: T2 T63 T64  561 1/1 error_d = CheckFailError; Tests: T2 T63 T64  562 // The check has finished and found an error. 563 1/1 integ_chk_ack_o = 1'b1; Tests: T2 T63 T64  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 T44  573 1/1 if (error_q == NoError) begin Tests: T2 T4 T44  574 1/1 error_d = FsmStateError; Tests: T25 T26 T27  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 T44  579 1/1 integ_chk_ack_o = 1'b1; Tests: T2 T4 T44  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 T44  604 1/1 fsm_err_o = 1'b1; Tests: T2 T4 T44  605 1/1 if (state_q != ErrorSt) begin Tests: T2 T4 T44  606 1/1 error_d = FsmStateError; Tests: T4 T44 T31  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 :
SCORELINE
94.39 98.00
tb.dut.gen_partitions[8].gen_buffered.u_part_buf

Line No.TotalCoveredPercent
TOTAL16014791.88
CONT_ASSIGN18211100.00
CONT_ASSIGN19311100.00
ALWAYS20614012790.71
CONT_ASSIGN63611100.00
CONT_ASSIGN64111100.00
CONT_ASSIGN64211100.00
CONT_ASSIGN64611100.00
CONT_ASSIGN65211100.00
CONT_ASSIGN67511100.00
CONT_ASSIGN67811100.00
CONT_ASSIGN68011100.00
CONT_ASSIGN70911100.00
CONT_ASSIGN72911100.00
ALWAYS75033100.00
ALWAYS75355100.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: T29 T56 T65  284 end MISSING_ELSE 285 end else begin 286 1/1 state_d = ErrorSt; Tests: T66 T67 T68  287 1/1 error_d = otp_err; Tests: T66 T67 T68  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 T24 T34  326 1/1 state_d = IntegDigClrSt; Tests: T3 T24 T34  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 T5 T24  335 1/1 cnt_clr = 1'b1; Tests: T4 T5 T24  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 T5 T24  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 T5 T24  349 1/1 base_sel = DigOffset; Tests: T4 T5 T24  350 end ==> MISSING_ELSE 351 1/1 if (otp_gnt_i) begin Tests: T4 T5 T24  352 1/1 state_d = CnstyReadWaitSt; Tests: T4 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: T4 T5 T24  363 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin Tests: T4 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: T4 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: T4 T5 T24  369 1/1 state_d = IdleSt; Tests: T4 T5 T24  370 1/1 cnsty_chk_ack_o = 1'b1; Tests: T4 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: T4 T5 T24  402 1/1 error_d = MacroEccCorrError; Tests: T50 T39 T69  403 end MISSING_ELSE 404 end else begin 405 1/1 state_d = ErrorSt; Tests: T70 T71 T52  406 1/1 error_d = otp_err; Tests: T70 T71 T52  407 // The check has finished and found an error. 408 1/1 cnsty_chk_ack_o = 1'b1; Tests: T70 T71 T52  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 T24 T34  557 end 558 // Error out and lock the partition if this check fails. 559 end else begin 560 1/1 state_d = ErrorSt; Tests: T72 T73  561 1/1 error_d = CheckFailError; Tests: T72 T73  562 // The check has finished and found an error. 563 1/1 integ_chk_ack_o = 1'b1; Tests: T72 T73  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 T44  573 1/1 if (error_q == NoError) begin Tests: T2 T4 T44  574 1/1 error_d = FsmStateError; Tests: T25 T26 T27  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 T44  579 1/1 integ_chk_ack_o = 1'b1; Tests: T2 T4 T44  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 T44  604 1/1 fsm_err_o = 1'b1; Tests: T2 T4 T44  605 1/1 if (state_q != ErrorSt) begin Tests: T2 T4 T44  606 1/1 error_d = FsmStateError; Tests: T2 T4 T44  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 :
SCORELINE
92.96 95.33
tb.dut.gen_partitions[9].gen_buffered.u_part_buf

Line No.TotalCoveredPercent
TOTAL16014389.38
CONT_ASSIGN18211100.00
CONT_ASSIGN19311100.00
ALWAYS20614012387.86
CONT_ASSIGN63611100.00
CONT_ASSIGN64111100.00
CONT_ASSIGN64211100.00
CONT_ASSIGN64611100.00
CONT_ASSIGN65211100.00
CONT_ASSIGN67511100.00
CONT_ASSIGN67811100.00
CONT_ASSIGN68011100.00
CONT_ASSIGN70911100.00
CONT_ASSIGN72911100.00
ALWAYS75033100.00
ALWAYS75355100.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: T74 T65 T75  284 end MISSING_ELSE 285 end else begin 286 1/1 state_d = ErrorSt; Tests: T28 T76 T77  287 1/1 error_d = otp_err; Tests: T28 T76 T77  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 T24 T34  326 1/1 state_d = IntegDigClrSt; Tests: T3 T24 T34  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 T5 T24  335 1/1 cnt_clr = 1'b1; Tests: T4 T5 T24  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 T5 T24  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 T5 T24  349 1/1 base_sel = DigOffset; Tests: T4 T5 T24  350 end ==> MISSING_ELSE 351 1/1 if (otp_gnt_i) begin Tests: T4 T5 T24  352 1/1 state_d = CnstyReadWaitSt; Tests: T4 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: T4 T5 T24  363 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin Tests: T4 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: T4 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: T4 T5 T24  369 1/1 state_d = IdleSt; Tests: T4 T5 T24  370 1/1 cnsty_chk_ack_o = 1'b1; Tests: T4 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: T4 T5 T24  402 0/1 ==> error_d = MacroEccCorrError; 403 end MISSING_ELSE 404 end else begin 405 1/1 state_d = ErrorSt; Tests: T78 T61 T79  406 1/1 error_d = otp_err; Tests: T78 T61 T79  407 // The check has finished and found an error. 408 1/1 cnsty_chk_ack_o = 1'b1; Tests: T78 T61 T79  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 T24 T34  557 end 558 // Error out and lock the partition if this check fails. 559 end else begin 560 0/1 ==> state_d = ErrorSt; 561 0/1 ==> error_d = CheckFailError; 562 // The check has finished and found an error. 563 0/1 ==> 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 T44  573 1/1 if (error_q == NoError) begin Tests: T2 T4 T44  574 1/1 error_d = FsmStateError; Tests: T25 T26 T27  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 T44  579 1/1 integ_chk_ack_o = 1'b1; Tests: T2 T4 T44  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 T44  604 1/1 fsm_err_o = 1'b1; Tests: T2 T4 T44  605 1/1 if (state_q != ErrorSt) begin Tests: T2 T4 T44  606 1/1 error_d = FsmStateError; Tests: T2 T4 T44  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 :
SCORELINE
94.90 96.91
tb.dut.gen_partitions[10].gen_lifecycle.u_part_buf

Line No.TotalCoveredPercent
TOTAL1319471.76
CONT_ASSIGN18211100.00
CONT_ASSIGN19311100.00
ALWAYS2061117769.37
CONT_ASSIGN636100.00
CONT_ASSIGN64111100.00
CONT_ASSIGN64211100.00
CONT_ASSIGN64611100.00
CONT_ASSIGN65211100.00
CONT_ASSIGN67511100.00
CONT_ASSIGN67811100.00
CONT_ASSIGN68011100.00
CONT_ASSIGN723100.00
CONT_ASSIGN743100.00
ALWAYS75033100.00
ALWAYS75355100.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: T80 T81 T82  284 end MISSING_ELSE 285 end else begin 286 1/1 state_d = ErrorSt; Tests: T83 T84 T85  287 1/1 error_d = otp_err; Tests: T83 T84 T85  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 T24 T34  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 T24 T34  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 T5 T24  335 1/1 cnt_clr = 1'b1; Tests: T4 T5 T24  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 T5 T24  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 T5 T24  349 unreachable base_sel = DigOffset; 350 end MISSING_ELSE 351 1/1 if (otp_gnt_i) begin Tests: T4 T5 T24  352 1/1 state_d = CnstyReadWaitSt; Tests: T4 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: T4 T5 T24  363 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin Tests: T4 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: T4 T5 T24  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 T5 T24  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 T5 T24  386 1/1 state_d = IdleSt; Tests: T4 T5 T24  387 1/1 cnsty_chk_ack_o = 1'b1; Tests: T4 T5 T24  388 // Need to go back and read out more blocks. 389 end else begin 390 1/1 state_d = CnstyReadSt; Tests: T4 T5 T24  391 1/1 cnt_en = 1'b1; Tests: T4 T5 T24  392 end 393 end else begin 394 1/1 state_d = ErrorSt; Tests: T30 T56 T86  395 1/1 error_d = CheckFailError; Tests: T30 T56 T86  396 // The check has finished and found an error. 397 1/1 cnsty_chk_ack_o = 1'b1; Tests: T30 T56 T86  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 T5 T24  402 1/1 error_d = MacroEccCorrError; Tests: T87 T88 T89  403 end MISSING_ELSE 404 end else begin 405 1/1 state_d = ErrorSt; Tests: T51 T90  406 1/1 error_d = otp_err; Tests: T51 T90  407 // The check has finished and found an error. 408 1/1 cnsty_chk_ack_o = 1'b1; Tests: T51 T90  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 T44  573 1/1 if (error_q == NoError) begin Tests: T2 T4 T44  574 1/1 error_d = FsmStateError; Tests: T25 T26 T27  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 T44  579 1/1 integ_chk_ack_o = 1'b1; Tests: T2 T4 T44  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 T44  604 1/1 fsm_err_o = 1'b1; Tests: T2 T4 T44  605 1/1 if (state_q != ErrorSt) begin Tests: T2 T4 T44  606 1/1 error_d = FsmStateError; Tests: T2 T4 T44  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 :
SCORECOND
93.18 95.24
tb.dut.gen_partitions[5].gen_buffered.u_part_buf

TotalCoveredPercent
Conditions484083.33
Logical484083.33
Non-Logical00
Event00

 LINE       271
 EXPRESSION (cnt == LastScrmblBlock)
            ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       282
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT28,T29,T30

 LINE       302
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Not Covered
10Not Covered
11Not Covered

 LINE       368
 EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
             -----------1----------    --------2-------
-1--2-StatusTests
00Not Covered
01CoveredT9,T21,T22
10CoveredT91,T17,T92

 LINE       368
 SUB-EXPRESSION (digest_o == data_mux)
                -----------1----------
-1-StatusTests
0CoveredT9,T21,T22
1CoveredT4,T5,T24

 LINE       368
 SUB-EXPRESSION (digest_o == '0)
                --------1-------
-1-StatusTests
0CoveredT91,T17,T92
1CoveredT4,T5,T24

 LINE       385
 EXPRESSION (cnt == LastScrmblBlock)
            ------------1-----------
-1-StatusTests
0Unreachable
1Unreachable

 LINE       401
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT4,T5,T24
1CoveredT35,T36,T37

 LINE       426
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Unreachable
10Unreachable
11Unreachable

 LINE       433
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Not Covered
10Not Covered
11CoveredT1,T2,T3

 LINE       485
 EXPRESSION (cnt == PenultimateScrmblBlock)
            ---------------1---------------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       547
 EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
             -----------1----------    --------2-------
-1--2-StatusTests
00CoveredT41,T42,T43
01CoveredT1,T2,T3
10CoveredT3,T5,T10

 LINE       547
 SUB-EXPRESSION (digest_o == data_mux)
                -----------1----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT3,T5,T10

 LINE       547
 SUB-EXPRESSION (digest_o == '0)
                --------1-------
-1-StatusTests
0CoveredT3,T5,T10
1CoveredT1,T2,T3

 LINE       573
 EXPRESSION (error_q == NoError)
            ----------1---------
-1-StatusTests
0CoveredT2,T4,T44
1CoveredT25,T26,T27

 LINE       597
 EXPRESSION (state_q != ErrorSt)
            ----------1---------
-1-StatusTests
0Not Covered
1Not Covered

 LINE       605
 EXPRESSION (state_q != ErrorSt)
            ----------1---------
-1-StatusTests
0CoveredT2,T4,T44
1CoveredT2,T4,T44

 LINE       636
 EXPRESSION ((base_sel == DigOffset) ? DigestOffset : 11'b11001111000)
             -----------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT4,T5,T24

 LINE       636
 SUB-EXPRESSION (base_sel == DigOffset)
                -----------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT4,T5,T24

 LINE       652
 EXPRESSION ((data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i)
             ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       652
 SUB-EXPRESSION (data_sel == ScrmblData)
                ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       678
 EXPRESSION (init_done_o ? data : DataDefault)
             -----1-----
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       709
 EXPRESSION ((digest_o != '0) ? MuBi8True : MuBi8False)
             --------1-------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT2,T3,T5

 LINE       709
 SUB-EXPRESSION (digest_o != '0)
                --------1-------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT2,T3,T5

Cond Coverage for Module : otp_ctrl_part_buf ( parameter Info=-1,CntWidth=4,DigestOffset=1952,StateWidth=12 )
Cond Coverage for Module self-instances :
SCORECOND
92.96 89.58
tb.dut.gen_partitions[9].gen_buffered.u_part_buf

TotalCoveredPercent
Conditions524382.69
Logical524382.69
Non-Logical00
Event00

 LINE       271
 EXPRESSION (cnt == LastScrmblBlock)
            ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       282
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT74,T65,T75

 LINE       302
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Not Covered
10Not Covered
11CoveredT1,T2,T3

 LINE       368
 EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
             -----------1----------    --------2-------
-1--2-StatusTests
00Not Covered
01CoveredT93,T21,T94
10CoveredT95,T92,T18

 LINE       368
 SUB-EXPRESSION (digest_o == data_mux)
                -----------1----------
-1-StatusTests
0CoveredT93,T21,T94
1CoveredT4,T5,T24

 LINE       368
 SUB-EXPRESSION (digest_o == '0)
                --------1-------
-1-StatusTests
0CoveredT95,T92,T18
1CoveredT4,T5,T24

 LINE       385
 EXPRESSION (cnt == LastScrmblBlock)
            ------------1-----------
-1-StatusTests
0Unreachable
1Unreachable

 LINE       401
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT4,T5,T24
1Not Covered

 LINE       426
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Not Covered
10Not Covered
11CoveredT1,T2,T3

 LINE       433
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Unreachable
10Unreachable
11Unreachable

 LINE       485
 EXPRESSION (cnt == PenultimateScrmblBlock)
            ---------------1---------------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       547
 EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
             -----------1----------    --------2-------
-1--2-StatusTests
00Not Covered
01CoveredT1,T2,T3
10CoveredT3,T95,T92

 LINE       547
 SUB-EXPRESSION (digest_o == data_mux)
                -----------1----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT3,T95,T92

 LINE       547
 SUB-EXPRESSION (digest_o == '0)
                --------1-------
-1-StatusTests
0CoveredT3,T95,T92
1CoveredT1,T2,T3

 LINE       573
 EXPRESSION (error_q == NoError)
            ----------1---------
-1-StatusTests
0CoveredT2,T4,T44
1CoveredT25,T26,T27

 LINE       597
 EXPRESSION (state_q != ErrorSt)
            ----------1---------
-1-StatusTests
0Not Covered
1Not Covered

 LINE       605
 EXPRESSION (state_q != ErrorSt)
            ----------1---------
-1-StatusTests
0CoveredT2,T4,T44
1CoveredT2,T4,T44

 LINE       636
 EXPRESSION ((base_sel == DigOffset) ? DigestOffset : 11'b11101010000)
             -----------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT4,T5,T24

 LINE       636
 SUB-EXPRESSION (base_sel == DigOffset)
                -----------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT4,T5,T24

 LINE       652
 EXPRESSION ((data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i)
             ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       652
 SUB-EXPRESSION (data_sel == ScrmblData)
                ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       678
 EXPRESSION (init_done_o ? data : DataDefault)
             -----1-----
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       709
 EXPRESSION ((digest_o != '0) ? MuBi8True : MuBi8False)
             --------1-------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT3,T95,T92

 LINE       709
 SUB-EXPRESSION (digest_o != '0)
                --------1-------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT3,T95,T92

 LINE       729
 EXPRESSION ((digest_o != '0) ? MuBi8True : MuBi8False)
             --------1-------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT3,T95,T92

 LINE       729
 SUB-EXPRESSION (digest_o != '0)
                --------1-------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT3,T95,T92

Cond Coverage for Module : otp_ctrl_part_buf ( parameter Info=-1,CntWidth=1,DigestOffset=1736,StateWidth=12 )
Cond Coverage for Module self-instances :
SCORECOND
90.75 92.86
tb.dut.gen_partitions[6].gen_buffered.u_part_buf

TotalCoveredPercent
Conditions483981.25
Logical483981.25
Non-Logical00
Event00

 LINE       271
 EXPRESSION (cnt == LastScrmblBlock)
            ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       282
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT31,T28,T29

 LINE       302
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Not Covered
10Not Covered
11Not Covered

 LINE       368
 EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
             -----------1----------    --------2-------
-1--2-StatusTests
00Not Covered
01CoveredT9,T93,T96
10CoveredT91,T95,T17

 LINE       368
 SUB-EXPRESSION (digest_o == data_mux)
                -----------1----------
-1-StatusTests
0CoveredT9,T93,T96
1CoveredT4,T5,T24

 LINE       368
 SUB-EXPRESSION (digest_o == '0)
                --------1-------
-1-StatusTests
0CoveredT91,T95,T17
1CoveredT4,T5,T24

 LINE       385
 EXPRESSION (cnt == LastScrmblBlock)
            ------------1-----------
-1-StatusTests
0Unreachable
1Unreachable

 LINE       401
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT4,T5,T24
1CoveredT48,T49

 LINE       426
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Unreachable
10Unreachable
11Unreachable

 LINE       433
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Not Covered
10Not Covered
11CoveredT1,T2,T3

 LINE       485
 EXPRESSION (cnt == PenultimateScrmblBlock)
            ---------------1---------------
-1-StatusTests
0Not Covered
1CoveredT1,T2,T3

 LINE       547
 EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
             -----------1----------    --------2-------
-1--2-StatusTests
00CoveredT53,T54,T55
01CoveredT1,T2,T3
10CoveredT2,T5,T91

 LINE       547
 SUB-EXPRESSION (digest_o == data_mux)
                -----------1----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT2,T5,T91

 LINE       547
 SUB-EXPRESSION (digest_o == '0)
                --------1-------
-1-StatusTests
0CoveredT2,T5,T91
1CoveredT1,T2,T3

 LINE       573
 EXPRESSION (error_q == NoError)
            ----------1---------
-1-StatusTests
0CoveredT2,T4,T44
1CoveredT25,T26,T27

 LINE       597
 EXPRESSION (state_q != ErrorSt)
            ----------1---------
-1-StatusTests
0Not Covered
1Not Covered

 LINE       605
 EXPRESSION (state_q != ErrorSt)
            ----------1---------
-1-StatusTests
0CoveredT2,T4,T44
1CoveredT2,T4,T44

 LINE       636
 EXPRESSION ((base_sel == DigOffset) ? DigestOffset : 11'b11011000000)
             -----------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT4,T5,T24

 LINE       636
 SUB-EXPRESSION (base_sel == DigOffset)
                -----------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT4,T5,T24

 LINE       652
 EXPRESSION ((data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i)
             ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       652
 SUB-EXPRESSION (data_sel == ScrmblData)
                ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       678
 EXPRESSION (init_done_o ? data : DataDefault)
             -----1-----
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       709
 EXPRESSION ((digest_o != '0) ? MuBi8True : MuBi8False)
             --------1-------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT2,T5,T91

 LINE       709
 SUB-EXPRESSION (digest_o != '0)
                --------1-------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT2,T5,T91

Cond Coverage for Module : otp_ctrl_part_buf ( parameter Info=-1,CntWidth=3,DigestOffset=1776,StateWidth=12 )
Cond Coverage for Module self-instances :
SCORECOND
96.06 93.75
tb.dut.gen_partitions[7].gen_buffered.u_part_buf

TotalCoveredPercent
Conditions524586.54
Logical524586.54
Non-Logical00
Event00

 LINE       271
 EXPRESSION (cnt == LastScrmblBlock)
            ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       282
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT29,T30,T56

 LINE       302
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Not Covered
10Not Covered
11CoveredT1,T2,T3

 LINE       368
 EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
             -----------1----------    --------2-------
-1--2-StatusTests
00Not Covered
01CoveredT9,T93,T96
10CoveredT17,T92,T18

 LINE       368
 SUB-EXPRESSION (digest_o == data_mux)
                -----------1----------
-1-StatusTests
0CoveredT9,T93,T96
1CoveredT4,T5,T24

 LINE       368
 SUB-EXPRESSION (digest_o == '0)
                --------1-------
-1-StatusTests
0CoveredT17,T92,T18
1CoveredT4,T5,T24

 LINE       385
 EXPRESSION (cnt == LastScrmblBlock)
            ------------1-----------
-1-StatusTests
0Unreachable
1Unreachable

 LINE       401
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT4,T5,T24
1CoveredT60,T61,T62

 LINE       426
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Not Covered
10Not Covered
11CoveredT1,T2,T3

 LINE       433
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Unreachable
10Unreachable
11Unreachable

 LINE       485
 EXPRESSION (cnt == PenultimateScrmblBlock)
            ---------------1---------------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       547
 EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
             -----------1----------    --------2-------
-1--2-StatusTests
00CoveredT2,T63,T64
01CoveredT1,T2,T3
10CoveredT3,T5,T6

 LINE       547
 SUB-EXPRESSION (digest_o == data_mux)
                -----------1----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT3,T5,T6

 LINE       547
 SUB-EXPRESSION (digest_o == '0)
                --------1-------
-1-StatusTests
0CoveredT2,T3,T5
1CoveredT1,T2,T3

 LINE       573
 EXPRESSION (error_q == NoError)
            ----------1---------
-1-StatusTests
0CoveredT2,T4,T44
1CoveredT25,T26,T27

 LINE       597
 EXPRESSION (state_q != ErrorSt)
            ----------1---------
-1-StatusTests
0Not Covered
1Not Covered

 LINE       605
 EXPRESSION (state_q != ErrorSt)
            ----------1---------
-1-StatusTests
0CoveredT2,T4,T44
1CoveredT4,T44,T31

 LINE       636
 EXPRESSION ((base_sel == DigOffset) ? DigestOffset : 11'b11011010000)
             -----------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT4,T5,T24

 LINE       636
 SUB-EXPRESSION (base_sel == DigOffset)
                -----------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT4,T5,T24

 LINE       652
 EXPRESSION ((data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i)
             ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       652
 SUB-EXPRESSION (data_sel == ScrmblData)
                ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       678
 EXPRESSION (init_done_o ? data : DataDefault)
             -----1-----
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       709
 EXPRESSION ((digest_o != '0) ? MuBi8True : MuBi8False)
             --------1-------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT2,T3,T5

 LINE       709
 SUB-EXPRESSION (digest_o != '0)
                --------1-------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT2,T3,T5

 LINE       729
 EXPRESSION ((digest_o != '0) ? MuBi8True : MuBi8False)
             --------1-------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT2,T3,T5

 LINE       729
 SUB-EXPRESSION (digest_o != '0)
                --------1-------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT2,T3,T5

Cond Coverage for Module : otp_ctrl_part_buf ( parameter Info=-1,CntWidth=4,DigestOffset=2040,StateWidth=12 )
Cond Coverage for Module self-instances :
SCORECOND
94.90 100.00
tb.dut.gen_partitions[10].gen_lifecycle.u_part_buf

TotalCoveredPercent
Conditions241875.00
Logical241875.00
Non-Logical00
Event00

 LINE       271
 EXPRESSION (cnt == LastScrmblBlock)
            ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       282
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT80,T81,T82

 LINE       302
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Unreachable
10Unreachable
11Unreachable

 LINE       368
 EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
             -----------1----------    --------2-------
-1--2-StatusTests
00Unreachable
01Unreachable
10Unreachable

 LINE       368
 SUB-EXPRESSION (digest_o == data_mux)
                -----------1----------
-1-StatusTests
0Unreachable
1Unreachable

 LINE       368
 SUB-EXPRESSION (digest_o == '0)
                --------1-------
-1-StatusTests
0Unreachable
1Unreachable

 LINE       385
 EXPRESSION (cnt == LastScrmblBlock)
            ------------1-----------
-1-StatusTests
0CoveredT4,T5,T24
1CoveredT4,T5,T24

 LINE       401
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT4,T5,T24
1CoveredT87,T88,T89

 LINE       426
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Unreachable
10Unreachable
11Unreachable

 LINE       433
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Unreachable
10Unreachable
11Unreachable

 LINE       485
 EXPRESSION (cnt == PenultimateScrmblBlock)
            ---------------1---------------
-1-StatusTests
0Unreachable
1Unreachable

 LINE       547
 EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
             -----------1----------    --------2-------
-1--2-StatusTests
00Unreachable
01Unreachable
10Unreachable

 LINE       547
 SUB-EXPRESSION (digest_o == data_mux)
                -----------1----------
-1-StatusTests
0Unreachable
1Unreachable

 LINE       547
 SUB-EXPRESSION (digest_o == '0)
                --------1-------
-1-StatusTests
0Unreachable
1Unreachable

 LINE       573
 EXPRESSION (error_q == NoError)
            ----------1---------
-1-StatusTests
0CoveredT2,T4,T44
1CoveredT25,T26,T27

 LINE       597
 EXPRESSION (state_q != ErrorSt)
            ----------1---------
-1-StatusTests
0Not Covered
1Not Covered

 LINE       605
 EXPRESSION (state_q != ErrorSt)
            ----------1---------
-1-StatusTests
0CoveredT2,T4,T44
1CoveredT2,T4,T44

 LINE       636
 EXPRESSION ((base_sel == DigOffset) ? DigestOffset : 11'b11110101000)
             -----------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1Not Covered

 LINE       636
 SUB-EXPRESSION (base_sel == DigOffset)
                -----------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1Not Covered

 LINE       652
 EXPRESSION ((data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i)
             ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1Not Covered

 LINE       652
 SUB-EXPRESSION (data_sel == ScrmblData)
                ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1Not Covered

 LINE       678
 EXPRESSION (init_done_o ? data : DataDefault)
             -----1-----
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,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 :
SCORECOND
94.39 93.75
tb.dut.gen_partitions[8].gen_buffered.u_part_buf

TotalCoveredPercent
Conditions524586.54
Logical524586.54
Non-Logical00
Event00

 LINE       271
 EXPRESSION (cnt == LastScrmblBlock)
            ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       282
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT29,T56,T65

 LINE       302
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Not Covered
10Not Covered
11CoveredT1,T2,T3

 LINE       368
 EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
             -----------1----------    --------2-------
-1--2-StatusTests
00Not Covered
01CoveredT93,T97,T98
10CoveredT91,T17,T92

 LINE       368
 SUB-EXPRESSION (digest_o == data_mux)
                -----------1----------
-1-StatusTests
0CoveredT93,T97,T98
1CoveredT4,T5,T24

 LINE       368
 SUB-EXPRESSION (digest_o == '0)
                --------1-------
-1-StatusTests
0CoveredT91,T17,T92
1CoveredT4,T5,T24

 LINE       385
 EXPRESSION (cnt == LastScrmblBlock)
            ------------1-----------
-1-StatusTests
0Unreachable
1Unreachable

 LINE       401
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT4,T5,T24
1CoveredT50,T39,T69

 LINE       426
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Not Covered
10Not Covered
11CoveredT1,T2,T3

 LINE       433
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Unreachable
10Unreachable
11Unreachable

 LINE       485
 EXPRESSION (cnt == PenultimateScrmblBlock)
            ---------------1---------------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       547
 EXPRESSION ((digest_o == data_mux) || (digest_o == '0))
             -----------1----------    --------2-------
-1--2-StatusTests
00CoveredT72,T73
01CoveredT1,T2,T3
10CoveredT5,T91,T95

 LINE       547
 SUB-EXPRESSION (digest_o == data_mux)
                -----------1----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT5,T91,T95

 LINE       547
 SUB-EXPRESSION (digest_o == '0)
                --------1-------
-1-StatusTests
0CoveredT5,T91,T95
1CoveredT1,T2,T3

 LINE       573
 EXPRESSION (error_q == NoError)
            ----------1---------
-1-StatusTests
0CoveredT2,T4,T44
1CoveredT25,T26,T27

 LINE       597
 EXPRESSION (state_q != ErrorSt)
            ----------1---------
-1-StatusTests
0Not Covered
1Not Covered

 LINE       605
 EXPRESSION (state_q != ErrorSt)
            ----------1---------
-1-StatusTests
0CoveredT2,T4,T44
1CoveredT2,T4,T44

 LINE       636
 EXPRESSION ((base_sel == DigOffset) ? DigestOffset : 11'b11011111000)
             -----------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT4,T5,T24

 LINE       636
 SUB-EXPRESSION (base_sel == DigOffset)
                -----------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT4,T5,T24

 LINE       652
 EXPRESSION ((data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i)
             ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       652
 SUB-EXPRESSION (data_sel == ScrmblData)
                ------------1-----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       678
 EXPRESSION (init_done_o ? data : DataDefault)
             -----1-----
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       709
 EXPRESSION ((digest_o != '0) ? MuBi8True : MuBi8False)
             --------1-------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT5,T91,T95

 LINE       709
 SUB-EXPRESSION (digest_o != '0)
                --------1-------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT5,T91,T95

 LINE       729
 EXPRESSION ((digest_o != '0) ? MuBi8True : MuBi8False)
             --------1-------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT5,T91,T95

 LINE       729
 SUB-EXPRESSION (digest_o != '0)
                --------1-------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT5,T91,T95

FSM Coverage for Module : otp_ctrl_part_buf
Summary for FSM :: state_q
TotalCoveredPercent
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
statesLine No.CoveredTests
CnstyReadSt 334 Covered T4,T5,T24
CnstyReadWaitSt 352 Covered T4,T5,T24
ErrorSt 286 Covered T2,T4,T44
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


transitionsLine No.CoveredTests
CnstyReadSt->CnstyReadWaitSt 352 Covered T4,T5,T24
CnstyReadSt->ErrorSt 596 Covered T95,T99,T100
CnstyReadWaitSt->CnstyReadSt 390 Covered T4,T5,T24
CnstyReadWaitSt->ErrorSt 373 Covered T95,T99,T100
CnstyReadWaitSt->IdleSt 369 Covered T4,T5,T24
IdleSt->CnstyReadSt 334 Covered T4,T5,T24
IdleSt->ErrorSt 596 Covered T2,T4,T31
IdleSt->IntegDigClrSt 326 Covered T3,T24,T34
InitDescrSt->ErrorSt 596 Covered T2,T31,T41
InitDescrSt->InitDescrWaitSt 303 Covered T1,T2,T3
InitDescrWaitSt->ErrorSt 596 Covered T2,T31,T41
InitDescrWaitSt->InitSt 315 Covered T1,T2,T3
InitSt->ErrorSt 596 Covered T44,T31,T101
InitSt->InitWaitSt 256 Covered T1,T2,T3
InitWaitSt->ErrorSt 286 Covered T44,T31,T53
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 T2,T95,T78
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 T28,T102,T103
IntegDigFinSt->IntegDigWaitSt 532 Covered T1,T2,T3
IntegDigPadSt->ErrorSt 596 Not Covered
IntegDigPadSt->IntegDigFinSt 520 Covered T1,T2,T3
IntegDigSt->ErrorSt 596 Covered T95,T104,T61
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 T2,T41,T42
IntegDigWaitSt->IdleSt 548 Covered T1,T2,T3
IntegScrSt->ErrorSt 596 Covered T71,T72,T73
IntegScrSt->IntegScrWaitSt 460 Covered T1,T2,T3
IntegScrWaitSt->ErrorSt 596 Covered T78,T105,T106
IntegScrWaitSt->IntegDigSt 470 Covered T1,T2,T3
ResetSt->ErrorSt 596 Covered T107,T108,T109
ResetSt->InitSt 246 Covered T1,T2,T3


Summary for FSM :: error_q
TotalCoveredPercent
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
statesLine No.CoveredTests
CheckFailError 374 Covered T2,T41,T42
FsmStateError 574 Covered T2,T4,T44
MacroEccCorrError 283 Covered T31,T28,T60
NoError 573 Covered T1,T2,T3


transitionsLine No.CoveredTests
CheckFailError->FsmStateError 606 Not Covered
CheckFailError->MacroEccCorrError 283 Not Covered
FsmStateError->CheckFailError 374 Not Covered
FsmStateError->MacroEccCorrError 283 Not Covered
MacroEccCorrError->CheckFailError 374 Covered T80
MacroEccCorrError->FsmStateError 606 Covered T31,T28,T29
NoError->CheckFailError 374 Covered T2,T41,T42
NoError->FsmStateError 574 Covered T2,T4,T44
NoError->MacroEccCorrError 283 Covered T31,T28,T60



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 :
SCOREBRANCH
96.06 96.88
tb.dut.gen_partitions[7].gen_buffered.u_part_buf

SCOREBRANCH
94.39 96.88
tb.dut.gen_partitions[8].gen_buffered.u_part_buf

SCOREBRANCH
92.96 93.75
tb.dut.gen_partitions[9].gen_buffered.u_part_buf

Line No.TotalCoveredPercent
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-StatusTests
1 Covered T4,T5,T24
0 Covered T1,T2,T3


652 assign data_mux = (data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i; -1- ==> ==>

Branches:
-1-StatusTests
1 Covered T1,T2,T3
0 Covered T1,T2,T3


678 assign data_o = (init_done_o) ? data : DataDefault; -1- ==> ==>

Branches:
-1-StatusTests
1 Covered T1,T2,T3
0 Covered T1,T2,T3


709 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False; -1- ==> ==>

Branches:
-1-StatusTests
1 Covered T2,T3,T5
0 Covered T1,T2,T3


729 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False; -1- ==> ==>

Branches:
-1-StatusTests
1 Covered T2,T3,T5
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-StatusTests
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 T29,T30,T56
InitWaitSt - - 1 1 - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
InitWaitSt - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T28,T76,T77
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,T24,T34
IdleSt - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Unreachable
IdleSt - - - - - - - - - 0 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
IdleSt - - - - - - - - - 0 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
CnstyReadSt - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
CnstyReadSt - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - Not Covered
CnstyReadSt - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
CnstyReadSt - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
CnstyReadWaitSt - - - - - - - - - - - - - - 1 1 1 1 - - - - - - - - - - - - - - - - - - - - - Covered T4,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 T60,T61,T50
CnstyReadWaitSt - - - - - - - - - - - - - - 1 1 - - - - 0 - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
CnstyReadWaitSt - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - Covered T78,T70,T61
CnstyReadWaitSt - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,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,T24,T34
IntegDigWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - Covered T2,T63,T64
IntegDigWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - Covered T1,T2,T3
ErrorSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 Covered T25,T26,T27
ErrorSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 Covered T2,T4,T44
default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T25,T26,T27


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-StatusTests
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-StatusTests
1 1 Covered T2,T4,T44
1 0 Covered T2,T4,T44
0 - Covered T1,T2,T3


750 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt) -1- ==> ==>

Branches:
-1-StatusTests
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-StatusTests
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 :
SCOREBRANCH
93.18 98.15
tb.dut.gen_partitions[5].gen_buffered.u_part_buf

SCOREBRANCH
90.75 90.91
tb.dut.gen_partitions[6].gen_buffered.u_part_buf

Line No.TotalCoveredPercent
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-StatusTests
1 Covered T4,T5,T24
0 Covered T1,T2,T3


652 assign data_mux = (data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i; -1- ==> ==>

Branches:
-1-StatusTests
1 Covered T1,T2,T3
0 Covered T1,T2,T3


678 assign data_o = (init_done_o) ? data : DataDefault; -1- ==> ==>

Branches:
-1-StatusTests
1 Covered T1,T2,T3
0 Covered T1,T2,T3


709 assign digest_locked = (digest_o != '0) ? MuBi8True : MuBi8False; -1- ==> ==>

Branches:
-1-StatusTests
1 Covered T2,T3,T5
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-StatusTests
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 T31,T28,T29
InitWaitSt - - 1 1 - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
InitWaitSt - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T31,T45,T32
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,T24,T34
IdleSt - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Unreachable
IdleSt - - - - - - - - - 0 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
IdleSt - - - - - - - - - 0 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
CnstyReadSt - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
CnstyReadSt - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - Not Covered
CnstyReadSt - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
CnstyReadSt - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
CnstyReadWaitSt - - - - - - - - - - - - - - 1 1 1 1 - - - - - - - - - - - - - - - - - - - - - Covered T4,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 T35,T36,T48
CnstyReadWaitSt - - - - - - - - - - - - - - 1 1 - - - - 0 - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
CnstyReadWaitSt - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - Covered T50,T51,T38
CnstyReadWaitSt - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
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,T24,T34
IntegDigWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - Covered T41,T42,T53
IntegDigWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - Covered T1,T2,T3
ErrorSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 Covered T25,T26,T27
ErrorSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 Covered T2,T4,T44
default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T25,T26,T27


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-StatusTests
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-StatusTests
1 1 Covered T2,T4,T44
1 0 Covered T2,T4,T44
0 - Covered T1,T2,T3


750 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt) -1- ==> ==>

Branches:
-1-StatusTests
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-StatusTests
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 :
SCOREBRANCH
94.90 100.00
tb.dut.gen_partitions[10].gen_lifecycle.u_part_buf

Line No.TotalCoveredPercent
Branches 56 39 69.64
TERNARY 636 2 1 50.00
TERNARY 652 2 1 50.00
TERNARY 678 2 2 100.00
CASE 240 40 27 67.50
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-StatusTests
1 Not Covered
0 Covered T1,T2,T3


652 assign data_mux = (data_sel == ScrmblData) ? scrmbl_data_i : otp_rdata_i; -1- ==> ==>

Branches:
-1-StatusTests
1 Not Covered
0 Covered T1,T2,T3


678 assign data_o = (init_done_o) ? data : DataDefault; -1- ==> ==>

Branches:
-1-StatusTests
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-StatusTests
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 T80,T81,T82
InitWaitSt - - 1 1 - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
InitWaitSt - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T83,T84,T85
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,T24,T34
IdleSt - - - - - - - - - 0 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
IdleSt - - - - - - - - - 0 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
CnstyReadSt - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - Unreachable
CnstyReadSt - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
CnstyReadSt - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
CnstyReadSt - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
CnstyReadWaitSt - - - - - - - - - - - - - - 1 1 1 1 - - - - - - - - - - - - - - - - - - - - - Unreachable
CnstyReadWaitSt - - - - - - - - - - - - - - 1 1 1 0 - - - - - - - - - - - - - - - - - - - - - Unreachable
CnstyReadWaitSt - - - - - - - - - - - - - - 1 1 0 - 1 1 - - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
CnstyReadWaitSt - - - - - - - - - - - - - - 1 1 0 - 1 0 - - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
CnstyReadWaitSt - - - - - - - - - - - - - - 1 1 0 - 0 - - - - - - - - - - - - - - - - - - - - Covered T30,T56,T86
CnstyReadWaitSt - - - - - - - - - - - - - - 1 1 - - - - 1 - - - - - - - - - - - - - - - - - - Covered T87,T88,T89
CnstyReadWaitSt - - - - - - - - - - - - - - 1 1 - - - - 0 - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
CnstyReadWaitSt - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - Covered T51,T90
CnstyReadWaitSt - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,T5,T24
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 T25,T26,T27
ErrorSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 Covered T2,T4,T44
default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T25,T26,T27


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-StatusTests
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-StatusTests
1 1 Covered T2,T4,T44
1 0 Covered T2,T4,T44
0 - Covered T1,T2,T3


750 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, ResetSt) -1- ==> ==>

Branches:
-1-StatusTests
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-StatusTests
1 Covered T1,T2,T3
0 Covered T1,T2,T3


Assert Coverage for Module : otp_ctrl_part_buf
TotalAttemptedPercentSucceeded/MatchedPercent
Assertions 36 36 100.00 35 97.22
Cover properties 0 0 0
Cover sequences 0 0 0
Total 36 36 100.00 35 97.22




Assertion Details

NameAttemptsReal SuccessesFailuresIncomplete
AccessKnown_A 538359138 533147190 0 0
BypassEnable0_A 538359138 266573595 0 0
BypassEnable1_A 538359138 444289325 0 0
CnstyChkAckKnown_A 538359138 533147190 0 0
DataKnown_A 538359138 533147190 0 0
DigestKnown_A 538359138 533147190 0 0
DigestOffsetMustBeRepresentable_A 6750 6750 0 0
EccErrorState_A 538359138 0 0 0
ErrorKnown_A 538359138 533147190 0 0
InitDoneKnown_A 538359138 533147190 0 0
InitReadLocksPartition_A 538359138 175950903 0 0
InitWriteLocksPartition_A 538359138 175950903 0 0
IntegChkAckKnown_A 538359138 533147190 0 0
OffsetMustBeBlockAligned_A 6750 6750 0 0
OtpAddrKnown_A 538359138 533147190 0 0
OtpCmdKnown_A 538359138 533147190 0 0
OtpErrorState_A 89726523 15 0 0
OtpPartBufSize_A 6750 6750 0 0
OtpReqKnown_A 538359138 533147190 0 0
OtpSizeKnown_A 538359138 533147190 0 0
OtpWdataKnown_A 538359138 533147190 0 0
ReadLockImpliesDigest_A 538359138 444289325 0 0
ReadLockPropagation_A 538359138 122852934 0 0
ScrambledImpliesDigest_A 538359138 266573595 0 0
ScrmblCmdKnown_A 538359138 533147190 0 0
ScrmblDataKnown_A 534489082 529362658 0 0
ScrmblModeKnown_A 538359138 533147190 0 0
ScrmblMtxReqKnown_A 538359138 533147190 0 0
ScrmblSelKnown_A 538359138 533147190 0 0
ScrmblValidKnown_A 538359138 533147190 0 0
SizeMustBeBlockAligned_A 6750 6750 0 0
WriteLockImpliesDigest_A 538359138 266573595 0 0
WriteLockPropagation_A 538359138 127194892 0 0
gen_digest_read_lock.DigestReadLocksPartition_A 269179569 67874905 0 0
gen_digest_write_lock.DigestWriteLocksPartition_A 448632615 122405237 0 0
u_state_regs_A 538359138 533147190 0 0


AccessKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

BypassEnable0_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 266573595 0 0
T1 15879 15720 0 0
T2 41721 40956 0 0
T3 89151 87384 0 0
T4 33768 33027 0 0
T5 32376 31755 0 0
T6 33192 32628 0 0
T10 29799 28719 0 0
T11 16422 16233 0 0
T12 113865 113640 0 0
T13 17034 16803 0 0

BypassEnable1_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 444289325 0 0
T1 26465 26200 0 0
T2 69535 68260 0 0
T3 148585 145640 0 0
T4 56280 55045 0 0
T5 53960 52925 0 0
T6 55320 54380 0 0
T10 49665 47865 0 0
T11 27370 27055 0 0
T12 189775 189400 0 0
T13 28390 28005 0 0

CnstyChkAckKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

DataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

DigestKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

DigestOffsetMustBeRepresentable_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 6750 6750 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
T10 6 6 0 0
T11 6 6 0 0
T12 6 6 0 0
T13 6 6 0 0

EccErrorState_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 0 0 0

ErrorKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

InitDoneKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

InitReadLocksPartition_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 175950903 0 0
T1 31758 10098 0 0
T2 83442 39483 0 0
T3 178302 37323 0 0
T4 67536 46230 0 0
T5 64752 20340 0 0
T6 66384 15966 0 0
T10 59598 26064 0 0
T11 32844 9042 0 0
T12 227730 7788 0 0
T13 34068 7668 0 0

InitWriteLocksPartition_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 175950903 0 0
T1 31758 10098 0 0
T2 83442 39483 0 0
T3 178302 37323 0 0
T4 67536 46230 0 0
T5 64752 20340 0 0
T6 66384 15966 0 0
T10 59598 26064 0 0
T11 32844 9042 0 0
T12 227730 7788 0 0
T13 34068 7668 0 0

IntegChkAckKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

OffsetMustBeBlockAligned_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 6750 6750 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
T10 6 6 0 0
T11 6 6 0 0
T12 6 6 0 0
T13 6 6 0 0

OtpAddrKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

OtpCmdKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

OtpErrorState_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 89726523 15 0 0
T51 490251 1 0 0
T83 0 1 0 0
T84 0 1 0 0
T85 0 1 0 0
T90 0 1 0 0
T110 0 1 0 0
T111 0 1 0 0
T112 0 1 0 0
T113 0 1 0 0
T114 0 1 0 0
T115 25594 0 0 0
T116 5274 0 0 0
T117 21491 0 0 0
T118 94939 0 0 0
T119 74877 0 0 0
T120 43593 0 0 0
T121 4834 0 0 0
T122 74722 0 0 0
T123 11355 0 0 0

OtpPartBufSize_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 6750 6750 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
T10 6 6 0 0
T11 6 6 0 0
T12 6 6 0 0
T13 6 6 0 0

OtpReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

OtpSizeKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

OtpWdataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

ReadLockImpliesDigest_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 444289325 0 0
T1 26465 26200 0 0
T2 69535 68260 0 0
T3 148585 145640 0 0
T4 56280 55045 0 0
T5 53960 52925 0 0
T6 55320 54380 0 0
T10 49665 47865 0 0
T11 27370 27055 0 0
T12 189775 189400 0 0
T13 28390 28005 0 0

ReadLockPropagation_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 122852934 0 0
T1 10586 5240 0 0
T2 27814 13652 0 0
T3 59434 29128 0 0
T4 22512 11009 0 0
T5 21584 10585 0 0
T6 22128 10876 0 0
T10 19866 9573 0 0
T11 10948 5411 0 0
T12 75910 37880 0 0
T13 11356 5601 0 0
T17 120112 11113 0 0
T18 123502 6137 0 0
T19 76986 6991 0 0
T78 50932 0 0 0
T92 140898 2790 0 0
T99 0 9558 0 0
T100 0 10050 0 0
T105 0 4618 0 0
T124 104656 4778 0 0
T125 0 12460 0 0
T126 0 19791 0 0
T127 0 24263 0 0
T128 138928 0 0 0
T129 58326 0 0 0
T130 33464 0 0 0
T131 14950 0 0 0

ScrambledImpliesDigest_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 266573595 0 0
T1 15879 15720 0 0
T2 41721 40956 0 0
T3 89151 87384 0 0
T4 33768 33027 0 0
T5 32376 31755 0 0
T6 33192 32628 0 0
T10 29799 28719 0 0
T11 16422 16233 0 0
T12 113865 113640 0 0
T13 17034 16803 0 0

ScrmblCmdKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

ScrmblDataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 534489082 529362658 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

ScrmblModeKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

ScrmblMtxReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

ScrmblSelKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

ScrmblValidKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

SizeMustBeBlockAligned_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 6750 6750 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
T10 6 6 0 0
T11 6 6 0 0
T12 6 6 0 0
T13 6 6 0 0

WriteLockImpliesDigest_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 266573595 0 0
T1 15879 15720 0 0
T2 41721 40956 0 0
T3 89151 87384 0 0
T4 33768 33027 0 0
T5 32376 31755 0 0
T6 33192 32628 0 0
T10 29799 28719 0 0
T11 16422 16233 0 0
T12 113865 113640 0 0
T13 17034 16803 0 0

WriteLockPropagation_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 127194892 0 0
T1 5293 5240 0 0
T2 13907 13652 0 0
T3 29717 29128 0 0
T4 11256 11009 0 0
T5 10792 10585 0 0
T6 11064 10876 0 0
T10 9933 9573 0 0
T11 5474 5411 0 0
T12 37955 37880 0 0
T13 5678 5601 0 0
T17 180168 0 0 0
T91 69512 5038 0 0
T92 211347 1982 0 0
T95 124048 0 0 0
T99 0 7371 0 0
T100 0 11019 0 0
T105 0 13720 0 0
T124 0 2942 0 0
T125 0 7311 0 0
T126 0 4152 0 0
T127 0 24263 0 0
T128 208392 0 0 0
T129 87489 0 0 0
T130 50196 0 0 0
T131 7475 0 0 0
T132 0 2198 0 0
T133 0 1101 0 0
T134 41252 0 0 0
T135 48014 0 0 0
T136 48490 0 0 0

gen_digest_read_lock.DigestReadLocksPartition_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 269179569 67874905 0 0
T2 13907 3214 0 0
T3 59434 12297 0 0
T4 22512 0 0 0
T5 32376 4869 0 0
T6 33192 3391 0 0
T10 29799 0 0 0
T11 10948 0 0 0
T12 113865 0 0 0
T13 17034 0 0 0
T17 0 76818 0 0
T18 0 50339 0 0
T19 0 29405 0 0
T24 16222 2893 0 0
T31 33060 0 0 0
T34 14729 0 0 0
T44 38313 0 0 0
T91 0 20304 0 0
T92 0 120374 0 0
T95 0 15950 0 0
T99 0 52475 0 0
T105 0 48588 0 0
T124 0 55812 0 0
T125 0 34533 0 0
T129 0 3027 0 0
T130 0 3473 0 0
T136 0 6145 0 0
T137 0 5151 0 0
T138 76949 0 0 0

gen_digest_write_lock.DigestWriteLocksPartition_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 448632615 122405237 0 0
T2 41721 9965 0 0
T3 118868 18698 0 0
T4 45024 0 0 0
T5 53960 10854 0 0
T6 55320 3391 0 0
T10 49665 4683 0 0
T11 21896 0 0 0
T12 189775 0 0 0
T13 28390 0 0 0
T17 0 168655 0 0
T18 0 99548 0 0
T19 0 29405 0 0
T24 16222 2893 0 0
T31 33060 0 0 0
T34 14729 0 0 0
T44 63855 0 0 0
T91 0 72038 0 0
T92 0 202740 0 0
T95 0 30219 0 0
T99 0 52475 0 0
T105 0 48588 0 0
T124 0 55812 0 0
T125 0 34533 0 0
T129 0 9404 0 0
T130 0 3473 0 0
T135 0 20600 0 0
T136 0 20667 0 0
T137 0 5151 0 0
T138 76949 0 0 0

u_state_regs_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 538359138 533147190 0 0
T1 31758 31440 0 0
T2 83442 81912 0 0
T3 178302 174768 0 0
T4 67536 66054 0 0
T5 64752 63510 0 0
T6 66384 65256 0 0
T10 59598 57438 0 0
T11 32844 32466 0 0
T12 227730 227280 0 0
T13 34068 33606 0 0

0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%