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发写数据包。
我们的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个中断控制器的时钟周期。
为了让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发送引擎就好了。
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可以直接跳转到相应的中断服务函数处。
从DSP到FPGA,NWRITE波形
下面两张图是NWRITE包接收时的数据波形,第一张图是从起始处连续采样2048点的整体波形,第二张图是其中放大后的一部分波形。蓝色的波形是AXI接口的W通道的数据,数据正常写入DDR。
从FPGA到DSP,SWRITE波形
下面两张图是SWRITE包发送时的数据波形,第一张图是从起始处连续采样2048点的整体波形,第二张图是其中放大后的一部分波形。从第一包SWRITE发出包头到真正开始发送数据,经过了一段时间的等待,因为从DDR读数据需要等待;后续能够读到连续的数据是因为在AR通道已经把需要读的数据的地址都发过去了。
读写速率测试
为了对SRIO传输的速率进行测试,在DSP端利用TSC定时,分别对DSP通过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正确接收。