Skip to content
VLSI Mentor

USB · Module 11

Handshake Packets

Four one-byte packets and a silence: the difference between not now and not ever, and why a reference model reported zero divergence on a design that was wrong.

Chapter 11.2 left a device acknowledging. It said nothing about what happens when it cannot.

That is this chapter, and it is carried by the smallest packets in the protocol: a PID and nothing else. No address, no payload, no CRC beyond the PID's own check field. One byte.

1. Four Answers and a Silence

PacketPIDLow nibbleMeans
ACK0xD20010Received and accepted
NAK0x5A1010Not now. Try again
STALL0x1E1110Not ever. Do not try again
NYET0x960110Took this one; no room for the next

Every low nibble ends in 10 — the handshake group, one of Chapter 11.5's four groups of four.

And there is a fifth response that is not a packet: silence. A device that says nothing has said something quite specific, and §3 is about what.

2. Not Now Versus Not Ever

The central distinction, and the one that determines a device's entire error model.

NAK means the condition is transient. A buffer is full, data is not ready yet, the firmware has not got to it. Nothing is wrong. The host should retry, and it will succeed once the condition clears.

NAK is not an error. It is flow control.

On a typical bulk endpoint NAKs vastly outnumber ACKs — the host polls faster than the device produces, and most polls are answered not yet. Chapter 10.4 §4's nothing new is exactly this, seen from the wire.

STALL means the condition is permanent. The endpoint has halted, or the request is one this device cannot satisfy. Retrying is pointless, and the host must stop and take explicit recovery action — Chapter 11.2 §4's ClearFeature(ENDPOINT_HALT), which also resynchronises the toggle.

Confusing them fails in both directions, and neither failure is quiet:

  • NAK where STALL belongs: the host retries a condition that will never clear. The endpoint spins forever, consuming bus capacity, with no error reported to anybody. From outside it looks like an extremely slow device.
  • STALL where NAK belongs: the host abandons a transfer for a condition that would have cleared on its own microseconds later. A full buffer becomes a failed transfer, and the driver sees a halted endpoint that nothing was actually wrong with.

3. Silence Is an Answer

A device that transmits nothing has said something the four packets cannot.

Silence means I did not reliably receive this. Its only correct use is a transaction whose data failed its CRC — Chapter 11.6's verdict.

Why not answer a corrupted packet? Because every answer would be a lie:

  • ACK claims the data was accepted. It was not.
  • NAK claims the device could not take it now, implying it received it and understood the request. It did not.
  • STALL claims a permanent condition. Corruption is not one.

And there is a deeper reason. A device whose CRC failed does not know that the packet was for it. Chapter 11.1 §4 made the same argument for tokens: a device that cannot trust what it received cannot know that a reply would be addressed to the right party. Answering risks transmitting over another device's transaction.

Silence is also what the host is prepared for. It timed out waiting; the timeout path already exists; and a timeout is exactly the signal nothing reliable happened, which is true.

4. NYET, and Why It Exists

NYET says: I took this packet, and I have no room for the next one.

It is high-speed only, and it exists as a bandwidth optimisation rather than a correctness mechanism. Without it a high-speed host discovers a full endpoint by sending a full-size data packet and being NAKed — the whole payload is transmitted and thrown away. At high speed that is an expensive way to ask a question.

NYET lets the device answer the question in advance. The host, told there is no room for the next packet, asks with a tiny PING packet instead of a full one, and only sends real data once the answer is affirmative.

Which makes NYET a hint, not a refusal — and this is the part that is easy to get backwards:

NYET acknowledges the current transaction. It is ACK plus a warning, not a form of NAK.

A device that treats NYET as a refusal will have accepted a packet and told the host it did not — and Chapter 11.2's toggle will then be one step apart at the two ends, which is the wedge that chapter measured.

5. The SETUP Exemption

One rule overrides everything above:

