摘要: 文章首先分析USB2.0 协议,然后介绍基于该协议的一种设备控制器IP 核设计实现,着重分析了设计中的几个问题并提出相应的解决方案,简单介绍了IP 核的系统验证。
1 引言
为了满足各种不同设备类型需求,USB2.0 规范在USB1.1 全速(12Mbps)及低速(1.5Mbps)的基础上增加了高速(480Mbps)传输速率,同时为了兼容USB1.x 规范,高速设备在全速信号环境中必须以全速正常工作,即能够在高/全速两种信号环境中正确地进行速率切换,这也加大了高速设备控制器的设计难度。本文通过分析USB2.0 协议, 利用VerilogHDL 实现了符合该规范的高速设备控制器IP 核,同时对设计中的几个问题加以讨论并提出相应的解决方案。
2 USB2.0 协议
包(Packet)是USB 传输的单位。每个数据包的开始都有同步头(SYNC)以及相应的包标示符(PID),包的结尾处都有包结束符(EOP)。在全/低速信号环境中,SYNC 长度为8 个时钟周期(对应一个字节01h),EOP 为2 个时钟周期的单端0 (singleend,SE0)。而在高速信号环境中,除了新添加了几个信息包PID,以及同步头、EOP 分别增加到4 个字节长度和1 个字节(有个例外, 就是SOF 后面的EOP 可以到4 字节)长度以外,为保证包中数据的正确性而进行的PID 互补校验以及数据字段的CRC 校验都没有变化。
USB 传输(Transfer)是通过一个或者多个包含一系列数据包的事务(transaction)完成的,事务的格式示意图如图1(a)所示。令牌数据包定义传输类型、目标设备地址、端点号码以及数据传输方向,如图1(b);数据阶段的数据包装载长度与传输类型相关的数据,如图1(c);握手应答包(在同步传输中没有)定义该次事务的结果, 视接收情况分为4 种:ACK、NAK、STALL、NYET,分别表示数据成功接受、设备忙、设备(端点)不可用、还没有足够的缓存空间接受下一个数据包。
每一个USB 设备的端点都有其特定的属性标明如何访问它,每一种传输类型也都和具体的应用要求相联系。为了支持各种设备类型,USB 规范提供中断(interrupt) 传输、块(bulk) 传输和同步(isochronous) 传输以满足不同的应用要求。控制(control)传输基本用于主机(HOST)对设备进行配置以及下达各种命令,且有专门的PID 标示。因高速环境中总线带宽大大的提升,所以包的数据字段的有效载荷都相应的加大了。不过对于任何高速设备来说,首先都是以全速设备出现,如果其复位时发出握手信号(线性调频脉冲)主机端应答成功,则断开上拉电阻而进入高速模式。
3 设备控制器核的设计与实现
3.1 设计思想
目前USB 设备端控制器的实现主要有两种方式:一是全集成芯片,如专用的微处理器(MCU)内嵌符合USB 规范的SIE(Serial Interface Engine);二是部分集成芯片,如分立的通用微处理器+SIE。前者涉及到要开发专用的MCU,开发时间长、风险大;后者集成度虽低,但不需专门设计MCU,极大地缩短了开发时间和风险性,同时应用时具有更大灵活性。考虑设计开发时间、设计工作量及应用测试等因素,本设计采用第二种方式(外置通用MCU),完成设备控制器整个数字部分IP 核的设计。
设计完成的IP 核实现了控制,中断,批量,同步四种模式传输,同时根据总线信号环境自动完成高/全速转换。为了降低MCU 的开发难度,精简内部的中断产生, 自动实现数据重传而不需要MCU 的任何干预。
3.2 模块划分及具体实现
该USB 设备控制器的逻辑功能框图如图2(a)所示。SIE(串行接口引擎)为该设计的。设备在接收数据时, 对NRZI 数据流进行解码并提交数据及其接收情况;发送数据时生成相应的数据PID 并进行NRZI 编码发送出去。为了更好地实现整个控制逻辑,把整个设备端控制器核划成6 大块:物理层PHY,收发器宏单元接口UTMI,协议层PL,存储接口仲裁MIA , 内部状态控制寄存器CSR 以及端点存储DPRAM,如图2(b)所示。
3.2.1 PHY
由USB2.0 协议规范可知, 高速设备控制器必须能在高/全速信号环境之间正确切换, 因此PHY必须能够根据工作模式确定其信号环境;其次必须进行高速480M/全速12 MHz 的NRZI 数据流解码、编码工作及其相应的串并、并串转换。设计中PHY使用了Philips 的ISP1501, 因此该部分数模混合设计不做介绍,ISP1501 的详情请参考文献。
3.2.2 UTMI
UTMI 控制suspend/resume 的产生以及生成全/高速之间切换的模式信号, 由于ISP1501 的数据线宽度为16 bits,处理一个字(1 word=2 bytes),故还要起到PHY 与协议层(PL)之间数据交换的缓冲作用。内部框架如图3 所示。速度协商控制(SNC)为该模块的。
3.2.3 PL
协议层模块是整个SIE 的,控制着整个数据传输。总流程图如图4(a)所示。该过程主要有两个步骤:,检查PID 的有效性;第二,如果PID 有效,则根据PID 确定数据及传输类型。因此该模块实际上是4 个进程处理:IN、OUT、SETUP 事务以及特殊事务。在具体的模块设计实现中, 由于解包(Packet disassemble)、打包(Packet assemble)过程在4 个进程中都必不可少,所以统一编写而在PL 顶层调用。内部状态机的翻转以及复位都是以事务为周期,所以实现起来比较容易。在接收数据时,解析出各种令牌以及把数据包的内容写入RAM 中, 完毕以后填写相应的接收信息。发送数据时,从RAM 中读取数据并形成正确的数据PID。如果是0 长度的数据,则只有2 个字节的全0 CRC16 校验码。在一个事务的握手(handshake)阶段,则根据接收情况提交握手信号。图4(b)中给出了一个PID 为IN 令牌包的流程。
在USB 规范中,PID 为SETUP 标志的控制传输也称作消息(Message)传输,其实际上可以理解成为一种特殊的OUT 传输, 主要用来对USB 设备的配置以及向设备发送和数据传输相关的命令字。有着固定的格式:以PID[3:0]=1101 的SETUP 令牌包开始的建立阶段+数据阶段+状态阶段。数据阶段可以没有, 如HOST 给设备下放地址时的控制传输,但是状态阶段是必需的,以确保传输的正确性。
3.2.4 MIA
存储接口仲裁。存储管理设计的好坏直接影响控制器整体性能,需要谨慎处理。对存储单元进行读、写操作者是HOST 与MCU 两者。设计中要注意的是MCU 的读写信号与内部时钟的同步问题,这在后面部分还会进一步讨论。
3.2.5 DPRAM 与CSR
DPRAM 暂存传输中事务的数据, 同时把该次事务的接收状态信息写入对应的CSR(状态控制寄存器)。本设计把DPRAM 配置成端点FIFO,共16个, 总容量为8K。MCU 的工作是基于中断的,当SIE 给出中断时,首先会读出相应端点的CSR 从而知道中断产生的原因以及上次事务的状态:成功或失败。若失败则进入相应的中断例行程序。
3.3 设计中若干问题及其解决
3.3.1 端点的存储管理单元(MMU)
在USB1.x 规范中,由于数据有效载荷较小,纯粹意义上的FIFO, 由于不需寻址即可实现存取操作、逻辑控制简单等原因而作为端点的实现方法。但在USB2.0 规范中,由于带宽、吞吐量剧增,且FIFO 不便动态配置等原因, 故端点存储选择RAM来实现。无论在FPGA 设计还是ASIC 设计中,都可使用两种类型的RAM:单口(single port)RAM 与双口(dual port)RAM。对于双口RAM,其特别之处在于可同时读写, 即HOST 与MCU 可以同时对同一个端点进行读写操作。比如在由HOST 到设备方向的高速同步传输中,如果使用SPRAM 的话,同步端点的深度至少应配置为1024 (除非使用双缓冲)且必须等到端点"Full"然后才产生中断让MCU 读取端点内的数据。因此为了实现同步传输,SPRAM 配置实现的话,为了节省存储单元而一般需要双缓冲机制, 但增加了端点读写控制的复杂性; 而双口RAM 由于能够同时对不同地址的存储单元进行读写(如果同时读写相同地址的话,则看RAM 具体的时序了),因此双口RAM 只需要很少的缓冲存储容量就可以满足了, 为了使MCU 能够及时地读取数据,同时,又不致对MCU 的中断过于频繁,只要在写入到端点深度的一半处产生中断信号即可。因此设计中采用DPRAM,既可节省存储资源(减小了芯片面积),又可提高同步传输的"实时同步"性。
3.3.2 异步时钟域之间的数据交互
从前面的功能划分可以看到,整个USB 设备控制器分成3 个不同的时钟域。时域1 和时域2 之间实际上是同步的, 因为PHY 为时域2 提供了与数据同步的30MHz 的时钟,所以这里的异步时钟域主要是指时域2 与时域3 之间, 这在SIE 与MCU 之间的读写信号很容易看到。由于MCU 发出的读写有效脉宽比时域2 内的时钟周期要小很多,比如在本设计中读写脉宽为15ns,而内部的时钟为30MHz(T=33.3ns)。当MCU 要读取数据时,可以采用"超前送数"策略,即根据MCU 的读写命令字在读有效信号来之前把数据放入三态数据输出端口的输入端, 用读有效电平作为三态的开关即可。
MCU 读完本次数据以后,SIE 内部的异步读写控制逻辑立即对内部的MMU 产生一个读请求(如果还没有读空),准备好下一个数据。整个MMU 收到的读写信号是由异步读写控制逻辑内部产生的,对MCU 接口透明, 该方法在FPGA 验证中实现通过。
上述异步读写控制逻辑的设计是基于8051 类MCU的,值得注意的是,若MCU 是wishbone SoC 总线规范兼容的接口, 则不需上述复杂的读写控制逻辑,在这两个时钟域之间交换数据时,为了解决亚稳态问题,只须增加由本地时钟触发的寄存器实现作为过渡即可。
3.3.3 传输中一些错误检测及其处理
为了精简MCU 的编程,设计中提出"在保证传输正确的基础上尽量减少中断" 的设计原则。
USB2.0 规范中列出了种类繁多的错误产生及其相应的检测、恢复方法。笔者认为,USB 设备控制器设计者没有必要对传输过程中发生的任何错误都向外部MCU 提出中断,对规范中部分类型的错误,设备控制器内部应有处理及恢复机制。例如超时的发生有几种情形:正确接受完毕来自HOST 的非同步数据包后,必须及时返回一个成功接收握手;HOST发出IN 令牌包接收到数据以后, 同样必须及时地返回握手包,否则超时。对后者,没有必要马上向MCU 产生中断, 下一个IN 令牌到来时自动重传上次数据, 且多尝试3 次。若问题依旧, 再中断MCU,说明设备上游的线路可能出了故障。另一个就是Toggle 同步机制, 出错也完全没有必要通知MCU,可在协议实现的内部来处理。值得一提的是,控制传输比较特殊:在控制传输的建立阶段,SETUP令牌包后面的数据包的PID 一定是DATA0,然后在这个基础上进行触发切换。在状态阶段的数据包PID 肯定是DATA1。否则,在FPGA 验证中,即使触发位出错,主机还是会返回ACK,造成数据已正常接收的假象,而实际上主机已摒弃了数据。
4 系统仿真及FPGA验证
在设计的编码过程中,先分别对各模块进行了功能仿真,子模块仿真正确后对整个模块进行了整体功能仿真,然后综合代码、设置引脚、自动布局布线后到FPGA 内。本设计FPGA 器件采用Altera 的ACEX1K EP1K100QC208-3。USB 电缆的一端接在测试板的transceiver 上, 另一端接至PC机的USB 接口上,如果SIE 逻辑功能正确,则Windows会识别出一个新的USB 设备, 完成了PnP 过程。为了功能验证和应用测试,额外编写了一个模块,用于USB 设备枚举时,模拟MCU 的部分功能。
Windows 在对USB 设备进行枚举时,按如下顺序进行:
(1) 主机发出一个复位信号;
(2) 初次得到设备描述符的控制传输;
(3) 给设备分配地址。数据包DATA0 的第三个Byte 就是分配的地址;
(4) 以新的地址获取设备描述符;
(5) 初次获取设备配置描述符,以确定配置描述符+接口描述符+端点描述符的长度,这次主机只获取9 个字节的配置描述符。
(6) 获取字符串描述符(可能没有),根据设备描述符中是否有STRING 索引而定;
(7) 获取完整的设备配置描述符,性获取相应长度的上述三个描述符。
若以上步骤都正确, 则主机发现新的USB 设备,要为该设备安装驱动程序。然后利用Windriver可以在Windows 环境看到这个USB 设备以及相关端点信息等资源。在该驱动程序的控制台上,可以对USB 设备控制器的管道进行读写操作,并且操作结果,以验证核的功能是否正确。
5 结束语
系统逻辑功能仿真、综合后门级网表(gate levelnetlist) 功能仿真以及的FPGA 验证都表明:本设计中,双口RAM 配置、异步时钟域之间读写时的"超前送数策略"以及"尽可能减少错误中断产生"原则,简化了编码实现以及外部MCU 编程,在实现高速USB 设备控制器的设计过程中是有效的、切实可行的。该方案实现的USB2.0 设备控制器IP 核便于修改、易于实现,既可以进一步完成ASIC 设计,也可作为一个功能模块嵌入到SOC 中。
[1]. bulk datasheet https://www.dzsc.com/datasheet/bulk_2523104.html.
[2]. ISP1501 datasheet https://www.dzsc.com/datasheet/ISP1501+_1083529.html.
免责声明: 凡注明来源本网的所有作品,均为本网合法拥有版权或有权使用的作品,欢迎转载,注明出处。非本网作品均来自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。