Skip to content
VLSI Mentor

USB · Module 11

Data Packets

Two PIDs carrying identical data and one alternating bit: why it advances on acknowledgement rather than arrival, and the two bench defects that hid two of four mutations.

Chapter 11.1 named a destination. This packet carries something to it — and its interesting content is not the payload.

It is a single bit in the PID, and that bit exists to answer a question the token never had to ask.

1. The Problem the Payload Cannot Solve

A device receives a data packet, stores it, and acknowledges it. The acknowledgement is corrupted on the way back.

The host now knows nothing useful. It did not hear an acknowledgement, and there are two completely different reasons for that:

  • the device never got the data, or
  • the device got the data, acted on it, and the reply was lost.

The host cannot distinguish them, and the two need opposite responses. In the first case it must resend. In the second, resending delivers the same payload twice.

Nothing in the payload helps. The bytes of a retransmission are identical to the bytes of the original — that is what makes it a retransmission. A device comparing content cannot tell a repeat from a genuine second packet that happens to say the same thing, and on a bus carrying keystrokes or sensor samples, saying the same thing twice is completely ordinary.

2. The Four Data PIDs

PIDFull byteLow nibbleUsed by
DATA00xC30011Everything
DATA10x4B1011Everything
DATA20x870111High-speed high-bandwidth isochronous only
MDATA0x0F1111High-speed high-bandwidth isochronous and split transactions

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

DATA0 and DATA1 are the pair that alternates, and for almost every endpoint on almost every bus they are the only two that appear.

DATA2 and MDATA exist for a case Chapter 10.5 §3 already introduced: a high-speed isochronous endpoint may claim up to three transactions per interval, and when it does, the three packets within one interval need distinguishing from one another rather than from a retransmission. There is no retry for isochronous, so the toggle's usual job does not apply — what these PIDs carry is position within the interval, which is a different question with a similar-looking answer.

The rest of this chapter is about DATA0/DATA1, because that is where the state machine lives.

3. What the Toggle Actually Tracks

Both ends keep one bit. The rule is simple to state and is mis-implemented constantly:

The receiver accepts a packet when its PID matches what the receiver expects, and advances its bit only when the transaction completes.

Unpacking that into the three behaviours it produces:

Match → accept and advance. The expected packet arrived. Hand the payload up, acknowledge, and flip.

Mismatch → acknowledge, but discard. This is a retransmission of a packet already accepted. The acknowledgement is the important half — the host is retrying because it did not hear the first one, and it will keep retrying until it does. The data is thrown away because it is already upstairs.

No acknowledgement possible → say nothing. Covered in Chapter 11.3.

A block diagram of the data toggle decision. An arriving data packet whose CRC passed is compared against the receiver's expected PID. If the PID matches, the payload is handed to the endpoint, an acknowledgement is sent, and only then does the expected PID advance to the other value. If the PID does not match, the packet is recognised as a retransmission of something already accepted: the payload is discarded, an acknowledgement is still sent, and the expected PID does not move. A third path shows the resynchronisation events — bus reset, set configuration, clear endpoint halt and a setup token — which write the expected PID directly regardless of any packet.DATA packet inCRC16 already passedPID = expected?one XNORAccepthand payload upDiscardwe already have itAcknowledgeBOTH paths do thisAdvance the bitaccepted AND ackedResync eventswrite it directlyPIDmatchmismatchoverride12
Figure 1 — the three dispositions of an arriving data packet, and the one path that advances the bit. Note that two of the three paths acknowledge: only a packet the device cannot answer at all leaves the host waiting, and that is §6's most destructive mutation.

4. The Resynchronisation Points

Two independently-held bits will eventually disagree, so the protocol defines moments at which both ends set theirs to a known value. Every one of them is an event that already resets something else, which is not an accident — a resynchronisation point has to be a moment both ends agree happened.

EventBoth ends set the toggle toWhy it is a safe point
Bus resetDATA0Chapter 8.3: the host is rebuilding its whole view of the device
SET_CONFIGURATIONDATA0Chapter 8.5: endpoints come into existence; nothing was outstanding on them
ClearFeature(ENDPOINT_HALT)DATA0The explicit recovery request. The endpoint was stalled, so the sequence was already broken
A SETUP tokenDATA1 for the data stageChapter 10.2: a control transfer always begins afresh

