Skip to content
VLSI Mentor

USB · Module 10

Four Transfer Types Overview

The four transfer types are not a list to memorise — they fall out of two orthogonal questions plus one bootstrap question. Deriving them, and the policy block whose outputs are all derived and none stored.

Module 9 built the endpoint: a buffer with an identity, a direction, and its own state. Five chapters described how a flow is addressed, and every one of them said a transaction arrives and stopped.

Chapter 7.4 declared a transfer type in every endpoint descriptor. Chapter 9.1 stored it in a record and never used it.

This module is what that field is for, and it answers a question Module 9 could not:

Not every flow wants the same thing from the bus. Firmware commands want to be correct. Bulk data wants throughput. A mouse wants to be looked at often. An audio stream would rather lose a sample than receive a late one. One shared bus has to serve all of them.

The answer is four service models, and they are not an arbitrary list — §2 derives them from two questions.

1. What a Shared Bus Cannot Do

Start from the constraint, because the four types are a response to it.

There is one bus and one host. Chapter 9.1 §5 established that endpoints are multiplexed in time onto one differential pair, and Chapter 2.6 that the host decides the order. So every flow on every device is competing for the same finite sequence of service opportunities.

Now consider what different flows need from that sequence.

A firmware command must complete correctly. If it is delayed a millisecond, nothing is lost. If it is corrupted and applied anyway, the device is misconfigured.

A file transfer wants as many opportunities as it can get. It does not care when — it cares how much, in total, over seconds.

A mouse needs to be asked reasonably often. Its data is tiny and it produces little, but a report that arrives 200 ms late is a cursor that stutters.

An audio stream needs the next sample on time. A sample that arrives after its playback moment is worthless — and worse than worthless if delivering it delays the next one.

Those are not four degrees of the same requirement. They are different requirements, and no single scheduling policy satisfies all of them.

2. Two Questions Generate Four Answers

Here is the derivation, and it is the chapter's core.

Ask each flow two questions:

Question 1 — does it need service at a predictable rate? Some flows need to be visited on a schedule. Others just need to be visited eventually, as often as possible.

Question 2 — when something goes wrong, is retrying the old data useful? For most data, yes: a corrupted block must be re-sent. For real-time data, a re-sent sample arrives even later than the one that failed, and the moment it belonged to has passed.

The two questions are independent, which gives four combinations:

Retrying old data is usefulRetrying old data is not useful
Needs predictable serviceInterruptIsochronous
Takes what is availableBulk(no such traffic)

Three cells are populated and one is empty, and the empty one is informative: traffic that does not care when it is served but cannot tolerate a retry does not exist in practice. If timing does not matter, a retry costs nothing but time you were not counting anyway.

So where does the fourth type come from? Not from these two questions. Control answers a third one, and it is a question about the protocol rather than about the traffic:

Question 3 — does the bus itself depend on this flow working? Configuration, addressing and descriptor reads must work before anything else can. That is not a throughput or latency requirement; it is a bootstrap requirement, and Chapter 10.2 is about why it produces a separate service model.

3. What the Type Actually Is

Before going further, be precise about what a transfer type is and is not — because the next three modules own the machinery it influences.

A transfer type is a service contract attached to an endpoint. It tells the host what kind of scheduling this flow expects and tells the controller how to treat it.

It is declared once, in the endpoint descriptor's attributes (Chapter 7.4), in two bits:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  bmAttributes[1:0]   0 = Control
                      1 = Isochronous
                      2 = Bulk
                      3 = Interrupt

And it is not:

  • not a direction — that is Chapter 9.2's bit 7, an independent property;
  • not a rate — no transfer type names a bandwidth;
  • not a wireChapter 9.1 §2's point stands unchanged;
  • not a packet formatModule 11 owns packets, and every type uses the same ones;
  • not a transaction structureModule 12 owns that.

4. The Grid, Drawn

