Skip to content
VLSI Mentor

USB · Module 3

Speed Detection

Two speeds are announced by a resistor's position; the third cannot be, so it is negotiated. The chirp handshake in which a high-speed device first pretends to be full-speed, why the same SE0 condition means different things at different durations, and the RTL that turns a persisting condition into an event.

Chapter 3.5 ended on a limitation. A resistor's position can announce two speeds because there are two conductors, and both meanings are taken: pull-up on D+ means full speed, pull-up on D- means low speed. USB has a third speed, and the static mechanism has nothing left to say it with.

This chapter is how that is solved, and the solution is genuinely clever: a high-speed-capable device starts by pretending to be a full-speed one, because that is the only announcement available, and then it and the host conduct a negotiation in line states to discover whether both of them can do better. If they can, they switch to an electrical arrangement in which the pull-up is removed altogether.

It also settles a question this module has deferred four times: how long an SE0 must persist before it means something different.

1. The Easy Case: Two Speeds by Position

Low-speed and full-speed detection needs no negotiation at all, because Chapter 3.5 already did the work.

The host's port sits at SE0. A device attaches, its pull-up raises one conductor, and the host qualifies the condition over an interval rather than trusting a first look — for Chapter 3.5 §3's reasons. Which conductor rose is the answer: D+ means full speed, D- means low speed.

That is static, immediate and requires nothing from the device beyond existing. It is also the entire mechanism for those two speeds, and if the device is not high-speed capable it is the end of the story.

2. The Hard Case: a Third Speed With No Position Left

A high-speed-capable device has a problem at attachment: it must announce itself using a mechanism that can only say full speed or low speed. It says full speed — it presents a pull-up on D+ exactly as a full-speed device would — and is detected as one.

Two things make this workable rather than a deception.

It is a safe default. A host that is not high-speed capable, or that does not attempt the negotiation, simply carries on with a perfectly good full-speed device. Nothing breaks; the device operates at the lower speed it truthfully claimed.

And the negotiation happens inside something that was going to happen anyway. After detecting an attachment, a host resets the port — and a reset is signalled by driving SE0 for an extended period. That interval is the opportunity: the device is expected to be listening, the host is driving a known condition, and both ends have a defined moment in which to look for something more.

A sequence diagram of high-speed negotiation between a host or hub port and a high-speed capable device. The device first attaches presenting a full-speed pull-up on D plus, and the host detects a full-speed device. The host then begins a reset by driving SE0 for an extended period. The device, recognising the reset, drives a K condition known as the chirp. The host, if it is high-speed capable and detects that chirp, answers with an alternating sequence of K and J conditions. If the device detects that alternating sequence, both sides switch to high-speed operation and the device removes its pull-up. If either side fails to recognise the other's signalling, the port simply remains at full speed.High-speed negotiation during resetHost / hub portHigh-speed capable deviceattaches with afull-speed pull-upon D+detects a full-speeddevicedrives SE0 — resetbeginschirp: drives Khigh-speed capableand saw the chirp?answers withalternating K / Jsaw the alternatinganswer?removes pull-up;both switch to highspeedotherwise: stay atfull speed
Figure 1 — the negotiation happens inside the reset the host was going to perform anyway. Each side proceeds only if it recognises what the other did.

Read the structure rather than the details. It is a mutual-recognition handshake, and the important property is that it fails safe in both directions. A device that chirps at a host which cannot do high speed gets no answer, and stays full speed. A high-speed host that sees no chirp concludes the device is genuinely full speed, and proceeds. Neither side needs to know the other's capability in advance, and neither is harmed by the other lacking it.

3. Why a Chirp Rather Than a Message

It is worth asking why the negotiation uses raw line states instead of a packet, since packets exist.

Because at this moment nothing is agreed. The device does not know whether the host speaks high speed and the host does not know whether the device does. A packet requires a shared speed to be transmitted at, an encoding, a framing convention and a receiver configured to expect it — all of which are downstream of the question being asked. The negotiation is the precondition for packets and therefore cannot use them.

And a line state is the least demanding thing that can be said. Driving K for a period requires no clock recovery, no encoding, no framing and no addressing. A receiver can recognise it with nothing more than the line-state machinery of Chapter 3.1, which both ends already have because they need it anyway.

This is the same reasoning as Chapter 3.5 §3's: when nothing is agreed yet, the mechanism must be one that requires no agreement. A resistor's position and a sustained line state are both members of that small family, and USB uses each exactly where it fits.

4. The Same Condition, Three Meanings

Now the deferred question. SE0 has appeared throughout this module meaning several different things, and the ambiguity is resolved by duration.

Brief SE0 appears as part of normal signalling — it is how the end of a packet is marked. It lasts for a short, bounded period.

