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



Module Instance : tb.dut.u_otp_ctrl_dai

Instance :
SCORELINECONDTOGGLEFSMBRANCHASSERT
93.38 95.88 95.06 85.96 90.00 100.00


Instance's subtree :
SCORELINECONDTOGGLEFSMBRANCHASSERT
90.09 85.64 91.96 100.00 85.96 89.73 87.23


Parent :
SCORELINECONDTOGGLEFSMBRANCHASSERTNAME
96.16 94.16 96.15 96.85 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: T7 T67 T70  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 T11  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 T2 T3  300 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T2 T3  301 1/1 base_sel_d = PartOffset; Tests: T1 T2 T3  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 T5  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 T7 T12  330 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T6 T7 T12  331 1/1 dai_cmd_done_o = 1'b1; Tests: T6 T7 T12  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 T3 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: T7 T134 T70  359 end MISSING_ELSE 360 end else begin 361 1/1 state_d = ErrorSt; Tests: T8 T134 T146  362 1/1 error_d = otp_err; Tests: T8 T134 T146  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 T3 T5  381 1/1 scrmbl_valid_o = 1'b1; Tests: T2 T3 T5  382 1/1 scrmbl_cmd_o = Decrypt; Tests: T2 T3 T5  383 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T3 T5  384 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin Tests: T2 T3 T5  385 1/1 state_d = DescrWaitSt; Tests: T2 T3 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 T3 T5  394 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T3 T5  395 1/1 data_sel = ScrmblData; Tests: T2 T3 T5  396 1/1 if (scrmbl_valid_i) begin Tests: T2 T3 T5  397 1/1 state_d = IdleSt; Tests: T2 T3 T5  398 1/1 data_en = 1'b1; Tests: T2 T3 T5  399 1/1 dai_cmd_done_o = 1'b1; Tests: T2 T3 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 T11  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 T11 T6  434 1/1 state_d = IdleSt; Tests: T1 T11 T6  435 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T1 T11 T6  436 1/1 dai_cmd_done_o = 1'b1; Tests: T1 T11 T6  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: T8 T146 T9  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 T11  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 T11  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 T11  496 1/1 scrmbl_cmd_o = Encrypt; Tests: T2 T3 T11  497 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T3 T11  498 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin Tests: T2 T3 T11  499 1/1 state_d = ScrWaitSt; Tests: T2 T3 T11  500 end MISSING_ELSE 501 end else begin 502 1/1 state_d = IdleSt; Tests: T11 T6 T7  503 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T11 T6 T7  504 1/1 dai_cmd_done_o = 1'b1; Tests: T11 T6 T7  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 T11  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 T11  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 T11  520 1/1 if (scrmbl_valid_i) begin Tests: T2 T3 T11  521 1/1 state_d = WriteSt; Tests: T2 T3 T11  522 1/1 data_en = 1'b1; Tests: T2 T3 T11  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 T2 T3  537 1/1 scrmbl_valid_o = 1'b1; Tests: T1 T2 T3  538 // Need to reset the digest state and set digest mode to "standard". 539 1/1 scrmbl_cmd_o = DigestInit; Tests: T1 T2 T3  540 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin Tests: T1 T2 T3  541 1/1 state_d = DigReadSt; Tests: T1 T2 T3  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 T2 T3  550 1/1 if (part_sel_valid && Tests: T1 T2 T3  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 T2 T3  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 T2 T3  557 1/1 otp_cmd_o = prim_otp_pkg::Read; Tests: T1 T2 T3  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 T2 T3  562 1/1 state_d = DigReadWaitSt; Tests: T1 T2 T3  563 end MISSING_ELSE 564 end else begin 565 1/1 state_d = IdleSt; Tests: T6 T7 T12  566 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T6 T7 T12  567 1/1 dai_cmd_done_o = 1'b1; Tests: T6 T7 T12  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 T2 T3  578 1/1 if (otp_rvalid_i) begin Tests: T1 T2 T3  579 1/1 cnt_en = 1'b1; Tests: T1 T2 T3  580 // Check OTP return code. 581 1/1 if ((!(otp_err inside {NoError, MacroEccCorrError}))) begin Tests: T1 T2 T3  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 T2 T3  586 1/1 state_d = DigSt; Tests: T1 T2 T3  587 // Signal soft ECC errors, but do not go into terminal error state. 588 1/1 if (otp_err == MacroEccCorrError) begin Tests: T1 T2 T3  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 T2 T3  601 1/1 scrmbl_valid_o = 1'b1; Tests: T1 T2 T3  602 // No need to digest the digest value itself 603 1/1 if (otp_addr_o == digest_addr_lut[part_idx]) begin Tests: T1 T2 T3  604 // Trigger digest round in case this is the second block in a row. 605 1/1 if (!cnt[0]) begin Tests: T1 T2 T3  606 1/1 scrmbl_cmd_o = Digest; Tests: T1 T2 T3  607 1/1 if (scrmbl_ready_i) begin Tests: T1 T2 T3  608 1/1 state_d = DigFinSt; Tests: T1 T2 T3  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 T2 T3  612 1/1 state_d = DigPadSt; Tests: T1 T2 T3  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 T2 T3  617 1/1 scrmbl_cmd_o = Digest; Tests: T1 T2 T3  618 end MISSING_ELSE 619 // Go back and fetch more data blocks. 620 1/1 if (scrmbl_ready_i) begin Tests: T1 T2 T3  621 1/1 state_d = DigReadSt; Tests: T1 T2 T3  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 T2 T3  631 1/1 scrmbl_valid_o = 1'b1; Tests: T1 T2 T3  632 1/1 scrmbl_cmd_o = Digest; Tests: T1 T2 T3  633 1/1 if (scrmbl_ready_i) begin Tests: T1 T2 T3  634 1/1 state_d = DigFinSt; Tests: T1 T2 T3  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 T2 T3  642 1/1 scrmbl_valid_o = 1'b1; Tests: T1 T2 T3  643 1/1 scrmbl_cmd_o = DigestFinalize; Tests: T1 T2 T3  644 1/1 if (scrmbl_ready_i) begin Tests: T1 T2 T3  645 1/1 state_d = DigWaitSt; Tests: T1 T2 T3  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 T2 T3  657 1/1 data_sel = ScrmblData; Tests: T1 T2 T3  658 1/1 if (scrmbl_valid_i) begin Tests: T1 T2 T3  659 1/1 state_d = WriteSt; Tests: T1 T2 T3  660 1/1 data_en = 1'b1; Tests: T1 T2 T3  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 T7  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 T7  686 1/1 fsm_err_o = 1'b1; Tests: T2 T4 T7  687 1/1 if (state_q != ErrorSt) begin Tests: T2 T4 T7  688 1/1 error_d = FsmStateError; Tests: T2 T4 T7  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 T5  759 1/1 addr_base = {dai_addr_i[OtpByteAddrWidth-1:3], 3'h0}; Tests: T2 T3 T5  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 T2 T3  763 1/1 addr_base = PartInfo[part_idx].offset; Tests: T1 T2 T3  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: T5 T11 T6  769 1/1 addr_base = {dai_addr_i[OtpByteAddrWidth-1:3], 3'h0}; Tests: T5 T11 T6  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
01CoveredT7,T8,T134
10CoveredT1,T2,T3
11CoveredT7,T67,T70

 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
