2. 控制传输协议详解

控制传输(Control Transfer)是 USB 协议中最基础、最复杂的传输类型,也是 FPGA 验证中故障率最高的环节。它由 Setup 阶段、Data 阶段(可选) 和 Status 阶段 三个逻辑阶段组成,每个阶段都包含严格的令牌包、数据包和握手包交互。本章从 FPGA 验证视角,逐阶段拆解协议细节与常见故障点。

2.1 控制传输整体流程

控制传输总是从主机发起的 Setup 事务开始,随后根据请求方向决定 Data 阶段的方向(IN 或 OUT),最后以 Status 阶段结束。下图展示了标准控制传输的完整状态机:

控制传输三阶段状态机 IDLE 等待主机请求 Setup 阶段 令牌+数据+握手 Data 阶段 IN/OUT 事务 Status 阶段 反向握手确认 COMPLETE 传输完成 Data 阶段可选 无数据时直接跳 Status
FPGA 验证要点: 控制传输的每个阶段都必须严格按照 USB 2.0 规范的第 8.5 节执行。FPGA 状态机设计时,需为每个阶段设置独立的超时计数器(典型值 5 μs),防止因设备无响应导致总线死锁。

2.2 Setup 阶段

Setup 阶段是控制传输的起始阶段,由主机向设备发送 8 字节的 Setup 数据包。该阶段包含三个事务:令牌包、数据包和握手包。

2.2.1 令牌包格式

Setup 阶段的令牌包使用 SETUP(PID = 0xB4) 令牌,格式如下:

字段宽度(bit)描述
SYNC8同步序列(00000001)
PID8包标识符(SETUP = 0xB4)
ADDR7设备地址(0~127)
ENDP4端点号(控制端点必须为 0)
CRC55令牌包 CRC 校验
EOP—包结束(SE0 状态)
常见故障: FPGA 验证中,Setup 令牌包的 ADDR 字段错误是最常见的故障之一。如果主机发送的地址与设备枚举时分配的地址不一致,设备将不会响应 ACK,导致主机超时重试。

2.2.2 数据包格式

Setup 阶段的数据包固定为 8 字节,使用 DATA0 PID(0xC3)。数据包结构如下:

偏移字段宽度(byte)描述
0bmRequestType1请求类型(方向、类型、接收者)
1bRequest1请求码(如 GET_DESCRIPTOR = 0x06)
2~3wValue2请求参数(小端序)
4~5wIndex2索引(如接口号或端点号)
6~7wLength2Data 阶段期望传输的数据长度

2.2.3 握手包

设备在正确接收 Setup 数据包后,必须返回 ACK(PID = 0xD2) 握手包。如果设备检测到 CRC 错误或数据包损坏,应保持静默(不返回任何握手包),主机将超时重发。

Setup 阶段事务时序 SETUP 令牌 DATA0 (8B) ACK t0 t1 t2

2.3 Data 阶段(IN/OUT)

Data 阶段根据 Setup 包中 bmRequestType 的 bit[7](方向位)决定:0 = OUT(主机到设备),1 = IN(设备到主机)。Data 阶段可能包含多个数据事务,每个事务使用 DATA1/DATA0 交替翻转(Data Toggle)机制。

2.3.1 IN 事务

主机通过 IN 令牌(PID = 0x96)请求设备发送数据。设备收到 IN 令牌后,返回 DATA 包(DATA1 或 DATA0),主机收到后回复 ACK。

事务元素发送方PID说明
令牌包主机IN (0x96)请求设备发送数据
数据包设备DATA1/DATA0数据负载,最大 64 字节(全速)
握手包主机ACK (0xD2)确认接收成功

2.3.2 OUT 事务

主机通过 OUT 令牌(PID = 0x87)通知设备准备接收数据,随后主机发送 DATA 包,设备回复 ACK。