Extended SE0 is a bus reset: the host driving both conductors low for far longer than any packet boundary, which is what §2's negotiation happens inside.

Persistent SE0 with no device is simply an unoccupied port, as Chapter 3.6 established.

The same electrical condition, distinguished by how long it lasts and by what the port already believes. That has a direct consequence for hardware: a receiver must qualify SE0 by duration, because reacting to the condition itself would turn every packet boundary into a reset.

SE0 duration determines meaning — conceptual

9 cycles
A conceptual view of SE0 appearing with different durations. During normal signalling the pair alternates between J and K and then enters SE0 briefly to mark the end of a packet, after which it returns to idle. Later the host drives SE0 continuously for a much longer interval, which qualifies as a bus reset. The figure shows that the electrical condition is identical in both cases and only the duration differs. No real durations are depicted and the two intervals are not drawn to scale.short SE0 — a packet boundaryshort SE0 — a packetboundarySE0 begins again...SE0 begins again......and persists: now it is a reset...and persists: now it isa resetline stateJKJSE0JSE0SE0SE0SE0SE0 run000101234+meaningsignallingsignallingsignallingpacket endidleidleidleidleRESETt0t1t2t3t4t5t6t7t8
Figure 2 — one condition, three meanings, separated by duration. A design that reacts to SE0 rather than to a qualified SE0 treats every packet boundary as a reset.

5. Turning a Condition Into an Event

Here is the duration qualification as RTL. It is the smallest useful block in Module 3 and it makes a distinction the rest of the design depends on.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// se0_qualifier
//
// Classification: SIMPLIFIED SYNTHESIZABLE TEACHING RTL. It implements the
// duration-qualification IDEA, not USB's reset detection.
//
// WHAT IT MODELS. Distinguishing a brief SE0, which is ordinary signalling,
// from a persisting SE0, which means something else. It turns a CONDITION
// into an EVENT by requiring it to last.
//
// WHAT IT DOES NOT MODEL. The actual USB thresholds -- how long an SE0 must
// persist to be a reset is specified by USB-IF and is deliberately a
// PARAMETER here rather than a number this curriculum invents. It also does
// not model the chirp handshake of section 2, speed switching, the
// high-speed electrical arrangement, or what the controller should DO about
// a reset once detected.
//
// NOTE ON THE TWO RESETS. `rst_n` below is this module's own hardware reset
// -- a local electrical condition. `bus_reset` is a PROTOCOL EVENT this
// module DETECTS and reports. They are different things and must not be
// wired together: making a detected bus reset drive local `rst_n` would
// reset the very logic that is meant to observe and report it, and would
// erase the report in the act of making it.
// ─────────────────────────────────────────────────────────────────────────
module se0_qualifier
  import usb_ls_pkg::*;
