Before we start, one shared vocabulary reminder so nothing below uses an unearned word. Look at the picture first — it is the whole RTL machine on one slate: two registers with a cloud of logic between them, all whipped by one clock line.
Each is a claim. Answer strictly True or False, then explain why — the reason is the answer.
Every wire or reg you name in Verilog becomes a physical flip-flop.
False — only signals assigned inside @(posedge clk) (or with genuine feedback) become registers; combinational wire/assign signals are just gates, storing nothing across a clock.
Using reg in Verilog always means the tool builds a flip-flop.
False — reg is only a simulation datatype (something an always block may assign). A reg driven by always @(*) synthesizes to pure combinational gates, not a register.
assign y = a & b; describes a circuit with memory.
False — assign is continuous/combinational: y is a pure function of the current a and b with no clock, so it cannot remember a past value.
Slowing down the clock can fix a setup-time violation.
True — setup needs T≥tcq+tcomb,max+tsetup+tskew+tjitter, and a larger period T gives the logic more time to settle, so a slower clock relaxes setup.
Slowing down the clock can fix a hold-time violation.
False — the hold constraint tcq+tcomb,min≥thold+tskew contains no T at all, so changing the clock period does nothing; you must add delay on the fast path instead.
The critical path is the longest wire on the chip.
False — it is the path with the largest propagation delay between two registers, which depends on gate levels and load, not raw geometric length.
Non-blocking <= makes hardware run faster than blocking =.
False — both synthesize to the same gates; the difference is purely simulation semantics (order of update), so it changes correctness, not speed.
A synchronous reset takes effect the instant rst goes high.
False — a synchronous reset only acts on the next rising clock edge, since it is just data feeding the flip-flop's D input, gated by the clock.
If the combinational logic between two registers is empty (a direct wire), timing is automatically safe.
False — a direct connection is exactly where hold violations bite, because new data races to the next register with almost zero delay, possibly arriving before the same-edge capture finished.
Adding a pipeline register can never reduce a design's throughput.
False — usually it raises throughput by shortening the critical path, but if the register is placed badly (very unbalanced stages, or it stalls) throughput may not improve, and latency always grows; it is a trade, not a guarantee. See Pipelining.
Clock skew always hurts your timing.
False — skew that makes the capturing register's edge arrive later actually helps setup (more time to settle), while hurting hold; its sign matters, so it is not uniformly bad.
A multi-cycle path is a bug that must always be fixed in RTL.
False — it is a legitimate design intent (a path allowed several clock periods); you declare it as a timing constraint so the tool checks it against N⋅T instead of one T.
Read the described code/intent and name what is wrong and why.
always @(posedge clk) begin a = b; b = a; end — intended to swap a and b.
Blocking = runs in order: a=b first, so b=a reads the newa; both end as old b. Use <= so both right-hand sides read pre-edge values and swap truly.
always @(a) y = a + b; — meant to be combinational.
The sensitivity list is incomplete (b is missing), so a change in b won't re-evaluate y in simulation → sim/synth mismatch. Use always @(*) to auto-include all inputs.
always @(posedge clk) if (en) y <= d; with no else, intended purely combinational.
This isn't combinational at all — it's a clocked, enabled register: when en is low y holds its old value, inferring exactly the flip-flop the author didn't want.
always @(*) if (sel) y = a; (no else), intended combinational mux.
With no else, when sel is false y must "keep" its value → the tool infers an unwanted latch, a transparent memory that breaks the clean combinational model.
Mixing = and <= for the same variable inside one always @(posedge clk) block.
This gives ambiguous, tool-dependent update ordering and is a classic sim/synth mismatch source; keep one style per block — <= for all sequential assignments.
Trying to speed up a design by writing #5 delays inside RTL to "help timing."
# delays are simulation-only and are ignored by synthesis; real timing is fixed by gate delays, so this changes nothing on silicon and only lies to the testbench.
assign a = b; assign b = a; in combinational logic.
This is a combinational feedback loop with no register to break it — it either oscillates or latches unpredictably; combinational signals must be acyclic.
Declaring a genuinely single-cycle path as a multi-cycle path to make timing "pass."
This silences the tool but the silicon still only gets one period, so the chip will produce wrong data at speed — a false relaxation, not a fix.
Why do we use <= (non-blocking) for sequential logic but = (blocking) for combinational?
Because real flip-flops all latch simultaneously on the edge — <= models that parallel update — while combinational logic is a step-by-step data flow that = mirrors naturally within one evaluation.
Why is tcq (clock-to-Q) in the setup equation but appears with the same sign in the hold equation?
In both cases tcq is how long after the edge the source register's output starts moving; for setup that delay eats into the period budget, for hold it delays the earliest-possible arrival — helping hold, hurting setup.
Why do we subtract tskew and tjitter from T in a realistic setup budget?
Because the capturing clock edge may arrive earlier than ideal (skew) and wander cycle-to-cycle (jitter); budgeting for the worst early edge shrinks the usable period, so we must reserve that time up front.
Why does RTL sit between gate-level and behavioral abstraction?
Gate-level is too low to reason about (thousands of gates by hand) and behavioral is too abstract for tools to map deterministically; RTL — "which register gets which computed value each edge" — is both human-readable and synthesizable predictably.
Why can't you fix a hold violation by pipelining?
Pipelining adds registers to shorten long paths (helps setup); hold is about paths being too short, so inserting registers can even make it worse — the cure is adding delay buffers on the fast path.
Why does splitting "compute" and "store" (combinational math, then one always @(posedge clk)) capture the RTL idea?
Because it directly mirrors silicon: logic gates evaluate a next-value function continuously, and a single register bank samples that value on the edge — exactly the "transfer between registers through logic" definition.
Why does a longer combinational path lower your maximum clock frequency?
Because fmax=1/(tcq+tcomb,max+tsetup) — a bigger tcomb,max enlarges the denominator, so the period must grow and the frequency must fall.
Why declare a false path instead of just letting the tool time it?
Because a path that can never carry a real transition would otherwise be reported as a bogus critical path, forcing you to slow the clock for something that physically never happens.
Why is crossing between two clocks a special hazard even in clean RTL?
A signal sampled by an unrelated clock can be caught mid-transition, entering metastability — an undefined in-between voltage that hovers between 0 and 1 (see the wobbling trace in the figure below) — which no single flip-flop guarantees to resolve in time. See Clock domains and metastability.
Boundary and degenerate scenarios the naive model misses.
What happens to timing if tcomb=0 (two registers wired directly)?
Setup is trivially met, but you approach the hold boundary tcq≥thold+tskew — if clock-to-Q is smaller than hold plus skew, it fails and you must insert delay.
What if two paths reach the same register — a fast one and a slow one?
Setup is governed by the slowest path (tcomb,max) and hold by the fastest path (tcomb,min); both constraints must hold simultaneously on the one register.
What does a combinational block with an incomplete if/case (no default) infer at the boundary case where no branch matches?
It infers a latch to "hold" the unassigned value — a degenerate memory element that violates the intended memory-free combinational design.
At the very first clock edge after power-up with no reset, what is a register's value?
Unknown (x in simulation, arbitrary in silicon) — which is exactly why a reset (sync or async) is needed to force a known starting state.
If the clock is stopped entirely (held constant), what do the registers do?
They freeze — with no rising edge, no register updates, so the whole machine holds its last state indefinitely (the basis of clock gating for power saving).
What is the smallest meaningful design that is still "RTL"?
A single flip-flop fed by one combinational function of its own output and inputs (e.g. a toggle) — it already has both required pieces: state plus a next-state function updated on the edge.
If your combinational logic settles exactly at the setup deadline (zero margin), is the design correct?
In theory it just passes, but with zero slack any voltage/temperature/process variation — plus jitter — pushes it into violation; real designs demand positive timing margin, not a knife-edge pass.
When does clock skew flip from friend to foe for a single register pair?
If the capturing edge arrives later than the launching edge, skew adds to the setup budget (helpful) but subtracts from the hold margin (harmful); the same skew helps one constraint and hurts the other.
Recall One-line self-test (with the picture in your head)
Cover everything above. Picture the s01 slate: R1 → logic cloud → R2, one clock line. Ask yourself: "Does this signal need to remember across a clock?" If no it lives inside the cloud (a wire/gate, combinational); if yes it is one of the boxes (a register). Every RTL question here is a variation on that single boxes-vs-cloud distinction plus the realistic timing budget tcq+tcomb,max+tsetup≤T−tskew−tjitter.