A SETUP transaction may never be refused. Not NAKed, not STALLed, not by a halted endpoint, not by a full one.

Because the alternative is a device that can make itself unmanageable. Chapter 10.2 §1 established that control transfers are how a host manages a device it has not yet agreed anything with; a device that could decline the opening of that conversation could refuse the very request that would fix it — including the ClearFeature(ENDPOINT_HALT) that clears the halt causing the refusal.

The design consequence is concrete and often missed: a control endpoint must always have room for a SETUP. Not usually. Always. That storage cannot be shared with anything that might be occupied, and it must survive whatever condition has halted the endpoint.

This rule is also where the module's own development went wrong, which §8 reports rather than hides.

A block diagram of handshake selection in priority order. An active transaction first tests whether the payload arrived intact; if not, the device stays silent. Next it tests whether the transaction is a SETUP, which may never be refused and bypasses both refusal tests. Then it tests whether the endpoint is halted, which produces a STALL meaning do not retry. Then it tests whether the endpoint is ready, and if not produces a NAK meaning retry later. Then, on a high-speed device with no room for a following packet, it produces a NYET, which acknowledges this packet while warning about the next. Otherwise it produces an ACK.Transactiondata receivedIntact?Chapter 11.6Silencecannot trust itSETUP?never refusableHalted?permanentSTALLdo not retryReady?transientNAKretry laterACK / NYETtakennoyesSETUPelseyesnonoyes12
Figure 1 — the answer selection, in priority order. The order is not a style choice: each stage overrides the ones below it, and swapping any adjacent pair changes what the device tells the host about whether to try again.
A sequence diagram of three phases of a bulk transfer. In the first phase the host sends an IN token and the device answers with a negative acknowledgement because its buffer is not yet ready; the host retries and gets another negative acknowledgement; on the third attempt the data is ready and the device sends it, and the host acknowledges. In the second phase an error halts the endpoint, and the host's next IN token receives a stall rather than a negative acknowledgement; the host stops retrying. In the third phase the host issues a ClearFeature endpoint halt request on the control endpoint, which cannot be refused; the device acknowledges it, the halt is cleared and the data toggle resynchronised, and a subsequent IN token is answered with data normally. An annotation notes that the negative acknowledgement loop ended because the device's condition cleared, while the stall loop ended because the host was told to stop.Retry, stop, and recoverHostBulk endpointControl endpointINNAK — not yetIN (retry)NAK — still not yetIN (retry)DATA — the conditioncleared…later: an errorhalts the endpointINSTALL — do not retryhost STOPS. no moreIN tokensSETUP:ClearFeature(ENDPOINT_HALT)ACK — a SETUP isnever refusedhalt cleared ·toggle → DATA0INDATA — recovered
Figure 2 — the same endpoint answering three ways. The NAK loop terminates on its own because the condition clears; the STALL loop terminates because the host stops and takes action. Swapping the two answers turns either into a loop that never ends.