10CoveredT5,T6,T12
11CoveredT2,T3,T5

 LINE       350
 SUB-EXPRESSION (otp_addr_o != digest_addr_lut[part_idx])
                --------------------1--------------------
-1-StatusTests
0CoveredT5,T6,T7
1CoveredT1,T2,T3

 LINE       357
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT7,T134,T70

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

 LINE       467
 EXPRESSION (otp_err == MacroWriteBlankError)
            ----------------1----------------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT8,T146,T9

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

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

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

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

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

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

 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,T3,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,T5

 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,T3,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,T5
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,T5
11CoveredT2,T3,T5

 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,T5
11CoveredT2,T3,T5

 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,T3,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
10CoveredT8,T9,T10
11CoveredT2,T3,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
11CoveredT8,T9,T10

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

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

 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
011CoveredT147,T148,T149
101CoveredT14,T26,T150
110CoveredT1,T2,T3
111CoveredT5,T11,T6

 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
00CoveredT8,T9,T10
01CoveredT1,T2,T3
10CoveredT2,T3,T5

 LINE       765
 SUB-EXPRESSION (base_sel_q == DaiOffset)
                ------------1------------
-1-StatusTests
0CoveredT1,T84,T51
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
1CoveredT5,T11,T6

 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 41 85.42
Sequences 0 0

State, Transition and Sequence Details for FSM :: state_q
statesLine No.CoveredTests
DescrSt 351 Covered T2,T3,T5
DescrWaitSt 385 Covered T2,T3,T5
DigClrSt 299 Covered T1,T2,T3
DigFinSt 608 Covered T1,T2,T3
DigPadSt 612 Covered T1,T2,T3
DigReadSt 541 Covered T1,T2,T3
DigReadWaitSt 562 Covered T1,T2,T3
DigSt 586 Covered T1,T2,T3
DigWaitSt 645 Covered T1,T2,T3
ErrorSt 251 Covered T2,T4,T7
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,T11
ScrWaitSt 499 Covered T2,T3,T11
WriteSt 295 Covered T1,T2,T3
WriteWaitSt 429 Covered T1,T2,T3


