Line split page
dashboard | hierarchy | modlist | groups | tests | asserts
Go back

148 149 1/1 assign debug_state_o = state_q; Tests: T1 T2 T3  150 151 //SEC_CM: CTRL.FSM.SPARSE 152 3/3 `PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, lcmgr_state_e, StIdle) Tests: T1 T2 T3  | T1 T2 T3  | T1 T2 T3 
PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, lcmgr_state_e, StIdle): 152.1 `ifdef SIMULATION 152.2 prim_sparse_fsm_flop #( 152.3 .StateEnumT(lcmgr_state_e), 152.4 .Width($bits(lcmgr_state_e)), 152.5 .ResetValue($bits(lcmgr_state_e)'(StIdle)), 152.6 .EnableAlertTriggerSVA(1), 152.7 .CustomForceName("state_q") 152.8 ) u_state_regs ( 152.9 .clk_i ( clk_i ), 152.10 .rst_ni ( rst_ni ), 152.11 .state_i ( state_d ), 152.12 .state_o ( ) 152.13 ); 152.14 always_ff @(posedge clk_i or negedge rst_ni) begin 152.15 1/1 if (!rst_ni) begin Tests: T1 T2 T3  152.16 1/1 state_q <= StIdle; Tests: T1 T2 T3  152.17 end else begin 152.18 1/1 state_q <= state_d; Tests: T1 T2 T3  152.19 end 152.20 end 152.21 u_state_regs_A: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (state_q === u_state_regs.state_o)) 152.22 else begin 152.23 `ifdef UVM 152.24 uvm_pkg::uvm_report_error("ASSERT FAILED", "u_state_regs_A", uvm_pkg::UVM_NONE, 152.25 "../src/lowrisc_opentitan_top_earlgrey_flash_ctrl_0.1/rtl/flash_ctrl_lcmgr.sv", 152, "", 1); 152.26 `else 152.27 $error("%0t: (%0s:%0d) [%m] [ASSERT FAILED] %0s", $time, `__FILE__, `__LINE__, 152.28 `PRIM_STRINGIFY(u_state_regs_A)); 152.29 `endif 152.30 end 152.31 `else 152.32 prim_sparse_fsm_flop #( 152.33 .StateEnumT(lcmgr_state_e), 152.34 .Width($bits(lcmgr_state_e)), 152.35 .ResetValue($bits(lcmgr_state_e)'(StIdle)), 152.36 .EnableAlertTriggerSVA(1) 152.37 ) u_state_regs ( 152.38 .clk_i ( `PRIM_FLOP_CLK ), 152.39 .rst_ni ( `PRIM_FLOP_RST ), 152.40 .state_i ( state_d ), 152.41 .state_o ( state_q ) 152.42 ); 152.43 `endif153 154 lc_tx_t err_sts_d, err_sts_q; 155 logic err_sts_set; 156 lc_tx_t rma_ack_d, rma_ack_q; 157 logic validate_q, validate_d; 158 logic [SeedCntWidth-1:0] seed_cnt_q; 159 logic [SeedRdsWidth-1:0] addr_cnt_q; 160 logic seed_cnt_en, seed_cnt_clr; 161 logic addr_cnt_en, addr_cnt_clr; 162 logic rma_wipe_req, rma_wipe_done, rma_wipe_req_int; 163 logic [WipeIdxWidth-1:0] rma_wipe_idx; 164 logic rma_wipe_idx_incr; 165 flash_lcmgr_phase_e phase; 166 logic seed_phase; 167 logic rma_phase; 168 logic seed_err_q, seed_err_d; 169 170 1/1 assign seed_phase = phase == PhaseSeed; Tests: T1 T2 T3  171 1/1 assign rma_phase = phase == PhaseRma; Tests: T1 T2 T3  172 173 always_ff @(posedge clk_i or negedge rst_ni) begin 174 1/1 if (!rst_ni) begin Tests: T1 T2 T3  175 1/1 rma_ack_q <= lc_ctrl_pkg::Off; Tests: T1 T2 T3  176 1/1 validate_q <= 1'b0; Tests: T1 T2 T3  177 1/1 seed_err_q <= '0; Tests: T1 T2 T3  178 end else begin 179 1/1 rma_ack_q <= rma_ack_d; Tests: T1 T2 T3  180 1/1 validate_q <= validate_d; Tests: T1 T2 T3  181 1/1 seed_err_q <= seed_err_d; Tests: T1 T2 T3  182 end 183 end 184 185 1/1 assign seed_err_o = seed_err_q | seed_err_d; Tests: T1 T2 T3  186 187 // seed cnt tracks which seed round we are handling at the moment 188 // SEC_CM: CTR.REDUN 189 logic seed_cnt_err_d, seed_cnt_err_q; 190 prim_count #( 191 .Width(SeedCntWidth) 192 ) u_seed_cnt ( 193 .clk_i, 194 .rst_ni, 195 .clr_i(seed_cnt_clr), 196 .set_i('0), 197 .set_cnt_i('0), 198 .incr_en_i(seed_cnt_en), 199 .decr_en_i(1'b0), 200 .step_i(SeedCntWidth'(1'b1)), 201 .commit_i(1'b1), 202 .cnt_o(seed_cnt_q), 203 .cnt_after_commit_o(), 204 .err_o(seed_cnt_err_d) 205 ); 206 207 // SEC_CM: CTR.REDUN 208 logic addr_cnt_err_d, addr_cnt_err_q; 209 prim_count #( 210 .Width(SeedRdsWidth) 211 ) u_addr_cnt ( 212 .clk_i, 213 .rst_ni, 214 .clr_i(addr_cnt_clr), 215 .set_i('0), 216 .set_cnt_i('0), 217 .incr_en_i(addr_cnt_en), 218 .decr_en_i(1'b0), 219 .step_i(SeedRdsWidth'(1'b1)), 220 .commit_i(1'b1), 221 .cnt_o(addr_cnt_q), 222 .cnt_after_commit_o(), 223 .err_o(addr_cnt_err_d) 224 ); 225 226 always_ff @(posedge clk_i or negedge rst_ni) begin 227 1/1 if (!rst_ni) begin Tests: T1 T2 T3  228 1/1 addr_cnt_err_q <= '0; Tests: T1 T2 T3  229 1/1 seed_cnt_err_q <= '0; Tests: T1 T2 T3  230 end else begin 231 1/1 addr_cnt_err_q <= addr_cnt_err_q | addr_cnt_err_d; Tests: T1 T2 T3  232 1/1 seed_cnt_err_q <= seed_cnt_err_q | seed_cnt_err_d; Tests: T1 T2 T3  233 end 234 end 235 236 // read data integrity check 237 logic data_err; 238 logic data_intg_ok; 239 tlul_data_integ_dec u_data_intg_chk ( 240 .data_intg_i(rdata_i), 241 .data_err_o(data_err) 242 ); 243 1/1 assign data_intg_ok = ~data_err; Tests: T1 T2 T3  244 245 // hold on to failed integrity until reset 246 logic data_invalid_d, data_invalid_q; 247 1/1 assign data_invalid_d = data_invalid_q | Tests: T1 T2 T3  248 (rvalid_i & ~data_intg_ok); 249 250 always_ff @(posedge clk_i or negedge rst_ni) begin 251 1/1 if (!rst_ni) begin Tests: T1 T2 T3  252 1/1 data_invalid_q <= '0; Tests: T1 T2 T3  253 end else begin 254 1/1 data_invalid_q <= data_invalid_d; Tests: T1 T2 T3  255 end 256 end 257 258 // capture the seed values 259 logic [SeedRdsWidth-1:0] rd_idx; 260 logic [NumSeedWidth-1:0] seed_idx; 261 1/1 assign rd_idx = addr_cnt_q[SeedRdsWidth-1:0]; Tests: T1 T2 T3  262 1/1 assign seed_idx = seed_cnt_q[NumSeedWidth-1:0]; Tests: T1 T2 T3  263 always_ff @(posedge clk_i or negedge rst_ni) begin 264 1/1 if (!rst_ni) begin Tests: T1 T2 T3  265 1/1 seeds_q <= RndCnstAllSeeds; Tests: T1 T2 T3  266 1/1 end else if (seed_phase && validate_q && rvalid_i) begin Tests: T1 T2 T3  267 // validate current value 268 1/1 seeds_q[seed_idx][rd_idx] <= seeds_q[seed_idx][rd_idx] & Tests: T1 T2 T3  269 rdata_i[BusWidth-1:0]; 270 1/1 end else if (seed_phase && rvalid_i) begin Tests: T1 T2 T3  271 1/1 seeds_q[seed_idx][rd_idx] <= rdata_i[BusWidth-1:0]; Tests: T1 T2 T3  272 end MISSING_ELSE 273 end 274 275 page_addr_t seed_page; 276 logic [InfoTypesWidth-1:0] seed_info_sel; 277 logic [BusAddrW-1:0] seed_page_addr; 278 1/1 assign seed_page = SeedInfoPageSel[seed_idx]; Tests: T1 T2 T3  279 1/1 assign seed_info_sel = seed_page.sel; Tests: T1 T2 T3  280 1/1 assign seed_page_addr = BusAddrW'({seed_page.addr, BusWordW'(0)}); Tests: T1 T2 T3  281 282 logic start; 283 flash_op_e op; 284 flash_prog_e prog_type; 285 flash_erase_e erase_type; 286 flash_part_e part_sel; 287 logic [InfoTypesWidth-1:0] info_sel; 288 logic [11:0] num_words; 289 logic [BusAddrW-1:0] addr; 290 291 assign prog_type = FlashProgNormal; 292 assign erase_type = FlashErasePage; 293 // seed phase is always read 294 // rma phase is erase unless we are validating 295 assign op = FlashOpRead; 296 297 // synchronize inputs 298 logic init_q; 299 300 prim_flop_2sync #( 301 .Width(1), 302 .ResetValue(0) 303 ) u_sync_flash_init ( 304 .clk_i, 305 .rst_ni, 306 .d_i(init_i), 307 .q_o(init_q) 308 ); 309 310 typedef enum logic [1:0] { 311 RmaReqInit, 312 RmaReqKey, 313 RmaReqWait, 314 RmaReqLast 315 } rma_req_idx_e; 316 317 lc_tx_t [RmaReqLast-1:0] rma_req; 318 prim_lc_sync #( 319 .NumCopies(int'(RmaReqLast)) 320 ) u_sync_rma_req ( 321 .clk_i, 322 .rst_ni, 323 .lc_en_i(rma_req_i), 324 .lc_en_o(rma_req) 325 ); 326 327 logic addr_key_req_d; 328 logic addr_key_ack_q; 329 logic data_key_req_d; 330 logic data_key_ack_q; 331 332 // req/ack to otp 333 prim_sync_reqack u_addr_sync_reqack ( 334 .clk_src_i(clk_i), 335 .rst_src_ni(rst_ni), 336 .clk_dst_i(clk_otp_i), 337 .rst_dst_ni(rst_otp_ni), 338 .req_chk_i(1'b1), 339 .src_req_i(addr_key_req_d), 340 .src_ack_o(addr_key_ack_q), 341 .dst_req_o(otp_key_req_o.addr_req), 342 .dst_ack_i(otp_key_rsp_i.addr_ack) 343 ); 344 345 // req/ack to otp 346 prim_sync_reqack u_data_sync_reqack ( 347 .clk_src_i(clk_i), 348 .rst_src_ni(rst_ni), 349 .clk_dst_i(clk_otp_i), 350 .rst_dst_ni(rst_otp_ni), 351 .req_chk_i(1'b1), 352 .src_req_i(data_key_req_d), 353 .src_ack_o(data_key_ack_q), 354 .dst_req_o(otp_key_req_o.data_req), 355 .dst_ack_i(otp_key_rsp_i.data_ack) 356 ); 357 358 always_ff @(posedge clk_i or negedge rst_ni) begin 359 1/1 if (!rst_ni) begin Tests: T1 T2 T3  360 1/1 addr_key_o <= RndCnstAddrKey; Tests: T1 T2 T3  361 1/1 data_key_o <= RndCnstDataKey; Tests: T1 T2 T3  362 end else begin 363 1/1 if (addr_key_req_d && addr_key_ack_q) begin Tests: T1 T2 T3  364 1/1 addr_key_o <= flash_key_t'(otp_key_rsp_i.key); Tests: T1 T2 T3  365 1/1 rand_addr_key_o <= flash_key_t'(otp_key_rsp_i.rand_key); Tests: T1 T2 T3  366 end MISSING_ELSE 367 368 1/1 if (data_key_req_d && data_key_ack_q) begin Tests: T1 T2 T3  369 1/1 data_key_o <= flash_key_t'(otp_key_rsp_i.key); Tests: T1 T2 T3  370 1/1 rand_data_key_o <= flash_key_t'(otp_key_rsp_i.rand_key); Tests: T1 T2 T3  371 end MISSING_ELSE 372 end 373 end 374 375 376 /////////////////////////////// 377 // Hardware Interface FSM 378 /////////////////////////////// 379 logic rma_done; 380 1/1 assign rma_done = lc_tx_test_true_strict( Tests: T1 T2 T3  381 lc_ctrl_pkg::lc_tx_and_hi(rma_req_i,rma_ack_d)); 382 383 always_comb begin 384 385 // phases of the hardware interface 386 1/1 phase = PhaseNone; Tests: T1 T2 T3  387 388 // timer controls 389 1/1 seed_cnt_en = 1'b0; Tests: T1 T2 T3  390 1/1 seed_cnt_clr = 1'b0; Tests: T1 T2 T3  391 1/1 addr_cnt_en = 1'b0; Tests: T1 T2 T3  392 1/1 addr_cnt_clr = 1'b0; Tests: T1 T2 T3  393 394 // flash ctrl arb controls 395 1/1 start = 1'b0; Tests: T1 T2 T3  396 1/1 addr = '0; Tests: T1 T2 T3  397 1/1 part_sel = FlashPartInfo; Tests: T1 T2 T3  398 1/1 info_sel = 0; Tests: T1 T2 T3  399 1/1 num_words = SeedReads[11:0] - 12'd1; Tests: T1 T2 T3  400 401 // seed status 402 1/1 seed_err_d = seed_err_q; Tests: T1 T2 T3  403 404 1/1 state_d = state_q; Tests: T1 T2 T3  405 1/1 rma_ack_d = lc_ctrl_pkg::Off; Tests: T1 T2 T3  406 1/1 validate_d = validate_q; Tests: T1 T2 T3  407 408 // read buffer enable 409 1/1 rd_buf_en_o = 1'b0; Tests: T1 T2 T3  410 411 1/1 addr_key_req_d = 1'b0; Tests: T1 T2 T3  412 1/1 data_key_req_d = 1'b0; Tests: T1 T2 T3  413 414 // entropy handling 415 1/1 edn_req_o = 1'b0; Tests: T1 T2 T3  416 1/1 lfsr_en_o = 1'b0; Tests: T1 T2 T3  417 418 // rma related 419 1/1 rma_wipe_req = 1'b0; Tests: T1 T2 T3  420 1/1 rma_wipe_idx_incr = 1'b0; Tests: T1 T2 T3  421 422 // disable flash access entirely 423 1/1 dis_access_o = lc_ctrl_pkg::Off; Tests: T1 T2 T3  424 425 1/1 state_err = 1'b0; Tests: T1 T2 T3  426 427 1/1 unique case (state_q) Tests: T1 T2 T3  428 429 // If rma request is seen, directly transition to wipe. 430 // Since init has not been called, there are no guarantees 431 // to entropy behavior, thus do not reseed 432 StIdle: begin 433 1/1 if (lc_tx_test_true_strict(rma_req[RmaReqInit])) begin Tests: T1 T2 T3  434 1/1 state_d = StRmaWipe; Tests: T31 T32 T177  435 1/1 end else if (init_q) begin Tests: T1 T2 T3  436 1/1 state_d = StReqAddrKey; Tests: T1 T2 T3  437 end MISSING_ELSE 438 end 439 440 StReqAddrKey: begin 441 1/1 phase = PhaseSeed; Tests: T1 T2 T3  442 1/1 addr_key_req_d = 1'b1; Tests: T1 T2 T3  443 1/1 if (lc_tx_test_true_strict(rma_req[RmaReqKey])) begin Tests: T1 T2 T3  444 1/1 state_d = StRmaWipe; Tests: T96 T97 T99  445 1/1 end else if (addr_key_ack_q) begin Tests: T1 T2 T3  446 1/1 state_d = StReqDataKey; Tests: T1 T2 T3  447 end MISSING_ELSE 448 end 449 450 StReqDataKey: begin 451 1/1 phase = PhaseSeed; Tests: T1 T2 T3  452 1/1 data_key_req_d = 1'b1; Tests: T1 T2 T3  453 1/1 if (lc_tx_test_true_strict(rma_req[RmaReqKey])) begin Tests: T1 T2 T3  454 1/1 state_d = StRmaWipe; Tests: T97 T98 T178  455 1/1 end else if (data_key_ack_q) begin Tests: T1 T2 T3  456 // provision_en is only a "good" value after otp/lc initialization 457 1/1 state_d = provision_en_i ? StReadSeeds : StWait; Tests: T1 T2 T3  458 end MISSING_ELSE 459 end 460 461 // read seeds 462 StReadSeeds: begin 463 // seeds can be updated in this state 464 1/1 phase = PhaseSeed; Tests: T1 T2 T3  465 466 // kick off flash transaction 467 1/1 start = 1'b1; Tests: T1 T2 T3  468 1/1 addr = BusAddrW'(seed_page_addr); Tests: T1 T2 T3  469 1/1 info_sel = seed_info_sel; Tests: T1 T2 T3  470 471 // we have checked all seeds, proceed 472 1/1 addr_cnt_en = rvalid_i; Tests: T1 T2 T3  473 1/1 if (seed_cnt_q == NumSeeds) begin Tests: T1 T2 T3  474 1/1 start = 1'b0; Tests: T1 T2 T3  475 1/1 state_d = StWait; Tests: T1 T2 T3  476 1/1 end else if (done_i) begin Tests: T1 T2 T3  477 1/1 seed_err_d = |err_i; Tests: T1 T2 T3  478 1/1 state_d = StReadEval; Tests: T1 T2 T3  479 end MISSING_ELSE 480 end // case: StReadSeeds 481 482 StReadEval: begin 483 1/1 phase = PhaseSeed; Tests: T1 T2 T3  484 1/1 addr_cnt_clr = 1'b1; Tests: T1 T2 T3  485 1/1 state_d = StReadSeeds; Tests: T1 T2 T3  486 487 1/1 if (validate_q) begin Tests: T1 T2 T3  488 1/1 seed_cnt_en = 1'b1; Tests: T1 T2 T3  489 1/1 validate_d = 1'b0; Tests: T1 T2 T3  490 end else begin 491 1/1 validate_d = 1'b1; Tests: T1 T2 T3  492 end 493 end 494 495 // Waiting for an rma entry command 496 StWait: begin 497 1/1 rd_buf_en_o = 1'b1; Tests: T1 T2 T3  498 1/1 if (lc_tx_test_true_strict(rma_req[RmaReqWait])) begin Tests: T1 T2 T3  499 1/1 state_d = StEntropyReseed; Tests: T4 T31 T33  500 end MISSING_ELSE 501 end 502 503 // Reseed entropy 504 StEntropyReseed: begin 505 1/1 edn_req_o = 1'b1; Tests: T4 T31 T33  506 1/1 if(edn_ack_i) begin Tests: T4 T31 T33  507 1/1 state_d = StRmaWipe; Tests: T4 T31 T33  508 end ==> MISSING_ELSE 509 end 510 511 StRmaWipe: begin 512 1/1 phase = PhaseRma; Tests: T4 T31 T33  513 1/1 lfsr_en_o = 1'b1; Tests: T4 T31 T33  514 1/1 rma_wipe_req = 1'b1; Tests: T4 T31 T33  515 516 1/1 if (rma_wipe_idx == MaxWipeEntry[WipeIdxWidth-1:0] && rma_wipe_done) begin Tests: T4 T31 T33  517 // first check for error status 518 // If error status is set, go directly to invalid terminal state 519 // If error status is good, go to second check 520 1/1 state_d = lc_ctrl_pkg::lc_tx_test_false_loose(err_sts_q) ? StInvalid : StRmaRsp; Tests: T28 T29 T30  521 1/1 end else if (rma_wipe_done) begin Tests: T4 T31 T33  522 1/1 rma_wipe_idx_incr = 1; Tests: T28 T29 T30  523 end MISSING_ELSE 524 end 525 526 // response to rma request 527 // Second check for error status: 528 // If error status indicates error, jump to invalid terminal state 529 // Otherwise assign output to error status; 530 StRmaRsp: begin 531 1/1 phase = PhaseRma; Tests: T28 T29 T137  532 1/1 dis_access_o = lc_ctrl_pkg::On; Tests: T28 T29 T137  533 1/1 if (lc_ctrl_pkg::lc_tx_test_false_loose(err_sts_q)) begin Tests: T28 T29 T137  534 0/1 ==> state_d = StInvalid; 535 end else begin 536 1/1 rma_ack_d = err_sts_q; Tests: T28 T29 T137  537 end 538 end 539 540 // Disabled state is functionally equivalent to invalid, just without the 541 // the explicit error-ing 542 StDisabled: begin 543 1/1 dis_access_o = lc_ctrl_pkg::On; Tests: T4 T5 T6  544 1/1 rma_ack_d = lc_ctrl_pkg::Off; Tests: T4 T5 T6  545 1/1 state_d = StDisabled; Tests: T4 T5 T6  546 end 547 548 StInvalid: begin 549 1/1 dis_access_o = lc_ctrl_pkg::On; Tests: T30 T108 T179  550 1/1 state_err = 1'b1; Tests: T30 T108 T179  551 1/1 rma_ack_d = lc_ctrl_pkg::Off; Tests: T30 T108 T179  552 1/1 state_d = StInvalid; Tests: T30 T108 T179  553 end 554 555 // Invalid catch-all state 556 default: begin 557 dis_access_o = lc_ctrl_pkg::On; 558 state_err = 1'b1; 559 state_d = StInvalid; 560 end 561 562 endcase // unique case (state_q) 563 564 // This fsm does not directly interface with flash so can be 565 // be transitioned to invalid immediately. 566 // If rma transition is successful however, do not transition 567 // and continue acking the life cycle controller, as disable is 568 // expected behavior under this situation. 569 1/1 if (prim_mubi_pkg::mubi4_test_true_loose(disable_i) && Tests: T1 T2 T3  570 state_d != StInvalid && 571 !rma_done) begin 572 1/1 state_d = StDisabled; Tests: T4 T5 T6  573 end MISSING_ELSE 574 575 end // always_comb 576 577 // If state is already invalid, disable has no impact. 578 // If state is currently in StRmaRsp with a successful RMA transition, also do not 579 // transition to disabled state as we need to continue acknowledging lc_ctrl. 580 `ASSERT(DisableChk_A, prim_mubi_pkg::mubi4_test_true_loose(disable_i) & state_q != StRmaRsp 581 |=> state_q == StDisabled) 582 583 /////////////////////////////// 584 // RMA wiping Mechanism 585 /////////////////////////////// 586 587 localparam int unsigned PageCntWidth = prim_util_pkg::vbits(PagesPerBank + 1); 588 localparam int unsigned WordCntWidth = prim_util_pkg::vbits(BusWordsPerPage + 1); 589 localparam int unsigned MaxRmaProgBurst = WidthMultiple * 2; 590 localparam int unsigned BeatCntWidth = prim_util_pkg::vbits(MaxRmaProgBurst); 591 localparam int unsigned MaxBeatCnt = MaxRmaProgBurst - 1; 592 593 logic page_cnt_ld; 594 logic page_cnt_incr; 595 logic page_cnt_clr; 596 logic word_cnt_incr; 597 logic word_cnt_ld; 598 logic word_cnt_clr; 599 logic prog_cnt_en; 600 logic rd_cnt_en; 601 logic beat_cnt_clr; 602 logic [PageCntWidth-1:0] page_cnt, end_page; 603 logic [WordCntWidth-1:0] word_cnt; 604 logic [BeatCntWidth-1:0] beat_cnt; 605 logic [MaxBeatCnt:0][BusWidth-1:0] prog_data; 606 607 1/1 assign end_page = RmaWipeEntries[rma_wipe_idx].start_page + Tests: T1 T2 T3  608 RmaWipeEntries[rma_wipe_idx].num_pages; 609 610 rma_state_e rma_state_d, rma_state_q; 611 612 // SEC_CM: CTRL.FSM.SPARSE 613 3/3 `PRIM_FLOP_SPARSE_FSM(u_rma_state_regs, rma_state_d, rma_state_q, rma_state_e, StRmaIdle) Tests: T1 T2 T3  | T1 T2 T3  | T1 T2 T3 
PRIM_FLOP_SPARSE_FSM(u_rma_state_regs, rma_state_d, rma_state_q, rma_state_e, StRmaIdle): 613.1 `ifdef SIMULATION 613.2 prim_sparse_fsm_flop #( 613.3 .StateEnumT(rma_state_e), 613.4 .Width($bits(rma_state_e)), 613.5 .ResetValue($bits(rma_state_e)'(StRmaIdle)), 613.6 .EnableAlertTriggerSVA(1), 613.7 .CustomForceName("rma_state_q") 613.8 ) u_rma_state_regs ( 613.9 .clk_i ( clk_i ), 613.10 .rst_ni ( rst_ni ), 613.11 .state_i ( rma_state_d ), 613.12 .state_o ( ) 613.13 ); 613.14 always_ff @(posedge clk_i or negedge rst_ni) begin 613.15 1/1 if (!rst_ni) begin Tests: T1 T2 T3  613.16 1/1 rma_state_q <= StRmaIdle; Tests: T1 T2 T3  613.17 end else begin 613.18 1/1 rma_state_q <= rma_state_d; Tests: T1 T2 T3  613.19 end 613.20 end 613.21 u_rma_state_regs_A: assert property (@(posedge clk_i) disable iff ((!rst_ni) !== '0) (rma_state_q === u_rma_state_regs.state_o)) 613.22 else begin 613.23 `ifdef UVM 613.24 uvm_pkg::uvm_report_error("ASSERT FAILED", "u_rma_state_regs_A", uvm_pkg::UVM_NONE, 613.25 "../src/lowrisc_opentitan_top_earlgrey_flash_ctrl_0.1/rtl/flash_ctrl_lcmgr.sv", 613, "", 1); 613.26 `else 613.27 $error("%0t: (%0s:%0d) [%m] [ASSERT FAILED] %0s", $time, `__FILE__, `__LINE__, 613.28 `PRIM_STRINGIFY(u_rma_state_regs_A)); 613.29 `endif 613.30 end 613.31 `else 613.32 prim_sparse_fsm_flop #( 613.33 .StateEnumT(rma_state_e), 613.34 .Width($bits(rma_state_e)), 613.35 .ResetValue($bits(rma_state_e)'(StRmaIdle)), 613.36 .EnableAlertTriggerSVA(1) 613.37 ) u_rma_state_regs ( 613.38 .clk_i ( `PRIM_FLOP_CLK ), 613.39 .rst_ni ( `PRIM_FLOP_RST ), 613.40 .state_i ( rma_state_d ), 613.41 .state_o ( rma_state_q ) 613.42 ); 613.43 `endif614 615 // SEC_CM: CTR.REDUN 616 logic page_err_q, page_err_d; 617 prim_count #( 618 .Width(PageCntWidth) 619 ) u_page_cnt ( 620 .clk_i, 621 .rst_ni, 622 .clr_i(page_cnt_clr), 623 .set_i(page_cnt_ld), 624 .set_cnt_i(RmaWipeEntries[rma_wipe_idx].start_page), 625 .incr_en_i(page_cnt_incr), 626 .decr_en_i(1'b0), 627 .step_i(PageCntWidth'(1)), 628 .commit_i(1'b1), 629 .cnt_o(page_cnt), 630 .cnt_after_commit_o(), 631 .err_o(page_err_d) 632 ); 633 634 logic word_err_q, word_err_d; 635 //SEC_CM: CTR.REDUN 636 prim_count #( 637 .Width(WordCntWidth) 638 ) u_word_cnt ( 639 .clk_i, 640 .rst_ni, 641 .clr_i(word_cnt_clr), 642 .set_i(word_cnt_ld), 643 .set_cnt_i('0), 644 .incr_en_i(word_cnt_incr), 645 .decr_en_i(1'b0), 646 .step_i(WordCntWidth'(MaxRmaProgBurst)), 647 .commit_i(1'b1), 648 .cnt_o(word_cnt), 649 .cnt_after_commit_o(), 650 .err_o(word_err_d) 651 ); 652 653 logic rma_idx_err_q, rma_idx_err_d; 654 //SEC_CM: CTR.REDUN 655 prim_count #( 656 .Width(WipeIdxWidth) 657 ) u_wipe_idx_cnt ( 658 .clk_i, 659 .rst_ni, 660 .clr_i('0), 661 .set_i('0), 662 .set_cnt_i('0), 663 .incr_en_i(rma_wipe_idx_incr), 664 .decr_en_i(1'b0), 665 .step_i(WipeIdxWidth'(1'b1)), 666 .commit_i(1'b1), 667 .cnt_o(rma_wipe_idx), 668 .cnt_after_commit_o(), 669 .err_o(rma_idx_err_d) 670 ); 671 672 always_ff @(posedge clk_i or negedge rst_ni) begin 673 1/1 if (!rst_ni) begin Tests: T1 T2 T3  674 1/1 page_err_q <= '0; Tests: T1 T2 T3  675 1/1 word_err_q <= '0; Tests: T1 T2 T3  676 1/1 rma_idx_err_q <= '0; Tests: T1 T2 T3  677 end else begin 678 1/1 page_err_q <= page_err_q | page_err_d; Tests: T1 T2 T3  679 1/1 word_err_q <= word_err_q | word_err_d; Tests: T1 T2 T3  680 1/1 rma_idx_err_q <= rma_idx_err_q | rma_idx_err_d; Tests: T1 T2 T3  681 end 682 end 683 684 // beat cnt is not made a prim_count because if beat_cnt 685 // if tampered, the read verification stage will automatically 686 // fail. 687 always_ff @(posedge clk_i or negedge rst_ni) begin 688 1/1 if (!rst_ni) begin Tests: T1 T2 T3  689 1/1 beat_cnt <= '0; Tests: T1 T2 T3  690 1/1 end else if (beat_cnt_clr) begin Tests: T1 T2 T3  691 1/1 beat_cnt <= '0; Tests: T32 T28 T29  692 1/1 end else if (prog_cnt_en) begin Tests: T1 T2 T3  693 1/1 if (wvalid_o && wready_i) begin Tests: T31 T32 T28  694 1/1 beat_cnt <= beat_cnt + 1'b1; Tests: T31 T32 T28  695 end MISSING_ELSE 696 1/1 end else if (rd_cnt_en) begin Tests: T1 T2 T3  697 1/1 if (rvalid_i && rready_o) begin Tests: T32 T28 T29  698 1/1 beat_cnt <= beat_cnt + 1'b1; Tests: T32 T28 T29  699 end MISSING_ELSE 700 end MISSING_ELSE 701 end 702 703 // latch data programmed 704 always_ff @(posedge clk_i) begin 705 1/1 if (prog_cnt_en && wvalid_o && wready_i) begin Tests: T1 T2 T3  706 1/1 prog_data[beat_cnt] <= rand_i; Tests: T31 T32 T28  707 end MISSING_ELSE 708 end 709 710 // once error is set to off, it cannot be unset without a reboot 711 // On - no errors 712 // Off - errors were observed 713 logic [lc_ctrl_pkg::TxWidth-1:0] err_sts_raw_q; 714 1/1 assign err_sts_q = lc_tx_t'(err_sts_raw_q); Tests: T1 T2 T3  715 1/1 assign err_sts_d = err_sts_set && lc_ctrl_pkg::lc_tx_test_true_loose(err_sts_q) ? Tests: T1 T2 T3  716 lc_ctrl_pkg::Off : err_sts_q; 717 // This primitive is used to place a size-only constraint on the flops in order to prevent 718 // optimizations. Without this Vivado may infer combo loops. For details, see 719 // https://github.com/lowRISC/opentitan/issues/10204 720 prim_flop #( 721 .Width(lc_ctrl_pkg::TxWidth), 722 .ResetValue(lc_ctrl_pkg::TxWidth'(lc_ctrl_pkg::On)) 723 ) u_prim_flop_err_sts ( 724 .clk_i, 725 .rst_ni, 726 .d_i(err_sts_d), 727 .q_o(err_sts_raw_q) 728 ); 729 730 logic rma_start; 731 logic [BusAddrW-1:0] rma_addr; 732 flash_op_e rma_op; 733 flash_part_e rma_part_sel; 734 logic [InfoTypesWidth-1:0] rma_info_sel; 735 logic [11:0] rma_num_words; 736 737 1/1 assign rma_addr = {RmaWipeEntries[rma_wipe_idx].bank, Tests: T1 T2 T3  738 page_cnt[PageW-1:0], 739 word_cnt[BusWordW-1:0]}; 740 741 1/1 assign rma_part_sel = RmaWipeEntries[rma_wipe_idx].part; Tests: T1 T2 T3  742 1/1 assign rma_info_sel = RmaWipeEntries[rma_wipe_idx].info_sel; Tests: T1 T2 T3  743 assign rma_num_words = MaxBeatCnt; 744 745 // this variable is specifically here to work around some tooling issues identified in #9661. 746 // Certain tools identify rma_wipe_req as part of a combinational loop. 747 // It is not a combinational loop in the synthesized sense, but rather a combinational loop from 748 // the perspective of simulation scheduler. 749 // This is not a synthesized combo loop for the following reasons 750 // 1. rma_wipe_req is changed only based on the value of state_q, so it cannot be 751 // affected by non-flop signals 752 // 2. other lint tools do not identify (including sign-off tool) an issue. 753 // The direct feedthrough assignment below helps address some of the tooling issues. 754 1/1 assign rma_wipe_req_int = rma_wipe_req; Tests: T1 T2 T3  755 756 //fsm for handling the actual wipe 757 logic fsm_err; 758 759 // SEC_CM: RMA_ENTRY.MEM.SEC_WIPE 760 always_comb begin 761 1/1 rma_state_d = rma_state_q; Tests: T1 T2 T3  762 1/1 rma_wipe_done = 1'b0; Tests: T1 T2 T3  763 1/1 rma_start = 1'b0; Tests: T1 T2 T3  764 1/1 rma_op = FlashOpInvalid; Tests: T1 T2 T3  765 1/1 err_sts_set = 1'b0; Tests: T1 T2 T3  766 1/1 page_cnt_ld = 1'b0; Tests: T1 T2 T3  767 1/1 page_cnt_incr = 1'b0; Tests: T1 T2 T3  768 1/1 page_cnt_clr = 1'b0; Tests: T1 T2 T3  769 1/1 word_cnt_ld = 1'b0; Tests: T1 T2 T3  770 1/1 word_cnt_incr = 1'b0; Tests: T1 T2 T3  771 1/1 word_cnt_clr = 1'b0; Tests: T1 T2 T3  772 1/1 prog_cnt_en = 1'b0; Tests: T1 T2 T3  773 1/1 rd_cnt_en = 1'b0; Tests: T1 T2 T3  774 1/1 beat_cnt_clr = 1'b0; Tests: T1 T2 T3  775 1/1 fsm_err = 1'b0; Tests: T1 T2 T3  776 777 1/1 unique case (rma_state_q) Tests: T1 T2 T3  778 // Transition to invalid state via disable only when any ongoing stateful 779 // operations are complete. This ensures we do not electrically disturb 780 // any ongoing operation. 781 // This of course cannot be guaranteed if the FSM state is directly disturbed, 782 // and that is considered an extremely invasive attack. 783 StRmaIdle: begin 784 1/1 if (prim_mubi_pkg::mubi4_test_true_loose(disable_i)) begin Tests: T1 T2 T3  785 1/1 rma_state_d = StRmaDisabled; Tests: T4 T5 T6  786 1/1 end else if (rma_wipe_req_int) begin Tests: T1 T2 T3  787 1/1 rma_state_d = StRmaPageSel; Tests: T4 T31 T33  788 1/1 page_cnt_ld = 1'b1; Tests: T4 T31 T33  789 end MISSING_ELSE 790 end 791 792 StRmaPageSel: begin 793 1/1 if (prim_mubi_pkg::mubi4_test_true_loose(disable_i)) begin Tests: T4 T31 T33  794 0/1 ==> rma_state_d = StRmaDisabled; 795 1/1 end else if (page_cnt < end_page) begin Tests: T4 T31 T33  796 1/1 rma_state_d = StRmaErase; Tests: T4 T31 T33  797 end else begin 798 1/1 rma_wipe_done = 1'b1; Tests: T28 T29 T30  799 1/1 page_cnt_clr = 1'b1; Tests: T28 T29 T30  800 1/1 rma_state_d = StRmaIdle; Tests: T28 T29 T30  801 end 802 end 803 804 StRmaErase: begin 805 1/1 rma_start = 1'b1; Tests: T4 T31 T33  806 1/1 rma_op = FlashOpErase; Tests: T4 T31 T33  807 1/1 if (done_i) begin Tests: T4 T31 T33  808 1/1 err_sts_set = |err_i; Tests: T4 T31 T32  809 1/1 rma_state_d = StRmaEraseWait; Tests: T4 T31 T32  810 end MISSING_ELSE 811 end 812 813 StRmaEraseWait: begin 814 1/1 word_cnt_ld = 1'b1; Tests: T4 T31 T32  815 1/1 rma_state_d = StRmaWordSel; Tests: T4 T31 T32  816 end 817 818 StRmaWordSel: begin 819 1/1 if (prim_mubi_pkg::mubi4_test_true_loose(disable_i)) begin Tests: T4 T31 T32  820 1/1 rma_state_d = StRmaDisabled; Tests: T4 T150 T180  821 1/1 end else if (word_cnt < BusWordsPerPage) begin Tests: T31 T32 T28  822 1/1 rma_state_d = StRmaProgram; Tests: T31 T32 T28  823 end else begin 824 1/1 word_cnt_clr = 1'b1; Tests: T28 T29 T30  825 1/1 page_cnt_incr = 1'b1; Tests: T28 T29 T30  826 1/1 rma_state_d = StRmaPageSel; Tests: T28 T29 T30  827 end 828 end 829 830 StRmaProgram: begin 831 1/1 rma_start = 1'b1; Tests: T31 T32 T28  832 1/1 rma_op = FlashOpProgram; Tests: T31 T32 T28  833 1/1 prog_cnt_en = 1'b1; Tests: T31 T32 T28  834 835 1/1 if ((beat_cnt == MaxBeatCnt[BeatCntWidth-1:0]) && wready_i) begin Tests: T31 T32 T28  836 1/1 rma_state_d = StRmaProgramWait; Tests: T31 T32 T28  837 end MISSING_ELSE 838 end 839 840 StRmaProgramWait: begin 841 1/1 rma_start = 1'b1; Tests: T31 T32 T28  842 1/1 rma_op = FlashOpProgram; Tests: T31 T32 T28  843 844 1/1 if (done_i) begin Tests: T31 T32 T28  845 1/1 beat_cnt_clr = 1'b1; Tests: T32 T28 T29  846 1/1 err_sts_set = |err_i; Tests: T32 T28 T29  847 1/1 rma_state_d = StRmaRdVerify; Tests: T32 T28 T29  848 end MISSING_ELSE 849 end 850 851 StRmaRdVerify: begin 852 1/1 rma_start = 1'b1; Tests: T32 T28 T29  853 1/1 rma_op = FlashOpRead; Tests: T32 T28 T29  854 1/1 rd_cnt_en = 1'b1; Tests: T32 T28 T29  855 856 1/1 if ((beat_cnt == MaxBeatCnt[BeatCntWidth-1:0]) && done_i) begin Tests: T32 T28 T29  857 1/1 beat_cnt_clr = 1'b1; Tests: T32 T28 T29  858 1/1 word_cnt_incr = 1'b1; Tests: T32 T28 T29  859 1/1 rma_state_d = StRmaWordSel; Tests: T32 T28 T29  860 end MISSING_ELSE 861 862 1/1 if (rvalid_i && rready_o) begin Tests: T32 T28 T29  863 1/1 err_sts_set = prog_data[beat_cnt] != rdata_i[BusWidth-1:0]; Tests: T32 T28 T29  864 end MISSING_ELSE 865 end 866 867 StRmaDisabled: begin 868 1/1 rma_state_d = StRmaDisabled; Tests: T4 T5 T6  869 end 870 871 StRmaInvalid: begin 872 1/1 rma_state_d = StRmaInvalid; Tests: T12 T13 T14  873 1/1 err_sts_set = 1'b1; Tests: T12 T13 T14  874 1/1 fsm_err = 1'b1; Tests: T12 T13 T14  875 end 876 877 default: begin 878 rma_state_d = StRmaInvalid; 879 fsm_err = 1'b1; 880 end 881 882 endcase // unique case (rma_state_q) 883 884 end // always_comb 885 886 tlul_data_integ_enc u_bus_intg ( 887 .data_i(rand_i), 888 .data_intg_o(wdata_o) 889 ); 890 891 1/1 assign wvalid_o = prog_cnt_en; Tests: T1 T2 T3  892 1/1 assign ctrl_o.start.q = seed_phase ? start : rma_start; Tests: T1 T2 T3  893 1/1 assign ctrl_o.op.q = seed_phase ? op : rma_op; Tests: T1 T2 T3  894 unreachable assign ctrl_o.prog_sel.q = prog_type; 895 unreachable assign ctrl_o.erase_sel.q = erase_type; 896 1/1 assign ctrl_o.partition_sel.q = seed_phase ? part_sel : rma_part_sel; Tests: T1 T2 T3  897 1/1 assign ctrl_o.info_sel.q = seed_phase ? info_sel : rma_info_sel; Tests: T1 T2 T3  898 1/1 assign ctrl_o.num = seed_phase ? num_words : rma_num_words; Tests: T1 T2 T3  899 // address is consistent with software width format (full bus) 900 1/1 assign addr_o = seed_phase ? {addr, {BusByteWidth{1'b0}}} : Tests: T1 T2 T3  901 {rma_addr, {BusByteWidth{1'b0}}}; 902 1/1 assign init_busy_o = seed_phase; Tests: T1 T2 T3  903 904 // Initialization is considered done when read buffer is enabled. 905 1/1 assign initialized_o = rd_buf_en_o; Tests: T1 T2 T3  906 1/1 assign req_o = seed_phase | rma_phase; Tests: T1 T2 T3  907 assign rready_o = 1'b1; 908 1/1 assign seeds_o = seeds_q; Tests: T1 T2 T3  909 1/1 assign phase_o = phase; Tests: T1 T2 T3  910 911 1/1 assign rma_ack_o = rma_ack_q; Tests: T1 T2 T3  912 913 // all of these are considered fatal errors 914 1/1 assign fatal_err_o = page_err_q | word_err_q | fsm_err | state_err | rma_idx_err_q | Tests: T1 T2 T3  915 addr_cnt_err_q | seed_cnt_err_q; 916 917 // integrity error is its own category 918 1/1 assign intg_err_o = data_invalid_q; Tests: T1 T2 T3  919 920 logic unused_seed_valid; 921 1/1 assign unused_seed_valid = otp_key_rsp_i.seed_valid; Tests: T1 T2 T3  922 923 // assertion 924 925 `ifdef INC_ASSERT 926 //VCS coverage off 927 // pragma coverage off 928 localparam int MaxRmaDataWidth = MaxRmaProgBurst * BusWidth; 929 localparam int ShiftWidth = (MaxRmaProgBurst - 1) * BusWidth; 930 logic [MaxRmaDataWidth-1:0] rma_data_q, rma_data; 931 always_ff @(posedge clk_i) begin 932 unreachable if (rma_start && rvalid_i && rready_o) begin 933 unreachable rma_data_q <= rma_data; 934 end ==> MISSING_ELSE 935 end 936 //VCS coverage on 937 // pragma coverage on 938 939 1/1 assign rma_data = {rdata_i, rma_data_q[MaxRmaDataWidth-1 -: ShiftWidth]}; Tests: T1 T2 T3 
0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%