6. The Handshake Selector, as RTL

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// usb_handshake_select
//
// Classification: SIMPLIFIED SYNTHESIZABLE TEACHING RTL. It models the
// choice of answer at the end of one transaction.
//
// WHAT IT MODELS. Sections 2 to 5 as a priority chain: silence beats every
// answer, a SETUP beats every refusal, permanent beats transient, and a
// warning rides along with an acceptance.
//
// WHAT IT DOES NOT MODEL. The handshake PACKET -- its PID bits, framing and
// transmission (Module 14); the halt condition's own lifecycle, which is
// set by a request or an error and cleared only by ClearFeature (Module 13);
// the PING protocol NYET enables (Module 12); the transaction timing that
// decides WHEN this answer must be on the wire; and the endpoint buffer
// whose occupancy produces `ep_ready` (Chapter 9.5).
//
// ── ON THE PRIORITY ORDER ───────────────────────────────────────────────
// The order of the branches below is the specification, not a style
// preference. Every adjacent swap is a real defect and section 7 measures
// three of them. Written as an if/else chain rather than a case so that the
// precedence is syntactically visible rather than implied.
// ─────────────────────────────────────────────────────────────────────────
module usb_handshake_select (
  input  logic clk,
  input  logic rst_n,

  input  logic txn_active,    // a transaction is concluding now
  input  logic is_setup,      // section 5 -- overrides every refusal
  input  logic ep_halted,     // sticky; cleared only by ClearFeature
  input  logic ep_ready,      // room to accept / data to send
  input  logic data_ok,       // Chapter 11.6: the payload's CRC passed
  input  logic hs_capable,    // high speed -- NYET exists at all
  input  logic space_after,   // room for ANOTHER packet after this one

  output logic send_ack,
  output logic send_nak,
  output logic send_stall,
  output logic send_nyet,
  output logic send_nothing   // section 3 -- an answer, not an absence
);

  // SECTION 5, AS ONE SIGNAL. Making the exemption a named term rather than
  // repeating `&& !is_setup` on each refusal is what keeps the two refusal
  // paths from drifting apart -- and section 8 reports what happened when
  // this block did NOT have it.
  logic may_refuse;
  assign may_refuse = !is_setup;

  logic refuse_forever, refuse_for_now;
  assign refuse_forever = ep_halted && may_refuse;
  assign refuse_for_now = !ep_ready && may_refuse;

  always_comb begin
    send_ack     = 1'b0;
    send_nak     = 1'b0;
    send_stall   = 1'b0;
    send_nyet    = 1'b0;
    send_nothing = 1'b0;

    if (!txn_active) begin
      send_nothing = 1'b1;
    end else if (!data_ok) begin
      // SECTION 3. Every possible answer would assert something false, and
      // a device that cannot trust the packet cannot know a reply belongs
      // to this transaction at all.
      send_nothing = 1'b1;
    end else if (refuse_forever) begin
      // SECTION 2. Permanent beats transient: an endpoint that is both
      // halted and full is halted, and saying NAK would invite a retry that
      // can never succeed.
      send_stall = 1'b1;
    end else if (refuse_for_now) begin
      send_nak = 1'b1;
    end else if (hs_capable && !space_after && may_refuse) begin
      // SECTION 4. NYET is an ACCEPTANCE carrying a warning. It sits here,
      // below both refusals, because it is not one.
      send_nyet = 1'b1;
    end else begin
      send_ack = 1'b1;
    end
  end

endmodule

What it models. The selection of one of five responses at the end of a transaction.

Engineering reason. Because the choice between not now and not ever is the whole of a device's error model, and it is one bit on the wire.

Inputs. Whether a transaction is concluding, whether it is a SETUP, the endpoint's halt and readiness, the CRC verdict, and two facts about high-speed capability.

State retained. None. The halt condition is sticky, but it is stored elsewhere and arrives here as an input — this block is the decision, not the memory.

Outputs. Five mutually exclusive indications, one of which is transmit nothing.

Hardware implied. A priority encoder over five conditions. Tens of gates.

Reset behaviour. Nothing to reset. clk and rst_n are present for §7's properties.

Assumptions. That data_ok is meaningful for this transaction; that ep_halted is the sticky condition rather than a momentary one; that is_setup comes from Chapter 11.1's filter and is therefore already addressed to this device; and that space_after refers to the packet after the one being answered.

Omissions. The packet itself, the halt lifecycle, the PING protocol, the timing and the buffer — in the header.

What DV should verify. That exactly one response is produced, always; that a SETUP is never refused; that a corrupted payload is never answered; that a transient condition never produces STALL; that a permanent condition never produces NAK; and that NYET never appears where a refusal belongs.

Every answer a device can give

