Skip to content
VLSI Mentor

USB · Module 8

Configured State

The state whose consequences leave the state machine: derived enables versus stored copies, distributed state drift across four holders, and why firmware may disagree with hardware while endpoints may not.

Chapter 8.4 established that a state is a claim about a register, and measured what happens when the claim stops being true.

Configured takes that one step further, and the step is the hard one:

Configured is the first state whose consequences leave the state machine entirely. Address affects one register. Configured brings hardware to life — endpoint logic, buffers, enables — none of which the state machine contains.

Which introduces a failure mode Address does not have. Not two things disagreeing, but many — each locally correct.

1. What Configured Means

A device is Configured after a configuration commit carrying a non-zero value. It holds an address, it holds a configuration, and the endpoints belonging to that configuration operate.

What is legal? Everything the device is for. Data transfers on its function endpoints, plus the control communication that was already legal.

What is guaranteed? That the device holds a non-default address and a non-zero configuration and that the endpoints that configuration declares are operating. Three claims, which is one more than any earlier state, and §3 is about the third.

How is it entered? From Address by a configuration commit with a non-zero value. From Configured itself by re-selecting.

How is it left? To Address by an un-select (Chapter 6.5). To Default by a bus reset. To Attached by power loss or disconnection.

2. The Third Claim Is Different

Compare what the states claim.

StateClaimsHeld where
Defaultaddress is the defaultone register
Addressaddress is assignedone register
Configuredaddress is assigned, and a configuration is selected, and its endpoints operateone register, another register, and hardware elsewhere

The first two claims are about registers the state machine owns. Chapter 8.4's composition invariants work because both sides of each invariant are visible from one place.

The third is not. Endpoint hardware lives in its own block, with its own state, its own buffers, and — critically — its own opinion about whether it is enabled.

So the question this chapter has to answer is: where does that opinion come from?

3. Derived or Stored

Two architectures, and choosing between them is the chapter's central design decision.

Derived

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
assign function_eps_enabled = (dev_state == DEV_CONFIGURED);

The enable is a function of the state. It has no memory. It cannot be wrong unless the state is wrong, and it cannot be forgotten on any transition because there is nothing to forget.

Stored

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
always_ff @(posedge clk) begin
  if (config_commit && config_value != 0) function_eps_enabled <= 1'b1;
  if (bus_reset)                          function_eps_enabled <= 1'b0;
  // ... and every other transition that should clear it
end

The enable is its own state, updated by events. It can be set, and it can be forgotten.

The rule worth carrying:

A derived signal cannot disagree with its source. A stored copy can, and will, at whichever transition nobody thought about.

And the transition nobody thinks about is reliably the same one: the downward one. Setting an enable when a configuration is selected is the obvious half. Clearing it on un-select, on bus reset, on power loss and on disconnection is four separate obligations, and §5 measures what missing one costs.

4. Distributed State Drift

Now the failure mode that is specific to this state.

Four places can hold an opinion about whether the device is configured:

A diagram showing four places that can hold an opinion about whether a device is configured. The protocol state machine holds a state value. The configuration register holds the selected configuration number. The endpoint block holds enable signals controlling whether its endpoints operate. Firmware holds a belief derived from status registers and interrupts. Each is updated by its own events, and an annotation notes that nothing in the design is responsible for keeping the four in agreement.Protocol statemachinedev_state = CONFIGUREDConfigurationregisteractive_config = 1Endpoint blockits own enablesFirmwarewhat software believesThe device is correctonly when all four agreeWho enforcesagreement?nobody, unless somebody istold tomust agreemust agreemust agreemust agree — with alag12
Figure 1 — four holders of one fact. Each is updated by its own events and each can be individually correct; the device is correct only when all four agree, and nothing in the design is responsible for that agreement.

Each is updated by its own events. The state machine by commits and resets. The configuration register by commits and resets. The endpoint block by whatever the designer wired to it. Firmware by status reads and interrupts.

Each can be individually correct and the set can still be wrong, which is Chapter 8.1 §2's point in its most concrete form.

Strategies that work — and none is universally right:

  • One authoritative holder, everything else derived. Strongest guarantee, and constrained by the timing and clock-domain realities of §3.
  • Explicit commit events with a single owner. If several blocks must hold state, one block emits the event and the others consume it — never each deciding independently from the same raw inputs.
  • Clear ownership of reset. Every holder must respond to a bus reset, and the list of holders must be written down somewhere, because the failure is always the one that was not on the list.
  • Cross-block assertions. Chapter 8.4 §4's technique, extended — §6 does exactly that.

What does not work is each block deriving its own opinion from the raw events. That produces four state machines that agree most of the time, which is the hardest failure to find.

5. Firmware Is Allowed to Disagree