A diagram deriving the four USB transfer types. Two independent questions are asked of each flow: whether it needs service at a predictable rate, and whether retrying old data is useful when something goes wrong. Flows needing predictable service where retry is useful map to interrupt transfers; flows needing predictable service where retry is not useful map to isochronous transfers; flows taking whatever service is available where retry is useful map to bulk transfers. The fourth combination, indifferent to timing but unable to tolerate retry, has no real traffic. Control transfers sit outside this grid because they answer a different question: whether the bus itself depends on the flow working, which is a bootstrap requirement rather than a traffic requirement.Predictable service?must be visited on ascheduleIs a retry useful?is old data still worthhavingInterruptpredictable · retry usefulIsochronouspredictable · retry uselessBulkopportunistic · retryuseful(no such traffic)indifferent to timing, yetcannot retryControlthe bus depends on itworkingyesnonoa different question12
Figure 1 — the four types are not a list but the cells of a grid, and the empty cell is informative: traffic indifferent to timing has no reason to refuse a retry. Control sits outside the grid because its requirement is about the protocol's own bootstrap rather than about the traffic.

5. What the Bus Has to Give Up

The grid explains what flows want. The bus then has to reconcile the demands, and the reconciliation has a shape worth seeing now.

Predictable service has to be reserved in advance. A flow promised a visit at a regular interval can only be promised it if the capacity is set aside — otherwise the promise is worth nothing the moment the bus gets busy.

So the periodic types consume budget whether or not they use it. An interrupt endpoint asking to be polled every millisecond costs that allocation continuously, from configuration until the device is un-configured — Chapter 7.3 §3's alternate settings exist precisely so a device can avoid paying when idle.

And the reservation is capped. It has to be: if periodic flows could reserve everything, there would be nothing left for the traffic that takes what is available — including the control traffic the bus depends on.

The cap is real and specific. Host implementations enforce it directly. The Linux kernel defines a full-speed frame as 1 millisecond, 12,000 bit times, and caps periodic allocation at 90% of it:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
#define FRAME_TIME_BITS            12000L   /* frame = 1 millisecond */
#define FRAME_TIME_MAX_BITS_ALLOC  (90L * FRAME_TIME_BITS / 100L)

At least a tenth of every frame is therefore unavailable to periodic traffic, and that residue is what Bulk and Control run in.

6. The Policy Decode, as RTL

A controller has to turn two bits into behaviour. This is the module's first block, and its design is determined by a lesson Module 9 learned the hard way.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// ─────────────────────────────────────────────────────────────────────────
// usb_xfer_policy
//
// Classification: SIMPLIFIED SYNTHESIZABLE TEACHING RTL. It derives a
// controller's treatment of an endpoint from its transfer type, and holds
// no state at all.
//
// WHAT IT MODELS. Section 2's grid, as combinational logic: the two
// questions -- does this flow need predictable service, and is a retry
// useful -- read directly out of the transfer type, plus the protocol-level
// property that identifies the management path.
//
// WHAT IT DOES NOT MODEL. Anything that ACTS on the policy: scheduling
// (Chapter 10.3 builds an arbiter), event pending state (Chapter 10.4),
// freshness (Chapter 10.5), transactions (Module 12), packets (Module 11),
// or the handshake behaviour that makes "retry" concrete (Modules 11-12
// own it -- this block only says whether retry is MEANINGFUL for the flow).
//
// ── WHY THERE IS NO STATE HERE ─────────────────────────────────────────
// The transfer type is already stored, once, in the endpoint record
// (Chapter 9.1). Every output below is a function of it. Registering these
// separately would create four more pieces of state that must be written
// when a configuration is selected, cleared on a bus reset, and kept in
// agreement with the record forever -- which Chapter 9.3 section 7 measured
// going wrong on a reset path, and Chapter 8.5 section 3 argued about at
// length. A derived signal cannot disagree with its source.
// ─────────────────────────────────────────────────────────────────────────
package usb_policy_pkg;
  import usb_ep_pkg::*;

  // The controller's treatment of one endpoint. Every field is DERIVED.
  typedef struct packed {
    // Section 2, question 1. The host must offer this endpoint service at
    // a rate the configuration asked for, which means capacity is reserved
    // (section 5) and the flow is scheduled rather than fitted in.
    logic periodic;

    // Section 2, question 2. Whether re-sending data that failed is worth
    // doing. NOTE this says the retry is MEANINGFUL, not that a particular
    // handshake occurs -- Modules 11 and 12 own the mechanism.
    logic retry_meaningful;

    // Section 2, question 3. This endpoint carries the management traffic
    // the bus itself depends on (Chapter 10.2).
    logic management_path;

    // Consumes reserved budget from the cap of section 5. True exactly for
    // the periodic types, and stated separately from `periodic` because a
    // scheduler asks the two questions at different times: one when
    // admitting a configuration, the other when choosing what to serve.
    logic consumes_reservation;
  } ep_policy_t;