8 cycles
A waveform of handshake selection over eight transactions. In the first, the payload is intact and the endpoint is ready, so an acknowledgement is sent. In the second the endpoint is not ready, so a negative acknowledgement is sent meaning retry later. In the third the endpoint is halted, so a stall is sent meaning do not retry. In the fourth the payload failed its check, so nothing is transmitted at all. In the fifth the endpoint is both halted and not ready, but the transaction is a SETUP, which may never be refused, so it is acknowledged anyway. In the sixth the device is high speed and has no room for a following packet, so a NYET is sent, which accepts this packet while warning about the next. In the seventh the endpoint is still halted and a stall is sent again. In the eighth the endpoint has recovered and an acknowledgement is sent.not now — retrynot now — retrynot ever — stopnot ever — stopcorrupt — say nothingcorrupt — say nothinghalted AND full, but SETUP: ACKhalted AND full, but SETUP:ACKtransactionOUTOUTOUTOUTSETUPOUTOUTOUTdata_okep_haltedep_readyis_setupresponseACKNAKSTALLnoneACKNYETSTALLACKsilencet0t1t2t3t4t5t6t7
Figure 3 — eight transactions covering every response, every column taken from a simulation of the block above. Cycle 4 is the one to study: the endpoint is both halted and full, and because the transaction is a SETUP it is acknowledged regardless.

7. Mutation Test

Four mutations over 528 stimuliall 128 input combinations exhaustively, plus 400 randomised. Exhaustive coverage is affordable here because the block is combinational with seven inputs, and §9 argues that changes what the bench owes.

The unmutated block's response histogram, which the mutant columns are read against:

ACK 77 · NAK 14 · STALL 32 · NYET 8 · silence 397 — with 0 violations of every obligation.

ACKNAKSTALLNYETsilenceobligation violated
golden7714328397
H1 NAK where STALL belongs774608397permanent made retryable: 32
H2 STALL where NAK belongs770468397transient made fatal: 14
H3 answer a corrupt payload77164328247corrupt answered: 150
H4 SETUP refusable2029739397SETUP refused: 56

Each mutation zeroes or inflates exactly one response class and violates exactly one obligation — which is the shape a priority chain's mutation table should have, and a useful check that the obligations are independent rather than restatements of each other.

H1 — NAK where STALL belongs

Measured: STALL disappears entirely — 32 occurrences become NAKs.

The device now reports a permanent condition as transient. The host retries, forever, and every individual packet is well formed and correct. §2's callout is the consequence: nothing anywhere is told that anything is wrong.

And note what the histogram does not show. ACK, NYET and silence are unchanged. A bench checking that the device acknowledges what it should, refuses what it should and stays silent when it should passes completely — the defect is entirely in which kind of refusal.

H2 — STALL where NAK belongs

Measured: NAK disappears — 14 occurrences become STALLs.

The mirror image, and the less dangerous one. A full buffer becomes a halted endpoint; the driver is told a transfer failed; somebody gets an error to search for.

The measurement makes §2's asymmetry concrete: H1 and H2 are the same edit in opposite directions, H1 corrupts more responses (32 versus 14), and H2 is the one you will hear about.

H3 — answer a corrupt payload with NAK

Measured: silence drops from 397 to 247 — 150 transactions answered that should have had no answer.

The largest count of the four, and the least subtle failure, because it breaks §3's rule on every corrupted packet rather than on some condition. A device that NAKs a bad CRC tells the host I received this and cannot take it now, when the truth is I do not know what I received, or whether it was for me.

The practical damage is worse than a wrong answer. The device may be transmitting over another device's transaction — it never established that the packet was addressed to it.

H4 — allow a SETUP to be refused

Measured: 56 refused SETUPs. ACK falls from 77 to 20; STALL more than doubles, from 32 to 73.

§5's rule removed. A halted control endpoint now refuses the very request that would clear the halt, and the device becomes unrecoverable by any means short of a bus reset.