transitionsLine No.CoveredTests
DescrSt->DescrWaitSt 385 Covered T2,T3,T5
DescrSt->ErrorSt 685 Covered T151
DescrWaitSt->ErrorSt 685 Not Covered
DescrWaitSt->IdleSt 397 Covered T2,T3,T5
DigClrSt->DigReadSt 541 Covered T1,T2,T3
DigClrSt->ErrorSt 685 Not Covered
DigFinSt->DigWaitSt 645 Covered T1,T2,T3
DigFinSt->ErrorSt 685 Covered T149,T152,T153
DigPadSt->DigFinSt 634 Covered T1,T2,T3
DigPadSt->ErrorSt 685 Not Covered
DigReadSt->DigReadWaitSt 562 Covered T1,T2,T3
DigReadSt->ErrorSt 685 Covered T154
DigReadSt->IdleSt 565 Covered T6,T7,T12
DigReadWaitSt->DigSt 586 Covered T1,T2,T3
DigReadWaitSt->ErrorSt 582 Covered T155,T156,T157
DigSt->DigFinSt 608 Covered T1,T2,T3
DigSt->DigPadSt 612 Covered T1,T2,T3
DigSt->DigReadSt 621 Covered T1,T2,T3
DigSt->ErrorSt 685 Covered T158,T159,T160
DigWaitSt->ErrorSt 685 Covered T161,T162,T163
DigWaitSt->WriteSt 659 Covered T1,T2,T3
IdleSt->DigClrSt 299 Covered T1,T2,T3
IdleSt->ErrorSt 685 Covered T4,T7,T12
IdleSt->ReadSt 281 Covered T1,T2,T3
IdleSt->ScrSt 293 Covered T2,T3,T11
IdleSt->WriteSt 295 Covered T1,T2,T3
InitOtpSt->ErrorSt 251 Covered T164,T165
InitOtpSt->InitPartSt 254 Covered T1,T2,T3
InitPartSt->ErrorSt 685 Covered T2,T67,T95
InitPartSt->IdleSt 267 Covered T1,T2,T3
ReadSt->ErrorSt 685 Not Covered
ReadSt->IdleSt 329 Covered T6,T7,T12
ReadSt->ReadWaitSt 326 Covered T1,T2,T3
ReadWaitSt->DescrSt 351 Covered T2,T3,T5
ReadWaitSt->ErrorSt 361 Covered T8,T134,T146
ReadWaitSt->IdleSt 353 Covered T1,T2,T3
ResetSt->ErrorSt 685 Covered T101,T102,T103
ResetSt->InitOtpSt 238 Covered T1,T2,T3
ScrSt->ErrorSt 685 Not Covered
ScrSt->IdleSt 502 Covered T11,T6,T7
ScrSt->ScrWaitSt 499 Covered T2,T3,T11
ScrWaitSt->ErrorSt 528 Not Covered
ScrWaitSt->WriteSt 521 Covered T2,T3,T11
WriteSt->ErrorSt 685 Not Covered
WriteSt->IdleSt 434 Covered T1,T11,T6
WriteSt->WriteWaitSt 429 Covered T1,T2,T3
WriteWaitSt->ErrorSt 459 Covered T166,T167,T168
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,T11,T6
FsmStateError 370 Covered T2,T4,T7
MacroEccCorrError 358 Covered T7,T134,T70
NoError 172 Covered T1,T2,T3


