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



Module Instance : tb.dut.u_otp_ctrl_dai

Instance :
SCORELINECONDTOGGLEFSMBRANCHASSERT
93.03 95.88 95.06 84.21 90.00 100.00


Instance's subtree :
SCORELINECONDTOGGLEFSMBRANCHASSERT
89.80 85.64 91.96 100.00 84.21 89.73 87.23


Parent :
SCORELINECONDTOGGLEFSMBRANCHASSERTNAME
96.17 94.16 96.15 96.94 96.43 97.18 dut


Subtrees :
NAMESCORELINECONDTOGGLEFSMBRANCHASSERT
u_part_sel_idx 74.55 65.65 89.83 88.89 53.85
u_prim_count 100.00 100.00
u_state_regs 100.00 100.00 100.00 100.00

Line Coverage for Module : otp_ctrl_dai
Line No.TotalCoveredPercent
TOTAL24723394.33
ALWAYS16933100.00
CONT_ASSIGN17711100.00
CONT_ASSIGN17911100.00
CONT_ASSIGN18011100.00
CONT_ASSIGN18411100.00
ALWAYS18719918592.96
CONT_ASSIGN71811100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
ALWAYS7531111100.00
CONT_ASSIGN79611100.00
CONT_ASSIGN79711100.00
ALWAYS80333100.00
ALWAYS8061414100.00

168 always_comb begin 169 1/1 otp_err = otp_err_e'(otp_err_i); Tests: T1 T2 T3  170 1/1 if (!PartInfo[part_idx].integrity && Tests: T1 T2 T3  171 otp_err_e'(otp_err_i) inside {MacroEccCorrError, MacroEccUncorrError}) begin 172 1/1 otp_err = NoError; Tests: T2 T85 T147  173 end MISSING_ELSE 174 end 175 176 // Output partition error state. 177 1/1 assign error_o = error_q; Tests: T1 T2 T3  178 // Working register is connected to data outputs. 179 1/1 assign otp_wdata_o = data_q; Tests: T1 T2 T3  180 1/1 assign scrmbl_data_o = data_q; Tests: T1 T2 T3  181 // Only expose this working register in IdleSt. 182 // The FSM below makes sure to clear this register 183 // after digest and write ops. 184 1/1 assign dai_rdata_o = (state_q == IdleSt) ? data_q : '0; Tests: T1 T2 T3  185 186 always_comb begin : p_fsm 187 1/1 state_d = state_q; Tests: T1 T2 T3  188 189 // Init signals 190 1/1 init_done_o = 1'b1; Tests: T1 T2 T3  191 1/1 part_init_req_o = 1'b0; Tests: T1 T2 T3  192 193 // DAI signals 194 1/1 dai_idle_o = 1'b0; Tests: T1 T2 T3  195 1/1 dai_prog_idle_o = 1'b1; Tests: T1 T2 T3  196 1/1 dai_cmd_done_o = 1'b0; Tests: T1 T2 T3  197 198 // OTP signals 199 1/1 otp_req_o = 1'b0; Tests: T1 T2 T3  200 1/1 otp_cmd_o = prim_otp_pkg::Init; Tests: T1 T2 T3  201 202 // Scrambling mutex 203 1/1 scrmbl_mtx_req_o = 1'b0; Tests: T1 T2 T3  204 205 // Scrambling datapath 206 1/1 scrmbl_cmd_o = LoadShadow; Tests: T1 T2 T3  207 1/1 scrmbl_sel_o = CnstyDigest; Tests: T1 T2 T3  208 1/1 scrmbl_mode_o = StandardMode; Tests: T1 T2 T3  209 1/1 scrmbl_valid_o = 1'b0; Tests: T1 T2 T3  210 211 // Counter 212 1/1 cnt_en = 1'b0; Tests: T1 T2 T3  213 1/1 cnt_clr = 1'b0; Tests: T1 T2 T3  214 1/1 base_sel_d = base_sel_q; Tests: T1 T2 T3  215 216 // Temporary data register 217 1/1 data_en = 1'b0; Tests: T1 T2 T3  218 1/1 data_clr = 1'b0; Tests: T1 T2 T3  219 1/1 data_sel = OtpData; Tests: T1 T2 T3  220 221 // Error Register 222 1/1 error_d = error_q; Tests: T1 T2 T3  223 1/1 fsm_err_o = 1'b0; Tests: T1 T2 T3  224 225 1/1 unique case (state_q) Tests: T1 T2 T3  226 /////////////////////////////////////////////////////////////////// 227 // We get here after reset and wait until the power manager 228 // requests OTP initialization. If initialization is requested, 229 // an init command is written to the OTP macro, and we move on 230 // to the InitOtpSt waiting state. 231 ResetSt: begin 232 1/1 init_done_o = 1'b0; Tests: T1 T2 T3  233 1/1 dai_prog_idle_o = 1'b0; Tests: T1 T2 T3  234 1/1 data_clr = 1'b1; Tests: T1 T2 T3  235 1/1 if (init_req_i) begin Tests: T1 T2 T3  236 1/1 otp_req_o = 1'b1; Tests: T1 T2 T3  237 1/1 if (otp_gnt_i) begin Tests: T1 T2 T3  238 1/1 state_d = InitOtpSt; Tests: T1 T2 T3  239 end ==> MISSING_ELSE 240 end MISSING_ELSE 241 end 242 /////////////////////////////////////////////////////////////////// 243 // We wait here unitl the OTP macro has initialized without 244 // error. If an error occurred during this stage, we latch that 245 // error and move into a terminal error state. 246 InitOtpSt: begin 247 1/1 init_done_o = 1'b0; Tests: T1 T2 T3  248 1/1 dai_prog_idle_o = 1'b0; Tests: T1 T2 T3  249 1/1 if (otp_rvalid_i) begin Tests: T1 T2 T3  250 1/1 if ((!(otp_err inside {NoError, MacroEccCorrError}))) begin Tests: T1 T2 T3  251 0/1 ==> state_d = ErrorSt; 252 0/1 ==> error_d = otp_err; 253 end else begin 254 1/1 state_d = InitPartSt; Tests: T1 T2 T3  255 end 256 end MISSING_ELSE 257 end 258 /////////////////////////////////////////////////////////////////// 259 // Since the OTP macro is now functional, we can send out an 260 // initialization request to all partitions and wait until they 261 // all have initialized. 262 InitPartSt: begin 263 1/1 init_done_o = 1'b0; Tests: T1 T2 T3  264 1/1 dai_prog_idle_o = 1'b0; Tests: T1 T2 T3  265 1/1 part_init_req_o = 1'b1; Tests: T1 T2 T3  266 1/1 if (part_init_done_i == {NumPart{1'b1}}) begin Tests: T1 T2 T3  267 1/1 state_d = IdleSt; Tests: T1 T2 T3  268 end MISSING_ELSE 269 end 270 /////////////////////////////////////////////////////////////////// 271 // Idle state where we wait for incoming commands. 272 // Invalid commands trigger a CmdInvErr, which is recoverable. 273 IdleSt: begin 274 1/1 dai_idle_o = 1'b1; Tests: T1 T2 T3  275 1/1 if (dai_req_i) begin Tests: T1 T2 T3  276 // This clears previous (recoverable) and reset the counter. 277 1/1 error_d = NoError; Tests: T1 T2 T3  278 1/1 cnt_clr = 1'b1; Tests: T1 T2 T3  279 1/1 unique case (dai_cmd_i) Tests: T1 T2 T3  280 DaiRead: begin 281 1/1 state_d = ReadSt; Tests: T1 T2 T3  282 // Clear the temporary data register. 283 1/1 data_clr = 1'b1; Tests: T1 T2 T3  284 1/1 base_sel_d = DaiOffset; Tests: T1 T2 T3  285 end 286 DaiWrite: begin 287 1/1 data_sel = DaiData; Tests: T1 T2 T3  288 // Fetch data block. 289 1/1 data_en = 1'b1; Tests: T1 T2 T3  290 1/1 base_sel_d = DaiOffset; Tests: T1 T2 T3  291 // If this partition is scrambled, directly go to write scrambling first. 292 1/1 if (PartInfo[part_idx].secret) begin Tests: T1 T2 T3  293 1/1 state_d = ScrSt; Tests: T2 T3 T4  294 end else begin 295 1/1 state_d = WriteSt; Tests: T1 T2 T3  296 end 297 end 298 DaiDigest: begin 299 1/1 state_d = DigClrSt; Tests: T1 T3 T5  300 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T3 T5  301 1/1 base_sel_d = PartOffset; Tests: T1 T3 T5  302 end 303 default: ; // Ignore invalid commands 304 endcase // dai_cmd_i 305 end // dai_req_i MISSING_ELSE 306 end 307 /////////////////////////////////////////////////////////////////// 308 // Each time we request a block of data from OTP, we re-check 309 // whether read access has been locked for this partition. If 310 // that is the case, we immediately bail out. Otherwise, we 311 // request a block of data from OTP. 312 ReadSt: begin 313 1/1 if (part_sel_valid && (mubi8_test_false_strict(part_access_i[part_idx].read_lock) || Tests: T1 T2 T3  314 // HW digests always remain readable. 315 PartInfo[part_idx].hw_digest && otp_addr_o == 316 digest_addr_lut[part_idx])) begin 317 1/1 otp_req_o = 1'b1; Tests: T1 T2 T3  318 // Depending on the partition configuration, 319 // the wrapper is instructed to ignore integrity errors. 320 1/1 if (PartInfo[part_idx].integrity) begin Tests: T1 T2 T3  321 1/1 otp_cmd_o = prim_otp_pkg::Read; Tests: T1 T2 T3  322 end else begin 323 1/1 otp_cmd_o = prim_otp_pkg::ReadRaw; Tests: T2 T3 T4  324 end 325 1/1 if (otp_gnt_i) begin Tests: T1 T2 T3  326 1/1 state_d = ReadWaitSt; Tests: T1 T2 T3  327 end MISSING_ELSE 328 end else begin 329 1/1 state_d = IdleSt; Tests: T6 T12 T36  330 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T6 T12 T36  331 1/1 dai_cmd_done_o = 1'b1; Tests: T6 T12 T36  332 end 333 end 334 /////////////////////////////////////////////////////////////////// 335 // Wait for OTP response and write to readout register. Check 336 // whether descrambling is required or not. In case an OTP 337 // transaction fails, latch the OTP error code, and jump to 338 // terminal error state. 339 ReadWaitSt: begin 340 // Continuously check read access and bail out if this is not consistent. 341 1/1 if (part_sel_valid && (mubi8_test_false_strict(part_access_i[part_idx].read_lock) || Tests: T1 T2 T3  342 // HW digests always remain readable. 343 PartInfo[part_idx].hw_digest && otp_addr_o == 344 digest_addr_lut[part_idx])) begin 345 1/1 if (otp_rvalid_i) begin Tests: T1 T2 T3  346 // Check OTP return code. 347 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin Tests: T1 T2 T3  348 1/1 data_en = 1'b1; Tests: T1 T2 T3  349 // We do not need to descramble the digest values. 350 1/1 if (PartInfo[part_idx].secret && otp_addr_o != digest_addr_lut[part_idx]) begin Tests: T1 T2 T3  351 1/1 state_d = DescrSt; Tests: T2 T4 T5  352 end else begin 353 1/1 state_d = IdleSt; Tests: T1 T2 T3  354 1/1 dai_cmd_done_o = 1'b1; Tests: T1 T2 T3  355 end 356 // At this point the only error that we could have gotten are correctable ECC errors. 357 1/1 if (otp_err != NoError) begin Tests: T1 T2 T3  358 1/1 error_d = MacroEccCorrError; Tests: T126 T93 T100  359 end MISSING_ELSE 360 end else begin 361 1/1 state_d = ErrorSt; Tests: T12 T126 T7  362 1/1 error_d = otp_err; Tests: T12 T126 T7  363 end 364 end MISSING_ELSE 365 // At this point, this check MUST succeed - otherwise this means that 366 // there was a tampering attempt. Hence we go into a terminal error state 367 // when this check fails. 368 end else begin 369 0/1 ==> state_d = ErrorSt; 370 0/1 ==> error_d = FsmStateError; 371 end 372 end 373 /////////////////////////////////////////////////////////////////// 374 // Descrambling state. This first acquires the scrambling 375 // datapath mutex. Note that once the mutex is acquired, we have 376 // exclusive access to the scrambling datapath until we release 377 // the mutex by deasserting scrmbl_mtx_req_o. 378 // SEC_CM: SECRET.MEM.SCRAMBLE 379 DescrSt: begin 380 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T2 T4 T5  381 1/1 scrmbl_valid_o = 1'b1; Tests: T2 T4 T5  382 1/1 scrmbl_cmd_o = Decrypt; Tests: T2 T4 T5  383 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T4 T5  384 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin Tests: T2 T4 T5  385 1/1 state_d = DescrWaitSt; Tests: T2 T4 T5  386 end MISSING_ELSE 387 end 388 /////////////////////////////////////////////////////////////////// 389 // Wait for the descrambled data to return. Note that we release 390 // the mutex lock upon leaving this state. 391 // SEC_CM: SECRET.MEM.SCRAMBLE 392 DescrWaitSt: begin 393 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T2 T4 T5  394 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T4 T5  395 1/1 data_sel = ScrmblData; Tests: T2 T4 T5  396 1/1 if (scrmbl_valid_i) begin Tests: T2 T4 T5  397 1/1 state_d = IdleSt; Tests: T2 T4 T5  398 1/1 data_en = 1'b1; Tests: T2 T4 T5  399 1/1 dai_cmd_done_o = 1'b1; Tests: T2 T4 T5  400 end MISSING_ELSE 401 end 402 /////////////////////////////////////////////////////////////////// 403 // First, check whether write accesses are allowed to this 404 // partition, and error out otherwise. Note that for buffered 405 // partitions, we do not allow DAI writes to the digest offset. 406 // Unbuffered partitions have SW managed digests, hence that 407 // check is not needed in that case. The LC partition is 408 // permanently write locked and can hence not be written via the DAI. 409 WriteSt: begin 410 1/1 dai_prog_idle_o = 1'b0; Tests: T1 T2 T3  411 1/1 if (part_sel_valid && mubi8_test_false_strict(part_access_i[part_idx].write_lock) && Tests: T1 T2 T3  412 // If this is a HW digest write to a buffered partition. 413 ((PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].hw_digest && 414 base_sel_q == PartOffset && otp_addr_o == digest_addr_lut[part_idx]) || 415 // If this is a non HW digest write to a buffered partition. 416 (PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].hw_digest && 417 base_sel_q == DaiOffset && otp_addr_o < digest_addr_lut[part_idx]) || 418 // If this is a write to an unbuffered partition 419 (PartInfo[part_idx].variant != Buffered && base_sel_q == DaiOffset))) begin 420 1/1 otp_req_o = 1'b1; Tests: T1 T2 T3  421 // Depending on the partition configuration, 422 // the wrapper is instructed to ignore integrity errors. 423 1/1 if (PartInfo[part_idx].integrity) begin Tests: T1 T2 T3  424 1/1 otp_cmd_o = prim_otp_pkg::Write; Tests: T1 T2 T3  425 end else begin 426 1/1 otp_cmd_o = prim_otp_pkg::WriteRaw; Tests: T2 T3 T5  427 end 428 1/1 if (otp_gnt_i) begin Tests: T1 T2 T3  429 1/1 state_d = WriteWaitSt; Tests: T1 T2 T3  430 end MISSING_ELSE 431 end else begin 432 // Clear working register state. 433 1/1 data_clr = 1'b1; Tests: T1 T36 T94  434 1/1 state_d = IdleSt; Tests: T1 T36 T94  435 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T1 T36 T94  436 1/1 dai_cmd_done_o = 1'b1; Tests: T1 T36 T94  437 end 438 end 439 /////////////////////////////////////////////////////////////////// 440 // Wait for OTP response, and then go back to idle. In case an 441 // OTP transaction fails, latch the OTP error code, and jump to 442 // terminal error state. 443 WriteWaitSt: begin 444 1/1 dai_prog_idle_o = 1'b0; Tests: T1 T2 T3  445 // Continuously check write access and bail out if this is not consistent. 446 1/1 if (part_sel_valid && mubi8_test_false_strict(part_access_i[part_idx].write_lock) && Tests: T1 T2 T3  447 // If this is a HW digest write to a buffered partition. 448 ((PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].hw_digest && 449 base_sel_q == PartOffset && otp_addr_o == digest_addr_lut[part_idx]) || 450 // If this is a non HW digest write to a buffered partition. 451 (PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].hw_digest && 452 base_sel_q == DaiOffset && otp_addr_o < digest_addr_lut[part_idx]) || 453 // If this is a write to an unbuffered partition 454 (PartInfo[part_idx].variant != Buffered && base_sel_q == DaiOffset))) begin 455 456 1/1 if (otp_rvalid_i) begin Tests: T1 T2 T3  457 // Check OTP return code. Note that non-blank errors are recoverable. 458 1/1 if ((!(otp_err inside {NoError, MacroWriteBlankError}))) begin Tests: T1 T2 T3  459 0/1 ==> state_d = ErrorSt; 460 0/1 ==> error_d = otp_err; 461 end else begin 462 // Clear working register state. 463 1/1 data_clr = 1'b1; Tests: T1 T2 T3  464 1/1 state_d = IdleSt; Tests: T1 T2 T3  465 1/1 dai_cmd_done_o = 1'b1; Tests: T1 T2 T3  466 // Signal non-blank state, but do not go to terminal error state. 467 1/1 if (otp_err == MacroWriteBlankError) begin Tests: T1 T2 T3  468 1/1 error_d = otp_err; Tests: T12 T7 T8  469 end MISSING_ELSE 470 end 471 end MISSING_ELSE 472 // At this point, this check MUST succeed - otherwise this means that 473 // there was a tampering attempt. Hence we go into a terminal error state 474 // when this check fails. 475 end else begin 476 0/1 ==> state_d = ErrorSt; 477 0/1 ==> error_d = FsmStateError; 478 end 479 end 480 /////////////////////////////////////////////////////////////////// 481 // Scrambling state. This first acquires the scrambling 482 // datapath mutex. Note that once the mutex is acquired, we have 483 // exclusive access to the scrambling datapath until we release 484 // the mutex by deasserting scrmbl_mtx_req_o. 485 // SEC_CM: SECRET.MEM.SCRAMBLE 486 ScrSt: begin 487 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T2 T3 T4  488 // Check write access and bail out if this is not consistent. 489 1/1 if (part_sel_valid && mubi8_test_false_strict(part_access_i[part_idx].write_lock) && Tests: T2 T3 T4  490 // If this is a non HW digest write to a buffered partition. 491 (PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].secret && 492 PartInfo[part_idx].hw_digest && base_sel_q == DaiOffset && 493 otp_addr_o < digest_addr_lut[part_idx])) begin 494 495 1/1 scrmbl_valid_o = 1'b1; Tests: T2 T3 T4  496 1/1 scrmbl_cmd_o = Encrypt; Tests: T2 T3 T4  497 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T3 T4  498 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin Tests: T2 T3 T4  499 1/1 state_d = ScrWaitSt; Tests: T2 T3 T4  500 end MISSING_ELSE 501 end else begin 502 1/1 state_d = IdleSt; Tests: T6 T12 T36  503 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T6 T12 T36  504 1/1 dai_cmd_done_o = 1'b1; Tests: T6 T12 T36  505 end 506 end 507 /////////////////////////////////////////////////////////////////// 508 // Wait for the scrambled data to return. Note that we release 509 // the mutex lock upon leaving this state. 510 // SEC_CM: SECRET.MEM.SCRAMBLE 511 ScrWaitSt: begin 512 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T2 T3 T4  513 // Continously check write access and bail out if this is not consistent. 514 1/1 if (part_sel_valid && mubi8_test_false_strict(part_access_i[part_idx].write_lock) && Tests: T2 T3 T4  515 // If this is a non HW digest write to a buffered partition. 516 (PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].secret && 517 PartInfo[part_idx].hw_digest && base_sel_q == DaiOffset && 518 otp_addr_o < digest_addr_lut[part_idx])) begin 519 1/1 data_sel = ScrmblData; Tests: T2 T3 T4  520 1/1 if (scrmbl_valid_i) begin Tests: T2 T3 T4  521 1/1 state_d = WriteSt; Tests: T2 T3 T4  522 1/1 data_en = 1'b1; Tests: T2 T3 T4  523 end MISSING_ELSE 524 // At this point, this check MUST succeed - otherwise this means that 525 // there was a tampering attempt. Hence we go into a terminal error state 526 // when this check fails. 527 end else begin 528 0/1 ==> state_d = ErrorSt; 529 0/1 ==> error_d = FsmStateError; 530 end 531 end 532 /////////////////////////////////////////////////////////////////// 533 // First, acquire the mutex for the digest and clear the digest state. 534 // SEC_CM: PART.MEM.DIGEST 535 DigClrSt: begin 536 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T3 T5  537 1/1 scrmbl_valid_o = 1'b1; Tests: T1 T3 T5  538 // Need to reset the digest state and set digest mode to "standard". 539 1/1 scrmbl_cmd_o = DigestInit; Tests: T1 T3 T5  540 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin Tests: T1 T3 T5  541 1/1 state_d = DigReadSt; Tests: T1 T3 T5  542 end MISSING_ELSE 543 end 544 /////////////////////////////////////////////////////////////////// 545 // This requests a 64bit block to be pushed into the digest datapath. 546 // We also check here whether the partition has been write locked. 547 // SEC_CM: PART.MEM.DIGEST 548 DigReadSt: begin 549 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T3 T5  550 1/1 if (part_sel_valid && Tests: T1 T3 T5  551 mubi8_test_false_strict(part_access_i[part_idx].read_lock) && 552 mubi8_test_false_strict(part_access_i[part_idx].write_lock)) begin 553 1/1 otp_req_o = 1'b1; Tests: T1 T3 T5  554 // Depending on the partition configuration, 555 // the wrapper is instructed to ignore integrity errors. 556 1/1 if (PartInfo[part_idx].integrity) begin Tests: T1 T3 T5  557 1/1 otp_cmd_o = prim_otp_pkg::Read; Tests: T1 T3 T5  558 end else begin 559 0/1 ==> otp_cmd_o = prim_otp_pkg::ReadRaw; 560 end 561 1/1 if (otp_gnt_i) begin Tests: T1 T3 T5  562 1/1 state_d = DigReadWaitSt; Tests: T1 T3 T5  563 end MISSING_ELSE 564 end else begin 565 1/1 state_d = IdleSt; Tests: T6 T36 T94  566 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T6 T36 T94  567 1/1 dai_cmd_done_o = 1'b1; Tests: T6 T36 T94  568 end 569 end 570 /////////////////////////////////////////////////////////////////// 571 // Wait for OTP response and write to readout register. Check 572 // whether descrambling is required or not. In case an OTP 573 // transaction fails, latch the OTP error code, and jump to 574 // terminal error state. 575 // SEC_CM: PART.MEM.DIGEST 576 DigReadWaitSt: begin 577 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T3 T5  578 1/1 if (otp_rvalid_i) begin Tests: T1 T3 T5  579 1/1 cnt_en = 1'b1; Tests: T1 T3 T5  580 // Check OTP return code. 581 1/1 if ((!(otp_err inside {NoError, MacroEccCorrError}))) begin Tests: T1 T3 T5  582 0/1 ==> state_d = ErrorSt; 583 0/1 ==> error_d = otp_err; 584 end else begin 585 1/1 data_en = 1'b1; Tests: T1 T3 T5  586 1/1 state_d = DigSt; Tests: T1 T3 T5  587 // Signal soft ECC errors, but do not go into terminal error state. 588 1/1 if (otp_err == MacroEccCorrError) begin Tests: T1 T3 T5  589 0/1 ==> error_d = otp_err; 590 end MISSING_ELSE 591 end 592 end MISSING_ELSE 593 end 594 /////////////////////////////////////////////////////////////////// 595 // Push the word read into the scrambling datapath. The last 596 // block is repeated in case the number blocks in this partition 597 // is odd. 598 // SEC_CM: PART.MEM.DIGEST 599 DigSt: begin 600 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T3 T5  601 1/1 scrmbl_valid_o = 1'b1; Tests: T1 T3 T5  602 // No need to digest the digest value itself 603 1/1 if (otp_addr_o == digest_addr_lut[part_idx]) begin Tests: T1 T3 T5  604 // Trigger digest round in case this is the second block in a row. 605 1/1 if (!cnt[0]) begin Tests: T1 T3 T5  606 1/1 scrmbl_cmd_o = Digest; Tests: T1 T3 T5  607 1/1 if (scrmbl_ready_i) begin Tests: T1 T3 T5  608 1/1 state_d = DigFinSt; Tests: T1 T3 T5  609 end ==> MISSING_ELSE 610 // Otherwise, just load low word and go to padding state. 611 1/1 end else if (scrmbl_ready_i) begin Tests: T1 T5 T11  612 1/1 state_d = DigPadSt; Tests: T1 T5 T11  613 end MISSING_ELSE 614 end else begin 615 // Trigger digest round in case this is the second block in a row. 616 1/1 if (!cnt[0]) begin Tests: T1 T3 T5  617 1/1 scrmbl_cmd_o = Digest; Tests: T1 T3 T5  618 end MISSING_ELSE 619 // Go back and fetch more data blocks. 620 1/1 if (scrmbl_ready_i) begin Tests: T1 T3 T5  621 1/1 state_d = DigReadSt; Tests: T1 T3 T5  622 end MISSING_ELSE 623 end 624 end 625 /////////////////////////////////////////////////////////////////// 626 // Padding state, just repeat the last block and go to digest 627 // finalization. 628 // SEC_CM: PART.MEM.DIGEST 629 DigPadSt: begin 630 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T5 T11  631 1/1 scrmbl_valid_o = 1'b1; Tests: T1 T5 T11  632 1/1 scrmbl_cmd_o = Digest; Tests: T1 T5 T11  633 1/1 if (scrmbl_ready_i) begin Tests: T1 T5 T11  634 1/1 state_d = DigFinSt; Tests: T1 T5 T11  635 end ==> MISSING_ELSE 636 end 637 /////////////////////////////////////////////////////////////////// 638 // Trigger digest finalization and go wait for the result. 639 // SEC_CM: PART.MEM.DIGEST 640 DigFinSt: begin 641 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T3 T5  642 1/1 scrmbl_valid_o = 1'b1; Tests: T1 T3 T5  643 1/1 scrmbl_cmd_o = DigestFinalize; Tests: T1 T3 T5  644 1/1 if (scrmbl_ready_i) begin Tests: T1 T3 T5  645 1/1 state_d = DigWaitSt; Tests: T1 T3 T5  646 end MISSING_ELSE 647 end 648 /////////////////////////////////////////////////////////////////// 649 // Wait for the digest to return, and write the result to OTP. 650 // Note that the write address will be correct in this state, 651 // since the counter has been stepped to the correct address as 652 // part of the readout sequence, and the correct size for this 653 // access has been loaded before. 654 // SEC_CM: PART.MEM.DIGEST 655 DigWaitSt: begin 656 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T3 T5  657 1/1 data_sel = ScrmblData; Tests: T1 T3 T5  658 1/1 if (scrmbl_valid_i) begin Tests: T1 T3 T5  659 1/1 state_d = WriteSt; Tests: T1 T3 T5  660 1/1 data_en = 1'b1; Tests: T1 T3 T5  661 end MISSING_ELSE 662 end 663 /////////////////////////////////////////////////////////////////// 664 // Terminal Error State. This locks access to the DAI. Make sure 665 // an FsmStateError error code is assigned here, in case no error code has 666 // been assigned yet. 667 ErrorSt: begin 668 1/1 if (error_q == NoError) begin Tests: T2 T4 T11  669 1/1 error_d = FsmStateError; Tests: T27 T28 T29  670 end MISSING_ELSE 671 end 672 /////////////////////////////////////////////////////////////////// 673 // We should never get here. If we do (e.g. via a malicious 674 // glitch), error out immediately. 675 default: begin 676 state_d = ErrorSt; 677 fsm_err_o = 1'b1; 678 end 679 /////////////////////////////////////////////////////////////////// 680 endcase // state_q 681 682 // Unconditionally jump into the terminal error state in case of escalation. 683 // SEC_CM: DAI.FSM.LOCAL_ESC, DAI.FSM.GLOBAL_ESC 684 1/1 if (lc_ctrl_pkg::lc_tx_test_true_loose(escalate_en_i) || cnt_err) begin Tests: T1 T2 T3  685 1/1 state_d = ErrorSt; Tests: T2 T4 T11  686 1/1 fsm_err_o = 1'b1; Tests: T2 T4 T11  687 1/1 if (state_q != ErrorSt) begin Tests: T2 T4 T11  688 1/1 error_d = FsmStateError; Tests: T2 T4 T11  689 end MISSING_ELSE 690 end MISSING_ELSE 691 end 692 693 //////////////////////////// 694 // Partition Select Logic // 695 //////////////////////////// 696 697 // This checks which partition the address belongs to by comparing 698 // the incoming address to the partition address ranges. The onehot 699 // bitvector generated by the parallel comparisons is fed into a 700 // binary tree that determines the partition index with O(log(N)) delay. 701 702 logic [NumPart-1:0] part_sel_oh; 703 for (genvar k = 0; k < NumPart; k++) begin : gen_part_sel 704 localparam int unsigned PartEndInt = 32'(PartInfo[k].offset) + 32'(PartInfo[k].size); 705 localparam int unsigned DigestOffsetInt = PartEndInt - ScrmblBlockWidth / 8; 706 localparam int unsigned DigestAddrLutInt = DigestOffsetInt >> OtpAddrShift; 707 708 // PartEnd has an extra bit to cope with the case where offset + size overflows. However, we 709 // arrange the address map to make sure that PartEndInt is at most 1 << OtpByteAddrWidth. Check 710 // that here. 711 `ASSERT_INIT(PartEndMax_A, PartEndInt <= (1 << OtpByteAddrWidth)) 712 713 // The shift right by OtpAddrShift drops exactly the bottom bits that are needed to convert 714 // between OtpAddrWidth and OtpByteAddrWidth, so we know that we can slice safely here. 715 localparam bit [OtpAddrWidth-1:0] DigestAddrLut = DigestAddrLutInt[OtpAddrWidth-1:0]; 716 717 if (PartInfo[k].offset == 0) begin : gen_zero_offset 718 1/1 assign part_sel_oh[k] = ({1'b0, dai_addr_i} < PartEndInt[OtpByteAddrWidth:0]); Tests: T1 T2 T3  719 720 end else begin : gen_nonzero_offset 721 10/10 assign part_sel_oh[k] = (dai_addr_i >= PartInfo[k].offset) & Tests: T1 T2 T3  | T1 T2 T3  | T1 T2 T3  | T1 T2 T3  | T1 T2 T3  | T1 T2 T3  | T1 T2 T3  | T1 T2 T3  | T1 T2 T3  | T1 T2 T3  722 ({1'b0, dai_addr_i} < PartEndInt[OtpByteAddrWidth:0]); 723 end 724 assign digest_addr_lut[k] = DigestAddrLut; 725 end 726 727 `ASSERT(ScrmblBlockWidthGe8_A, ScrmblBlockWidth >= 8) 728 `ASSERT(PartSelMustBeOnehot_A, $onehot0(part_sel_oh)) 729 730 prim_arbiter_fixed #( 731 .N(NumPart), 732 .EnDataPort(0) 733 ) u_part_sel_idx ( 734 .clk_i, 735 .rst_ni, 736 .req_i ( part_sel_oh ), 737 .data_i ( '{default: '0} ), 738 .gnt_o ( ), // unused 739 .idx_o ( part_idx ), 740 .valid_o ( part_sel_valid ), // used for detecting OOB addresses 741 .data_o ( ), // unused 742 .ready_i ( 1'b0 ) 743 ); 744 745 ///////////////////////////////////// 746 // Address Calculations for Digest // 747 ///////////////////////////////////// 748 749 // Depending on whether this is a 32bit or 64bit partition, we cut off the lower address bits. 750 // Access sizes are either 64bit or 32bit, depending on what region the access goes to. 751 logic [OtpByteAddrWidth-1:0] addr_base; 752 always_comb begin : p_size_sel 753 1/1 otp_size_o = OtpSizeWidth'(unsigned'(32 / OtpWidth - 1)); Tests: T1 T2 T3  754 1/1 addr_base = {dai_addr_i[OtpByteAddrWidth-1:2], 2'h0}; Tests: T1 T2 T3  755 756 // 64bit transaction for scrambled partitions. 757 1/1 if (PartInfo[part_idx].secret) begin Tests: T1 T2 T3  758 1/1 otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth - 1)); Tests: T2 T3 T4  759 1/1 addr_base = {dai_addr_i[OtpByteAddrWidth-1:3], 3'h0}; Tests: T2 T3 T4  760 // 64bit transaction if computing a digest. 761 1/1 end else if (PartInfo[part_idx].hw_digest && (base_sel_q == PartOffset)) begin Tests: T1 T2 T3  762 1/1 otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth - 1)); Tests: T1 T3 T5  763 1/1 addr_base = PartInfo[part_idx].offset; Tests: T1 T3 T5  764 // 64bit transaction if the DAI address points to the partition's digest offset. 765 1/1 end else if ((PartInfo[part_idx].hw_digest || PartInfo[part_idx].sw_digest) && Tests: T1 T2 T3  766 (base_sel_q == DaiOffset) && 767 ({dai_addr_i[OtpByteAddrWidth-1:3], 2'b0} == digest_addr_lut[part_idx])) begin 768 1/1 otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth - 1)); Tests: T6 T129 T36  769 1/1 addr_base = {dai_addr_i[OtpByteAddrWidth-1:3], 3'h0}; Tests: T6 T129 T36  770 end MISSING_ELSE 771 end 772 773 // Address counter - this is only used for computing a digest, hence the increment is 774 // fixed to 8 byte. 775 // SEC_CM: DAI.CTR.REDUN 776 prim_count #( 777 .Width(CntWidth) 778 ) u_prim_count ( 779 .clk_i, 780 .rst_ni, 781 .clr_i(cnt_clr), 782 .set_i(1'b0), 783 .set_cnt_i('0), 784 .incr_en_i(cnt_en), 785 .decr_en_i(1'b0), 786 .step_i(CntWidth'(1)), 787 .commit_i(1'b1), 788 .cnt_o(cnt), 789 .cnt_after_commit_o(), 790 .err_o(cnt_err) 791 ); 792 793 // Note that OTP works on halfword (16bit) addresses, hence need to 794 // shift the addresses appropriately. 795 logic [OtpByteAddrWidth-1:0] addr_calc; 796 1/1 assign addr_calc = {cnt, {$clog2(ScrmblBlockWidth/8){1'b0}}} + addr_base; Tests: T1 T2 T3  797 1/1 assign otp_addr_o = OtpAddrWidth'(addr_calc >> OtpAddrShift); Tests: T1 T2 T3  798 799 /////////////// 800 // Registers // 801 /////////////// 802 803 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): 803.1 `ifdef SIMULATION 803.2 prim_sparse_fsm_flop #( 803.3 .StateEnumT(state_e), 803.4 .Width($bits(state_e)), 803.5 .ResetValue($bits(state_e)'(ResetSt)), 803.6 .EnableAlertTriggerSVA(1), 803.7 .CustomForceName("state_q") 803.8 ) u_state_regs ( 803.9 .clk_i ( clk_i ), 803.10 .rst_ni ( rst_ni ), 803.11 .state_i ( state_d ), 803.12 .state_o ( ) 803.13 ); 803.14 always_ff @(posedge clk_i or negedge rst_ni) begin 803.15 1/1 if (!rst_ni) begin Tests: T1 T2 T3  803.16 1/1 state_q <= ResetSt; Tests: T1 T2 T3  803.17 end else begin 803.18 1/1 state_q <= state_d; Tests: T1 T2 T3  803.19 end 803.20 end 803.21 u_state_regs_A: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (state_q === u_state_regs.state_o)) 803.22 else begin 803.23 `ifdef UVM 803.24 uvm_pkg::uvm_report_error("ASSERT FAILED", "u_state_regs_A", uvm_pkg::UVM_NONE, 803.25 "../src/lowrisc_ip_otp_ctrl_1.0/rtl/otp_ctrl_dai.sv", 803, "", 1); 803.26 `else 803.27 $error("%0t: (%0s:%0d) [%m] [ASSERT FAILED] %0s", $time, `__FILE__, `__LINE__, 803.28 `PRIM_STRINGIFY(u_state_regs_A)); 803.29 `endif 803.30 end 803.31 `else 803.32 prim_sparse_fsm_flop #( 803.33 .StateEnumT(state_e), 803.34 .Width($bits(state_e)), 803.35 .ResetValue($bits(state_e)'(ResetSt)), 803.36 .EnableAlertTriggerSVA(1) 803.37 ) u_state_regs ( 803.38 .clk_i ( `PRIM_FLOP_CLK ), 803.39 .rst_ni ( `PRIM_FLOP_RST ), 803.40 .state_i ( state_d ), 803.41 .state_o ( state_q ) 803.42 ); 803.43 `endif804 805 always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs 806 1/1 if (!rst_ni) begin Tests: T1 T2 T3  807 1/1 error_q <= NoError; Tests: T1 T2 T3  808 1/1 data_q <= '0; Tests: T1 T2 T3  809 1/1 base_sel_q <= DaiOffset; Tests: T1 T2 T3  810 end else begin 811 1/1 error_q <= error_d; Tests: T1 T2 T3  812 1/1 base_sel_q <= base_sel_d; Tests: T1 T2 T3  813 814 // Working register 815 1/1 if (data_clr) begin Tests: T1 T2 T3  816 1/1 data_q <= '0; Tests: T1 T2 T3  817 1/1 end else if (data_en) begin Tests: T1 T2 T3  818 1/1 if (data_sel == ScrmblData) begin Tests: T1 T2 T3  819 1/1 data_q <= scrmbl_data_i; Tests: T1 T2 T3  820 1/1 end else if (data_sel == DaiData) begin Tests: T1 T2 T3  821 1/1 data_q <= dai_wdata_i; Tests: T1 T2 T3  822 end else begin 823 1/1 data_q <= otp_rdata_i; Tests: T1 T2 T3  824 end 825 end MISSING_ELSE

