USB · Module 12
Transaction Flow
Three stages in order, as a state machine — and the hardest problem in the module: two ends maintain separate beliefs about one transaction, and nothing on the wire reconciles them.
Three chapters described three stages in isolation. This one puts them in order, and the order is where the interesting failures live — because a sequencer has to answer three questions none of the stage chapters could.
What happens when a packet arrives that belongs to a different stage? How does a transaction end when the next stage never comes? And the hard one: what does a device believe about a transaction the host has already given up on?
1. The Shape, and Why It Is Not Three Stages
The canonical transaction is token → data → handshake. It is also not always three stages, and the exceptions are not edge cases:
| Transaction | Stages | Why |
|---|---|---|
| OUT / SETUP | token → data → handshake | the device receives, so the device answers |
| IN | token → data → handshake | the device sends, so the host answers |
| Isochronous | token → data | no retry, so nothing to acknowledge — Chapter 12.3 §2 |
| Any, interrupted | token → nothing | the device could not continue — Chapter 12.1 §2 |
The last row is the one a state machine must be designed around rather than patched for. A transaction that stops partway through is not an exceptional case: it is what every failure on the bus looks like from inside the sequencer, because Chapter 11.3 §3 established that the response to anything untrustworthy is silence.
A USB transaction has no error packet. Every failure presents identically: the next stage does not happen.
Which means a sequencer cannot be driven by events alone. Events tell it what arrived; nothing tells it what failed to arrive, and that is the more common case.
2. The Two Beliefs
The module's hardest idea, and it is worth stating before any RTL.
The host maintains a belief about the transaction. The device maintains its own. Nothing on the wire carries either one.
Each end infers the other's state from what it has seen — and the inferences diverge whenever a packet is lost, because a lost packet is invisible to the end that would have received it.
The four disagreements, and they are not symmetric:
| Lost packet | Host believes | Device believes |
|---|---|---|
| Token | a transaction is running | nothing is happening |
| OUT data | data was delivered | the token was never followed |
| IN data | the device is late | it has sent its data |
| Handshake | the transaction failed | the transaction succeeded |
The last row is the dangerous one, and it is the reason Chapter 11.2 exists: both ends are certain, both are reasoning correctly from what they saw, and they disagree about whether data was delivered.
3. Out of Phase
A packet arrives that belongs to a stage other than the current one. A handshake during the token stage; a data packet while waiting for a handshake.
It is not noise, and it is not usually a host error. The commonest cause is the disagreement of §2: the host has moved on and this device has not, so the host's packets are perfectly correct for its belief and wrong for this one.
Three possible responses, and only one is right:
- Act on it. Treat the handshake as though it concluded the stage. Wrong — it concludes a transaction this device is not in.
- Ignore it silently. Safe, and throws away the only evidence that the two ends have diverged.
- Ignore it and report it. Right. The packet cannot be acted on, and the fact that it arrived is diagnostic information available nowhere else.
An out-of-phase packet is the only direct evidence a device ever gets that its belief and the host's have diverged.
And it is cheap — a flag and a pulse. §6's F3 measures what its absence costs, and the answer is that it costs nothing functionally and removes the one signal that would explain a field failure.
4. Ending a Transaction Three Ways
A transaction leaves the sequencer by exactly one of three routes, and confusing them is §6's most damaging mutation.
Completed. The final stage happened. The endpoint's state advances — Chapter 11.2's toggle moves, the buffer is committed.
Abandoned. Either a timeout fired, or a new token arrived while this one was still open — Chapter 12.1 §6's overrun. Nothing advances. Partial state is discarded, and the endpoint is left exactly as it was before the token.
Ended by a bus reset. The whole device is being rebuilt (Chapter 8.3), so there is no transaction-level cleanup to do.
5. The Transaction Sequencer, as RTL
// ─────────────────────────────────────────────────────────────────────────
// usb_txn_pkg + usb_transaction_fsm
//
// Classification: SIMPLIFIED SYNTHESIZABLE TEACHING RTL. It sequences the
// three stages and, more importantly, handles the case where the next one
// never arrives.
//
// WHAT IT MODELS. Section 1's stage order including its exceptions, section
// 3's out-of-phase detection, and section 4's three endings.
//
// WHAT IT DOES NOT MODEL. Any packet (Module 11); the context the token
// creates (Chapter 12.1, consumed here as `token_accept` and its
// qualifiers); the data stage's termination rules (Chapter 12.2); which
// handshake to send (Chapter 11.3) or who sends it (Chapter 12.3); the
// timeout's duration and derivation (Chapter 12.5 -- `timeout` arrives here
// already expired); and the endpoint state that a completion advances.
//
// ── WHY THERE IS NO ERROR STATE ─────────────────────────────────────────
// Section 1: a USB transaction has no error packet, so there is no event
// that means "this went wrong". Every failure is the ABSENCE of the next
// stage, and absence is not an input -- which is why `timeout` is the only
// thing that can end a stalled transaction, and why removing it (section
// 6's F1) leaves the machine stuck rather than erroring.
// ─────────────────────────────────────────────────────────────────────────
package usb_txn_pkg;
typedef enum logic [2:0] {
T_IDLE = 3'd0,
T_TOKEN = 3'd1, // a token was accepted; awaiting the data stage
T_DATA_OUT = 3'd2, // data received from the host
T_DATA_IN = 3'd3, // data transmitted to the host
T_HS_SEND = 3'd4, // we owe a handshake (Chapter 12.3)
T_HS_WAIT = 3'd5, // we await the host's (Chapter 12.3)
T_DONE = 3'd6
} txn_state_e;
endpackage
module usb_transaction_fsm
import usb_txn_pkg::*;
(
input logic clk,
input logic rst_n,
input logic bus_reset,
// Chapter 12.1's filtered, captured token.
input logic token_accept,
input logic token_is_in,
input logic token_is_iso,
// Stage events. Note there is no `data_failed` or `hs_failed`: see the
// header. Failure is the absence of one of these.
input logic data_seen,
input logic data_sent,
input logic hs_seen,
input logic hs_sent,
input logic timeout, // Chapter 12.5
output txn_state_e state,
output logic txn_active,
output logic txn_complete, // section 4: the endpoint may advance
output logic txn_abandoned, // section 4: discard partial state
output logic out_of_phase // section 3: the beliefs have diverged
);
txn_state_e st_q;
logic complete_q, abandoned_q, oop_q;
assign state = st_q;
assign txn_active = (st_q != T_IDLE) && (st_q != T_DONE);
assign txn_complete = complete_q;
assign txn_abandoned = abandoned_q;
assign out_of_phase = oop_q;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
st_q <= T_IDLE; complete_q <= 1'b0; abandoned_q <= 1'b0; oop_q <= 1'b0;
end else if (bus_reset) begin
// Section 4's third ending. Note it does NOT raise `abandoned` -- see
// the callout there: every consumer of that signal is being reset too.
st_q <= T_IDLE; complete_q <= 1'b0; abandoned_q <= 1'b0; oop_q <= 1'b0;
end else begin
complete_q <= 1'b0; // all three are pulses, not levels
abandoned_q <= 1'b0;
oop_q <= 1'b0;
// ── A NEW TOKEN ALWAYS RESTARTS, FROM ANY STATE ────────────────────
// Chapter 12.1 section 2: the host owns the bus. A token arriving
// mid-transaction is not a request to be queued -- it is evidence the
// host has already abandoned the previous one. Gating this on T_IDLE
// (section 6's F4) makes the device unreachable after any disagreement.
if (token_accept) begin
if (st_q != T_IDLE && st_q != T_DONE) abandoned_q <= 1'b1;
st_q <= T_TOKEN;
end else if (timeout && st_q != T_IDLE && st_q != T_DONE) begin
// THE ONLY WAY A STALLED TRANSACTION ENDS. See the header.
st_q <= T_IDLE;
abandoned_q <= 1'b1;
end else begin
case (st_q)
T_TOKEN: begin
if (data_seen) st_q <= T_DATA_OUT;
else if (data_sent) st_q <= T_DATA_IN;
// Section 3: a handshake here belongs to a transaction we are
// not in. Not acted on -- but recorded, because it is the only
// direct evidence the two beliefs have diverged.
else if (hs_seen || hs_sent) oop_q <= 1'b1;
end
T_DATA_OUT: begin
// Chapter 12.3 section 2: isochronous has no third stage.
if (token_is_iso) begin st_q <= T_DONE; complete_q <= 1'b1; end
else st_q <= T_HS_SEND;
end
T_DATA_IN: begin
if (token_is_iso) begin st_q <= T_DONE; complete_q <= 1'b1; end
else st_q <= T_HS_WAIT;
end
T_HS_SEND: begin
if (hs_sent) begin st_q <= T_DONE; complete_q <= 1'b1; end
else if (data_seen) oop_q <= 1'b1;
end
T_HS_WAIT: begin
if (hs_seen) begin st_q <= T_DONE; complete_q <= 1'b1; end
else if (data_seen) oop_q <= 1'b1;
end
T_DONE: st_q <= T_IDLE;
default: st_q <= T_IDLE;
endcase
end
end
end
endmoduleWhat it models. The order of the three stages, and every way that order can fail to complete.
Engineering reason. Because failure on a USB bus has no packet — it is the absence of the next stage — so the sequencer is the only place that can notice.
Inputs. A token with two qualifiers, four stage events, a timeout, and a bus reset.
State retained. Three bits of state plus three pulse registers — 6 flip-flops.
Outputs. The state, an activity indication, and §4's three endings as pulses.
Hardware implied. A seven-state machine with a two-level priority in front of it.
Reset behaviour. Everything to T_IDLE on hard reset and bus reset, with no abandonment report — §4's documented exclusion.
Assumptions. That token_accept has passed Chapter 11.1's filters and Chapter 12.1's capture; that the four stage events are single-cycle and mutually exclusive within a stage; and that timeout arrives already expired rather than as a running count.
Omissions. Every packet, the context, the data-stage rules, the handshake choice, the timeout derivation and the endpoint state — in the header.
What DV should verify. That every accepted token ends exactly once — §4's law; that a transaction never remains active indefinitely; that a timeout while active always ends it on the next cycle; that a new token restarts from any state; that out-of-phase packets are reported and never acted on; and that completion and abandonment are never simultaneous.
One completed, one abandoned
10 cycles6. Mutation Test
Five mutations over 1,295 cycles and 180 accepted tokens, with a randomised phase driving tokens, all four stage events and timeouts independently — so that stage events routinely arrive in stages that do not expect them.
The unmutated design: 180 tokens = 47 completed + 132 abandoned + 1 ended by bus reset, conservation exact; 142 out-of-phase packets reported; 0 timeouts ignored; not stuck; longest active span 52 cycles.
| conservation | out of phase | timeout ignored | stuck at end | longest active | |
|---|---|---|---|---|---|
| golden | holds (47+132+1) | 142 | 0 | 0 | 52 |
| F1 no timeout path | FAILS (60+118+1) | 161 | 66 | 1 | 54 |
| F2 handshake accepted early | FAILS (27+79+1) | 16 | 0 | 0 | 26 |
| F3 no out-of-phase detection | holds | 121 | 0 | 0 | 52 |
| F4 token restarts only from idle | FAILS (57+29+1) | 118 | 0 | 0 | 35 |
F5 T_DONE never returns to idle | holds | 142 | 0 | 0 | 52 |
F1 — remove the timeout path
Measured: 66 timeouts ignored, conservation broken by 61 transactions, and the machine left stuck active at the end of the run.
The only exit from a stalled stage is gone. §1: there is no error packet, so nothing else can end a transaction whose next stage never arrives.
And the machine is not wedged permanently — a later token restarts it, which is why 118 abandonments still occurred. That is what makes it insidious: the device recovers on the next transaction, so the symptom is one lost transaction rather than a dead endpoint, and it recurs at exactly the rate packets are lost.
F2 — accept a handshake during the token stage
Measured: conservation broken by 73 transactions, and out-of-phase reports collapse from 142 to 16.
§3's first wrong answer. A handshake belonging to a transaction this device is not in is treated as concluding the current one — so a transaction ends on evidence from a different transaction.
Both effects are visible and they point in opposite directions, which is what makes this mutation legible: fewer transactions end properly and fewer anomalies are reported, because the anomalies are being consumed as normal events.
F3 — stop reporting out-of-phase packets
Measured: conservation holds. Nothing stuck. No timeouts ignored. Every transaction ends exactly as it should. The only change is 142 out-of-phase reports falling to 121.
No functional defect whatsoever — and §3's point arriving as a measurement. What is lost is the only direct evidence a device ever gets that its belief and the host's have diverged.
Whether that matters is a product decision, not an RTL one. A device that will never be debugged in the field does not need it. A device that will be is losing the signal that distinguishes the host is retrying because the bus is noisy from the host and I disagree about what transaction we are in — and those have entirely different fixes.
F4 — allow a token to restart only from idle
if (token_accept && st_q == T_IDLE) begin // MUTANT F4Measured: conservation broken by 93 transactions — the largest gap of the five. Abandonments collapse from 132 to 29.
Chapter 12.1 §2's rule removed. A device mid-transaction now ignores the host's new token entirely — and since the host has moved on, the device is waiting for a stage that will never come while refusing the only event that could rescue it.
The timeout does eventually free it, which is why it is not a permanent wedge. But the device misses every transaction issued during the wait, so a single disagreement costs several transactions rather than one.
F5 — T_DONE never returns to idle
Measured: nothing. Conservation holds, out-of-phase count identical, nothing stuck, longest active span unchanged at 52 cycles. Every observable is bit-identical to the golden design.
And it survives because it is genuinely unobservable — for a reason worth more than the mutation.
7. The Assertions
// ─────────────────────────────────────────────────────────────────────────
// Classification: TEACHING ASSERTIONS about the transaction sequencer.
// L-properties are the LIFECYCLE law; P the progress guarantees;
// O the out-of-phase contract.
// ─────────────────────────────────────────────────────────────────────────
// L1 -- EVERY TOKEN ENDS EXACTLY ONCE. Section 4's law, as a property over
// one transaction rather than as a run-level count. The three disjuncts are
// its three endings, and there is no fourth.
property p_token_ends_once;
@(posedge clk) disable iff (!rst_n)
token_accept |=> (!txn_complete && !txn_abandoned)[*0:$]
##1 (txn_complete || txn_abandoned || bus_reset);
endproperty
assert property (p_token_ends_once);
// L2 -- AND NEVER BOTH AT ONCE. Completion and abandonment mean opposite
// things to the endpoint -- one advances the toggle, one discards state --
// so a cycle asserting both is not merely redundant, it is contradictory.
property p_not_both_endings;
@(posedge clk) disable iff (!rst_n)
!(txn_complete && txn_abandoned);
endproperty
assert property (p_not_both_endings);
// P1 -- A TIMEOUT ALWAYS ENDS AN ACTIVE TRANSACTION, ON THE NEXT CYCLE.
// Section 6's F1. Bounded to one cycle deliberately: an unbounded
// "eventually" cannot fail in simulation, and Chapter 10.3 section 7
// measured what that costs.
property p_timeout_ends_it;
@(posedge clk) disable iff (!rst_n)
(timeout && txn_active && !token_accept && !bus_reset) |=> !txn_active;
endproperty
assert property (p_timeout_ends_it);
// P2 -- A TOKEN ALWAYS RESTARTS, FROM ANY STATE. Section 6's F4. Note the
// antecedent has no state qualifier at all -- that absence IS the property.
property p_token_always_restarts;
@(posedge clk) disable iff (!rst_n)
(token_accept && !bus_reset) |=> (state == T_TOKEN);
endproperty
assert property (p_token_always_restarts);
// P3 -- AND SUPERSEDING ONE REPORTS AN ABANDONMENT. Without this, F4's
// silent drop and a correct supersede are indistinguishable.
property p_supersede_abandons;
@(posedge clk) disable iff (!rst_n)
(token_accept && txn_active && !bus_reset) |=> txn_abandoned;
endproperty
assert property (p_supersede_abandons);
// O1 -- AN OUT-OF-PHASE PACKET NEVER ADVANCES THE MACHINE. Section 3's
// first wrong answer, and section 6's F2. Stated as what must NOT change,
// because "acting on it" has several shapes and "not moving" has one.
property p_oop_does_not_advance;
@(posedge clk) disable iff (!rst_n)
((state == T_TOKEN) && (hs_seen || hs_sent) && !token_accept
&& !timeout && !bus_reset) |=> (state == T_TOKEN);
endproperty
assert property (p_oop_does_not_advance);
// O2 -- AND IT IS REPORTED. Section 6's F3 -- the ONLY property that catches
// it, because F3 has no functional effect at all.
property p_oop_reported;
@(posedge clk) disable iff (!rst_n)
((state == T_TOKEN) && (hs_seen || hs_sent) && !token_accept
&& !timeout && !bus_reset) |=> out_of_phase;
endproperty
assert property (p_oop_reported);
// I1 -- ISOCHRONOUS NEVER REACHES A HANDSHAKE STAGE. Chapter 12.3 section 2
// enforced from the sequencer's side, so that the two blocks cannot drift.
property p_iso_no_handshake_state;
@(posedge clk) disable iff (!rst_n)
(txn_active && token_is_iso)
|-> (state != T_HS_SEND && state != T_HS_WAIT);
endproperty
assert property (p_iso_no_handshake_state);L1 is the lifecycle law as a property, and it is worth contrasting with the run-level count §4 used. The count catches an imbalance; the property catches which transaction was imbalanced — and on a 1,295-cycle run with 180 transactions, the difference is between knowing something is wrong and knowing where.
P2's antecedent is bare, and that is the property. A token restarts the machine with no qualification about the current state is exactly §4's rule, and F4 is the mutation that adds a qualification. A property whose strength is in what it omits is unusual and worth recognising — the temptation is always to add the state check that makes it "more precise", which would make it satisfied by the defect.
O1 and O2 must both exist. O1 alone is satisfied by a machine that ignores everything; O2 alone by one that reports and also acts. §6's F2 violates O1 and F3 violates O2, and neither property catches the other's mutation.
8. Verification
This chapter's commit point is every transaction that started, ended — exactly once, and for a reason the endpoint could act on.
Stimulus. Clean transactions of all four shapes (OUT, IN, isochronous OUT, isochronous IN); transactions the host abandons, with silence and then a timeout; a handshake arriving during the token stage; a new token superseding an open transaction; a bus reset mid-transaction; 1,200 randomised events driving tokens, all four stage events and timeouts independently; and finally 30 forced timeouts and 10 idle cycles, to establish that the machine returns to rest.
Observation. The state every cycle, the three ending pulses, the out-of-phase pulse, a running count of accepted tokens against endings (§4's law), and the longest span any transaction stayed active — which is the measurement that catches a machine that never exits, independently of whether it ends things correctly.
Reference model. Deliberately none for the state itself. §4's conservation law and the liveness bound do the work instead, and both are stated in the protocol's terms rather than the design's. Chapter 11.3 §8 measured what a reference model sharing the design's assumptions is worth; for a sequencer, a second state machine would share them completely.
Coverage — crosses:
- transaction shape (OUT / IN / iso-OUT / iso-IN) × ending (complete / timeout / supersede / bus reset)
- each of the four stage events × each of the seven states — 28 cells, most of them out of phase
- timeout arriving in each active state
- a new token arriving in each state,
T_DONEincluded - consecutive abandonments without an intervening completion
Negative cases with defined outcomes: no transaction ends twice; none ends zero times; complete and abandoned never coincide; an out-of-phase packet never advances the state; and no transaction remains active beyond a timeout.
9. Debugging: the Endpoint That Recovers Too Slowly
A bulk endpoint on a busy bus achieves far less throughput than expected. It never stalls and never reports errors. A trace shows the host frequently retrying, and every retry eventually succeeds. Throughput is roughly a third of what the bus should support.
What does every retry eventually succeeds tell you? That nothing is broken in the data path. The bytes are correct when they arrive. The cost is entirely in time.
Where does the time go? Each retry costs whatever the host waited before deciding to retry — and Chapter 12.5's timeout is short, so a few retries should cost very little. A third of the bus is not a few retries.
So what multiplies it? §6's F4 is the shape: a device that ignores the host's new token while waiting out its own stalled transaction loses every transaction issued during that wait, not just the one that failed. One disagreement costs several transactions.
How do you confirm it from the trace? Count. Compare the number of tokens the host issued to this endpoint against the number the device answered. If the device answered fewer, it was deaf for part of the time — and the length of each deaf window is the device's own timeout.
What if the device answered every token? Then it is not deafness, and the throughput loss is in the retry rate itself — a signal-integrity problem rather than a sequencing one, and a completely different investigation.
What is the single most useful device-side signal? §5's out_of_phase. It fires exactly when the device receives a packet belonging to a transaction it is not in, which is the direct observation of §2's divergence. A device that reports it turns this investigation into one measurement.
And §6's F3 is why many devices cannot do this. The flag costs a register and has no functional effect, so it is the first thing removed in a size review — and it is the only thing that would have made this failure diagnosable from the device side.
The signature to keep: throughput loss with no errors and successful retries is a recovery-latency problem — and the question is not why the retry happened but how long the device was unavailable afterwards.
10. Common Misconceptions
11. Reason It Through
A device's sequencer is being reviewed. A reviewer proposes adding a
T_ERRORstate entered whenever a packet arrives out of phase, exited on the next token. The argument: the machine currently ignores such packets, and ignoring an anomaly is how bugs hide.
Is the premise right? Partly. Ignoring anomalies silently is how bugs hide — which is why §5 already reports them on out_of_phase.
What would the new state add? It would make the machine stop making progress until a token arrives. Currently an out-of-phase packet leaves the state alone, so the transaction continues and can still complete.
Is stopping better or worse? Worse, and for a reason specific to this protocol. §2: an out-of-phase packet usually means the host has moved on. The transaction in progress on this device is already doomed. But not always — a spuriously-decoded packet, or another device's traffic that passed this device's filters, produces the same event on a transaction that is perfectly healthy.
So the proposal trades a certainty for a possibility. It guarantees the current transaction fails, in exchange for making an anomaly more visible — and the anomaly is already visible on a dedicated output.
Is there a version of the proposal that is right? Yes, and it is the useful part of the review: count them. An out-of-phase packet is a pulse; a rate of out-of-phase packets is diagnostic. A saturating counter costs a few bits and turns a transient into a trend, without changing behaviour at all.
What is the general principle? Do not let a diagnostic change behaviour. Chapter 10.5 §6 made the same point from the other direction — a flag that made coalescing visible without altering the data stream. A signal that reports is free to be wrong; a signal that acts is not, and conflating them means an over-sensitive detector becomes an availability problem.
And what should the reviewer be told? That the concern is right, the mechanism already exists, and the improvement is a counter rather than a state. Rejecting the proposal while accepting the argument is the correct outcome, and saying so explicitly is what keeps the next review useful.
12. Understanding Check
13. Summary
A transaction is three stages when nothing goes wrong, and something else otherwise. Isochronous has two; an interrupted transaction has one. And because USB has no error packet, every failure presents identically — the next stage does not happen — which is why a timeout is the only exit from a stalled stage, and why a sequencer cannot be driven by events alone.
The module's hardest idea is §2: the two ends maintain separate beliefs about one transaction, and nothing on the wire carries either. A lost handshake leaves the device certain it succeeded and the host certain it failed, both reasoning correctly.
And only the host can resolve it. The device usually notices first and can do nothing — every recovery mechanism is host-initiated. The device's job is to stay in a state from which the host's recovery works, which is what txn_abandoned exists for: not to report a problem, but to trigger the cleanup that makes the next attempt land somewhere consistent.
An out-of-phase packet is the one piece of direct evidence a device ever gets that the beliefs have diverged — and it is usually correct traffic for the host's belief, not a host error. It must be ignored and reported.
§4's conservation law — tokens = completed + abandoned + ended by bus reset — held exactly on the unmutated design at 180 = 47 + 132 + 1, with one documented exclusion and no second.
§6 measured five mutations over 1,295 cycles: removing the timeout left the machine stuck and costing one transaction per lost packet; accepting a handshake early ended transactions on evidence from other transactions; restarting only from idle produced the largest conservation gap, because one disagreement then costs several transactions; removing the out-of-phase report was functionally free and diagnostically fatal.
And the fifth changed nothing at all — which turned out to be information about the design rather than the bench:
T_DONEandT_IDLEare behaviourally identical, so the machine carries a state the specification does not require. That is redundancy, not coverage — and worth telling apart from Chapter 10.4's guard, which was merely covered and became observable once the clause dominating it was removed.
§8 adds a distinction the earlier modules had not needed: stimulus that is illegal as a sequence is not the same as stimulus that is illegal as a packet. The second needs a broken host; the first happens the moment a packet is lost. A sequencer must be verified against arbitrary event orders, because the expected order is what happens when nothing goes wrong — and nothing going wrong is not the case a sequencer exists for.
14. What Comes Next
Everything in this chapter treated timeout as an input that simply arrived. Chapter 12.5 is where it comes from — and it is not one number.
A device must respond within a bound; a host must wait at least a bound before giving up. Those are two different numbers with an ordering requirement between them, and the whole of USB's transaction reliability rests on that ordering holding across cable lengths, hub delays and a bit rate that varies by a factor of 320 from low speed to high.
The chapter closes Module 12 by making the arithmetic explicit — in bit times, which is the only unit in which the numbers are the same at every speed.
Browse the full path on the USB tutorials index.
Continue learning
Related tutorials
- Related topic
Token Stage
The stage that moves no data and decides everything after it — why the token's contents must be captured rather than read, and what a data packet means when no transaction is open.
- Related topic
Data Stage
The rule that ends a transfer is not a byte count. Why a short packet terminates, why a zero-length packet is a message, and the guard no legal stimulus can test.
- Related topic
Handshake Stage
The stage whose transmitter changes with the token's direction — why the host answers an IN, why isochronous has no handshake stage, and the mutation that says every right thing while driving the wrong wire.
- Related topic
Transaction Timing Relationships
Two bounds with an ordering requirement between them — a device answering within a budget, a host waiting past it, and the guard band that must survive a bit rate varying by 320 times.
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.