endpackage

module usb_xfer_policy
  import usb_ep_pkg::*, usb_policy_pkg::*;
(
  // The authoritative transfer type, from the endpoint record (Chapter 9.1).
  input  ep_xfer_type_e xfer_type,

  // Endpoint zero is the control endpoint whether or not anything declared
  // it (Chapter 9.3 section 2), so the policy has to know which endpoint
  // this is -- the type alone is not sufficient to identify it.
  input  logic          is_endpoint_zero,

  output ep_policy_t    policy
);

  always_comb begin
    // Deterministic default: the most restrictive policy. An unrecognised
    // encoding gets no reservation, no periodic promise and no management
    // privilege -- a fail-safe direction, since every field grants
    // something rather than forbidding it.
    // Written field by field rather than as a named assignment pattern:
    // the pattern form is standard but not universally supported, and RTL
    // in a tutorial should compile in whatever the reader has to hand.
    policy.periodic             = 1'b0;
    policy.retry_meaningful     = 1'b0;
    policy.management_path      = 1'b0;
    policy.consumes_reservation = 1'b0;

    unique case (xfer_type)

      EP_CONTROL: begin
        // Not periodic: control traffic runs in what is left (section 5).
        // Retry IS meaningful -- a management operation that failed must be
        // repeated, because the alternative is a device in an unknown
        // configuration.
        policy.retry_meaningful = 1'b1;
        policy.management_path  = 1'b1;
      end

      EP_ISOC: begin
        // The only type where retry is NOT meaningful (Chapter 10.5).
        policy.periodic             = 1'b1;
        policy.consumes_reservation = 1'b1;
      end

      EP_BULK: begin
        // Opportunistic and retryable -- the plain case (Chapter 10.3).
        policy.retry_meaningful = 1'b1;
      end

      EP_INTR: begin
        // Predictable service AND retryable (Chapter 10.4).
        policy.periodic             = 1'b1;
        policy.retry_meaningful     = 1'b1;
        policy.consumes_reservation = 1'b1;
      end

      default: ;   // keep the restrictive default
    endcase

    // Endpoint zero is the management path regardless of what its type
    // field says, because it exists before any descriptor declares anything
    // (Chapter 9.3 section 2).
    //
    // Placed AFTER the case deliberately. Section 8 measured that with the
    // arms as written -- each setting only the bits it owns -- the position
    // makes no difference, because nothing above can clear these. It starts
    // to matter the moment any arm assigns the whole struct, which is a
    // normal style and is exactly what the default assignment does. So this
    // placement is a defence against a future edit rather than a current
    // necessity, and section 8 is explicit about the difference.
    if (is_endpoint_zero) begin
      policy.management_path  = 1'b1;
      policy.retry_meaningful = 1'b1;
    end
  end

endmodule

What it models. §2's grid, as a function of the transfer type.

Engineering reason. A controller must treat endpoints differently, and the difference has to come from somewhere. Deriving it from the authoritative type is the alternative to storing four more flags per endpoint.

Inputs. The transfer type from the endpoint record, and whether this is endpoint zero.

State retained. None, deliberately — the header says why.

Outputs. Four derived policy bits.

Hardware implied. A small decoder: a 2-to-4 decode and a handful of gates, replicated or shared depending on the controller's structure. No flip-flops.

Reset behaviour. None required. That is the point of deriving: there is no reset path to get wrong, which is the defect Chapter 9.3 §7 measured on endpoint zero's enable.

Assumptions. That xfer_type comes from the endpoint record and is not a second copy; that an endpoint's type does not change while traffic is in flight — it changes only at a configuration commit (Chapter 8.5); and that endpoint zero is identified by Chapter 9.2's decode.

