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



Module Instance : tb.dut.u_otp_ctrl_dai

Instance :
SCORELINECONDTOGGLEFSMBRANCHASSERT
92.68 95.88 95.06 82.46 90.00 100.00


Instance's subtree :
SCORELINECONDTOGGLEFSMBRANCHASSERT
89.50 85.64 91.96 100.00 82.46 89.73 87.23


Parent :
SCORELINECONDTOGGLEFSMBRANCHASSERTNAME
96.15 94.16 96.15 96.81 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: T13 T103 T29  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 T6  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: T3 T6 T10  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: T4 T5 T11  330 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T4 T5 T11  331 1/1 dai_cmd_done_o = 1'b1; Tests: T4 T5 T11  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 T6  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: T13 T7 T111  359 end MISSING_ELSE 360 end else begin 361 1/1 state_d = ErrorSt; Tests: T7 T103 T111  362 1/1 error_d = otp_err; Tests: T7 T103 T111  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 T6  381 1/1 scrmbl_valid_o = 1'b1; Tests: T2 T3 T6  382 1/1 scrmbl_cmd_o = Decrypt; Tests: T2 T3 T6  383 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T3 T6  384 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin Tests: T2 T3 T6  385 1/1 state_d = DescrWaitSt; Tests: T2 T3 T6  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 T6  394 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T3 T6  395 1/1 data_sel = ScrmblData; Tests: T2 T3 T6  396 1/1 if (scrmbl_valid_i) begin Tests: T2 T3 T6  397 1/1 state_d = IdleSt; Tests: T2 T3 T6  398 1/1 data_en = 1'b1; Tests: T2 T3 T6  399 1/1 dai_cmd_done_o = 1'b1; Tests: T2 T3 T6  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: T3 T6 T4  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 T6 T4  434 1/1 state_d = IdleSt; Tests: T1 T6 T4  435 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T1 T6 T4  436 1/1 dai_cmd_done_o = 1'b1; Tests: T1 T6 T4  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: T7 T137 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 T6  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 T6  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 T6  496 1/1 scrmbl_cmd_o = Encrypt; Tests: T2 T3 T6  497 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T3 T6  498 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin Tests: T2 T3 T6  499 1/1 state_d = ScrWaitSt; Tests: T2 T3 T6  500 end MISSING_ELSE 501 end else begin 502 1/1 state_d = IdleSt; Tests: T6 T4 T5  503 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T6 T4 T5  504 1/1 dai_cmd_done_o = 1'b1; Tests: T6 T4 T5  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 T6  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 T6  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 T6  520 1/1 if (scrmbl_valid_i) begin Tests: T2 T3 T6  521 1/1 state_d = WriteSt; Tests: T2 T3 T6  522 1/1 data_en = 1'b1; Tests: T2 T3 T6  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: T4 T5 T11  566 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T4 T5 T11  567 1/1 dai_cmd_done_o = 1'b1; Tests: T4 T5 T11  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: T3 T4 T12  669 1/1 error_d = FsmStateError; Tests: T23 T24 T25  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: T3 T4 T12  686 1/1 fsm_err_o = 1'b1; Tests: T3 T4 T12  687 1/1 if (state_q != ErrorSt) begin Tests: T3 T4 T12  688 1/1 error_d = FsmStateError; Tests: T3 T4 T12  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 T6  759 1/1 addr_base = {dai_addr_i[OtpByteAddrWidth-1:3], 3'h0}; Tests: T2 T3 T6  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: T6 T10 T4  769 1/1 addr_base = {dai_addr_i[OtpByteAddrWidth-1:3], 3'h0}; Tests: T6 T10 T4  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
01CoveredT13,T7,T103
10CoveredT1,T2,T3
11CoveredT13,T103,T29

 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
10CoveredT10,T11,T13
11CoveredT2,T3,T6

 LINE       350
 SUB-EXPRESSION (otp_addr_o != digest_addr_lut[part_idx])
                --------------------1--------------------
-1-StatusTests
0CoveredT10,T4,T5
1CoveredT1,T2,T3

 LINE       357
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT13,T7,T111

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

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

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

 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
0CoveredT3,T4,T12
1CoveredT23,T24,T25

 LINE       687
 EXPRESSION (state_q != ErrorSt)
            ----------1---------
-1-StatusTests
0CoveredT3,T4,T12
1CoveredT3,T4,T12

 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
11CoveredT3,T6,T10

 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,T6

 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
11CoveredT3,T6,T10

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

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

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

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

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

 LINE       761
 EXPRESSION (otp_ctrl_part_pkg::PartInfo[part_idx].hw_digest && (base_sel_q == PartOffset))
             -----------------------1-----------------------    -------------2------------
-1--2-StatusTests
01CoveredT1,T8,T14
10CoveredT2,T3,T6
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
011CoveredT138,T139,T140
101CoveredT21,T141,T22
110CoveredT1,T2,T3
111CoveredT6,T10,T4

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

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

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

 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 39 81.25
Sequences 0 0

State, Transition and Sequence Details for FSM :: state_q
statesLine No.CoveredTests
DescrSt 351 Covered T2,T3,T6
DescrWaitSt 385 Covered T2,T3,T6
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 T3,T4,T12
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,T6
ScrWaitSt 499 Covered T2,T3,T6
WriteSt 295 Covered T1,T2,T3
WriteWaitSt 429 Covered T1,T2,T3


transitionsLine No.CoveredTests
DescrSt->DescrWaitSt 385 Covered T2,T3,T6
DescrSt->ErrorSt 685 Not Covered
DescrWaitSt->ErrorSt 685 Covered T142,T143
DescrWaitSt->IdleSt 397 Covered T2,T3,T6
DigClrSt->DigReadSt 541 Covered T1,T2,T3
DigClrSt->ErrorSt 685 Not Covered
DigFinSt->DigWaitSt 645 Covered T1,T2,T3
DigFinSt->ErrorSt 685 Covered T121,T144,T145
DigPadSt->DigFinSt 634 Covered T1,T2,T3
DigPadSt->ErrorSt 685 Not Covered
DigReadSt->DigReadWaitSt 562 Covered T1,T2,T3
DigReadSt->ErrorSt 685 Not Covered
DigReadSt->IdleSt 565 Covered T4,T5,T11
DigReadWaitSt->DigSt 586 Covered T1,T2,T3
DigReadWaitSt->ErrorSt 582 Covered T109,T146,T147
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 T148,T149,T150
DigWaitSt->ErrorSt 685 Covered T151,T94,T152
DigWaitSt->WriteSt 659 Covered T1,T2,T3
IdleSt->DigClrSt 299 Covered T1,T2,T3
IdleSt->ErrorSt 685 Covered T4,T12,T13
IdleSt->ReadSt 281 Covered T1,T2,T3
IdleSt->ScrSt 293 Covered T2,T3,T6
IdleSt->WriteSt 295 Covered T1,T2,T3
InitOtpSt->ErrorSt 251 Covered T98,T153
InitOtpSt->InitPartSt 254 Covered T1,T2,T3
InitPartSt->ErrorSt 685 Covered T3,T29,T92
InitPartSt->IdleSt 267 Covered T1,T2,T3
ReadSt->ErrorSt 685 Not Covered
ReadSt->IdleSt 329 Covered T4,T5,T11
ReadSt->ReadWaitSt 326 Covered T1,T2,T3
ReadWaitSt->DescrSt 351 Covered T2,T3,T6
ReadWaitSt->ErrorSt 361 Covered T7,T103,T110
ReadWaitSt->IdleSt 353 Covered T1,T2,T3
ResetSt->ErrorSt 685 Covered T97,T154,T155
ResetSt->InitOtpSt 238 Covered T1,T2,T3
ScrSt->ErrorSt 685 Not Covered
ScrSt->IdleSt 502 Covered T6,T4,T5
ScrSt->ScrWaitSt 499 Covered T2,T3,T6
ScrWaitSt->ErrorSt 528 Not Covered
ScrWaitSt->WriteSt 521 Covered T2,T3,T6
WriteSt->ErrorSt 685 Not Covered
WriteSt->IdleSt 434 Covered T1,T6,T4
WriteSt->WriteWaitSt 429 Covered T1,T2,T3
WriteWaitSt->ErrorSt 459 Not Covered
WriteWaitSt->IdleSt 464 Covered T1,T2,T3


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

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


transitionsLine No.CoveredTests
AccessError->FsmStateError 370 Covered T12,T14,T21
AccessError->MacroEccCorrError 358 Not Covered
AccessError->NoError 172 Covered T1,T6,T4
FsmStateError->AccessError 330 Not Covered
FsmStateError->MacroEccCorrError 358 Not Covered
FsmStateError->NoError 172 Covered T3,T4,T12
MacroEccCorrError->AccessError 330 Not Covered
MacroEccCorrError->FsmStateError 370 Covered T156,T157,T158
MacroEccCorrError->NoError 172 Covered T13,T7,T111
NoError->AccessError 330 Covered T1,T6,T4
NoError->FsmStateError 370 Covered T3,T4,T13
NoError->MacroEccCorrError 358 Covered T13,T7,T111



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 T13,T103,T29
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,T6
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 T3,T6,T10
ReadSt - - - - - - - - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadSt - - - - - - - - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T5,T106,T125
ReadSt - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,T5,T11
ReadWaitSt - - - - - - - - - - - 1 1 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T6
ReadWaitSt - - - - - - - - - - - 1 1 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 1 1 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T13,T7,T111
ReadWaitSt - - - - - - - - - - - 1 1 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 1 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T7,T103,T111
ReadWaitSt - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Not Covered
DescrSt - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T6
DescrSt - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T105,T107,T159
DescrWaitSt - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T6
DescrWaitSt - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T6
WriteSt - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
WriteSt - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T3,T6,T4
WriteSt - - - - - - - - - - - - - - - - - - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
WriteSt - - - - - - - - - - - - - - - - - - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T5,T106,T125
WriteSt - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T6,T4
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 1 1 1 - - - - - - - - - - - - - - - - - - - - - - Not Covered
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 1 1 0 1 - - - - - - - - - - - - - - - - - - - - - Covered T7,T137,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,T6
ScrSt - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - Covered T105,T107,T159
ScrSt - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - Covered T6,T4,T5
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - Covered T2,T3,T6
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - Covered T2,T3,T6
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - Not Covered
DigClrSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - Covered T1,T2,T3
DigClrSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - Covered T105,T107,T109
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - Covered T1,T2,T3
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - Not Covered
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 1 - - - - - - - - - - - - - Covered T1,T2,T3
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 0 - - - - - - - - - - - - - Covered T5,T106,T160
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - Covered T4,T5,T11
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 T23,T24,T25
ErrorSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 Covered T3,T4,T12
default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T23,T24,T25


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 T3,T4,T12
1 0 Covered T3,T4,T12
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,T6
0 1 - Covered T1,T2,T3
0 0 1 Covered T6,T10,T4
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 1120 1120 0 0
CheckNativeOtpWidth1_A 1120 1120 0 0
DaiIdleKnown_A 95995079 95123308 0 0
DaiRdataKnown_A 95995079 95123308 0 0
ErrorKnown_A 95995079 95123308 0 0
InitDoneKnown_A 95995079 95123308 0 0
OtpAddrKnown_A 95995079 95123308 0 0
OtpCmdKnown_A 95995079 95123308 0 0
OtpErrorState_A 95995079 325 0 0
OtpReqKnown_A 95995079 95123308 0 0
OtpSizeKnown_A 95995079 95123308 0 0
OtpWdataKnown_A 95995079 95123308 0 0
PartInitReqKnown_A 95995079 95123308 0 0
PartSelMustBeOnehot_A 95995079 95123308 0 0
ScrmblBlockWidthGe8_A 95995079 95123308 0 0
ScrmblCmdKnown_A 95995079 95123308 0 0
ScrmblDataKnown_A 95995079 95123308 0 0
ScrmblModeKnown_A 95995079 95123308 0 0
ScrmblMtxReqKnown_A 95995079 95123308 0 0
ScrmblSelKnown_A 95995079 95123308 0 0
ScrmblValidKnown_A 95995079 95123308 0 0
gen_part_sel[0].PartEndMax_A 1120 1120 0 0
gen_part_sel[10].PartEndMax_A 1120 1120 0 0
gen_part_sel[1].PartEndMax_A 1120 1120 0 0
gen_part_sel[2].PartEndMax_A 1120 1120 0 0
gen_part_sel[3].PartEndMax_A 1120 1120 0 0
gen_part_sel[4].PartEndMax_A 1120 1120 0 0
gen_part_sel[5].PartEndMax_A 1120 1120 0 0
gen_part_sel[6].PartEndMax_A 1120 1120 0 0
gen_part_sel[7].PartEndMax_A 1120 1120 0 0
gen_part_sel[8].PartEndMax_A 1120 1120 0 0
gen_part_sel[9].PartEndMax_A 1120 1120 0 0
u_state_regs_A 95995079 95123308 0 0


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

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

DaiIdleKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

DaiRdataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

ErrorKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

InitDoneKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

OtpAddrKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

OtpCmdKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

OtpErrorState_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 325 0 0
T7 111593 1 0 0
T9 0 1 0 0
T16 0 1 0 0
T17 7426 0 0 0
T18 123084 0 0 0
T29 11450 0 0 0
T90 7244 0 0 0
T93 66768 0 0 0
T103 118648 1 0 0
T104 21552 0 0 0
T105 52425 0 0 0
T106 71675 0 0 0
T111 0 4 0 0
T113 0 1 0 0
T137 0 1 0 0
T161 0 2 0 0
T162 0 4 0 0
T163 0 1 0 0

OtpReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

OtpSizeKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

OtpWdataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

PartInitReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

PartSelMustBeOnehot_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

ScrmblBlockWidthGe8_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

ScrmblCmdKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

ScrmblDataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

ScrmblModeKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

ScrmblMtxReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

ScrmblSelKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

ScrmblValidKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

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

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

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

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

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

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

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

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

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

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

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

u_state_regs_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 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: T13 T103 T29  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 T6  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: T3 T6 T10  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: T4 T5 T11  330 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T4 T5 T11  331 1/1 dai_cmd_done_o = 1'b1; Tests: T4 T5 T11  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 T6  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: T13 T7 T111  359 end MISSING_ELSE 360 end else begin 361 1/1 state_d = ErrorSt; Tests: T7 T103 T111  362 1/1 error_d = otp_err; Tests: T7 T103 T111  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 T6  381 1/1 scrmbl_valid_o = 1'b1; Tests: T2 T3 T6  382 1/1 scrmbl_cmd_o = Decrypt; Tests: T2 T3 T6  383 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T3 T6  384 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin Tests: T2 T3 T6  385 1/1 state_d = DescrWaitSt; Tests: T2 T3 T6  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 T6  394 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T3 T6  395 1/1 data_sel = ScrmblData; Tests: T2 T3 T6  396 1/1 if (scrmbl_valid_i) begin Tests: T2 T3 T6  397 1/1 state_d = IdleSt; Tests: T2 T3 T6  398 1/1 data_en = 1'b1; Tests: T2 T3 T6  399 1/1 dai_cmd_done_o = 1'b1; Tests: T2 T3 T6  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: T3 T6 T4  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 T6 T4  434 1/1 state_d = IdleSt; Tests: T1 T6 T4  435 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T1 T6 T4  436 1/1 dai_cmd_done_o = 1'b1; Tests: T1 T6 T4  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: T7 T137 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 T6  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 T6  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 T6  496 1/1 scrmbl_cmd_o = Encrypt; Tests: T2 T3 T6  497 1/1 scrmbl_sel_o = PartInfo[part_idx].key_sel; Tests: T2 T3 T6  498 1/1 if (scrmbl_mtx_gnt_i && scrmbl_ready_i) begin Tests: T2 T3 T6  499 1/1 state_d = ScrWaitSt; Tests: T2 T3 T6  500 end MISSING_ELSE 501 end else begin 502 1/1 state_d = IdleSt; Tests: T6 T4 T5  503 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T6 T4 T5  504 1/1 dai_cmd_done_o = 1'b1; Tests: T6 T4 T5  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 T6  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 T6  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 T6  520 1/1 if (scrmbl_valid_i) begin Tests: T2 T3 T6  521 1/1 state_d = WriteSt; Tests: T2 T3 T6  522 1/1 data_en = 1'b1; Tests: T2 T3 T6  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: T4 T5 T11  566 1/1 error_d = AccessError; // Signal this error, but do not go into terminal error state. Tests: T4 T5 T11  567 1/1 dai_cmd_done_o = 1'b1; Tests: T4 T5 T11  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: T3 T4 T12  669 1/1 error_d = FsmStateError; Tests: T23 T24 T25  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: T3 T4 T12  686 1/1 fsm_err_o = 1'b1; Tests: T3 T4 T12  687 1/1 if (state_q != ErrorSt) begin Tests: T3 T4 T12  688 1/1 error_d = FsmStateError; Tests: T3 T4 T12  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 T6  759 1/1 addr_base = {dai_addr_i[OtpByteAddrWidth-1:3], 3'h0}; Tests: T2 T3 T6  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: T6 T10 T4  769 1/1 addr_base = {dai_addr_i[OtpByteAddrWidth-1:3], 3'h0}; Tests: T6 T10 T4  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
01CoveredT13,T7,T103
10CoveredT1,T2,T3
11CoveredT13,T103,T29

 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
10CoveredT10,T11,T13
11CoveredT2,T3,T6

 LINE       350
 SUB-EXPRESSION (otp_addr_o != digest_addr_lut[part_idx])
                --------------------1--------------------
-1-StatusTests
0CoveredT10,T4,T5
1CoveredT1,T2,T3

 LINE       357
 EXPRESSION (otp_err != NoError)
            ----------1---------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT13,T7,T111

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

 LINE       467
 EXPRESSION (otp_err == MacroWriteBlankError)
            ----------------1----------------
-1-StatusTests
0CoveredT1,T2,T3
1CoveredT7,T137,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,T6

 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
0CoveredT3,T4,T12
1CoveredT23,T24,T25

 LINE       687
 EXPRESSION (state_q != ErrorSt)
            ----------1---------
-1-StatusTests
0CoveredT3,T4,T12
1CoveredT3,T4,T12

 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
11CoveredT3,T6,T10

 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,T6

 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
11CoveredT3,T6,T10

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

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

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

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

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

 LINE       761
 EXPRESSION (otp_ctrl_part_pkg::PartInfo[part_idx].hw_digest && (base_sel_q == PartOffset))
             -----------------------1-----------------------    -------------2------------
-1--2-StatusTests
01CoveredT1,T8,T14
10CoveredT2,T3,T6
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
011CoveredT138,T139,T140
101CoveredT21,T141,T22
110CoveredT1,T2,T3
111CoveredT6,T10,T4

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

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

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

 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 39 81.25
Sequences 0 0

State, Transition and Sequence Details for FSM :: state_q
statesLine No.CoveredTests
DescrSt 351 Covered T2,T3,T6
DescrWaitSt 385 Covered T2,T3,T6
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 T3,T4,T12
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,T6
ScrWaitSt 499 Covered T2,T3,T6
WriteSt 295 Covered T1,T2,T3
WriteWaitSt 429 Covered T1,T2,T3


transitionsLine No.CoveredTests
DescrSt->DescrWaitSt 385 Covered T2,T3,T6
DescrSt->ErrorSt 685 Not Covered
DescrWaitSt->ErrorSt 685 Covered T142,T143
DescrWaitSt->IdleSt 397 Covered T2,T3,T6
DigClrSt->DigReadSt 541 Covered T1,T2,T3
DigClrSt->ErrorSt 685 Not Covered
DigFinSt->DigWaitSt 645 Covered T1,T2,T3
DigFinSt->ErrorSt 685 Covered T121,T144,T145
DigPadSt->DigFinSt 634 Covered T1,T2,T3
DigPadSt->ErrorSt 685 Not Covered
DigReadSt->DigReadWaitSt 562 Covered T1,T2,T3
DigReadSt->ErrorSt 685 Not Covered
DigReadSt->IdleSt 565 Covered T4,T5,T11
DigReadWaitSt->DigSt 586 Covered T1,T2,T3
DigReadWaitSt->ErrorSt 582 Covered T109,T146,T147
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 T148,T149,T150
DigWaitSt->ErrorSt 685 Covered T151,T94,T152
DigWaitSt->WriteSt 659 Covered T1,T2,T3
IdleSt->DigClrSt 299 Covered T1,T2,T3
IdleSt->ErrorSt 685 Covered T4,T12,T13
IdleSt->ReadSt 281 Covered T1,T2,T3
IdleSt->ScrSt 293 Covered T2,T3,T6
IdleSt->WriteSt 295 Covered T1,T2,T3
InitOtpSt->ErrorSt 251 Covered T98,T153
InitOtpSt->InitPartSt 254 Covered T1,T2,T3
InitPartSt->ErrorSt 685 Covered T3,T29,T92
InitPartSt->IdleSt 267 Covered T1,T2,T3
ReadSt->ErrorSt 685 Not Covered
ReadSt->IdleSt 329 Covered T4,T5,T11
ReadSt->ReadWaitSt 326 Covered T1,T2,T3
ReadWaitSt->DescrSt 351 Covered T2,T3,T6
ReadWaitSt->ErrorSt 361 Covered T7,T103,T110
ReadWaitSt->IdleSt 353 Covered T1,T2,T3
ResetSt->ErrorSt 685 Covered T97,T154,T155
ResetSt->InitOtpSt 238 Covered T1,T2,T3
ScrSt->ErrorSt 685 Not Covered
ScrSt->IdleSt 502 Covered T6,T4,T5
ScrSt->ScrWaitSt 499 Covered T2,T3,T6
ScrWaitSt->ErrorSt 528 Not Covered
ScrWaitSt->WriteSt 521 Covered T2,T3,T6
WriteSt->ErrorSt 685 Not Covered
WriteSt->IdleSt 434 Covered T1,T6,T4
WriteSt->WriteWaitSt 429 Covered T1,T2,T3
WriteWaitSt->ErrorSt 459 Not Covered
WriteWaitSt->IdleSt 464 Covered T1,T2,T3


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

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


transitionsLine No.CoveredTestsExclude Annotation
AccessError->FsmStateError 370 Covered T12,T14,T21
AccessError->MacroEccCorrError 358 Excluded VC_COV_UNR
AccessError->NoError 172 Covered T1,T6,T4
FsmStateError->AccessError 330 Excluded VC_COV_UNR
FsmStateError->MacroEccCorrError 358 Excluded VC_COV_UNR
FsmStateError->NoError 172 Covered T3,T4,T12
MacroEccCorrError->AccessError 330 Not Covered
MacroEccCorrError->FsmStateError 370 Covered T156,T157,T158
MacroEccCorrError->NoError 172 Covered T13,T7,T111
NoError->AccessError 330 Covered T1,T6,T4
NoError->FsmStateError 370 Covered T3,T4,T13
NoError->MacroEccCorrError 358 Covered T13,T7,T111



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 T13,T103,T29
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,T6
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 T3,T6,T10
ReadSt - - - - - - - - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadSt - - - - - - - - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T5,T106,T125
ReadSt - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T4,T5,T11
ReadWaitSt - - - - - - - - - - - 1 1 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T6
ReadWaitSt - - - - - - - - - - - 1 1 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 1 1 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T13,T7,T111
ReadWaitSt - - - - - - - - - - - 1 1 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 1 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T7,T103,T111
ReadWaitSt - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
ReadWaitSt - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Not Covered
DescrSt - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T6
DescrSt - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T105,T107,T159
DescrWaitSt - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T6
DescrWaitSt - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T2,T3,T6
WriteSt - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
WriteSt - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T3,T6,T4
WriteSt - - - - - - - - - - - - - - - - - - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T2,T3
WriteSt - - - - - - - - - - - - - - - - - - 1 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - Covered T5,T106,T125
WriteSt - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T1,T6,T4
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 1 1 1 - - - - - - - - - - - - - - - - - - - - - - Excluded VC_COV_UNR
WriteWaitSt - - - - - - - - - - - - - - - - - - - - - 1 1 0 1 - - - - - - - - - - - - - - - - - - - - - Covered T7,T137,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,T6
ScrSt - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - - - Covered T105,T107,T159
ScrSt - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - Covered T6,T4,T5
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - - - - Covered T2,T3,T6
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - - - - Covered T2,T3,T6
ScrWaitSt - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - - - Not Covered
DigClrSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - - - - - - - - - - - - - - - - Covered T1,T2,T3
DigClrSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - - Covered T105,T107,T109
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 1 - - - - - - - - - - - - - - Covered T1,T2,T3
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 0 - - - - - - - - - - - - - - Not Covered
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 1 - - - - - - - - - - - - - Covered T1,T2,T3
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1 - 0 - - - - - - - - - - - - - Covered T5,T106,T160
DigReadSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - Covered T4,T5,T11
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 T23,T24,T25
ErrorSt - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0 Covered T3,T4,T12
default - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Covered T23,T24,T25


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 T3,T4,T12
1 0 Covered T3,T4,T12
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,T6
0 1 - Covered T1,T2,T3
0 0 1 Covered T6,T10,T4
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 1120 1120 0 0
CheckNativeOtpWidth1_A 1120 1120 0 0
DaiIdleKnown_A 95995079 95123308 0 0
DaiRdataKnown_A 95995079 95123308 0 0
ErrorKnown_A 95995079 95123308 0 0
InitDoneKnown_A 95995079 95123308 0 0
OtpAddrKnown_A 95995079 95123308 0 0
OtpCmdKnown_A 95995079 95123308 0 0
OtpErrorState_A 95995079 325 0 0
OtpReqKnown_A 95995079 95123308 0 0
OtpSizeKnown_A 95995079 95123308 0 0
OtpWdataKnown_A 95995079 95123308 0 0
PartInitReqKnown_A 95995079 95123308 0 0
PartSelMustBeOnehot_A 95995079 95123308 0 0
ScrmblBlockWidthGe8_A 95995079 95123308 0 0
ScrmblCmdKnown_A 95995079 95123308 0 0
ScrmblDataKnown_A 95995079 95123308 0 0
ScrmblModeKnown_A 95995079 95123308 0 0
ScrmblMtxReqKnown_A 95995079 95123308 0 0
ScrmblSelKnown_A 95995079 95123308 0 0
ScrmblValidKnown_A 95995079 95123308 0 0
gen_part_sel[0].PartEndMax_A 1120 1120 0 0
gen_part_sel[10].PartEndMax_A 1120 1120 0 0
gen_part_sel[1].PartEndMax_A 1120 1120 0 0
gen_part_sel[2].PartEndMax_A 1120 1120 0 0
gen_part_sel[3].PartEndMax_A 1120 1120 0 0
gen_part_sel[4].PartEndMax_A 1120 1120 0 0
gen_part_sel[5].PartEndMax_A 1120 1120 0 0
gen_part_sel[6].PartEndMax_A 1120 1120 0 0
gen_part_sel[7].PartEndMax_A 1120 1120 0 0
gen_part_sel[8].PartEndMax_A 1120 1120 0 0
gen_part_sel[9].PartEndMax_A 1120 1120 0 0
u_state_regs_A 95995079 95123308 0 0


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

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

DaiIdleKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

DaiRdataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

ErrorKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

InitDoneKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

OtpAddrKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

OtpCmdKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

OtpErrorState_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 325 0 0
T7 111593 1 0 0
T9 0 1 0 0
T16 0 1 0 0
T17 7426 0 0 0
T18 123084 0 0 0
T29 11450 0 0 0
T90 7244 0 0 0
T93 66768 0 0 0
T103 118648 1 0 0
T104 21552 0 0 0
T105 52425 0 0 0
T106 71675 0 0 0
T111 0 4 0 0
T113 0 1 0 0
T137 0 1 0 0
T161 0 2 0 0
T162 0 4 0 0
T163 0 1 0 0

OtpReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

OtpSizeKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

OtpWdataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

PartInitReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

PartSelMustBeOnehot_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

ScrmblBlockWidthGe8_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

ScrmblCmdKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

ScrmblDataKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

ScrmblModeKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

ScrmblMtxReqKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

ScrmblSelKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

ScrmblValidKnown_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

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

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

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

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

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

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

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

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

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

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

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

u_state_regs_A
NameAttemptsReal SuccessesFailuresIncomplete
Total 95995079 95123308 0 0
T1 6346 6266 0 0
T2 20779 20387 0 0
T3 16526 16188 0 0
T4 41540 41124 0 0
T5 24984 24368 0 0
T6 30776 30706 0 0
T10 44472 44397 0 0
T11 20926 20462 0 0
T12 41197 40991 0 0
T13 73799 72549 0 0

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