The SETUP row is the one that catches people. The SETUP packet itself is DATA0, and the stage that follows it is DATA1 — always, unconditionally, regardless of what the toggle was before. A control endpoint therefore does not carry its toggle across transfers; each one restarts, which is why a control endpoint can recover from a confusion that would wedge a bulk endpoint permanently.

A sequence diagram of a data transaction in which an acknowledgement is lost. The host sends an OUT token followed by a DATA0 packet. The device is expecting DATA0, so it accepts the payload, hands it to the endpoint, advances its toggle to DATA1, and returns an acknowledgement. The acknowledgement is corrupted and never reaches the host. The host, having heard nothing, retransmits the identical DATA0 packet. The device is now expecting DATA1, so the PID does not match; it recognises the packet as a retransmission, discards the payload because it already has it, does not advance its toggle, and acknowledges again. This acknowledgement arrives, the host advances its own toggle, and the next transaction carries DATA1, which the device accepts normally.A retransmission, correctly absorbedHostDevice endpointDevice firmwareOUT tokenDATA0 · payloadexpected DATA0 —accepttoggle → DATA1ACK … lost intransitDATA0 again —identical bytesexpected DATA1 —DISCARD, do notadvanceACK (again) — thisone arriveshost toggle → DATA1DATA1 · next payloadexpected DATA1 —accept
Figure 2 — the lost-acknowledgement case, which is the only reason the toggle exists. The device accepts the payload and acknowledges; the acknowledgement does not arrive; the host resends the identical packet. The device recognises it by its PID, discards the payload it already has, and acknowledges again. Nothing is delivered twice and nothing is lost.

5. The Toggle, as RTL

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// usb_data_toggle
//
// Classification: SIMPLIFIED SYNTHESIZABLE TEACHING RTL. It models section
// 3's rule and section 4's resynchronisation points for ONE endpoint in one
// direction.
//
// WHAT IT MODELS. Whether an arriving data packet is the expected one, what
// to do when it is not, and when the expectation advances.
//
// WHAT IT DOES NOT MODEL. The payload or its storage (Chapter 9.5); the
// CRC16 over it (Chapter 11.6 -- `data_rx_valid` already means "received
// and intact"); the handshake packet itself (Chapter 11.3 -- this block
// says a transaction completed, not what was transmitted to say so); the
// transaction sequencing (Module 12); DATA2 and MDATA (section 2 -- they
// answer a different question and do not use this machine); and the OTHER
// direction, which needs its own instance and its own bit.
//
// ── WHY `handshake_sent` IS AN INPUT ────────────────────────────────────
// Section 3's rule is that the bit advances on COMPLETION, and completion
// means both halves: the payload was taken AND the host was told. A block
// that advanced on `data_rx_valid` alone would be advancing on arrival,
// which is section 6's D1 and the most common real implementation error in
// USB device logic. Making the second half an explicit input is what forces
// the distinction to be visible in the port list.
// ─────────────────────────────────────────────────────────────────────────
module usb_data_toggle (
  input  logic clk,
  input  logic rst_n,

  // ── Section 4's resynchronisation points ────────────────────────────────
  input  logic bus_reset,       // Chapter 8.3
  input  logic ep_enabled,      // Chapter 9.3 -- an endpoint that does not
                                // exist holds no sequence
  input  logic toggle_clear,    // SET_CONFIGURATION, or
                                // ClearFeature(ENDPOINT_HALT)
  input  logic setup_received,  // a SETUP token arrived on this endpoint
  input  logic is_control_ep,

  // ── The transaction ─────────────────────────────────────────────────────
  input  logic data_rx_valid,   // a DATA packet arrived, CRC16 good
  input  logic rx_pid_is_data1, // DATA1 rather than DATA0
  input  logic handshake_sent,  // we acknowledged it -- see the header

  output logic expected_is_data1,
  output logic accept_payload,     // hand it up
  output logic discard_duplicate   // acknowledge it, but throw it away
);

  logic tog_q;
  assign expected_is_data1 = tog_q;

  // Derived, not stored (Chapter 8.4): the comparison has exactly one source
  // of truth and cannot drift from it.
  logic pid_expected;
  assign pid_expected = data_rx_valid && (rx_pid_is_data1 == tog_q);

  assign accept_payload    = pid_expected;

  // THE RETRANSMISSION PATH. Section 3: a mismatch is not an error, it is a
  // packet we already have. Acknowledging it is how the host escapes the
  // retry loop -- section 6's D4 measures what its absence costs, and the
  // answer is that the endpoint stops forever.
  assign discard_duplicate = data_rx_valid && !pid_expected;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      tog_q <= 1'b0;
    end else if (bus_reset || !ep_enabled) begin
      tog_q <= 1'b0;
    end else if (toggle_clear) begin
      tog_q <= 1'b0;
    end else if (is_control_ep && setup_received) begin
      // Section 4: the stage after a SETUP is DATA1, unconditionally,
      // whatever the bit was before. This is why a control endpoint can
      // recover from a desynchronisation that would wedge a bulk endpoint.
      tog_q <= 1'b1;
    end else begin
      // ADVANCE ON COMPLETION. Both terms are required and the second one is
      // the one people drop.
      if (accept_payload && handshake_sent) tog_q <= ~tog_q;
    end
  end

