现场可编程门阵列(FPGA)的高度灵活性和强大的数据处理能力,使其在越来越多的领域得到应用。USB 3.0 也是目前主流的数据传输协议之一,具有速度快、功耗低等优点。将 USB 3.0 接口应用到 FPGA 上,能够有效地解决 FPGA 与上位机之间的数据传输问题,大大提高生产效率。文章利用 USB 3.0 的控制器芯片 CYUSB3014 实现了 FPGA 与上位机之间的高达 390 MB/s 的数据传输系统。
 
0 引言
现场可编程门阵列(FPGA)具有极高的灵活性以及强大的数据处理能力,在科学研究、大型实验仪器和商用医疗设备等诸多领域中早已被成熟使用。但是 FPGA 本身并没有提供任何与上位机通信的接口,这使得 FPGA 与上位机之间传输数据变得很不方便。开发者每次都必须根据具体外设重新开发 FPGA 和上位机的数据传输系统,从而降低了开发效率。
 
通用串行总线(USB)3.0 标准早在 2008 年就已经提出,现在已取代 USB2.0 成为 USB 主要使用版本。USB3.0 比 USB2.0 有更高的传输速度和更低的功耗。USB3.0 的协议速度高达 5.0 Gb/s(625 MB/s),是 USB2.0 的 10 倍之多。CYUSB3014 是赛普拉斯(CYPRESS)公司设计的一款 USB3.0 外设控制芯片,它的主要功能是在 USB 主机与外设之间传输高宽带数据。该芯片提供一个第二代通用可编程接口(GPIF II),开发者可以对 GPIF II 和 FPGA 编程,来实现从 FPGA 到 USB 控制器,再到上位机的数据传输通道。
 
本文利用 USB3.0 外设控制器 CYUSB3014,实现了基于 FPGA 与上位机之间的数据传输接口设计[13]。经测试,本设计可以实现 390 MB/s 的 FPGA 到上位机的数据传输通道,以及 355 MB/s 的上位机到 FPGA 的数据传输通道,几乎达到了该芯片支持的最高速度(400 MB/s)。
 
1 系统结构
 
 
图 1 为整个系统的结构。上位机的软件应用程序(例如 MATLAB)通过调用驱动程序中的应用程序编程接口(API),向 CYUSB3014 控制器发送数据或从它接收数据;USB 控制器芯片内部通过直接内存存取(DMA)互联结构建立 USB 端点到 GPIF II 的数据传输通道;FPGA 内部接口逻辑模块负责其他逻辑模块与 GPIF 之间的数据传输。
 
图 1 系统整体结构本设计以 FPGA 接口逻辑为主设备,GPIF 为从设备,接口逻辑负责控制整个系统的工作状态。为了通用性起见,本文设计了上位机对 FPGA 进行 FIFO 读写和寄存器读写共 4 种功能。FIFO 读写可以完成高宽带高速数据的双向传输;寄存器读写则可以完成控制和监测的功能。这样的设计能够满足大部分 FPGA 设计对上位机接口的需求。
 
2 控制器芯片工作原理
赛普拉斯公司设计生产的 USB3.0 外设控制芯片 CYUSB3014 具有高度集成的灵活特性,它具有一个可进行完全配置的并行通用可编程接口 GPIF II,可与任何处理器、ASIC 或 FPGA 连接。芯片集成了 USB 3.0 和 USB 2.0 物理层(PHY)以及 32 位 ARM926EJS 微处理器,具有强大的数据处理能力,并可用于构建定制应用。
 
图 2 表示了控制器芯片的数据输入输出。其中 DMA 描述符(DMA Descriptor)保存了 DMA 缓冲区的地址和大小,以及指向下一个 DMA 描述符的指针。套接字(Socket)是外设硬件模块与 RAM 之间的连接点,每个外设硬件模块(如 USB、GPIF、UART 和 SPI)具有各自固定的套接字数量,简单来说可以把套接字看成外设的接口。DMA 缓冲区(DMA Buffer)是 RAM 的一部分,用来缓存外设间需要传输的数据,这部分 RAM 的地址正是 DMA 描述符中保存的地址。
 
  
 