It is also the mutation with the largest footprint in the histogram, moving three of the five columns — because the SETUP exemption sits above both refusal tests and therefore affects every path below it.

8. What Went Wrong While Writing This Block

The first version of the RTL above refused SETUPs, and the reference model agreed with it.

The exemption was written as ep_halted && !is_setup on the permanent path and plain !ep_ready on the transient one. STALL was correctly suppressed for a SETUP; NAK was not. A SETUP arriving at a busy control endpoint was answered not now, which §5 says may never happen.

The reference model reported zero divergences, across all 128 exhaustive combinations, because it had been written from the same understanding as the RTL — the same !is_setup on one branch and not the other.

What caught it was a check written from the rule instead of from the design:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
if (txn_active && data_ok && is_setup && (send_stall || send_nak)) setup_refused++;

It fired 34 times.

9. The Assertions

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// Classification: TEACHING ASSERTIONS about the handshake selector.
// X is exclusivity. O-properties are the OBLIGATIONS -- each one is a
// sentence from sections 2 to 5, written in the specification's terms and
// deliberately NOT derived from the RTL. Section 8 is why.
// ─────────────────────────────────────────────────────────────────────────

// X1 -- EXACTLY ONE RESPONSE, ALWAYS. Including "nothing", which is why this
// is $onehot and not $onehot0: a transaction with no response at all is a
// distinct defect from one with two.
property p_exactly_one_response;
  @(posedge clk) disable iff (!rst_n)
    $onehot({send_ack, send_nak, send_stall, send_nyet, send_nothing});
endproperty
assert property (p_exactly_one_response);

// O1 -- A SETUP IS NEVER REFUSED. Section 5. The property that would have
// caught the defect in section 8 on the first run.
property p_setup_never_refused;
  @(posedge clk) disable iff (!rst_n)
    (txn_active && data_ok && is_setup) |-> (!send_stall && !send_nak);
endproperty
assert property (p_setup_never_refused);

// O2 -- A CORRUPT PAYLOAD IS NEVER ANSWERED. Section 3.
property p_corrupt_gets_silence;
  @(posedge clk) disable iff (!rst_n)
    (txn_active && !data_ok) |-> send_nothing;
endproperty
assert property (p_corrupt_gets_silence);

// O3 -- A TRANSIENT CONDITION IS NEVER FATAL. Section 2. Note that the
// antecedent names the CONDITION (not halted, not ready) rather than the
// design's internal `refuse_for_now`: an obligation that referenced the
// design's own term would inherit the design's own misunderstanding.
property p_transient_not_fatal;
  @(posedge clk) disable iff (!rst_n)
    (txn_active && data_ok && !ep_halted && !ep_ready && !is_setup) |-> send_nak;
endproperty
assert property (p_transient_not_fatal);

// O4 -- A PERMANENT CONDITION IS NEVER RETRYABLE. Section 2, the other way.
property p_permanent_not_retryable;
  @(posedge clk) disable iff (!rst_n)
    (txn_active && data_ok && ep_halted && !is_setup) |-> send_stall;
endproperty
assert property (p_permanent_not_retryable);

// O5 -- NYET IS AN ACCEPTANCE. Section 4: it may only appear where the
// alternative was ACK, never where a refusal belonged. Stated as what must
// be TRUE when NYET is sent, so that it constrains NYET's placement in the
// priority chain rather than merely its encoding.
property p_nyet_only_over_ack;
  @(posedge clk) disable iff (!rst_n)
    send_nyet |-> (txn_active && data_ok && !ep_halted && ep_ready && hs_capable);
endproperty
assert property (p_nyet_only_over_ack);

// I1 -- AND NOTHING IS SENT OUTSIDE A TRANSACTION.
property p_idle_is_silent;
  @(posedge clk) disable iff (!rst_n)
    !txn_active |-> send_nothing;
endproperty
assert property (p_idle_is_silent);

