USB · Module 12
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.
Module 11 built every packet on the bus and then stopped at each one's boundary. Not one relationship between them was specified.
A token is followed by a data packet, which is answered by a handshake — and those two words, followed and answered, are the whole of Module 12.
This chapter is the first of the three stages, and its distinguishing feature is that it transfers nothing.
1. A Stage That Moves No Data
Chapter 11.1 described the token packet: a PID, an address, an endpoint, a CRC5. What it did not describe is what happens next, because nothing in the packet says.
The token stage transfers no data. It creates a context.
Everything after it is interpreted in that context, and nothing after it repeats the context. The data packet has no address and no endpoint. The handshake has neither, and no payload at all.
Which produces the constraint the whole chapter turns on:
The token is said once. Every packet that follows depends on it, and none of them can ask again.
Three obligations follow immediately, and §5's RTL is precisely these three:
- The device must capture what the token said — not observe it, capture it — because the decoder's outputs are gone the moment the packet ends.
- The device must know a transaction is open, because a data packet arriving outside one has no meaning that could be recovered.
- The device must know when it closes, because a context that outlives its transaction makes the next stray packet look legitimate.
2. What the Token Commits Each Side To
A token is not a request that may be ignored. It opens a window in which both ends owe each other something specific, and the two obligations are not symmetric.
The host has committed bus time. It has decided this transaction happens now, allocated the slot (Chapter 10.3's arbitration produced it), and will not use the bus for anything else until the transaction resolves.
The device has committed to respond within a bounded window, and the bound is Chapter 12.5's subject. What matters here is that the window exists and that it is short.
| Host | Device | |
|---|---|---|
| After the token | waits | must act |
| If the other side is silent | times out, retries | nothing to wait for |
| Cost of being slow | a retry | the transaction is lost |
| Can abandon the transaction | yes | no |
3. A Data Packet With No Transaction
A data packet arrives. No token preceded it. What does it mean?
Nothing, and that is not a figure of speech. A data packet carries a PID, a payload and a CRC16 — no address, no endpoint, no direction. Without a token there is no fact anywhere on the bus saying whether it was for this device, which endpoint it belongs to, or which direction it is travelling.
So it must be discarded, silently. Chapter 11.3 §3's argument applies exactly: answering would require knowing that a reply belongs to this device, and that is precisely what is not known.
How does this happen on a real bus? Three ways, and all three are ordinary:
- The token was corrupted. The host sent one; this device's Chapter 11.1 filter rejected it on CRC. The host does not know that, and sends the data.
- The token was for someone else and this device's own token was lost. Another device is mid-transaction; its data packet is on the bus and this device sees it.
- The device aborted — §2's silent withdrawal — and the host has not yet timed out.
The third is the one that catches designs, because the device did have a transaction a moment ago, and the difference between a context that closed and a context that never opened is exactly one register bit.
4. Capture, Do Not Observe
The distinction that produces §6's headline defect.
The naive structure wires Chapter 11.1's decoder outputs straight to whatever consumes them. The decoder is combinational — it said so explicitly — so endp and is_in are valid exactly while the token packet's bits are present and meaningless afterwards.
The data stage happens later. Not much later on a fast bus, but later: a gap, then a packet that takes microseconds to arrive. By then the decoder's outputs describe nothing.
5. The Transaction Context, as RTL
// ─────────────────────────────────────────────────────────────────────────
// usb_txn_context
//
// Classification: SIMPLIFIED SYNTHESIZABLE TEACHING RTL. It models section
// 1's three obligations: capture what the token said, know a transaction is
// open, and know when it closes.
//
// WHAT IT MODELS. The state that exists BETWEEN packets -- which is the
// thing Module 11 never needed, because every chapter there began and ended
// inside one packet.
//
// WHAT IT DOES NOT MODEL. The token packet or its filtering (Chapter 11.1
// -- `token_accept` is that block's output); the data stage itself (Chapter
// 12.2); the handshake (Chapter 12.3); the timeout that produces most
// `txn_abort` pulses (Chapter 12.5); and the full stage sequencing, which
// is Chapter 12.4 and consumes this block rather than replacing it.
//
// ── WHY EVERY FIELD IS REGISTERED ───────────────────────────────────────
// Chapter 11.1's decoder is combinational by design -- its outputs are
// valid only while the token's bits are on the wire. The data stage happens
// AFTER that. So this block's registers are not an optimisation or a
// pipeline stage: they are the only place the token's contents exist once
// the token is over. Section 6's X1 measures what their absence costs, and
// the answer is that the device uses somebody else's endpoint number.
// ─────────────────────────────────────────────────────────────────────────
module usb_txn_context (
input logic clk,
input logic rst_n,
input logic bus_reset, // Chapter 8.3
// From Chapter 11.1's filter: a token addressed to US, CRC good, not an SOF.
input logic token_accept,
input logic [3:0] token_endp,
input logic token_is_in,
input logic token_is_out,
input logic token_is_setup,
// The transaction ended. `txn_done` is a normal conclusion; `txn_abort`
// covers section 2's silent withdrawal and Chapter 12.5's timeout, NEITHER
// of which corresponds to a packet on the wire.
input logic txn_done,
input logic txn_abort,
output logic txn_open,
output logic [3:0] ctx_endp,
output logic ctx_is_in,
output logic ctx_is_setup,
// Section 3: a data packet is interpretable ONLY inside an inbound
// transaction. Outside one there is no address, endpoint or direction
// anywhere on the bus that could apply to it.
output logic data_may_be_accepted,
// A token arriving while one is already open. Not an error this block can
// fix -- it is evidence the host gave up on the previous transaction and
// this device did not notice. Reporting it is how that becomes findable.
output logic token_overrun
);
logic open_q;
logic [3:0] endp_q;
logic in_q, setup_q;
logic overrun_q;
assign txn_open = open_q;
assign ctx_endp = endp_q;
assign ctx_is_in = in_q;
assign ctx_is_setup = setup_q;
assign token_overrun = overrun_q;
// Derived (Chapter 8.4), so it cannot disagree with the context it
// summarises. Note the !in_q: during an IN the DEVICE transmits, so an
// inbound data packet is as meaningless as one with no transaction at all.
assign data_may_be_accepted = open_q && !in_q;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
open_q <= 1'b0; endp_q <= '0; in_q <= 1'b0; setup_q <= 1'b0;
overrun_q <= 1'b0;
end else if (bus_reset) begin
open_q <= 1'b0; endp_q <= '0; in_q <= 1'b0; setup_q <= 1'b0;
overrun_q <= 1'b0;
end else begin
overrun_q <= 1'b0; // a pulse, not a level
if (token_accept) begin
// A NEW TOKEN ALWAYS WINS, even mid-transaction. The host owns the
// bus (section 2): if it has issued a new token, the previous
// transaction is over whatever this device believed, and continuing
// to act on the old context would mean answering the new token with
// the old endpoint's data.
if (open_q) overrun_q <= 1'b1;
open_q <= 1'b1;
endp_q <= token_endp;
in_q <= token_is_in;
setup_q <= token_is_setup;
end else if (txn_done || txn_abort) begin
open_q <= 1'b0;
// The context fields are deliberately NOT cleared. They are only
// readable while open_q is set, so clearing them would spend logic
// making an already-unreadable value more unreadable -- and would
// hide, rather than prevent, a consumer that reads them anyway.
end
end
end
endmoduleWhat it models. The state that exists between the packets of one transaction.
Engineering reason. Because the token is said once and everything after it depends on what it said.
Inputs. A bus reset, an accepted token with its fields, and the two ways a transaction ends.
State retained. One open flag, 4 bits of endpoint, two type bits, and the overrun pulse — 8 flip-flops.
Outputs. The open indication, the captured context, a derived acceptance permission, and the overrun report.
Hardware implied. A small register file with a two-way priority on its write enables.
Reset behaviour. Everything clears on hard reset and bus reset. A transaction does not survive a bus reset — Chapter 8.3 is rebuilding the relationship the transaction was conducted under.
Assumptions. That token_accept has already passed Chapter 11.1's four filters, SOF exclusion included; that txn_done and txn_abort are single-cycle; and that the consumer reads ctx_* only while txn_open is set.
Omissions. The packets, the stages, the timeout and the full sequencing — in the header.
What DV should verify. That the context matches the token that opened it, for the whole transaction and not merely the cycle after; that no data is accepted with no transaction open; that no data is accepted during an IN; that a mid-transaction token replaces the context and is reported; that a transaction closes on either ending; and that a bus reset closes one.
Context: created, held, discarded
10 cycles6. Mutation Test
Five mutations over 666 checks spanning 123 transactions, including a phase with twelve idle cycles between the token and the data — the gap §4 is about.
The unmutated block: 22 data packets declared acceptable, and 0 errors of every kind.
| acceptable | endpoint wrong | direction wrong | data with no txn | data during IN | overrun unreported | |
|---|---|---|---|---|---|---|
| golden | 22 | 0 | 0 | 0 | 0 | 0 |
| X1 context not captured | 56 | 340 | 213 | 0 | 34 | 0 |
| X2 no context required | 94 | 0 | 0 | 38 | 34 | 0 |
| X3 second token ignored | 22 | 194 | 116 | 0 | 9 | 78 |
| X4 transaction never closes | 30 | 0 | 0 | 8 | 0 | 0 |
| X5 direction not captured | 56 | 0 | 213 | 0 | 34 | 0 |
X1 — read the decoder instead of capturing it
Measured: wrong endpoint on 340 checks, wrong direction on 213, and 34 data packets accepted during IN transactions.
§4's defect. The device acts on whatever the token decoder's outputs are now, and after the token they describe nothing.
The IN-transaction figure is the one to read. Thirty-four times the device prepared to receive during a stage in which it was supposed to transmit — which is not a data error but a direction error, and produces a device and a host both driving the bus.
X2 — accept data without an open transaction
Measured: 38 data packets accepted with no transaction at all, and 34 during IN transactions. 94 declared acceptable against a correct 22 — more than four times too many.
§3's rule removed. The device becomes a promiscuous receiver, absorbing packets belonging to other devices' transactions and to its own aborted ones.
And the damage is not confined to this device. A device that accepts another's data packet will Chapter 12.3-answer it, putting a handshake on the bus during somebody else's transaction — so the corruption lands on a device that is entirely correct.
X3 — ignore a token arriving mid-transaction
Measured: 78 unreported overruns, 194 wrong endpoints, 116 wrong directions.
The device holds its stale context while the host has moved on. Every subsequent packet of the new transaction is interpreted against the old transaction's endpoint and direction.
The host is not misbehaving. §2: it owns the bus, and a new token means the previous transaction is over whether or not this device noticed. A device that disagrees is wrong by construction, because it is the only party without the authority to decide.
X4 — never close the transaction
Measured: 196 wrong txn_open, and 8 data packets accepted with no transaction.
The context outlives its transaction, so a stray packet arriving afterwards is interpreted against the previous transaction's endpoint — plausibly, consistently, and entirely wrongly.
This is §3's third case made permanent: the difference between a context that closed and one that never opened is one register bit, and this mutation removes it.
X5 — capture the endpoint but not the direction
Measured: 213 wrong directions and 34 data packets accepted during IN transactions — identical to X1's figures on both counts.
X5 is X1's damage without X1's obviousness. X1 also corrupts the endpoint, which shows up as data going to the wrong place; X5 leaves the endpoint perfect and gets only the direction wrong.
7. The Assertions
// ─────────────────────────────────────────────────────────────────────────
// Classification: TEACHING ASSERTIONS about the transaction context.
// C-properties are the CAPTURE contract; O the OPEN/CLOSE contract;
// D the acceptance rule.
// ─────────────────────────────────────────────────────────────────────────
// C1 -- THE CONTEXT MATCHES THE TOKEN THAT OPENED IT, FOR AS LONG AS IT IS
// OPEN. The `throughout` is the entire point: a property checking only the
// cycle after the token would pass on section 6's X1, because X1's error
// appears LATER, when the decoder's outputs have moved on.
property p_context_holds;
@(posedge clk) disable iff (!rst_n)
(token_accept && !bus_reset) |=>
( (ctx_endp == $past(token_endp) && ctx_is_in == $past(token_is_in))
throughout (txn_open [->1:$] ##0 (!txn_open || token_accept || bus_reset)) );
endproperty
assert property (p_context_holds);
// C2 -- AND IT NEVER CHANGES WITHOUT A TOKEN. The complement of C1: C1 says
// the right value was captured, this says nothing else writes it.
property p_context_stable;
@(posedge clk) disable iff (!rst_n)
(ctx_endp != $past(ctx_endp) || ctx_is_in != $past(ctx_is_in))
|-> $past(token_accept || bus_reset);
endproperty
assert property (p_context_stable);
// O1 -- A TOKEN OPENS A TRANSACTION, ALWAYS -- including one already open.
// Section 6's X3: the host owns the bus, so a new token is not a request.
property p_token_opens;
@(posedge clk) disable iff (!rst_n)
(token_accept && !bus_reset) |=> txn_open;
endproperty
assert property (p_token_opens);
// O2 -- AND A MID-TRANSACTION TOKEN IS REPORTED. Without this, X3's silent
// context replacement would be indistinguishable from a normal one.
property p_overrun_reported;
@(posedge clk) disable iff (!rst_n)
(token_accept && txn_open && !bus_reset) |=> token_overrun;
endproperty
assert property (p_overrun_reported);
// O3 -- EITHER ENDING CLOSES IT. Section 6's X4.
property p_ending_closes;
@(posedge clk) disable iff (!rst_n)
((txn_done || txn_abort) && !token_accept && !bus_reset) |=> !txn_open;
endproperty
assert property (p_ending_closes);
// O4 -- AND NOTHING ELSE OPENS ONE. Catches an open flag that sets itself.
property p_open_has_a_cause;
@(posedge clk) disable iff (!rst_n)
$rose(txn_open) |-> $past(token_accept);
endproperty
assert property (p_open_has_a_cause);
// D1 -- DATA IS ACCEPTABLE EXACTLY INSIDE AN INBOUND TRANSACTION. An
// EQUIVALENCE, and the ONLY property that catches section 6's X5 -- the
// mutation whose endpoint handling is perfect.
property p_accept_iff_inbound_open;
@(posedge clk) disable iff (!rst_n)
data_may_be_accepted == (txn_open && !ctx_is_in);
endproperty
assert property (p_accept_iff_inbound_open);
// R1 -- A BUS RESET ENDS ANY TRANSACTION. Chapter 8.3: the relationship the
// transaction was conducted under is being rebuilt.
property p_bus_reset_closes;
@(posedge clk) disable iff (!rst_n)
bus_reset |=> (!txn_open && !token_overrun);
endproperty
assert property (p_bus_reset_closes);C1 is the property this chapter exists for, and its throughout is doing the work. The obvious formulation — one cycle after a token, the context equals the token — passes on X1, because X1's error is not in the capture but in the persistence: the value is briefly right and then drifts to whatever the decoder is showing.
A property about state must span the state's lifetime, not its first cycle.
D1 is the property that sounds redundant and is not. It reads like a restatement of one assignment. It is the only statement in the set that constrains the direction half of the context, and §6's X5 satisfies every other property here.
8. Verification
This chapter's commit point is every packet after the token was interpreted against what that token actually said.
Stimulus. An OUT transaction; an IN transaction; a SETUP; data packets with no transaction open — four of them consecutively, which is the case X2 needs; a second token arriving mid-transaction; an abort followed immediately by a data packet; a twelve-cycle gap between token and data; a bus reset mid-transaction; and 600 randomised events mixing tokens, data presentations, completions and aborts.
Observation. txn_open, the whole captured context, and the acceptance permission — every cycle, not merely at stage boundaries, because X1's error lives entirely between them.
Reference model. Four variables updated by the same rules stated in §1. Its value here is limited and worth being honest about: it is structurally similar to the design. The checks that actually catch things are the two obligations — no data without a transaction and no data during an IN — which are stated in the protocol's terms and not in the design's.
Coverage — crosses:
- token type (IN / OUT / SETUP) × transaction already open or not
- gap length between token and data: 0, 1, 2, 12 cycles
- ending type (done / abort / bus reset / superseding token) × each stage
- data presented with: no transaction, an IN open, an OUT open, an aborted one
- endpoint number 0 to 15 × each direction
Negative cases with defined outcomes: no data accepted with no transaction; none during an IN; txn_open never rises without a token; the context never changes without one; and nothing survives a bus reset.
9. Debugging: the Device That Only Works on Endpoint 0
A device enumerates perfectly and every control transfer succeeds. Its bulk endpoints do not work at all — data sent to EP2 appears to arrive at EP0, or is silently lost. The failure is completely reproducible.
What does enumeration works tell you? That the token filter, the data path, the handshake and the toggle are all functional. Enumeration exercises nearly everything — Chapter 10.2 — so a device that enumerates has most of its stack working.
What is different about enumeration? It is entirely endpoint 0. Chapter 9.3 §2: EP0 exists before any configuration, and every control transfer uses it.
So what breaks when the endpoint number is not zero? Anything that reads an endpoint number from somewhere it should not. §6's X1: a device reading its token decoder live, between packets, sees idle — which decodes to endpoint 0.
Why does that look like data "arriving at EP0"? Because it does. The endpoint number the device used was the one it read after the token was over, and the idle decode is stable and consistent — §4's point that the value is plausible rather than random.
What is the fastest confirming test? Send to EP1 and EP2 and see whether both land in the same place. A wrong-but-consistent destination is a captured-value problem; a random one is a timing problem. They look similar in a log and have different causes.
What if the data is lost rather than misdelivered? Then the direction is also wrong — §6's X5. The device decoded an idle bus as an IN, prepared to transmit, and discarded an inbound packet it should have accepted. Look for the device driving the bus during a stage where it should be listening, which a differential probe shows immediately and a protocol analyser often does not.
And why is it completely reproducible? Because the idle decode is deterministic. This class of bug does not present as flakiness — which misleads, because reproducible suggests a logic error and this is a lifetime error.
The signature to keep: works on endpoint 0 and nowhere else means a value was read after it stopped being valid — and idle decodes to zero.
10. Common Misconceptions
11. Reason It Through
A device works perfectly when it is the only thing plugged in. On a hub with other active devices it corrupts transfers — but only occasionally, and only under load. Its own traffic pattern does not affect the rate; other devices' traffic does.
What does other devices' traffic matters and mine does not tell you? That the device is being affected by packets that are not addressed to it. Its own load would matter if the fault were in its own datapath.
Which packets does a device see that are not its own? All of them. Chapter 11.1 §1: every device sees every packet, and filtering is the device's job.
So which filter could be leaking? Two candidates, and they are distinguishable:
- The address filter — Chapter 11.1 §6's T2. The device would accept other devices' tokens, and the corruption would track the number of other devices.
- The transaction-context requirement — §6's X2. The device accepts other devices' data packets, in the gaps of its own transactions, and the corruption tracks other devices' traffic volume.
How would you tell them apart? Add a second device that is attached but idle. An address-filter fault gets worse; a context fault does not, because an idle device generates no data packets.
Why is it only occasional? Because it needs a coincidence: another device's data packet arriving while this device has no transaction open but is listening. Load raises the probability and does not create the mechanism.
Is there a third candidate? Yes — the device might be correct and the hub faulty. Testable by moving it to a direct port. Rule out the cheap external hypothesis before opening the RTL, because the cost of being wrong in that direction is a week.
And the transferable point: a fault whose rate tracks somebody else's activity is a filtering fault, and the filter in question is whichever one distinguishes this device's traffic from traffic this device can see. On a shared bus those are different sets, and every device is responsible for the difference.
12. Understanding Check
13. Summary
The token stage transfers nothing. It creates a context — endpoint, direction, transaction type — and every packet after it is interpreted in that context while carrying none of it. The token is said once and cannot be asked again.
The obligations it creates are asymmetric. The host has committed bus time and can abandon the transaction at any moment; the device has committed to respond within a bounded window and cannot withdraw — its only option is silence, which means it must survive transactions that stop with nothing on the wire marking the end.
A data packet outside a transaction means nothing, literally: no address, no endpoint, no direction exists anywhere for it. It is discarded silently, and it happens routinely — a corrupted token, another device's traffic, or this device's own abort.
Which makes capture, not observation, the design's centre. Chapter 11.1's decoder is combinational; the token's contents exist after the packet only in registers you wrote. §6 measured the alternative at 340 wrong endpoints and 213 wrong directions — and the failure is not randomness: idle decodes to a stable, plausible endpoint 0, which is why such a device enumerates flawlessly and fails on every other endpoint.
Five mutations, each with a distinct signature: no capture (everything wrong), no context required (38 foreign packets absorbed, with the handshake landing in another device's transaction), a second token ignored (78 overruns and a stale context the host has already left), a transaction that never closes (a stray packet read against the previous transaction), and direction not captured — which is the interesting one: every payload at the right endpoint, 213 wrong directions, and a destination-checking bench passes.
And §8 adds a fourth shape to Module 11's catalogue of benches that pass wrongly: not an unreachable state, a shared misunderstanding, an empty negative space or a missing anchor, but a compressed timeline.
A bench that runs a protocol faster than the protocol runs removes the very intervals the design exists to survive.
14. What Comes Next
The context is open. Chapter 12.2 is the Data Stage, where something finally moves — in the direction the token specified, from whichever end the token made the transmitter.
Its subject is not the data packet, which Chapter 11.2 already built. It is the rule that decides when a transfer is over, and it is not a length: a packet shorter than the endpoint's maximum ends the transfer, which makes a zero-length packet a meaningful message rather than an empty one. The Linux kernel carries both halves as flags — URB_SHORT_NOT_OK and URB_ZERO_PACKET — and a hardware quirk bit for controllers that get the rule wrong.
Browse the full path on the USB tutorials index.
Continue learning
Related tutorials
- 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 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.
- 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.