事务元素发送方PID说明
令牌包主机OUT (0x87)通知设备准备接收
数据包主机DATA1/DATA0数据负载
握手包设备ACK (0xD2)确认接收成功
Data Toggle 验证技巧: FPGA 验证中,务必在逻辑分析仪中捕获 DATA0/DATA1 的切换序列。控制传输的 Data 阶段起始 DATA PID 由 Setup 阶段决定:Setup 使用 DATA0,后续第一个 Data 事务使用 DATA1,之后交替翻转。Status 阶段固定使用 DATA1。

2.4 Status 阶段

Status 阶段是控制传输的最后一个阶段,用于确认整个控制传输是否成功完成。Status 阶段的方向与 Data 阶段相反:

  • 如果 Data 阶段是 IN(设备→主机),则 Status 阶段为 OUT(主机→设备),主机发送一个零长度数据包,设备回复 ACK。
  • 如果 Data 阶段是 OUT(主机→设备),则 Status 阶段为 IN(设备→主机),设备发送一个零长度数据包,主机回复 ACK。
  • 如果无 Data 阶段(wLength = 0),则 Status 阶段为 IN,设备发送零长度数据包。
Status 阶段方向判定逻辑 bmRequestType[7] 方向位判定 bit[7] = 1 (IN) Data 阶段为 IN Status = OUT bit[7] = 0 (OUT) Data 阶段为 OUT Status = IN

2.5 各阶段数据包格式汇总

下表汇总了控制传输三个阶段中所有可能出现的包格式及其 PID 值:

阶段包类型PID(二进制)PID(十六进制)数据负载
Setup令牌包1011 01000xB4ADDR+ENDP+CRC5
数据包1100 00110xC38 字节 Setup 数据
握手包1101 00100xD2无
Data (IN)令牌包1001 01100x96ADDR+ENDP+CRC5
数据包1100 0011 / 0100 10110xC3 / 0x4B0~64 字节
握手包1101 00100xD2无
Data (OUT)令牌包1000 01110x87ADDR+ENDP+CRC5
数据包1100 0011 / 0100 10110xC3 / 0x4B0~64 字节
握手包1101 00100xD2无
Status令牌包1001 0110 / 1000 01110x96 / 0x87ADDR+ENDP+CRC5
数据包0100 10110x4B零长度(仅 PID+EOP)
握手包1101 00100xD2无

2.6 FPGA 验证中的常见故障模式

基于实际项目经验,控制传输在 FPGA 验证中高频出现的故障可归纳为以下六类:

  1. Setup 包 CRC5 错误:FPGA 的令牌包 CRC5 生成器实现错误,导致设备丢弃 Setup 令牌。验证时应使用 USB 分析仪对比 CRC5 计算值。
  2. Data Toggle 不同步:主机与设备的 DATA PID 翻转状态不一致,设备返回 NYET 或 STALL。FPGA 状态机必须为每个端点维护独立的 toggle 位。
  3. Status 阶段方向错误:FPGA 状态机未正确解析 bmRequestType[7],导致 Status 阶段使用错误的方向令牌,设备无响应。
  4. 超时处理不当:设备无响应时,主机未在 5 μs 内超时重试,导致总线挂起。FPGA 验证中需在状态机中插入超时跳转逻辑。
  5. wLength 与实际数据长度不匹配:Setup 包中的 wLength 字段与 Data 阶段实际传输的数据长度不一致,设备返回 STALL 握手。
  6. EOP 时序违规:FPGA 的包结束信号(SE0)宽度不符合 USB 规范(全速 2 bit time),导致接收端无法正确识别包边界。
验证建议: 在 FPGA 仿真环境中,建议为控制传输的每个阶段编写独立的 scoreboard,分别检查令牌包 PID、数据包 CRC16/CRC5、握手包类型和 Data Toggle 状态。使用 SystemVerilog 的断言(assertion)实时监控协议违规,可大幅缩短故障定位时间。