O3 and O4 are the pair that pins §2. Each states one direction of the not now / not ever distinction, and neither implies the other — H1 violates O4 while satisfying O3, and H2 does the reverse. A single property covering both would have to encode the whole decision, which would make it a reference model in property clothing and lose §8's independence.

O5's shape is the one to copy. The temptation is to write NYET implies not NAK, which is trivially true given X1. Instead it states the full set of conditions under which NYET is permitted — which constrains where it sits in the priority chain, not merely that it is distinct from the others.

10. Verification

This chapter's commit point is the host was told the right kind of thing about whether to try again.

Stimulus. All 128 combinations of the seven inputs, exhaustively — the block is combinational and small enough that this is affordable, plus 400 randomised stimuli to catch state that should not exist.

Observation. All five outputs plus a histogram of the response classes, which is what makes §7's table readable — a mutation that converts one class into another is visible as a zero, and a zero in a class that should occur is a stronger signal than a count that merely shifted.

Reference model. A five-way priority chain. §8 is an extended argument about its limits: it is worth having for the errors it does catch, and it must never be the only thing in the bench.

Coverage — the crosses are the 128 combinations, but three deserve naming because they are where the rules live:

  • is_setup × ep_halted × ep_readyall eight, including SETUP, halted and full, which is §5's rule at full strength and the cell §8's defect lived in
  • data_ok low × every other input — silence must dominate all of them
  • hs_capable × space_after × ep_ready — NYET's placement relative to both refusals

Negative cases with defined outcomes: never two responses; never zero; never an answer to a corrupt payload; never a refused SETUP; never STALL for a transient condition; never NAK for a permanent one; and never NYET where a refusal belonged.

11. Debugging: the Transfer That Never Completes and Never Fails

A bulk transfer hangs. The application waits indefinitely. No error is reported. A protocol analyser shows continuous, well-formed traffic between host and device for as long as you care to watch.

What does well-formed traffic, forever tell you? That both ends are working correctly at the packet level and disagree about something at the transfer level. Nothing is malformed; the conversation simply never concludes.

What are the candidates? Exactly two, and the trace separates them immediately:

  • The device is NAKing continuously. It is saying not yet, and the host is obediently retrying.
  • The device is not responding and the host is timing out. Different trace, different fix.

Given a trace full of NAKs, what next? Ask whether the condition can clear. A device NAKing because its buffer is full will stop when the firmware drains it. A device NAKing because its endpoint is halted will never stop — and that is §7's H1.

How do you tell those apart from outside? Try to provoke the condition to clear. If the transfer completes when you reduce the rate or give the device idle time, it is genuine flow control. If nothing you do on the host side changes anything, the device is reporting a permanent condition as transient.

And the confirming test? Issue ClearFeature(ENDPOINT_HALT). If the endpoint recovers, it was halted all along — and the device should have been sending STALL, because STALL is what tells the host to issue that request in the first place. The device knew; it just described the condition wrongly.

Why is no error reported? Because no layer has anything to report. Every packet is valid, the device is answering promptly, and the host's retry logic is behaving exactly as designed. The error is in the meaning of a correct packet, and no amount of protocol validation detects that.

The signature to keep: a transfer that never completes and never fails, with a clean trace, is a NAK that should have been a STALL — and the test that confirms it is whether an explicit halt-clear makes the problem disappear.

12. Common Misconceptions

13. Reason It Through

A device's bulk IN endpoint returns STALL under heavy load and works fine when lightly loaded. The firmware author insists nothing sets the halt condition, and inspection of the code confirms it — there is no code path that halts this endpoint.

If nothing halts the endpoint, where is the STALL coming from? Either the halt input is asserted by something other than the intended code path, or the selection logic is producing STALL without a halt. §7's H2 is exactly the second.

What does only under load suggest? That the trigger is the condition which load produces — a full buffer, which is §2's transient case. So the shape is: the transient condition is being answered with the permanent response, and load simply makes the transient condition frequent.