Omissions. Everything that acts on the policy, and all transaction and packet mechanism.

What DV should verify. That each of the four types produces exactly the documented policy; that an unrecognised encoding produces the restrictive default; that endpoint zero is always a management path whatever its type says; that no output is ever asserted for a type the grid does not assign it to; and — the composition property — that the policy always agrees with the record's type, since nothing else in the design should be able to make them differ.

7. Application Mappings Are Consequences, Not Definitions

Everyone learns the table. It is worth stating why it is the wrong thing to learn.

Commonly memorisedWhat actually determines it
keyboards and mice use Interruptsmall events needing regular service opportunities, where a retry is still useful
mass storage uses Bulklarge volumes needing correctness, indifferent to when
audio and video use Isochronousa continuous stream where a late sample is worthless
enumeration uses Controlthe bus depends on this working before anything else can

The right-hand column is the definition. The left is an example.

And the mappings break as soon as the requirement changes. A device that streams high-rate sensor data with timestamps may use Bulk, because the timestamps make late delivery useful and throughput matters more than regularity. A storage device's status notifications may use Interrupt, because they are small and want prompt attention. A vendor command channel may use Bulk rather than Control, because it moves more data than a management path should.

The design question is always the two questions of §2, asked of the flow you have.

8. Mutation Test

Four mutations. One survived and the investigation changed what §6's ordering comment claims.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  mutation                                    result
  ──────────────────────────────────────────────────────────────────────
  correct decoder                             OK
  P1  Interrupt decoded as Bulk               4 failures (reference model)
  P2  policy stored instead of derived        disagrees after a bus reset
  P3  endpoint-zero handling moved earlier    SURVIVES
  P3b P3 plus one arm assigning the struct    2 failures

P1 — decode Interrupt as Bulk

Result. Four failures against §9's reference model. Nothing inside the decoder fails — the outputs are internally consistent, and the module has no notion of what an interrupt endpoint deserves.

The downstream consequence is severe. An interrupt endpoint reported as non-periodic consumes no reservation, so Chapter 10.4's service guarantee silently does not apply: the endpoint is admitted without capacity being set aside and then competes as opportunistic traffic. It works on an idle bus and degrades under load.

P2 — store the policy instead of deriving it

Register the outputs at a configuration commit.