Cond Coverage for Module : otp_ctrl_dai
TotalCoveredPercent
Conditions857790.59
Logical857790.59
Non-Logical00
Event00

 LINE       170
 EXPRESSION (((!otp_ctrl_part_pkg::PartInfo[part_idx].integrity)) && (otp_err_e'(otp_err_i) inside {MacroEccCorrError, MacroEccUncorrError}))
             --------------------------1-------------------------    -----------------------------------2-----------------------------------
-1--2-StatusTests
01CoveredT12,T126,T93
10CoveredT1,T2,T3
11CoveredT2,T85,T147

 LINE       184
 EXPRESSION ((state_q == IdleSt) ? data_q : '0)
             ---------1---------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       184
 SUB-EXPRESSION (state_q == IdleSt)
                ---------1---------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       266
 EXPRESSION (part_init_done_i == {otp_ctrl_reg_pkg::NumPart {1'b1}})
            ----------------------------1---------------------------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       350
 EXPRESSION (otp_ctrl_part_pkg::PartInfo[part_idx].secret && (otp_addr_o != digest_addr_lut[part_idx]))
             ----------------------1---------------------    --------------------2--------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT6,T129,T36
11CoveredT2,T4,T5

 LINE       350
 SUB-EXPRESSION (otp_addr_o != digest_addr_lut[part_idx])
                --------------------1--------------------
-1-StatusTests
0CoveredT6,T129,T36
1CoveredT1,T2,T3

 LINE       357
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT126,T93,T100

 LINE       384
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Not Covered
10Not Covered
11CoveredT2,T4,T5

 LINE       467
 EXPRESSION (otp_err == MacroWriteBlankError)
            ----------------1----------------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT12,T7,T8

 LINE       498
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTests
01Not Covered
10Not Covered
11CoveredT2,T3,T4

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

 LINE       588
 EXPRESSION (otp_err == MacroEccCorrError)
            ---------------1--------------
-1-StatusTests
0CoveredT1,T3,T5
1Not Covered

 LINE       603
 EXPRESSION (otp_addr_o == digest_addr_lut[part_idx])
            --------------------1--------------------
-1-StatusTests
0CoveredT1,T3,T5
1CoveredT1,T3,T5

 LINE       668
 EXPRESSION (error_q == NoError)
            ----------1---------
-1-StatusTests
0CoveredT2,T4,T11
1CoveredT27,T28,T29

 LINE       687
 EXPRESSION (state_q != ErrorSt)
            ----------1---------
-1-StatusTests
0CoveredT2,T4,T11
1CoveredT2,T4,T11

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b00001000000) & ({1'b0, dai_addr_i} < gen_part_sel[1].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT1,T2,T3
11CoveredT1,T2,T3

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b00110110000) & ({1'b0, dai_addr_i} < gen_part_sel[2].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT1,T2,T3
11CoveredT2,T4,T5

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b10001111000) & ({1'b0, dai_addr_i} < gen_part_sel[3].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT1,T2,T3
11CoveredT2,T3,T4

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b11001010000) & ({1'b0, dai_addr_i} < gen_part_sel[4].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT1,T2,T3
11CoveredT2,T4,T5

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b11001111000) & ({1'b0, dai_addr_i} < gen_part_sel[5].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT2,T3,T4
11CoveredT1,T2,T3

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b11011000000) & ({1'b0, dai_addr_i} < gen_part_sel[6].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT2,T3,T4
11CoveredT2,T3,T4

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b11011010000) & ({1'b0, dai_addr_i} < gen_part_sel[7].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT2,T3,T4
11CoveredT2,T5,T6

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b11011111000) & ({1'b0, dai_addr_i} < gen_part_sel[8].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT2,T4,T5
11CoveredT2,T3,T5

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b11101010000) & ({1'b0, dai_addr_i} < gen_part_sel[9].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT7,T8,T9
11CoveredT2,T4,T5

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b11110101000) & ({1'b0, dai_addr_i} < gen_part_sel[10].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   --------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10Not Covered
11CoveredT7,T8,T9

 LINE       761
 EXPRESSION (otp_ctrl_part_pkg::PartInfo[part_idx].hw_digest && (base_sel_q == PartOffset))
             -----------------------1-----------------------    -------------2------------
-1--2-StatusTests
01CoveredT1,T41,T14
10CoveredT2,T3,T4
11CoveredT1,T3,T5

 LINE       761
 SUB-EXPRESSION (base_sel_q == PartOffset)
                -------------1------------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T3,T5

 LINE       765
 EXPRESSION 
 Number  Term
      1  (otp_ctrl_part_pkg::PartInfo[part_idx].hw_digest || otp_ctrl_part_pkg::PartInfo[part_idx].sw_digest) && 
      2  (base_sel_q == DaiOffset) && 
      3  ({dai_addr_i[(otp_ctrl_reg_pkg::OtpByteAddrWidth - 1):3], 2'b0} == digest_addr_lut[part_idx]))
-1--2--3-StatusTests
011CoveredT148,T149
101CoveredT90,T95,T21
110CoveredT1,T2,T3
111CoveredT6,T129,T36

 LINE       765
 SUB-EXPRESSION (otp_ctrl_part_pkg::PartInfo[part_idx].hw_digest || otp_ctrl_part_pkg::PartInfo[part_idx].sw_digest)
                 -----------------------1-----------------------    -----------------------2-----------------------
-1--2-StatusTests
00CoveredT7,T8,T9
01CoveredT1,T2,T3
10CoveredT2,T3,T4

 LINE       765
 SUB-EXPRESSION (base_sel_q == DaiOffset)
                ------------1------------
-1-StatusTests
0CoveredT1,T41,T14
1CoveredT1,T2,T3

 LINE       765
 SUB-EXPRESSION ({dai_addr_i[(otp_ctrl_reg_pkg::OtpByteAddrWidth - 1):3], 2'b0} == digest_addr_lut[part_idx])
                ----------------------------------------------1----------------------------------------------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT6,T129,T36

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

 LINE       820
 EXPRESSION (data_sel == DaiData)
            ----------1----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

FSM Coverage for Module : otp_ctrl_dai
Summary for FSM :: state_q
TotalCoveredPercent
States 20 20 100.00 (Not included in score)
Transitions 48 40 83.33
Sequences 0 0

State, Transition and Sequence Details for FSM :: state_q
statesLine No.CoveredTests
DescrSt 351 Covered T2,T4,T5
DescrWaitSt 385 Covered T2,T4,T5
DigClrSt 299 Covered T1,T3,T5
DigFinSt 608 Covered T1,T3,T5
DigPadSt 612 Covered T1,T5,T11
DigReadSt 541 Covered T1,T3,T5
DigReadWaitSt 562 Covered T1,T3,T5
DigSt 586 Covered T1,T3,T5
DigWaitSt 645 Covered T1,T3,T5
ErrorSt 251 Covered T2,T4,T11
IdleSt 267 Covered T1,T2,T3
InitOtpSt 238 Covered T1,T2,T3
InitPartSt 254 Covered T1,T2,T3
ReadSt 281 Covered T1,T2,T3
ReadWaitSt 326 Covered T1,T2,T3
ResetSt 231 Covered T1,T2,T3
ScrSt 293 Covered T2,T3,T4
ScrWaitSt 499 Covered T2,T3,T4
WriteSt 295 Covered T1,T2,T3
WriteWaitSt 429 Covered T1,T2,T3


transitionsLine No.CoveredTests
DescrSt->DescrWaitSt 385 Covered T2,T4,T5
DescrSt->ErrorSt 685 Not Covered
DescrWaitSt->ErrorSt 685 Covered T150
DescrWaitSt->IdleSt 397 Covered T2,T4,T5
DigClrSt->DigReadSt 541 Covered T1,T3,T5
DigClrSt->ErrorSt 685 Not Covered
DigFinSt->DigWaitSt 645 Covered T1,T3,T5
DigFinSt->ErrorSt 685 Covered T151,T152,T153
DigPadSt->DigFinSt 634 Covered T1,T5,T11
DigPadSt->ErrorSt 685 Not Covered
DigReadSt->DigReadWaitSt 562 Covered T1,T3,T5
DigReadSt->ErrorSt 685 Not Covered
DigReadSt->IdleSt 565 Covered T6,T36,T94
DigReadWaitSt->DigSt 586 Covered T1,T3,T5
DigReadWaitSt->ErrorSt 582 Covered T154,T155,T156
DigSt->DigFinSt 608 Covered T1,T3,T5
DigSt->DigPadSt 612 Covered T1,T5,T11
DigSt->DigReadSt 621 Covered T1,T3,T5
DigSt->ErrorSt 685 Covered T157,T158,T159
DigWaitSt->ErrorSt 685 Covered T160,T161
DigWaitSt->WriteSt 659 Covered T1,T3,T5
IdleSt->DigClrSt 299 Covered T1,T3,T5
IdleSt->ErrorSt 685 Covered T4,T102,T126
IdleSt->ReadSt 281 Covered T1,T2,T3
IdleSt->ScrSt 293 Covered T2,T3,T4
IdleSt->WriteSt 295 Covered T1,T2,T3
InitOtpSt->ErrorSt 251 Covered T108
InitOtpSt->InitPartSt 254 Covered T1,T2,T3
InitPartSt->ErrorSt 685 Covered T2,T11,T85
InitPartSt->IdleSt 267 Covered T1,T2,T3
ReadSt->ErrorSt 685 Not Covered
ReadSt->IdleSt 329 Covered T6,T12,T36
ReadSt->ReadWaitSt 326 Covered T1,T2,T3
ReadWaitSt->DescrSt 351 Covered T2,T4,T5
ReadWaitSt->ErrorSt 361 Covered T12,T126,T7
ReadWaitSt->IdleSt 353 Covered T1,T2,T3
ResetSt->ErrorSt 685 Covered T109,T110,T111
ResetSt->InitOtpSt 238 Covered T1,T2,T3
ScrSt->ErrorSt 685 Not Covered
ScrSt->IdleSt 502 Covered T6,T12,T36
ScrSt->ScrWaitSt 499 Covered T2,T3,T4
ScrWaitSt->ErrorSt 528 Not Covered
ScrWaitSt->WriteSt 521 Covered T2,T3,T4
WriteSt->ErrorSt 685 Not Covered
WriteSt->IdleSt 434 Covered T1,T36,T94
WriteSt->WriteWaitSt 429 Covered T1,T2,T3
WriteWaitSt->ErrorSt 459 Covered T162,T163,T164
WriteWaitSt->IdleSt 464 Covered T1,T2,T3


Summary for FSM :: error_q
TotalCoveredPercent
States 4 4 100.00 (Not included in score)
Transitions 12 8 66.67
Sequences 0 0

State, Transition and Sequence Details for FSM :: error_q
statesLine No.CoveredTests
AccessError 330 Covered T1,T6,T12
FsmStateError 370 Covered T2,T4,T11
MacroEccCorrError 358 Covered T126,T93,T100
NoError 172 Covered T1,T2,T3


transitionsLine No.CoveredTests
AccessError->FsmStateError 370 Covered T165,T166,T24
AccessError->MacroEccCorrError 358 Not Covered
AccessError->NoError 172 Covered T1,T6,T12
FsmStateError->AccessError 330 Not Covered
FsmStateError->MacroEccCorrError 358 Not Covered
FsmStateError->NoError 172 Covered T2,T4,T11
MacroEccCorrError->AccessError 330 Not Covered
MacroEccCorrError->FsmStateError 370 Covered T147,T167,T168
MacroEccCorrError->NoError 172 Covered T126,T93,T100
NoError->AccessError 330 Covered T1,T6,T12
NoError->FsmStateError 370 Covered T2,T4,T11
NoError->MacroEccCorrError 358 Covered T126,T93,T100



Branch Coverage for Module : otp_ctrl_dai
Line No.TotalCoveredPercent
Branches 93 81 87.10
TERNARY 184 2 2 100.00
IF 170 2 2 100.00
CASE 225 74 62 83.78
IF 684 3 3 100.00
IF 757 4 4 100.00
IF 803 2 2 100.00
IF 806 6 6 100.00


184 assign dai_rdata_o = (state_q == IdleSt) ? data_q : '0; -1- ==> ==>

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


170 if (!PartInfo[part_idx].integrity && -1- 171 otp_err_e'(otp_err_i) inside {MacroEccCorrError, MacroEccUncorrError}) begin 172 otp_err = NoError; ==> 173 end MISSING_ELSE ==>

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


225 unique case (state_q) -1- 226 /////////////////////////////////////////////////////////////////// 227 // We get here after reset and wait until the power manager 228 // requests OTP initialization. If initialization is requested, 229 // an init command is written to the OTP macro, and we move on 230 // to the InitOtpSt waiting state. 231 ResetSt: begin 232 init_done_o = 1'b0; 233 dai_prog_idle_o = 1'b0; 234 data_clr = 1'b1; 235 if (init_req_i) begin -2- 236 otp_req_o = 1'b1; 237 if (otp_gnt_i) begin -3- 238 state_d = InitOtpSt; ==> 239 end MISSING_ELSE ==> 240 end MISSING_ELSE ==> 241 end 242 /////////////////////////////////////////////////////////////////// 243 // We wait here unitl the OTP macro has initialized without 244 // error. If an error occurred during this stage, we latch that 245 // error and move into a terminal error state. 246 InitOtpSt: begin 247 init_done_o = 1'b0; 248 dai_prog_idle_o = 1'b0; 249 if (otp_rvalid_i) begin -4- 250 if ((!(otp_err inside {NoError, MacroEccCorrError}))) begin -5- 251 state_d = ErrorSt; ==> 252 error_d = otp_err; 253 end else begin 254 state_d = InitPartSt; ==> 255 end 256 end MISSING_ELSE ==> 257 end 258 /////////////////////////////////////////////////////////////////// 259 // Since the OTP macro is now functional, we can send out an 260 // initialization request to all partitions and wait until they 261 // all have initialized. 262 InitPartSt: begin 263 init_done_o = 1'b0; 264 dai_prog_idle_o = 1'b0; 265 part_init_req_o = 1'b1; 266 if (part_init_done_i == {NumPart{1'b1}}) begin -6- 267 state_d = IdleSt; ==> 268 end MISSING_ELSE ==> 269 end 270 /////////////////////////////////////////////////////////////////// 271 // Idle state where we wait for incoming commands. 272 // Invalid commands trigger a CmdInvErr, which is recoverable. 273 IdleSt: begin 274 dai_idle_o = 1'b1; 275 if (dai_req_i) begin -7- 276 // This clears previous (recoverable) and reset the counter. 277 error_d = NoError; 278 cnt_clr = 1'b1; 279 unique case (dai_cmd_i) -8- 280 DaiRead: begin 281 state_d = ReadSt; ==> 282 // Clear the temporary data register. 283 data_clr = 1'b1; 284 base_sel_d = DaiOffset; 285 end 286 DaiWrite: begin 287 data_sel = DaiData; 288 // Fetch data block. 289 data_en = 1'b1; 290 base_sel_d = DaiOffset; 291 // If this partition is scrambled, directly go to write scrambling first. 292 if (PartInfo[part_idx].secret) begin -9- 293 state_d = ScrSt; ==> 294 end else begin 295 state_d = WriteSt; ==> 296 end 297 end 298 DaiDigest: begin 299 state_d = DigClrSt; ==> 300 scrmbl_mtx_req_o = 1'b1; 301 base_sel_d = PartOffset; 302 end 303 default: ; // Ignore invalid commands ==> 304 endcase // dai_cmd_i 305 end // dai_req_i MISSING_ELSE ==> 306 end 307 /////////////////////////////////////////////////////////////////// 308 // Each time we request a block of data from OTP, we re-check 309 // whether read access has been locked for this partition. If 310 // that is the case, we immediately bail out. Otherwise, we 311 // request a block of data from OTP. 312 ReadSt: begin 313 if (part_sel_valid && (mubi8_test_false_strict(part_access_i[part_idx].read_lock) || -10- 314 // HW digests always remain readable. 315 PartInfo[part_idx].hw_digest && otp_addr_o == 316 digest_addr_lut[part_idx])) begin 317 otp_req_o = 1'b1; 318 // Depending on the partition configuration, 319 // the wrapper is instructed to ignore integrity errors. 320 if (PartInfo[part_idx].integrity) begin -11- 321 otp_cmd_o = prim_otp_pkg::Read; ==> 322 end else begin 323 otp_cmd_o = prim_otp_pkg::ReadRaw; ==> 324 end 325 if (otp_gnt_i) begin -12- 326 state_d = ReadWaitSt; ==> 327 end MISSING_ELSE ==> 328 end else begin 329 state_d = IdleSt; ==> 330 error_d = AccessError; // Signal this error, but do not go into terminal error state. 331 dai_cmd_done_o = 1'b1; 332 end 333 end 334 /////////////////////////////////////////////////////////////////// 335 // Wait for OTP response and write to readout register. Check 336 // whether descrambling is required or not. In case an OTP 337 // transaction fails, latch the OTP error code, and jump to 338 // terminal error state. 339 ReadWaitSt: begin 340 // Continuously check read access and bail out if this is not consistent. 341 if (part_sel_valid && (mubi8_test_false_strict(part_access_i[part_idx].read_lock) || -13- 342 // HW digests always remain readable. 343 PartInfo[part_idx].hw_digest && otp_addr_o == 344 digest_addr_lut[part_idx])) begin 345 if (otp_rvalid_i) begin -14- 346 // Check OTP return code. 347 if (otp_err inside {NoError, MacroEccCorrError}) begin -15- 348 data_en = 1'b1; 349 // We do not need to descramble the digest values. 350 if (PartInfo[part_idx].secret && otp_addr_o != digest_addr_lut[part_idx]) begin -16- 351 state_d = DescrSt; ==> 352 end else begin 353 state_d = IdleSt; ==> 354 dai_cmd_done_o = 1'b1; 355 end 356 // At this point the only error that we could have gotten are correctable ECC errors. 357 if (otp_err != NoError) begin -17- 358 error_d = MacroEccCorrError; ==> 359 end MISSING_ELSE ==> 360 end else begin 361 state_d = ErrorSt; ==> 362 error_d = otp_err; 363 end 364 end MISSING_ELSE ==> 365 // At this point, this check MUST succeed - otherwise this means that 366 // there was a tampering attempt. Hence we go into a terminal error state 367 // when this check fails. 368 end else begin 369 state_d = ErrorSt; ==> 370 error_d = FsmStateError; 371 end 372 end 373 /////////////////////////////////////////////////////////////////// 374 // Descrambling state. This first acquires the scrambling 375 // datapath mutex. Note that once the mutex is acquired, we have 376 // exclusive access to the scrambling datapath until we release 377 // the mutex by deasserting scrmbl_mtx_req_o. 378 // SEC_CM: SECRET.MEM.SCRAMBLE 379 DescrSt: begin 380 scrmbl_mtx_req_o = 1'b1; 381 scrmbl_valid_o = 1'b1; 382 scrmbl_cmd_o = Decrypt; 383 scrmbl_sel_o = PartInfo[part_idx].key_sel; 384 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin -18- 385 state_d = DescrWaitSt; ==> 386 end MISSING_ELSE ==> 387 end 388 /////////////////////////////////////////////////////////////////// 389 // Wait for the descrambled data to return. Note that we release 390 // the mutex lock upon leaving this state. 391 // SEC_CM: SECRET.MEM.SCRAMBLE 392 DescrWaitSt: begin 393 scrmbl_mtx_req_o = 1'b1; 394 scrmbl_sel_o = PartInfo[part_idx].key_sel; 395 data_sel = ScrmblData; 396 if (scrmbl_valid_i) begin -19- 397 state_d = IdleSt; ==> 398 data_en = 1'b1; 399 dai_cmd_done_o = 1'b1; 400 end MISSING_ELSE ==> 401 end 402 /////////////////////////////////////////////////////////////////// 403 // First, check whether write accesses are allowed to this 404 // partition, and error out otherwise. Note that for buffered 405 // partitions, we do not allow DAI writes to the digest offset. 406 // Unbuffered partitions have SW managed digests, hence that 407 // check is not needed in that case. The LC partition is 408 // permanently write locked and can hence not be written via the DAI. 409 WriteSt: begin 410 dai_prog_idle_o = 1'b0; 411 if (part_sel_valid && mubi8_test_false_strict(part_access_i[part_idx].write_lock) && -20- 412 // If this is a HW digest write to a buffered partition. 413 ((PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].hw_digest && 414 base_sel_q == PartOffset && otp_addr_o == digest_addr_lut[part_idx]) || 415 // If this is a non HW digest write to a buffered partition. 416 (PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].hw_digest && 417 base_sel_q == DaiOffset && otp_addr_o < digest_addr_lut[part_idx]) || 418 // If this is a write to an unbuffered partition 419 (PartInfo[part_idx].variant != Buffered && base_sel_q == DaiOffset))) begin 420 otp_req_o = 1'b1; 421 // Depending on the partition configuration, 422 // the wrapper is instructed to ignore integrity errors. 423 if (PartInfo[part_idx].integrity) begin -21- 424 otp_cmd_o = prim_otp_pkg::Write; ==> 425 end else begin 426 otp_cmd_o = prim_otp_pkg::WriteRaw; ==> 427 end 428 if (otp_gnt_i) begin -22- 429 state_d = WriteWaitSt; ==> 430 end MISSING_ELSE ==> 431 end else begin 432 // Clear working register state. 433 data_clr = 1'b1; ==> 434 state_d = IdleSt; 435 error_d = AccessError; // Signal this error, but do not go into terminal error state. 436 dai_cmd_done_o = 1'b1; 437 end 438 end 439 /////////////////////////////////////////////////////////////////// 440 // Wait for OTP response, and then go back to idle. In case an 441 // OTP transaction fails, latch the OTP error code, and jump to 442 // terminal error state. 443 WriteWaitSt: begin 444 dai_prog_idle_o = 1'b0; 445 // Continuously check write access and bail out if this is not consistent. 446 if (part_sel_valid && mubi8_test_false_strict(part_access_i[part_idx].write_lock) && -23- 447 // If this is a HW digest write to a buffered partition. 448 ((PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].hw_digest && 449 base_sel_q == PartOffset && otp_addr_o == digest_addr_lut[part_idx]) || 450 // If this is a non HW digest write to a buffered partition. 451 (PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].hw_digest && 452 base_sel_q == DaiOffset && otp_addr_o < digest_addr_lut[part_idx]) || 453 // If this is a write to an unbuffered partition 454 (PartInfo[part_idx].variant != Buffered && base_sel_q == DaiOffset))) begin 455 456 if (otp_rvalid_i) begin -24- 457 // Check OTP return code. Note that non-blank errors are recoverable. 458 if ((!(otp_err inside {NoError, MacroWriteBlankError}))) begin -25- 459 state_d = ErrorSt; ==> 460 error_d = otp_err; 461 end else begin 462 // Clear working register state. 463 data_clr = 1'b1; 464 state_d = IdleSt; 465 dai_cmd_done_o = 1'b1; 466 // Signal non-blank state, but do not go to terminal error state. 467 if (otp_err == MacroWriteBlankError) begin -26- 468 error_d = otp_err; ==> 469 end MISSING_ELSE ==> 470 end 471 end MISSING_ELSE ==> 472 // At this point, this check MUST succeed - otherwise this means that 473 // there was a tampering attempt. Hence we go into a terminal error state 474 // when this check fails. 475 end else begin 476 state_d = ErrorSt; ==> 477 error_d = FsmStateError; 478 end 479 end 480 /////////////////////////////////////////////////////////////////// 481 // Scrambling state. This first acquires the scrambling 482 // datapath mutex. Note that once the mutex is acquired, we have 483 // exclusive access to the scrambling datapath until we release 484 // the mutex by deasserting scrmbl_mtx_req_o. 485 // SEC_CM: SECRET.MEM.SCRAMBLE 486 ScrSt: begin 487 scrmbl_mtx_req_o = 1'b1; 488 // Check write access and bail out if this is not consistent. 489 if (part_sel_valid && mubi8_test_false_strict(part_access_i[part_idx].write_lock) && -27- 490 // If this is a non HW digest write to a buffered partition. 491 (PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].secret && 492 PartInfo[part_idx].hw_digest && base_sel_q == DaiOffset && 493 otp_addr_o < digest_addr_lut[part_idx])) begin 494 495 scrmbl_valid_o = 1'b1; 496 scrmbl_cmd_o = Encrypt; 497 scrmbl_sel_o = PartInfo[part_idx].key_sel; 498 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin -28- 499 state_d = ScrWaitSt; ==> 500 end MISSING_ELSE ==> 501 end else begin 502 state_d = IdleSt; ==> 503 error_d = AccessError; // Signal this error, but do not go into terminal error state. 504 dai_cmd_done_o = 1'b1; 505 end 506 end 507 /////////////////////////////////////////////////////////////////// 508 // Wait for the scrambled data to return. Note that we release 509 // the mutex lock upon leaving this state. 510 // SEC_CM: SECRET.MEM.SCRAMBLE 511 ScrWaitSt: begin 512 scrmbl_mtx_req_o = 1'b1; 513 // Continously check write access and bail out if this is not consistent. 514 if (part_sel_valid && mubi8_test_false_strict(part_access_i[part_idx].write_lock) && -29- 515 // If this is a non HW digest write to a buffered partition. 516 (PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].secret && 517 PartInfo[part_idx].hw_digest && base_sel_q == DaiOffset && 518 otp_addr_o < digest_addr_lut[part_idx])) begin 519 data_sel = ScrmblData; 520 if (scrmbl_valid_i) begin -30- 521 state_d = WriteSt; ==> 522 data_en = 1'b1; 523 end MISSING_ELSE ==> 524 // At this point, this check MUST succeed - otherwise this means that 525 // there was a tampering attempt. Hence we go into a terminal error state 526 // when this check fails. 527 end else begin 528 state_d = ErrorSt; ==> 529 error_d = FsmStateError; 530 end 531 end 532 /////////////////////////////////////////////////////////////////// 533 // First, acquire the mutex for the digest and clear the digest state. 534 // SEC_CM: PART.MEM.DIGEST 535 DigClrSt: begin 536 scrmbl_mtx_req_o = 1'b1; 537 scrmbl_valid_o = 1'b1; 538 // Need to reset the digest state and set digest mode to "standard". 539 scrmbl_cmd_o = DigestInit; 540 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin -31- 541 state_d = DigReadSt; ==> 542 end MISSING_ELSE ==> 543 end 544 /////////////////////////////////////////////////////////////////// 545 // This requests a 64bit block to be pushed into the digest datapath. 546 // We also check here whether the partition has been write locked. 547 // SEC_CM: PART.MEM.DIGEST 548 DigReadSt: begin 549 scrmbl_mtx_req_o = 1'b1; 550 if (part_sel_valid && -32- 551 mubi8_test_false_strict(part_access_i[part_idx].read_lock) && 552 mubi8_test_false_strict(part_access_i[part_idx].write_lock)) begin 553 otp_req_o = 1'b1; 554 // Depending on the partition configuration, 555 // the wrapper is instructed to ignore integrity errors. 556 if (PartInfo[part_idx].integrity) begin -33- 557 otp_cmd_o = prim_otp_pkg::Read; ==> 558 end else begin 559 otp_cmd_o = prim_otp_pkg::ReadRaw; ==> 560 end 561 if (otp_gnt_i) begin -34- 562 state_d = DigReadWaitSt; ==> 563 end MISSING_ELSE ==> 564 end else begin 565 state_d = IdleSt; ==> 566 error_d = AccessError; // Signal this error, but do not go into terminal error state. 567 dai_cmd_done_o = 1'b1; 568 end 569 end 570 /////////////////////////////////////////////////////////////////// 571 // Wait for OTP response and write to readout register. Check 572 // whether descrambling is required or not. In case an OTP 573 // transaction fails, latch the OTP error code, and jump to 574 // terminal error state. 575 // SEC_CM: PART.MEM.DIGEST 576 DigReadWaitSt: begin 577 scrmbl_mtx_req_o = 1'b1; 578 if (otp_rvalid_i) begin -35- 579 cnt_en = 1'b1; 580 // Check OTP return code. 581 if ((!(otp_err inside {NoError, MacroEccCorrError}))) begin -36- 582 state_d = ErrorSt; ==> 583 error_d = otp_err; 584 end else begin 585 data_en = 1'b1; 586 state_d = DigSt; 587 // Signal soft ECC errors, but do not go into terminal error state. 588 if (otp_err == MacroEccCorrError) begin -37- 589 error_d = otp_err; ==> 590 end MISSING_ELSE ==> 591 end 592 end MISSING_ELSE ==> 593 end 594 /////////////////////////////////////////////////////////////////// 595 // Push the word read into the scrambling datapath. The last 596 // block is repeated in case the number blocks in this partition 597 // is odd. 598 // SEC_CM: PART.MEM.DIGEST 599 DigSt: begin 600 scrmbl_mtx_req_o = 1'b1; 601 scrmbl_valid_o = 1'b1; 602 // No need to digest the digest value itself 603 if (otp_addr_o == digest_addr_lut[part_idx]) begin -38- 604 // Trigger digest round in case this is the second block in a row. 605 if (!cnt[0]) begin -39- 606 scrmbl_cmd_o = Digest; 607 if (scrmbl_ready_i) begin -40- 608 state_d = DigFinSt; ==> 609 end MISSING_ELSE ==> 610 // Otherwise, just load low word and go to padding state. 611 end else if (scrmbl_ready_i) begin -41- 612 state_d = DigPadSt; ==> 613 end MISSING_ELSE ==> 614 end else begin 615 // Trigger digest round in case this is the second block in a row. 616 if (!cnt[0]) begin -42- 617 scrmbl_cmd_o = Digest; ==> 618 end MISSING_ELSE ==> 619 // Go back and fetch more data blocks. 620 if (scrmbl_ready_i) begin -43- 621 state_d = DigReadSt; ==> 622 end MISSING_ELSE ==> 623 end 624 end 625 /////////////////////////////////////////////////////////////////// 626 // Padding state, just repeat the last block and go to digest 627 // finalization. 628 // SEC_CM: PART.MEM.DIGEST 629 DigPadSt: begin 630 scrmbl_mtx_req_o = 1'b1; 631 scrmbl_valid_o = 1'b1; 632 scrmbl_cmd_o = Digest; 633 if (scrmbl_ready_i) begin -44- 634 state_d = DigFinSt; ==> 635 end MISSING_ELSE ==> 636 end 637 /////////////////////////////////////////////////////////////////// 638 // Trigger digest finalization and go wait for the result. 639 // SEC_CM: PART.MEM.DIGEST 640 DigFinSt: begin 641 scrmbl_mtx_req_o = 1'b1; 642 scrmbl_valid_o = 1'b1; 643 scrmbl_cmd_o = DigestFinalize; 644 if (scrmbl_ready_i) begin -45- 645 state_d = DigWaitSt; ==> 646 end MISSING_ELSE ==> 647 end 648 /////////////////////////////////////////////////////////////////// 649 // Wait for the digest to return, and write the result to OTP. 650 // Note that the write address will be correct in this state, 651 // since the counter has been stepped to the correct address as 652 // part of the readout sequence, and the correct size for this 653 // access has been loaded before. 654 // SEC_CM: PART.MEM.DIGEST 655 DigWaitSt: begin 656 scrmbl_mtx_req_o = 1'b1; 657 data_sel = ScrmblData; 658 if (scrmbl_valid_i) begin -46- 659 state_d = WriteSt; ==> 660 data_en = 1'b1; 661 end MISSING_ELSE ==> 662 end 663 /////////////////////////////////////////////////////////////////// 664 // Terminal Error State. This locks access to the DAI. Make sure 665 // an FsmStateError error code is assigned here, in case no error code has 666 // been assigned yet. 667 ErrorSt: begin 668 if (error_q == NoError) begin -47- 669 error_d = FsmStateError; ==> 670 end MISSING_ELSE ==> 671 end 672 /////////////////////////////////////////////////////////////////// 673 // We should never get here. If we do (e.g. via a malicious 674 // glitch), error out immediately. 675 default: begin 676 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--41--42--43--44--45--46--47-StatusTests
ResetSt 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ResetSt 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Not Covered
ResetSt 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
InitOtpSt - - 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Not Covered
InitOtpSt - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
InitOtpSt - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
InitPartSt - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
InitPartSt - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
IdleSt - - - - - 1 DaiRead - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
IdleSt - - - - - 1 DaiWrite 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T4
IdleSt - - - - - 1 DaiWrite 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
IdleSt - - - - - 1 DaiDigest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T3,T5
IdleSt - - - - - 1 default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Not Covered
IdleSt - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadSt - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadSt - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T4
ReadSt - - - - - - - - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadSt - - - - - - - - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T36,T94,T9
ReadSt - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T6,T12,T36
ReadWaitSt - - - - - - - - - - - 1 1 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T4,T5
ReadWaitSt - - - - - - - - - - - 1 1 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 1 1 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T126,T93,T100
ReadWaitSt - - - - - - - - - - - 1 1 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 1 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T12,T126,T7
ReadWaitSt - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Not Covered
DescrSt - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T4,T5
DescrSt - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T6,T92,T119
DescrWaitSt - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T4,T5
DescrWaitSt - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T4,T5
WriteSt - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
WriteSt - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T5
WriteSt - - - - - - - - - - - - - - - - - - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
WriteSt - - - - - - - - - - - - - - - - - - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T36,T94,T9
WriteSt - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T36,T94
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 1 1 1 - - - - - - - - - - - - - - - - - - - - - - Not Covered
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 1 1 0 1 - - - - - - - - - - - - - - - - - - - - - Covered T12,T7,T8
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 1 1 0 0 - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - Not Covered
ScrSt - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - - - Covered T2,T3,T4
ScrSt - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - Covered T6,T92,T119
ScrSt - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - Covered T6,T12,T36
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - Covered T2,T3,T4
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - Covered T2,T3,T4
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - Not Covered
DigClrSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - Covered T1,T3,T5
DigClrSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - Covered T6,T92,T119
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - Covered T1,T3,T5
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - Not Covered
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 1 - - - - - - - - - - - - - Covered T1,T3,T5
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 0 - - - - - - - - - - - - - Covered T36,T94,T9
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - Covered T6,T36,T94
DigReadWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - Not Covered
DigReadWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 1 - - - - - - - - - - Not Covered
DigReadWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 0 - - - - - - - - - - Covered T1,T3,T5
DigReadWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - Covered T1,T3,T5
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 1 - - - - - - - Covered T1,T3,T5
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 0 - - - - - - - Not Covered
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - 1 - - - - - - Covered T1,T5,T11
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - 0 - - - - - - Covered T1
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - 1 - - - - - Covered T1,T3,T5
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - 0 - - - - - Covered T1,T3,T5
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 1 - - - - Covered T1,T3,T5
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0 - - - - Covered T1,T3,T5
DigPadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - Covered T1,T5,T11
DigPadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - Not Covered
DigFinSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - Covered T1,T3,T5
DigFinSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - Covered T1,T3,T5
DigWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - Covered T1,T3,T5
DigWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - Covered T1,T3,T5
ErrorSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 Covered T27,T28,T29
ErrorSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 Covered T2,T4,T11
default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T27,T28,T29


684 if (lc_ctrl_pkg::lc_tx_test_true_loose(escalate_en_i) || cnt_err) begin -1- 685 state_d = ErrorSt; 686 fsm_err_o = 1'b1; 687 if (state_q != ErrorSt) begin -2- 688 error_d = FsmStateError; ==> 689 end MISSING_ELSE ==> 690 end MISSING_ELSE ==>

Branches:
-1--2-StatusTests
1 1 Covered T2,T4,T11
1 0 Covered T2,T4,T11
0 - Covered T1,T2,T3


757 if (PartInfo[part_idx].secret) begin -1- 758 otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth - 1)); ==> 759 addr_base = {dai_addr_i[OtpByteAddrWidth-1:3], 3'h0}; 760 // 64bit transaction if computing a digest. 761 end else if (PartInfo[part_idx].hw_digest && (base_sel_q == PartOffset)) begin -2- 762 otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth - 1)); ==> 763 addr_base = PartInfo[part_idx].offset; 764 // 64bit transaction if the DAI address points to the partition's digest offset. 765 end else if ((PartInfo[part_idx].hw_digest || PartInfo[part_idx].sw_digest) && -3- 766 (base_sel_q == DaiOffset) && 767 ({dai_addr_i[OtpByteAddrWidth-1:3], 2'b0} == digest_addr_lut[part_idx])) begin 768 otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth - 1)); ==> 769 addr_base = {dai_addr_i[OtpByteAddrWidth-1:3], 3'h0}; 770 end MISSING_ELSE ==>

Branches:
-1--2--3-StatusTests
1 - - Covered T2,T3,T4
0 1 - Covered T1,T3,T5
0 0 1 Covered T6,T129,T36
0 0 0 Covered T1,T2,T3


803 `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


806 if (!rst_ni) begin -1- 807 error_q <= NoError; ==> 808 data_q <= '0; 809 base_sel_q <= DaiOffset; 810 end else begin 811 error_q <= error_d; 812 base_sel_q <= base_sel_d; 813 814 // Working register 815 if (data_clr) begin -2- 816 data_q <= '0; ==> 817 end else if (data_en) begin -3- 818 if (data_sel == ScrmblData) begin -4- 819 data_q <= scrmbl_data_i; ==> 820 end else if (data_sel == DaiData) begin -5- 821 data_q <= dai_wdata_i; ==> 822 end else begin 823 data_q <= otp_rdata_i; ==> 824 end 825 end MISSING_ELSE ==>

Branches:
-1--2--3--4--5-StatusTests
1 - - - - Covered T1,T2,T3
0 1 - - - Covered T1,T2,T3
0 0 1 1 - Covered T1,T2,T3
0 0 1 0 1 Covered T1,T2,T3
0 0 1 0 0 Covered T1,T2,T3
0 0 0 - - Covered T1,T2,T3


Assert Coverage for Module : otp_ctrl_dai
TotalAttemptedPercentSucceeded/MatchedPercent
Assertions 33 33 100.00 33 100.00
Cover properties 0 0 0
Cover sequences 0 0 0
Total 33 33 100.00 33 100.00




Assertion Details

NameAttemptsReal SuccessesFailuresIncomplete
CheckNativeOtpWidth0_A 1122 1122 0 0
CheckNativeOtpWidth1_A 1122 1122 0 0
DaiIdleKnown_A 100520911 99678943 0 0
DaiRdataKnown_A 100520911 99678943 0 0
ErrorKnown_A 100520911 99678943 0 0
InitDoneKnown_A 100520911 99678943 0 0
OtpAddrKnown_A 100520911 99678943 0 0
OtpCmdKnown_A 100520911 99678943 0 0
OtpErrorState_A 100520911 352 0 0
OtpReqKnown_A 100520911 99678943 0 0
OtpSizeKnown_A 100520911 99678943 0 0
OtpWdataKnown_A 100520911 99678943 0 0
PartInitReqKnown_A 100520911 99678943 0 0
PartSelMustBeOnehot_A 100520911 99678943 0 0
ScrmblBlockWidthGe8_A 100520911 99678943 0 0
ScrmblCmdKnown_A 100520911 99678943 0 0
ScrmblDataKnown_A 100520911 99678943 0 0
ScrmblModeKnown_A 100520911 99678943 0 0
ScrmblMtxReqKnown_A 100520911 99678943 0 0
ScrmblSelKnown_A 100520911 99678943 0 0
ScrmblValidKnown_A 100520911 99678943 0 0
gen_part_sel[0].PartEndMax_A 1122 1122 0 0
gen_part_sel[10].PartEndMax_A 1122 1122 0 0
gen_part_sel[1].PartEndMax_A 1122 1122 0 0
gen_part_sel[2].PartEndMax_A 1122 1122 0 0
gen_part_sel[3].PartEndMax_A 1122 1122 0 0
gen_part_sel[4].PartEndMax_A 1122 1122 0 0
gen_part_sel[5].PartEndMax_A 1122 1122 0 0
gen_part_sel[6].PartEndMax_A 1122 1122 0 0
gen_part_sel[7].PartEndMax_A 1122 1122 0 0
gen_part_sel[8].PartEndMax_A 1122 1122 0 0
gen_part_sel[9].PartEndMax_A 1122 1122 0 0
u_state_regs_A 100520911 99678943 0 0


CheckNativeOtpWidth0_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

CheckNativeOtpWidth1_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

DaiIdleKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

DaiRdataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

ErrorKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

InitDoneKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

OtpAddrKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

OtpCmdKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

OtpErrorState_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 352 0 0
T7 0 1 0 0
T8 0 1 0 0
T9 0 1 0 0
T12 24721 1 0 0
T13 35219 0 0 0
T17 3538 0 0 0
T36 71599 0 0 0
T92 19581 0 0 0
T94 33983 0 0 0
T97 11787 0 0 0
T102 18611 0 0 0
T125 70975 0 0 0
T126 0 3 0 0
T129 38435 0 0 0
T147 0 8 0 0
T169 0 1 0 0
T170 0 1 0 0
T171 0 1 0 0
T172 0 4 0 0

OtpReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

OtpSizeKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

OtpWdataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

PartInitReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

PartSelMustBeOnehot_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

ScrmblBlockWidthGe8_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

ScrmblCmdKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

ScrmblDataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

ScrmblModeKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

ScrmblMtxReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

ScrmblSelKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

ScrmblValidKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

gen_part_sel[0].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[10].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[1].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[2].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[3].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[4].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[5].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[6].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[7].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[8].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[9].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

u_state_regs_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

Line Coverage for Instance : tb.dut.u_otp_ctrl_dai
Line No.TotalCoveredPercent
TOTAL24323395.88
ALWAYS16933100.00
CONT_ASSIGN17711100.00
CONT_ASSIGN17911100.00
CONT_ASSIGN18011100.00
CONT_ASSIGN18411100.00
ALWAYS18719518594.87
CONT_ASSIGN71811100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
CONT_ASSIGN72111100.00
ALWAYS7531111100.00
CONT_ASSIGN79611100.00
CONT_ASSIGN79711100.00
ALWAYS80333100.00
ALWAYS8061414100.00

168 always_comb begin 169 1/1 otp_err = otp_err_e'(otp_err_i); Tests: T1 T2 T3  170 1/1 if (!PartInfo[part_idx].integrity && Tests: T1 T2 T3  171 otp_err_e'(otp_err_i) inside {MacroEccCorrError, MacroEccUncorrError}) begin 172 1/1 otp_err = NoError; Tests: T2 T85 T147  173 end MISSING_ELSE 174 end 175 176 // Output partition error state. 177 1/1 assign error_o = error_q; Tests: T1 T2 T3  178 // Working register is connected to data outputs. 179 1/1 assign otp_wdata_o = data_q; Tests: T1 T2 T3  180 1/1 assign scrmbl_data_o = data_q; Tests: T1 T2 T3  181 // Only expose this working register in IdleSt. 182 // The FSM below makes sure to clear this register 183 // after digest and write ops. 184 1/1 assign dai_rdata_o = (state_q == IdleSt) ? data_q : '0; Tests: T1 T2 T3  185 186 always_comb begin : p_fsm 187 1/1 state_d = state_q; Tests: T1 T2 T3  188 189 // Init signals 190 1/1 init_done_o = 1'b1; Tests: T1 T2 T3  191 1/1 part_init_req_o = 1'b0; Tests: T1 T2 T3  192 193 // DAI signals 194 1/1 dai_idle_o = 1'b0; Tests: T1 T2 T3  195 1/1 dai_prog_idle_o = 1'b1; Tests: T1 T2 T3  196 1/1 dai_cmd_done_o = 1'b0; Tests: T1 T2 T3  197 198 // OTP signals 199 1/1 otp_req_o = 1'b0; Tests: T1 T2 T3  200 1/1 otp_cmd_o = prim_otp_pkg::Init; Tests: T1 T2 T3  201 202 // Scrambling mutex 203 1/1 scrmbl_mtx_req_o = 1'b0; Tests: T1 T2 T3  204 205 // Scrambling datapath 206 1/1 scrmbl_cmd_o = LoadShadow; Tests: T1 T2 T3  207 1/1 scrmbl_sel_o = CnstyDigest; Tests: T1 T2 T3  208 1/1 scrmbl_mode_o = StandardMode; Tests: T1 T2 T3  209 1/1 scrmbl_valid_o = 1'b0; Tests: T1 T2 T3  210 211 // Counter 212 1/1 cnt_en = 1'b0; Tests: T1 T2 T3  213 1/1 cnt_clr = 1'b0; Tests: T1 T2 T3  214 1/1 base_sel_d = base_sel_q; Tests: T1 T2 T3  215 216 // Temporary data register 217 1/1 data_en = 1'b0; Tests: T1 T2 T3  218 1/1 data_clr = 1'b0; Tests: T1 T2 T3  219 1/1 data_sel = OtpData; Tests: T1 T2 T3  220 221 // Error Register 222 1/1 error_d = error_q; Tests: T1 T2 T3  223 1/1 fsm_err_o = 1'b0; Tests: T1 T2 T3  224 225 1/1 unique case (state_q) Tests: T1 T2 T3  226 /////////////////////////////////////////////////////////////////// 227 // We get here after reset and wait until the power manager 228 // requests OTP initialization. If initialization is requested, 229 // an init command is written to the OTP macro, and we move on 230 // to the InitOtpSt waiting state. 231 ResetSt: begin 232 1/1 init_done_o = 1'b0; Tests: T1 T2 T3  233 1/1 dai_prog_idle_o = 1'b0; Tests: T1 T2 T3  234 1/1 data_clr = 1'b1; Tests: T1 T2 T3  235 1/1 if (init_req_i) begin Tests: T1 T2 T3  236 1/1 otp_req_o = 1'b1; Tests: T1 T2 T3  237 1/1 if (otp_gnt_i) begin Tests: T1 T2 T3  238 1/1 state_d = InitOtpSt; Tests: T1 T2 T3  239 end ==> MISSING_ELSE 240 end MISSING_ELSE 241 end 242 /////////////////////////////////////////////////////////////////// 243 // We wait here unitl the OTP macro has initialized without 244 // error. If an error occurred during this stage, we latch that 245 // error and move into a terminal error state. 246 InitOtpSt: begin 247 1/1 init_done_o = 1'b0; Tests: T1 T2 T3  248 1/1 dai_prog_idle_o = 1'b0; Tests: T1 T2 T3  249 1/1 if (otp_rvalid_i) begin Tests: T1 T2 T3  250 1/1 if ((!(otp_err inside {NoError, MacroEccCorrError}))) begin Tests: T1 T2 T3  251 excluded state_d = ErrorSt; Exclude Annotation: VC_COV_UNR 252 excluded error_d = otp_err; Exclude Annotation: VC_COV_UNR 253 end else begin 254 1/1 state_d = InitPartSt; Tests: T1 T2 T3  255 end 256 end MISSING_ELSE 257 end 258 /////////////////////////////////////////////////////////////////// 259 // Since the OTP macro is now functional, we can send out an 260 // initialization request to all partitions and wait until they 261 // all have initialized. 262 InitPartSt: begin 263 1/1 init_done_o = 1'b0; Tests: T1 T2 T3  264 1/1 dai_prog_idle_o = 1'b0; Tests: T1 T2 T3  265 1/1 part_init_req_o = 1'b1; Tests: T1 T2 T3  266 1/1 if (part_init_done_i == {NumPart{1'b1}}) begin Tests: T1 T2 T3  267 1/1 state_d = IdleSt; Tests: T1 T2 T3  268 end MISSING_ELSE 269 end 270 /////////////////////////////////////////////////////////////////// 271 // Idle state where we wait for incoming commands. 272 // Invalid commands trigger a CmdInvErr, which is recoverable. 273 IdleSt: begin 274 1/1 dai_idle_o = 1'b1; Tests: T1 T2 T3  275 1/1 if (dai_req_i) begin Tests: T1 T2 T3  276 // This clears previous (recoverable) and reset the counter. 277 1/1 error_d = NoError; Tests: T1 T2 T3  278 1/1 cnt_clr = 1'b1; Tests: T1 T2 T3  279 1/1 unique case (dai_cmd_i) Tests: T1 T2 T3  280 DaiRead: begin 281 1/1 state_d = ReadSt; Tests: T1 T2 T3  282 // Clear the temporary data register. 283 1/1 data_clr = 1'b1; Tests: T1 T2 T3  284 1/1 base_sel_d = DaiOffset; Tests: T1 T2 T3  285 end 286 DaiWrite: begin 287 1/1 data_sel = DaiData; Tests: T1 T2 T3  288 // Fetch data block. 289 1/1 data_en = 1'b1; Tests: T1 T2 T3  290 1/1 base_sel_d = DaiOffset; Tests: T1 T2 T3  291 // If this partition is scrambled, directly go to write scrambling first. 292 1/1 if (PartInfo[part_idx].secret) begin Tests: T1 T2 T3  293 1/1 state_d = ScrSt; Tests: T2 T3 T4  294 end else begin 295 1/1 state_d = WriteSt; Tests: T1 T2 T3  296 end 297 end 298 DaiDigest: begin 299 1/1 state_d = DigClrSt; Tests: T1 T3 T5  300 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T3 T5  301 1/1 base_sel_d = PartOffset; Tests: T1 T3 T5  302 end 303 default: ; // Ignore invalid commands 304 endcase // dai_cmd_i 305 end // dai_req_i MISSING_ELSE 306 end 307 /////////////////////////////////////////////////////////////////// 308 // Each time we request a block of data from OTP, we re-check 309 // whether read access has been locked for this partition. If 310 // that is the case, we immediately bail out. Otherwise, we 311 // request a block of data from OTP. 312 ReadSt: begin 313 1/1 if (part_sel_valid && (mubi8_test_false_strict(part_access_i[part_idx].read_lock) || Tests: T1 T2 T3  314 // HW digests always remain readable. 315 PartInfo[part_idx].hw_digest && otp_addr_o == 316 digest_addr_lut[part_idx])) begin 317 1/1 otp_req_o = 1'b1; Tests: T1 T2 T3  318 // Depending on the partition configuration, 319 // the wrapper is instructed to ignore integrity errors. 320 1/1 if (PartInfo[part_idx].integrity) begin Tests: T1 T2 T3  321 1/1 otp_cmd_o = prim_otp_pkg::Read; Tests: T1 T2 T3  322 end else begin 323 1/1 otp_cmd_o = prim_otp_pkg::ReadRaw; Tests: T2 T3 T4  324 end 325 1/1 if (otp_gnt_i) begin Tests: T1 T2 T3  326 1/1 state_d = ReadWaitSt; Tests: T1 T2 T3  327 end MISSING_ELSE 328 end else begin 329 1/1 state_d = IdleSt; Tests: T6 T12 T36  330 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T6 T12 T36  331 1/1 dai_cmd_done_o = 1'b1; Tests: T6 T12 T36  332 end 333 end 334 /////////////////////////////////////////////////////////////////// 335 // Wait for OTP response and write to readout register. Check 336 // whether descrambling is required or not. In case an OTP 337 // transaction fails, latch the OTP error code, and jump to 338 // terminal error state. 339 ReadWaitSt: begin 340 // Continuously check read access and bail out if this is not consistent. 341 1/1 if (part_sel_valid && (mubi8_test_false_strict(part_access_i[part_idx].read_lock) || Tests: T1 T2 T3  342 // HW digests always remain readable. 343 PartInfo[part_idx].hw_digest && otp_addr_o == 344 digest_addr_lut[part_idx])) begin 345 1/1 if (otp_rvalid_i) begin Tests: T1 T2 T3  346 // Check OTP return code. 347 1/1 if (otp_err inside {NoError, MacroEccCorrError}) begin Tests: T1 T2 T3  348 1/1 data_en = 1'b1; Tests: T1 T2 T3  349 // We do not need to descramble the digest values. 350 1/1 if (PartInfo[part_idx].secret && otp_addr_o != digest_addr_lut[part_idx]) begin Tests: T1 T2 T3  351 1/1 state_d = DescrSt; Tests: T2 T4 T5  352 end else begin 353 1/1 state_d = IdleSt; Tests: T1 T2 T3  354 1/1 dai_cmd_done_o = 1'b1; Tests: T1 T2 T3  355 end 356 // At this point the only error that we could have gotten are correctable ECC errors. 357 1/1 if (otp_err != NoError) begin Tests: T1 T2 T3  358 1/1 error_d = MacroEccCorrError; Tests: T126 T93 T100  359 end MISSING_ELSE 360 end else begin 361 1/1 state_d = ErrorSt; Tests: T12 T126 T7  362 1/1 error_d = otp_err; Tests: T12 T126 T7  363 end 364 end MISSING_ELSE 365 // At this point, this check MUST succeed - otherwise this means that 366 // there was a tampering attempt. Hence we go into a terminal error state 367 // when this check fails. 368 end else begin 369 0/1 ==> state_d = ErrorSt; 370 0/1 ==> error_d = FsmStateError; 371 end 372 end 373 /////////////////////////////////////////////////////////////////// 374 // Descrambling state. This first acquires the scrambling 375 // datapath mutex. Note that once the mutex is acquired, we have 376 // exclusive access to the scrambling datapath until we release 377 // the mutex by deasserting scrmbl_mtx_req_o. 378 // SEC_CM: SECRET.MEM.SCRAMBLE 379 DescrSt: begin 380 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T2 T4 T5  381 1/1 scrmbl_valid_o = 1'b1; Tests: T2 T4 T5  382 1/1 scrmbl_cmd_o = Decrypt; Tests: T2 T4 T5  383 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T4 T5  384 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin Tests: T2 T4 T5  385 1/1 state_d = DescrWaitSt; Tests: T2 T4 T5  386 end MISSING_ELSE 387 end 388 /////////////////////////////////////////////////////////////////// 389 // Wait for the descrambled data to return. Note that we release 390 // the mutex lock upon leaving this state. 391 // SEC_CM: SECRET.MEM.SCRAMBLE 392 DescrWaitSt: begin 393 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T2 T4 T5  394 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T4 T5  395 1/1 data_sel = ScrmblData; Tests: T2 T4 T5  396 1/1 if (scrmbl_valid_i) begin Tests: T2 T4 T5  397 1/1 state_d = IdleSt; Tests: T2 T4 T5  398 1/1 data_en = 1'b1; Tests: T2 T4 T5  399 1/1 dai_cmd_done_o = 1'b1; Tests: T2 T4 T5  400 end MISSING_ELSE 401 end 402 /////////////////////////////////////////////////////////////////// 403 // First, check whether write accesses are allowed to this 404 // partition, and error out otherwise. Note that for buffered 405 // partitions, we do not allow DAI writes to the digest offset. 406 // Unbuffered partitions have SW managed digests, hence that 407 // check is not needed in that case. The LC partition is 408 // permanently write locked and can hence not be written via the DAI. 409 WriteSt: begin 410 1/1 dai_prog_idle_o = 1'b0; Tests: T1 T2 T3  411 1/1 if (part_sel_valid && mubi8_test_false_strict(part_access_i[part_idx].write_lock) && Tests: T1 T2 T3  412 // If this is a HW digest write to a buffered partition. 413 ((PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].hw_digest && 414 base_sel_q == PartOffset && otp_addr_o == digest_addr_lut[part_idx]) || 415 // If this is a non HW digest write to a buffered partition. 416 (PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].hw_digest && 417 base_sel_q == DaiOffset && otp_addr_o < digest_addr_lut[part_idx]) || 418 // If this is a write to an unbuffered partition 419 (PartInfo[part_idx].variant != Buffered && base_sel_q == DaiOffset))) begin 420 1/1 otp_req_o = 1'b1; Tests: T1 T2 T3  421 // Depending on the partition configuration, 422 // the wrapper is instructed to ignore integrity errors. 423 1/1 if (PartInfo[part_idx].integrity) begin Tests: T1 T2 T3  424 1/1 otp_cmd_o = prim_otp_pkg::Write; Tests: T1 T2 T3  425 end else begin 426 1/1 otp_cmd_o = prim_otp_pkg::WriteRaw; Tests: T2 T3 T5  427 end 428 1/1 if (otp_gnt_i) begin Tests: T1 T2 T3  429 1/1 state_d = WriteWaitSt; Tests: T1 T2 T3  430 end MISSING_ELSE 431 end else begin 432 // Clear working register state. 433 1/1 data_clr = 1'b1; Tests: T1 T36 T94  434 1/1 state_d = IdleSt; Tests: T1 T36 T94  435 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T1 T36 T94  436 1/1 dai_cmd_done_o = 1'b1; Tests: T1 T36 T94  437 end 438 end 439 /////////////////////////////////////////////////////////////////// 440 // Wait for OTP response, and then go back to idle. In case an 441 // OTP transaction fails, latch the OTP error code, and jump to 442 // terminal error state. 443 WriteWaitSt: begin 444 1/1 dai_prog_idle_o = 1'b0; Tests: T1 T2 T3  445 // Continuously check write access and bail out if this is not consistent. 446 1/1 if (part_sel_valid && mubi8_test_false_strict(part_access_i[part_idx].write_lock) && Tests: T1 T2 T3  447 // If this is a HW digest write to a buffered partition. 448 ((PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].hw_digest && 449 base_sel_q == PartOffset && otp_addr_o == digest_addr_lut[part_idx]) || 450 // If this is a non HW digest write to a buffered partition. 451 (PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].hw_digest && 452 base_sel_q == DaiOffset && otp_addr_o < digest_addr_lut[part_idx]) || 453 // If this is a write to an unbuffered partition 454 (PartInfo[part_idx].variant != Buffered && base_sel_q == DaiOffset))) begin 455 456 1/1 if (otp_rvalid_i) begin Tests: T1 T2 T3  457 // Check OTP return code. Note that non-blank errors are recoverable. 458 1/1 if ((!(otp_err inside {NoError, MacroWriteBlankError}))) begin Tests: T1 T2 T3  459 excluded state_d = ErrorSt; Exclude Annotation: VC_COV_UNR 460 excluded error_d = otp_err; Exclude Annotation: VC_COV_UNR 461 end else begin 462 // Clear working register state. 463 1/1 data_clr = 1'b1; Tests: T1 T2 T3  464 1/1 state_d = IdleSt; Tests: T1 T2 T3  465 1/1 dai_cmd_done_o = 1'b1; Tests: T1 T2 T3  466 // Signal non-blank state, but do not go to terminal error state. 467 1/1 if (otp_err == MacroWriteBlankError) begin Tests: T1 T2 T3  468 1/1 error_d = otp_err; Tests: T12 T7 T8  469 end MISSING_ELSE 470 end 471 end MISSING_ELSE 472 // At this point, this check MUST succeed - otherwise this means that 473 // there was a tampering attempt. Hence we go into a terminal error state 474 // when this check fails. 475 end else begin 476 0/1 ==> state_d = ErrorSt; 477 0/1 ==> error_d = FsmStateError; 478 end 479 end 480 /////////////////////////////////////////////////////////////////// 481 // Scrambling state. This first acquires the scrambling 482 // datapath mutex. Note that once the mutex is acquired, we have 483 // exclusive access to the scrambling datapath until we release 484 // the mutex by deasserting scrmbl_mtx_req_o. 485 // SEC_CM: SECRET.MEM.SCRAMBLE 486 ScrSt: begin 487 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T2 T3 T4  488 // Check write access and bail out if this is not consistent. 489 1/1 if (part_sel_valid && mubi8_test_false_strict(part_access_i[part_idx].write_lock) && Tests: T2 T3 T4  490 // If this is a non HW digest write to a buffered partition. 491 (PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].secret && 492 PartInfo[part_idx].hw_digest && base_sel_q == DaiOffset && 493 otp_addr_o < digest_addr_lut[part_idx])) begin 494 495 1/1 scrmbl_valid_o = 1'b1; Tests: T2 T3 T4  496 1/1 scrmbl_cmd_o = Encrypt; Tests: T2 T3 T4  497 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T3 T4  498 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin Tests: T2 T3 T4  499 1/1 state_d = ScrWaitSt; Tests: T2 T3 T4  500 end MISSING_ELSE 501 end else begin 502 1/1 state_d = IdleSt; Tests: T6 T12 T36  503 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T6 T12 T36  504 1/1 dai_cmd_done_o = 1'b1; Tests: T6 T12 T36  505 end 506 end 507 /////////////////////////////////////////////////////////////////// 508 // Wait for the scrambled data to return. Note that we release 509 // the mutex lock upon leaving this state. 510 // SEC_CM: SECRET.MEM.SCRAMBLE 511 ScrWaitSt: begin 512 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T2 T3 T4  513 // Continously check write access and bail out if this is not consistent. 514 1/1 if (part_sel_valid && mubi8_test_false_strict(part_access_i[part_idx].write_lock) && Tests: T2 T3 T4  515 // If this is a non HW digest write to a buffered partition. 516 (PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].secret && 517 PartInfo[part_idx].hw_digest && base_sel_q == DaiOffset && 518 otp_addr_o < digest_addr_lut[part_idx])) begin 519 1/1 data_sel = ScrmblData; Tests: T2 T3 T4  520 1/1 if (scrmbl_valid_i) begin Tests: T2 T3 T4  521 1/1 state_d = WriteSt; Tests: T2 T3 T4  522 1/1 data_en = 1'b1; Tests: T2 T3 T4  523 end MISSING_ELSE 524 // At this point, this check MUST succeed - otherwise this means that 525 // there was a tampering attempt. Hence we go into a terminal error state 526 // when this check fails. 527 end else begin 528 0/1 ==> state_d = ErrorSt; 529 0/1 ==> error_d = FsmStateError; 530 end 531 end 532 /////////////////////////////////////////////////////////////////// 533 // First, acquire the mutex for the digest and clear the digest state. 534 // SEC_CM: PART.MEM.DIGEST 535 DigClrSt: begin 536 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T3 T5  537 1/1 scrmbl_valid_o = 1'b1; Tests: T1 T3 T5  538 // Need to reset the digest state and set digest mode to "standard". 539 1/1 scrmbl_cmd_o = DigestInit; Tests: T1 T3 T5  540 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin Tests: T1 T3 T5  541 1/1 state_d = DigReadSt; Tests: T1 T3 T5  542 end MISSING_ELSE 543 end 544 /////////////////////////////////////////////////////////////////// 545 // This requests a 64bit block to be pushed into the digest datapath. 546 // We also check here whether the partition has been write locked. 547 // SEC_CM: PART.MEM.DIGEST 548 DigReadSt: begin 549 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T3 T5  550 1/1 if (part_sel_valid && Tests: T1 T3 T5  551 mubi8_test_false_strict(part_access_i[part_idx].read_lock) && 552 mubi8_test_false_strict(part_access_i[part_idx].write_lock)) begin 553 1/1 otp_req_o = 1'b1; Tests: T1 T3 T5  554 // Depending on the partition configuration, 555 // the wrapper is instructed to ignore integrity errors. 556 1/1 if (PartInfo[part_idx].integrity) begin Tests: T1 T3 T5  557 1/1 otp_cmd_o = prim_otp_pkg::Read; Tests: T1 T3 T5  558 end else begin 559 0/1 ==> otp_cmd_o = prim_otp_pkg::ReadRaw; 560 end 561 1/1 if (otp_gnt_i) begin Tests: T1 T3 T5  562 1/1 state_d = DigReadWaitSt; Tests: T1 T3 T5  563 end MISSING_ELSE 564 end else begin 565 1/1 state_d = IdleSt; Tests: T6 T36 T94  566 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T6 T36 T94  567 1/1 dai_cmd_done_o = 1'b1; Tests: T6 T36 T94  568 end 569 end 570 /////////////////////////////////////////////////////////////////// 571 // Wait for OTP response and write to readout register. Check 572 // whether descrambling is required or not. In case an OTP 573 // transaction fails, latch the OTP error code, and jump to 574 // terminal error state. 575 // SEC_CM: PART.MEM.DIGEST 576 DigReadWaitSt: begin 577 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T3 T5  578 1/1 if (otp_rvalid_i) begin Tests: T1 T3 T5  579 1/1 cnt_en = 1'b1; Tests: T1 T3 T5  580 // Check OTP return code. 581 1/1 if ((!(otp_err inside {NoError, MacroEccCorrError}))) begin Tests: T1 T3 T5  582 0/1 ==> state_d = ErrorSt; 583 0/1 ==> error_d = otp_err; 584 end else begin 585 1/1 data_en = 1'b1; Tests: T1 T3 T5  586 1/1 state_d = DigSt; Tests: T1 T3 T5  587 // Signal soft ECC errors, but do not go into terminal error state. 588 1/1 if (otp_err == MacroEccCorrError) begin Tests: T1 T3 T5  589 0/1 ==> error_d = otp_err; 590 end MISSING_ELSE 591 end 592 end MISSING_ELSE 593 end 594 /////////////////////////////////////////////////////////////////// 595 // Push the word read into the scrambling datapath. The last 596 // block is repeated in case the number blocks in this partition 597 // is odd. 598 // SEC_CM: PART.MEM.DIGEST 599 DigSt: begin 600 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T3 T5  601 1/1 scrmbl_valid_o = 1'b1; Tests: T1 T3 T5  602 // No need to digest the digest value itself 603 1/1 if (otp_addr_o == digest_addr_lut[part_idx]) begin Tests: T1 T3 T5  604 // Trigger digest round in case this is the second block in a row. 605 1/1 if (!cnt[0]) begin Tests: T1 T3 T5  606 1/1 scrmbl_cmd_o = Digest; Tests: T1 T3 T5  607 1/1 if (scrmbl_ready_i) begin Tests: T1 T3 T5  608 1/1 state_d = DigFinSt; Tests: T1 T3 T5  609 end ==> MISSING_ELSE 610 // Otherwise, just load low word and go to padding state. 611 1/1 end else if (scrmbl_ready_i) begin Tests: T1 T5 T11  612 1/1 state_d = DigPadSt; Tests: T1 T5 T11  613 end MISSING_ELSE 614 end else begin 615 // Trigger digest round in case this is the second block in a row. 616 1/1 if (!cnt[0]) begin Tests: T1 T3 T5  617 1/1 scrmbl_cmd_o = Digest; Tests: T1 T3 T5  618 end MISSING_ELSE 619 // Go back and fetch more data blocks. 620 1/1 if (scrmbl_ready_i) begin Tests: T1 T3 T5  621 1/1 state_d = DigReadSt; Tests: T1 T3 T5  622 end MISSING_ELSE 623 end 624 end 625 /////////////////////////////////////////////////////////////////// 626 // Padding state, just repeat the last block and go to digest 627 // finalization. 628 // SEC_CM: PART.MEM.DIGEST 629 DigPadSt: begin 630 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T5 T11  631 1/1 scrmbl_valid_o = 1'b1; Tests: T1 T5 T11  632 1/1 scrmbl_cmd_o = Digest; Tests: T1 T5 T11  633 1/1 if (scrmbl_ready_i) begin Tests: T1 T5 T11  634 1/1 state_d = DigFinSt; Tests: T1 T5 T11  635 end ==> MISSING_ELSE 636 end 637 /////////////////////////////////////////////////////////////////// 638 // Trigger digest finalization and go wait for the result. 639 // SEC_CM: PART.MEM.DIGEST 640 DigFinSt: begin 641 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T3 T5  642 1/1 scrmbl_valid_o = 1'b1; Tests: T1 T3 T5  643 1/1 scrmbl_cmd_o = DigestFinalize; Tests: T1 T3 T5  644 1/1 if (scrmbl_ready_i) begin Tests: T1 T3 T5  645 1/1 state_d = DigWaitSt; Tests: T1 T3 T5  646 end MISSING_ELSE 647 end 648 /////////////////////////////////////////////////////////////////// 649 // Wait for the digest to return, and write the result to OTP. 650 // Note that the write address will be correct in this state, 651 // since the counter has been stepped to the correct address as 652 // part of the readout sequence, and the correct size for this 653 // access has been loaded before. 654 // SEC_CM: PART.MEM.DIGEST 655 DigWaitSt: begin 656 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T3 T5  657 1/1 data_sel = ScrmblData; Tests: T1 T3 T5  658 1/1 if (scrmbl_valid_i) begin Tests: T1 T3 T5  659 1/1 state_d = WriteSt; Tests: T1 T3 T5  660 1/1 data_en = 1'b1; Tests: T1 T3 T5  661 end MISSING_ELSE 662 end 663 /////////////////////////////////////////////////////////////////// 664 // Terminal Error State. This locks access to the DAI. Make sure 665 // an FsmStateError error code is assigned here, in case no error code has 666 // been assigned yet. 667 ErrorSt: begin 668 1/1 if (error_q == NoError) begin Tests: T2 T4 T11  669 1/1 error_d = FsmStateError; Tests: T27 T28 T29  670 end MISSING_ELSE 671 end 672 /////////////////////////////////////////////////////////////////// 673 // We should never get here. If we do (e.g. via a malicious 674 // glitch), error out immediately. 675 default: begin 676 state_d = ErrorSt; 677 fsm_err_o = 1'b1; 678 end 679 /////////////////////////////////////////////////////////////////// 680 endcase // state_q 681 682 // Unconditionally jump into the terminal error state in case of escalation. 683 // SEC_CM: DAI.FSM.LOCAL_ESC, DAI.FSM.GLOBAL_ESC 684 1/1 if (lc_ctrl_pkg::lc_tx_test_true_loose(escalate_en_i) || cnt_err) begin Tests: T1 T2 T3  685 1/1 state_d = ErrorSt; Tests: T2 T4 T11  686 1/1 fsm_err_o = 1'b1; Tests: T2 T4 T11  687 1/1 if (state_q != ErrorSt) begin Tests: T2 T4 T11  688 1/1 error_d = FsmStateError; Tests: T2 T4 T11  689 end MISSING_ELSE 690 end MISSING_ELSE 691 end 692 693 //////////////////////////// 694 // Partition Select Logic // 695 //////////////////////////// 696 697 // This checks which partition the address belongs to by comparing 698 // the incoming address to the partition address ranges. The onehot 699 // bitvector generated by the parallel comparisons is fed into a 700 // binary tree that determines the partition index with O(log(N)) delay. 701 702 logic [NumPart-1:0] part_sel_oh; 703 for (genvar k = 0; k < NumPart; k++) begin : gen_part_sel 704 localparam int unsigned PartEndInt = 32'(PartInfo[k].offset) + 32'(PartInfo[k].size); 705 localparam int unsigned DigestOffsetInt = PartEndInt - ScrmblBlockWidth / 8; 706 localparam int unsigned DigestAddrLutInt = DigestOffsetInt >> OtpAddrShift; 707 708 // PartEnd has an extra bit to cope with the case where offset + size overflows. However, we 709 // arrange the address map to make sure that PartEndInt is at most 1 << OtpByteAddrWidth. Check 710 // that here. 711 `ASSERT_INIT(PartEndMax_A, PartEndInt <= (1 << OtpByteAddrWidth)) 712 713 // The shift right by OtpAddrShift drops exactly the bottom bits that are needed to convert 714 // between OtpAddrWidth and OtpByteAddrWidth, so we know that we can slice safely here. 715 localparam bit [OtpAddrWidth-1:0] DigestAddrLut = DigestAddrLutInt[OtpAddrWidth-1:0]; 716 717 if (PartInfo[k].offset == 0) begin : gen_zero_offset 718 1/1 assign part_sel_oh[k] = ({1'b0, dai_addr_i} < PartEndInt[OtpByteAddrWidth:0]); Tests: T1 T2 T3  719 720 end else begin : gen_nonzero_offset 721 10/10 assign part_sel_oh[k] = (dai_addr_i >= PartInfo[k].offset) & Tests: T1 T2 T3  | T1 T2 T3  | T1 T2 T3  | T1 T2 T3  | T1 T2 T3  | T1 T2 T3  | T1 T2 T3  | T1 T2 T3  | T1 T2 T3  | T1 T2 T3  722 ({1'b0, dai_addr_i} < PartEndInt[OtpByteAddrWidth:0]); 723 end 724 assign digest_addr_lut[k] = DigestAddrLut; 725 end 726 727 `ASSERT(ScrmblBlockWidthGe8_A, ScrmblBlockWidth >= 8) 728 `ASSERT(PartSelMustBeOnehot_A, $onehot0(part_sel_oh)) 729 730 prim_arbiter_fixed #( 731 .N(NumPart), 732 .EnDataPort(0) 733 ) u_part_sel_idx ( 734 .clk_i, 735 .rst_ni, 736 .req_i ( part_sel_oh ), 737 .data_i ( '{default: '0} ), 738 .gnt_o ( ), // unused 739 .idx_o ( part_idx ), 740 .valid_o ( part_sel_valid ), // used for detecting OOB addresses 741 .data_o ( ), // unused 742 .ready_i ( 1'b0 ) 743 ); 744 745 ///////////////////////////////////// 746 // Address Calculations for Digest // 747 ///////////////////////////////////// 748 749 // Depending on whether this is a 32bit or 64bit partition, we cut off the lower address bits. 750 // Access sizes are either 64bit or 32bit, depending on what region the access goes to. 751 logic [OtpByteAddrWidth-1:0] addr_base; 752 always_comb begin : p_size_sel 753 1/1 otp_size_o = OtpSizeWidth'(unsigned'(32 / OtpWidth - 1)); Tests: T1 T2 T3  754 1/1 addr_base = {dai_addr_i[OtpByteAddrWidth-1:2], 2'h0}; Tests: T1 T2 T3  755 756 // 64bit transaction for scrambled partitions. 757 1/1 if (PartInfo[part_idx].secret) begin Tests: T1 T2 T3  758 1/1 otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth - 1)); Tests: T2 T3 T4  759 1/1 addr_base = {dai_addr_i[OtpByteAddrWidth-1:3], 3'h0}; Tests: T2 T3 T4  760 // 64bit transaction if computing a digest. 761 1/1 end else if (PartInfo[part_idx].hw_digest && (base_sel_q == PartOffset)) begin Tests: T1 T2 T3  762 1/1 otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth - 1)); Tests: T1 T3 T5  763 1/1 addr_base = PartInfo[part_idx].offset; Tests: T1 T3 T5  764 // 64bit transaction if the DAI address points to the partition's digest offset. 765 1/1 end else if ((PartInfo[part_idx].hw_digest || PartInfo[part_idx].sw_digest) && Tests: T1 T2 T3  766 (base_sel_q == DaiOffset) && 767 ({dai_addr_i[OtpByteAddrWidth-1:3], 2'b0} == digest_addr_lut[part_idx])) begin 768 1/1 otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth - 1)); Tests: T6 T129 T36  769 1/1 addr_base = {dai_addr_i[OtpByteAddrWidth-1:3], 3'h0}; Tests: T6 T129 T36  770 end MISSING_ELSE 771 end 772 773 // Address counter - this is only used for computing a digest, hence the increment is 774 // fixed to 8 byte. 775 // SEC_CM: DAI.CTR.REDUN 776 prim_count #( 777 .Width(CntWidth) 778 ) u_prim_count ( 779 .clk_i, 780 .rst_ni, 781 .clr_i(cnt_clr), 782 .set_i(1'b0), 783 .set_cnt_i('0), 784 .incr_en_i(cnt_en), 785 .decr_en_i(1'b0), 786 .step_i(CntWidth'(1)), 787 .commit_i(1'b1), 788 .cnt_o(cnt), 789 .cnt_after_commit_o(), 790 .err_o(cnt_err) 791 ); 792 793 // Note that OTP works on halfword (16bit) addresses, hence need to 794 // shift the addresses appropriately. 795 logic [OtpByteAddrWidth-1:0] addr_calc; 796 1/1 assign addr_calc = {cnt, {$clog2(ScrmblBlockWidth/8){1'b0}}} + addr_base; Tests: T1 T2 T3  797 1/1 assign otp_addr_o = OtpAddrWidth'(addr_calc >> OtpAddrShift); Tests: T1 T2 T3  798 799 /////////////// 800 // Registers // 801 /////////////// 802 803 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): 803.1 `ifdef SIMULATION 803.2 prim_sparse_fsm_flop #( 803.3 .StateEnumT(state_e), 803.4 .Width($bits(state_e)), 803.5 .ResetValue($bits(state_e)'(ResetSt)), 803.6 .EnableAlertTriggerSVA(1), 803.7 .CustomForceName("state_q") 803.8 ) u_state_regs ( 803.9 .clk_i ( clk_i ), 803.10 .rst_ni ( rst_ni ), 803.11 .state_i ( state_d ), 803.12 .state_o ( ) 803.13 ); 803.14 always_ff @(posedge clk_i or negedge rst_ni) begin 803.15 1/1 if (!rst_ni) begin Tests: T1 T2 T3  803.16 1/1 state_q <= ResetSt; Tests: T1 T2 T3  803.17 end else begin 803.18 1/1 state_q <= state_d; Tests: T1 T2 T3  803.19 end 803.20 end 803.21 u_state_regs_A: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (state_q === u_state_regs.state_o)) 803.22 else begin 803.23 `ifdef UVM 803.24 uvm_pkg::uvm_report_error("ASSERT FAILED", "u_state_regs_A", uvm_pkg::UVM_NONE, 803.25 "../src/lowrisc_ip_otp_ctrl_1.0/rtl/otp_ctrl_dai.sv", 803, "", 1); 803.26 `else 803.27 $error("%0t: (%0s:%0d) [%m] [ASSERT FAILED] %0s", $time, `__FILE__, `__LINE__, 803.28 `PRIM_STRINGIFY(u_state_regs_A)); 803.29 `endif 803.30 end 803.31 `else 803.32 prim_sparse_fsm_flop #( 803.33 .StateEnumT(state_e), 803.34 .Width($bits(state_e)), 803.35 .ResetValue($bits(state_e)'(ResetSt)), 803.36 .EnableAlertTriggerSVA(1) 803.37 ) u_state_regs ( 803.38 .clk_i ( `PRIM_FLOP_CLK ), 803.39 .rst_ni ( `PRIM_FLOP_RST ), 803.40 .state_i ( state_d ), 803.41 .state_o ( state_q ) 803.42 ); 803.43 `endif804 805 always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs 806 1/1 if (!rst_ni) begin Tests: T1 T2 T3  807 1/1 error_q <= NoError; Tests: T1 T2 T3  808 1/1 data_q <= '0; Tests: T1 T2 T3  809 1/1 base_sel_q <= DaiOffset; Tests: T1 T2 T3  810 end else begin 811 1/1 error_q <= error_d; Tests: T1 T2 T3  812 1/1 base_sel_q <= base_sel_d; Tests: T1 T2 T3  813 814 // Working register 815 1/1 if (data_clr) begin Tests: T1 T2 T3  816 1/1 data_q <= '0; Tests: T1 T2 T3  817 1/1 end else if (data_en) begin Tests: T1 T2 T3  818 1/1 if (data_sel == ScrmblData) begin Tests: T1 T2 T3  819 1/1 data_q <= scrmbl_data_i; Tests: T1 T2 T3  820 1/1 end else if (data_sel == DaiData) begin Tests: T1 T2 T3  821 1/1 data_q <= dai_wdata_i; Tests: T1 T2 T3  822 end else begin 823 1/1 data_q <= otp_rdata_i; Tests: T1 T2 T3  824 end 825 end MISSING_ELSE

Cond Coverage for Instance : tb.dut.u_otp_ctrl_dai
TotalCoveredPercent
Conditions817795.06
Logical817795.06
Non-Logical00
Event00

 LINE       170
 EXPRESSION (((!otp_ctrl_part_pkg::PartInfo[part_idx].integrity)) && (otp_err_e'(otp_err_i) inside {MacroEccCorrError, MacroEccUncorrError}))
             --------------------------1-------------------------    -----------------------------------2-----------------------------------
-1--2-StatusTests
01CoveredT12,T126,T93
10CoveredT1,T2,T3
11CoveredT2,T85,T147

 LINE       184
 EXPRESSION ((state_q == IdleSt) ? data_q : '0)
             ---------1---------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       184
 SUB-EXPRESSION (state_q == IdleSt)
                ---------1---------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       266
 EXPRESSION (part_init_done_i == {otp_ctrl_reg_pkg::NumPart {1'b1}})
            ----------------------------1---------------------------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

 LINE       350
 EXPRESSION (otp_ctrl_part_pkg::PartInfo[part_idx].secret && (otp_addr_o != digest_addr_lut[part_idx]))
             ----------------------1---------------------    --------------------2--------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT6,T129,T36
11CoveredT2,T4,T5

 LINE       350
 SUB-EXPRESSION (otp_addr_o != digest_addr_lut[part_idx])
                --------------------1--------------------
-1-StatusTests
0CoveredT6,T129,T36
1CoveredT1,T2,T3

 LINE       357
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT126,T93,T100

 LINE       384
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTestsExclude Annotation
01Excluded VC_COV_UNR
10Not Covered
11CoveredT2,T4,T5

 LINE       467
 EXPRESSION (otp_err == MacroWriteBlankError)
            ----------------1----------------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT12,T7,T8

 LINE       498
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTestsExclude Annotation
01Excluded VC_COV_UNR
10Not Covered
11CoveredT2,T3,T4

 LINE       540
 EXPRESSION (scrmbl_mtx_gnt_i && scrmbl_ready_i)
             --------1-------    -------2------
-1--2-StatusTestsExclude Annotation
01Excluded VC_COV_UNR
10Not Covered
11CoveredT1,T3,T5

 LINE       588
 EXPRESSION (otp_err == MacroEccCorrError)
            ---------------1--------------
-1-StatusTests
0CoveredT1,T3,T5
1Not Covered

 LINE       603
 EXPRESSION (otp_addr_o == digest_addr_lut[part_idx])
            --------------------1--------------------
-1-StatusTests
0CoveredT1,T3,T5
1CoveredT1,T3,T5

 LINE       668
 EXPRESSION (error_q == NoError)
            ----------1---------
-1-StatusTests
0CoveredT2,T4,T11
1CoveredT27,T28,T29

 LINE       687
 EXPRESSION (state_q != ErrorSt)
            ----------1---------
-1-StatusTests
0CoveredT2,T4,T11
1CoveredT2,T4,T11

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b00001000000) & ({1'b0, dai_addr_i} < gen_part_sel[1].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT1,T2,T3
11CoveredT1,T2,T3

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b00110110000) & ({1'b0, dai_addr_i} < gen_part_sel[2].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT1,T2,T3
11CoveredT2,T4,T5

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b10001111000) & ({1'b0, dai_addr_i} < gen_part_sel[3].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT1,T2,T3
11CoveredT2,T3,T4

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b11001010000) & ({1'b0, dai_addr_i} < gen_part_sel[4].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT1,T2,T3
11CoveredT2,T4,T5

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b11001111000) & ({1'b0, dai_addr_i} < gen_part_sel[5].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT2,T3,T4
11CoveredT1,T2,T3

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b11011000000) & ({1'b0, dai_addr_i} < gen_part_sel[6].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT2,T3,T4
11CoveredT2,T3,T4

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b11011010000) & ({1'b0, dai_addr_i} < gen_part_sel[7].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT2,T3,T4
11CoveredT2,T5,T6

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b11011111000) & ({1'b0, dai_addr_i} < gen_part_sel[8].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT2,T4,T5
11CoveredT2,T3,T5

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b11101010000) & ({1'b0, dai_addr_i} < gen_part_sel[9].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   -------------------------------------------2-------------------------------------------
-1--2-StatusTests
01CoveredT1,T2,T3
10CoveredT7,T8,T9
11CoveredT2,T4,T5

 LINE       721
 EXPRESSION ((dai_addr_i >= 11'b11110101000) & ({1'b0, dai_addr_i} < gen_part_sel[10].PartEndInt[otp_ctrl_reg_pkg::OtpByteAddrWidth:0]))
             ---------------1---------------   --------------------------------------------2-------------------------------------------
-1--2-StatusTestsExclude Annotation
01CoveredT1,T2,T3
10Excluded vcs_gen_start:k=10:vcs_gen_end:VC_COV_UNR
11CoveredT7,T8,T9

 LINE       761
 EXPRESSION (otp_ctrl_part_pkg::PartInfo[part_idx].hw_digest && (base_sel_q == PartOffset))
             -----------------------1-----------------------    -------------2------------
-1--2-StatusTests
01CoveredT1,T41,T14
10CoveredT2,T3,T4
11CoveredT1,T3,T5

 LINE       761
 SUB-EXPRESSION (base_sel_q == PartOffset)
                -------------1------------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T3,T5

 LINE       765
 EXPRESSION 
 Number  Term
      1  (otp_ctrl_part_pkg::PartInfo[part_idx].hw_digest || otp_ctrl_part_pkg::PartInfo[part_idx].sw_digest) && 
      2  (base_sel_q == DaiOffset) && 
      3  ({dai_addr_i[(otp_ctrl_reg_pkg::OtpByteAddrWidth - 1):3], 2'b0} == digest_addr_lut[part_idx]))
-1--2--3-StatusTests
011CoveredT148,T149
101CoveredT90,T95,T21
110CoveredT1,T2,T3
111CoveredT6,T129,T36

 LINE       765
 SUB-EXPRESSION (otp_ctrl_part_pkg::PartInfo[part_idx].hw_digest || otp_ctrl_part_pkg::PartInfo[part_idx].sw_digest)
                 -----------------------1-----------------------    -----------------------2-----------------------
-1--2-StatusTests
00CoveredT7,T8,T9
01CoveredT1,T2,T3
10CoveredT2,T3,T4

 LINE       765
 SUB-EXPRESSION (base_sel_q == DaiOffset)
                ------------1------------
-1-StatusTests
0CoveredT1,T41,T14
1CoveredT1,T2,T3

 LINE       765
 SUB-EXPRESSION ({dai_addr_i[(otp_ctrl_reg_pkg::OtpByteAddrWidth - 1):3], 2'b0} == digest_addr_lut[part_idx])
                ----------------------------------------------1----------------------------------------------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT6,T129,T36

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

 LINE       820
 EXPRESSION (data_sel == DaiData)
            ----------1----------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT1,T2,T3

FSM Coverage for Instance : tb.dut.u_otp_ctrl_dai
Summary for FSM :: state_q
TotalCoveredPercent
States 20 20 100.00 (Not included in score)
Transitions 48 40 83.33
Sequences 0 0

State, Transition and Sequence Details for FSM :: state_q
statesLine No.CoveredTests
DescrSt 351 Covered T2,T4,T5
DescrWaitSt 385 Covered T2,T4,T5
DigClrSt 299 Covered T1,T3,T5
DigFinSt 608 Covered T1,T3,T5
DigPadSt 612 Covered T1,T5,T11
DigReadSt 541 Covered T1,T3,T5
DigReadWaitSt 562 Covered T1,T3,T5
DigSt 586 Covered T1,T3,T5
DigWaitSt 645 Covered T1,T3,T5
ErrorSt 251 Covered T2,T4,T11
IdleSt 267 Covered T1,T2,T3
InitOtpSt 238 Covered T1,T2,T3
InitPartSt 254 Covered T1,T2,T3
ReadSt 281 Covered T1,T2,T3
ReadWaitSt 326 Covered T1,T2,T3
ResetSt 231 Covered T1,T2,T3
ScrSt 293 Covered T2,T3,T4
ScrWaitSt 499 Covered T2,T3,T4
WriteSt 295 Covered T1,T2,T3
WriteWaitSt 429 Covered T1,T2,T3


transitionsLine No.CoveredTests
DescrSt->DescrWaitSt 385 Covered T2,T4,T5
DescrSt->ErrorSt 685 Not Covered
DescrWaitSt->ErrorSt 685 Covered T150
DescrWaitSt->IdleSt 397 Covered T2,T4,T5
DigClrSt->DigReadSt 541 Covered T1,T3,T5
DigClrSt->ErrorSt 685 Not Covered
DigFinSt->DigWaitSt 645 Covered T1,T3,T5
DigFinSt->ErrorSt 685 Covered T151,T152,T153
DigPadSt->DigFinSt 634 Covered T1,T5,T11
DigPadSt->ErrorSt 685 Not Covered
DigReadSt->DigReadWaitSt 562 Covered T1,T3,T5
DigReadSt->ErrorSt 685 Not Covered
DigReadSt->IdleSt 565 Covered T6,T36,T94
DigReadWaitSt->DigSt 586 Covered T1,T3,T5
DigReadWaitSt->ErrorSt 582 Covered T154,T155,T156
DigSt->DigFinSt 608 Covered T1,T3,T5
DigSt->DigPadSt 612 Covered T1,T5,T11
DigSt->DigReadSt 621 Covered T1,T3,T5
DigSt->ErrorSt 685 Covered T157,T158,T159
DigWaitSt->ErrorSt 685 Covered T160,T161
DigWaitSt->WriteSt 659 Covered T1,T3,T5
IdleSt->DigClrSt 299 Covered T1,T3,T5
IdleSt->ErrorSt 685 Covered T4,T102,T126
IdleSt->ReadSt 281 Covered T1,T2,T3
IdleSt->ScrSt 293 Covered T2,T3,T4
IdleSt->WriteSt 295 Covered T1,T2,T3
InitOtpSt->ErrorSt 251 Covered T108
InitOtpSt->InitPartSt 254 Covered T1,T2,T3
InitPartSt->ErrorSt 685 Covered T2,T11,T85
InitPartSt->IdleSt 267 Covered T1,T2,T3
ReadSt->ErrorSt 685 Not Covered
ReadSt->IdleSt 329 Covered T6,T12,T36
ReadSt->ReadWaitSt 326 Covered T1,T2,T3
ReadWaitSt->DescrSt 351 Covered T2,T4,T5
ReadWaitSt->ErrorSt 361 Covered T12,T126,T7
ReadWaitSt->IdleSt 353 Covered T1,T2,T3
ResetSt->ErrorSt 685 Covered T109,T110,T111
ResetSt->InitOtpSt 238 Covered T1,T2,T3
ScrSt->ErrorSt 685 Not Covered
ScrSt->IdleSt 502 Covered T6,T12,T36
ScrSt->ScrWaitSt 499 Covered T2,T3,T4
ScrWaitSt->ErrorSt 528 Not Covered
ScrWaitSt->WriteSt 521 Covered T2,T3,T4
WriteSt->ErrorSt 685 Not Covered
WriteSt->IdleSt 434 Covered T1,T36,T94
WriteSt->WriteWaitSt 429 Covered T1,T2,T3
WriteWaitSt->ErrorSt 459 Covered T162,T163,T164
WriteWaitSt->IdleSt 464 Covered T1,T2,T3


Summary for FSM :: error_q
TotalCoveredPercent
States 4 4 100.00 (Not included in score)
Transitions 9 8 88.89
Sequences 0 0

State, Transition and Sequence Details for FSM :: error_q
statesLine No.CoveredTests
AccessError 330 Covered T1,T6,T12
FsmStateError 370 Covered T2,T4,T11
MacroEccCorrError 358 Covered T126,T93,T100
NoError 172 Covered T1,T2,T3


transitionsLine No.CoveredTestsExclude Annotation
AccessError->FsmStateError 370 Covered T165,T166,T24
AccessError->MacroEccCorrError 358 Excluded VC_COV_UNR
AccessError->NoError 172 Covered T1,T6,T12
FsmStateError->AccessError 330 Excluded VC_COV_UNR
FsmStateError->MacroEccCorrError 358 Excluded VC_COV_UNR
FsmStateError->NoError 172 Covered T2,T4,T11
MacroEccCorrError->AccessError 330 Not Covered
MacroEccCorrError->FsmStateError 370 Covered T147,T167,T168
MacroEccCorrError->NoError 172 Covered T126,T93,T100
NoError->AccessError 330 Covered T1,T6,T12
NoError->FsmStateError 370 Covered T2,T4,T11
NoError->MacroEccCorrError 358 Covered T126,T93,T100



Branch Coverage for Instance : tb.dut.u_otp_ctrl_dai
Line No.TotalCoveredPercent
Branches 90 81 90.00
TERNARY 184 2 2 100.00
IF 170 2 2 100.00
CASE 225 71 62 87.32
IF 684 3 3 100.00
IF 757 4 4 100.00
IF 803 2 2 100.00
IF 806 6 6 100.00


184 assign dai_rdata_o = (state_q == IdleSt) ? data_q : '0; -1- ==> ==>

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


170 if (!PartInfo[part_idx].integrity && -1- 171 otp_err_e'(otp_err_i) inside {MacroEccCorrError, MacroEccUncorrError}) begin 172 otp_err = NoError; ==> 173 end MISSING_ELSE ==>

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


225 unique case (state_q) -1- 226 /////////////////////////////////////////////////////////////////// 227 // We get here after reset and wait until the power manager 228 // requests OTP initialization. If initialization is requested, 229 // an init command is written to the OTP macro, and we move on 230 // to the InitOtpSt waiting state. 231 ResetSt: begin 232 init_done_o = 1'b0; 233 dai_prog_idle_o = 1'b0; 234 data_clr = 1'b1; 235 if (init_req_i) begin -2- 236 otp_req_o = 1'b1; 237 if (otp_gnt_i) begin -3- 238 state_d = InitOtpSt; ==> 239 end MISSING_ELSE ==> (Excluded) Exclude Annotation: VC_COV_UNR 240 end MISSING_ELSE ==> 241 end 242 /////////////////////////////////////////////////////////////////// 243 // We wait here unitl the OTP macro has initialized without 244 // error. If an error occurred during this stage, we latch that 245 // error and move into a terminal error state. 246 InitOtpSt: begin 247 init_done_o = 1'b0; 248 dai_prog_idle_o = 1'b0; 249 if (otp_rvalid_i) begin -4- 250 if ((!(otp_err inside {NoError, MacroEccCorrError}))) begin -5- 251 state_d = ErrorSt; ==> (Excluded) Exclude Annotation: VC_COV_UNR 252 error_d = otp_err; 253 end else begin 254 state_d = InitPartSt; ==> 255 end 256 end MISSING_ELSE ==> 257 end 258 /////////////////////////////////////////////////////////////////// 259 // Since the OTP macro is now functional, we can send out an 260 // initialization request to all partitions and wait until they 261 // all have initialized. 262 InitPartSt: begin 263 init_done_o = 1'b0; 264 dai_prog_idle_o = 1'b0; 265 part_init_req_o = 1'b1; 266 if (part_init_done_i == {NumPart{1'b1}}) begin -6- 267 state_d = IdleSt; ==> 268 end MISSING_ELSE ==> 269 end 270 /////////////////////////////////////////////////////////////////// 271 // Idle state where we wait for incoming commands. 272 // Invalid commands trigger a CmdInvErr, which is recoverable. 273 IdleSt: begin 274 dai_idle_o = 1'b1; 275 if (dai_req_i) begin -7- 276 // This clears previous (recoverable) and reset the counter. 277 error_d = NoError; 278 cnt_clr = 1'b1; 279 unique case (dai_cmd_i) -8- 280 DaiRead: begin 281 state_d = ReadSt; ==> 282 // Clear the temporary data register. 283 data_clr = 1'b1; 284 base_sel_d = DaiOffset; 285 end 286 DaiWrite: begin 287 data_sel = DaiData; 288 // Fetch data block. 289 data_en = 1'b1; 290 base_sel_d = DaiOffset; 291 // If this partition is scrambled, directly go to write scrambling first. 292 if (PartInfo[part_idx].secret) begin -9- 293 state_d = ScrSt; ==> 294 end else begin 295 state_d = WriteSt; ==> 296 end 297 end 298 DaiDigest: begin 299 state_d = DigClrSt; ==> 300 scrmbl_mtx_req_o = 1'b1; 301 base_sel_d = PartOffset; 302 end 303 default: ; // Ignore invalid commands ==> 304 endcase // dai_cmd_i 305 end // dai_req_i MISSING_ELSE ==> 306 end 307 /////////////////////////////////////////////////////////////////// 308 // Each time we request a block of data from OTP, we re-check 309 // whether read access has been locked for this partition. If 310 // that is the case, we immediately bail out. Otherwise, we 311 // request a block of data from OTP. 312 ReadSt: begin 313 if (part_sel_valid && (mubi8_test_false_strict(part_access_i[part_idx].read_lock) || -10- 314 // HW digests always remain readable. 315 PartInfo[part_idx].hw_digest && otp_addr_o == 316 digest_addr_lut[part_idx])) begin 317 otp_req_o = 1'b1; 318 // Depending on the partition configuration, 319 // the wrapper is instructed to ignore integrity errors. 320 if (PartInfo[part_idx].integrity) begin -11- 321 otp_cmd_o = prim_otp_pkg::Read; ==> 322 end else begin 323 otp_cmd_o = prim_otp_pkg::ReadRaw; ==> 324 end 325 if (otp_gnt_i) begin -12- 326 state_d = ReadWaitSt; ==> 327 end MISSING_ELSE ==> 328 end else begin 329 state_d = IdleSt; ==> 330 error_d = AccessError; // Signal this error, but do not go into terminal error state. 331 dai_cmd_done_o = 1'b1; 332 end 333 end 334 /////////////////////////////////////////////////////////////////// 335 // Wait for OTP response and write to readout register. Check 336 // whether descrambling is required or not. In case an OTP 337 // transaction fails, latch the OTP error code, and jump to 338 // terminal error state. 339 ReadWaitSt: begin 340 // Continuously check read access and bail out if this is not consistent. 341 if (part_sel_valid && (mubi8_test_false_strict(part_access_i[part_idx].read_lock) || -13- 342 // HW digests always remain readable. 343 PartInfo[part_idx].hw_digest && otp_addr_o == 344 digest_addr_lut[part_idx])) begin 345 if (otp_rvalid_i) begin -14- 346 // Check OTP return code. 347 if (otp_err inside {NoError, MacroEccCorrError}) begin -15- 348 data_en = 1'b1; 349 // We do not need to descramble the digest values. 350 if (PartInfo[part_idx].secret && otp_addr_o != digest_addr_lut[part_idx]) begin -16- 351 state_d = DescrSt; ==> 352 end else begin 353 state_d = IdleSt; ==> 354 dai_cmd_done_o = 1'b1; 355 end 356 // At this point the only error that we could have gotten are correctable ECC errors. 357 if (otp_err != NoError) begin -17- 358 error_d = MacroEccCorrError; ==> 359 end MISSING_ELSE ==> 360 end else begin 361 state_d = ErrorSt; ==> 362 error_d = otp_err; 363 end 364 end MISSING_ELSE ==> 365 // At this point, this check MUST succeed - otherwise this means that 366 // there was a tampering attempt. Hence we go into a terminal error state 367 // when this check fails. 368 end else begin 369 state_d = ErrorSt; ==> 370 error_d = FsmStateError; 371 end 372 end 373 /////////////////////////////////////////////////////////////////// 374 // Descrambling state. This first acquires the scrambling 375 // datapath mutex. Note that once the mutex is acquired, we have 376 // exclusive access to the scrambling datapath until we release 377 // the mutex by deasserting scrmbl_mtx_req_o. 378 // SEC_CM: SECRET.MEM.SCRAMBLE 379 DescrSt: begin 380 scrmbl_mtx_req_o = 1'b1; 381 scrmbl_valid_o = 1'b1; 382 scrmbl_cmd_o = Decrypt; 383 scrmbl_sel_o = PartInfo[part_idx].key_sel; 384 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin -18- 385 state_d = DescrWaitSt; ==> 386 end MISSING_ELSE ==> 387 end 388 /////////////////////////////////////////////////////////////////// 389 // Wait for the descrambled data to return. Note that we release 390 // the mutex lock upon leaving this state. 391 // SEC_CM: SECRET.MEM.SCRAMBLE 392 DescrWaitSt: begin 393 scrmbl_mtx_req_o = 1'b1; 394 scrmbl_sel_o = PartInfo[part_idx].key_sel; 395 data_sel = ScrmblData; 396 if (scrmbl_valid_i) begin -19- 397 state_d = IdleSt; ==> 398 data_en = 1'b1; 399 dai_cmd_done_o = 1'b1; 400 end MISSING_ELSE ==> 401 end 402 /////////////////////////////////////////////////////////////////// 403 // First, check whether write accesses are allowed to this 404 // partition, and error out otherwise. Note that for buffered 405 // partitions, we do not allow DAI writes to the digest offset. 406 // Unbuffered partitions have SW managed digests, hence that 407 // check is not needed in that case. The LC partition is 408 // permanently write locked and can hence not be written via the DAI. 409 WriteSt: begin 410 dai_prog_idle_o = 1'b0; 411 if (part_sel_valid && mubi8_test_false_strict(part_access_i[part_idx].write_lock) && -20- 412 // If this is a HW digest write to a buffered partition. 413 ((PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].hw_digest && 414 base_sel_q == PartOffset && otp_addr_o == digest_addr_lut[part_idx]) || 415 // If this is a non HW digest write to a buffered partition. 416 (PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].hw_digest && 417 base_sel_q == DaiOffset && otp_addr_o < digest_addr_lut[part_idx]) || 418 // If this is a write to an unbuffered partition 419 (PartInfo[part_idx].variant != Buffered && base_sel_q == DaiOffset))) begin 420 otp_req_o = 1'b1; 421 // Depending on the partition configuration, 422 // the wrapper is instructed to ignore integrity errors. 423 if (PartInfo[part_idx].integrity) begin -21- 424 otp_cmd_o = prim_otp_pkg::Write; ==> 425 end else begin 426 otp_cmd_o = prim_otp_pkg::WriteRaw; ==> 427 end 428 if (otp_gnt_i) begin -22- 429 state_d = WriteWaitSt; ==> 430 end MISSING_ELSE ==> 431 end else begin 432 // Clear working register state. 433 data_clr = 1'b1; ==> 434 state_d = IdleSt; 435 error_d = AccessError; // Signal this error, but do not go into terminal error state. 436 dai_cmd_done_o = 1'b1; 437 end 438 end 439 /////////////////////////////////////////////////////////////////// 440 // Wait for OTP response, and then go back to idle. In case an 441 // OTP transaction fails, latch the OTP error code, and jump to 442 // terminal error state. 443 WriteWaitSt: begin 444 dai_prog_idle_o = 1'b0; 445 // Continuously check write access and bail out if this is not consistent. 446 if (part_sel_valid && mubi8_test_false_strict(part_access_i[part_idx].write_lock) && -23- 447 // If this is a HW digest write to a buffered partition. 448 ((PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].hw_digest && 449 base_sel_q == PartOffset && otp_addr_o == digest_addr_lut[part_idx]) || 450 // If this is a non HW digest write to a buffered partition. 451 (PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].hw_digest && 452 base_sel_q == DaiOffset && otp_addr_o < digest_addr_lut[part_idx]) || 453 // If this is a write to an unbuffered partition 454 (PartInfo[part_idx].variant != Buffered && base_sel_q == DaiOffset))) begin 455 456 if (otp_rvalid_i) begin -24- 457 // Check OTP return code. Note that non-blank errors are recoverable. 458 if ((!(otp_err inside {NoError, MacroWriteBlankError}))) begin -25- 459 state_d = ErrorSt; ==> (Excluded) Exclude Annotation: VC_COV_UNR 460 error_d = otp_err; 461 end else begin 462 // Clear working register state. 463 data_clr = 1'b1; 464 state_d = IdleSt; 465 dai_cmd_done_o = 1'b1; 466 // Signal non-blank state, but do not go to terminal error state. 467 if (otp_err == MacroWriteBlankError) begin -26- 468 error_d = otp_err; ==> 469 end MISSING_ELSE ==> 470 end 471 end MISSING_ELSE ==> 472 // At this point, this check MUST succeed - otherwise this means that 473 // there was a tampering attempt. Hence we go into a terminal error state 474 // when this check fails. 475 end else begin 476 state_d = ErrorSt; ==> 477 error_d = FsmStateError; 478 end 479 end 480 /////////////////////////////////////////////////////////////////// 481 // Scrambling state. This first acquires the scrambling 482 // datapath mutex. Note that once the mutex is acquired, we have 483 // exclusive access to the scrambling datapath until we release 484 // the mutex by deasserting scrmbl_mtx_req_o. 485 // SEC_CM: SECRET.MEM.SCRAMBLE 486 ScrSt: begin 487 scrmbl_mtx_req_o = 1'b1; 488 // Check write access and bail out if this is not consistent. 489 if (part_sel_valid && mubi8_test_false_strict(part_access_i[part_idx].write_lock) && -27- 490 // If this is a non HW digest write to a buffered partition. 491 (PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].secret && 492 PartInfo[part_idx].hw_digest && base_sel_q == DaiOffset && 493 otp_addr_o < digest_addr_lut[part_idx])) begin 494 495 scrmbl_valid_o = 1'b1; 496 scrmbl_cmd_o = Encrypt; 497 scrmbl_sel_o = PartInfo[part_idx].key_sel; 498 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin -28- 499 state_d = ScrWaitSt; ==> 500 end MISSING_ELSE ==> 501 end else begin 502 state_d = IdleSt; ==> 503 error_d = AccessError; // Signal this error, but do not go into terminal error state. 504 dai_cmd_done_o = 1'b1; 505 end 506 end 507 /////////////////////////////////////////////////////////////////// 508 // Wait for the scrambled data to return. Note that we release 509 // the mutex lock upon leaving this state. 510 // SEC_CM: SECRET.MEM.SCRAMBLE 511 ScrWaitSt: begin 512 scrmbl_mtx_req_o = 1'b1; 513 // Continously check write access and bail out if this is not consistent. 514 if (part_sel_valid && mubi8_test_false_strict(part_access_i[part_idx].write_lock) && -29- 515 // If this is a non HW digest write to a buffered partition. 516 (PartInfo[part_idx].variant == Buffered && PartInfo[part_idx].secret && 517 PartInfo[part_idx].hw_digest && base_sel_q == DaiOffset && 518 otp_addr_o < digest_addr_lut[part_idx])) begin 519 data_sel = ScrmblData; 520 if (scrmbl_valid_i) begin -30- 521 state_d = WriteSt; ==> 522 data_en = 1'b1; 523 end MISSING_ELSE ==> 524 // At this point, this check MUST succeed - otherwise this means that 525 // there was a tampering attempt. Hence we go into a terminal error state 526 // when this check fails. 527 end else begin 528 state_d = ErrorSt; ==> 529 error_d = FsmStateError; 530 end 531 end 532 /////////////////////////////////////////////////////////////////// 533 // First, acquire the mutex for the digest and clear the digest state. 534 // SEC_CM: PART.MEM.DIGEST 535 DigClrSt: begin 536 scrmbl_mtx_req_o = 1'b1; 537 scrmbl_valid_o = 1'b1; 538 // Need to reset the digest state and set digest mode to "standard". 539 scrmbl_cmd_o = DigestInit; 540 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin -31- 541 state_d = DigReadSt; ==> 542 end MISSING_ELSE ==> 543 end 544 /////////////////////////////////////////////////////////////////// 545 // This requests a 64bit block to be pushed into the digest datapath. 546 // We also check here whether the partition has been write locked. 547 // SEC_CM: PART.MEM.DIGEST 548 DigReadSt: begin 549 scrmbl_mtx_req_o = 1'b1; 550 if (part_sel_valid && -32- 551 mubi8_test_false_strict(part_access_i[part_idx].read_lock) && 552 mubi8_test_false_strict(part_access_i[part_idx].write_lock)) begin 553 otp_req_o = 1'b1; 554 // Depending on the partition configuration, 555 // the wrapper is instructed to ignore integrity errors. 556 if (PartInfo[part_idx].integrity) begin -33- 557 otp_cmd_o = prim_otp_pkg::Read; ==> 558 end else begin 559 otp_cmd_o = prim_otp_pkg::ReadRaw; ==> 560 end 561 if (otp_gnt_i) begin -34- 562 state_d = DigReadWaitSt; ==> 563 end MISSING_ELSE ==> 564 end else begin 565 state_d = IdleSt; ==> 566 error_d = AccessError; // Signal this error, but do not go into terminal error state. 567 dai_cmd_done_o = 1'b1; 568 end 569 end 570 /////////////////////////////////////////////////////////////////// 571 // Wait for OTP response and write to readout register. Check 572 // whether descrambling is required or not. In case an OTP 573 // transaction fails, latch the OTP error code, and jump to 574 // terminal error state. 575 // SEC_CM: PART.MEM.DIGEST 576 DigReadWaitSt: begin 577 scrmbl_mtx_req_o = 1'b1; 578 if (otp_rvalid_i) begin -35- 579 cnt_en = 1'b1; 580 // Check OTP return code. 581 if ((!(otp_err inside {NoError, MacroEccCorrError}))) begin -36- 582 state_d = ErrorSt; ==> 583 error_d = otp_err; 584 end else begin 585 data_en = 1'b1; 586 state_d = DigSt; 587 // Signal soft ECC errors, but do not go into terminal error state. 588 if (otp_err == MacroEccCorrError) begin -37- 589 error_d = otp_err; ==> 590 end MISSING_ELSE ==> 591 end 592 end MISSING_ELSE ==> 593 end 594 /////////////////////////////////////////////////////////////////// 595 // Push the word read into the scrambling datapath. The last 596 // block is repeated in case the number blocks in this partition 597 // is odd. 598 // SEC_CM: PART.MEM.DIGEST 599 DigSt: begin 600 scrmbl_mtx_req_o = 1'b1; 601 scrmbl_valid_o = 1'b1; 602 // No need to digest the digest value itself 603 if (otp_addr_o == digest_addr_lut[part_idx]) begin -38- 604 // Trigger digest round in case this is the second block in a row. 605 if (!cnt[0]) begin -39- 606 scrmbl_cmd_o = Digest; 607 if (scrmbl_ready_i) begin -40- 608 state_d = DigFinSt; ==> 609 end MISSING_ELSE ==> 610 // Otherwise, just load low word and go to padding state. 611 end else if (scrmbl_ready_i) begin -41- 612 state_d = DigPadSt; ==> 613 end MISSING_ELSE ==> 614 end else begin 615 // Trigger digest round in case this is the second block in a row. 616 if (!cnt[0]) begin -42- 617 scrmbl_cmd_o = Digest; ==> 618 end MISSING_ELSE ==> 619 // Go back and fetch more data blocks. 620 if (scrmbl_ready_i) begin -43- 621 state_d = DigReadSt; ==> 622 end MISSING_ELSE ==> 623 end 624 end 625 /////////////////////////////////////////////////////////////////// 626 // Padding state, just repeat the last block and go to digest 627 // finalization. 628 // SEC_CM: PART.MEM.DIGEST 629 DigPadSt: begin 630 scrmbl_mtx_req_o = 1'b1; 631 scrmbl_valid_o = 1'b1; 632 scrmbl_cmd_o = Digest; 633 if (scrmbl_ready_i) begin -44- 634 state_d = DigFinSt; ==> 635 end MISSING_ELSE ==> 636 end 637 /////////////////////////////////////////////////////////////////// 638 // Trigger digest finalization and go wait for the result. 639 // SEC_CM: PART.MEM.DIGEST 640 DigFinSt: begin 641 scrmbl_mtx_req_o = 1'b1; 642 scrmbl_valid_o = 1'b1; 643 scrmbl_cmd_o = DigestFinalize; 644 if (scrmbl_ready_i) begin -45- 645 state_d = DigWaitSt; ==> 646 end MISSING_ELSE ==> 647 end 648 /////////////////////////////////////////////////////////////////// 649 // Wait for the digest to return, and write the result to OTP. 650 // Note that the write address will be correct in this state, 651 // since the counter has been stepped to the correct address as 652 // part of the readout sequence, and the correct size for this 653 // access has been loaded before. 654 // SEC_CM: PART.MEM.DIGEST 655 DigWaitSt: begin 656 scrmbl_mtx_req_o = 1'b1; 657 data_sel = ScrmblData; 658 if (scrmbl_valid_i) begin -46- 659 state_d = WriteSt; ==> 660 data_en = 1'b1; 661 end MISSING_ELSE ==> 662 end 663 /////////////////////////////////////////////////////////////////// 664 // Terminal Error State. This locks access to the DAI. Make sure 665 // an FsmStateError error code is assigned here, in case no error code has 666 // been assigned yet. 667 ErrorSt: begin 668 if (error_q == NoError) begin -47- 669 error_d = FsmStateError; ==> 670 end MISSING_ELSE ==> 671 end 672 /////////////////////////////////////////////////////////////////// 673 // We should never get here. If we do (e.g. via a malicious 674 // glitch), error out immediately. 675 default: begin 676 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--41--42--43--44--45--46--47-StatusTestsExclude Annotation
ResetSt 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ResetSt 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Excluded VC_COV_UNR
ResetSt 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
InitOtpSt - - 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Excluded VC_COV_UNR
InitOtpSt - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
InitOtpSt - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
InitPartSt - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
InitPartSt - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
IdleSt - - - - - 1 DaiRead - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
IdleSt - - - - - 1 DaiWrite 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T4
IdleSt - - - - - 1 DaiWrite 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
IdleSt - - - - - 1 DaiDigest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T3,T5
IdleSt - - - - - 1 default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Not Covered
IdleSt - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadSt - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadSt - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T4
ReadSt - - - - - - - - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadSt - - - - - - - - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T36,T94,T9
ReadSt - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T6,T12,T36
ReadWaitSt - - - - - - - - - - - 1 1 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T4,T5
ReadWaitSt - - - - - - - - - - - 1 1 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 1 1 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T126,T93,T100
ReadWaitSt - - - - - - - - - - - 1 1 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 1 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T12,T126,T7
ReadWaitSt - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Not Covered
DescrSt - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T4,T5
DescrSt - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T6,T92,T119
DescrWaitSt - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T4,T5
DescrWaitSt - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T4,T5
WriteSt - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
WriteSt - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T5
WriteSt - - - - - - - - - - - - - - - - - - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
WriteSt - - - - - - - - - - - - - - - - - - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T36,T94,T9
WriteSt - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T36,T94
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 1 1 1 - - - - - - - - - - - - - - - - - - - - - - Excluded VC_COV_UNR
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 1 1 0 1 - - - - - - - - - - - - - - - - - - - - - Covered T12,T7,T8
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 1 1 0 0 - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - Not Covered
ScrSt - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - - - Covered T2,T3,T4
ScrSt - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - Covered T6,T92,T119
ScrSt - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - Covered T6,T12,T36
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - Covered T2,T3,T4
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - Covered T2,T3,T4
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - Not Covered
DigClrSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - Covered T1,T3,T5
DigClrSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - Covered T6,T92,T119
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - Covered T1,T3,T5
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - Not Covered
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 1 - - - - - - - - - - - - - Covered T1,T3,T5
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 0 - - - - - - - - - - - - - Covered T36,T94,T9
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - Covered T6,T36,T94
DigReadWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - Not Covered
DigReadWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 1 - - - - - - - - - - Not Covered
DigReadWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 0 - - - - - - - - - - Covered T1,T3,T5
DigReadWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - Covered T1,T3,T5
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 1 - - - - - - - Covered T1,T3,T5
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 0 - - - - - - - Not Covered
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - 1 - - - - - - Covered T1,T5,T11
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - 0 - - - - - - Covered T1
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - 1 - - - - - Covered T1,T3,T5
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - 0 - - - - - Covered T1,T3,T5
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 1 - - - - Covered T1,T3,T5
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0 - - - - Covered T1,T3,T5
DigPadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - Covered T1,T5,T11
DigPadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - Not Covered
DigFinSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - Covered T1,T3,T5
DigFinSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - Covered T1,T3,T5
DigWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - Covered T1,T3,T5
DigWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - Covered T1,T3,T5
ErrorSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 Covered T27,T28,T29
ErrorSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 Covered T2,T4,T11
default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T27,T28,T29


684 if (lc_ctrl_pkg::lc_tx_test_true_loose(escalate_en_i) || cnt_err) begin -1- 685 state_d = ErrorSt; 686 fsm_err_o = 1'b1; 687 if (state_q != ErrorSt) begin -2- 688 error_d = FsmStateError; ==> 689 end MISSING_ELSE ==> 690 end MISSING_ELSE ==>

Branches:
-1--2-StatusTests
1 1 Covered T2,T4,T11
1 0 Covered T2,T4,T11
0 - Covered T1,T2,T3


757 if (PartInfo[part_idx].secret) begin -1- 758 otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth - 1)); ==> 759 addr_base = {dai_addr_i[OtpByteAddrWidth-1:3], 3'h0}; 760 // 64bit transaction if computing a digest. 761 end else if (PartInfo[part_idx].hw_digest && (base_sel_q == PartOffset)) begin -2- 762 otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth - 1)); ==> 763 addr_base = PartInfo[part_idx].offset; 764 // 64bit transaction if the DAI address points to the partition's digest offset. 765 end else if ((PartInfo[part_idx].hw_digest || PartInfo[part_idx].sw_digest) && -3- 766 (base_sel_q == DaiOffset) && 767 ({dai_addr_i[OtpByteAddrWidth-1:3], 2'b0} == digest_addr_lut[part_idx])) begin 768 otp_size_o = OtpSizeWidth'(unsigned'(ScrmblBlockWidth / OtpWidth - 1)); ==> 769 addr_base = {dai_addr_i[OtpByteAddrWidth-1:3], 3'h0}; 770 end MISSING_ELSE ==>

Branches:
-1--2--3-StatusTests
1 - - Covered T2,T3,T4
0 1 - Covered T1,T3,T5
0 0 1 Covered T6,T129,T36
0 0 0 Covered T1,T2,T3


803 `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


806 if (!rst_ni) begin -1- 807 error_q <= NoError; ==> 808 data_q <= '0; 809 base_sel_q <= DaiOffset; 810 end else begin 811 error_q <= error_d; 812 base_sel_q <= base_sel_d; 813 814 // Working register 815 if (data_clr) begin -2- 816 data_q <= '0; ==> 817 end else if (data_en) begin -3- 818 if (data_sel == ScrmblData) begin -4- 819 data_q <= scrmbl_data_i; ==> 820 end else if (data_sel == DaiData) begin -5- 821 data_q <= dai_wdata_i; ==> 822 end else begin 823 data_q <= otp_rdata_i; ==> 824 end 825 end MISSING_ELSE ==>

Branches:
-1--2--3--4--5-StatusTests
1 - - - - Covered T1,T2,T3
0 1 - - - Covered T1,T2,T3
0 0 1 1 - Covered T1,T2,T3
0 0 1 0 1 Covered T1,T2,T3
0 0 1 0 0 Covered T1,T2,T3
0 0 0 - - Covered T1,T2,T3


Assert Coverage for Instance : tb.dut.u_otp_ctrl_dai
TotalAttemptedPercentSucceeded/MatchedPercent
Assertions 33 33 100.00 33 100.00
Cover properties 0 0 0
Cover sequences 0 0 0
Total 33 33 100.00 33 100.00




Assertion Details

NameAttemptsReal SuccessesFailuresIncomplete
CheckNativeOtpWidth0_A 1122 1122 0 0
CheckNativeOtpWidth1_A 1122 1122 0 0
DaiIdleKnown_A 100520911 99678943 0 0
DaiRdataKnown_A 100520911 99678943 0 0
ErrorKnown_A 100520911 99678943 0 0
InitDoneKnown_A 100520911 99678943 0 0
OtpAddrKnown_A 100520911 99678943 0 0
OtpCmdKnown_A 100520911 99678943 0 0
OtpErrorState_A 100520911 352 0 0
OtpReqKnown_A 100520911 99678943 0 0
OtpSizeKnown_A 100520911 99678943 0 0
OtpWdataKnown_A 100520911 99678943 0 0
PartInitReqKnown_A 100520911 99678943 0 0
PartSelMustBeOnehot_A 100520911 99678943 0 0
ScrmblBlockWidthGe8_A 100520911 99678943 0 0
ScrmblCmdKnown_A 100520911 99678943 0 0
ScrmblDataKnown_A 100520911 99678943 0 0
ScrmblModeKnown_A 100520911 99678943 0 0
ScrmblMtxReqKnown_A 100520911 99678943 0 0
ScrmblSelKnown_A 100520911 99678943 0 0
ScrmblValidKnown_A 100520911 99678943 0 0
gen_part_sel[0].PartEndMax_A 1122 1122 0 0
gen_part_sel[10].PartEndMax_A 1122 1122 0 0
gen_part_sel[1].PartEndMax_A 1122 1122 0 0
gen_part_sel[2].PartEndMax_A 1122 1122 0 0
gen_part_sel[3].PartEndMax_A 1122 1122 0 0
gen_part_sel[4].PartEndMax_A 1122 1122 0 0
gen_part_sel[5].PartEndMax_A 1122 1122 0 0
gen_part_sel[6].PartEndMax_A 1122 1122 0 0
gen_part_sel[7].PartEndMax_A 1122 1122 0 0
gen_part_sel[8].PartEndMax_A 1122 1122 0 0
gen_part_sel[9].PartEndMax_A 1122 1122 0 0
u_state_regs_A 100520911 99678943 0 0


CheckNativeOtpWidth0_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

CheckNativeOtpWidth1_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

DaiIdleKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

DaiRdataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

ErrorKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

InitDoneKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

OtpAddrKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

OtpCmdKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

OtpErrorState_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 352 0 0
T7 0 1 0 0
T8 0 1 0 0
T9 0 1 0 0
T12 24721 1 0 0
T13 35219 0 0 0
T17 3538 0 0 0
T36 71599 0 0 0
T92 19581 0 0 0
T94 33983 0 0 0
T97 11787 0 0 0
T102 18611 0 0 0
T125 70975 0 0 0
T126 0 3 0 0
T129 38435 0 0 0
T147 0 8 0 0
T169 0 1 0 0
T170 0 1 0 0
T171 0 1 0 0
T172 0 4 0 0

OtpReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

OtpSizeKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

OtpWdataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

PartInitReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

PartSelMustBeOnehot_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

ScrmblBlockWidthGe8_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

ScrmblCmdKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

ScrmblDataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

ScrmblModeKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

ScrmblMtxReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

ScrmblSelKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

ScrmblValidKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

gen_part_sel[0].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[10].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[1].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[2].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[3].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[4].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[5].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[6].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[7].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[8].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

gen_part_sel[9].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1122 1122 0 0
T1 1 1 0 0
T2 1 1 0 0
T3 1 1 0 0
T4 1 1 0 0
T5 1 1 0 0
T6 1 1 0 0
T10 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

u_state_regs_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 100520911 99678943 0 0
T1 4694 4634 0 0
T2 12395 12162 0 0
T3 13919 13658 0 0
T4 14699 14449 0 0
T5 23906 23532 0 0
T6 23760 23518 0 0
T10 4132 4057 0 0
T11 15255 14984 0 0
T12 24721 24489 0 0
T13 35219 34664 0 0

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