Is the firmware author wrong? No, and this matters. They are right that nothing halts the endpoint — and the bug is real anyway, because STALL is being sent without the halt. Looking for the code that sets the halt is looking for something that does not exist, which is why this class of bug consumes days.

What is the single most useful next observation? The value of the halt condition at the moment STALL is transmitted. If halt is low and STALL goes out, the selection logic is wrong and the search should move out of the firmware entirely.

Could it be the host's interpretation instead? Possible but unlikely, and testable: a second host would have to make the same mistake. Test the cheap hypothesis first — but note that the device sends STALL and the host reports a stall are different claims, and only a bus trace distinguishes them.

And what makes this expensive in practice? The symptom points at the halt condition, and the halt condition is innocent. The evidence for the real fault is a signal that is not asserted — and a missing assertion leaves no trace anywhere, which is why the trace shows only the consequence and never the cause.

14. Understanding Check

15. Summary

Handshake packets are one byte: a PID and nothing else. Four of them — ACK, NAK, STALL, NYET — plus silence, which is a defined response rather than an absence.

The central distinction is not now versus not ever. NAK is flow control, not an error, and outnumbers ACK on a typical bulk endpoint. STALL is permanent and requires explicit recovery. They differ by one bit in the PID's low nibble — because PID values are chosen for detectability, not semantic distance.

Confusing them fails asymmetrically. STALL-for-NAK fails a transfer and gets reported. NAK-for-STALL spins forever with every packet well formed and nothing anywhere reporting a fault — the device has told the truth in each packet and lied about the whole.

Silence answers a corrupted payload, because every alternative asserts something false and because a device that cannot trust the packet cannot know its reply belongs to this transaction.

NYET is an acceptance with a warning, not a refusal — high-speed only, and a bandwidth optimisation rather than a correctness mechanism.

And a SETUP may never be refused, which forces a control endpoint to always have room for one. §7 measured all four mutations against 128 exhaustive input combinations: NAK-for-STALL corrupted 32 responses; STALL-for-NAK, 14; answering a corrupt payload, 150; a refusable SETUP, 56 — each violating exactly one obligation and leaving the others clean.

§8 is the chapter's hardest lesson, and it is about this module's own development. The first version of the block refused SETUPs on the NAK path. The reference model reported zero divergences across all 128 combinations, because it had been written from the same misunderstanding. A one-line obligation, phrased in the specification's own words, found it immediately.

Zero divergence against a reference model is evidence that the design matches your understanding. It is not evidence that your understanding is right.

And §10 pairs that with Chapter 11.1's finding to make the general point: that bench asked the right question of too little stimulus; this one asked the wrong question of all of it. Exhaustive coverage removes every excuse about reachability and none about what you are checking — and a coverage report measures only the first.

16. What Comes Next

Three packet types down, and every one of them was addressed to somebody. The next is addressed to nobody at all.

Chapter 11.4 is SOF Packets — the start-of-frame, broadcast to the whole bus, carrying an 11-bit frame number and expecting no reply. It is how every periodic guarantee in Module 10 actually gets its timebase, and Chapter 11.1 §2 already showed what happens to a decoder that mistakes its frame number for an address.

The chapter's real subject is what a device should do when an SOF fails to arrive — because the frame number is a shared clock, and a clock you only hear about intermittently has to be maintained rather than merely received.

Browse the full path on the USB tutorials index.

Continue learning

Standards & specifications

Governing standard
USB-IF (Universal Serial Bus Specification)(opens USB Implementers Forum (USB-IF) in a new tab)

Defines the USB bus — its electrical signalling, connectors, packet and transaction model, device framework and the descriptors a device must expose — together with the device-class specifications layered on it. It does not define host-controller register interfaces (xHCI and EHCI are separate documents) nor any operating system's driver architecture.

This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.

Where this fits

Part of the USB curriculum.