Result, traced across a bus reset:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  after configuring an ISOCHRONOUS endpoint
      stored  consumes_reservation = 1      derived = 1

  after a bus reset (the record's type returns to its reset value)
      stored  consumes_reservation = 1      derived = 0
      >>> the stored policy disagrees with the record it came from

The controller now treats a freshly-reset endpoint as reserving periodic capacity, on the authority of a configuration that no longer exists. This is Chapter 9.3 §7's measured defect in a new place, and the reason §6's header is emphatic: a derived signal has no reset path to forget.

P3 — move the endpoint-zero handling before the case

The prediction was that endpoint zero would lose its management status whenever its type field held something other than Control.

Result: it survives. Endpoint zero keeps management_path for every type in its record, with the handling before the case exactly as with it after.

Why? Because the case arms are additive. Each arm sets only the bits it owns and never clears the others; the single assignment at the top of the always_comb is what clears. So the endpoint-zero block's assignments cannot be undone by any arm, wherever it sits.

P3b — the same reordering, plus one arm that assigns the whole struct

Change the isochronous arm to assign all four fields, in the style the default assignment uses.

Result, probed across endpoint zero with each type in its record:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
                    correct / P3          P3b
  EP0, type ISOC    mgmt=1 retry=1        mgmt=0 retry=0   ← lost
  EP0, other types  mgmt=1 retry=1        mgmt=1 retry=1

Two failures against the reference model, and the failure mode is the predicted one — endpoint zero stops being recognised as the management path, which produces a device that cannot be enumerated at all.

9. Verification

This module's commit point is the right service model was applied to the flow.

The reference model is a four-entry table stating, for each transfer type, what the policy should be — written from the specification's definitions rather than from §6's case statement. Comparing two independently-derived mappings is the only meaningful check of a decoder, per §8's callout.

Stimulus. Each of the four types; an unrecognised encoding; endpoint zero with each type in its record, including the reset value; and a type change across a configuration commit and a bus reset.

The stimulus requirement §8 makes non-negotiable: exercise endpoint zero with a non-Control type in its record. P3 is invisible otherwise, and no configuration ever sets endpoint zero's type — so the case only arises from a reset value, which a test driving realistic configurations never produces.

Observation. All four policy bits, and the endpoint record's type, compared as a pair. P2's defect is a disagreement between them and is invisible to an observation of the policy alone.

Coverage — crosses:

  • transfer type × endpoint zero versus a data endpoint — all eight cells
  • transfer type × a bus reset between the commit and the observation
  • unrecognised encodings, each producing the restrictive default
  • policy observed immediately after a configuration commit and after a bus reset

Negative cases with defined outcomes: an unrecognised type must grant nothing; endpoint zero must be a management path regardless of its type field; and no type may produce a policy the grid does not assign it.

10. Common Misconceptions

11. Reason It Through

A device streams sensor data at a high, steady rate. Each sample carries a timestamp. A reviewer proposes Isochronous, because the data is a continuous real-time stream.

Does the traffic need predictable service? It is produced at a steady rate, so the buffer must be drained at a comparable average rate — but that is an average requirement, not a per-visit one. If the host is late and then catches up, nothing is lost.

Is a retry useful? Yes — and this is the deciding question. The samples carry timestamps, so a sample delivered late is still correct: the consumer knows when it was taken and can place it properly. Lateness costs buffering, not meaning.

So which cell of §2's grid? Retry useful, service need is average rather than per-visit — which is Bulk.

What would Isochronous cost here? Two things. It consumes reserved capacity continuously, from §5's capped budget, reducing what is available to everything else on the bus. And it discards data the application would rather have received late, since the whole point of the type is to prefer timeliness over completeness — which is the opposite of what timestamped data wants.

When would the reviewer be right? If the samples had no timestamps and were consumed as a live stream, so that a late sample could not be placed and would corrupt the stream's cadence. The timestamps are what change the answer, and they are an application-level detail that the transfer-type decision depends on entirely.

And the transferable point? Real-time is not a property of the data rate. It is a property of whether late data is still useful — which is §2's second question, and it is answered by the consumer, not by the producer.

12. Understanding Check

13. Summary

One bus serves flows with genuinely different requirements, and no single scheduling policy satisfies all of them. The four transfer types are the response.

They are derivable rather than arbitrary. Two independent questions — does this flow need predictable service? and is retrying old data useful? — produce three populated cells: Interrupt (predictable, retryable), Isochronous (predictable, retry useless), Bulk (opportunistic, retryable). The fourth cell is empty because traffic indifferent to timing has no reason to refuse a retry. Control answers a third question — does the bus itself depend on this working? — which is about the protocol's bootstrap rather than about the traffic.

A transfer type is a service contract, declared in two bits of an endpoint descriptor. It is not a direction, a rate, a wire, a packet format or a transaction structure — and transfer, transaction and packet are nested things this module keeps carefully apart, because Modules 11 and 12 own the lower two.

Predictable service must be reserved, and reservation must be capped. The Linux kernel enforces it at 90% of a 12,000-bit-time frame, leaving at least a tenth for Bulk and Control — which is simultaneously why periodic flows can be promised anything, why Bulk can be promised nothing, why management traffic always has somewhere to run, and why a device asking for too much can fail to configure.

In hardware the type becomes a derived policy — never a stored copy, because §8 measured a stored one surviving a bus reset that cleared the type it came from. And §8's other measurements: decoding one type as another is caught by nothing inside the decoder, because a mapping can only be checked against an independently-sourced second mapping; and letting endpoint zero's type field override its management status produces a device that cannot enumerate at all.

Finally, the application mappings everyone memorises are consequences. Keyboards use Interrupt is an example; the definition is the requirement, and traffic that does not match the stereotype picks differently.

14. What Comes Next

Three of the four types answer questions about the traffic. One does not.

Chapter 10.2 is Control, and it is the type that exists because of a problem the protocol has with itself: every other type requires a configured device, and configuring a device requires talking to it. Control is the service model that resolves that, which is why it is the one type available before anything else works — and why the guarantees it needs are unlike the other three.

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.