AXI协议(五)-AXI-STREAM及接入思路解析

在本文中,你将可能学会:

  1. AXI-STREAM协议的梗概(下简称axis)
  2. 尝试编写出普通摄像头接入AXIS的思路

本来想讲完怎么接入的,由于篇幅的原因,代码只能留在下一节中讲了,那我们下一节也顺便为这个系列做个简单的收尾吧。

AXIS概述与异同处

终于介绍到AXI4中的最后一个协议了,AXI-Stream顾名思义是用来传输数据流的,如图像输入,高速AD等。如果有接触过的朋友应该知道,这种数据流的处理一般是和DMA一并使用的,那么也就会有一个叫做内存映射(Memory Mapping)的问题,一般会对数据的位宽(对齐),流传输方式比较敏感,反而对地址,读写上比较无所谓(因为这个基本由DMA控制)。

所以相较于AXI-FULL,AXIS有以下的改动,接口上:

  • 取消AXI-FULL中的AW/AR(Address Write/Read)通道
  • 取消读写响应(BRESP通道/RRESP信号)
  • 单向传输,即读写就只留下一个

功能性上:

  • 读端(从端)允许穿插,读写均不允许乱序
  • AXI4流接口没有定义或最大突发或分组长度
  • AXI4-Stream接口允许数据宽度是任何整数的数据字节数
  • AXI4流接口包括TID和TDEST信号分别指示源和目的地
  • AXI4-Stream接口包括用于插入和移除空字节的TKEEP信号。

此时我们来看看总体的端口表(主端,即发送端):

对比AXI-FULL,握手啥的我们就不讲了,下面需要介绍的有:

  • TKEEP && TSTRB : 指示数据字节类型及流格式
  • TID && TDEST: 指示数据的去向问题
  • TLAST && TUSER:边界值和用户自定义问题

AXIS数据流的去向问题(省)

由于取消了地址这个概念,所以这里引入了一个“路由”的概念提示当前数据应该送到哪去,

其中:

  • TID 指示数据的"来源"
  • TDEST指示数据的"去向",会在AXI-Interconnecting中请求接收的从端.

实际上,这两个功能xilinx的ip也没有实现,所以我们这里就不过多介绍了

AXIS数据字节类型及流格式

在AXIS中,定义了三种流数据字节:

  • 数据字节(Data Byte):包含在源和目标之间传输的有效信息的数据字节。
  • 占位字节 (Position byte):表示流内部数据字节的相对位置的字节。 这是一个不包含在源和目标之间传输的任何相关数据值的占位符
  • 空字节(Null byte):不包含任何数据信息的字节或关于流内数据字节的相对位置的任何信息。

其中,位置字节和空字节最大的差别就是他们能不能被删除,正如上文中提到,我们这些AXIS的数据一般都是后接DMA的,对于内存的写入位宽对齐尤为重要,下看AXIS中的三种数据流:

字节流(Byte stream)

字节流是传输多个数据和空字节。 在每个TVALID,TREADY握手,可以传输任何数量的数据字节。 null字节没有含义,可以从流中插入或删除。

在图中,每个垂直列表示单个传输中的字节,使用4字节宽数据总线。

连续对齐流(Continuous aligned stream)

这个就是就喜闻乐见的情况了,没有任何Position byte和Null byte,数据本身就是对齐的,可以直接拉进内存。

这里也是一样,每次传4个Byte。

连续不对齐流(Continuous unaligned stream)

这里就相当于,数据包只有18B,但是对齐需要20B/24B,这个时候就需要引入占位字节:

这里的Position Byte可以在传输的开头或者结尾给出,以存进内存的时候位宽对齐。

稀疏流(Sparse stream)

这个就是连续不对齐流的推广,它允许数据流的中间也有占位字节,区分就靠你是怎么定义的了。

如何指示不同字节类型

在AXI-FULL中,我们可以通过WSTRB来分开有效数据和无效数据,但现在又多了占位字节,所以相应地协议多了TKEEP信号,具体规则如下:

image-20210708182822402

AXIS边界问题

