极快入门AXI4总线--AXI4-Stream篇3----XILINX IP AXI4 STREAM DATA FIFO
写在前面
AXI4系列链接:带你快速入门AXI4总线--汇总篇(直达链接)
1、AXI4 STREAM DATA FIFO是什么?
IP核----AXI4 STREAM DATA FIFO也是一种先入先出形式的数据缓存队列(FIFO),不过输入输出接口均为AXIS接口。可用在数据缓存,跨时钟域传输等各类场景。搭载的AXIS接口方便了模块移植,比较适合SOC系统。
在IP catalog搜索,AXI4 STREAM DATA FIFO,再双击出现其配置界面:
点击documentation--product guide有XILINX提供的IP手册,需要注意的是这个IP的手册是和其他多个IP构成的一个手册(PG085),所以内容不是特别详尽。
该IP的参数如下:
Component Name:自己例化的IP名称,根据自己需求来命名即可
FIFO Depth:FIFO深度,可选择范围16 and 32768,我们这里设置32
Memory type:实现FIFO的RAM类型,一般选择自动auto即可
Independent:是否选择独立时钟,即同步FIFO或者异步FIFO,我们这里不搞复杂了,选择同步FIFO ,选择NO
CDC sync stages:跨时钟域处理的同步阶数,我们选择的同步时钟,用不到
Enable Packet Mode: 使能包模式:设置为Yes将使能包模式。此项设定需要TLAST信号被使能。FIFO的操作在包模式下被修改为存储传送的数据,直到TLAST信号被置位。当TLAST信号被置位或者FIFO满了,存储的传送数据将被送至AXI4-Stream master interface。我们这里先不使用。
ACLKEN Conversion Mode(选择NONE) :ACLKEN转换模式: 这个下拉选项为ACLKEN信号的转换模式。当ACLKEN转换执行时会消耗额外的延迟和逻辑。这个选项有:
- None - 这里没有ACLKEN信号关联于IP。
- S AXIS Only - 一个S_AXIS_ACLKEN信号关联到S_AXIS_ACLK时钟信号和没M_AXIS_ACLKEN信号。
- M AXIS Only - 一个M_AXIS_ACLKEN信号关联到M_AXIS_ACLK时钟信号和没有S_AXIS_ACLKEN信号。
- S AXIS & M AXIS - 两边时钟都有 ACLKEN信号关联到他们。
Enable ECC:Error Correction Checking ,错误纠正检查。不使用
TDATA Width(bytes): TDATA位宽(字节为最小单位), 该参数指定了所有AXI4-Stream interfaces中的TDATA信号的位宽,以字节为最小单位。该参数为整数,在0到512(IP核设置界面是256)之间。设为0将省略TDATA信号。如果TDATA信号被省略,TKEEP和TSTRB信号也会被省略。接口数据的位宽按bits计算,需要乘以8。我们这里设置1
Enable TSTRB :使能TSTRB信号 ,如果设定为Yes,这个参数指定是否在所有AXI4-Stream interfaces使用可选的TSTRB信号。这个选项只能在TDATA Width(bytes)参数大于0时才可以使能。这个信号和TKEEP一起构成了对TDATA的描述,表明当前传输的数据是有效、或是占位符或无效。
Enable TKEEP :使能TSTRB信号 ,如果设定为Yes,这个参数指定是否在所有AXI4-Stream interfaces使用可选的TKEEP信号。这个选项只能在TDATA Width(bytes)参数大于0时才可以使能。这个信号和TKEEP一起构成了对TDATA的描述,表明当前传输的数据是有效、或是占位符或无效。
Enable TLAST: 使能TLAST。如果设定为Yes,这个参数指定是否在所有AXI4-Stream interfaces使用可选的TLAST信号。对于TLAST信号要重点说明,因为在使用STREAM FIFO时TLAST的作用特别的重要。对于STREAM FIFO来说,TLAST信号的作用是指示一次传输数据流的最后一个数据,也指示着该数据流的结束。其会记录下TLAST信号的位置,及当其SLAVE接口(SFIFO的数据写入接口)的某一个数据写入的同时TLASET信号也为高的话,当MASTER接口(SFIFO的数据读出接口)读出该数据的同时也会将TLAST信号拉高。总结起来就是,进的数据有TLAST,该数据出的时候就会有TLAST。
TID Width(bits): TID位宽(比特为单位): 如果该参数大于0,这个参数指定是否在所有的AXI4-Stream interfaces中使用TID信号。值大于0省略这个信号。适用于多个AXIS接口构成的系统通信,用于区别源信号。这里不使用
TDEST Width(bits): TDEST位宽(bits): 如果该参数大于0,这个参数指定是否在所有的AXI4-Stream interfaces中使用TDEST信号。值大于0省略这个信号。适用于多个AXIS接口构成的系统通信,用于区别目标信号。这里不使用
TUSER Width(bits): TUSER 位宽(bits): 如果该参数大于0,这个参数指定是否在所有的AXI4-Stream interfaces中使用TDEST信号。值大于0省略这个信号。传输用于的定制信息,这里不使用
FLAG类的信号设置如下:
Enable write data count:使能写入数据计数,同步于写时钟
Enable almost full:使能写入几乎满,同步于写时钟
Enable programmable full:使能可编程满,同步于写时钟。可以自己设置阈值来提醒当前FIFO的写入状态
Programmable full threshold:可编程满阈值
Enable read data count:使能读取数据计数,同步于读时钟
Enable almost empty:使能读取几乎空,同步于读时钟
Enable programmable empty:使能可编程空,同步于读时钟。可以自己设置阈值来提醒当前FIFO的读取状态
Programmable empty threshold:可编程空阈值
再来看一下此时的FIFO框图:
其中除了标志信号、时钟、复位信号外,就是两个接口M_AXIS、S_AXIS。我们知道AXIS是一种半双工的总线,数据传输永远是从MASTER发送给SLAVE,所以可以判断出M_AXIS是发送接口来发送FIFO中的数据,即FIFO读取端;S_AXIS是接收接口来将数据写入FIFO中,即FIFO写入端。
2、自己编写的仿真验证
接下来我们例化一个FIFO,并依照AXIS的握手协议来对其进行仿真验证,预期实现以下功能:
- FIFO深度32,AXIS的数据位宽32位,读写时钟50M
- 先将FIFO写满,等待几个周期,将其读空
编写的Testbench如下:
-
`timescale 1ns/1ns //时间单位/精度
-
//------------<模块及端口声明>----------------------------------------
-
module tb_fifo();
-
-
reg s_axis_aresetn;
-
reg s_axis_aclk;
-
//写FIFO端口
-
reg s_axis_tvalid;
-
reg [31 : 0] s_axis_tdata;
-
reg s_axis_tlast;
-
wire [31 : 0] axis_wr_data_count;
-
wire s_axis_tready;
-
wire almost_full;
-
//读FIFO端口
-
reg m_axis_tready;
-
wire m_axis_tvalid;
-
wire [31 : 0] m_axis_tdata;
-
wire m_axis_tlast;
-
wire [31 : 0] axis_rd_data_count;
-
wire almost_empty;
-
//------------<设置初始测试条件>----------------------------------------
-
initial begin
-
s_axis_aclk = 1'b0; //初始时钟为0
-
s_axis_aresetn <= 1'b0; //初始复位
-
s_axis_tvalid <= 1'b0;
-
s_axis_tdata <= 32'd0;
-
s_axis_tlast <= 1'b0;
-
m_axis_tready <= 1'b0;
-
#60 //60个时钟周期后
-
s_axis_aresetn <= 1'b1; //拉高复位,系统进入工作状装
-
#70
-
s_axis_tvalid <= 1'b1; //拉高tvalid,准备发送信好
-
wait(s_axis_tready); //等待从机响应
-
repeat(35)begin //重复35个时钟周期
-
@(posedge s_axis_aclk)
-
s_axis_tdata <= s_axis_tdata 1; //发数据从1开始累加1
-
end
-
s_axis_tvalid <= 1'b0; //结束发送
-
m_axis_tready <= 1'b1; //拉高tready,准备接收
-
@(posedge almost_empty)
-
#20 m_axis_tready <= 1'b0; //接收完所有数据后拉低m_axis_tready
-
#40 $finish;
-
end
-
//------------<设置时钟>----------------------------------------------
-
always #10 s_axis_aclk = ~s_axis_aclk; //系统时钟周期20ns
-
-
//tlast
-
always@(posedge s_axis_aclk or negedge s_axis_aresetn ) begin
-
if(!s_axis_aresetn)
-
s_axis_tlast <= 1'b0;
-
//发送33个数据(最后一个数据)拉高
-
else if(axis_data_fifo_0_inst.s_axis_tdata == 'd33)
-
s_axis_tlast <= 1'b1;
-
else
-
s_axis_tlast <= 1'b0;
-
end
-
-
//------------<例化被测试模块>----------------------------------------
-
axis_data_fifo_0 axis_data_fifo_0_inst (
-
//系统端口
-
.s_axis_aresetn (s_axis_aresetn ), // input wire s_axis_aresetn
-
.s_axis_aclk (s_axis_aclk ), // input wire s_axis_aclk
-
//写FIFO端口
-
.s_axis_tvalid (s_axis_tvalid ), // input wire s_axis_tvalid
-
.s_axis_tready (s_axis_tready ), // output wire s_axis_tready
-
.s_axis_tdata (s_axis_tdata ), // input wire [7 : 0] s_axis_tdata
-
.s_axis_tlast (s_axis_tlast ), // input wire s_axis_tlast
-
.axis_wr_data_count (axis_wr_data_count ), // output wire [31 : 0] axis_wr_data_count
-
.almost_empty (almost_empty ), // output wire almost_empty
-
//读FIFO端口
-
.m_axis_tvalid (m_axis_tvalid ), // output wire m_axis_tvalid
-
.m_axis_tready (m_axis_tready ), // input wire m_axis_tready
-
.m_axis_tdata (m_axis_tdata ), // output wire [7 : 0] m_axis_tdata
-
.m_axis_tlast (m_axis_tlast ), // output wire m_axis_tlast
-
.axis_rd_data_count (axis_rd_data_count ), // output wire [31 : 0] axis_rd_data_count
-
.almost_full (almost_full ) // output wire almost_full
-
);
-
-
endmodule
仿真结果如下:
局部放大,写数据部分仿真图:
读数据部分仿真图:
这里对时序图不做讲解(图上的注释已经非常详尽了),只说一下FIFO的深度问题。从图中我们发现两点:
- FIFO设置的深度为32,仿真实际深度为34
- 读取FIFO时,数据并没有落后1个时钟周期
关于XILINX的FIFO IP核,有两种读取模式:standard FIFO,first word fall through。这两种模式的时序如下:
不难发现,standard FIFO模式读取数据会有一个周期的延迟;而first word fall through模式下,读取数据没有延迟。所以在本文中的FIFO都是first word fall through模式。
而这两种模式的actual depth而会有一点点区别。依然打开FIFO generator,分别选择两种模式看看实际深度的区别,如下:
可以看到standard FIFO模式的实际深度是32,而first word fall through模式的实际深度是34。这就解释了为什么我们的仿真FIFO深度是34了。
3、XILINX官方例程仿真
同其他许多IP一样,这个IP Xilinx也会我们提供example design。右击IP,选择open IP example design
点击OK
此时会新生成一个工程,该工程目录如下:
的
点击run simulation进行行为仿真,添加波形如下:
仿真结果如下所示:
过程较长,我们截取一些局部图。
下图中,FIFO复位未完成时,存在不稳定的现象 ;FIFO的写入和读取均需要等待一定的时间。
下图中:
每1个时钟周期写入1个数据 ;每2个时钟周期读取1个数据
tlast一直被拉高,代表每包数据只有一个
写入数据累加1(32‘d16843 == 32'b0000_0001_0000_0001_0000_0001_0000_0001;32‘d33686 == 32'b0000_0002_0000_0002_0000_0002_0000_0002)
下图中:
由于写时钟是读时钟的2倍,所以FIFO很快会被写满,被写满后只有等待读出数据后才能继续写入,由于写使能一直拉高,就会形成一种读写平衡状态
下图中:
一次写入一包数据,个数16个,s_axis_tlast表示写入一包数据的最后一个
下图中:
一次读出一包数据,个数16个,m_axis_tlast表示读取一包数据的最后一个
下图中:
用户拉低s_axis_tvalid信号,停止写入FIFO;继续读取FIFO;待FIFO中的数据全部被读出来后,FIFO拉低m_axis_tvalid信号,表示FIFO被读空
4、其他
- 需要整个工程的朋友可以私信或者评论留下邮箱
- 创作不易,希望各位大佬多多三连支持!一家之言,如有错误还请指正!
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgfahic
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01