#(
  // Cycles of continuous SE0 after which the condition is a bus reset.
  // Must come from the specification and the controller's clock period.
  //
  // MEASURED BEHAVIOUR, NOT ASSUMED: because the line state is registered on
  // the way in and bus_reset is registered on the way out, the event actually
  // asserts after RESET_CYCLES + 2 cycles of SE0, not RESET_CYCLES. Simulation
  // with RESET_CYCLES = 8 asserts on the 10th cycle. A real design must budget
  // that pipeline against the specification's window rather than assume the
  // parameter is the answer -- an off-by-two here is exactly the kind of error
  // that passes review because the parameter's NAME looks like the guarantee.
  parameter int RESET_CYCLES = 64
) (
  input  logic        clk,
  input  logic        rst_n,          // LOCAL hardware reset -- see header

  input  line_state_e line_state,     // from Chapter 3.1's decode
  input  logic        line_state_ok,  // qualifies line_state as usable

  output logic        se0_active,     // SE0 is present right now
  output logic        bus_reset       // level: SE0 has persisted long enough
);

  localparam int CNT_W = $clog2(RESET_CYCLES + 1);
  logic [CNT_W-1:0] run_q;

  logic se0_now;
  assign se0_now = line_state_ok && (line_state == LS_SE0);

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      run_q      <= '0;
      se0_active <= 1'b0;
      bus_reset  <= 1'b0;
    end else begin
      se0_active <= se0_now;

      if (!se0_now) begin
        // ANY departure from SE0 restarts the measurement. A reset is a
        // CONTINUOUS condition; counting cumulative SE0 across packet
        // boundaries would eventually declare a reset on a busy, healthy
        // bus -- the classic error in this kind of qualifier.
        run_q <= '0;
      end else if (run_q != CNT_W'(RESET_CYCLES)) begin
        // Saturate rather than wrap. A wrapping counter would drop out of
        // the reset condition and re-enter it periodically for as long as
        // the host held SE0, producing repeated spurious reset edges.
        run_q <= run_q + 1'b1;
      end

      // Level, not a pulse: the condition is still true while SE0 persists,
      // and a consumer may sample it whenever it is ready.
      bus_reset <= se0_now && (run_q == CNT_W'(RESET_CYCLES));
    end
  end

endmodule

What it models. Duration qualification: a condition becomes an event by lasting.

Why the structure exists. Any departure from SE0 clears the run, because a reset is continuous — accumulating SE0 across packet boundaries would declare a reset on a perfectly healthy busy bus, which is the classic bug in this kind of block. The counter saturates rather than wrapping, because a wrapping counter would leave and re-enter the reset condition repeatedly while the host held SE0, producing a train of spurious reset edges. bus_reset is a level rather than a pulse because the condition remains true while SE0 persists and a consumer should be able to observe it whenever it is ready.

Hardware implied. One counter, one comparator, two flops.

Measured latency. Simulation with RESET_CYCLES = 8 asserts bus_reset on the tenth cycle of continuous SE0, not the eighth: the input line state is registered on the way in and the output on the way out, adding two cycles. A real design must budget that against the specification's window. This is worth stating because the parameter's name reads like a guarantee and is not one — which is precisely how off-by-two errors survive a review.

State retained. The run length only. It has no memory across a departure from SE0, which is the definition of continuous.

Inputs assumed. A decoded line state already in this clock domain and already qualified as usable — the crossing warned about in Chapter 3.1 §6 must have been handled before this block sees it.

Output meaning. se0_active is the raw condition; bus_reset is the qualified conclusion. Keeping both is deliberate: a consumer that wants the condition and one that wants the event need different things, and conflating them forces one of them to re-derive what the other already had.

What DV should verify. That an SE0 one cycle short of the threshold does not assert bus_reset; that one at exactly the threshold does; that a brief interruption resets the run completely rather than pausing it; that repeated short SE0 intervals never accumulate into a reset; and that the output is a stable level rather than a train of pulses while SE0 persists.

What it deliberately omits. The real thresholds, the chirp handshake, speed switching, and everything about what a controller should do once a reset is detected.

6. Two Resets That Must Not Be Confused

The header above flags this and it deserves the emphasis, because it is a genuine and damaging design error.

A local hardware reset is an electrical condition asserted by the surrounding system. It returns logic to a known state and is not a protocol concept at all.

A bus reset is a protocol event — a condition on the wires, which this block detects and reports. It is information, not a control input.

The tempting and wrong move is to wire the detected bus reset into the local reset of the receive logic. It is wrong for a specific reason: it resets the logic that is meant to observe and report the condition, so the report is erased in the act of being made. The consumer never sees a stable indication, and the block that detected it forgets it did.

What a bus reset should do is be reported, and then acted on deliberately by whatever owns the port's state — returning the protocol-visible state to its defined starting condition, exactly the distinction Chapter 2.2 §6 drew between protocol-visible and implementation state. Some state must be cleared; the machinery doing the clearing must not be part of what is cleared.

7. Verification and Debug

The stimulus dimensions are duration and interruption, and both need deliberate construction. An SE0 exactly at the threshold, one cycle below, and one cycle above; an SE0 interrupted for a single cycle and then resumed, which must restart the measurement rather than continue it; long bursts of normal traffic with frequent packet-boundary SE0 intervals, which must never accumulate into a reset; and reset asserted locally while a bus reset is in progress, which exercises the §6 distinction.

The assertions worth writing:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// Classification: TEACHING ASSERTIONS for this qualifier's semantics. They
// check the duration logic, not USB conformance.
// ─────────────────────────────────────────────────────────────────────────

// S1 -- a reset is never declared without SE0 actually being present. The
// most basic protection against a counter that has drifted out of step
// with the condition it is supposed to be measuring.
property p_reset_requires_se0;
  @(posedge clk) disable iff (!rst_n)
    bus_reset |-> se0_active;
endproperty
assert property (p_reset_requires_se0);

// S2 -- THE ONE THAT MATTERS. Any departure from SE0 must clear the
// condition immediately. Without this, cumulative SE0 across packet
// boundaries eventually declares a reset on a healthy busy bus -- a fault
// whose frequency rises with traffic, which is a deeply confusing signature.
property p_departure_clears;
  @(posedge clk) disable iff (!rst_n)
    !se0_active |=> !bus_reset;
endproperty
assert property (p_departure_clears);

// S3 -- the qualified event requires the full duration. An SE0 shorter than
// the threshold must never assert it, or ordinary packet boundaries become
// resets.
//
// HONEST LIMITATION: this is a NECESSARY condition, not a sufficient one --
// it samples a single earlier cycle rather than proving continuity, so it
// catches a grossly early assertion and would not catch a subtle one. S2 is
// what actually protects continuity. Stating that is better than dressing
// this up as a stronger property than it is.
property p_requires_full_duration;
  @(posedge clk) disable iff (!rst_n)
    $rose(bus_reset) |-> $past(se0_active, RESET_CYCLES);
endproperty
assert property (p_requires_full_duration);

S2 is the one to keep. The bug it catches — accumulating rather than measuring continuously — produces spurious resets whose rate increases with bus traffic, because busier buses have more packet boundaries. A device that works when idle and resets itself under load is a memorably confusing symptom, and it is entirely prevented by one property.

For debug, the observation that localises a spurious reset is whether SE0 was genuinely continuous for the required interval. That is a question for an instrument observing the conductors, and it splits the problem cleanly: continuous SE0 of sufficient length means the host really did reset the port, and the question moves to why; SE0 that was not continuous means the detection is wrong, and the question stays in the receiving design. As throughout this module, the diagnosis comes from comparing two observation levels rather than from either alone.

8. Common Misconceptions

9. Reason It Through

A device works correctly when lightly used. Under sustained heavy traffic it intermittently resets itself. The resets become more frequent as throughput rises. Nothing in the host's logs shows a reset being issued.

What does the correlation with throughput suggest? That whatever triggers the resets scales with bus activity, not with time or temperature. That immediately distinguishes it from the analog degradation of Chapter 3.2, whose rate scales with physical variables rather than with how much correct traffic is flowing.

What scales with traffic on this interface? Packet boundaries — each of which is a brief SE0. More throughput means more packets, which means more short SE0 intervals per unit time.

What would turn that into a reset? A qualifier that accumulates SE0 rather than requiring it to be continuous. Each packet boundary adds to a count that never clears, so a sufficiently busy interval eventually reaches the threshold and declares a reset that the host never issued.

Why does the host's log confirm rather than contradict this? Because the host genuinely did not reset the port. The event is being manufactured in the device's receive logic, so the absence of any host-side record is exactly what this hypothesis predicts — and would be inexplicable if the host really were resetting.

How would you confirm it in one observation? Capture the conductors and check whether SE0 was ever continuous for the required interval. If it was not, the detection is wrong, and assertion S2 would have caught it in simulation.

The general lesson. A failure whose rate tracks correct activity is usually caused by the correct activity, and the mechanism is almost always something accumulating that should have been measuring. That pattern — works when idle, fails under load, no error upstream — is worth recognising directly, because it recurs wherever a design counts occurrences of a thing instead of measuring the duration of a condition.

10. Understanding Check

11. Summary

Two speeds are announced by position; the third is negotiated. Low and full speed are established statically by which conductor a device's pull-up raises, qualified over an interval rather than at first sight.

A high-speed-capable device attaches claiming full speed, because the static mechanism has no third meaning available, and that claim is a safe truthful default. The upgrade is negotiated inside the reset the host performs anyway: the host drives extended SE0, the device answers with a chirp — a sustained K — and a capable host that saw it replies with an alternating K/J sequence. If the device recognises that, both switch to high-speed operation and the pull-up is removed. The handshake is mutual recognition and fails safe in both directions: any failure to recognise leaves a working full-speed connection.

It uses line states rather than packets because nothing is agreed yet — a packet needs a shared speed, encoding and framing, all downstream of the question being asked — and a sustained line state needs only machinery both ends already have. That is the same principle as the resistor: when nothing is agreed, use a mechanism requiring no agreement.

SE0 means three things separated by duration: a packet boundary when brief, a bus reset when extended, an unoccupied port when persistent with nothing attached. A receiver must therefore qualify SE0 by duration, restarting its measurement on any departure — because accumulating instead of measuring declares resets on a healthy busy bus, at a rate that rises with traffic.

And a bus reset is a protocol event to be detected and reported, not a control input. Wiring it into local reset destroys the logic meant to report it.

12. What Comes Next

This module has repeatedly said the electrical layer and moved on. Every waveform has carried a note saying it depicts no voltages, no rise times and no margin; every RTL block has declared that its inputs are already-thresholded digital values; and Chapter 3.2 drew a clean line between deterministic logic failures and statistical physical ones without examining what lies on the far side.

Chapter 3.8 goes there. It covers the voltage levels the interface defines, why transition speed is specified at both ends rather than only a minimum, what termination and controlled impedance are for, and what a cable actually is electrically. It is also the chapter that is most careful about its own limits: an honest treatment of the electrical layer includes saying clearly which questions a digital engineer can answer, which require instruments, and which belong to specialists whose work this curriculum can describe but not replace.

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.