当外设之间进行数据传输时,例如将 GPIF 的数据传输到 USB 端点,控制器会自动加载相应的 DMA 描述符,然后从 GPIF 的套接字接收数据,保存到 RAM 中 DMA 描述符所指定的地址。当前 DMA 描述符处理完后,系统会自动加载下一个 DMA 描述符。DMA 缓冲区的切换需要消耗几个微秒的时间,在切换 DMA 缓冲区时,当前的 DMA 通道不能进行数据传输[4]。当某个 DMA 缓冲区被写满,或者 GPIF 主动提交数据包时,系统开始把该缓冲区的数据发送到 USB 端点。从 USB 端点到 GPIF 的数据传输过程与之类似,只不过数据传输的方向刚好相反。
 
3 系统设计
3.1 控制器芯片固件设计
USB 控制器芯片的固件设计包括 GPIF II 状态机设计和运行于芯片内部 ARM 微处理器上的可执行程序设计。其中,GPIF II 状态机的设计是关键,它描述了 USB 芯片如何响应主设备 FPGA 接口逻辑模块发出的请求。
 
图 3 给出了 USB 控制芯片与 FPGA 的接口连接。其中,CLK 是由 FPGA 提供的频率最高为 100 MHz 的时钟信号。DATA 信号是双向数据线,完成 GPIF 与 FPGA 之间的双向数据传输。ADDR 为地址线,用于选择使用哪个 GPIF 进程传输数据。GPIF 共有 4 个独立进程,每个进程与相应的 DMA 通道绑定。FPGA 通过改变地址线 ADDR,从而选择使用哪个 DMA 通道进行数据传输。控制信号均由 FPGA 发出,控制信号包括 SLOE、SLCS、SLWR、SLRD、PKTEND,这些信号均为低电平有效。SLCS 为片选信号,系统工作时,SLCS 必须始终有效(即始终为 0)。SLRD 为读请求信号,该信号有效时,GPIF 会把缓存在 RAM 中的数据传输给 FPGA。SLOE 为输出使能信号,它的唯一作用是驱动数据总线 DATA 翻转。因为 FPGA 发出读请求后,USB 芯片并不能立刻将有效数据传递到 GPIF 端点,从 SLRD 有效到 DATA 有效有两个时钟周期的延迟[5],因此需要额外的数据总线驱动信号 SLOE。SLWR 是写请求信号,该信号有效时,FPGA 会发送数据给 GPIF,GPIF 随之将这些数据缓存在 RAM 中。PKTEND 为传输结束信号,该信号用来标志此次数据传输结束。
 
 
另外,还有 4 个 DMA 标志信号 FLAGX。这些信号由 USB 芯片发出,FPGA 接收。这些信号并不是由 GPIF 状态机控制的,FLAG 信号用来标志指定 DMA 通道对应的缓冲区的状态。
 
3.2FPGA 接口设计
FPGA 接口既要完成与 USB 控制器 GPIF II 对接,同时也要提供对 FPGA 内部逻辑模块的数据传输接口。FPGA 接口逻辑是本系统的核心,它作为主设备,控制着从设备 GPIF 的工作状态。FPGA 接口逻辑模块内部有一些标志工作状态的寄存器,用户可以通过上位机软件来配置这些寄存器,从而指定整个系统的工作模式。因此,在执行某种操作之前,需要通过上位机软件先对 FPGA 接口逻辑模块进行配置。
 
 
 
FPGA 接口逻辑除了具有 3.1 节中与 GPIF II 相连接的接口外,还提供了其他接口与 FPGA 内部其他逻辑模块相连接。图 4 给出了这些接口信号。CLK 是接口的工作时钟(100 MHz),同时这个时钟也是 GPIF II 的工作时钟。RST 是全局复位信号。剩下的信号则用来完成 FIFO 读写和寄存器读写的功能。
 
在进行 FIFO 读操作时,使用的接口信号是 RD_ACK、RD_VALID 和 RD_DATA。当 RD_VALID 有效时,标志着外部 FIFO 数据有效,RD_ACK 作为应答信号告知外部逻辑已经完成对该有效数据的读取。使用时,先通过上位机软件对接口逻辑模块进行配置,配置的信息确定了接口模块将工作在读 FIFO 模式,同时还确定了此次读 FIFO 的数据个数。当读取 FIFO 的数据个数达到上位机所请求的个数时,接口逻辑模块停止读取外部 FIFO,同时停止向 GPIF 发送数据,并且发出 PKTEND 信号,标志着此次传输结束。
 
