Each list gives the rules that decide most puzzles in a section. Every rule is taken from the answers and traps of the puzzle named next to it, so you can open that puzzle to see the rule in action. Read the list, then try to explain each rule without looking. Where a rule depends on the tool, the puzzle says so.
== and != return x when an operand has x or z; === and !== compare x and z exactly. (datatype-and-bit-puzzles-1)
If any operand of an expression is unsigned, the whole expression is unsigned: a signed value compared with an unsigned one can flip the result. (datatype-and-bit-puzzles-2)
A part-select is unsigned even when the vector is signed; a cast such as $signed decides sign extension. (datatype-and-bit-puzzles-4)
The expression width decides whether a carry survives: a sum evaluated in too narrow a context drops it. (datatype-and-bit-puzzles-6)
join waits for all children, join_any for the first, join_none for none; wait fork waits for all children of the calling process. (fork-join-puzzles-1)
Threads forked in a loop capture the loop variable, not its value, unless each thread gets its own copy; order inside one time step is not defined. (fork-join-puzzles-2)
Popping an empty queue returns the element default (some tools only warn); assigning a queue copies it by value, but arrays of class handles share the objects. (queue-and-array-puzzles-3)
$cast returns 0 when the value or type does not fit (an illegal enum value, a base handle cast to a derived type); atoi stops at the first non-digit and keeps the digits read so far. (string-and-casting-puzzles-4)
A copy of an object copies nested handles, not the objects they point to, unless do_copy copies them too. (handle-and-copy-puzzles-1)
Assigning a queue of handles still aliases the same objects. (handle-and-copy-puzzles-2)
A monitor that reuses one object and writes it to an analysis port gives every subscriber the same handle: create a new object per sample. (handle-and-copy-puzzles-3)
== on handles compares identity, not contents. (handle-and-copy-puzzles-5)
A non-virtual method binds to the handle type; a virtual method binds to the object type. (virtual-method-puzzles-1)
A derived constructor must call super.new with the arguments the base needs; a virtual call from a base constructor reaches the child method before the child constructor has run. (virtual-method-puzzles-3)
Each specialization of a parameterized class has its own statics; a typedef alias is the same specialization; different specializations are unrelated types. (parameterized-class-puzzles-2)
Factory overrides affect only creates that happen later; chained type overrides resolve; with overlapping instance overrides the first match wins; components built without the factory are not overridden. (factory-override-puzzles-4)
Assertions evaluate on Preponed (pre-edge) values. (event-scheduling-puzzles-1)
#0 runs before the NBA region in the same time slot; nonblocking assignments update in the NBA region, and the last NBA to the same variable in a process wins. (event-scheduling-puzzles-2)
A process that starts waiting after an event was triggered misses it. (event-scheduling-puzzles-3)
Reading q in the Active region at the clock edge returns the old value; this is deterministic, not a race. (race-condition-puzzles-3)
Two always_ff processes driving one register are illegal; a forked counter can lose updates. (race-condition-puzzles-6)
A clocking block samples the value from before the edge, so a sample looks one cycle old; input #0 and input #1step can sample on opposite sides of the NBA. (clocking-block-puzzles-1)
disable fork kills all children of the calling process, including unrelated background threads. (clocking-block-puzzles-3)
Holding a semaphore while blocking on a bounded mailbox can deadlock; a zero-delay try_get loop is a livelock because time never advances; a leaked semaphore token blocks every later get. (semaphore-mailbox-puzzles-2)
Constraints are declarative and solved together, not top to bottom: count the legal tuples first, then reason about probability. (constraint-order-02-bidirectional-sum)
randc cycles through every legal value before repeating. (constraint-order-04-implication-chain)
In dist, := gives each listed value that weight and :/ divides the weight across the range; a zero weight is never chosen. (dist-01-operator-semantics-baseline)
A hard constraint prunes the legal set first; dist weights apply to what is left. (dist-04-pruned-by-hard-constraint)
solve a before b never changes the set of legal solutions, only how often each appears. (solve-before-01-classic-a-b)
An inline randomize() with is ANDed with the class constraints, so it can make the problem unsatisfiable. (randomize-with-02-inline-if-else)
constraint_mode(0) switches a constraint block off; rand_mode(0) freezes a value and can overconstrain the rest. (randomize-with-05-rand-mode-freeze)
A value set in pre_randomize is overwritten by the solver; when randomize() fails, post_randomize does not run. (randomize-with-06-pre-post-lifecycle)
|-> checks the consequent in the same cycle; |=> starts one cycle later. (imp-001)
If the antecedent never matches, the property passes vacuously; pair every assertion with a cover on its antecedent. (imp-002)
[->N] allows gaps between the matches and ends on the last one; [=N] allows more gap after the last match. (seq-003)
A ranged antecedent matches once per end point; first_match keeps only the first. (seq-005)
$rose and $fell are events on sampled values, not levels; a glitch between clock edges is never sampled. (temp-003)
$past at start-up returns the default value, so gate it with a reset-released condition. (temp-005)
disable iff aborts the attempt: a short reset glitch can hide a failure. (dbg-001)
A weak property leaves a pending attempt silent at the end of simulation; a strong one fails. One grant can satisfy overlapping attempts, so a green log does not prove each request was answered. (dbg-003)
A default bin is not scored; coverage is hit scored bins divided by scored bins. (cov-cg-002)
ignore_bins leave the denominator; a hit on illegal_bins is an error and does not count as coverage. (cov-cg-005)
The same samples give different percentages when the scored bin set differs. (cov-cg-006)
auto_bin_max is ignored once bins are explicit; option.at_least makes a bin need that many hits. (cov-opt-005)
option.weight = 0 removes a coverpoint from the aggregate. (cov-opt-006)
Type coverage depends on type_option.merge_instances: it selects the union of the instances or their average, so the same run can show 100 or 75 percent; state it explicitly. (cov-opt-003)
A cross has the product of the bins as denominator, minus what ignore_bins, binsof and intersect remove; a plateau at an exact fraction usually means unreachable bins. (cov-cross-004)
Sampling errors cause closure stalls: a derived clock sees updated values, reset-time samples fill bins unless filtered with iff, and an unreachable tuple is a model problem, not a seed problem. (cov-close-003)
Nine balls, one heavier: split 3-3-3, then 1 against 1; two weighings suffice. (classic-01)
Two eggs and 100 floors: the worst case is 14 drops, using decreasing intervals. (classic-02)
Bridge and torch (1, 2, 7, 10): the minimum total is 17 minutes. (classic-05)
Biased coin to a fair bit: use HT and TH pairs and discard the rest. (probability-01)
Two children with at least one boy: P(both boys) is 1/3. Monty Hall: switching wins 2/3. Expected tosses to the first HH: 6. (probability-03)
A pulse narrower than the receiving clock period can be missed; convert it to a toggle, synchronise the level and detect the edge. (logic-02)
An overlapping 1011 detector needs four states (S0, S1, S10, S101); the smallest XOR built only from NAND gates needs 4. (logic-04, logic-03)
An extra synchroniser stage adds to the exponent, so MTBF multiplies; it protects against metastability, not against a pulse that is never sampled. (logic-06, logic-02)
Every branch of a driver loop must reach item_done exactly once: an early continue skips it, a retry branch can call it twice. (tb-001)
Every exit path of a task must drop the objection it raised; an early return leaks it and the phase never ends. (dead-001)
A join_none poller keeps running after the traffic ends unless something stops it. (dead-002)
A bare disable fork in a helper kills every child of the calling thread, including unrelated ones. (dead-006)
Return a semaphore token on every path; acquire two semaphores in one fixed order. (dead-005)
A scoreboard must match by id when the DUT may legally reorder; one lost item shifts every later compare. (sb-001)
Create a new object per monitored transaction, or subscribers see mutated duplicates; give the scoreboard a drain window before the end-of-test check. (sb-003)
Debug in five stages: symptom, hypotheses, instrumentation, root cause, fix; a timeout must run in parallel with the wait it guards. (round-006)
build_phase runs top down; connect_phase and report_phase run bottom up. (uvm-phase-01)
A derived build_phase without super.build_phase can leave children uncreated; creating a component after build is a fatal error. (uvm-phase-04)
The default config_db rule: a set higher in the hierarchy wins over a later set from below; the key includes the parameter type. (uvm-config-02)
A config_db set must happen before the get in build_phase; with a null context the path needs the uvm_test_top. prefix. (uvm-config-01)
A factory override of a parameterized component applies only to the specialization it names. (uvm-config-06)
A try_next_item loop with no time control hangs at time zero; grab goes ahead of a waiting lock; a virtual sequence started with a null sequencer leaves p_sequencer null. (uvm-seq-01)
write() is a function and cannot wait; two analysis imps need uvm_analysis_imp_decl to get separate write methods. (uvm-sb-02)
RAL keeps a desired and a mirrored value; update() writes the desired value to the DUT; predict() changes the model without writing the DUT; a backdoor access bypasses side effects such as clear-on-read. (uvm-sb-04, uvm-sb-05)
An asynchronous reset obeys a pulse between clock edges; a synchronous reset misses it. (crc-rst-01)
A flop that is never reset stays unknown until it is loaded. (crc-rst-02)
Assert reset asynchronously and release it synchronously; release the receiving domain before the sender starts. (crc-rst-03)
An AND gate fed straight from a flop can produce a runt clock pulse; a latch defers the enable to a safe phase (count one cycle of latency); switching a clock mux with the select alone can create a runt. (crc-clk-01, crc-clk-02, crc-clk-04)
A third synchroniser flop raises MTBF enormously; a toggle synchroniser still loses events closer than about one destination clock period. (crc-cdc-01, crc-cdc-02)
Gray code changes one bit per count, so a crossing captures either the old or the new value; synchronising a valid bit does not synchronise the data. (crc-cdc-03)
RTL simulation cannot tell one synchroniser flop from two; vary clock ratio and start offset to find phase bugs. (crc-ver-01)
A reset checker that never ran is a vacuous pass; if/else hides an X select while AND-OR can invent one; with clock skew larger than clk-to-q, data shoots through even though nonblocking assignments protect same-time-step edges. (crc-ver-03, crc-ver-04, crc-ver-05)
Interview puzzles on the protocols a DV engineer is asked about: valid/ready handshakes (stall, drop, skid buffers), AMBA APB, AXI4 channels, ordering and burst rules, and FIFO, arbitration and credit flow control. The rule list for this section is not written yet: start from the section page and its tricky Q&A.