这个跟AXI-FULL是一致的,都是用tlast来指示到这一包的的接收了。但是在一些二维数据(比如图像)中,就必须再引入一条指示线,以Xilinx家出名的VDMA为例,他们的行结束(end of line)是用 tlast来指示的,而帧开始(start of frame)是用tuser的第一位指示的(一般用法,还可以多加一条fsync),见手册:

image-20210708183726095

Default value signaling

这个是大家可能看我上面的端口表感觉不对劲,或许多了些端口或少了些,这是因为这个协议是允许较大程度的自定义(省略)的:

  • TDATA:这个我也匪夷所思,见官方文档3.1.5:

Most applications of the AXI4-Stream interface will transfer a data payload. However, it is allowable to implement an interface that does not have a TDATA data payload.

  • TID,TDEST,TUSER:

TID, TDEST, and TUSER are all optional signals on the interface

  • TLAST:如果省掉TLAST,即意味着他要不常1,要不常0,大家可以从数据包的角度出发想想有怎样的影响,这里就不多说了,指路文档3.1.3,因为我觉得正常人都不会省略这个信号…
  • TKEEP and TSTRB: 最省事的全拉高,然后数据发送注意字节个数就行
  • TREADY 是的,就连ready也是能省掉的,你一直拉高就完事了。但是这事就得牵涉到收发端能不能处理“反压”的问题

反压问题

简单来说,反压即入口流量大于出口流量,系统处理能力跟不上数据进来的速度,对多级流水线而言,处理能力越慢的那级就会使前面的流水线动弹不得(降速),导致链路速率下降,我们举一个简单例子:

现在我们来处理这么一个材料生产流程:

  • 第一级:染色

Snipaste_2021-07-08_19-09-26

当前链路带宽为16/s,可见已达链路最大输入带宽,而一级处理速率为8,由于需要双通道输入,故每种染料需要16/s,证明一级流水线满速运行!

  • 第二级:合并

image-20210708192230219

  1. 已知合并机的输出速率为2/s,由于是双输入,则输入速率为4/s
  2. 此时链路输出速率只有1/s,证明流水线内部出现反压
  3. 检查到一级合并机由于只有一台也是输出2/s,但不满足二级合并机的输入速率4/s
  4. 反压导致上级染色速率下降至4,即一级合并机的最大输入速率
  • 解决方法:增加设备,解决反压:

image-20210708193524333

可见此时多加了一台合并机在一级合并中,各个速率就达到了一致。

回到AXIS中,所以取不取消tready信号,即:

assign axis_ready = 1'b1; // -> 你使点劲来数据啊.jpg

得从两个角度看问题:

  • 主端(发送端):有处理反压的能力,即从端处理太慢时,主端能缓存一部分数据就保留tready信号,听指挥。如果去掉tready信号即发送端没有处理反压能力,处理不了的数据就只能丢掉了(危)。
  • 从端(接收端):如果接收端主动去除tready,就证明接收端处理数据的能力大于等于了链路带宽,你使劲来就行,实际上,一般大型的ip都会给出这个数据,继续以vdma为例:

image-20210708194446992

​ 当然,这不代表他们就去掉tready信号了,因为达到吞吐量上限了他们也依然会进行反压。

将摄像头转化AXIS的思路

以一个行扫描的摄像头输入为例,输入信号有:

  • 像素时钟
  • 像素值
  • 行同步信号
  • 帧同步信号

所以我们要解决的问题和处理的基本思路有:

  1. 跨时钟域处理(像素时钟和AXI时钟不同源,打拍?异步fifo/ram?)
  2. 边界指示信号处理(行同步 -> tlast,帧同步->tuser[0]?)

在下一篇中有一个更有趣的现象就是,摄像头输入的物理位宽和像素格式位宽还不对齐,这又要解决呢?

欲知后事如何,且听下回分解。

小结

在本节中,主要介绍了AXI-Stream,AXI4家族的最后一个成员,

和小何为了解释反压问题而买了个游戏,专门挑了这么个例子。

所以给个关注吧观众老爷们:

参考资料

Xilinx-VDMA官方手册PG020

ARM-AXI-Stream官方手册

异形世界

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