详解赛灵思SRIO IP并提供一种FIFO封装SRIO的收发控制器仿真验证
概述
RapidIO标准定义为三层:逻辑层、传输层、物理层。
逻辑层:定义总体协议和包格式,包含设备发起/完成事务的必要信息。
传输层:提供包传输的路由信息(对顶层不可见)。
物理层:描述设备级接口细节(包传输机制、流控、电气特性、低级错误管理)。
逻辑层(LOG)
逻辑层划分为模块控制并解析数据包,包含三种接口:
用户接口(User Interface)
可配置端口数量和事务类型。
支持通过AXI4-Lite总线访问本地/远程寄存器。
传输接口(Transport Interface)
相当于缓存Buffer(对顶层不可见)。
配置接口(Configuration Fabric Interface)
读写本地配置空间及逻辑层/传输层寄存器。
用户接口详解
- I/O端口集:
支持I/O事务(NWRITEs、NWRITE_Rs、SWRITEs、NREADs、RESPONSEs)。
可选支持消息事务(取决于IP核配置)。
支持门铃事务。
消息端口:专用于消息事务。
维护端口:专用于维护事务。
用户自定义端口:支持自定义事务类型(未使能时丢弃包)。
I/O端口类型
- Condensed I/O:
单AXI4-Stream通道发送/接收所有包类型。
- Initiator/Target:
分离请求与响应事务,共4个AXI4-Stream通道。
数据流协议
支持HELLO格式与SRIO Stream格式。
- 通道映射关系:
s_axis_ireq*
→ ireq(本地请求)m_axis_iresp*
→ iresp(远程响应)m_axis_treq*
→ treq(远程请求)s_axis_tresp*
→ tresp(本地响应)
物理层(PHY)
功能:处理链路训练、初始化、协议、CRC校验、应答标识符插入。
- 接口:
通过AXI4-Stream通道连接传输层。
AXI4-Lite接口连接配置层。
串行接口连接高速收发器(通常使用FPGA集成的GT接口)。
寄存器空间
能力寄存器空间(CAR)
命令和状态寄存器空间(CSR)
均在逻辑层实现。
HELLO包格式
标准化包头域,包头与数据分离传输。
- Size域规则:
值 = 传输字节总数 - 1(有效范围0~255,对应实际1~256字节)。
需与RapidIO包的size/address/wdptr域一致。
- 因AXI4-Stream的
tdata
为8字节,需分情况处理:数据量 < 8字节
数据量 > 8字节
SRIO事务类型及关系梳理
1. 直接I/O(DMA)事务
事务类型 | 特性 | 应用场景 |
---|---|---|
NWRITE | 写操作,无需响应 | 高效无确认数据传输 |
NWRITE_R | 写操作,需响应 | 需数据完整性的场景 |
SWRITE | 流式写(数据长度需为8B整数倍) | 连续数据流(如视频) |
NREAD | 读操作,返回响应包+数据 | 读取目标地址数据 |
2. 消息传递事务
事务类型 | 特性 | 应用场景 |
---|---|---|
DOORBELL | 短消息通知(如中断触发) | 轻量级事件通知 |
MESSAGE | 长消息传输(邮箱路由) | 动态通信/软件管理交互 |
3. 维护事务
MAINTENANCE READ/WRITE:读写配置寄存器(初始化/错误处理)。
事务对比
特性 | 直接I/O事务 | 消息传递事务 |
---|---|---|
效率 | 高(硬件控制) | 低(软件介入) |
可靠性 | NWRITE无确认 | 依赖软件处理 |
延迟 | 低 | 较高 |
典型场景 | DSP与FPGA间实时通信 | 多处理器系统通知 |
事务类型对应表如下,更具体地可以见PG007开发手册P73页。
SRIO事务时序仿真
仿真步骤(Vivado 2020.1)
创建工程及SRIO IP核。
右键IP核 → "Open IP Example Design"。
运行仿真,添加
request
/response
模块观察信号。
运行约1000us捕获事务动作。
关键事务时序
- MAINTENANCE READ REQUEST
接收请求,无响应(
val_tresp_tvalid=0
)。
SWRITE请求(发送)
val_ireq_tvalid
拉高,ftype=6
,ttype=0
。
SWRITE请求(接收)
response
模块验证事务类型。
ftype(6)和ttype(0)
NWRITE_R请求(发送)
请求包发送。
NWRITE_R请求(接收+响应)
接收请求后发送响应包,和发送的请求包一致,该事务会产生响应,在一段时间后可以看到val_tresp_tvalid拉高一个周期,发送响应包val_tresp_tdata = 64’h25d0_4000_0000_0000。
NREAD请求(发送)
仅包头无数据。
NREAD请求(接收)
接收模块返回响应包+数据。
- NREAD响应(发送)
size=8'h3f
→ 发送64字节数据(8个周期)。
- NREAD响应(接收)
接收包头(
val_iresp_tdata=64'h4bd8400000000000
)及数据。 跟在包头后面的是数据0。
自定义事务传输仿真
计划仿真NWRITE和SWRITE两种事务类型,通过FIFO实现用户层时钟到IP核跨时钟传输以及数据缓存的功能,方便用户直接使用。
移植srio_example工程
配置参数:
parameter SIM_VERBOSE = 1, // 仿真详细日志 parameter VALIDATION_FEATURES = 0, // 关闭验证功能 parameter QUICK_STARTUP = 1, // 启用快速启动 parameter STATISTICS_GATHERING = 0, // 关闭统计功能 parameter C_LINK_WIDTH = 4 // 4x通道
将示例工程文件夹import拷贝到自己工程中:
添加文件:
除了仿真文件其余都加进去。
添加好的工程目录如下:
搭建好总的框架,并对SRIO官方案例工程进行一些修改
创建收发模块:
首先创建好两个模块,分别是Message_TX数据发送模块和Message_RX数据接收模块。
创建顶层模块:
创建一个顶层模块srio_demo。
对srio_example模块进行修改:
要提前对srio_example模块进行一些处理,添加一些信号给数据收发模块用。(下面图片中左边时示例程序,右边是对其修改后的程序)
首先把一些不必要的报告和一些附加功能屏蔽掉
然后把port_initialized和link_initialized两个信号引出来
然后把log_clk用户时钟引出来给外部使用
然后把ireq和treq相关AXI总线信号引出来
最后就是把IP核的其他输入信号赋上一些初始值,主要是iresp和tresp,保证IP核正常运行。
最终修改好之后整体框架如下图:
加上FIFO IP核,并配置好相应参数,编写好发送模块
这里描述简单些,例化好FIFO IP,并给FIFO相关信号赋值
最后编写发送模块的剩余代码,发送模块状态转换图如下图所示
加上FIFO IP核,并配置好相应参数,编写好接收模块
这里描述简单些,接收模块的状态转换图如下图所示
编写仿真程序,仿真调试
首先创建仿真文件
把顶层文件的端口添加到仿真文件中
例化两个端,分别是PORTA端和PORTB端,两个端TX和RX引脚反接,并设置A端作为发送端,B端设为接收端
产生时钟和复位信号
添加上一些监测信号
编译完成后,点击仿真,添加PORTA的tx模块和PORTB的rx模块进波形窗口
继续运行仿真,看一下是否link上。在58us左右的时候,port_initialized拉高
在77us左右link_initialized拉高,表示建链成功。一般port_initialized&link_initialized作为初始化完成的标志。
在94us左右treq_tdata不会有动作,跟之前示例工程有区别,这是没有传数过去,是正常的。
编写传输数据流程:
点击开始仿真,100us时tx_vld正常拉高,tx_data数据传输也正常。
ireq信号启动发送流程,时间大概再100.6us左右,这里帧头是0x006020fcd0000600,事务类型是SWRITE。
PORTB的接收模块的treq信号在101.6us左右有动作。
接收模块输出的结果如下图所示,即rx_vld信号拉高之后开始数据接收的数据,不包括SRIO帧头。
至此,仿真验证结束,结果符合预期。
本期分享结束,感谢大家看完,私信我可获取相关源码工程