在 SpinalHDL 中为 RISC-V SoC 实现 USB 1.0 主机控制器
基于 RISC-V 开发可综合片上系统需要集成现代外围接口。USB 1.0 主机控制器支持连接 HID 输入设备:键盘、鼠标、游戏手柄。用 SpinalHDL 实现它,能在硬件层面处理协议,避免 PS/2 或模拟摇杆的软件妥协。
USB 物理层采用差分对 D+ 和 D-,以及 VBUS 和 GND 线。半双工传输模式将 USB 与 UART 区分开来:数据一次仅一个方向逐位发送,并严格分离主机与设备角色。
USB 1.0 物理层
电气特性定义信号电平:D+ 和 D- 的空闲状态决定速度。低速(1.5 Mbps)—— D- 高电平,全速(12 Mbps)—— D+ 高电平。NRZI 编码:信号跳变表示 '1',无跳变表示 '0'。同步通过位填充实现:连续六个相同位后插入反转位。
控制信号:
- SE0 (Single Ended Zero):D+/D- 均低——用于总线复位。
- J/K 状态:用于空闲和速度的差分电平。
- Chirp:K/J 交换以检测集线器速度。
传输以 SYNC(8 位 '0')开始,后跟 PID(Packet ID)。
USB 协议:数据包和事务
PID 定义数据包类型:
- 令牌:SETUP(控制请求)、IN(读)、OUT(写)、SOF(帧开始)。
- 数据:DATA0/1(用于完整性的切换位)。
- 握手:ACK(确认)、NAK(拒绝)、STALL(错误)。
事务:
- 控制传输:SETUP + DATA(可选)+ IN/OUT + ACK。
- 中断传输:IN/OUT + DATA + ACK——用于 HID 报告。
- 批量传输:大块数据,支持重试。
- 等时传输:无握手,用于流数据。
校验和:令牌使用 CRC5,数据使用 CRC16。公式:
// CRC5 for address/kontsa
crc5_next = crc5_reg ^ data_in;
// Polinom: x^5 + x^2 + 1 (0b001101)
描述符和设备初始化
描述符描述设备:
- 设备描述符:bLength=18, bDescriptorType=1, idVendor, idProduct。
- 配置描述符:bConfigurationValue, maxPower。
- 接口/端点:bInterfaceClass(HID=3), bEndpointAddress, bmAttributes(中断)。
- HID 描述符:bcdHID, bCountryCode, Report Descriptor。
初始化:
- 总线复位(SE0 >10 μs)。
- GET_DESCRIPTOR(设备)。
- SET_ADDRESS。
- GET_DESCRIPTOR(配置)。
- SET_CONFIGURATION。
对于 HID,额外 GET_DESCRIPTOR(报告)。键盘报告示例:修饰符字节 + 保留 + 6 个键码。
在 SpinalHDL 中的硬件实现
控制器构建为有限状态机层次结构:
- USBMain:主 FSM,管理序列。
- USBSendSE0:生成 SE0 用于复位。
- USBSendShortToken:短令牌(SOF)。
- USBSendLongToken:完整令牌(地址+端点)。
- USBSendData:NRZI 编码 + 位填充。
- USBReceiver:NRZI 解码,CRC 检查。
接口:
import spinal.core._
case class USB_IO() extends Bundle {
val dpp = in Bool()
val dpn = in Bool()
val txen = out Bool()
val txdp = out Bool()
val txdn = out Bool()
}
Apb3USB10Ctrl 通过 APB3 集成到 SoC 中。时钟:全速 48 MHz。
集成到 KarnixSoC 和驱动程序
连接:Karna 板上的 USB Type A,信号从 FPGA 路由。SpinalHDL 配置将模块添加到顶层。
RISC-V 的 C 驱动:
- usb10_bus_reset():SE0 持续 20 μs。
- usb10_in_request():IN 令牌 + DATA1 + ACK。
- usb10_setup_request():SETUP + DATA + IN。
初始化:usb10_init() 检测设备、读取描述符、设置地址。
使用 HID 设备测试
应用程序 karnix_usb10_test:
- 游戏手柄:模拟轴、按钮在中断端点 1。
- 鼠标:X/Y 增量、按钮在 4 字节报告中。
- 键盘:引导协议,8 字节报告(修饰符 + 键)。
集成到 TetRISC-V:用 USB 输入替换 PS/2。
关键点:
- 无 MACRO-IP,用 FSM 实现 USB 1.0 全速(12 Mbps)。
- SpinalHDL 生成 FPGA 综合 RTL。
- HID 引导协议简化键盘/鼠标驱动。
- NRZI + 位填充需要精确时序(48 MHz 时钟)。
- CRC5/16 验证防止数据包错误。
— Editorial Team
暂无评论。