transitionsLine No.CoveredTests
AccessError->FsmStateError 370 Covered T169,T170,T22
AccessError->MacroEccCorrError 358 Not Covered
AccessError->NoError 172 Covered T1,T11,T6
FsmStateError->AccessError 330 Not Covered
FsmStateError->MacroEccCorrError 358 Not Covered
FsmStateError->NoError 172 Covered T2,T4,T7
MacroEccCorrError->AccessError 330 Not Covered
MacroEccCorrError->FsmStateError 370 Covered T171,T172,T173
MacroEccCorrError->NoError 172 Covered T7,T134,T70
NoError->AccessError 330 Covered T1,T11,T6
NoError->FsmStateError 370 Covered T2,T4,T7
NoError->MacroEccCorrError 358 Covered T7,T134,T70



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 T7,T67,T70
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,T11
IdleSt - - - - - 1 DaiWrite 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
IdleSt - - - - - 1 DaiDigest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
IdleSt - - - - - 1 default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Not Covered
IdleSt - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadSt - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadSt - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T5
ReadSt - - - - - - - - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadSt - - - - - - - - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T6,T115,T118
ReadSt - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T6,T7,T12
ReadWaitSt - - - - - - - - - - - 1 1 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T5
ReadWaitSt - - - - - - - - - - - 1 1 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 1 1 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T7,T134,T70
ReadWaitSt - - - - - - - - - - - 1 1 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 1 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T8,T134,T146
ReadWaitSt - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Not Covered
DescrSt - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T5
DescrSt - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T117,T119,T123
DescrWaitSt - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T5
DescrWaitSt - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T5
WriteSt - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
WriteSt - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T11
WriteSt - - - - - - - - - - - - - - - - - - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
WriteSt - - - - - - - - - - - - - - - - - - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T6,T115,T118
WriteSt - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T11,T6
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 1 1 1 - - - - - - - - - - - - - - - - - - - - - - Not Covered
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 1 1 0 1 - - - - - - - - - - - - - - - - - - - - - Covered T8,T146,T9
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,T11
ScrSt - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - Covered T117,T119,T174
ScrSt - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - Covered T11,T6,T7
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - Covered T2,T3,T11
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - Covered T2,T3,T11
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - Not Covered
DigClrSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - Covered T1,T2,T3
DigClrSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - Covered T117,T119,T123
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - Covered T1,T2,T3
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - Not Covered
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 1 - - - - - - - - - - - - - Covered T1,T2,T3
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 0 - - - - - - - - - - - - - Covered T6,T115,T118
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - Covered T6,T7,T12
DigReadWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - Not Covered
DigReadWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 1 - - - - - - - - - - Not Covered
DigReadWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 0 - - - - - - - - - - Covered T1,T2,T3
DigReadWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - Covered T1,T2,T3
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 1 - - - - - - - Covered T1,T2,T3
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 0 - - - - - - - Not Covered
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - 1 - - - - - - Covered T1,T2,T3
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - 0 - - - - - - Covered T1
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - 1 - - - - - Covered T1,T2,T3
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - 0 - - - - - Covered T1,T2,T3
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 1 - - - - Covered T1,T2,T3
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0 - - - - Covered T1,T2,T3
DigPadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - Covered T1,T2,T3
DigPadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - Not Covered
DigFinSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - Covered T1,T2,T3
DigFinSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - Covered T1,T2,T3
DigWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - Covered T1,T2,T3
DigWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - Covered T1,T2,T3
ErrorSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 Covered T27,T28,T29
ErrorSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 Covered T2,T4,T7
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,T7
1 0 Covered T2,T4,T7
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,T5
0 1 - Covered T1,T2,T3
0 0 1 Covered T5,T11,T6
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 1133 1133 0 0
CheckNativeOtpWidth1_A 1133 1133 0 0
DaiIdleKnown_A 85678330 84858870 0 0
DaiRdataKnown_A 85678330 84858870 0 0
ErrorKnown_A 85678330 84858870 0 0
InitDoneKnown_A 85678330 84858870 0 0
OtpAddrKnown_A 85678330 84858870 0 0
OtpCmdKnown_A 85678330 84858870 0 0
OtpErrorState_A 85678330 337 0 0
OtpReqKnown_A 85678330 84858870 0 0
OtpSizeKnown_A 85678330 84858870 0 0
OtpWdataKnown_A 85678330 84858870 0 0
PartInitReqKnown_A 85678330 84858870 0 0
PartSelMustBeOnehot_A 85678330 84858870 0 0
ScrmblBlockWidthGe8_A 85678330 84858870 0 0
ScrmblCmdKnown_A 85678330 84858870 0 0
ScrmblDataKnown_A 85678330 84858870 0 0
ScrmblModeKnown_A 85678330 84858870 0 0
ScrmblMtxReqKnown_A 85678330 84858870 0 0
ScrmblSelKnown_A 85678330 84858870 0 0
ScrmblValidKnown_A 85678330 84858870 0 0
gen_part_sel[0].PartEndMax_A 1133 1133 0 0
gen_part_sel[10].PartEndMax_A 1133 1133 0 0
gen_part_sel[1].PartEndMax_A 1133 1133 0 0
gen_part_sel[2].PartEndMax_A 1133 1133 0 0
gen_part_sel[3].PartEndMax_A 1133 1133 0 0
gen_part_sel[4].PartEndMax_A 1133 1133 0 0
gen_part_sel[5].PartEndMax_A 1133 1133 0 0
gen_part_sel[6].PartEndMax_A 1133 1133 0 0
gen_part_sel[7].PartEndMax_A 1133 1133 0 0
gen_part_sel[8].PartEndMax_A 1133 1133 0 0
gen_part_sel[9].PartEndMax_A 1133 1133 0 0
u_state_regs_A 85678330 84858870 0 0


CheckNativeOtpWidth0_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1133 1133 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
T7 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

CheckNativeOtpWidth1_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1133 1133 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
T7 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

DaiIdleKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

DaiRdataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

ErrorKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

InitDoneKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

OtpAddrKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

OtpCmdKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

OtpErrorState_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 337 0 0
T8 39849 1 0 0
T9 0 1 0 0
T10 0 1 0 0
T17 41359 0 0 0
T70 73330 0 0 0
T94 94487 0 0 0
T95 12629 0 0 0
T114 37856 0 0 0
T115 61563 0 0 0
T122 27775 0 0 0
T124 25646 0 0 0
T134 104629 8 0 0
T146 0 1 0 0
T171 0 6 0 0
T175 0 3 0 0
T176 0 2 0 0
T177 0 1 0 0
T178 0 4 0 0

OtpReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

OtpSizeKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

OtpWdataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

PartInitReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

PartSelMustBeOnehot_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

ScrmblBlockWidthGe8_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

ScrmblCmdKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

ScrmblDataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

ScrmblModeKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

ScrmblMtxReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

ScrmblSelKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

ScrmblValidKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

