1、初识串行RapidIO(SRIO)
SRIO是串行RapidIO的简写,其实现代比较常用的高速接口协议,比如SRIO、PCIE、JESD204B等都是基于SERDES开发的,均属于高速串行总线。
在此之前有对应的并行总线,比如RapidIO、PCI、LVDS接口的AD和DA,并行总线的缺点在于速率过高时会引起信道偏差,并且PCB布线难度很大。
比如RapidIO 1.x协议定义了8/16并行LVDS协议和1x/4x串行协议(SRIO)共两种物理层接口协议,其中并行RapidIO协议需要40~76根走线,而SRIO只需要4~16根信号线。
下图是TI的DSP芯片的SRIO接口,集成了1x/4x的SRIO接口
发送通道的数据先经过CRC编码,然后进行8B10B编码,之后转换为串行数据输出。
而接收通道的CDR先根据串行数据去调节时钟和数据的相位关系,之后把串行数据转换为并行数据,并行数据通过8B10B解码,最后在进行CRC校验,然后接收到数据。
至于8B10B编码原理,并串转换及CDR时钟恢复的原理在GTX相关文章已经讲解过,本文不再赘述。
RapidIO 2.0标准的线速率支持1.25GHz、2.5GHz、3.125GHz、5GHz、6.25GHz,协议分为三层:逻辑层、传输层、物理层,如下图所示。
逻辑层定义了操作协议,传输层定义了包交换、路由和寻址机制,物理层定义了电气特性、链路控制和纠错重传等。
如图所示,RapidIO包由包头、可选的数据段和16bits CRC校验组成。包头的长度因类型不同可能是十几到二十几个字节,每包的数据段长度不超过256字节。
逻辑层业务主要支持直接IO/DMA和消息传递,直接IO/DMA模式又可以进一步分为写操作(NWRITE)、带响应的写操作(NWRITE_R)、流写(SWRITE,数据长度为8字节整数倍)、读操作(NREAD)。
在一个网络中,可以存在很多SRIO设备,各种互联结构如下图所示,传输层定义了包交换的路由和寻址机制。通过ID区分不同的终端器件,RapidIO支持8位或者16位器件ID,一个网络最多可以容纳256个或65536个终端器件。
以上就是SRIO的一些概述内容,参考TI的一些内容。RapidIO的协议是比较复杂的,协议手册包含一千多页内容,有兴趣的可以在公众号后台回复“SRIO手册”(不包括引号)获取。
SRIO协议在FPGA中使用的并不是很多,大多数只会在FPGA与DSP通信时使用。由于手中并没有DSP相关硬件,因此就不对SRIO的标准协议进行解读了。
下文讲解Xilinx提供的SRIO IP相关内容,后文使用SRIO IP通过光纤回环,验证IP的简单使用方式。后续如果具体使用到DSP,在对相关内容进行解读。
2、Xilinx的SRIO IP 概述
Xilinx提供了SRIO协议的IP,支持1~4通道,不同速度等级的FPGA能够支持的协议是不相同的。下表展示了xilinx的FPGA芯片能够支持的SRIO协议类型及线速率。
上图显示的是支持该协议的FPGA芯片最低速度等级,比如速度等级为3的Zynq-7000芯片支持所有类型的SRIO协议,而速度等级为1的Zynq-7000芯片不支持4通道的线速率大于等于5Gbps的SRIO协议。
SRIO IP的内部框图如下图所示,由图可知SRIO的IP是在底层高速收发器GT的基础上封装而来的,因此比如部分时钟信号的关系与GTX其实是一致的。
PHY层是在GT收发器的基础上对数据进行组帧或者解帧,与前文通过GTX实现自定义协议的PHY设计一致。PHY层和GT收发器的时钟应该是相关的,而逻辑层与PHY层的时钟是不同的,因此中间通过BUFFER进行缓冲数据。
3、逻辑层
逻辑层 (LOG) 包含三个接口,分别为用户接口、传输接口、配置结构接口。下图显示了与每个LOG接口关联的端口,粗箭头表示AXI4-Stream端口,细箭头表示AXI4-Lite端口。
传输接口与BUFFER直接相连,配置接口用于配置逻辑层的一些寄存器参数,一般不常用。用户接口经常使用IO端口收发数据,其余端口也不常用。
用户接口包含一组I/O端口,还有可选的消息端口、维护端口、用户自定义端口。通常情况下,任何支持的I/O事务(如NWRITE、NWRITE_Rs、S_WRITE、NREADs和响应(不包括维护响应)都是在I/O端口上发送或接收的。
消息事务(如果支持)可以分配给消息端口或I/O端口,门铃只能使用I/O端口。如果启用了维护端口,所有维护数据包都将出现在维护端口上。
如果事务是用户定义的、不受支持的类型或没有分配的端口,它将使用用户定义的端口(当用户定义的端口被禁用时,接收到的与另一个端口不对应的数据包将被丢弃)。
I/O端口可以配置为Condensed I/O 或 Initiator/Target,I/O端口由AXI4-Stream通道构建而成,可以使用HELLO或SRIO Stream两种数据格式,常用HELLO格式。
3.1、Initiator/Target
Initiator/Target端口的构成如下所示,这个模式包含四个AXI_Stream端口。
本地端点生成的请求被放置在启动器请求(ireq)通道上,以便在链路上传输。如果远程设备接收到该数据包时,向本地端点发送应答报文,则应答报文会出现在响应(iresp)通道上。
本地设备接收到来自远程设备的请求数据包会出现在目标请求(treq)通道上,同理,对其的应答数据包应通过目标响应(tresp)通道发送。
如果对上述的数据传输不是很理解,可以参考下图,两个FPGA(或者两个高速收发器)通过SRIO通信。
两个高速收发器均使用Initiator/Target端口模式,FPGA1通过ireq向FPGA2发送指令(包含写、带响应的写、读、门铃等),该数据包会出现在FPGA的treq通道。如果该数据包需要FPGA响应,那么FPGA2会从tresp发送响应数据包,响应数据包会出现在FPGA1的iresp端口。
下图中FPGA1与FPGA2相同颜色的端口传输对应的数据包,比如FPGA2通过ireq发送的请求数据包会出现在FPGA1的treq端口上。
上述就是Initiator/Target端口的原理,一般页经常使用该端口,接收和发送数据包比较清晰。
3.2、Condensed I/O
精简I/O端口样式减少了用于发送和接收I/O数据包的通道数量。有一个axi4_stream通道用于传输与I/O端口(iotx)相关的所有数据包类型,所有接收到的I/O端口数据包(iorx)都使用一个通道,如下图所示。
Condensed I/O端口将Initiator/Target端口端口的ireq和tresp合并为iotx,将treq和iresp合并为iorx,两个FPGA使用该接口模式通信时的框图如下所示。
其实两种端口区别在于简洁和清晰,功能上没有区别。逻辑层的用户端口还包含消息端口和用户自定义端口,这两个均通过axi_stream传输数据,而维护端口通过axi4_lite传输数据。这些端口不经常使用,在具体使用时查看手册即可,端口信号都比较规范。
4、BUFFER、PHY、GT层结构
如下是BUFFER层相关接口,左侧通过axi4_stream接口与逻辑层相连,右侧通过axi_stream接口与PHY层相连,下面包含一个axi_lite的配置接口。
PHY层和GT的接口框图如下所示,左侧通过axi_stream接口与BUFFER直连,右侧连接GT收发器,下面同样可以通过一个axi_lite接口配置PHY内部寄存器。
手册中有大量篇幅描述配置寄存器的含义,但是一般只用来收发数据时,使用默认参数即可,不需要人为配置寄存器,因此这部分省略,需要什么功能再去查手册即可。
5、SRIO支持数据包类型及格式
SRIO一次最多只能传输256字节数据,并且不能将数据包拆分,在传输数据时必须保证数据段小于等于256字节。
下表定义了SRIO IP支持的一些事务的类型及参数,FTYPE和TTYPE都在后文协议中会被使用,读数据在发送端从Initiator/Target的ireq端口发出,会出现在接收端的treq端口上。
接收到不支持的事务会出现在用户定义的端口上,如果用户定义的端口不存在,则事务在内核中被丢弃,并拉高port_decode_error信号。
5.1 、HELLO数据包
用户端口通过发送HELLO数据包来发送各种数据帧,HELLO数据包格式如下所示,其中size表示数据段的长度,取值范围[1,256],单位字节。
上述各个字段的含义如下表所示,其中FTYPE和TTYPE的值可以从图13中获取。
field | 含义 |
---|---|
TID | 数据包的事务ID |
FTYPE | 数据包的事务类,HELLO格式支持的FTYPE有2、5、6、A、B和d。 |
TTYPE | 数据包的交易类型,仅用于FTYPE 2、5和13。 |
priority | 数据包的优先级,请求数据包只能使用优先级0-2,响应包优先级应该是请求优先级+1 |
CRF | 数据包的关键请求流标志,拉高表示该数据包优先级比较高。 |
size | 数据段的长度,以字节为单位。 |
Error(E) | 高电平表示数据包处于错误状态。 |
address | 读写数据的首字节地址。 |
info | 信息字段,仅适用于门铃包。 |
Msglen-1 | 组成消息序列的数据包数量,仅适用于邮件。 |
Msgseg-1 | 此数据包代表的消息段,仅适用于邮件。 |
mailbox | 通信的目标邮箱,仅适用于消息包,具体含义要查看具体的芯片。 |
letter | 仅用于信息包的字母字段。示邮箱中的插槽。 |
Cos | 服务等级。 |
StreamID | 端到端业务流标识符。 |
length | PDU长度。 |
下图是一个典型的用户接口端口上的数据传输时序,HELLO报头出现在第一时钟,同时用户信号上传输源ID和目的ID。如果该数据包有数据段,则会出现在后续时钟。
下图先传输HELLO包头,在接下来的四个时钟传输32字节数据,总共需要五个时钟周期。
下图是一个包含三个数据包的时序。首先有两个单周期(仅报头)数据包,通过拉高tlast信号指示数据包边界。在单周期数据包之后,主机等待一个周期,然后开始发送下一个数据包。
在第三个数据包中,主机和从机都在不同的周期暂停数据传输 (分别拉低tvalid和tready),经过五个时钟周期传输了16字节数据。
5.2、 SRIO Stream数据包
用户端口可以配置为使用SRIO Stream格式来实现最大程度的控制。在这种格式中,数据包以RapidIO规范中定义的完整形式传输数据,包括所有逻辑/传输层字段。
SRIO Stream的数据包格式如下所示,由于这种数据包使用的比较少,了解即可。
下图是用户接口端口上典型的SRIO Stream数据传输时序,五个时钟周期传输40字节数据,CRF和RESP出现在第一个时钟周期。
如下图所示,首先发送一个单周期包,主机等待一个时钟周期,然后发送两个背靠背的16字节数据包,拉高tlast来指示数据包的边界。
6、时钟关系
又到了时钟关系推导了,先将手册中提到的各个时钟关系列出来,然后在根据前文对GTX时钟的理解,再来推导SRIO各个时钟的关系,这些结论就会很清晰,毕竟SRIO只是在GTX的基础上封装得到的,很多规则依旧适用。
phy_clk是主内核时钟,gt_pcs_clk用于串行收发器与PHY通信的时钟信号(与GTX的userclk2对应),gt_clk是高速收发器内部PCS与PMA传输并行数据的时钟信号(与GTX的userclk对应)。因此gt_pcs_clk的时钟频率是gt_clk的一半,phy_clk等于(gt_clk *高速收发器数据)/4。
为了防止BUFFER溢出,逻辑层的时钟log_clk应大于等于phy_clk,同时log_clk应该与phy_clk同步。所有配置接口的cfg_clk必须与log_clk保持一致。下表显示了链路宽度为1的各个时钟频率取值。
下图是7系列FPGA的SRIO内部时钟架构,由图可知gt_clk就是高速收发器的usrclk(内部PCS与PMA传输并行数据的时钟),其时钟频率等于线速率除以PCS传输并行数据位宽,通过上图可知PCS并行数据位宽为20。
而gt_pcs_clk(高速收发器端口时钟信号)是gt_clk的一半,因此可知高速收发器的端口数据位宽为32位,经过8B10B编码后变为40位。接口传输一次数据,内部PCS需要传输两次,才能保证带宽一致,这也是gt_clk频率为gt_pcs_clk二倍的原因。
逻辑层与PHY层传输数据位宽是一致的,从HELLO数据包格式可知,逻辑层每个时钟传输64位数据,如果底层只有一路高速收发器,那么逻辑层传输一次数据,高速收发器就需要传输两次数据,才能保证带宽一致。
因此,当数据链路为1x(即1路高速收发器)时,gt_pcs_clk的频率是了PHY层时钟频率phy_clk的2倍,也是逻辑层log_clk的2倍。
接下来可以推断,当数据链路为2x(底层包含两路高速收发器),每路高速收发器端口数据位宽为32位,2路就是64位,与逻辑层和PHY数据位宽一致。则逻辑层时钟log_clk、PHY层时钟phy_clk和高速收发器接口时钟gt_pcs_clk频率一致。
结果如下表所示,验证了上述推论。
同理可知,当底层包含4路高速收发器时,高速收发器每个时钟可以传输128字节数据,为了让带宽保持一致,需要将PHY层和逻辑层时钟设置为gt_pcs_clk的2倍,如下表所示。
7、复位信号
每个时钟域下都有对应的复位信号,复位信号需要在相应时钟域下至少拉高四个时钟周期才有效。
示例工程的复位参考设计模块(srio_rst.v)有一个异步复位输入sys_rst,该模块使复位与每个时钟域同步,并延长脉冲以满足最小复位周期要求。
接收端和发送端的SRIO应通过握手实现内核复位,以减少数据包和控制符号的丢失。接收对方的复位会通过拉高内核的phy_rcvd_link_reset信号来告知用户。
当phy_rcvd_link_reset为高电平时,将sys_rst拉高。如果要向对方发送复位请求,则需要把phy_link_reset信号拉高,同时将sys_rst拉高,直到port_initalized为低电平时拉低,完成握手。
关于SRIO IP的讲解到此结束了,由于该IP的功能比较多,本文只是讲解了最基础的使用方式需要了解的原理。其余的维护端口、消息端口、用户自定义端口、配置端口等等,在需要使用时,可以自行查看手册,原理也比较简单。
本文参考TI的一些文章以及xilinx的SRIO手册PG007,需要的可以在公众号后台回复“xlinx手册”(不包括引号)获取。
如果对文章内容理解有疑惑或者对代码不理解,可以在评论区或者后台留言,看到后均会回复!
如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐!您的支持是我更新的最大动力!将持续更新工程!