在进行 FIFO 写操作时,使用的接口信号是 WR_ACK、WR_READY、WR_DATA。当 WR_READY 有效时,标志着接口模块可以向外部 FIFO 写入数据,WR_ACK 作为应答信号告知外部逻辑已经完成了数据的写入。与读 FIFO 类似,使用时先通过上位机软件对接口模块进行配置。配置信息确定了接口模块工作在 FIFO 写模式,同时确定了将要写入的数据个数。
 
 
图 5FPGA 接口逻辑状态机图 5 给出了 FPGA 接口逻辑模块的状态机向 GPIF 收发数据时的工作流程。系统最初处在空闲状态(IDLE),然后根据配置信息确定的工作模式,以及 DMA 通道的 FLAG 标志信号,进入相应的状态机流程中。
 
此外,接口逻辑模块还实现了寄存器读写的功能,寄存器读写使用的 DMA 通道与 FIFO 读写的通道相同,只是传输的数据个数始终为 1。
 
3.3 上位机软件设计
赛普拉斯官方提供了 USB 控制器芯片的驱动程序,并且提供了相应的应用程序接口(API)。为了使用方便,本设计在官方提供的 API 基础上,将主要功能(FIFO 读写和寄存器读写)用 C++封装成动态链接库(DLL)。这样用户可以直接在自己的 C/C++工程中调用已经封装好的库函数。在封装库函数时,已经将配置 FPGA 接口模块这步工作封装在了相应的功能函数中,这样用户就不必先单独配置 FPGA 逻辑模块。
 
考虑到现在大部分研究阶段的数据处理工作都是使用 MATLAB 进行,本设计进一步将 DLL 函数封装成 MATLAB 函数,以便 MATLAB 能够直接使用 USB 的相关功能。
 
4 测试结果
4.1 测试环境
 
 
测试环境如表 1 所示。
 
4.2 寄存器读写测试
寄存器读写只涉及到正确性问题,测试工程在 FPGA 内部例化了 16 个 32 bit 的寄存器。测试时对某个寄存器随机写入一个数值,然后再把该寄存器的值读回来,比较读取的值是否等于写入的数值。经循环对这 16 个寄存器进行读写测试,发现寄存器读写功能能够稳定地正常工作。
 
4.3FIFO 回环测试
FIFO 回环测试是为了验证 FIFO 读写的正确性。测试时,MATLAB 先将 1 024 个数据写入到 FPGA 的 FIFO 中,然后再将这些数据从该 FIFO 中读出,验证读出的数据是否是原来写入的数据。经过测试,FIFO 读写也能正常稳定地工作。
 
4.4 读写 FIFO 速度测试
测试读 FIFO 时,FPGA 内部一直将某个加 1 的计数器的值写入 FIFO,MATLAB 则从该 FIFO 中读取数据。测试写 FIFO 时,MATLAB 一直将数据写入 FPGA 的 FIFO 中,FPGA 内部逻辑负责读取该 FIFO。MATLAB 每次读取或者写入 5 000 000 个数据(每个数据 32 bit),循环操作 50 次,记录这 50 次操作所消耗的总时间,记为 t(单位为 s)。则,读写 FIFO 的速度为:
 
50×5 000 000×328×1 000 000×t(MB/s)
 
经测试,本设计读 FIFO 的速度能够达到 390 MB/s 左右,而写 FIFO 的速度能够达到 355 MB/s 左右。
 
5 结论
本设计利用 USB 3.0 控制器芯片 CYUSB3014 实现了 FPGA 与上位机之间的高宽带数据传输系统。主要实现的功能包括上位机对 FPGA 的寄存器读写和 FIFO 读写。经测试,这些功能都能稳定地正常工作。上位机读 FIFO 的速度能够达到 390 MB/s,写 FIFO 的速度能够达到 355 MB/s,接近于 CYUSB3014 芯片支持的理论最高速度 400 MB/s。之所以读 FIFO 的速度会比写 FIFO 的速度高出不少,主要原因是因为在设计固件程序时,读 FIFO 使用了 DMA 双通道,而写 FIFO 则只使用了 DMA 单通道。