gen_part_sel[0].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 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: T7 T67 T70  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 T11  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 T2 T3  300 1/1 scrmbl_mtx_req_o = 1'b1; Tests: T1 T2 T3  301 1/1 base_sel_d = PartOffset; Tests: T1 T2 T3  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 T5  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 T7 T12  330 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T6 T7 T12  331 1/1 dai_cmd_done_o = 1'b1; Tests: T6 T7 T12  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 T3 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: T7 T134 T70  359 end MISSING_ELSE 360 end else begin 361 1/1 state_d = ErrorSt; Tests: T8 T134 T146  362 1/1 error_d = otp_err; Tests: T8 T134 T146  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 T3 T5  381 1/1 scrmbl_valid_o = 1'b1; Tests: T2 T3 T5  382 1/1 scrmbl_cmd_o = Decrypt; Tests: T2 T3 T5  383 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T3 T5  384 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin Tests: T2 T3 T5  385 1/1 state_d = DescrWaitSt; Tests: T2 T3 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 T3 T5  394 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T3 T5  395 1/1 data_sel = ScrmblData; Tests: T2 T3 T5  396 1/1 if (scrmbl_valid_i) begin Tests: T2 T3 T5  397 1/1 state_d = IdleSt; Tests: T2 T3 T5  398 1/1 data_en = 1'b1; Tests: T2 T3 T5  399 1/1 dai_cmd_done_o = 1'b1; Tests: T2 T3 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 T11  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 T11 T6  434 1/1 state_d = IdleSt; Tests: T1 T11 T6  435 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T1 T11 T6  436 1/1 dai_cmd_done_o = 1'b1; Tests: T1 T11 T6  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: T8 T146 T9  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 T11  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 T11  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 T11  496 1/1 scrmbl_cmd_o = Encrypt; Tests: T2 T3 T11  497 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T3 T11  498 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin Tests: T2 T3 T11  499 1/1 state_d = ScrWaitSt; Tests: T2 T3 T11  500 end MISSING_ELSE 501 end else begin 502 1/1 state_d = IdleSt; Tests: T11 T6 T7  503 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T11 T6 T7  504 1/1 dai_cmd_done_o = 1'b1; Tests: T11 T6 T7  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 T11  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 T11  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 T11  520 1/1 if (scrmbl_valid_i) begin Tests: T2 T3 T11  521 1/1 state_d = WriteSt; Tests: T2 T3 T11  522 1/1 data_en = 1'b1; Tests: T2 T3 T11  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 T2 T3  537 1/1 scrmbl_valid_o = 1'b1; Tests: T1 T2 T3  538 // Need to reset the digest state and set digest mode to "standard". 539 1/1 scrmbl_cmd_o = DigestInit; Tests: T1 T2 T3  540 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin Tests: T1 T2 T3  541 1/1 state_d = DigReadSt; Tests: T1 T2 T3  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 T2 T3  550 1/1 if (part_sel_valid && Tests: T1 T2 T3  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 T2 T3  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 T2 T3  557 1/1 otp_cmd_o = prim_otp_pkg::Read; Tests: T1 T2 T3  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 T2 T3  562 1/1 state_d = DigReadWaitSt; Tests: T1 T2 T3  563 end MISSING_ELSE 564 end else begin 565 1/1 state_d = IdleSt; Tests: T6 T7 T12  566 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T6 T7 T12  567 1/1 dai_cmd_done_o = 1'b1; Tests: T6 T7 T12  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 T2 T3  578 1/1 if (otp_rvalid_i) begin Tests: T1 T2 T3  579 1/1 cnt_en = 1'b1; Tests: T1 T2 T3  580 // Check OTP return code. 581 1/1 if ((!(otp_err inside {NoError, MacroEccCorrError}))) begin Tests: T1 T2 T3  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 T2 T3  586 1/1 state_d = DigSt; Tests: T1 T2 T3  587 // Signal soft ECC errors, but do not go into terminal error state. 588 1/1 if (otp_err == MacroEccCorrError) begin Tests: T1 T2 T3  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 T2 T3  601 1/1 scrmbl_valid_o = 1'b1; Tests: T1 T2 T3  602 // No need to digest the digest value itself 603 1/1 if (otp_addr_o == digest_addr_lut[part_idx]) begin Tests: T1 T2 T3  604 // Trigger digest round in case this is the second block in a row. 605 1/1 if (!cnt[0]) begin Tests: T1 T2 T3  606 1/1 scrmbl_cmd_o = Digest; Tests: T1 T2 T3  607 1/1 if (scrmbl_ready_i) begin Tests: T1 T2 T3  608 1/1 state_d = DigFinSt; Tests: T1 T2 T3  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 T2 T3  612 1/1 state_d = DigPadSt; Tests: T1 T2 T3  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 T2 T3  617 1/1 scrmbl_cmd_o = Digest; Tests: T1 T2 T3  618 end MISSING_ELSE 619 // Go back and fetch more data blocks. 620 1/1 if (scrmbl_ready_i) begin Tests: T1 T2 T3  621 1/1 state_d = DigReadSt; Tests: T1 T2 T3  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 T2 T3  631 1/1 scrmbl_valid_o = 1'b1; Tests: T1 T2 T3  632 1/1 scrmbl_cmd_o = Digest; Tests: T1 T2 T3  633 1/1 if (scrmbl_ready_i) begin Tests: T1 T2 T3  634 1/1 state_d = DigFinSt; Tests: T1 T2 T3  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 T2 T3  642 1/1 scrmbl_valid_o = 1'b1; Tests: T1 T2 T3  643 1/1 scrmbl_cmd_o = DigestFinalize; Tests: T1 T2 T3  644 1/1 if (scrmbl_ready_i) begin Tests: T1 T2 T3  645 1/1 state_d = DigWaitSt; Tests: T1 T2 T3  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 T2 T3  657 1/1 data_sel = ScrmblData; Tests: T1 T2 T3  658 1/1 if (scrmbl_valid_i) begin Tests: T1 T2 T3  659 1/1 state_d = WriteSt; Tests: T1 T2 T3  660 1/1 data_en = 1'b1; Tests: T1 T2 T3  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 T7  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 T7  686 1/1 fsm_err_o = 1'b1; Tests: T2 T4 T7  687 1/1 if (state_q != ErrorSt) begin Tests: T2 T4 T7  688 1/1 error_d = FsmStateError; Tests: T2 T4 T7  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 T5  759 1/1 addr_base = {dai_addr_i[OtpByteAddrWidth-1:3], 3'h0}; Tests: T2 T3 T5  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 T2 T3  763 1/1 addr_base = PartInfo[part_idx].offset; Tests: T1 T2 T3  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: T5 T11 T6  769 1/1 addr_base = {dai_addr_i[OtpByteAddrWidth-1:3], 3'h0}; Tests: T5 T11 T6  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
01CoveredT7,T8,T134
10CoveredT1,T2,T3
11CoveredT7,T67,T70

 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
