深入理解 USB 通信与 FPGA 实现:从协议到逻辑设计
前言
USB(Universal Serial Bus)是我们日常工作中最熟悉的接口之一,但很多开发者对它的理解往往停留在“插上就能用”的层面。当我们深入到底层,特别是要在 FPGA 上实现一个 USB 设备时,会发现 USB 的架构与 PCIe 等总线有着本质区别。
本文将从四个核心问题出发,系统梳理 USB 的通信模型、协议层次、设备分类,并最终聚焦于在 Xilinx Kintex-7 410T FPGA 上实现 USB 2.0 设备的逻辑设计框架。
让我们开始这场从协议到实现的旅程。
一、核心区别:PCIe 直接寻址 vs USB 消息传递
1.1 PCIe 的内存映射模型
PCIe 设备采用内存映射 I/O(MMIO)机制。系统启动时,BIOS/OS 将设备内部的寄存器或存储空间直接映射到系统物理内存地址空间中。
CPU 可以像访问普通内存一样,通过 LOAD/STORE 指令直接读写设备寄存器。这是硬件层面的事务,对 CPU 几乎透明,延迟极低。
1.2 USB 的消息传递模型
USB 则完全不同,它是一种基于包(Packet) 的消息传递协议。USB 设备没有映射到系统内存地址空间。
整个过程 CPU 完全不感知设备的“内部地址”。CPU 只知道与 USB 主机控制器 通信,设备的内部地址只有设备自己的控制器能解析。
1.3 形象类比
| 对比维度 | PCIe | USB |
|---|---|---|
| 通信模型 | 直接寻址 | 消息传递 |
| 类比 | 设备内存直接插在 CPU 地址总线上 | 打电话让设备管理员查资料 |
| 访问方式 | CPU 直接 LOAD/STORE | 发指令包,由设备控制器解析 |
| 延迟 | 极低(硬件事务) | 较高(需封装/解封装) |
| 典型应用 | NVMe 固态硬盘、显卡 | U盘、键盘、鼠标 |
这也解释了为什么 NVMe 固态走 PCIe 延迟极低,而 U 盘走 USB 延迟就高很多。
二、USB 设备端协议:层次化解析
正因为 USB 不能直接寻址,所有操作都必须在消息传递的框架下进行。USB 设备端协议分为三个清晰的层次。
2.1 第一层:物理与包结构
这是最底层,USB 传输不靠寻址,而靠标准化的包(Packet)。
包的基本格式:
| 字段 | SYNC | PID | 地址/数据 | CRC | EOP |
|---|---|---|---|---|---|
| 描述 | 同步字段 | 包标识符 | 负载内容 | 校验 | 包结束 |
关键包类型:
| 类型 | 名称 | 作用 | 发起方 |
|---|---|---|---|
| 令牌包 | IN/OUT/SETUP | 指明传输方向与类型 | 仅主机 |
| 数据包 | DATA0/DATA1 | 承载实际数据,交替同步 | 主机或设备 |
| 握手包 | ACK/NAK/STALL | 设备回应状态 | 仅设备 |
2.2 第二层:事务与传输——四种核心对话逻辑
这一层解决主机和设备控制器之间如何可靠对话的问题。USB 定义了四种标准传输类型:
(1)控制传输——所有设备必须支持
控制传输是所有 USB 设备的根基,用于设备的初始配置和命令下发。
三个标准阶段:
- SETUP 阶段:主机发送命令
- DATA 阶段(可选):根据命令方向传输数据
- STATUS 阶段:汇报操作结果
(2)批量传输——大数据、高可靠
- 特点:可靠传输,有 CRC 校验和重传机制,利用总线空闲带宽
- 典型场景:U盘读写、打印机
- 权衡:无延迟保证,但数据 100% 正确
(3)中断传输——小数据、低延迟
- 特点:主机以固定间隔轮询设备
- 典型场景:鼠标每隔 8ms 被问一次"有移动吗?"
- 权衡:保证最大延迟上限,适合实时交互
(4)同步传输——流媒体、实时性优先
- 特点:不可靠传输,没有重传机制
- 典型场景:USB 麦克风、摄像头
- 权衡:为保带宽和实时性,数据错了就丢弃
2.3 第三层:设备类协议——定义数据的通用语言
这一层解决了主机如何理解设备数据的含义。USB-IF 定义了若干标准设备类,使得不同厂商的设备能使用通用驱动。
常见设备类及代码:
| 类代码 | 类名称 | 典型设备 |
|---|---|---|
| 01h | Audio (UAC) | USB声卡、耳机、麦克风 |
| 02h | CDC (通信设备) | USB网卡、虚拟串口 |
| 03h | HID (人机接口) | 键盘、鼠标、手柄 |
| 06h | Image | 扫描仪、数码相机 |
| 07h | Printer | 打印机 |
| 08h | Mass Storage (MSC) | U盘、移动硬盘 |
| 09h | Hub | USB集线器 |
| 0Eh | Video (UVC) | 网络摄像头 |
| 0Fh | Personal Healthcare | 血压计、血糖仪 |
| FFh | Vendor Specific | 厂商自定义设备 |
HID 类的精妙之处
HID 类不限于键盘鼠标,其灵活性源于报告描述符(Report Descriptor):
报告描述符是一段代码,能精确告诉主机:“我传的 8 字节数据里,第 1 字节低 3 位是左、中、右键,第 2、3 字节是 X 轴移动距离……”
这种自描述能力使得 HID 协议可以适配几乎任何输入设备。
MSC 类的工作原理
三、USB 设备类全景图
USB-IF 定义了十几大类标准设备,涵盖了我们日常使用的大部分外设。
查看设备类别的方法:
在 Windows 设备管理器中,查看设备属性的"详细信息"->“硬件 Id”,其中的兼容 ID 字段通常包含类代码。例如 USB\Class_08 表示大容量存储设备。
四、FPGA 实现:Kintex-7 410T USB 2.0 设备
4.1 为什么在 FPGA 上实现 USB?
Xilinx Kintex-7 410T 拥有丰富的逻辑资源和高速收发器,可以灵活实现各种 USB 设备类型。相比 MCU 方案,FPGA 的优势在于:
- 高吞吐量:可以充分发挥 USB 2.0 480Mbps 带宽
- 灵活定制:实现任意设备类或复合设备
- 并行处理:数据采集与 USB 通信完全并行
4.2 在 7K410T 上常见的设备类型
最常见的选择: 为了实现最大吞吐量,通常配置为厂商自定义类 + 大批量 IN 端点的高性能数据流设备。
4.3 关键硬件:外部 ULPI PHY
7K410T 通常不内置 USB PHY,需要外接一个 ULPI 接口的 USB 2.0 PHY 芯片(如 Microchip USB3320)。
ULPI 是什么?
ULPI(UTMI+ Low Pin Interface)将 USB 物理层的模拟部分和数字部分标准化,用 12 根信号线连接 FPGA 和 PHY 芯片。
ULPI 接口核心信号(12线双向总线模式):
| 信号名 | 方向 | 位宽 | 描述 |
|---|---|---|---|
| CLK | PHY → FPGA | 1 | 60MHz 接口时钟 |
| DATA | 双向 | 8 | 8 位数据/命令总线 |
| DIR | PHY → FPGA | 1 | 方向指示(高=PHY在发送) |
| STP | FPGA → PHY | 1 | FPGA 请求停止/接管总线 |
| NXT | PHY → FPGA | 1 | PHY 准备好接收/发送下一字节 |
4.4 数据传输时序示例
以 FPGA 通过 ULPI 发送一个 USB 数据包为例:
简单来说,ULPI 就是把复杂的 USB 模拟世界,变成 FPGA 能直接对话的同步 8 位数字总线。
五、FPGA 内部逻辑设计框架
5.1 整体架构
5.2 各模块详解
(1)ULPI 总线控制器
这是最底层模块,负责驱动外部 PHY 的 12 根信号线。
功能:
- 将上层"发数据包/收数据包"请求翻译成 ULPI 总线时序
- 处理 DIR、STP、NXT 信号,实现双向总线仲裁
- 严格的时序逻辑模块
(2)协议引擎 (SIE - Serial Interface Engine)
这是 USB 2.0 协议栈的核心,最复杂的部分。
发送路径:
端点控制器 → 数据 → [添加 PID] → [计算 CRC] → [NRZI 编码] → [位填充] → ULPI 控制器
接收路径:
ULPI 控制器 → 串行流 → [同步检测] → [NRZI 解码] → [位去填充] → [CRC 校验] → [提取 PID] → 数据 → 端点控制器
(3)端点控制器
管理设备的各种端点(Endpoint),这是协议的核心管理层。
端点 0 的特殊性:
- 必须实现,处理所有标准设备请求
- 硬件状态机自动解析 SETUP 包
- 响应标准请求:获取描述符、设置地址、设置配置等
其他端点的作用:
- IN 端点:应用往里写数据,USB 主机读取(FPGA→主机)
- OUT 端点:主机发数据过来,应用读取(主机→FPGA)
(4)描述符与请求处理
硬件负责解析包,但内容需要你来填充。
两种实现方式:
| 方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 纯硬件状态机 | 固定功能设备 | 高效、低资源 | 灵活性差 |
| 软核 CPU (MicroBlaze) | 多功能复合设备 | 灵活、易修改 | 资源消耗大 |
(5)你的应用逻辑
这是 FPGA 价值最大的部分。以高速数据采集卡为例:
应用逻辑只需要关心:FIFO 不满时就往里写数据,完全不需要关心 USB 总线状态。USB 协议栈会自动打包发送。
5.3 典型设计流程总结
在 Kintex-7 上实现 USB 2.0 设备的步骤:
- 硬件选型:外部 USB3320 PHY,12 线 ULPI 模式
- IP 核集成:在 Vivado 中例化 USB 2.0 Device IP,配置为"仅设备模式",定义批量端点
- 时钟与复位:连接 60MHz PHY 时钟,设计全局复位
- 核心逻辑:搭建应用逻辑,实现端点 0 的管理状态机或 MicroBlaze 固件,设计数据流 FIFO
- 约束与调试:ULPI 接口管脚分配和时序约束,上板验证
六、总结
本文从四个角度深入剖析了 USB 通信:
- 与 PCIe 的本质区别:USB 是消息传递模型,主机不能直接寻址设备内部寄存器
- 三层协议架构:物理包结构 → 四种传输类型 → 设备类协议
- 设备类全景:十几大类标准设备,HID/MSC/UVC/UAC 是最常用的
- FPGA 实现框架:ULPI 接口 + SIE 协议引擎 + 端点控制器 + 应用逻辑
理解这套分层体系,不仅能帮助我们更好地使用 USB 设备,也为在 FPGA 上实现定制化 USB 解决方案打下了坚实基础。
本文旨在提供系统化的 USB 底层知识。实际 FPGA 开发请参考 Xilinx 官方文档和 USB-IF 规范。

233

被折叠的 条评论
为什么被折叠?



