AXI Memory-Mapped SRIO收发控制器

  Xilinx的SRIO IP可以用混合的接口或者分Initiator和Target的AXI4-Stream接口,数据是以Hello Format的包格式传输(SRIO IP的文档里有说明)。为了实现SRIO接口直接访问DDR数据空间,需要将Hello Format包格式转换为AXI4 master接口。
  在我们的系统中,DSP和FPGA通过x4的SRIO链路互连,单条链路最高支持3.125Gbps。为了实现高效的数据传输,一般采用写的方式,比如NWRTIE包或者SWRITE包。如果用读的方式,就需要先发读请求包,然后过一段时间才能收到响应的数据,虽然可以连续发起多个读请求,但是面对大批量的数据传输,读的过程相对来说就比较繁琐,所以在我们的系统里主要用写的方式来实现数据传输。从DSP到FPGA的数据,由DSP发写数据包;从FPGA到DSP的数据,由FPGA发写数据包。
AXI Memory-Mapped SRIO收发控制器
  我们的DSP的SRIO外设支持DMA操作,可以将批量的数据以NWRITE包的形式发送。因此FPGA端的SRIO接收控制器主要负责解析NWRITE包;FPGA发送数据则可以采用SWRTIE包,它的额外开销最小,因此SRIO发送控制器主要发送SWRITE包,由MicroBlaze软和处理器通过AXI4-Lite接口发起启动指令。除了主要的数据传输功能,门铃中断信号的接收与发送也需要实现。

SRIO接收控制器

设计思路

  SRIO接收控制器主要负责接收门铃事务包和NWRITE事务包。
  NWRITE事务包从treq端口接收后,根据包头的目的地址和包大小,计算出所需要的AXI突发(burst)次数和每次的突发长度。AXI协议中要求突发传输不能超过4kB地址边界,所以对一包NWRITE事务包的分解需要考虑多种情况。另外需要注意的是SRIO的数据是大端模式传输,如果要配合系统中的其他小端模式的设备,需要对字节位置进行调整。
  门铃事务包的接收就相对比较简单了。一方面是对接收到的门铃事务包进行响应,注意:响应包的prio字段的值等于接收到的门铃事务的prio字段的值加一。输出的中断脉冲信号是给到MicroBlaze的中断控制器,中断控制器如果设置为边沿触发,那么要求这个中断脉冲宽度大于2个中断控制器的时钟周期。

AXI Memory-Mapped SRIO收发控制器
  为了让treq的端口不堵塞,门铃接收引擎对于任何门铃事务包,都无条件接收,并且发送响应,即使没有使能门铃中断。通过AXI4-Lite接口使能门铃中断后,接收到的门铃信息才会存到CSR寄存器中,并且产生门铃中断脉冲。通过AXI4-Lite接口读取中断信息之后,才能接收新的门铃,所以这里要求门铃中断产生之后,MicroBlaze要尽快从CSR寄存器读取门铃信息,不然就有可能导致门铃接收堵塞。

寄存器说明

寄存器偏移地址 寄存器名称
0x00 Control and Status Register(CSR)

CSR寄存器的位域说明:

字段 位域 复位值 读写权限 描述
Doorbell Enable 0 0 W/R 门铃中断使能,高电平有效
Doorbell Info [31:16] 0x0000 R 上一个接收的门铃事务包携带的门铃信息

SRIO收发控制器

设计思路

  这个模块最开始的设计想法是做一个“收发控制器”,但目前只做了“发送”的功能。一开始想做收发控制器是因为,这样子不管数据怎么走,FPGA始终是主动方,这样可以减少DSP的负担。但目前我们的DSP有DMA发送NWRITE包的功能,所以这个从DSP读数据的功能就没做了(下图中的NREAD模块是虚线框)。要做的话只需要加一个NREAD发送引擎就好了。
AXI Memory-Mapped SRIO收发控制器
  iresp和ireq端口的输出信号需要由多个引擎驱动,在设计中是依靠“或”的方式实现的。
  在模块顶层中,AXI4-Lite接口完成对寄存器的读写。寄存器中的信息作为驱动信号(图中未画出)施加给不同的引擎。
  DoorBell发送引擎维护了一个16bit的门铃空闲寄存器,一个门铃发送后如果没收到对应的响应,那么这个门铃对应的事务ID就不能再次发送。如果连续发送了16个门铃,但是没有收到任何响应,就无法再发送门铃了。一个门铃只有被成功发送,才能会将寄存器中的门铃启动位清零,之后才能发送新的门铃。
  SWRITE发送引擎接收MicroBlaze给出的启动命令,接着就通过AXI4接口从特定地址读数据,从ireq端口用SWRITE包格式进行发送。发送完成后还会额外发送一个门铃事务包通知对方发送完成,也会向MicroBlaze发送sw_irq中断信号告知MicroBlaze发送已完成。只有在发送完成之后才能启动新的传输,且传输不能中断。由于SRIO是大端模式,因此发送的数据也需要对字节位置进行调整。
  NREAD发送引擎没有做,等之后有需要了再做。

寄存器说明

寄存器偏移地址 寄存器名称
0x00 START
0x04 Source Address (SRCADDR)
0x08 Destination Address (DSTADDR)
0x0C DoorBell Information and Transfer Size (INFOSIZE)

START寄存器的位域说明:

