← 05 Code Reading and Debugging | Index | 07 ECO, LEC and Post-Freeze Flows →
Round 06 — Combined answers (Gemini · GPT · Claude)
Contents
- 0. Resume probe
- Part A — Rapid-fire Q and A (0:05–0:20)
- M6Q2 · A1. Name the UVM phases in order of execution, and say which…
- M6Q3 · A2. Sequence, sequencer, driver: who calls get_next_item, who…
- M6Q4 · A3. Analysis port vs. TLM blocking put port: when do you use…
- M6Q5 · A4. Your scoreboard receives expected transactions from a…
- M6Q6 · A5. Functional vs. code coverage: give an example of 100% code…
- M6Q7 · A6. How do you decide coverage closure is done on a block? What…
- M6Q8 · A7. Constrained-random vs. directed: for the 802.11 rate matrix…
- M6Q9 · A8. SVA: a -> b vs. a => b; what does rose(a) mean on the first…
- M6Q10 · A9. Write (speak) an SVA that says: "req stays high until ack,…
- M6Q11 · A10. DPI-C: what are the rules for passing a 64-bit value and…
- M6Q12 · A11. Why use a C reference model at all, versus a SystemVerilog…
- M6Q13 · A12. Regressions: how do you pick seeds, how many, and how do…
- M6Q14 · A13. X-propagation: what does -xprop (or equivalent) do, and…
- M6Q15 · A14. Gate-level simulation: what does it catch that RTL sim…
- M6Q16 · A15. When would you choose formal property verification over…
- Part B — Deep dive: verification plan for the TBTT/TSF block (0:20–0:55)
- Part C — Your questions (0:55–1:00)
- Additional notes
0. Resume probe
M6Q1 · "300+ single-user tests: how many of them would fail if the ceil-divide in the length-parameter block were off by one? Why?"
Gemini Answer
- Answer: Depending on which off-by-one bug it is:
- If the ceil-divide computed
floor(num / N_DBPS)instead ofceil(num / N_DBPS)(off bywhenever numis not an exact multiple ofN_DBPS), ~99% of the 300+ tests would fail immediately becausenum = 8 * psdu_len + 16 + 6*(~ldpc)is almost never an exact multiple ofN_DBPS. - However, if the bug is the classic
ceil(A / B)boundary off-by-one (floor(A / B) + 1instead offloor((A - 1) / B) + 1, which is only wrong whenAis an exact multiple ofN_DBPS), randompsdu_lentests would only hit it with probability! - Why my suite catches both: When I built the module-level testbench and the 300+ 802.11bn tests, I didn't just use uniform random
psdu_len; I constrainedpsdu_lenacross every rate combination to specifically target symbol-boundary exact multiples (num == k * N_DBPS - 8,k * N_DBPS,k * N_DBPS + 8) and LDPC extra-symbol punctuation thresholds, so around 40–50 boundary-targeted tests fail deterministically on a boundary off-by-one.
- If the ceil-divide computed
GPT Answer
"I extended an existing block environment for Wi-Fi 8 and wrote 300+ 802.11bn single-user tests when DV staffing was short. Earlier I built the Wi-Fi 6E Tx length-parameter module testbench and verified every a/b/g/n/ac/ax rate combination before tapeout. Test count alone does not show sensitivity to a ceil-divide bug; I would identify which tests check nonzero remainders and exact-division boundaries, and demonstrate the checker with an injected off-by-one mutation." The resume does not establish an actual mutation-test result.
Claude Answer
"It depends on which off-by-one, and I can say which tests because the suite was generated
from the rate matrix, not hand-written. If ceil degraded to floor, every test whose
8·len + 22 is not a multiple of N_DBPS fails — that is almost every random length, so
most of the suite. If the bug is only in the exactly-divisible case (one symbol too many),
random lengths essentially never hit it; it's caught only by the directed boundary lengths
I put in every MCS/NSS/BW cell: num mod N_DBPS ∈ {0, 1, N_DBPS−1}. Either way the failure
is detected because the scoreboard compares against a spec-derived model of N_SYM, not
against the RTL's own arithmetic. The count isn't the point; knowing which tests own which
boundary is."
Part A — Rapid-fire Q and A (0:05–0:20)
M6Q2 · A1. Name the UVM phases in order of execution, and say which ones are time-consuming (task) and which are zero-time (function). Where do you raise objections?
Gemini Answer
- Build-time (
function, top-down / bottom-up):build_phase(top-downfunction)connect_phase(bottom-upfunction)end_of_elaboration_phase(bottom-upfunction)start_of_simulation_phase(bottom-upfunction)
- Run-time (
task, parallel, consumes simulation time):
5.run_phase(and its 12 parallel run-time sub-phases:pre_reset→reset→post_reset→pre_configure→configure→post_configure→pre_main→main→post_main→pre_shutdown→shutdown→post_shutdown). - Clean-up (
function, bottom-up):
6.extract_phase, 7.check_phase, 8.report_phase, 9.final_phase(top-down). - Where objections are raised: In
run_phase(ormain_phase), typically at the top-leveluvm_test(or base sequence) viaphase.raise_objection(this)/phase.drop_objection(this).
GPT Answer
Common phases: build, connect, end_of_elaboration, start_of_simulation, run, extract, check, report, final. These are functions except run, which is a task. Runtime subphases pre/reset/post_reset, pre/configure/post_configure, pre/main/post_main, and pre/shutdown/post_shutdown execute alongside run in their schedule. Raise/drop objections in the chosen runtime task phase around required stimulus and drain completion, not in build.
Claude Answer
build → connect → end_of_elaboration → start_of_simulation → run (with the
twelve parallel sub-phases pre_reset … post_shutdown) → extract → check → report →
final. Only run_phase and its sub-phases are tasks (consume time); the rest are
functions. Objections are raised/dropped in run_phase (or a sub-phase) from the test or
the top-level sequence.
M6Q3 · A2. Sequence, sequencer, driver: who calls get_next_item, who calls item_done, and what breaks if the driver never calls item_done?
Gemini Answer
- Who calls what: The driver calls
seq_item_port.get_next_item(req)(which blocks until the sequencer arbitrates a sequence'sstart_item(req)/finish_item(req)), drives the pins on the virtual interface, and then the driver callsseq_item_port.item_done(). - What breaks if
item_done()is never called:finish_item(req)in the sequence blocks forever waiting for the completion handshake, hanging the sequencer and timing out the test.
GPT Answer
Driver calls get_next_item, drives the item, then calls item_done. Omitting completion leaves the sequence/sequencer handshake blocked. Match one completion to each fetched item and define reset-abort behavior.
Claude Answer
The driver calls get_next_item (blocks until a sequence's start_item/finish_item
hands one over) and the driver calls item_done. Without item_done, finish_item never
returns, the sequence hangs, and the next get_next_item errors because the sequencer
still holds the previous item.
M6Q4 · A3. Analysis port vs. TLM blocking put port: when do you use each between monitor and scoreboard?
Gemini Answer
uvm_analysis_port(write()): Zero-time function, 1-to-broadcast (0, 1, or many subscribers like scoreboards and functional coverage collectors); monitor never blocks. uvm_blocking_put_port(put()): Task that can consume time and block for backpressure, 1-to-1 connection; used when chaining predictor/translation stages that require flow control.
GPT Answer
Analysis write is nonblocking broadcast and cannot consume time; use an analysis FIFO for a scoreboard that waits. Blocking put provides backpressure and can consume time. A passive monitor should not stall observation because the scoreboard is busy.
Claude Answer
Analysis port: non-blocking, one-to-many broadcast — monitor to scoreboard,
coverage and model at once. Blocking put: point-to-point with back-pressure — between
model stages where the consumer must be able to stall the producer.
M6Q5 · A4. Your scoreboard receives expected transactions from a reference model and actual ones from the monitor, but the DUT may legally reorder them. How do you design the compare?
Gemini Answer
- Store expected transactions in an associative array indexed by unique transaction ID / tag (
exp_q[id][$]— a queue per ID so same-ID transactions remain FIFO ordered while different IDs match out-of-order). - On actual monitor arrival: look up
exp_q[act.id], pop the front item, and compare fields. - End-of-test & watchdog check: Assert in
check_phasethatexp_q.num() == 0(no dropped packets), and attach a per-item timestamp watchdog so a starved transaction fails immediately rather than waiting until end-of-sim.
GPT Answer
Match by protocol identity: ID/tag plus per-ID ordering rules and reset epoch. Keep expected queues/maps, detect duplicate/unexpected responses, and timeout missing ones. Do not globally sort transactions if ordering within an ID is mandatory.
Claude Answer
Match on transaction identity (stream/user id + sequence number or address), not
arrival order: per-stream associative arrays or queues, out-of-order lookup, a timeout on
expected items, and an end-of-test sweep that reports both missing-expected and
unexpected-actual. Keep an in-order check only within streams where the spec guarantees it.
M6Q6 · A5. Functional vs. code coverage: give an example of 100% code coverage with a bug, and of 100% functional coverage with a bug.
Gemini Answer
- 100% code coverage with a bug: Every line, branch, and toggle is exercised (
assign y = a + b;instead ofa - b, or a missing pipeline stall state that was never written in the RTL at all—code coverage cannot measure missing code!). - 100% functional coverage with a bug: Every defined
coverpointbin was hit (and the testbench had a shallow/disabled checker or missed a cross-coverage interaction between TSF slew and config write).
GPT Answer
Code coverage can reach 100% while arithmetic results are wrong. Functional bins can all be sampled while the scoreboard is disabled or the bins fail to check data/order. Coverage measures exercised structure/scenarios, not correctness.
Claude Answer
Code 100%, bug: a wrong constant in a table or a < that should be <= — every
line executes, the value is wrong. Functional 100%, bug: an interaction you never defined
a cross for (TSF jump in the same cycle as a config write).
M6Q7 · A6. How do you decide coverage closure is done on a block? What do you do with holes that are unreachable by design?
Gemini Answer
- Closure criteria: 100% of verification plan features tested, 0 failing seeds across nightly regressions, 100% functional coverage (including crosses), and 100% (after reviewed exclusions) block code/FSM/toggle/assertion coverage.
- Unreachable holes: Never blindly waive! Either prove formal unreachability using JasperGold/VC Formal (generating an automated
.elexclusion file) or write a line-by-line waiver file co-signed by both the RTL designer and DV lead explaining why the hardware invariant prevents that branch/bit from toggling.
GPT Answer
Close against a reviewed feature plan, meaningful crosses, checked assertions, justified code holes, resolved bugs, and risk-based stress. Prove or document unreachability and obtain reviewed exclusions; do not delete inconvenient bins merely to raise a percentage.
Claude Answer
Done when a spec-reviewed plan has every item hit or waived in writing, waivers
reviewed by the designer, bug rate flat across the last N seeds, and holes triaged. Holes
unreachable by design go into exclusion files whose rationale points at the RTL structure
("one-hot state 3 unreachable"), not "can't hit", and they are re-examined on any RTL change.
M6Q8 · A7. Constrained-random vs. directed: for the 802.11 rate matrix (MCS × NSS × BW × GI × LDPC × STBC × DCM) which do you use, and how do you guarantee every legal combination is hit?
Gemini Answer
- Hybrid strategy: Use table-driven / directed iteration over all ~1,500 legal
(MCS, NSS, BW/RU, GI, LDPC, STBC, DCM)tuples with boundary PSDU lengths (fast, deterministic 100% rate-matrix coverage in <5 minutes), plus constrained-random sequences for random PSDU lengths, back-to-back inter-frame spacing, dynamic rate switches, and abort/reset injection, backed by a crosscovergroupwithignore_binsfor spec-illegal tuples.
GPT Answer
Enumerate the approved legal rate matrix for deterministic completeness, then randomize ordering, lengths, stalls, reset, and boundary conditions. Sample coverage on accepted/executed transactions, not just generated ones; explicitly report uncovered legal tuples.
Claude Answer
Constrained-random with legality constraints derived from the spec table, a
coverage cross over the matrix with ignore_bins for illegal cells, and a generated
directed sweep as the backstop that guarantees every legal cell plus boundary lengths per
cell. The 300 tests were generated that way; random alone never proves the last cells.
M6Q9 · A8. SVA: a |-> b vs. a |=> b; what does $rose(a) mean on the first clock; what is the difference between an immediate and a concurrent assertion in terms of when it samples?
Gemini Answer
a |-> bvs.a |=> b:|->is overlapping implication (checksbin the same clock cycleais true);|=>is non-overlapping implication (checksbin the next clock cycle, equivalent toa |-> ##1 b).$rose(a)on the first clock: Compares the current sampled value ofa(1) against its initial pre-clock value (Xforlogic,0forbit). BecauseX -> 1counts as a rising transition in SV ($rosecheckslsb === 1'b1 && $past(lsb) !== 1'b1),$rose(a)evaluates true on clock 1 ifa == 1unless gated bydisable iff (!rst_n)!- Immediate vs. Concurrent: Immediate assertions (
assert (expr)) evaluate procedurally inline in the Active region (susceptible to combinational glitches); concurrent assertions (assert property (@(posedge clk) ...)) sample signals in the Preponed region (just before the clock edge, immune to delta-cycle races) and evaluate in the Observed region.
GPT Answer
|-> begins the consequent on the matching antecedent's ending clock; |=> begins on the following clock. $rose uses the sampled least-significant bit and can be true at the first sample if its prior default sampled value is X and it is now 1; gate startup checks with valid history/reset. Immediate assertions evaluate procedurally; concurrent properties normally sample in Preponed and evaluate in Observed.
Claude Answer
|-> overlapping: b checked in the same cycle as a; |=> next cycle. $rose
on the first clock compares with an X/initial previous value and is vendor-dependent, so
guard with disable iff (!rst_n) or start after reset. Immediate assertions evaluate at
the moment procedural code executes them; concurrent assertions sample in the Preponed
region at the clock and evaluate in Observed.
M6Q10 · A9. Write (speak) an SVA that says: "req stays high until ack, and ack comes within 1 to 8 cycles."
Gemini Answer
property p_req_ack_1to8;
@(posedge clk) disable iff (!rst_n)
$rose(req) |-> (req throughout (##[1:8] ack));
// Equivalent: $rose(req) |-> (req && !ack)[*0:7] ##1 (req && ack);
endproperty
ap_req_ack_1to8: assert property (p_req_ack_1to8);
GPT Answer
On a new request, require ack in 1-8 cycles and req to remain high through ack: $rose(req) |=> (req s_until_with ack) and ##[0:7] ack. This assumes no same-cycle acknowledgment and one outstanding request. Add reset/history guards and specify whether a one-cycle req drop is legal at the acknowledgment edge.
Claude Answer
ap_req_ack: assert property (@(posedge clk) disable iff (!rst_n)
$rose(req) |-> (req throughout ##[1:8] ack));
req must hold through the sequence, and the sequence requires ack within 1–8 cycles.
M6Q11 · A10. DPI-C: what are the rules for passing a 64-bit value and an unpacked array of bytes between SystemVerilog and C? What about calling back into SV from C?
Gemini Answer
- 64-bit value: 2-state
longint unsigned/bit [63:0]maps directly to Cuint64_t(unsigned long long); 4-statelogic [63:0]maps to an array ofsvLogicVecValstructs (aval/bvalpairs). - Unpacked array of bytes: Fixed-size
byte arr[N]maps tochar *arr(oruint8_t *); dynamic/open arraybyte arr[]maps tosvOpenArrayHandleaccessed viasvGetArrayPtr()/svSize(). - Calling SV from C: Declare the import as
import "DPI-C" context function ...and export the SV task/function viaexport "DPI-C" function my_sv_func;, setting the scope in C withsvSetScope().
GPT Answer
For a two-state 64-bit value, use longint unsigned and the generated DPI header's matching C type; four-state packed values use svLogicVecVal, and packed bit vectors use svBitVecVal. An open unpacked byte array uses svOpenArrayHandle and svdpi.h accessors; respect byte signedness and bounds. Callbacks need exported SV routines and an imported context routine with correct scope. A function cannot call a time-consuming task; use a supported task interface for that behavior.
Claude Answer
64-bit: longint ↔ long long/int64_t by value; bit [63:0] ↔
svBitVecVal[2], logic [63:0] ↔ svLogicVecVal[2]. Open unpacked arrays (byte a[])
↔ svOpenArrayHandle with svGetArrayPtr/svGetArrElemPtr; fixed-size byte a[16] ↔ a
plain const char*. C → SV: declare the SV side export "DPI-C" function/task and the
calling import context, with svSetScope if the scope differs.
M6Q12 · A11. Why use a C reference model at all, versus a SystemVerilog one? What is the risk when the same engineer writes both the RTL and the C model?
Gemini Answer
- Why C/C++: Reuse the exact golden bit-accurate C model written by the PHY/Systems/Standards team (or
802.11reference model), plusfaster execution on heavy math (LDPC, encryption, CRC). - Same-author risk: If the RTL designer writes both the RTL and the C reference model, any misinterpretation of the IEEE 802.11 spec is coded identically into both models, yielding a 100% green scoreboard on a spec-non-compliant chip!
GPT Answer
C helps reuse independent protocol models and fast arithmetic, but introduces type/build/debug costs. Same-author RTL/model can share the same wrong assumption. Derive the model from the specification and use independent boundary vectors/review.
Claude Answer
C model: an independent expression of the spec, reuse of the architecture team's
golden model, speed, bit-exact integer arithmetic that firmware can share. Risk with one
author: the same spec misreading lands in both sides and cancels out. Mitigate with
spec-table vectors, a second reviewer of the model, or a captured external reference.
M6Q13 · A12. Regressions: how do you pick seeds, how many, and how do you make a failure reproducible when the testbench has fork/join_none randomness?
Gemini Answer
- Seeds: Run 50–200 random seeds per test nightly, logging the exact
+ntb_random_seed=<N>and git SHA. - Reproducibility with
fork/join_none: Standard SystemVerilog provides hierarchical thread seeding, but calling system$urandomor modifying shared queues across racingfork/join_nonethreads breaks random stability. Always use object-scopedthis.srandom()/std::randomize(), avoid zero-delay races between parallel threads, and run with simulator random-stability flags (+ntb_random_seed_automatic).
GPT Answer
Use a reproducible seed list plus targeted and rotating seeds; choose count from coverage and failure statistics, not a magic number. Record source/tool/options/test/seed and external stimulus. Control thread creation order, per-object RNG use, and shared random state; a seed alone cannot repair a race.
Claude Answer
Seeds random per run, logged with test, build and tool version; 50–200 seeds
nightly for a block, more weekly. Reproducibility needs the seed plus identical thread
ordering: UVM random stability (per-object seeding by hierarchical name), never
$urandom inside unordered fork/join_none threads (seed from the object), and record /
replay of the failing seed.
M6Q14 · A13. X-propagation: what does -xprop (or equivalent) do, and why might a design that passes without it fail with it? Which one is the truth?
Gemini Answer
- What it does: Instruments
if/else,case, and ternary operators so that when the condition is1'bx, the simulator merges the outcomes of both branches (setting assigned variables toXwhere the two branches disagree) instead of optimistically taking theelsebranch. - Which is the truth: Neither standard sim nor
-xpropis physical silicon (silicon only has0and1), but-xpropis the conservative truth covering all possible silicon outcomes of an uninitialized flop or timing/CDC violation.
GPT Answer
X-prop makes ambiguous control propagate uncertainty more pessimistically than ordinary if semantics. It can expose missing reset or illegal state use. Neither simulation mode is literal analog silicon; investigate whether the X represents a real uninitialized or timing ambiguity and whether the checker is masking it.
Claude Answer
X-prop makes if/case on an X selector pessimistic (merge both branches or
propagate X) instead of silently taking else. A design that passes without it may depend
on X-optimism, typically an un-reset flop that "happens" to read 0. Neither is the truth:
silicon holds a definite random value per flop. X-prop is closer; the actual requirement is
that no decision depends on an uninitialised value.
M6Q15 · A14. Gate-level simulation: what does it catch that RTL sim cannot, and what is the minimal set of GLS tests you would insist on before tapeout?
Gemini Answer
- What GLS catches that RTL sim misses:
- Uninitialized reset-less flip-flops (no
-xpropblind spots when SDF + non-reset flop init are used). - Multi-cycle / false-path / CDC timing constraint bugs (with SDF timing annotation).
- Glitch-sensitive clock-gating / clock-mux logic and DFT scan-chain shift/capture timing.
- Broken UPF isolation/retention sequences.
- Uninitialized reset-less flip-flops (no
- Minimal GLS test suite before tapeout:
- Power-on reset + cold boot + CSR read/write sweep.
- One full Tx PPDU (SU + MU) and one full Rx PPDU with BA response.
- Clock-switch / low-power sleep-wake sequence.
- Full DFT scan-chain shift + capture pattern and MBIST pass check.
GPT Answer
GLS checks implemented clock/reset/scan connectivity, library semantics, initialization, and with SDF selected timing behavior. Minimum targeted tests: reset/boot, clock gating/switching, test-mode/scan entry-exit, power sequencing where modeled, and critical functional handshakes. STA remains the timing signoff method; GLS is not exhaustive.
Claude Answer
GLS catches un-reset flop behaviour without X-optimism, SDF timing (bad MCP /
false-path constraints), DFT structures and test-mode muxes, clock-gating races, synthesis
pragma effects, UPF isolation/retention. Minimum before tapeout: power-on reset + boot, one
full Tx and one full Rx PPDU with SDF at both corners, scan shift/capture sanity, one
low-power entry/exit, and a clock-switch/wake sequence.
M6Q16 · A15. When would you choose formal property verification over simulation for a MAC block? Give one concrete property per: arbiter, FIFO, CDC handshake.
Gemini Answer
- When FPV wins: Control-dense blocks with small datapath state and deep corner-case sequences (arbiters, FIFOs, skid buffers, CDC handshakes, TBTT catch-up FSMs) where FPV proves correctness across 100% of all possible input sequences in minutes.
- Three concrete properties:
- Arbiter (No Starvation):
req_valid[i] && $stable(req_valid[i]) |-> ##[1:N] (req_valid[i] && req_ready[i])(assumingout_readyis fair). - FIFO (Data Integrity / Ordering): Using the classic 2-value symbolic tracker (
nd_itemtagged on push): when that tracked item pops,out_data == tracked_dataand no item pops whileempty. - CDC 4-Phase Handshake:
$rose(src_req) |-> (src_req until_with dst_ack_sync)and$fell(src_req) |-> (!src_req until_with !dst_ack_sync).
- Arbiter (No Starvation):
GPT Answer
Formal suits bounded control/invariants: arbiter one-hot grants plus fairness under sink-progress assumptions; FIFO order/conservation and no overflow/underflow; CDC mailbox holds payload until ack and produces exactly one receive event per accepted request. Analog metastability still needs structural/physical signoff.
Claude Answer
Formal when the block is control-heavy with a small state space and universal
properties. Arbiter: req[i] |-> ##[1:N] gnt[i] and grants one-hot. FIFO:
push && full && !pop |-> 0, plus symbolic data-integrity (a tagged word comes out once, in
order). CDC handshake: $rose(req) |-> req until_with ack and no new req until ack
drops.
Part B — Deep dive: verification plan for the TBTT/TSF block (0:20–0:55)
You are given the corrected
tbtt_genfrom round 05 (synchronized tick, catch-up FSM,
range-based pre-TBTT, proper resets). It must be verified at block level in an existing UVM
environment that already has:
- an APB agent for configuration registers,
- a "timer" agent that drives
tsf_tick/tsf_usand can inject jumps and slew (double-step
or pause),- a basic scoreboard that only checks that
tbtt_pulseoccurs at all.The block will be reused across Wi-Fi 7 and Wi-Fi 8 with multi-link (MLO): up to 4 links,
each with its own beacon interval and TSF offset, sharing one timer.
M6Q17 · B1. Verification plan
- (10 min) Verification plan. Produce a feature list and, for each feature, the
stimulus, the checker, and the coverage item. At minimum cover: normal periodic TBTT,
pre-TBTT lead time, config change mid-interval, enable/disable, TSF forward jump
(small/large), TSF slew (pause and double-step), beacon interval corner values
(min, max, non-power-of-two), reset mid-operation,tbtt_missedsemantics.
Gemini Answer
| # | Feature | Stimulus | Checker / Expected Behavior | Coverage Item |
|---|---|---|---|---|
| 1 | Periodic TBTT | Program BI en=1, steady tsf_tick. | tbtt_pulse fires for 1 clk cycle whenever tsf_us == k * (BI * 1024). | cp_bi: min (1), typical (100), max (65535), prime (101). |
| 2 | Pre-TBTT Lead Time | Sweep pre_tbtt_us | pre_tbtt_pulse fires exactly once per interval at next_tbtt - pre_tbtt_us. | cp_pre_tbtt cross with cp_bi. |
| 3 | Smooth Slew (+0 Pause / +2 Step) | Timer agent injects next_tbtt_us and next_tbtt_us - pre_tbtt_us. | Zero missed pulses on | Cross: slew_mode |
| 4 | Forward TSF Jump (Catch-Up) | Jump tsf_us forward by | No burst of pulses! tbtt_missed asserts if next_tbtt_us lands on | cp_jump_size: <1 BI, ==1 BI, 2..10 BI, >100 BI. |
| 5 | Mid-Interval Re-Config & Disable | Assert cfg_wr with new BI or drop en=0 1 cycle before, on, and 1 cycle after tbtt_hit. | Clean re-arming without runt pulse; tbtt_missed clears on cfg_wr. | Cross: cfg_wr timing relative to tbtt_hit |
| 6 | Cold Boot Underflow Guard | Start at tsf_us = 0 with BI = 1 TU (pre_tbtt_us = 2000. | No unsigned underflow glitch on pre_tbtt_pulse. | cp_underflow: next_tbtt_us < pre_tbtt_us. |
GPT Answer
| Feature | Stimulus | Checker | Coverage |
|---|---|---|---|
| Periodic TBTT | Several legal BI values | One event per scheduled target | BI x link x interval count |
| Pre-TBTT | Zero/min/max lead and threshold crossing | Exactly once with correct target/lead policy | Lead x BI x slew |
| Config update | Write before/on/after event | Atomic config epoch, documented re-arm | Register x phase x pending state |
| Enable/disable | Toggle around pre/TBTT | No disabled events; correct restart | Edge phase x enable state |
| Forward jump | Before/onto/over one or many targets | No replay burst; aligned future target; missed status | Jump size x target relation |
| Slew | Pause/double-step at thresholds | No duplicate or skipped eligible event | Slew sign x threshold proximity |
| BI corners | Min/max/non-power-of-two, zero attempt | Correct units; zero rejected/disabled | BI class x lead class |
| Reset | Before capture, during alignment, near pulse | No stale event; correct reset epoch/status | Reset phase x pipeline state |
| Missed status | Skipped events plus clear/set collision | Sticky set/clear priority per spec | Miss cause x clear collision |
Keep event identity {link, config_epoch, target_TSF} in the model even if only pulse wires exist in RTL. Cover backward jumps/wrap if supported, or assert they are outside the live operating contract.
Claude Answer
| Feature | Stimulus | Checker | Coverage |
|---|---|---|---|
| Periodic TBTT | enable, run ≥ 10 BIs | pulse at every TSF mod BI == 0 ± 1 tick, exactly one per BI | BI count bins 1, 2–10, >10 |
| Pre-TBTT lead | random pre_tbtt_us 0…BI−1 | pre precedes tbtt by pre_tbtt_us ± 1 tick; never without a following tbtt | lead ∈ {0, 1, mid, BI−1}; lead ≥ BI (illegal → no pulse) |
| Config change mid-interval | write BI / pre while armed | re-alignment to new TSF mod BI == 0; no pulse during catch-up | write phase within BI: early/late/at-TBTT |
| Enable / disable | toggle en at random phases | no pulses while disabled; clean restart; no stale pulse on re-enable | disable at pulse cycle, during catch-up |
| TSF forward jump | small (< BI), large (n·BI), huge | skipped TBTTs flagged once by tbtt_missed; next pulse on the correct multiple; no burst | jump size bins; jump landing exactly on a TBTT |
| TSF slew | pause / double-step every slew period | pulses still land within ±1 tick; no missed, no double | step crosses a TBTT boundary |
| BI corners | min, max, non-power-of-two (e.g. 100 TU), 1 TU | arithmetic exact vs model | BI value bins |
| Reset mid-operation | async reset at random cycles | outputs low, all regs at reset values, recovery | reset during catch-up, during pulse |
tbtt_missed | jumps + FW clear | set once per miss event, clear wins with re-set next cycle (per spec decision), no X at power-up | set/clear same cycle |
| Tick CDC | tick jitter, tsf_us update skew | tsf_us stable through capture; synchroniser latency bounded | tick edge relative to clk phase |
| Back-to-back writes | cfg_wr consecutive cycles | last write wins, one realignment | — |
M6Q18 · B2. Assertions
- (10 min) Assertions. Write four concurrent SVAs for the block. One must be a liveness
/bounded-response property, one must relatepre_tbtt_pulsetotbtt_pulse, one must
capture "TBTT isTSF mod BI == 0", and one must be a CDC-adjacent property on the
synchronizer/tick (e.g.,tsf_usstable while captured).
Gemini Answer
// 1. Bounded Liveness: when armed & TSF advances normally without jumps/config writes,
// tbtt_pulse must fire within (bi_us + 2) tsf_tick rising edges.
property p_tbtt_liveness;
@(posedge clk) disable iff (!rst_n || !en || cfg_wr || tsf_jumped)
(armed && tick_rise) |-> ##[1:MAX_BI_CLKS] tbtt_pulse;
endproperty
ap_tbtt_liveness: assert property (p_tbtt_liveness);
// 2. Pre-TBTT to TBTT ordering: every pre_tbtt_pulse is followed by exactly one tbtt_pulse
// before another pre_tbtt_pulse can occur (unless reconfigured/disabled).
property p_pre_then_tbtt;
@(posedge clk) disable iff (!rst_n || !en || cfg_wr || tsf_jumped)
pre_tbtt_pulse |=> (!pre_tbtt_pulse throughout tbtt_pulse[->1]);
endproperty
ap_pre_then_tbtt: assert property (p_pre_then_tbtt);
// 3. Modulo / Spec Anchor (Formal-friendly without variable % operator!):
// Whenever tbtt_pulse fires in steady state, tsf_q is in [next_tbtt_us, next_tbtt_us + 1]
// and next_tbtt_us[9:0] == 10'b0 (exact multiple of 1 TU = 1024 us).
property p_tbtt_spec_align;
@(posedge clk) disable iff (!rst_n)
tbtt_pulse |-> (tsf_q >= $past(next_tbtt_us)) &&
(tsf_q <= $past(next_tbtt_us) + 64'd1) &&
($past(next_tbtt_us[9:0]) == 10'd0);
endproperty
ap_tbtt_spec_align: assert property (p_tbtt_spec_align);
// 4. CDC Input Stability Contract: tsf_us must remain stable from 1 clk before
// synchronized tick_rise through 2 clks after tick_rise.
property p_cdc_tsf_stable;
@(posedge clk) disable iff (!rst_n)
$rose(tick_sync2_q) |-> $stable(tsf_us)[*3];
endproperty
ap_cdc_tsf_stable: assert property (p_cdc_tsf_stable);
GPT Answer
Checker signals below are defined by the accepted-snapshot interface and an independent model, not invented DUT ports: due means an eligible target was crossed; pulse_target is the scheduled TSF associated with an output pulse; pre_seen_for_target records its pre-event; normal_epoch excludes jump/config/reset recovery; MAX_LAT is a specified core-clock response bound. Assume enable/config remain valid during each bounded obligation, or explicitly cancel obligations on an epoch change.
// 1. Bounded response; due is one cycle per target.
assert property (@(posedge clk) disable iff (!rst_n || epoch_cancel)
due |-> ##[0:MAX_LAT] tbtt_pulse);
// 2. Normal-operation pre-event relation; timestamps use coherent samples.
assert property (@(posedge clk) disable iff (!rst_n)
tbtt_pulse && normal_epoch && pre_required |->
pre_seen_for_target &&
(pre_target == pulse_target) &&
(pre_sample_tsf >= pulse_target - lead_us) &&
(pre_sample_tsf < pulse_target));
// 3. Alignment is about the scheduled target, not delayed sampled TSF.
assert property (@(posedge clk) disable iff (!rst_n)
tbtt_pulse |-> (bi_us != 0) && ((pulse_target % bi_us) == 0));
// 4. Source-domain bundled-data protocol. Capture occurs only after
// synchronized request; physical settle time is checked separately.
assert property (@(posedge src_clk) disable iff (!src_rst_n)
snap_req && !snap_ack_sync |=> $stable(snap_payload));
For zero lead, define whether pre/TBTT may coincide and adjust property 2. For a pulse that crosses both thresholds, use the documented jump/slew policy rather than requiring a physically impossible exact lead. These assertions are sketches with named checker state, not a drop-in bind file. Add pulse uniqueness, no spurious event, and reset checks so liveness cannot pass on extra pulses.
Claude Answer
// 1. Bounded response: once armed and not catching up, a TBTT arrives within one BI (+tol)
ap_live: assert property (@(posedge clk) disable iff (!rst_n)
(armed && !catchup_busy && $rose(armed || !catchup_busy))
|-> ##[1:BI_CYC_MAX] tbtt_pulse);
// 2. pre precedes tbtt by pre_tbtt_us (±1 tick), and only one tbtt in between
ap_pre: assert property (@(posedge clk) disable iff (!rst_n)
pre_tbtt_pulse |-> !tbtt_pulse[*0:PRE_MIN-1] ##[PRE_MIN:PRE_MAX] tbtt_pulse);
// 3. TBTT is TSF mod BI == 0 (sampled TSF, slew tolerance)
ap_mod: assert property (@(posedge clk) disable iff (!rst_n)
tbtt_pulse |-> ((tsf_q % bi_us) <= SLEW_TOL));
// 4. CDC: tsf_us stable for 3 clk after the synchronized tick edge, and the
// capture only ever happens on that edge
ap_stable: assert property (@(posedge clk) disable iff (!rst_n)
$rose(tick_sync) |-> $stable(tsf_us)[*3]);
ap_cap: assert property (@(posedge clk) disable iff (!rst_n)
$changed(tsf_q) |-> $past($rose(tick_sync), 1));
Also: catchup_busy |-> !tbtt_pulse, tbtt_pulse |=> !tbtt_pulse (one cycle).
M6Q19 · B3. Reference model
- (5 min) Reference model. Describe a reference model that is independent of the RTL's
catch-up algorithm. Where does it live (SV class, C via DPI)? How does it handle the
1-cycle uncertainty inherent in sampling a synchronized tick?
Gemini Answer
- Algorithm independence: Instead of mimicking the RTL's iterative
next_tbtt_us + bi_usstate machine, the SV predictor class uses pure 64-bit mathematical spec equations whenevertsf_usupdates:Whenever , expect 1 tbtt_pulse; whenever, expect 0 tbtt_pulse(after catch-up) andtbtt_missed == 1! - Handling 1-cycle synchronizer uncertainty: Because the 2-flop synchronizer on
tsf_tickcan resolve in either 2 or 3clkcycles, the predictor timestampstbtt_pulseintsf_tickepochs (or allows aclkcycle window around the nominaltick_risedelay).
GPT Answer
- Model: an SV class is sufficient; use wide-integer modulo to enumerate aligned targets from coherent snapshots and implement the explicit skip/re-arm policy. It should not copy the RTL's subtract-loop FSM. Model capture/CDC latency separately from ideal TSF arithmetic. Synchronization uncertainty may exceed one core cycle depending on the defined capture path; derive the tolerance from that contract.
Claude Answer
An SV class (reuse the C TSF model via DPI if the system team already has one) that knows
only the spec: TBTT_n = n·BI from TSF zero; on every observed TSF sample it computes
next = ceil((tsf + 1) / BI) · BI with a plain division — the RTL's shift-and-add catch-up
is never reproduced. The slew engine is modelled as "the DUT's TSF is monotonic with at most
one skipped or paused value per slew period". The one-cycle synchroniser uncertainty is
absorbed by emitting expected events as windows ([t − 1 tick, t + 1 tick]), never
instants, and by taking the model's TSF from the timer agent, not from the DUT.
M6Q20 · B4. Scoreboard
- (5 min) Scoreboard. The DUT emits pulses; the model emits expected TBTT timestamps.
How do you compare them with tolerance, and how do you decide whether a missing pulse is
a DUT bug vs. a model misalignment after a jump?
Gemini Answer
- Maintain an expected-event window
[exp_clk_min, exp_clk_max]for each predictedpre_tbtt_pulseandtbtt_pulse. - If a
tbtt_pulsearrives inside[exp_clk_min, exp_clk_max], match and pop. - If simulation time passes
exp_clk_maxwith no DUT pulse: check if the timer agent injected a forward jump during that tick. If no jump, flag an immediateUVM_ERROR ("MISSING_TBTT_PULSE"). If jump occurred, verify thattbtt_missedasserted within the catch-up latency bound.
GPT Answer
- Scoreboard: compare ordered target identities per link/epoch, with bounded output-clock latency from accepted snapshot processing. Close each obligation after one matched pulse. Flag duplicates immediately and missing events at deadline. After a jump, explicitly cancel skipped targets, create the new epoch/target expectation, and check missed status. Never widen tolerance until a failure disappears.
Claude Answer
Queue of expected windows per link. A DUT pulse matches the head window → pop; a pulse with
no window → "unexpected pulse" error; a window that ages past the DUT time by more than the
tolerance → "missing pulse" error unless the timer agent has flagged a jump since that
window was issued. On a jump the model re-syncs, logs the expected number of skipped TBTTs,
and the scoreboard requires exactly one tbtt_missed assertion to coincide (missing flag =
DUT bug, extra flag = DUT bug, missing pulses equal to the skipped count = correct). Model
misalignment is therefore only possible if the timer agent and the model disagree about the
TSF, which a self-check in the agent rules out.
M6Q21 · B5. Scaling to MLO / Wi-Fi 8
- (5 min) Scaling to MLO / Wi-Fi 8. You now have 4 instances with per-link offsets and
one shared timer. What in the env is reusable as-is, what must become parameterised, and
how do you keep the regression time from growing 4×? What would you do with formal here?
Gemini Answer
- Reusable vs. Parameterized: Keep the single shared APB agent and single shared Timer agent; instantiate an array of 4 passive link monitors and 4 parameterized scoreboard predictor instances (
uvm_scoreboard_link[0..3]), each configured with its link-specifictsf_offset_link[i]andbi_tu[i]. - Keeping regression time flat (1× instead of 4×): Drive all 4 links concurrently in every test with randomized relative
tsf_offsetandBIvalues (including coincident TBTT collisions across links 0 and 1!). - Where Formal wins: Prove the catch-up FSM termination bound, absence of double-pulses under arbitrary
slew sequences, and link-independence across all 4 links in JasperGold in ~2 minutes.
GPT Answer
- MLO: reuse APB, timer stimulus, monitor/checker classes, and the mathematical model. Parameterize link ID, offset, BI, and per-link state. Use common stimulus with independent expected queues; cover same-target collisions, offset wrap, and one-link reconfiguration while others run. Avoid the full four-link Cartesian product: exhaustive single-link arithmetic plus targeted inter-link crosses and shared-resource stress. Formal can prove per-link isolation and scheduler fairness under bounded resource availability.
Claude Answer
- Reusable as-is: APB agent, timer agent (shared timer is the real topology), the SVAs
(bound per instance), the reference model class. - Parameterise: link count from
uvm_config_db; per-link config (BI, offset, pre) in a
config object; scoreboard and coverage become per-link instances plus a cross-link check
(links with equal BI and different offsets must never collide incorrectly; the shared
timer's jump must re-align all four). - Regression time: one multi-link test with four active links replaces four single-link
tests; the single-link suite shrinks to smoke; legality-constrained random covers the
per-link matrix in parallel across links. - Formal: the pure arithmetic (catch-up lands on the correct multiple for every TSF and BI,
no pulse during catch-up, modulo property, missed-flag exactly once) has a small state
space oncetsfis symbolic — a proof replaces thousands of seeds, and connectivity
checks cover the 4× wiring.
Part C — Your questions (0:55–1:00)
M6Q22 · C1. Questions for the interviewer
Gemini Answer
- "How closely do RTL designers and DV engineers collaborate on writing the initial block verification plan and SVAs here?"
- "Where do you draw the line between formal property verification and UVM simulation for MAC control blocks?"
- "How is block-level coverage reused or waived when blocks are integrated into the full MAC subsystem testbench?"
GPT Answer
Who reviews functional coverage intent? How are model changes independently checked? Which block-level proofs are reused at subsystem level?
Claude Answer
- How is block coverage rolled up into subsystem closure, and who signs the waivers?
- What is the designer's expected involvement in DV here (plan review, SVAs, debug)?
- Is formal used beyond connectivity, and is there appetite for designer-owned properties?
Additional notes
Notes. Material not tied to a question
Gemini Answer
No answer in gemini_answer.md.
GPT Answer
Reference
Accellera UVM tutorial: execution phases.
Claude Answer
No answer in claude_answer.md.