An exception that is not a weakening, and a place where the rule genuinely changes.

Hardware holders must agree instantly. The state register, the configuration register and the endpoint enables are all in the same clock domain and all updated by the same events. There is no reason for them to differ on any cycle, and Chapter 8.4's invariants forbid it.

Firmware cannot. It learns about transitions by reading a status register or taking an interrupt, both of which take time. A bus reset can return a device to Default while firmware is midway through a routine that believes it is Configured, and firmware will not find out until it next looks.

So the invariant has to be different in kind. Not firmware agrees with hardware, which is unachievable, but something like firmware's belief is never more than one notification behind — and the notification must be reliable, which is the real requirement hiding underneath.

6. The Configuration Composition Checker

Chapter 8.4's technique, extended to cover the third claim.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// usb_config_composition_check
//
// Classification: VERIFICATION MODEL. Bound alongside the design; never
// drives it.
//
// WHAT IT MODELS. The invariants relating the protocol state, the
// configuration register, and the ENDPOINT ENABLES -- the third of which
// lives in a different block, which is what makes this chapter's checking
// harder than Chapter 8.4's.
//
// WHAT IT DOES NOT MODEL. Endpoint behaviour (Module 9 owns it -- the
// enable arrives here as one abstract bit), transfers (Modules 11-13),
// descriptors (Module 7), the commit decision (Chapter 6.5), or firmware
// timing (section 5 explains why firmware needs a different kind of
// invariant, and this checker deliberately does not attempt it).
//
// ON THE ENABLE INPUT. `eps_enabled` must be sampled from the ENDPOINT
// BLOCK, not from the state machine's derived output. A checker fed the
// state machine's own derivation is checking that a signal equals itself.
// ─────────────────────────────────────────────────────────────────────────
module usb_config_composition_check
  import usb_state_pkg::*;
(
  input logic            clk,
  input logic            rst_n,

  input usb_dev_state_e  dev_state,
  input logic [7:0]      active_config,

  // From the ENDPOINT BLOCK -- see the note above.
  input logic            eps_enabled,

  input logic            bus_reset,
  input logic            config_commit,
  input logic            phys_connected,
  input logic            phys_powered,

  output logic           config_error
);

  logic c1, c2, c3, c4;
  usb_dev_state_e p_state, ds_v;
  logic [7:0]     p_config;
  logic           p_enabled, p_reset, p_commit;

  always @* ds_v = dev_state;

  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      p_state   <= DEV_NOTATTACHED;
      p_config  <= USB_NO_CONFIG;
      p_enabled <= 1'b0;
      p_reset   <= 1'b0;
      p_commit  <= 1'b0;
    end else begin
      p_state   <= dev_state;
      p_config  <= active_config;
      p_enabled <= eps_enabled;
      p_reset   <= bus_reset;
      p_commit  <= config_commit;
    end
  end

  // ── C1: Configured means actually holding a configuration ──────────────
  assign c1 = (dev_state == DEV_CONFIGURED) && (active_config == USB_NO_CONFIG);

  // ── C2: the other direction -- holding a configuration means Configured.
  // Chapter 8.4 section 5 measured a set that had only one direction of an
  // invariant letting two mutations through; this is that lesson applied
  // before rather than after.
  assign c2 = (active_config != USB_NO_CONFIG) && (dev_state != DEV_CONFIGURED);

  // ── C3: THE ONE THIS CHAPTER IS ABOUT. Endpoints operate exactly when
  // the device is Configured. Written as an equality rather than two
  // implications, deliberately: enabled-without-Configured and
  // Configured-without-enabled are both defects, and an equality is the
  // only form that forbids both without needing two properties.
  assign c3 = (eps_enabled != (dev_state == DEV_CONFIGURED));

  // ── C4: a bus reset takes everything down TOGETHER. The conjunction is
  // the requirement (Chapter 8.4's I4, extended by one term).
  assign c4 = p_reset && phys_connected && phys_powered
              && !((dev_state == DEV_DEFAULT)
                && (active_config == USB_NO_CONFIG)
                && !eps_enabled);

  // ── There is deliberately NO provenance invariant here, although Chapter
  // 8.4's I3 is exactly that for the address register. Section 7 explains
  // why: the enable is a single bit fully determined by the state, so C3's
  // equality already constrains it completely and a provenance check adds
  // nothing but a near-vacuous exclusion list.

  assign config_error = c1 | c2 | c3 | c4;

  always_ff @(posedge clk) begin
    if (rst_n) begin
      if (c1) $error("C1: CONFIGURED with no configuration selected");
      if (c2) $error("C2: configuration %0d held while in state %0s",
                     active_config, ds_v.name());
      if (c3) $error("C3: endpoints %0s while state is %0s",
                     eps_enabled ? "ENABLED" : "disabled", ds_v.name());
      if (c4) $error("C4: after reset state=%0s config=%0d eps=%0b",
                     ds_v.name(), active_config, eps_enabled);
    end
  end