字段 位域 复位值 读写权限 描述
DoorBell Start 0 0 W/R 根据当前INFOSIZE寄存器中的INFO字段,发送门铃事务包;置一发送门铃,发送完成后自动清零;在该bit为1的情况下写1无效
Swrite Start 1 0 W/R 根据当前SRCADDR、DSTADDR、INFOSIZE寄存器连续发送一定数量的SWRITE事务包;置一启动SWRTIE,所有数据发送完成后自动清零;在该bit为1的情况下写1无效
Nread Start 2 0 W/R (待实现功能)根据当前SRCADDR、DSTADDR、INFOSIZE寄存器连续发送一定数量的NREAD事务包;置一启动NREAD,所有数据接收完成后自动清零;在该bit为1的情况下写1无效

SRCADDR寄存器的位域说明:

字段 位域 复位值 读写权限 描述
Source Address [31:0] 0x00000000 W/R 待传输数据的源地址。对于SWRITE来说,是FPGA端的地址;(待实现功能)对于NREAD来说,是DSP端的地址

DSTADDR寄存器的位域说明:

字段 位域 复位值 读写权限 描述
Destination Address [31:0] 0x00000000 W/R 待传输数据的目的地址。对于SWRITE来说,是DSP端的地址;(待实现功能)对于NREAD来说,是FPGA端的地址

INFOSIZE寄存器的位域说明:

字段 位域 复位值 读写权限 描述
DoorBell Information [31:16] 0x0000 W/R 需要发送的门铃信息
Transfer Size [15:0] 0x0000 W/R Swrite或Nread传输的数据大小。以双字为单位,实际传输大小为该该字段值加一

系统测试

  下图为FPGA端的Block Design,添加了SRIO接收控制器和SRIO发送控制器。SRIO IP设置为x4链路,每条链路3.125Gbps,对应的log_clk为156.25MHz,这也是两个控制器的工作频率。MIG外接1GB的DDR3,MIG输出的时钟频率为200MHz,同时作为MicroBlaze的系统时钟。目的设备ID和本地设备ID通过IP的参数设置。MB中断控制器通过concat连接SRIO接收控制器发出的门铃中断信号和SRIO发送控制器发出的SWRITE发送完成中断信号,在软件上采用fast_interrupt模式,当中断产生时,MB可以直接跳转到相应的中断服务函数处。
AXI Memory-Mapped SRIO收发控制器

从DSP到FPGA,NWRITE波形

  下面两张图是NWRITE包接收时的数据波形,第一张图是从起始处连续采样2048点的整体波形,第二张图是其中放大后的一部分波形。蓝色的波形是AXI接口的W通道的数据,数据正常写入DDR。
AXI Memory-Mapped SRIO收发控制器
AXI Memory-Mapped SRIO收发控制器

从FPGA到DSP,SWRITE波形

  下面两张图是SWRITE包发送时的数据波形,第一张图是从起始处连续采样2048点的整体波形,第二张图是其中放大后的一部分波形。从第一包SWRITE发出包头到真正开始发送数据,经过了一段时间的等待,因为从DDR读数据需要等待;后续能够读到连续的数据是因为在AR通道已经把需要读的数据的地址都发过去了。

AXI Memory-Mapped SRIO收发控制器
AXI Memory-Mapped SRIO收发控制器

读写速率测试

  为了对SRIO传输的速率进行测试,在DSP端利用TSC定时,分别对DSP通过SRIO读写数据的速率和门铃功能进行测试。
AXI Memory-Mapped SRIO收发控制器
  首先是DSP利用SRIO的DMA,从DSP向FPGA外接的DDR写数据。数据量是640×512×8bit。DSP在发送完成后会进入发送完成中断,同时会向FPGA发送一个门铃事务包,所以MicroBlaze也会进入中断。MicroBlaze读取门铃Info,判断出是收到了数据。发送数据所用时间为327920ns,可以计算数据传输速率:
640 × 512 × 8 b i t 327920 n s = 7.99 G b p s \frac{640\times512\times8bit}{327920ns}=7.99Gbps 327920ns640×512×8bit​=7.99Gbps
η = 7.99 G b p s 3.125 G b p s × 4 × 100 % = 63.95 % \eta=\frac{7.99Gbps}{3.125Gbps\times4}\times100\%=63.95\% η=3.125Gbps×47.99Gbps​×100%=63.95%

  接着是测试FPGA向DSP发送SWRITE的速率,从DSP向FPGA发送门铃信息为“0xAAAA”的门铃,MicroBlaze收到之后就发起一个较少数据量的SWRITE包,利用这次传输计算额外开销;DSP接着发送门铃信息为“0xBBBB”的门铃,MicroBlaze收到之后就发起640×512×8bit的数据传输。传输完成后,DSP和MicroBlaze都会进入中断,DSP收到门铃中断,MicroBlaze收到sw_irq的中断脉冲。可以看到FPGA向DSP发送同样大小的数据所用的时间为296076ns
640 × 512 × 8 b i t 296076 n s = 8.85 G b p s \frac{640\times512\times8bit}{296076ns}=8.85Gbps 296076ns640×512×8bit​=8.85Gbps
η = 8.85 G b p s 3.125 G b p s × 4 × 100 % = 70.83 % \eta=\frac{8.85Gbps}{3.125Gbps\times4}\times100\%=70.83\% η=3.125Gbps×48.85Gbps​×100%=70.83%
  最后是单独对门铃接收的测试,可以看到DSP发送的门铃信息都被MicroBlaze正确接收。

上一篇:MPU、MCU、CPU、GPU、DSP、MMU、TPU、NPU大杂烩


下一篇:Android 265投屏传输push端、拉流端