USB · Module 6
Device Connection
What the host actually observes when a device is plugged in, why four different kinds of state are involved, and why debounce is a correctness requirement rather than a convenience.
Module 5 left the link in a known operating mode. The wire carries bits reliably, the speed is established and observed, and both ends agree about how to signal.
The host still does not know what is attached to it.
Module 6 is how that changes. It is, as the curriculum's own blurb puts it, the single most important USB sequence — the gap between plugging something in and software being able to use it. And it begins with a question narrower than it sounds: how does the host come to believe that a device is there?
1. Four Kinds of State, Kept Apart
Before any sequence, fix a distinction that enumeration discussions routinely blur. At any moment during this module there are four independent states, and confusing them is the source of most enumeration debugging confusion.
| State | Question it answers | Owned by |
|---|---|---|
| Physical connection | Is something electrically attached? | conductors, Chapter 3.6 |
| Speed / PHY | Which operating mode is established? | PHY, Chapter 5.3 |
| Device protocol state | Default, Address, or Configured? | the device, per the specification |
| Host enumeration progress | Which step is the host's algorithm on? | host software |
These advance at different times and can disagree. A device can be physically attached with no speed established. A speed can be established with the device still in its default protocol state. A host can believe it is mid-enumeration while the device has been reset back to the beginning.
Keeping them apart is the single most valuable habit this module teaches, and Chapter 6.6 assembles them into one picture once all four have been developed.
2. From a Conductor Moving to a Device Worth Talking To
Chapter 3.5 established the electrical mechanism: a downstream port rests at SE0 through its pull-downs, and a device's pull-up raises one conductor, winning a contest that makes its presence unmistakable. Chapter 2.4 established how such an event becomes software-visible: synchronised, latched stickily, and reported.
Enumeration begins where those two end. The steps between a conductor moved and the host has a device worth enumerating are these.
The port observes a change. Its status bit reflects that something is now present.
The condition is debounced. A connector's contacts do not mate cleanly, a pull-up charging a cable takes real time, and a user may be halfway through inserting. So the port waits for the condition to be stable before reporting it as an attachment. Chapter 6.7 treats the duration; what matters here is why the wait exists.
The port is powered and enabled. A port that has observed an attachment is not automatically one that will carry traffic. The host decides to bring it up, and that decision is software's — Chapter 2.1 §2's ownership showing through.
Speed is established. The mechanism is Chapter 3.7's, and is not repeated.
Only now is there something to enumerate.
3. Why Debounce Is Not Optional
The debounce deserves its own argument, because it looks like a workaround and is a correctness requirement.
Without it, a single insertion produces several attachments. Contacts bounce; a partially inserted connector may make and break contact repeatedly. A port reporting every transition would report an attach, a detach, another attach — and the host would start enumerating a device that is not yet properly connected, fail, and start again.
Worse, it would enumerate during an unstable electrical condition. Chapter 3.5 §3 made this point: a pull-up charging the line takes real time, and during it the conductor's level is moving. Speed detection performed on a still-settling line may reach the wrong answer — and a wrong speed is far more expensive than a delayed attach, because everything downstream is then built on it.
So the debounce buys a belief worth acting on. The cost is latency the user may notice; the benefit is that when the host proceeds, it proceeds on a condition that has demonstrated stability.
Attach debounce — port-logic view, not physical signalling
11 cyclesAnd this generalises. Any system reacting to a physical event from outside itself faces the same choice: react quickly to something that might be noise, or wait and act on something established. Enumeration chooses the second, consistently, and Chapter 6.7 shows the same reasoning behind every other duration in the sequence.
4. What the Host Knows — Almost Nothing
This is the chapter's most useful contribution to the rest of the module.
At the moment enumeration begins, the host's knowledge is startlingly thin. It knows:
That something is attached, to a specific port, on a specific hub.
What operating mode was established — Chapter 5.3's observed active mode, not a requested one.
That the device is reachable in its default protocol state, which Chapter 6.2 develops.
And that is all. It does not know what kind of device it is, what it can do, how much power it needs, what interfaces it offers, how large its control transfers may be, or even whether it is a device it can support. It does not know the device's address, because the device does not have one yet.
Enumeration is therefore best understood as a progressive reduction of uncertainty. Each step the host takes is chosen to make the next step possible, and the order is forced by what the host is permitted to assume at each point. That framing explains nearly every apparent oddity in the sequence — including why the host sometimes reads only part of a descriptor before it can safely read the rest, which is Chapter 6.4's subject.
5. The Debounce, as RTL
§3 argued that the debounce is a correctness requirement rather than a convenience. That argument is small enough to build exactly, and building it exposes a distinction the prose can gloss over.
// ─────────────────────────────────────────────────────────────────────────
// usb_attach_debounce
//
// Classification: SIMPLIFIED SYNTHESIZABLE TEACHING RTL. It models the
// stability qualification of section 3 -- turning a bouncing presence
// indication into exactly one believable attach event -- and nothing else.
//
// WHAT IT MODELS. A presence indication must be CONTINUOUSLY stable for a
// required interval before it is adopted, and adopting it produces a single
// EVENT rather than a level that others must edge-detect for themselves.
// Detach is qualified the same way, for the same reason.
//
// WHAT IT DOES NOT MODEL. The electrical decision that produces
// raw_present (Module 3 owns pull-ups, line levels and the analogue
// behaviour), the hub's port-status machinery (Chapter 2.4), speed
// detection (Chapter 3.7), or the real duration of the interval -- the
// parameter here is in clock cycles, scaled down so a simulation is short.
// Chapter 6.7 owns the specified value.
// ─────────────────────────────────────────────────────────────────────────
module usb_attach_debounce #(
// Cycles of continuous stability required before a change is believed.
parameter int unsigned STABLE_CYCLES = 8
)(
input logic clk,
input logic rst_n,
// The port's own presence indication, ALREADY SYNCHRONISED to this clock.
// It crosses from analogue decision logic, so a synchroniser is mandatory
// upstream; debouncing a metastable signal debounces nothing.
input logic raw_present,
output logic attached, // the believed state -- a level
output logic attach_event, // 1-cycle pulse when it becomes believed
output logic detach_event // 1-cycle pulse when removal becomes believed
);
logic raw_q;
logic [31:0] stable_cnt;
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
raw_q <= 1'b0;
stable_cnt <= '0;
attached <= 1'b0;
attach_event <= 1'b0;
detach_event <= 1'b0;
end else begin
attach_event <= 1'b0; // single-cycle pulses
detach_event <= 1'b0;
raw_q <= raw_present;
// THE LINE THAT MATTERS. Any transition restarts the count from zero.
// The requirement is CONTINUOUS stability, and a counter that merely
// accumulates time-while-present measures something else entirely --
// section 7 measures exactly how much else.
if (raw_present != raw_q) begin
stable_cnt <= '0;
end else if (stable_cnt < STABLE_CYCLES) begin
stable_cnt <= stable_cnt + 1;
if (stable_cnt == STABLE_CYCLES - 1) begin
// Stable for long enough. Adopt it -- but only if it differs from
// what is already believed, so a steady line produces one event
// and not a stream of them.
if (raw_present != attached) begin
attached <= raw_present;
if (raw_present) attach_event <= 1'b1;
else detach_event <= 1'b1;
end
end
end
end
end
endmoduleWhat it models. Continuous-stability qualification, and the conversion of a qualified level into a single event.
Why this hardware exists. Because §3's requirement — do not act until the condition has demonstrated stability — is not expressible as combinational logic. Demonstrating stability takes time, and measuring time takes a counter.
Inputs. Clock, reset, and a synchronised presence indication.
State retained. The previous raw value, the stability counter, and the believed state.
Outputs. The believed level plus an attach and a detach pulse.
Hardware implied. A counter, a comparator against the parameter, and two flip-flops.
Assumptions. That raw_present has already been synchronised into this clock domain. The header says why this is not a detail: debouncing a metastable signal debounces nothing, because the comparison that restarts the counter is itself unreliable.
Deliberately omits. The electrical decision, the port-status machinery, speed detection, and the real interval.
What DV should verify. That a bouncing indication produces exactly one event; that a presence shorter than the interval produces none; that stability is required to be continuous rather than cumulative; that a steady line produces one event and not a stream; and that detach is qualified as carefully as attach.
Two decisions carry the teaching:
- Any transition restarts the count. The requirement is continuous stability, and §7 measures what a counter that merely accumulates presence reports instead.
- The output is an event, not just a level. Every consumer would otherwise have to edge-detect the level for itself, and consumers that forget produce repeated enumeration attempts for one insertion — which is the symptom §3 opened with, reintroduced one layer further in.
6. The Assertions
// ─────────────────────────────────────────────────────────────────────────
// Assertions for usb_attach_debounce.
//
// Classification: TEACHING ASSERTIONS about stability qualification.
// Not a USB compliance suite.
// ─────────────────────────────────────────────────────────────────────────
// B1 -- an event must accompany the corresponding change in the believed
// state. Catches a design whose event is a level rather than a pulse, and
// one whose event fires without the state following.
property p_event_matches_change;
@(posedge clk) disable iff (!rst_n)
(attach_event |-> ( attached && !$past(attached))) and
(detach_event |-> (!attached && $past(attached)));
endproperty
assert property (p_event_matches_change);
// B2 -- the believed state never changes silently.
property p_no_silent_change;
@(posedge clk) disable iff (!rst_n)
!$stable(attached) |-> (attach_event || detach_event);
endproperty
assert property (p_no_silent_change);
// B3 -- THE CENTRAL ONE. Stability must be CONTINUOUS. The believed state
// may only change if the raw indication held its new value for the whole
// required interval, with no transition inside it.
property p_continuous_stability;
@(posedge clk) disable iff (!rst_n)
!$stable(attached) |-> $past($stable(raw_present), 1) [*STABLE_CYCLES];
endproperty
assert property (p_continuous_stability);
// B4 -- the two events are mutually exclusive.
property p_events_exclusive;
@(posedge clk) disable iff (!rst_n)
!(attach_event && detach_event);
endproperty
assert property (p_events_exclusive);B3 is the property this section exists to produce, and it is worth noticing that it is harder to write than the others. B1, B2 and B4 are relationships between signals in a single cycle; B3 is a statement about a window of history, which is what a stability requirement fundamentally is. Whenever a requirement contains the word continuously, expect the property to reach backwards rather than sideways.
7. Mutation Test
Two mutants. Both were run; the results are measured.
D1 — count while present, instead of restarting on any transition
The natural way to write a debounce from intuition, and the one that reads correctly: count how long it has been present, and believe it once the count is high enough.
if (raw_present && (stable_cnt < STABLE_CYCLES)) begin // MUTANT D1What it actually measures. Not continuous stability — cumulative presence. The distinction sounds academic until it is exercised.
The mutant was driven with four separate presences of three cycles each, every one of them well below the eight-cycle requirement, each separated by a clean absence:
after 4 presences of 3 cycles each (threshold = 8):
GOLDEN attached=0 attach events=0 -> correctly reported nothing
D1 attached=1 attach events=1 -> REPORTED ATTACHEDThe device was never stably connected at any point, and the mutant reported it as attached. It added up fragments of presence that were individually meaningless and reached a threshold that was supposed to mean something. This is precisely the condition §3 says must not be acted on, produced by logic that looks like it enforces §3.
Why it survives casual testing. Against a clean insertion it is indistinguishable from the correct design, and against a fast bounce it often is too — this mutant did not fail the chapter's own bouncing-contacts check, because a signal toggling every cycle accumulates presence only half the time and never reaches the threshold. It takes a slow, intermittent contact — a connector being pushed in hesitantly, which is exactly the physical event §3 is about — to expose it.
D2 — report the qualified state as a level rather than an event
Drop the per-cycle clearing of the outputs, so the indications stay asserted.
Result. B1 fires on the cycle after the state changes and on every cycle thereafter. A consumer treating the indication as an event now sees a continuous stream of attachments from one insertion, and enumeration is attempted repeatedly — the original symptom, reintroduced downstream of the logic that was supposed to eliminate it.
8. What This Means for Hardware and Verification
On the device side, this chapter's hardware consequence is small and specific: the device must present its pull-up at a moment of its own choosing, and — Chapter 3.5 §4's point — it should not do so until it is ready to be noticed. A device that announces itself while still initialising gets a reset and a sequence of requests it cannot answer.
On the host side, the port's status machinery is Chapter 2.4's, including the sticky-status and set-beats-clear discipline that keeps an attach from being lost.
For verification, this chapter defines the module's first commit point. Enumeration is a chain of them, and this is the first: attachment believed. The cases worth constructing:
- a clean attach, and an attach with bouncing contacts that must debounce to exactly one event
- an attach followed immediately by a detach, shorter than the debounce, which must produce no enumeration attempt
- a detach during each subsequent stage — this chapter's contribution to a cross the whole module uses
- a device that delays presenting its pull-up
And the debugging consequence. The device does nothing has, at this point, several independent causes: no electrical change, a change that never debounced, a debounced change never reported to software, software that did not act, a port never enabled, or speed establishment that failed. Chapter 3.3 §5 established that did the port ever leave SE0 partitions the problem; this chapter adds that even a port that left SE0 has four more places to stop before enumeration begins.
9. Common Misconceptions
10. Reason It Through
A device is plugged in. The port's status bit toggles several times over a few milliseconds. The host reports a single attachment and enumerates normally.
What produced the multiple toggles? Contact bounce during insertion, or a partially seated connector briefly making and breaking. Both are ordinary.
Why did the host report only one attachment? Because the port debounced: it required the condition to be stable before treating it as an attachment, so the intermediate transitions never became reportable events.
What would have happened without the debounce? Several attach and detach events, each potentially starting an enumeration that the next transition invalidated. And at least one enumeration attempt would have begun on a line that was still settling, risking a speed established from an unstable observation.
Now change one thing: the user withdraws the connector after 20 ms. The condition was present but never stable for the required interval, so no attachment is reported and no enumeration begins. That is correct behaviour — the host has not missed anything, because there was never a device stably connected.
What is the general principle? A system reacting to physical events must decide what it is willing to believe, and a debounce is that decision made explicit. The cost is latency; the benefit is that everything downstream is built on a condition that demonstrated itself.
11. Understanding Check
12. Summary
Enumeration begins by establishing something narrower than it sounds: that a device is there and worth talking to.
This module keeps four states apart — physical connection, speed/PHY, device protocol state, and host enumeration progress. They advance at different times and can disagree, and keeping them separate is the module's most valuable habit.
Between a conductor moving and an enumerable device lie several independent steps: the port observes a change, debounces it until stable, reports it to software, software decides to enable and reset the port, and speed is established. Each can fail without the next running.
Debounce is a correctness requirement, not a convenience. Without it one insertion yields repeated spurious enumerations, and speed detection may run on a still-settling line — and a wrong speed is far more expensive than a delayed attach.
In hardware that requirement is continuous stability, and the word continuous is load-bearing. Mutation testing measured the difference: a qualifier that counts cumulative presence rather than restarting on every transition reported a device as attached after four separate three-cycle presences against an eight-cycle threshold — a device that was never stably connected at any point. That mutant is not careless; it is a correct implementation of the sentence most people would use to describe a debounce. The qualifier must also emit an event, not merely a level, or every consumer has to edge-detect for itself and the one that forgets reproduces the original symptom downstream.
At the moment enumeration begins the host knows almost nothing: something is attached to a port, at a known operating mode, reachable in its default protocol state. Not its type, capabilities, power needs, or address — it has none yet.
Which makes the governing framing progressive reduction of uncertainty: each step exists to make the next one possible, and the order is forced by what the host may assume at each point.
13. What Comes Next
The host has a port with something stably attached at a known speed. What it does not have is any guarantee about the state that device is in.
It may have just been plugged in. It may have been sitting there through a previous host's failed enumeration attempt. It may be mid-way through answering a request nobody is listening for any more. The host cannot ask, because asking requires the device to be in a state where it answers — which is the thing in question.
Chapter 6.2 is how that circularity is broken. The host drives a reset, and the device's obligation is to arrive in a defined state regardless of what it was doing before. That chapter is about what reset establishes rather than how it is signalled — Chapter 3.7 owns the SE0 mechanics — and about the sharp distinction between a bus reset and the hardware reset inside a chip, which are different events that a great deal of bad RTL conflates.
Browse the full path on the USB tutorials index.
Continue learning
Related tutorials
- Related topic
The Peripheral-Connectivity Problem
Before a universal peripheral bus, every class of device arrived with its own connector, signalling, host interface, configuration story and driver model — and the cost of that fragmentation landed on the host, the operating system, the peripheral vendor and the user at once. The problem, layer by layer, and the requirements it forces on any architecture meant to replace it.
- Related topic
Why USB Was Created
The synthesis chapter: what three examined legacy interfaces had structurally in common, the six architectural decisions that follow from that evidence, the cost each decision carries, and why standardising peripheral attachment changes the economics of controller silicon, verification IP and compliance rather than removing the engineering.
- Related topic
USB Reset
Reset as an assertion rather than a question: what a bus reset clears, what it deliberately does not, and why a protocol bus reset and an RTL reset are different mechanisms with different scopes.
- Related topic
Address Assignment
Receiving an address and beginning to answer to it are not the same event. Why the default address exists, where the commit boundary falls, the pending-versus-active register architecture that follows, and three mutation tests — one of which forced a sixth assertion.
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.
