← 01 RTL Fundamentals and SV Coding | Index | 03 CDC, Reset and Async Design →
Round 02 — Combined answers (Gemini · GPT · Claude)
Contents
- 0. Resume probe
- Part A — Rapid-fire Q and A (0:05–0:20)
- M2Q2 · A1. Write the setup and hold inequalities including clock skew…
- M2Q3 · A2. A path fails hold by 30 ps after CTS. List three fixes in…
- M2Q4 · A3. "Useful skew" — what is it, who applies it, and why is it…
- M2Q5 · A4. What exactly is a multicycle path constraint telling STA?…
- M2Q6 · A5. Why might a multicycle path that is correct at the RTL…
- M2Q7 · A6. False path vs. multicycle path vs. case analysis: give an…
- M2Q8 · A7. At 1 GHz in a modern FinFET node, roughly how many levels of…
- M2Q9 · A8. What are path groups in PrimeTime, and why would you want…
- M2Q10 · A9. Max transition / max capacitance violations: are they…
- M2Q11 · A10. Register retiming in synthesis: what does it do, what does…
- M2Q12 · A11. Latency vs. throughput: a 5-stage pipeline with a 1-cycle…
- M2Q13 · A12. You have a 32-bit × 16-bit multiply followed by a…
- M2Q14 · A13. How do you decide where to cut a datapath into stages?…
- M2Q15 · A14. When is a combinational output from a block acceptable at…
- Part B — Deep dive: re-pipeline the Tx length-parameter datapath…
- Part C — Your questions (0:55–1:00)
- Additional notes
0. Resume probe
M2Q1 · "Your resume says you removed a multicycle path. Why was it there, why was it bad, and what did removing it cost?"
Gemini Answer
- Why it was there: In the legacy Wi-Fi 6E design, computing
N_SYMand LDPC encoding parameters (N_avbits,N_pld, shortening/puncturing/extra-symbol check) used a chained combinational divider/multiplier cone constrained with a 3-cycleset_multicycle_pathbecause single-user mode only evaluated it once per PPDU. - Why it was bad: Two reasons:
- Throughput for MU-OFDMA / MU-MIMO: In Wi-Fi 7, up to 8–16 users must be evaluated per PPDU within the tight SIFS/preamble preparation budget; waiting 3 cycles per user serialized the loop too slowly.
- Backend/Silicon Fragility: A 3-cycle MCP requires exact
-setup 3and-hold 2constraints plus an architectural enable guard so launches/captures never occur early. When hierarchy names or clock gating shifted during physical synthesis, MCP exceptions repeatedly broke or risked hold-time silicon escapes.
- What removing it cost: Re-architecting the divider into a factored reciprocal-multiply + 1-step remainder correction and cutting the arithmetic into a 1-cycle-per-stage fully synchronous pipeline added ~450 flip-flops of pipeline registers (~0.3% of MAC area), which was more than offset by eliminating the combinational divider and simplifying PD sign-off.
GPT Answer
"I re-architected the Tx length-parameter datapath for Wi-Fi 7 MU-MIMO/MU-OFDMA and re-pipelined it to remove the legacy multicycle path. The key tradeoff is added latency and registers versus simpler single-cycle timing contracts. I would explain the actual stage boundaries and timing evidence from the project; those details and its clock frequency are not in my resume."
Claude Answer
"The legacy Tx length-parameter block computed N_SYM, the LDPC extra-symbol decision and
TXTIME combinationally from the registered PPDU parameters. It was too deep for one cycle,
and because a new PPDU only starts every SIFS or longer, the original designer constrained
it as a 3-cycle multicycle path instead of pipelining it. That was bad for three reasons:
the constraint lived in an SDC that had to survive SoC integration and hierarchy changes;
the -hold side was easy to get wrong, and PD got it wrong twice; and nothing in the RTL
enforced the 3-cycle stability assumption, so any new consumer sampling early, or Wi-Fi 7's
per-user MU loop re-driving the inputs, could silently break it. Removing it cost about
ten extra pipeline cycles of latency (tens of ns against a 16 µs SIFS budget), a few hundred
flops, and a verification effort: I kept the old combinational block as the golden model and
compared every output across the full rate matrix. In exchange the block became
single-cycle constrained, retime-free and integrator-proof."
Part A — Rapid-fire Q and A (0:05–0:20)
M2Q2 · A1. Write the setup and hold inequalities including clock skew and uncertainty. Which one does a faster clock make worse, and which one is frequency-independent?
Gemini Answer
- Setup:
- Gets worse with a faster clock (
shrinks).
- Gets worse with a faster clock (
- Hold:
- Frequency-independent (checks same clock edge launch vs. capture;
does not appear).
- Frequency-independent (checks same clock edge launch vs. capture;
GPT Answer
With skew = capture_arrival - launch_arrival: setup is tcq_max + data_max + setup <= T + skew - Usetup; hold is tcq_min + data_min >= hold + skew + Uhold. Increasing frequency worsens setup; ordinary same-edge hold does not depend on period.
Claude Answer
Setup: t_cq(max) + t_logic(max) + t_setup ≤ T + (t_skew_capture − t_skew_launch) − t_uncertainty.
Hold: t_cq(min) + t_logic(min) ≥ t_hold + (t_skew_capture − t_skew_launch) + t_uncertainty_hold.
A faster clock shrinks T and only hurts setup. Hold has no T in it: frequency-independent,
which is why a hold bug can't be fixed by slowing the clock.
M2Q3 · A2. A path fails hold by 30 ps after CTS. List three fixes in the order backend would try them, and one fix an RTL engineer can make.
Gemini Answer
- Backend fixes (in order):
- Swap launch/datapath cells to higher-
(HVT) or smaller drive strength to slightly increase with zero area penalty. - Insert delay buffers (
DLYcells) close to the capture flip-flop's D pin. - Adjust local clock tree skew (reduce capture clock insertion delay relative to launch).
- Swap launch/datapath cells to higher-
- RTL fix: Almost never needed for 30 ps post-CTS, unless caused by a bad clock-gating / generated-clock topology in RTL (fix by moving to standard synchronous enables / library ICGs).
GPT Answer
Insert delay cells, downsize/use slower data-path cells, then adjust clock skew if feasible; actual order depends on the implementation flow. RTL can change the microarchitecture or move a register boundary, but adding combinational RTL delay is unreliable and not a normal hold fix.
Claude Answer
Backend order: (1) insert delay/hold-fix buffers on the data path, (2) swap to
slower or higher-Vt cells, (3) adjust clock tree skew (reduce early launch / late capture).
RTL side: avoid the pattern — zero-logic flop-to-flop paths across clock-gate or tree
boundaries, scan-shift paths between chains (lock-up latches), or data crossing between
different-edge or divided clocks without a register.
M2Q4 · A3. "Useful skew" — what is it, who applies it, and why is it dangerous for hold?
Gemini Answer
- What & who: Intentionally delaying the arrival of the clock at a capture flip-flop (or advancing the launch clock) during CTS/post-CTS optimization to "borrow" time from the subsequent pipeline stage.
- Why dangerous for hold: Delaying the capture clock increases positive
for the current stage (helping setup but hurting hold on that same stage by ), and shrinks the available setup budget for the next pipeline stage.
GPT Answer
Useful skew deliberately changes clock arrival times to redistribute slack. Delaying capture helps setup on that path but hurts its hold; it also changes adjacent paths' budgets. PD owns the physical implementation and checks all corners.
Claude Answer
Deliberately delaying the capture clock of a setup-failing endpoint so it borrows
time from the following stage. CTS/PD applies it. Danger: the borrowed stage launches
later, so its downstream setup gets tighter, and the same path's hold check gets worse
because the capture edge now arrives after the launch edge plus min delay.
M2Q5 · A4. What exactly is a multicycle path constraint telling STA? Why does a set_multicycle_path 2 almost always need a companion -hold constraint?
Gemini Answer
- What it tells STA: The data launched at cycle 0 does not need to be captured until clock edge
(giving for setup). - Why
-hold 1is needed: By default in PrimeTime/SDC, moving the setup check to edgemoves the hold check to edge (i.e., checking that the new data does not arrive before 1 full clock period!). Unless you intend data to be delayed by >1 full cycle, you must specify set_multicycle_path 1 -holdso hold is still checked at the launch edge (edge 0).
GPT Answer
Multicycle setup changes the intended launch/capture edge pairing. For ordinary same-clock N-cycle setup with original-edge hold, use setup N plus hold N-1. Different clock periods or -start/-end semantics require checking the actual edges, not applying this recipe blindly.
Claude Answer
set_multicycle_path N -setup tells STA the data launched at edge 0 is captured at
edge N, so the path has N periods. By default the hold check moves with it, to edge N−1,
demanding the data be held stable for N−1 cycles after launch — never what you mean.
set_multicycle_path N-1 -hold moves the hold check back to the launch edge.
M2Q6 · A5. Why might a multicycle path that is correct at the RTL hand-off become a silicon bug? Name two mechanisms.
Gemini Answer
- Missing enable qualification / early read: Downstream logic samples the destination register (or an intermediate node) after 1 cycle instead of waiting for the 2-cycle enable strobe.
- SDC pattern mismatch after synthesis: Ungrouping, register replication, or retiming renames the start/end flops so the
set_multicycle_pathwildcard partially misses (or the-holdrule is dropped during SoC SDC merge), causing PD to insert massive hold buffers or miss setup timing.
GPT Answer
An enable changes so a consumer uses data earlier than the exception allows; or integration drops/misapplies an exception after hierarchy changes. Wrong edge/hold pairing is another risk. Constraint errors may cause bad optimization or hide a violation; the exception itself does not change hardware.
Claude Answer
(1) The RTL stability assumption breaks: a new consumer samples the output early,
or the inputs are re-driven sooner than N cycles (back-to-back MU users). (2) The constraint decouples from the netlist: hierarchy ungroup, renaming, retiming or clock-gating insertion changes the start/end points, or the SDC merge at SoC drops it, so the path becomes unconstrained or mis-constrained. Plus the -hold mistake of A4.
M2Q7 · A6. False path vs. multicycle path vs. case analysis: give an example of each from a Wi-Fi MAC.
Gemini Answer
- False path (
set_false_path): Path between two asynchronous clock domains already protected by a 2-flop synchronizer (e.g.,sync_pulseintotsf_timer), or between mutually exclusive static debug buses. - Multicycle path (
set_multicycle_path): A slow MIB statistics counter or legacy non-pipelined datapath whose launch and capture flops are strictly gated by a pulse that asserts at most once everycycles. - Case analysis (
set_case_analysis): Pinningscan_mode = 0,dft_clk_mux_sel = 0, or a static clock-mode strap during functional STA so the tool analyzes only the functional timing arc.
GPT Answer
False path: mutually exclusive functional/test modes, proven impossible in the analyzed mode. Multicycle: a launch/capture enable protocol that permits N cycles. Case analysis: pin scan/test mode low for functional STA. A slowly changing configuration register is not automatically a false path.
Claude Answer
False path: static config registers (MAC address, BSSID) to datapath, or scan-enable
into functional logic. Multicycle: a TBTT compare against a target register that updates
once per beacon interval. Case analysis: scan_mode = 0 and the test clock mux select
pinned to functional for the functional STA run.
M2Q8 · A7. At 1 GHz in a modern FinFET node, roughly how many levels of logic fit in a cycle? Walk me through your estimate (FO4 or gate delays, flop overhead, skew/uncertainty budget).
Gemini Answer
- Clock period:
. - Overhead: Flop
; clock skew + jitter/uncertainty + OCV derate . - Remaining logic budget:
. - Gate + wire delay: A typical 2-input NAND/AOI gate plus local FinFET wire load is
(FO4 ). - Result: Roughly 18 to 24 levels of logic (fewer—around 12–15—if routing spans long wires or wide muxes/adders).
GPT Answer
Estimate using the actual library: 1 ns - flop overhead - uncertainty/skew - routing. For example, 200 ps overhead plus 150 ps wiring leaves 650 ps; at 25-40 ps per effective logic level that is roughly 16-26 simple levels. This is a planning estimate, not a FinFET guarantee.
Claude Answer
1 GHz = 1000 ps. Ask the library first. Typical 5 nm: clk-to-q ≈ 60–80 ps, setup ≈
30–50 ps, skew + jitter/uncertainty ≈ 80–120 ps, so roughly 750–800 ps of logic. FO4 ≈ 12–15
ps, but a real NAND2/NOR2 with FO3 and wire ≈ 25–35 ps. That is about 22–30 simple gate
levels, or in datapath terms: a 32-bit adder (~8–10 levels) plus a mux, not a multiplier.
M2Q9 · A8. What are path groups in PrimeTime, and why would you want reg-to-reg separated from in-to-reg when reading a first report?
Gemini Answer
- What they are: Buckets (
reg2reg,in2reg,reg2out,in2out, and per-clock groups) that STA optimizes and reports separately. - Why separate
reg2regfromin2reg: I/O paths (in2reg/reg2out) often have placeholder or overly aggressive 70% external delay constraints early in the project; separating them prevents fake I/O violations from hiding real internalreg2regcritical paths (or distracting the synthesis optimizer).
GPT Answer
Path groups organize optimization/reporting by clocks or endpoint classes. Separate register/register from input/register so poor I/O budgets do not obscure internal critical paths.
Claude Answer
Path groups are the buckets PrimeTime reports worst paths in (per clock by default,
plus in2reg, reg2out, reg2reg if you create them). Input/output delays are often
guesses that dominate the first report; separating reg-to-reg lets you see the real
internal worst path and lets synthesis weight the groups separately.
M2Q10 · A9. Max transition / max capacitance violations: are they timing bugs? What do they mean for the RTL author?
Gemini Answer
- Are they timing bugs? They are Electrical Design Rule Violations (DRVs), though slow slew (
max_transition) also degrades downstream cell delay and causes crosstalk/short-circuit power issues. - What they mean for RTL: Usually a high-fanout control signal (e.g., a clear/enable driving 1,000 flops without pipelining) or a huge combinational mux across a large floorplan. RTL can help by registering/duplicating high-fanout control flops.
GPT Answer
Transition/capacitance violations are electrical design-rule failures, and can invalidate delay assumptions or hurt power/reliability. Reduce fanout and mux load, localize control, or coordinate buffering/replication with PD.
Claude Answer
No, they are design-rule violations. Outside the characterized transition/cap range
the delay model is invalid, and slow edges hurt timing, noise and crowbar current. For the
RTL author they mean a high-fanout net or a huge mux: replicate the register, build a
fanout tree, or pipeline the enable (out_ready, resets, clock enables are usual suspects).
M2Q11 · A10. Register retiming in synthesis: what does it do, what does it break downstream (name at least LEC and DFT), and how do you contain the damage?
Gemini Answer
- What it does: Moves registers forward or backward across combinational logic cones to balance stage delays without changing input-to-output latency.
- What it breaks:
- LEC (Conformal): One-to-one register key-point mapping fails because the flops moved across logic and changed count/width.
- DFT / Reset: Reset values cannot easily be pushed backward across complex logic, and scan-chain/debug signal names become unrecognizable (
clk_r_REG123_S2).
- How to contain: Restrict retiming to dedicated arithmetic submodules (
set_optimize_registers trueonly on multiplier/divider wrapper), use reset-less datapath stages inside the retimed boundary, and export the synthesis.svfguidance file for Conformal LEC.
GPT Answer
Retiming moves registers across logic while preserving an allowed sequential behavior. It complicates register matching, resets, scan planning, and debug. Limit its scope and use an equivalence flow that understands the transformation; regenerate DFT artifacts if implementation changes.
Claude Answer
Retiming moves flops across combinational logic to balance stages. It breaks the
register correspondence LEC depends on (you need sequential equivalence or a retiming-aware
flow), changes which flops exist for scan chains and may give a moved flop a reset value
that can't be expressed, kills signal visibility for debug and ECO. Contain it: enable only
inside a specific arithmetic module with fixed boundary registers, no resets on the
retimed flops, retime once and freeze, keep a sequential-equivalence checkpoint.
M2Q12 · A11. Latency vs. throughput: a 5-stage pipeline with a 1-cycle bubble every 4 transfers — what is its throughput, and what does that cost in a system with fixed SIFS deadlines?
Gemini Answer
- Throughput:
( ). - Cost in a SIFS-constrained MAC: SIFS in 5/6 GHz is fixed at
. A 20% throughput loss on frame parsing, BA generation, or length calculation stretches processing latency by 25%, eating directly into the 2–3 MAC turnaround window.
GPT Answer
One bubble per four transfers gives 4/5 transfer/cycle after fill. A five-stage pipeline adds about five cycles of latency, depending on convention. Account for bubbles, queuing, and dependencies in the complete RX-to-TX deadline; do not assume one SIFS value for every PHY.
Claude Answer
4 transfers per 5 cycles = 0.8 transfers/cycle, latency 5. SIFS (16 µs at 5/6 GHz)
is shared by PHY RX end, MAC response build and PHY TX preamble; a 20% throughput loss on
a per-byte or per-MPDU pipeline (crypto, FCS) scales with frame size and eats margin we
don't own. On a per-PPDU block it's noise.
M2Q13 · A12. You have a 32-bit × 16-bit multiply followed by a ceil-divide by a small variable integer. Describe how you would implement this without a divider and how many cycles it would take at a tight clock.
Gemini Answer
- No-divider implementation: Store precomputed fixed-point reciprocals
in a small LUT indexed by the variable divisor (with ). Compute quotient estimate , and verify exactness (or apply a 1-step remainder check if (q * d < P) q = q + 1). - Cycles at tight clock (640 MHz): 3 to 4 cycles (Stage 1:
multiply → 48-bit product ; Stage 2–3: reciprocal multiply + shift; Stage 4: remainder check / round-up adjustment).
GPT Answer
Use a reciprocal table for supported divisors, a pipelined multiply, then an exact remainder correction. Bound approximation error to prove the correction count. Budget roughly 4-6 arithmetic cycles plus decode, subject to mapped timing; repeated subtraction has data-dependent worst-case latency.
Claude Answer
Multiply: 32×16 → 48 bits, two stages at a tight clock (hand-split the partial
products, or a library Booth/Wallace cell). Ceil-divide by a small-set variable d:
reciprocal ROM r = ceil(2^k/d) with k ≥ numerator width, q = ((n + d − 1) · r) >> k,
then one correction if (q·d > n + d − 1) q−1. Two stages for the reciprocal multiply,
one to two for the correction multiply, one for the compare: about 6 cycles total.
Alternative if latency is free: a radix-4 restoring divider, 2 bits/cycle, tiny.
M2Q14 · A13. How do you decide where to cut a datapath into stages? Name three signals/heuristics.
Gemini Answer
- Minimum cut-set width (bit-width bottleneck): Cut where the total number of bits crossing the boundary is smallest (e.g., after an adder tree reduction or encoder rather than across all partial products).
- Logic-depth symmetry (~15–20 FO4 levels): Cut right after heavy arithmetic blocks (multipliers, wide carry-propagate adders, SRAM outputs) and before high-fanout muxes.
- Control/handshake boundaries: Keep tightly coupled feedback loops inside a single stage so you don't introduce stall bubbles.
GPT Answer
Cut around multiplier/compressor trees, long carry/decode paths, and high-fanout control. Balance physical delay and register cost; carry all metadata/valid bits through the same cuts.
Claude Answer
Cut (1) where the bit width is smallest (fewest flops, cleanest valid), (2) after
each operator of comparable depth so stages balance, (3) before high-fanout decode or
large muxes, (4) so every stage reads only from the previous stage (no skip paths),
(5) never through a recurrence — a feedback loop can't be pipelined without changing the
algorithm. Then let the first synthesis report move the cuts.
M2Q15 · A14. When is a combinational output from a block acceptable at an IP boundary, and what do you document for the integrator?
Gemini Answer
- When acceptable: Only when latency is strictly critical (e.g., combinatorial
readyor fast SRAM request) and agreed upon in the architecture spec. - What to document: Maximum combinational delay budget (e.g.,
of clock period = ), driving cell strength, and the corresponding set_output_delayin the block SDC.
GPT Answer
A combinational boundary is acceptable with an agreed input/output delay budget, no handshake loop, and documented load/fanout. Deliver SDC, latency, operating modes, and the cross-block timing contract.
Claude Answer
Acceptable when it is specified and budgeted: the IP's SDC carries set_input_delay
/ set_output_delay (or max_delay) for that path, the integration guide has a timing
budget table ("bb_ready is combinational from bb_valid, ≤ 300 ps"), and the protocol
allows it (AXI ready may depend combinationally on valid). Default is registered.
Part B — Deep dive: re-pipeline the Tx length-parameter datapath (0:20–0:55)
The Tx path must compute, per PPDU, the number of OFDM symbols and the padding/length
fields that go into the PHY preamble. A simplified version of the legacy block:Inputs (valid for one cycle with tx_start): psdu_len_bytes[19:0] // A-MPDU length mcs[3:0], nss[2:0], bw[2:0], ldpc, stbc, dcm, gi_ltf[1:0] n_users[2:0] // MU: up to 8 users per-user: ru_size[3:0], mcs_u[3:0], nss_u[2:0] (serially, one per cycle after tx_start) Steps (legacy, combinational, constrained as a 3-cycle multicycle path): 1. N_DBPS = lookup(mcs, nss, bw/ru_size, dcm) // 1 of ~1500 table entries 2. N_SYM_init = ceil( (8*psdu_len + 16 + 6*(~ldpc)) / N_DBPS ) 3. if stbc: N_SYM = 2*ceil(N_SYM_init/2) 4. if ldpc: run the 802.11 LDPC encoding-parameter procedure: N_pld, N_avbits, N_cw, L_LDPC, N_shrt, N_punc, N_rep -> may add one extra symbol 5. TXTIME = T_preamble(bw, nss, gi_ltf, n_users) + N_SYM * T_SYM(gi) 6. For MU: N_SYM is the MAX over users of per-user N_SYM; each user then gets pre-FEC padding so all users finish at the same symbol. 7. Output: n_sym, txtime_us, per-user pad bits, legacy L-SIG length = ceil((TXTIME - 20us)/4) * 3 - 3 - m (where m is a per-PPDU constant)Target: 640 MHz MAC clock, 5 nm. The 3-cycle multicycle path has caused two timing
escapes in the last generation because the PD team did not get the-holdside right.
Your job: remove it.
M2Q16 · B1. Clarify
- (5 min) Clarify. Ask the interviewer whatever you need: how often does a new PPDU
arrive (latency budget)? Is the per-user loop allowed to serialize? Which outputs are
needed first by the PHY?
Gemini Answer
- PPDU arrival rate & SIFS latency budget: Only one PPDU starts at a time, and PHY needs
TXTIME/L-SIG length/N_SYMwithin 150 ns (~96 clocks at 640 MHz) oftx_start. - Serial per-user loop: Since 8 MU users serialized at 1 user/cycle takes only 8 cycles + pipeline depth (~15 cycles total
), we can share a single pipelined arithmetic engine across all 8 users rather than instantiating 8 parallel dividers!
GPT Answer
Ask for PPDU initiation interval, worst-case latency, first PHY-needed output, per-user arrival schedule, buffering/backpressure, supported rate matrix, and exact LDPC/rounding rules. Three-bit user/NSS fields need an explicit encoding for eight. Confirm whether outputs may be streamed or must retire atomically.
Claude Answer
1. Clarify (what I'd ask and the assumed answers)
- New PPDU rate? One per PPDU, ≥ SIFS apart, so a latency budget of hundreds of cycles.
- May the MU per-user loop serialize? Yes, up to 8 users, one per cycle.
- Which outputs first? TXTIME and L-SIG length (preamble), then N_SYM and per-user pad.
- Can
tx_startarrive while a previous computation is in flight? Assume no; I'll add a
busyoutput and an assertion rather than design for it. - How many distinct N_DBPS values in this generation? Assumed small (tens). If it's
hundreds, the reciprocal ROM is no longer free and I switch to the sequential divider.
M2Q17 · B2. Draw the pipeline
- (15 min) Draw the pipeline. Propose a stage-by-stage breakdown. For each stage name
the arithmetic it contains and why you believe it closes at 640 MHz. Specifically address:
- replacing the ceil-divide by a variable
N_DBPS(hint:N_DBPStakes a small number of
distinct values; or reciprocal-multiply; or iterative subtract — justify your choice),- the serial per-user loop for MU and the running MAX,
- the LDPC extra-symbol decision, which depends on the result of step 2,
- the L-SIG length formula, which depends on TXTIME.
Gemini Answer
Task 2: Stage-by-Stage Pipeline Breakdown (640 MHz, 1.56 ns period)
[S0: Input Latch & Factored N_DBPS Decode]
- Register per-user (mcs_u, nss_u, ru_size, ldpc, stbc, dcm)
- Lookup N_SD (12b), N_BPSCS*R numerator/denominator, and 36-bit Reciprocal R_NDBPS = ceil(2^36 / N_DBPS)
- Compute num_bits = (psdu_len_bytes << 3) + 16 + (ldpc ? 0 : 6) [24-bit adder]
|
[S1: Reciprocal Multiply Stage 1 (Partial Products)]
- Start 24-bit (num_bits) * 36-bit (R_NDBPS) -> Wallace tree reduction / Stage 1 of 2-stage pipelined mult
- In parallel: finish factored N_DBPS[15:0] exact integer value
|
[S2: Reciprocal Multiply Stage 2 & Initial N_SYM_init]
- Complete 60-bit product; quotient estimate q = prod[59:36]
- Exact ceil-divide adjustment: because R_NDBPS = ceil(2^36 / N_DBPS) and num_bits < 2^24,
ceil(num_bits / N_DBPS) == ((num_bits - 1) * R_NDBPS) >> 36 + 1 (exact with zero remainder multiply!)
- Apply STBC even-symbol rounding: n_sym_s2 = (stbc && q[0]) ? (q + 1) : q
|
[S3: LDPC N_avbits & Extra-Symbol Threshold Check]
- Compute N_avbits = N_DBPS * n_sym_s2 (16b x 12b mult)
- Compare shortening/puncturing inequality: does N_punc exceed threshold -> ldpc_extra_sym (0 or 1, or 2 if STBC)
|
[S4: Running MU Max & Final N_SYM]
- n_sym_user = n_sym_s2 + (ldpc_extra_sym ? (stbc ? 2 : 1) : 0)
- Update running max across users: max_n_sym <= (first_user || n_sym_user > max_n_sym) ? n_sym_user : max_n_sym
|
[S5: TXTIME & L-SIG Length (Run once after last user finishes S4)]
- txtime_us = T_preamble + max_n_sym * T_sym(gi) (shift-add: T_sym is 13.6, 14.4, or 16.0 us in 0.4 us units)
- l_sig_len = ceil((txtime_us - 20) / 4) * 3 - 3 - m (shift by 2 + multiply by 3 via (x << 1) + x)
GPT Answer
| Stage | Work |
|---|---|
| S0 | Capture packet context; assign PPDU/user IDs; validate configuration. |
| S1 | Factored rate lookup, divisor/reciprocal selection, 24-bit numerator 8*len+16+tail. |
| S2-S3 | Reciprocal multiply with a real internal pipeline cut if required. |
| S4 | Multiply trial quotient by divisor. |
| S5 | Exact floor correction, then ceiling; STBC rounding. |
| S6-S8 | LDPC capacity/codeword arithmetic and exact extra-symbol decision; pipeline products and comparisons. |
| S9 | Update running maximum on completed user results; store per-user information. |
| S10-S11 | After last user completes, calculate common duration and L-SIG fields. |
| Padding pass | Derive each user's final padding from the common symbol count and coding rules. |
The stage count is a proposal, not proof of 640 MHz closure. LDPC common-duration selection may require another bounded adjustment pass; verify the standard's exact dependency rather than assuming independent per-user rounding always suffices.
Accept one user per cycle if resources support that initiation interval. The last serial user adds U-1 cycles; tagging and PPDU-level state prevent a late result from contaminating a new packet. Convert times to integer fine units, preserve fractional symbol duration, and apply each specified ceiling at the correct point. For L-SIG, implement ceiling division by 4 only after consistent unit conversion; guard subtraction and field overflow.
Claude Answer
2. Pipeline (all stages registered, a valid bit travels alongside)
| Stage | Contents | Why it closes at 640 MHz (1.56 ns) |
|---|---|---|
| S0 | Register inputs. Factored N_DBPS: N_SD(ru/bw,dcm) × N_BPSCS(mcs) × nss × R(mcs); same index selects recip = ceil(2^25 / N_DBPS) from a small ROM | Two small ROMs + one small multiply; the factored form is what replaced the 1500-entry case in my redesign |
| S1 | num = {psdu_len,3'b0} + 16 + (ldpc ? 0 : 6); num_c = num + N_DBPS − 1 (turns ceil into floor) | Two adders ≤ 25 bits |
| S2 | Hand-split partial products: num_c × recip[11:0], num_c × recip[22:12] | Each a 25×12 multiplier, ~25 gate levels |
| S3 | Sum partials; q_est = prod[25 +: 22] | One 48-bit add |
| S4 | q_est × N_DBPS (22×19) | Borderline; see plan B |
| S5 | n_sym_init = (q_est·d > num_c) ? q_est − 1 : q_est | Compare + decrement |
| S6 | STBC: n_sym = stbc ? n_sym_init + n_sym_init[0] : n_sym_init; LDPC: N_pld = n_sym_init × N_DBPS, N_avbits = N_CBPS × n_sym (two small multiplies, reuse S4-style split if needed) | Multiplies by values already in registers |
| S7–S8 | LDPC: pick L_LDPC by N_avbits range, N_cw, N_shrt, N_punc, the two punctuate/repeat tests → extra_sym; n_sym += extra_sym (×2 if stbc) | Compares and shifts; the divides in the spec are by constants (648/1296/1944) → constant-reciprocal multiplies |
| S9 | TXTIME = T_pre(bw,nss,gi_ltf,n_users) + n_sym × T_SYM(gi) in 0.1 µs units (136/144/160 → shift-adds selected by gi) | Constant multiplies |
| S10 | L-SIG: ceil((TXTIME − 20)/4)·3 − 3 − m → shift, round, shift-add | Trivial |
MU: per-user tuples stream through S0–S5 one per cycle; a running-MAX register collects
n_sym across users (the AP picks the max). After the last user, the common n_sym goes
through S6–S10 once, and the stored per-user N_DBPS_u stream through a second S4-style
multiply to produce pad_bits_u = n_sym × N_DBPS_u − bits_u (pre-FEC padding so every user
ends on the same symbol).
Why reciprocal-multiply over the alternatives: with k = 25 ≥ width(num_c) and
r = ceil(2^k/d), the estimate is floor(num_c/d) or one too big, never too small, so one
compare fixes it. Iterative subtract (radix-4, 12 cycles, ~300 gates) is smaller and I'd
pick it if the distinct-N_DBPS count makes the ROM big; it just can't stream MU users at
one per cycle. Dividing by each factor in turn (ceil(ceil(x/a)/b) = ceil(x/ab)) kills the
ROM but needs four divide stages — too much for the win.
M2Q18 · B3. Code one stage
- (10 min) Code one stage. Write the SystemVerilog for the stage containing the
ceil-divide, including its valid pipeline and any constant tables. Be explicit about
widths.
Gemini Answer
Task 3: Live Code — Stage S1/S2 Exact Reciprocal Ceil-Divide (SystemVerilog)
// Exact ceil(num_bits / n_dbps) for num_bits in [1 .. (5_484_000 * 8 + 22)] (< 2^26)
// identity: ceil(A / B) = floor((A - 1) / B) + 1 (for A >= 1)
// Choosing K = 36: with R = ceil(2^36 / B), floor(((A - 1) * R) / 2^36) + 1 == ceil(A / B)
// holds identically for all A < 2^26 and B < 2^16 because the maximum over-approximation
// error is (A - 1) * (1 - 1/B) < 2^26 < 2^36 / B.
module tx_nsym_div_stage (
input logic clk,
input logic rst_n,
input logic in_valid,
input logic in_stbc,
input logic [25:0] in_num_bits, // 8 * psdu_len + 16 + 6*(~ldpc), >= 16
input logic [35:0] in_recip_ndbps,// ceil(2^36 / N_DBPS) from factored LUT
output logic out_valid,
output logic [14:0] out_n_sym_init
);
// Stage 1: prepare (A - 1) and register inputs to multiplier
logic s1_valid, s1_stbc;
logic [25:0] s1_num_m1;
logic [35:0] s1_recip;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) s1_valid <= 1'b0;
else s1_valid <= in_valid;
end
always_ff @(posedge clk) begin
if (in_valid) begin
s1_stbc <= in_stbc;
s1_num_m1 <= in_num_bits - 26'd1;
s1_recip <= in_recip_ndbps;
end
end
// Stage 2: 26x36 multiply (synthesis maps/retimes across s2_prod_q if needed)
logic s2_valid, s2_stbc;
logic [61:0] s2_prod;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) s2_valid <= 1'b0;
else s2_valid <= s1_valid;
end
always_ff @(posedge clk) begin
if (s1_valid) begin
s2_stbc <= s1_stbc;
s2_prod <= s1_num_m1 * s1_recip;
end
end
// Stage 3: shift right by 36, add 1, and round up to even if STBC
logic [14:0] q_raw, q_stbc;
assign q_raw = s2_prod[50:36] + 15'd1;
assign q_stbc = (s2_stbc && q_raw[0]) ? (q_raw + 15'd1) : q_raw;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) out_valid <= 1'b0;
else out_valid <= s2_valid;
end
always_ff @(posedge clk) begin
if (s2_valid) out_n_sym_init <= q_stbc;
end
endmodule
GPT Answer
3. Exact ceil-divide example
Below is a complete arithmetic unit for a parameterized set of positive divisors. Default entries are illustrative, not the full Wi-Fi table. Generate D from the approved legal-rate reference. Numerator is 24 bits, divisor is 19 bits because the exercise's full rate range exceeds 16 bits. It accepts a new input each cycle; there is no output backpressure.
Let R=floor(2^24/D) and q0=floor(x*R/2^24). Since x<2^24, q0 is the exact floor quotient or one below it. Correct the floor first, then add one for a nonzero remainder. Merely incrementing q0 once when its product is below x does not always implement ceiling.
module ceil_div_set #(
parameter int ND = 3,
parameter int IDW = (ND > 1 ? $clog2(ND) : 1),
parameter logic [18:0] D [ND] = '{19'd12,19'd24,19'd36}
) (
input logic clk, rst_n, in_valid,
input logic [23:0] x,
input logic [IDW-1:0] d_id,
output logic out_valid,
output logic [24:0] y
);
wire [24:0] recip [ND];
for (genvar g=0; g<ND; g++) begin : g_recip
// Elaboration-time division only. Contract: every D[g] > 0.
assign recip[g] = 25'd16777216 / D[g];
end
logic [3:0] v;
logic [48:0] product_q;
logic [23:0] x1, x2, x3, q2, floor3;
logic [18:0] d1, d2;
logic [42:0] trial_product, p2, floor_product3;
logic [24:0] next_q;
always_comb begin
trial_product = 43'(product_q[47:24]) * 43'(d1);
next_q = {1'b0,q2} + 25'd1;
end
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) v <= '0;
else v <= {v[2:0], in_valid && (int'(d_id) < ND)};
end
always_ff @(posedge clk) begin
if (in_valid && (int'(d_id) < ND)) begin
product_q <= 49'(x) * 49'(recip[d_id]);
x1 <= x;
d1 <= D[d_id];
end
if (v[0]) begin
q2 <= product_q[47:24];
p2 <= trial_product;
x2 <= x1;
d2 <= d1;
end
if (v[1]) begin
if (p2 + 43'(d2) <= 43'(x2)) begin
floor3 <= next_q[23:0];
floor_product3 <= p2 + 43'(d2);
end else begin
floor3 <= q2;
floor_product3 <= p2;
end
x3 <= x2;
end
if (v[2]) y <= {1'b0,floor3} + 25'(floor_product3 != 43'(x3));
end
assign out_valid = v[3];
endmodule
This code specifies four registered arithmetic steps; assigning a multiply to one register does not automatically pipeline its internal logic. If timing fails, split the multiplier itself and extend valid/metadata latency. HDL compilation is unverified in this environment.
Claude Answer
// q = ceil(num / n_dbps) via reciprocal multiply and one correction.
// Preconditions: num < 2^NUM_W, 6 <= n_dbps < 2^DIV_W,
// recip == ceil(2^K / n_dbps) with K >= NUM_W+1.
// Then q_est = floor(num_c * recip / 2^K) is exact or one too large, never too small.
module ceil_div_stage #(
parameter int NUM_W = 24,
parameter int DIV_W = 19,
parameter int K = 25,
parameter int RCP_W = 23, // ceil(2^25 / 6) needs 23 bits
parameter int Q_W = 22 // 2^24 / 6 < 2^22
)(
input logic clk, rst_n,
input logic in_valid,
input logic [NUM_W-1:0] num, // 8*psdu_len + 16 + 6*~ldpc
input logic [DIV_W-1:0] n_dbps,
input logic [RCP_W-1:0] recip, // from the S0 ROM
output logic out_valid,
output logic [Q_W-1:0] q
);
localparam int NC_W = NUM_W + 1; // num + n_dbps - 1
localparam int RL = RCP_W / 2; // low half of recip
localparam int RH = RCP_W - RL;
localparam int P_W = NC_W + RCP_W;
// valid pipeline: the only reset flops in the stage
logic [5:1] v;
always_ff @(posedge clk or negedge rst_n)
if (!rst_n) v <= '0;
else v <= {v[4:1], in_valid};
assign out_valid = v[5];
// datapath registers, reset-less (qualified by v[])
logic [NC_W-1:0] nc1, nc2, nc3, nc4;
logic [DIV_W-1:0] d1, d2, d3;
logic [RCP_W-1:0] r1;
logic [NC_W+RL-1:0] pl2; // num_c * recip[RL-1:0]
logic [NC_W+RH-1:0] ph2; // num_c * recip[RCP_W-1:RL]
logic [P_W-1:0] prod3;
logic [Q_W-1:0] qe3, qe4;
logic [Q_W+DIV_W-1:0] qd4;
assign prod3 = P_W'(pl2) + (P_W'(ph2) << RL);
always_ff @(posedge clk) begin
// P1: ceil -> floor
nc1 <= NC_W'(num) + NC_W'(n_dbps) - 1'b1;
d1 <= n_dbps;
r1 <= recip;
// P2: hand-split multiplier (two half-width products)
pl2 <= nc1 * r1[RL-1:0];
ph2 <= nc1 * r1[RCP_W-1:RL];
nc2 <= nc1; d2 <= d1;
// P3: combine, take the integer part
qe3 <= prod3[K +: Q_W];
nc3 <= nc2; d3 <= d2;
// P4: back-multiply for the correction
qd4 <= qe3 * d3;
qe4 <= qe3; nc4 <= nc3;
// P5: estimate is exact or +1; never low
q <= (qd4 > (Q_W+DIV_W)'(nc4)) ? qe4 - 1'b1 : qe4;
end
endmodule
Width notes: num_c < 2^24 + 2^19 < 2^25, so K = 25 gives
num_c·(r − 2^K/d)/2^K < 1, which is the "at most one too big" guarantee.
M2Q19 · B4. Defend it
- (5 min) Defend it.
- What is the latency in cycles from
tx_starttotxtimevalid? Is it within SIFS
budget? (Interviewer will give you the number if you ask.)- Which stage would you bet fails timing first after place-and-route, and what is plan B?
- How does this design get verified against the legacy combinational version? What would
you keep from the old testbench?
Gemini Answer
- Latency: 6 pipeline stages + 8 cycles for 8 MU users = 14 cycles (
at 640 MHz), less than 0.2% of the SIFS budget. - Which stage fails timing first in P&R & Plan B: The
multiplier in S2 (or LDPC check in S3). Plan B: Split the multiply into two halves across two cycles (adds 1 cycle latency, 1.56 ns), or instantiate a DesignWare 2-stage pipelined multiplier ( DW02_mult_2_stage). - Verification against legacy combinational RTL: Wrap the legacy combinational RTL inside the UVM scoreboard as a cycle-accurate golden reference predictor, and run an exhaustive sweep over all legal
(MCS, NSS, RU, GI, LDPC, STBC, DCM)tuples plus boundarypsdu_len_bytesaround symbol roll-over edges (k * N_DBPS - 1,k * N_DBPS,k * N_DBPS + 1).
GPT Answer
- Latency: for the proposed 12-stage path, about
12+U-1cycles from first accepted user to common duration, plus any extra LDPC pass and user-input gaps. At 640 MHz, 19 cycles is about 29.7 ns for eight users. It fits a microsecond-scale budget only if upstream arrival and the remaining PHY/system work also fit. - Timing risk: multiplier or LDPC compare/fanout logic. Plan B: more internal pipeline cuts, localized metadata/register replication, or resource changes after synthesis/place reports.
- Verification: preserve legacy legal-rate regressions and monitors; compare by PPDU/user ID rather than fixed latency. Add independent mathematical checks, exact-division boundaries, overflow, LDPC extra-symbol boundaries, STBC parity, MU maxima/ties, reset/flush, and back-to-back packets. The legacy design is useful but cannot be the only oracle for inherited bugs.
Claude Answer
- Latency: SU ≈ 11 cycles
tx_start→txtime≈ 17 ns; MU with 8 users ≈ 11 + 8 + ~6
(padding pass) ≈ 25 cycles ≈ 40 ns. SIFS is 16 µs, so three orders of magnitude of slack,
which is exactly why the legacy MCP was an unnecessary risk. - Fails first: S4, the single-stage 22×19 back-multiply. Plan B: split it like S2
(two 22×10 products, add in the next stage), or drop the back-multiply entirely by using
a widerK(k = 25 + 19 makes the estimate exact with no correction, at the cost of a
44-bit reciprocal — bigger multiply, so that's the second choice). Third choice: library
Booth multiplier with retiming confined to that module and sequential equivalence. - Verification: the legacy combinational block becomes the golden model in the
scoreboard, with a per-PPDU compare of every output after the pipeline latency. Keep the
existing full rate-matrix sweep (every a/b/g/n/ac/ax/be MCS × nss × bw/ru × dcm/ldpc/stbc),
add directed boundaries wherenum mod N_DBPS ∈ {0, 1, N_DBPS−1}and the LDPC
N_avbitsthresholds, keep the coverage bins, and add stage-valid andbusyassertions.
Formal equivalence of the divide stage againstceil(num/d)for alldin the ROM
closes the arithmetic argument without relying on simulation.
Part C — Your questions (0:55–1:00)
M2Q20 · Questions for the interviewer
Gemini Answer
- "What is the synthesis clock-uncertainty / over-constraint margin target at RTL hand-off before physical design takes over?"
- "How does your team manage SDC ownership—do RTL designers write and maintain block-level
.sdcfiles directly in git alongside the RTL?" - "How early in the project do RTL owners get post-placement trial timing reports back from Innovus/Fusion Compiler?"
GPT Answer
Who owns SDC exceptions? When are post-place timing reports available to RTL? What latency/frequency margin is expected at handoff?
Claude Answer
- How early do RTL engineers see post-place timing, and is there an RTL hand-off margin
policy (close at +10% over target)? - Who owns the SDC through SoC integration, and how are IP-level exceptions reviewed?
- Is retiming allowed anywhere in the flow today, and how is LEC run on those blocks?
Additional notes
Notes. Material not tied to a question
Gemini Answer
No answer in gemini_answer.md.
GPT Answer
Practice answers; proposed cycle counts and architectures are estimates, not additional resume claims.
Claude Answer
No answer in claude_answer.md.