10CoveredT5,T6,T12
11CoveredT2,T3,T5

 LINE       350
 SUB-EXPRESSION (otp_addr_o != digest_addr_lut[part_idx])
                --------------------1--------------------
-1-StatusTests
0CoveredT5,T6,T7
1CoveredT1,T2,T3

 LINE       357
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT7,T134,T70

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

 LINE       467
 EXPRESSION (otp_err == MacroWriteBlankError)
            ----------------1----------------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT8,T146,T9

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

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

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

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

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

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

 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,T3,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,T5

 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,T3,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,T5
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,T5
11CoveredT2,T3,T5

 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,T5
11CoveredT2,T3,T5

 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,T3,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
10CoveredT8,T9,T10
11CoveredT2,T3,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
11CoveredT8,T9,T10

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

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

 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
011CoveredT147,T148,T149
101CoveredT14,T26,T150
110CoveredT1,T2,T3
111CoveredT5,T11,T6

 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
00CoveredT8,T9,T10
01CoveredT1,T2,T3
10CoveredT2,T3,T5

 LINE       765
 SUB-EXPRESSION (base_sel_q == DaiOffset)
                ------------1------------
-1-StatusTests
0CoveredT1,T84,T51
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
1CoveredT5,T11,T6

 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 41 85.42
Sequences 0 0

State, Transition and Sequence Details for FSM :: state_q
statesLine No.CoveredTests
DescrSt 351 Covered T2,T3,T5
DescrWaitSt 385 Covered T2,T3,T5
DigClrSt 299 Covered T1,T2,T3
DigFinSt 608 Covered T1,T2,T3
DigPadSt 612 Covered T1,T2,T3
DigReadSt 541 Covered T1,T2,T3
DigReadWaitSt 562 Covered T1,T2,T3
DigSt 586 Covered T1,T2,T3
DigWaitSt 645 Covered T1,T2,T3
ErrorSt 251 Covered T2,T4,T7
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,T11
ScrWaitSt 499 Covered T2,T3,T11
WriteSt 295 Covered T1,T2,T3
WriteWaitSt 429 Covered T1,T2,T3


