小鲜肉自己给自己颁奖:USB 2.0主机端控制器协议层的设计及实现
关键词:USB2.0; 协议层;状态机
引言
USB(Universal Serial Bus)是当今流行的一种PC外围设备接口标准[1]。它具有即插即用、可热插拔等的优点,在实际应用中连接简单、使用方便。本文简要介绍了USB 2.0协议层的通信原理,并根据USB 2.0协议规范,利用Verilog硬件描述语言完成了主机端控制器协议层的设计,通过Cadence公司的NCSim进行软件仿真之后,在XILINX公司的Virtex xcv300efg456-6芯片上进行了验证。
1 协议层通信原理
USB接口是以令牌包(token-based) 为主的总线协议,PC主机掌握着总线的一切主控权[1],除令牌包外,还有数据封包、握手封包、特殊封包等。令牌包还可细分为OUT、IN、SETUP、SOF等4种封包格式,其他几个封包也同样可以细分为多种封包格式。在USB的传输中,每一个传输包含一笔或多笔事务,每一笔事务包含一到三个封包[2]。
USB有4种传输类型:控制传输、批量传输、中断传输和实时传输,每种传输类型用以处理不同的需求。具体来讲,批量传输类型用于对时间要求不严格的数据传输,可以发送大量数据而不会阻塞总线,并能通过错误检测和重试的方式保证主机和功能部件之间数据的无错发送。控制传输模块用以发送与设备的能力和配置有关的请求和数据,也可传输任何其他用途的信息块。中断传输类型适用于在一个规定的时间里传输一个中等数量的数据,通常应用在键盘、鼠标、其他指针设备和集线器的状态报告中,中断传输令设备引起硬件中断,将使计算机产生一个快速响应。实时传输类型是对数据以一个恒定的速率或在规定时间内完成的传输,仅包含令牌和数据两个时相,而不包含握手时相,因此不具备错误校正的能力,所接收的信息偶尔会包含少量的错误。对于所有的USB设备,都需要支持控制传输,而中断传输是除控制传输之外低速设备惟一的传输数据的方式,只有全速与高速设备才需支持批量传输和实时传输。
2 协议层主要模块的划分及实现
协议层(Protocol Layer)模块是USB 2.0主机控制器的核心,它负责处理所有USB的数据的读写以及通信的控制。根据协议层所需完成的功能,可将其划分为四个功能模块:封包PA(packet assembly)模块、拆包PD(packet disassembly)模块、协议引擎PE(protocol engine)模块和直接存储器存取(DMA)及存储器接口模块,其中前三个模块是协议层的主要模块。协议层PL的划分结构图如图1所示。
图1 协议层结构图
2.1 PA与PD模块的设计与仿真
封包(PA)模块的功能是将输出到总线的数据封包成USB协议层所规定的格式并送入UTMI(USB Transceiver Macrocell Interface)模块中的FIFO,包中主要包括同步包头、PID、数据、设备地址、端口等。而拆包PD模块所实现的是将接收到的数据包进行拆包分析,利用PID值判断属于哪种类型包并将判断结果发送给协议引擎,若是数据包则对包内的数据进行CRC (Cyclic Redundancy Check)校验,并将数据保存起来。它是封包模块的逆过程。本文对封包、拆包模块的设计均采用状态机的设计思想,图2和图3给出了两个模块的状态转换图。
图2 封包模块状态转换图
图3 拆包模块状态转换图
根据图2、图3的状态转换图,采用独热码的状态机编码方式,用verilog语言描述后,经NCSim进行软件仿真,由于拆包模块是对封包模块的逆过程,因而本文只给出了PA模块的测试波形,如图4所示。
图4 封包、拆包模块仿真波形
由图4可以看出,开始时由PE模块发出的信号data_pid_sel有一个跳变。data_pid_sel是一个两位的向量,其作用是通知PA模块封包的PID类型。当其为0时,表示封包的PID为DATA0,为1时表示DATA1,为2时表示DATA2,为3时表示MDATA。图中data_pid_sel为0,因而PA封包打包一个DATA0的数据包,tx_data为输出数据,当tx_first有效时,其首先输出C3,即DATA0的PID码0011,然后输出数据段以及16位的CRC校验码。
2.2 PE模块设计与仿真
协议引擎PE(protocol engine)模块是协议层PL中的核心部分,它要提供与UTMI、PA、PD、DMA、寄存器等的接口,其功能是处理所有USB协议提供的标准握手信号以及对通信的控制。握手信号主要是SOF令牌信号以及数据传输响应信号等,保证整个协议层的协调执行。
USB中数据的传输是通过端点(Endpoint)操作来进行的,控制器通过写端点的寄存器来配置端点,在全速状态下控制器最多可拥有16个输入端点与16个输出端点共32个端点[3],每个端点有相应的4个寄存器:Epn_CSR、Epn_INT、Epn_BUF0和Epn_BUF1。Epn_CSR是控制状态寄存器,Epn_INT是中断寄存器, Epn_Buffer0和Epn_Buffer1分别作为专用的输入/输出缓冲器来提高USB的数据吞吐能力。双Buffer能够减少微控制器和驱动软件之间的延迟,端点的CSR(Control Status Register)寄存器可以指定端点的工作模式并且向控制器报告指定端点的状态。图5为PE模块状态转换图。
图5 PE模块状态转换图
本文对于PE模块的主体功能的实现仍然使用状态机的设计方法,分别对数据的读/写控制、DMA传输控制等进行状态划分。PE模块的仿真测试波形如图6所示。图中给出的部分仿真波形为PE模块中写事务的时序波形,其中send_token、token_pid_sel、data_pid_sel三个信号线是与PA模块的接口,它通知PA模块把封包发送给UTMI接口,从而实现主机对设备的写操作。token_pid_sel、data_pid_sel选择封包功能如表1所示。
表1 token_pid_sel、data_pid_sel选择封包对应表
token_pid_sel
对应封包类型
data_pid_sel
对应封包类型
2’b00
ACK
2’b00
DATA0
2’b01
NACK
2’b01
DATA1
2’b10
STALL
2’b10
DATA2
2’b11
NYET
2’b11
MDATA
由图6可以看出,开始时rst为0,对PE模块内的寄存器进行置0,然后使pid_STALL置为1,send_token变为1,token_pid_sel变为2,即PE模块通知PA模块进行一个STALL封包。接着分别置pid_DATA0和pid_DATA1为1,由图中可以看到,data_pid_sel分别变为0和1,即PE模块通知PA模块分别进行一个DATA0封包和一个DATA1封包。
3 结束语
本文描述了USB 2.0协议层的设计思路,用Verilog语言对其进行了RTL级描述,并在Cadence公司的NCSim上通过了软仿验证。为了进一步验证设计的正确性,本文选择了XILINX公司的Virtex xcv300efg456-6芯片,并把上述由RTL级描述的USB 2.0协议层综合到此FPGA上加以验证。综合结果表明,协议层模块占用了514个Slice(16%),521个Slice触发器(8%),885个输入LUT表(14%),以及284个绑定的输入输出块(89%)。整个FPGA的速度可达到59.7MHz,完全满足USB2.0协议的规定。