endmodule

Classification. Verification model.

What it models. Four invariants relating state, configuration and endpoint enables.

Why it exists. Because the third claim lives in another block, so no property inside either block can relate them.

Inputs. State, configuration register, the endpoint block's own enable, and the events permitted to change any of them.

State retained. One cycle of history, for the two change-based invariants.

Outputs. An error flag and per-invariant reporting.

Reset behaviour. History clears; reporting suppressed during local reset.

Hardware implied. None.

Assumptions. That eps_enabled is sampled from the endpoint block — the header is emphatic because a checker fed the state machine's derived output verifies nothing; and that firmware is deliberately out of scope, per §5.

Deliberately omits. Endpoint behaviour, transfers, descriptors, the commit decision, and firmware timing.

What DV should verify with it. That each invariant fires on its specific defect — §7 measures exactly that.

Two decisions carry the teaching:

  • C3 is an equality, not an implication. Enabled without Configured and Configured without enabled are both defects, and an equality forbids both in one property. Two implications would do the same job and give a reader two chances to write only one — which is Chapter 8.4 §5's measured hole, avoided by construction.
  • C2 exists before a mutation demanded it. §7 does not measure a defect that only C2 catches. It is there because Chapter 8.4 §5 measured a one-directional set letting two mutations through, and applying that lesson before being forced to is the point of having learned it.

And one invariant was removed rather than added. §7 explains why a provenance check belongs in Chapter 8.4's checker and not in this one — the difference being whether the state determines the value.

7. Mutation Test

Five configurations measured, and one of them removed an invariant from §6.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  design / mutation                            C1    C2    C3    C4
  ─────────────────────────────────────────────────────────────────
  derived enable (correct)                      ·     ·     ·     ·
  stored enable, all four clearing paths        ·     ·     ·     ·
  G1  stored, un-select clearing missing        ·     ·     3     ·
  G2  stored, physical-loss clearing missing    ·     ·     7     ·
  G3  configuration register forced to zero    17     ·     ·     ·
  G4  stored, spurious change to the enable     ·     ·     6     ·

The second row matters as much as the others. A stored enable with all four clearing paths present is measured clean — §3's honesty made concrete. Storing is not wrong; storing incompletely is.

G1 — store the enable, forget to clear it on un-select

Result. C3 fires from the un-select onward. The device reports Address, holds no configuration, and its endpoints are still running.

And the consequence is worse than a reporting error. The host un-configured the device precisely because it wants the endpoints to stop — releasing bandwidth, entering a low-power mode, handing the device to another driver. Endpoints that keep operating are consuming resources the host has already reallocated.

G2 — store the enable, forget to clear it on physical loss

Result. C3 fires on disconnection, and for longer than G1 — the state drops to not-attached while the enable stays high.

Why this is the one most likely to survive review. Un-select is a protocol event that appears in the state diagram. Disconnection is not — it arrives from outside the protocol, and a designer enumerating "the transitions that leave Configured" by reading the state machine will list the un-select and the bus reset and stop.

G3 — clear the configuration register without leaving Configured

Result. C1 fires, and C3 does not — the enable follows the state, which did not change.

That is worth noticing rather than passing over. A naive check of the form enabled implies a non-zero configuration would have caught this and the derived architecture does not, because the derived enable is insensitive to the configuration register by construction. The derived architecture is not uniformly stronger; it is stronger against forgotten transitions and blind to a corrupted register, which is precisely why C1 exists.

G4 — a spurious change to a stored enable

Result. C3 fires. The provenance invariant did not — and investigating why removed it from §6.

8. Verification

This chapter's commit point is the device is usable — and usable is a claim about hardware outside the state machine.

Stimulus. Configuration selection and re-selection; un-select from Configured; bus reset from Configured; power loss and disconnection from Configured; a configuration commit in states where it is illegal; and re-configuration after each way of leaving.

The stimulus requirement §7 makes non-negotiable: exercise every exit from Configured, not just the protocol ones. G2 is invisible without a disconnection from Configured, and disconnection is the exit that does not appear in the state diagram.

Observation. The state, the configuration register, and the endpoint block's own enable — the last sampled from the endpoint block, per §6's header.

Reference model. Three fields compared as a set: expected state, expected configuration, expected enable. Comparing them separately reports G3 as two passes and one unrelated failure.

Representative coverage — crosses:

  • exits from Configured: un-select × bus reset × power loss × disconnection — all four
  • configuration value: zero × non-zero × a value the device does not offer
  • state × endpoint-enable, both polarities, for every state
  • re-configuration after each of the four exits
  • configuration commit attempted in Default and Powered