transitionsLine No.CoveredTests
DescrSt->DescrWaitSt 385 Covered T2,T3,T5
DescrSt->ErrorSt 685 Covered T151
DescrWaitSt->ErrorSt 685 Not Covered
DescrWaitSt->IdleSt 397 Covered T2,T3,T5
DigClrSt->DigReadSt 541 Covered T1,T2,T3
DigClrSt->ErrorSt 685 Not Covered
DigFinSt->DigWaitSt 645 Covered T1,T2,T3
DigFinSt->ErrorSt 685 Covered T149,T152,T153
DigPadSt->DigFinSt 634 Covered T1,T2,T3
DigPadSt->ErrorSt 685 Not Covered
DigReadSt->DigReadWaitSt 562 Covered T1,T2,T3
DigReadSt->ErrorSt 685 Covered T154
DigReadSt->IdleSt 565 Covered T6,T7,T12
DigReadWaitSt->DigSt 586 Covered T1,T2,T3
DigReadWaitSt->ErrorSt 582 Covered T155,T156,T157
DigSt->DigFinSt 608 Covered T1,T2,T3
DigSt->DigPadSt 612 Covered T1,T2,T3
DigSt->DigReadSt 621 Covered T1,T2,T3
DigSt->ErrorSt 685 Covered T158,T159,T160
DigWaitSt->ErrorSt 685 Covered T161,T162,T163
DigWaitSt->WriteSt 659 Covered T1,T2,T3
IdleSt->DigClrSt 299 Covered T1,T2,T3
IdleSt->ErrorSt 685 Covered T4,T7,T12
IdleSt->ReadSt 281 Covered T1,T2,T3
IdleSt->ScrSt 293 Covered T2,T3,T11
IdleSt->WriteSt 295 Covered T1,T2,T3
InitOtpSt->ErrorSt 251 Covered T164,T165
InitOtpSt->InitPartSt 254 Covered T1,T2,T3
InitPartSt->ErrorSt 685 Covered T2,T67,T95
InitPartSt->IdleSt 267 Covered T1,T2,T3
ReadSt->ErrorSt 685 Not Covered
ReadSt->IdleSt 329 Covered T6,T7,T12
ReadSt->ReadWaitSt 326 Covered T1,T2,T3
ReadWaitSt->DescrSt 351 Covered T2,T3,T5
ReadWaitSt->ErrorSt 361 Covered T8,T134,T146
ReadWaitSt->IdleSt 353 Covered T1,T2,T3
ResetSt->ErrorSt 685 Covered T101,T102,T103
ResetSt->InitOtpSt 238 Covered T1,T2,T3
ScrSt->ErrorSt 685 Not Covered
ScrSt->IdleSt 502 Covered T11,T6,T7
ScrSt->ScrWaitSt 499 Covered T2,T3,T11
ScrWaitSt->ErrorSt 528 Not Covered
ScrWaitSt->WriteSt 521 Covered T2,T3,T11
WriteSt->ErrorSt 685 Not Covered
WriteSt->IdleSt 434 Covered T1,T11,T6
WriteSt->WriteWaitSt 429 Covered T1,T2,T3
WriteWaitSt->ErrorSt 459 Covered T166,T167,T168
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,T11,T6
FsmStateError 370 Covered T2,T4,T7
MacroEccCorrError 358 Covered T7,T134,T70
NoError 172 Covered T1,T2,T3