endmodule

What it models. One endpoint's sequence position, and the accept / discard decision derived from it.

Engineering reason. Because a lost acknowledgement is indistinguishable from a lost packet, and this bit is the only thing that distinguishes the responses.

Inputs. Four resynchronisation events, and three facts about an arriving transaction — that it arrived intact, which PID it carried, and whether we answered it.

State retained. One flip-flop. It is one of Chapter 9.1's 18 bits per endpoint.

Outputs. The current expectation, and the two mutually exclusive dispositions of an arriving packet.

Hardware implied. One flip-flop, one XNOR, and the priority chain of the reset conditions.

Reset behaviour. DATA0 on hard reset, bus reset, endpoint disable and toggle_clear; DATA1 on a SETUP at a control endpoint. The priority order matters — a bus reset during a control transfer must win over the SETUP rule, which is why it is tested first.

Assumptions. That data_rx_valid implies the CRC16 passed, so a corrupted packet never reaches this block; that handshake_sent refers to this transaction; and that setup_received is asserted only for a SETUP that was accepted by Chapter 11.1's filter.

Omissions. The payload, the buffer, the handshake packet, the transaction sequencing, DATA2/MDATA, and the opposite direction — all in the header.

What DV should verify. That no payload is delivered twice; that no payload is lost while the endpoint stays enabled; that a mismatched PID produces a discard and still an acknowledgement; that the bit does not advance without both completion terms; that each resynchronisation point lands; and that accept_payload and discard_duplicate are never asserted together.

One retransmission, absorbed

8 cycles
A waveform of the data toggle over eight cycles. In the first cycle a DATA0 packet arrives while DATA0 is expected, so the payload is accepted, an acknowledgement is sent, and the expectation advances to DATA1. The second cycle is idle. In the third a DATA1 packet arrives while DATA1 is expected, so it is accepted, acknowledged, and the expectation returns to DATA0. The fourth cycle is idle; the host did not hear that acknowledgement. In the fifth cycle the host retransmits the same DATA1 packet while DATA0 is now expected, so the packet is discarded rather than accepted, the expectation does not move, and an acknowledgement is nevertheless sent. The sixth cycle is idle. In the seventh a DATA0 packet arrives and is accepted, and in the eighth a DATA1 packet arrives and is accepted.accepted — but this ACK is lostaccepted — but this ACK islostRETRANSMISSION: discard, still ACKRETRANSMISSION: discard,still ACKhost advanced — back in stephost advanced — back insteprx PIDDATA0DATA1DATA1DATA0DATA1data_rx_validexpectedD0D1D1D0D0D0D0D1acceptdiscard_dupack sentt0t1t2t3t4t5t6t7
Figure 3 — eight cycles including one retransmission, every column taken from a simulation of the block above. At cycle 4 a DATA1 arrives while DATA0 is expected: the payload is discarded, the toggle does not move, and the acknowledgement is sent anyway. That last part is the whole mechanism.

6. Mutation Test

Four mutations over 538 transactions, in a bench where acknowledgements are lost one time in four and the host retries until it hears one. The conservation law:

payloads the host sent = payloads the device delivered, with every retransmission discarded rather than delivered

The unmutated block: 434 sent, 434 delivered, 104 retransmissions correctly absorbed, 0 divergences, 0 wedges.

delivered (of 434)delivered − senttoggle divergencesendpoint wedged
golden434000
D1 advance on arrival298−1362400
D2 set instead of toggle269−1652650
D3 ignore toggle_clear433−120
D4 no retransmission path22+20414

D1 — advance on arrival rather than on completion

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
if (data_rx_valid) tog_q <= ~tog_q;   // MUTANT D1

Measured: 136 of 434 payloads lost.

The device advances when the packet arrives. When an acknowledgement is lost, the host retransmits the same PID — but the device has already moved on and is expecting the other one, so it treats the retransmission as the next packet and accepts it as new data. The genuine next packet then looks like a duplicate and is discarded.

Every lost acknowledgement costs one real payload, silently, and §3's callout is why this survives casual testing: it is wrong only when something else already went wrong.

D2 — set the bit instead of toggling it

Measured: 165 of 434 payloads lost — the worst of the four.

A <= 1'b1 where <= ~tog_q belongs. The sequence stops alternating, so every second packet is misclassified from the first transaction onward. Loud, immediate, and caught by everything — included as the contrast case for D1, which loses fewer packets and is far harder to find.

D3 — ignore toggle_clear

Measured: 2 divergences and 1 lost payload across 538 transactions.

And this mutation initially escaped the bench entirely — 0 divergences — for reasons that had nothing to do with the design. §8 is about that.

The signature is minimal because a resynchronisation point only matters when the two ends were about to disagree. Most of the time the toggle already holds the value the clear would write, and the omission does nothing at all.

D4 — remove the retransmission path

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
assign discard_duplicate = 1'b0;   // MUTANT D4

Measured: 414 wedged endpoints; only 22 of 434 payloads got through.

A mismatched PID produces neither an accept nor a discard, so the device has no reason to acknowledge. The host retries. The device says nothing again. The endpoint stops permanently after the first lost acknowledgement.

And it too initially escaped, for a different reason than D3 — also §8.

7. The Assertions

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// Classification: TEACHING ASSERTIONS about the toggle.
// D-properties are the DISPOSITION contract (what happens to a packet).
// A-properties are the ADVANCE contract (when the bit moves).
// R-properties are the RESYNCHRONISATION points.
// ─────────────────────────────────────────────────────────────────────────

// D1 -- EXACTLY ONE DISPOSITION. A received packet is accepted or discarded,
// never both and never neither. The "never neither" half is what catches
// section 6's D4, and it is the half that is easy to leave out.
property p_one_disposition;
  @(posedge clk) disable iff (!rst_n)
    data_rx_valid |-> (accept_payload ^ discard_duplicate);
endproperty
assert property (p_one_disposition);

// D2 -- ACCEPTANCE IS EXACTLY A PID MATCH. An equivalence, not an
// implication: Chapter 9.5 measured that the implication form is satisfied
// by a design that accepts nothing.
property p_accept_iff_match;
  @(posedge clk) disable iff (!rst_n)
    accept_payload == (data_rx_valid && (rx_pid_is_data1 == expected_is_data1));
endproperty
assert property (p_accept_iff_match);

// A1 -- THE BIT ADVANCES ONLY ON COMPLETION. Section 6's D1. Note that the
// antecedent is the CHANGE and the consequent is the CAUSE: written the
// other way round it would be a weaker statement about sufficiency, and the
// defect here is one of INSUFFICIENT cause.
property p_advance_needs_completion;
  @(posedge clk) disable iff (!rst_n)
    (expected_is_data1 != $past(expected_is_data1))
      |-> $past(  (accept_payload && handshake_sent)
                || bus_reset || !ep_enabled || toggle_clear
                || (is_control_ep && setup_received) );
endproperty
assert property (p_advance_needs_completion);

// A2 -- AND IT DOES ADVANCE WHEN IT SHOULD. Without this, a bit that never
// moves satisfies A1 completely.
property p_advance_on_completion;
  @(posedge clk) disable iff (!rst_n)
    (accept_payload && handshake_sent && !bus_reset && ep_enabled
       && !toggle_clear && !(is_control_ep && setup_received))
      |=> (expected_is_data1 != $past(expected_is_data1));