Negative cases with defined outcomes: endpoints must not operate in any state but Configured; an un-select must take the enable down in the same cycle it changes the state; a disconnection must clear everything; and a configuration commit outside Address or Configured must change nothing.

9. Debugging: the Device That Keeps Transmitting

A host un-configures a device to release bandwidth for another device. The bandwidth is not released, and the second device fails to start. The first device's status register reports the Address state.

What is the contradiction? An Address-state device has no operating function endpoints. Something is still using bandwidth.

Which evidence wins? The bandwidth. The status register is the device's claim; the bus is the observation. This is Chapter 8.4 §2's rule again, one layer out: the enable that reaches the endpoint hardware is the fact.

So what do you inspect? The endpoint block's enable, not the state machine's. If the two differ, the enable is stored rather than derived and a clearing path was missed.

Which path? Trace how the device left Configured. §7's G1 misses the un-select; G2 misses disconnection. Here the exit was an un-select, so G1.

Why did no state-machine test catch it? Because the state machine is correct and its test observed the state machine. The enable is in another block, and the endpoint block's own tests exercise endpoints — with the enable asserted, because that is how endpoints are tested.

And the signature? A device that reports a state it is not behaving as is Chapter 8.4's signature, and here it points one block further out. The rule generalises: when a device's report and its behaviour disagree, find the holder of the fact that produces the behaviour, and ask what is supposed to update it.

10. Common Misconceptions

11. Reason It Through

A controller runs its endpoint logic in a different clock domain from its protocol state machine. A reviewer objects that the endpoint enable therefore cannot be derived, and that §3's argument does not apply.

Is the reviewer right about the constraint? Yes. A combinational function of a register in another clock domain cannot be consumed directly; it has to be synchronised, which means registering it, which makes it state.

So does §3's argument fail? No — it relocates. The enable is now stored in the endpoint domain, and the four clearing obligations still exist. They have simply moved from remembering to clear a register to making sure four different events all propagate across the domain crossing.

Which is harder or easier? Harder in one way and easier in another. Harder because a crossing can drop or reorder events, and a disconnection is exactly the kind of event that arrives asynchronously. Easier because the obligation is now visible: a crossing is a thing a reviewer looks at, whereas a missing branch in a case is not.

What is the design that discharges it? Synchronise the state, not the events. If the endpoint domain receives the protocol state — or a single bit derived from it — through a synchroniser, then the enable is still derived, just from a synchronised copy. All four exits change the state, so all four propagate automatically, and no event can be missed because no event is being counted.

And the general principle? Synchronise facts, not events. A fact that crosses a domain carries its own consistency; an event that crosses a domain has to be counted, acknowledged, and reasoned about individually. Where a choice exists, crossing the state is safer than crossing the transitions — and it preserves the derived architecture rather than forcing a stored one.

12. Understanding Check

13. Summary

Configured is the first state whose consequences leave the state machine. Address affects one register; Configured brings hardware to life that the state machine does not contain. It claims three things — an address, a configuration, and operating endpoints — and the third is held somewhere else.

That makes the central design decision derived or stored. A derived enable is a function of the state and cannot disagree with it; a stored enable is its own state and creates one maintenance obligation per exit. Configured has four exits — un-select, bus reset, power loss, disconnection — of which only two appear in the state diagram, and §7 measured the disconnection case as the one most likely to survive review for exactly that reason.

Storing is not wrong, and §3 is honest about why real designs do it: timing paths, clock domains, and fan-out. What storing costs is a structural guarantee converted into a maintenance obligation, and the right response is to write the obligations down and let a cross-block checker enforce them — with §11's better answer available when a domain crossing is the reason: synchronise the state, not the transitions, and the enable stays derived.

Four holders can disagree: the state machine, the configuration register, the endpoint block and firmware. Each is updated by its own events, each can be locally correct, and nothing in the design is responsible for their agreement unless somebody is told to be.

Firmware is the one permitted exception, because it learns through status and interrupts and therefore learns late. The achievable requirement is not agreement but reliable notification — which forces transitions that matter to be sticky rather than polled levels, and forces a bus-reset event register to survive the reset it reports.

14. What Comes Next

Five states, one state machine, and a set of invariants that hold across blocks. The model is complete.

Except that it is not, because one state remains — and it does not fit.

Chapter 8.6 is Suspended, and it breaks the assumption every chapter so far has relied on: that a state is defined by what is true and not by how you got there. A suspended device must remember which state it was suspended from, because resuming returns it there. Suspend is not a sixth peer state at all; it is a modifier on the other five, and implementations that model it as a peer discover the problem at the moment of resume — when the device has to go back somewhere and no longer knows where.

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.