transitionsLine No.CoveredTestsExclude Annotation
AccessError->FsmStateError 370 Covered T169,T170,T22
AccessError->MacroEccCorrError 358 Excluded VC_COV_UNR
AccessError->NoError 172 Covered T1,T11,T6
FsmStateError->AccessError 330 Excluded VC_COV_UNR
FsmStateError->MacroEccCorrError 358 Excluded VC_COV_UNR
FsmStateError->NoError 172 Covered T2,T4,T7
MacroEccCorrError->AccessError 330 Not Covered
MacroEccCorrError->FsmStateError 370 Covered T171,T172,T173
MacroEccCorrError->NoError 172 Covered T7,T134,T70
NoError->AccessError 330 Covered T1,T11,T6
NoError->FsmStateError 370 Covered T2,T4,T7
NoError->MacroEccCorrError 358 Covered T7,T134,T70



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 T7,T67,T70
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,T11
IdleSt - - - - - 1 DaiWrite 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
IdleSt - - - - - 1 DaiDigest - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
IdleSt - - - - - 1 default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Not Covered
IdleSt - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadSt - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadSt - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T5
ReadSt - - - - - - - - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadSt - - - - - - - - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T6,T115,T118
ReadSt - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T6,T7,T12
ReadWaitSt - - - - - - - - - - - 1 1 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T5
ReadWaitSt - - - - - - - - - - - 1 1 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 1 1 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T7,T134,T70
ReadWaitSt - - - - - - - - - - - 1 1 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 1 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T8,T134,T146
ReadWaitSt - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Not Covered
DescrSt - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T5
DescrSt - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T117,T119,T123
DescrWaitSt - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T5
DescrWaitSt - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T5
WriteSt - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
WriteSt - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T11
WriteSt - - - - - - - - - - - - - - - - - - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
WriteSt - - - - - - - - - - - - - - - - - - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T6,T115,T118
WriteSt - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T11,T6
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 1 1 1 - - - - - - - - - - - - - - - - - - - - - - Excluded VC_COV_UNR
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 1 1 0 1 - - - - - - - - - - - - - - - - - - - - - Covered T8,T146,T9
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,T11
ScrSt - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - Covered T117,T119,T174
ScrSt - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - Covered T11,T6,T7
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - Covered T2,T3,T11
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - Covered T2,T3,T11
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - Not Covered
DigClrSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - Covered T1,T2,T3
DigClrSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - Covered T117,T119,T123
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - Covered T1,T2,T3
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - Not Covered
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 1 - - - - - - - - - - - - - Covered T1,T2,T3
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 0 - - - - - - - - - - - - - Covered T6,T115,T118
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - Covered T6,T7,T12
DigReadWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - Not Covered
DigReadWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 1 - - - - - - - - - - Not Covered
DigReadWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 0 - - - - - - - - - - Covered T1,T2,T3
DigReadWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - Covered T1,T2,T3
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 1 - - - - - - - Covered T1,T2,T3
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 0 - - - - - - - Not Covered
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - 1 - - - - - - Covered T1,T2,T3
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - 0 - - - - - - Covered T1
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - 1 - - - - - Covered T1,T2,T3
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - 0 - - - - - Covered T1,T2,T3
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 1 - - - - Covered T1,T2,T3
DigSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - 0 - - - - Covered T1,T2,T3
DigPadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - Covered T1,T2,T3
DigPadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - Not Covered
DigFinSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - Covered T1,T2,T3
DigFinSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - Covered T1,T2,T3
DigWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - Covered T1,T2,T3
DigWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - Covered T1,T2,T3
ErrorSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 Covered T27,T28,T29
ErrorSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 Covered T2,T4,T7
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,T7
1 0 Covered T2,T4,T7
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,T5
0 1 - Covered T1,T2,T3
0 0 1 Covered T5,T11,T6
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 1133 1133 0 0
CheckNativeOtpWidth1_A 1133 1133 0 0
DaiIdleKnown_A 85678330 84858870 0 0
DaiRdataKnown_A 85678330 84858870 0 0
ErrorKnown_A 85678330 84858870 0 0
InitDoneKnown_A 85678330 84858870 0 0
OtpAddrKnown_A 85678330 84858870 0 0
OtpCmdKnown_A 85678330 84858870 0 0
OtpErrorState_A 85678330 337 0 0
OtpReqKnown_A 85678330 84858870 0 0
OtpSizeKnown_A 85678330 84858870 0 0
OtpWdataKnown_A 85678330 84858870 0 0
PartInitReqKnown_A 85678330 84858870 0 0
PartSelMustBeOnehot_A 85678330 84858870 0 0
ScrmblBlockWidthGe8_A 85678330 84858870 0 0
ScrmblCmdKnown_A 85678330 84858870 0 0
ScrmblDataKnown_A 85678330 84858870 0 0
ScrmblModeKnown_A 85678330 84858870 0 0
ScrmblMtxReqKnown_A 85678330 84858870 0 0
ScrmblSelKnown_A 85678330 84858870 0 0
ScrmblValidKnown_A 85678330 84858870 0 0
gen_part_sel[0].PartEndMax_A 1133 1133 0 0
gen_part_sel[10].PartEndMax_A 1133 1133 0 0
gen_part_sel[1].PartEndMax_A 1133 1133 0 0
gen_part_sel[2].PartEndMax_A 1133 1133 0 0
gen_part_sel[3].PartEndMax_A 1133 1133 0 0
gen_part_sel[4].PartEndMax_A 1133 1133 0 0
gen_part_sel[5].PartEndMax_A 1133 1133 0 0
gen_part_sel[6].PartEndMax_A 1133 1133 0 0
gen_part_sel[7].PartEndMax_A 1133 1133 0 0
gen_part_sel[8].PartEndMax_A 1133 1133 0 0
gen_part_sel[9].PartEndMax_A 1133 1133 0 0
u_state_regs_A 85678330 84858870 0 0


CheckNativeOtpWidth0_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1133 1133 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
T7 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

CheckNativeOtpWidth1_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1133 1133 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
T7 1 1 0 0
T11 1 1 0 0
T12 1 1 0 0
T13 1 1 0 0

DaiIdleKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

DaiRdataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

ErrorKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

InitDoneKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

OtpAddrKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

OtpCmdKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

OtpErrorState_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 337 0 0
T8 39849 1 0 0
T9 0 1 0 0
T10 0 1 0 0
T17 41359 0 0 0
T70 73330 0 0 0
T94 94487 0 0 0
T95 12629 0 0 0
T114 37856 0 0 0
T115 61563 0 0 0
T122 27775 0 0 0
T124 25646 0 0 0
T134 104629 8 0 0
T146 0 1 0 0
T171 0 6 0 0
T175 0 3 0 0
T176 0 2 0 0
T177 0 1 0 0
T178 0 4 0 0

OtpReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

OtpSizeKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

OtpWdataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

PartInitReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

PartSelMustBeOnehot_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

ScrmblBlockWidthGe8_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

ScrmblCmdKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

ScrmblDataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

ScrmblModeKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

ScrmblMtxReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

ScrmblSelKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

ScrmblValidKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

gen_part_sel[0].PartEndMax_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 1133 1133 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
T7 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 85678330 84858870 0 0
T1 4777 4704 0 0
T2 17606 17368 0 0
T3 41714 41314 0 0
T4 16441 16195 0 0
T5 44101 44038 0 0
T6 76674 75266 0 0
T7 27615 27088 0 0
T11 59805 59708 0 0
T12 121869 120872 0 0
T13 4557 4490 0 0

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