endproperty
assert property (p_advance_on_completion);

// R1 -- THE RESYNCHRONISATION POINTS LAND. Section 6's D3. Grouped because
// they all write the same value for the same reason (section 4).
property p_resync_to_data0;
  @(posedge clk) disable iff (!rst_n)
    (bus_reset || !ep_enabled || toggle_clear) |=> !expected_is_data1;
endproperty
assert property (p_resync_to_data0);

// R2 -- A SETUP STARTS THE DATA STAGE AT DATA1. Section 4's row that catches
// people. The exclusion of the higher-priority resets is not a weakening --
// it is the priority order from the RTL, stated once.
property p_setup_to_data1;
  @(posedge clk) disable iff (!rst_n)
    (is_control_ep && setup_received && !bus_reset && ep_enabled && !toggle_clear)
      |=> expected_is_data1;
endproperty
assert property (p_setup_to_data1);

A1 and A2 must be written as a pair, and their shapes are deliberately different. A1 says the bit did not move without a cause; A2 says the cause did not fail to move it. A1 alone is satisfied by a bit that never moves; A2 alone by a bit that also moves at other times. Only together do they pin the update.

D1's ^ is doing real work. Writing it as accept || discard would allow both — and writing it as accept -> !discard would allow neither, which is exactly §6's D4. The exclusive-or is the only form that catches the failure in both directions, and it costs one character over the weaker version.

8. Verification

This chapter's commit point is every payload the host sent arrived upstairs exactly once.

Stimulus. A clean stream; a single lost acknowledgement followed by a retransmission; several consecutive lost acknowledgements; a bus reset mid-stream; a toggle_clear with the toggle deliberately set to DATA1 first; a SETUP on a control endpoint from each toggle value; and 400 randomised transactions with acknowledgements lost one time in four.

Observation. The expectation bit, both dispositions, and — the one that matters — a running count of distinct payloads the host sent against payloads the device delivered.

Reference model. Two models, doing different jobs. A next-state function for the bit, and a model host that holds its own toggle, retries until acknowledged, and advances only when it hears an acknowledgement. The second is what makes the bench meaningful, because the defect this chapter is about lives entirely in the disagreement between two independently-held bits, and a bench with only one of them cannot represent it.

Coverage — crosses:

  • expected × received PID × handshake_sentall eight, the mismatch-with-acknowledgement cell especially
  • consecutive lost acknowledgements: 1, 2, 3, 4
  • each resynchronisation event × toggle value DATA1 (the value at which the event does something)
  • SETUP × control and non-control endpoint
  • endpoint disabled mid-transaction

Negative cases with defined outcomes: no payload delivered twice; none lost while the endpoint stays enabled; never both dispositions at once; never neither; and the bit never moves without one of the five causes.

9. Debugging: the Endpoint That Stops Under Load

A bulk OUT endpoint works at low rates. Under sustained traffic it stops completely — not slowly, not intermittently. Once stopped it never recovers until the device is unplugged. The rate at which it stops scales with bus activity.

What does never recovers tell you? That it is not congestion. A busy device recovers when the load drops; this one does not, so the device and host are in states that cannot be reconciled by anything short of a reset.

What two states are held on both sides and never compared? The toggle. Nothing on the wire carries what the other end currently expects — each end infers it, and once the inferences diverge there is no message that says so.

Why would load matter? Because divergence needs a lost acknowledgement, and lost acknowledgements scale with traffic. Load does not cause the bug; it causes the precondition.

How do you confirm it from a trace? Look for the host retransmitting the same PID repeatedly with no acknowledgement. That is §6's D4. If instead the host is advancing normally and the device's data is wrong or missing, the device is accepting retransmissions as new — that is D1, and it looks like data corruption rather than a stall.

What distinguishes them in one observation? Whether the endpoint is silent or wrong. Silence means the device will not acknowledge a packet it should — a missing retransmission path. Wrong data means it acknowledges everything and mis-sequences — a toggle advancing at the wrong moment.

