最近一直再看rapidio,有什么不好的多多指出!
以物理层字段开始,
S位 指示这是一个包还是一个控制符号(S=0表示是一个包,S=1表示是控制符号),
AckID表明交换结构器件将用控制符号来确认哪一个包,
PRIO 字段指示用于流量控制的包优先级,
TT、目标地址( Target Address)和源地址( Source Address)字段 指示传输地址的机制类型、包应被传送到的器件的地址和产生包的器件的地址,
Ftype和事务(Transation) 指示正被请求的事务,Transation指的是Ttype
长度(Size)字段 等于编码后事务的长度,
Payload 是RapidIO事务数据的有效裁荷(Payload)长度从1到256字节不等,
SrcTID(源事务ID) 指示事务ID, RapidIO器件在两个端点器件间最多允许有256个未完成的事务。对于存储器映射事务,跟随在srcTID后面的是器件偏移地址 (Device Offset Address ) 字段。写事务必须附带数据的有效裁荷,所有包以16位(2个字节)循环冗余校验码(CRC)结束。
与请求包类似。状态(Status)字段指示是否成功完成了事务。目标TID(目标事务ID)字段的值与请求包中源事务 ID字段的值相等。
实现的功能是在按照 Hello Format 格式发送请求事务,SRIO 接收方处理请求事务,如果处理的是有响应的请求事务就返回 Hello Format 格式的响应,若是没有响应的,则完成相应的数据存储。
下图清楚的给出了各个层级添加的哪些信息:ireq通道传输给SRIO核的逻辑层,逻辑层会给包添加传输层的信息发送给Buffer,然后Buffer会把数据发送给物理层。
例如:SWRITE事务通道ireq通道(接口1)传输给SRIO核以后进入SRIO的逻辑层,逻辑层会给包添加传输层的信息发送给Buffer(接口3),然后Buffer会把数据发送给物理层(接口5),选中srio_gen2_0_block_inst,把中间的buft_*通道、phyt_*通道与gttx_*通道的信号拖到右边的波形窗口中,如下图所示
请求包
响应包
第2类事务(FTYPE=2)为请求类事务,根据TTYPE字段的不同值,它包括NREAD事务(TTYPE=4’b0100),ATOMIC Increment事务(TTYPE=4’b1100),ATOMIC Decrement事务(TTYPE=4’b1101),ATOMIC Set事务(TTYPE=4’b1110),ATOMIC Clear事务(TTYPE=4’b1111)这几种。
第5类事务(FTYPE=5)为写类事务,根据TTYPE字段的不同值,它包括NWRITE事务(TTYPE=4’b0100),NWRITE_R事务(TTYPE=4’b0101),ATOMIC Swap事务(TTYPE=4’b1100),ATOMIC Compare-and-Swap事务(TTYPE=4’b1101),ATOMIC Test-and-Swap事务(TTYPE=4’b1110)这几种。
第6类事务(FTYPE=6)为SWRITE事务(流写事务),请求方可以利用流写事务往目标方的存储空间写入大块数据。与NWRITE相比,流写事务具备以下两个特点:1、流写事务传输数据的最小单位为双字(Double Word);2、流写事务的包格式相对于NWRITE包格式具有更少的头部开销。SWRITE事务没有TTYPE字段,SWRITE事务没有size字段
第10类事务(FTYPE=10)为DOORBELL事务(门铃事务),门铃事务不包含数据负载,它只能用来传输16-bit的信息,所以DOORBELL事务适合传输中断或者信号量。DOORBELL事务没有TTYPE字段。
第11类事务(FTYPE=11)为MESSAGE事务(消息事务),消息事务必须携带数据负载,完成一次数据消息操作最多需要16个单独的消息事务,其中每个消息事务携带的数据负载最大仍为256字节,所以消息操作的最大数据载荷为4096字节(16*256 Bytes)。MESSAGE事务没有TTYPE字段。
第13类事务(FTYPE=13)为响应类事务,根据TTYPE字段的不同值,它包括不带数据响应事务(TTYPE=4’b0000),消息响应事务(TTYPE=4’b0001)和携带数据响应事务(TTYPE=4’b1000)。
第9类事务(FTYPE=9)为Data Streaming事务,在标准的RapidIO协议中第9类事务为保留事务,所以第9类事务是一种自定义的事务。关于第9类事务的详细内容请查看pg007_srio_gen2.pdf的第106页。
大致就上面几种,下图把所有的事务都放在一起以便于大家更快的查看相关的包格式与各个字段的位置。
维护事务—第8 类包不含地址字段,只含写请求和读响应的数据载荷
门铃事务—第10类包格式是门铃事务格式。它没有数据载荷。门铃事务的请求包格式如下图所示
消息事务—第11类包总有数据载荷,并且数据载荷长度总是双字(64-bits或8-bytes)长度的整数倍。一个消息请求包的格式如下图
1. 在IP Catalog中找到RapidIO
2、双击RapidIO核打开配置界面
3、选择Mode为Advanced
Component Name:IP的的名字,只能为字母,数字,下划线,其中首字符必须为字母。
Mode:IP的模式,有基本(Basic)和高级(Advanced)两种。
Link Width:链路宽度,可选值为1、2或者4,链路宽度越大,数据的传输带宽越大。
Transfer Frequency:传输频率,这个值表示的是每个串行链路的传输速率,可选值有1.25、2.5、3.125、5.0和6.25。传输频率越大,数据的传输带宽越大。
Reference Clock Frequency:参考时钟频率,可选值为125MHz或156.25MHz,它指的是外部时钟源(晶振或者锁相环芯片)送给FPGA串行收发器专用时钟引脚的时钟。
TX Buffer Depth:发送Buffer的深度,可选值为8、16或32。这个值表示的是发送Buffer中可存储的包的最大数目。
RX Buffer Depth:接收Buffer的深度,可选值为8、16或32。这个值表示的是接收Buffer中可存储的包的最大数目。
Component Device ID:这个参数是复位以后Base Device ID CSR寄存器的复位值。
Device ID Width:设备ID的宽度,收发双方的设备ID宽度应该相同,否则,由于包头的偏移可能会导致事务被错误的解释。大多数系统Device ID为8位,但是RapidIO核也提供了16位的Device ID供用户选择。
Unified Clock:如果用户设计中log_clk和phy_clk相同,那么可以选中这个选项,选中这个选项可以减少延时和资源利用率。
Transmitter Controlled:选中这个选项以后,RapidIO核会首先尝试用transmitter-controlled实现流控,但如果接收方不支持的话那么会自动切换为receiver-controlled。transmitter-controlled流控可以利用接收buffer的状态和水印最小化重试条件。receiver-controlled流控会随意的发包并使用重试协议。
Receiver Controlled:选中这个选项以后,RapidIO核仅能用receiver-controlled实现流控,在这种模式中,receiver-controlled流控会随意的发包并使用重试协议。
4、Logical Layer标签
Source (Initiator) Transaction Support:用来选择支持的发送事务类型。
Destination(Target) Transaction Support:用来选择支持的接收事务类型。
Enable Arbitration:用来使能逻辑层与输入端口之间的仲裁器。
Maintenance Transaction Support:这个选项应该保持一直使能。
Local Configuration Space Base Address:本地配置空间基地址,选中这个选项后,RapidIO会检查I/O事务的高地址位,如果地址匹配,那么会把事务发给维护端口。由于手册没有提供一种机制去关闭LCSBA,所以在这种情况下系统的行为是未定义的。
5、I/O标签
Port I/O Style:I/O接口可以配置为Condensed I/O和Initiator/Target两种类型。其中Condensed I/O接收和发送均使用一个AXI4-Stream通道。Initiator/Target接收和发送采用不同的AXI4-Stream通道。
I/O Format:I/O端口能被配置使用HELLO格式包或SRIO Stream格式包,一般情况下,强烈推荐使用HELLO格式
Messaging:用来选择消息事务的端口,可选的参数有Combined with IO和Separate Messaging Port两种。Combined with IO选项表明消息事务和I/O写事务采用相同的IO端,Separate Messaging Port选项表明消息事务采用一个独立的端口传输,选中这个选项以后IP核会出现消息事务的AXI4-Stream通道。
Maintainance:用来选择维护端口类型,维护端口类型只能为AXI4-Lite类型。
6、Buffer层标签
Request Reordering:选中这个选项以后,发送Buffer会根据请求包的优先级重新排序。
Flow Control Options:用来选择优先级水印复位值,详细内容请查看pg007_srio_gen2.pdf。
7、物理层标签
CRF Support:关键请求流(Critical Request Flow),一般不选中
Link Requests before Fatal:用来指定链路进入致命错误状态之前链路请求的个数,一般选择默认值
Software Assisted Error Recovery:RapidIO协议定义了3个CSRs用软件来辅助错误恢复。
IDLE Mode Support:空闲模式(IDLE Mode)的选择与传输速率有关,空闲序列1(IDLE1)仅仅支持每通道线速率小于5.5Gbps的情况,选择空闲序列1时,RapidIO使用的控制符号为短控制符号。空闲序列2(IDLE2)支持每通道线速率大于5.5Gbps的情况,6.25Gbps的线速率必须选择空闲序列2,空闲序列2提供了一些附加的功能,比如链路宽度,链路优先级信息以及一些用于改善均衡器性能,提高数据恢复率的随机数。当IDLE1和IDLE2均被选中时,每通道线速率仅支持小于等于5.5Gbps的情况。上一篇文章《RapidIO串行物理层的包传输过程》也介绍了空闲序列1和空闲序列2相关的内容。
8、逻辑层寄存器标签
Device Identity CAR:指定了Device ID与Vendor ID,这两个值不能修改。
Assembly Identity CAR:可通过设置这两个值唯一的确定RapidIO设备的标识符。这两个值不影响核的功能。
Assembly Information CAR:这个寄存器存储的是RapidiO子系统的版本信息,这个值不影响核的功能。
Processing Element Features CAR:选择存储器单元的主功能,默认为Memory,这个值不影响核的功能。
9、物理层寄存器标签
Extended Features Space:扩展特征空间,一般选择默认值。
Port Link Time-out Control CSR:指定链路控制符号丢失后的超时时间,最大值为0xFFFFFF,对应的超时时间约为4.5s,精确度为33%
Port Response Time-out Control CSR:指定链路包丢失后的超时时间,最大值为0xFFFFFF,对应的超时时间在3s到6s之间。
Port General Control CSR:Host选项表明RapidIO设备是主设备,这个选项不影响核的功能。Master Enable选项用来控制是否允许RapidiO核发起请求事务,如果未选中,RapidIO核只能发起响应事务而不能发起请求事务。Discovered选项表明RapidIO核能被处理器定位,这个选项不影响核的功能。
10、共享逻辑标签
当选中Include Shared Logic in Example Design选项时,MMCM、复位逻辑和GT COMMON块等共享逻辑被包含在例子设计中。当选中Include Shared Logic in Core选项时,MMCM、复位逻辑和GT COMMON块等共享逻辑被包含在IP核中。
1.当port_initialized信号与link_initialized信号都为高时,分别表示端口和链路被成功初始化。
2. pg007_srio_gen2.pdf第119页提到,当7个连续的error free控制符号被接收,并且15个连续的符号被发送的时候,link_initialized信号才被拉高,所以接下来看看link_initialized信号拉高之前物理层是否接收了7个控制符号并发送了15个控制符号。首先选中最左边的srio_gen2_0_block_inst,然后把中间列出的以gt开头的接口7的所有信号拖到最右边的波形窗口中进行查看。如图:
3. 在link_initialized拉高之前,先把gttx_charisk与gtrx_charisk用二进制显示,当gttx_charisk与gtrx_charisk对应的位为0时,表明gttx_data与gtrx_data上的数据为有效数据(控制符号与包属于有效数据)。当gttx_charisk与gtrx_charisk对应的位为1时,gttx_data与gtrx_data上的数据为空闲序列。(/K/,/R/,/A/组成的空闲随机序列,们分别为特殊字符/K28.5/,/K29.7/,/K27.7/,转化为16进制为bc,fd,fb)
上图表明在link_initialized拉高之前,发送与接收的控制符号为80f713,控制符号80f713前面的1c是/K28.0/,表示控制符号的起始位置。由于SRIO核默认使用的是短控制符号,所以这里控制符号为24-bit。
把80f713转化为二进制: 80f713 = 1000_0000_1111_0111_0001_0011,各个字段的对应关系如下图所示
4. 整个初始化的过程着重需要关注的两个信号就是port_initialized和link_initialized,如果初始化失败(port_initialized和link_initialized没有被拉高),那么首先必须检查gttx_data与gtrx_data上是否收到了空闲序列/K28.5/,/K29.7/,/K27.7/,同时需要检查是否存在编解码错误,编解码错误的判断标志是gtrx_notintable信号,当它为1时表明存在编解码错误。
当tvalid和tready同时为高时,tdata上的数据才为有效数据,所以这个SWRITE一共消耗了三个有效时钟周期,其中第一个时钟周期发送的是HELLO包头,后面两个时钟周期分别发送8个字节的数据(第一个时钟发送的数据是0000000000000000,第二个时钟发送的数据是0101010101010101),一共16个字节的数据,和instruction_list.vh中第50行定义完全一致,整个时序也与HELLO格式的时序完全吻合。FTYPE字段的值为6,表明确实是一个SWRITE事务
对照HELLO格式解析包头。包头为006020fcd0000600,转化为二进制后与HELLO格式各个字段对应关系如下所示:
SWRITE事务通道ireq通道(接口1)传输给SRIO核以后进入SRIO的逻辑层,逻辑层会给包添加传输层的信息发送给Buffer(接口3),然后Buffer会把数据发送给物理层(接口5),最后ireq通道的SWRITE请求事务经过逻辑层,传输层和物理层到达吉比特收发器(Gigabit Transceiver),吉比特收发器的数据通道gttx_data[31:0](接口7)波形如下图所示
由上图可知,整个串行物理层的包为:7c96f004_b04600ad_d0000600_00000000_00000000_01010101_01010101_e8d30000_7c96f203。(00000000和01010101的宽度为两个有效时钟)这个包的含义如下:
7c96f004中的7c是特殊字符/K28.3/,它是一个包界定符(Packet Deliminator Control Symbol),96f004转化为二进制为:96f004 = 1001_0110_1111_0000_0000_0100它是一个包起始控制符号,各个字段的对应关系如下图所示
b04600ad_d0000600_00000000_00000000_01010101_01010101_e8d30000是SWRITE事务串行物理层的包,把它转化为二进制后各个字段的对应关系如下图所示
上图中data字段是传输的00000000_00000000_01010101_01010101这16个字节数据的二进制码,因为它的二进制码太长了所以我直接用data替代。由于本次传输的字节小于80个字节,所以SWRITE事务的最后面的三个字段不存在,大家可以抓一下数据量为256个字节的SWRITE包,当数据量大于了80字节,后面的三个字段也会有数据。
包最后面的7c96f203中7c是特殊字符/K28.3/,它是一个包界定符(Packet Deliminator Control Symbol),96f203转化为二进制为:96f203= 1001_0110_1111_0010_0000_0011它是一个包结束控制符号,各个字段的对应关系如下图所示
至此,SWRITE事务全部分析完毕
锁定request_address为37的位置,找到请求事务的传输通道ireq。由上图可知FTYPE = 5,TTYPE = 5,这两个字段唯一的确定了这是一个NWRITE_R事务。可知第一个有效时钟传输的HELLO格式包头数据为:2555205004550002。发送的数据是afafafafafafafaf。
ireq通道的NWRITE_R请求事务经过逻辑层,传输层和物理层到达吉比特收发器(Gigabit Transceiver),吉比特收发器的数据通道gttx_data[31:0](接口7)波形如下图所示
由上图可知,整个串行物理层的包为:7c98f009_d84500ad_59250455_0000afaf_afafafaf_afafad15_7c17f21e。这个包的含义如下:7c98f009中的7c是特殊字符/K28.3/,它是一个包界定符(Packet Deliminator Control Symbol),98f009转化为二进制为:98f009=1001_1000_1111_0000_0000_1001它是一个包起始控制符号,
d84500ad_59250455_0000afaf_afafafaf_afafad15是NWRITE_R事务串行物理层的包
细心的人在这里可能发现了一个奇怪的现象:在HELLO格式中,address字段为36’ h004550002,其中高两位为保留位,所以address一共只有34-bit有效位,size字段为5,表示往36’ h004550002地址中写6(size+1)个字节的数据。但是上面串行物理层的包中address字段的值为0000_0100_0101_0101_0000_0000_0000_0,发送的数据个数为8个字节(afafafaf_afafafaf)。出现这种现象的原因为:HELLO格式address字段指向的存储空间的最小单元是1个字节,而串行物理层中的address字段指向的存储空间最小单元实际上是8个字节,address后面的xambsb字段是串行物理层的最高两位地址扩展字段,所以串行物理层的包可访问的存储空间大小为2^34=16G,这也是HELLO格式中address字段位宽为34-bit的原因(关于这部分的内容我在《RapidIO协议概述》也提到过)。正因为HELLO格式address字段与串行物理层address字段所指向的存储空间最小单元不同,所以pg007_srio_gen2.pdf中第78页才给出了一个HELLO格式size,addr与有效字节的对应关系表,如下所示
本例中size=5,addr[2:0] = 2,对应于上图中红框圈出来的情况。所以往36’ h004550002地址中写6(size+1)个字节的数据对串行物理层来说就是往36’ h004550000地址中写8个字节的数据,高6个字节(上图中灰色区域)为有效数据。包最后面的7c17f21e中7c是特殊字符/K28.3/,它是一个包界定符(Packet Deliminator Control Symbol),17f21e转化为二进制为:17f21e = 0001_0111_1111_0010_0001_1110
iresp_tdata的数据为:25d0400000000000。与HELLO包格式的对应关系如上图所示,可知FTYPE = 13,所以这是一个响应事务,prio字段变成了2,而NWRITE_R字段的prio字段为1,这是因为响应事务的prio为请求事务的prio+1。
事实上,响应事务的一整套传输流程为:目标方(Target)发回的响应事务被srio_example_top_primary模块的串行差分信号线接收到达Serial Transceivers,Serial Transceivers在把接收的数据通过gtrx_data通道(接口7)传到物理层,物理层把接收的包经过处理以后通过phyr_*通道(接口5)把数据发给Buffer层,Buffer层对数据进行二次处理以后把数据通过bufr_*通道(接口4)传给逻辑层,逻辑层再把数据传输给I/O端口(接口1),这样就得到了上图HELLO格式的响应包。大家可以把gtrx_data、phyr_*通道、bufr_*通道和I/O端口的波形全部抓出来观察一下。
上图中整个响应事务串行物理层的包为:7c83f00f_388dadad_00255540_7c83f208
7c83f00f中的7c是特殊字符/K28.3/,它是一个包界定符(Packet Deliminator Control Symbol),83f00f转化为二进制为:83f00f = 1000_0011_1111_0000_0000_1111,388dadad_00255540是NWRITE_R响应事务串行物理层的包,7c83f208中的7c是特殊字符/K28.3/,它是一个包界定符。
由于NWRITE_R的响应事务不带数据,所以没有data字段。target TID字段的值为16进制的25,也就是10进制的37,与发送的NWRITE_R请求事务target TID值完全相同。FTPYE字段的值为13,说明这是一个响应事务,整个响应事务的包正是NWRITE_R事务的响应包。
锁定request_address为56的位置,找到请求事务的传输通道ireq,并观察事务的波形如下图所示:
由上图可知第一个有效时钟传输的HELLO格式包头数据为:385420fde0000600。后两个有效时钟发送的数据分别是c2c2c2c2c2c2c2c2和c3c3c3c3c3c3c3c3。可知FTYPE = 5,TTYPE = 4,这两个字段唯一的确定了这是一个NWRITE_R事务。srcTID的值为16进制的38,也就是10进制的56,与request_address的值相等,因为代码里面就是直接把request_address的值赋给了srcTID。
NWRITE串行物理层包的数据为:7c93f010_c84500ad_4b38e000_0605c2c2_c2c2c2c2_c2c2c3c3_c3c3c3c3_c3c362a2_7c13f20e。
锁定request_address为78的位置,找到请求事务的传输通道ireq,并观察事务的波形如下图所示
NREAD请求事务不带任何数据,只包含一个HELLO格式的包头,包头的数据为:4e242070000023f0。FTYPE=2,TTYPE=4,这两个字段唯一的确定了这是一个NREAD事务包。
NREAD事务串行物理层的包格式:
整个串行物理层的包为:7c92f014_b84200ad_4b4e0000_23f09c5a_7c92f213。FTYPE = 2,TTYPE = 4,这两个值确定了这个包是一个NREAD事务包。rdsize=11(二进制的1011),wdptr=0,通过查RapidIO_Rev_2.2_Specification第34页的表可知数据量为8个字节。
NREAD事务是一个有响应的事务,且响应事务中携带读到的数据。所以当发起方(Initiator)往目标方(Target)发送一个NREAD事务以后,发起方(Initiator)还要接收目标方(Target)的发回响应事务。响应事务通过gtrx_data通道接收。响应事务串行物理层包时序如下图所示:
由上图可知,00000000这个数据传输了2个时钟周期,所以整个响应事务串行物理层的包为:7c8af01e_708dadad_804e0000_00000000_0000469c_7c8af219。FTYPE=13表示这是一个响应事务,TTYPE=8表示这个响应事务携带数据,target TID的值为16进制的4e(10进制的78),与请求事务刚好对应上,data字段是8个字节的00,由于并没有存储器,所以读出来的数据全部是0。
维护事务有本地(Local)和远程(Remote)两种类型,区分这两种维护事务是通过maintr_araddr信号的高八位的值来确定的。
由上图可知,maintr_araddr的[31:24]位用来区分本地维护事务和远程维护事务,当 maintr_araddr=01xxxxxx,表示的是远程(Remote)维护事务。
当maintr_araddr=00xxxxxx,表示的是本地(Local)维护事务。maintr_araddr的[23:0]位是读操作的偏移地址。
当 maintr_araddr=01000000,表示的是逻辑层的远程(Remote)维护事务。逻辑层I/O端口发起的维护事务会通过逻辑层、传输层到物理层转化为串行物理层的包通过高速串行收发器(Serial Transceiver)发出去。下图是一个远程维护事务串行物理层包的时序
由上图可知,维护事务串行物理层的包为:7c82f00b_104800ff_18010000_0060dead_beefdead_beefbe6e_7c82f20c。FTYPE = 8,TTYPE = 1,表明这是一个写请求的维护事务。
整片文章的重点只有一个,就是设计指南那一节所提到的HELLO格式与HELLO格式的时序,强烈建议对照pg007_srio_gen2.pdf文档多读几遍。 事实上,在编写Verilog代码时,就是先根据事务类型组装对应的HELLO格式的包头(Header),然后按照HELLO格式的时序,在第一个有效时钟周期类把包头(Header)发出去,后面几个有效的时钟周期发送你的数据。在这个过程中,RapidIO核会自动把HELLO格式的包转化为标准的RapidIO串行物理层的包,并添加控制符号,空闲序列等必要信息发出去,接收过程则正好相反,RapidIO核接收到标准的RapidIO串行物理层的包,控制符号,空闲序列等信息后以后,会把接收的信息转化为HELLO格式的包给用户做后续处理。所以对用户来说只需要理解HELLO格式包的组成与HELLO格式的时序就可以利用RapidIO核实现数据的高速传输,而不需要关注RapidIO协议的过多细节。
最近一直在看rapidio,有什么错误的望多多指出!