And why does unplugging fix it? Because reattachment forces a bus reset, which is §4's first resynchronisation point. A fault cured only by reattachment is a fault in state that only a bus reset clears — and that is a short list.

10. Common Misconceptions

11. Reason It Through

A device's bulk endpoint works with one host and fails with another. Both hosts are compliant. The failing combination works if a hub is inserted between them.

What can differ between two compliant hosts? Not the protocol. But plenty of timing: how quickly a host retries, how long it waits for an acknowledgement before giving up on one, how many transactions it pipelines back to back.

Why would inserting a hub help? A hub adds delay and repackages traffic. Anything that helps by adding delay is pointing at a timing margin, not at a protocol misunderstanding.

So what is the likely fault? The device is slow to produce its acknowledgement, and the faster host stops listening before it arrives. From the host's point of view the acknowledgement was lost, so it retransmits — and now everything depends on §3's retransmission path being correct.

Which means the visible failure may not be the actual defect. If the device handles retransmissions correctly, a slightly-too-slow acknowledgement costs throughput and nothing else. The failure appears only because a second bug is present — the retransmission path — and the timing issue merely exposes it.

How would you tell those apart? Count. If the host retransmits and the device recovers, the device's toggle logic is fine and the problem is purely one of speed. If the host retransmits and the endpoint stops, the toggle logic is broken and the timing is just what revealed it.

And what is the actual fix? Both, and in that order of priority. The retransmission path is a correctness defect that will eventually bite on any host. The acknowledgement timing is a performance defect. Fixing only the timing makes the symptom go away on this host and leaves the real bug in the product — which is the outcome to be most careful about, because it will look like a successful debug.

The transferable point: when a fault appears only in a fast configuration, separate the thing that made it visible from the thing that is wrong. They are usually not the same, and the one that made it visible is usually the one that gets fixed.

12. Understanding Check

13. Summary

A data packet's interesting content is one bit of its PID. It exists because a lost acknowledgement and a lost packet look identical to the host, and they need opposite responses — so the receiver answers a different question instead: is this the packet I expect, or the one I already have? That is a question about sequence position, which content cannot answer, and one bit suffices because only one packet is ever outstanding.

Four data PIDs exist; DATA0 and DATA1 alternate, and DATA2/MDATA answer a different question for high-speed high-bandwidth isochronous endpoints, which have no retry for the toggle to serve.

The rule is: accept on match, discard-but-still-acknowledge on mismatch, and advance only on completion. The acknowledgement on a mismatch is the half people drop, and it is the half that keeps the endpoint alive.

Four resynchronisation points — bus reset, SET_CONFIGURATION, ClearFeature(ENDPOINT_HALT) to DATA0, and a SETUP to DATA1 — each of them an event both ends already agree happened. The kernel keeps the host's half as unsigned int toggle[2], one bit per endpoint per direction, which is Chapter 9.3's budget confirmed from the other side of the wire.

§6 measured four mutations over 538 transactions with acknowledgements lost one time in four:

  • Advancing on arrival lost 136 of 434 payloads and is invisible on a bus where nothing is ever lost.
  • Setting instead of toggling lost 165 and fails on the second transaction of any stream — more damage, far less danger.
  • Ignoring toggle_clear produced 2 divergences, because a resynchronisation only matters when the ends were about to disagree.
  • Removing the retransmission path wedged the endpoint 414 times, permanently, after the first lost acknowledgement.

And §8 is the chapter's hardest lesson, because two of those four initially escaped and neither escape was about the design. One was a stimulus hole — the clear was applied to a value that was already correct. The other was a missing observation — the bench drove the acknowledgement that the design was supposed to cause, which silently replaced the behaviour under test with its own.

A bench that passes tells you nothing about the parts of it that were never really asking.

14. What Comes Next

The device in this chapter acknowledged. It has said nothing about what happens when it cannot.

Chapter 11.3 is Handshake PacketsACK, NAK, STALL and NYET — four packets of one byte each and no payload at all, which between them carry every negative answer the protocol can give. The distinction that matters is between “not now” and “not ever”: one invites a retry and the other forbids it, they differ by two bits on the wire, and confusing them produces either an endpoint that spins forever or a transfer abandoned for a condition that would have cleared on its own.

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.