跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
编程语言

Vivado AXI4-Stream Data FIFO 核配置与测试详解

综述由AI生成Vivado AXI4-Stream Data FIFO 核配置涉及深度、存储类型、时钟同步及包模式等关键参数。独立时钟选项支持跨时钟域设计,ECC 校验增强可靠性。读写标志位如几乎满、可编程阈值用于流控管理。Testbench 验证了写入速度差异、TLAST 信号逻辑及并发读写状态,仿真结果符合预期,展示了 AXI Stream 接口的缓存与握手机制。

星星泡饭发布于 2026/4/7更新于 2026/5/2417 浏览
Vivado AXI4-Stream Data FIFO 核配置与测试详解

Vivado AXI4-Stream Data FIFO 核配置与测试详解

image

FIFO depth (FIFO 深度): 定义了 FIFO 能存储多少个数据字(Data Words)。

注意:实际占用的存储资源取决于深度乘以数据宽度(TDATA width)。

Memory type (存储器类型): Auto

  • 决定用 FPGA 内部的哪种资源来实现 FIFO。
  • Auto: 让 Vivado 综合工具根据 FIFO 的大小自动选择(通常小 FIFO 用分布式 RAM/LUTRAM,大 FIFO 用块 RAM/BRAM)。
  • Block RAM: 强制使用 BRAM。
  • Distributed RAM: 强制使用 LUT 搭建的 RAM。
  • UltraRAM: 针对 UltraScale+ 系列的特殊大容量 RAM。

Independent clocks (独立时钟): No

  • No (同步 FIFO): 写入侧(Slave)和读取侧(Master)使用同一个时钟信号 (s_axis_aclk)。这消耗资源较少,延迟较低。
  • Yes (异步 FIFO): 启用跨时钟域功能。输入和输出可以使用不同频率的时钟。此时界面左侧的端口图会显示 s_axis_aclk (写时钟) 和 m_axis_aclk (读时钟)。

CDC sync stages (跨时钟域同步级数): 3 (灰色不可选)

只有当选择了'Independent clocks: Yes'时才有效。它定义了用于同步信号的寄存器级数,通常用于防止亚稳态。

Enable packet mode (启用包模式): No

  • No: 普通 FIFO 模式。只要 FIFO 里有数据,Master 端就会尝试输出。
  • Yes: FIFO 会等到接收到一个完整的数据包(即收到 TLAST 信号)后,才开始向 Master 端输出数据。这用于防止数据包在传输中间断流(Underrun),但会增加延迟。

ACLKEN conversion mode: None,用于控制时钟使能信号的处理方式。通常保持默认 None 即可。

Enable ECC (启用 ECC 校验): No,是否启用错误检查和纠正(Error Correction Code)。启用后会增加逻辑资源,用于检测和修复位翻转错误。


TDATA width (bytes) (数据位宽): 1

  • 定义主要数据总线 TDATA 的宽度。设为 1 byte,也就是 8 bits。这意味着每个时钟周期传输 8 位数据。

Enable TSTRB (启用 TSTRB 信号): No,TSTRB (Strobe) 用于指示哪些字节是有效的位置选通信号。对于纯数据流通常不需要。

Enable TKEEP (启用 TKEEP 信号): No,TKEEP (Keep) 用于指示数据流中的哪些字节是有效的(通常用于处理非对齐的数据包尾部)。

Enable TLAST (启用 TLAST 信号): No,TLAST 用于指示一个数据包(Packet)的结束。

设为 No,意味着这个 FIFO 认为数据是无限连续的流,没有'包'的概念。如果需要划分帧或包,必须选 Yes。

TID / TDEST / TUSER width (bits): 0

  • 这些是 AXI-Stream 的边带信号(ID、Destination、User data)。
  • 设为 0 表示不使用这些信号,它们不会出现在 IP 核的端口上,也不会被 FIFO 缓存。

image

Write flags(写入侧标志位)

Enable write data count (启用写入数据计数): Yes,勾选后,IP 核会增加一个输出端口 axis_wr_data_count。这个信号会实时输出 FIFO 中当前存储了多少个数据字(Data Words)。写入侧的逻辑可以读取这个值,精确判断 FIFO 里还有多少空间。

Enable almost full (启用'将满'信号): Yes,勾选后,IP 核会增加一个输出端口 almost_full。当 FIFO 只剩下一个写入位置时,这个信号就会变高。它是一个紧急警告信号,告诉前级电路'再写一个我就满了',通常比标准的 TREADY 变低(表示已满)提前一个周期提示。

Enable programmable full (启用可编程满信号): No,是否启用一个自定义阈值的'满'信号 (prog_full)。

如果选 Yes:你可以在下方的 Programmable full threshold 框中填入一个数字(例如 400)。当 FIFO 里的数据量达到或超过 400 时,prog_full 信号就会变高。这用于需要比'将满'更早进行流控的场景。

Read flags(读取侧标志位)

Enable read data count (启用读取数据计数): Yes,勾选后,IP 核会增加一个输出端口 axis_rd_data_count。实时输出 FIFO 中当前有多少个数据等待被读取。

注意: 如果使用的是独立时钟(异步 FIFO),write data count 和 read data count 分别属于写入时钟域和读取时钟域,数值可能略有延迟差异。如果是同步 FIFO,这两个值通常是一样的。

Enable almost empty (启用'将空'信号): Yes,勾选后,IP 核会增加一个输出端口 almost_empty。当 FIFO 只剩下一个数据可读时,这个信号就会变高。提示后级电路数据流即将断档。

Enable programmable empty (启用可编程空信号): No,是否启用一个自定义阈值的'空'信号 (prog_empty)。

如果选 Yes:可以在下方的 Programmable empty threshold 填入数字(例如 10)。当 FIFO 数据量少于等于 10 时,该信号变高。

选项与 FIFO 很类似,可以参考 FIFO 的使用。

可以直接打开官方的例程进行仿真:

image

1、写的速度是读的 2 倍:

这部分主要是因为从的程序:

always @(posedge aclk) begin if(areset) ... else begin s_axis_tready <= ~s_axis_tready; // 核心逻辑:每周期翻转一次 end end 

可以看到,s_axis_tready 信号在 0 和 1 之间不断跳变。这意味着接收端一会儿说'我满了',一会儿说'我可以收'。人为制造总线拥塞(Backpressure)。这强迫上游的 FIFO 必须将数据存入内部 RAM,从而验证 FIFO 的缓存功能和满标志逻辑是否正常工作。

2、tlast 一直为 1 是因为:代码逻辑显式地在复位后将其置 1。

image

3、快满以后,读跟写的间隔变为一致。

image

自测

可以直接编写一个 testbench:

`timescale 1ns / 1ps
module tb_axis_data_fifo();
//-------------------------------------------------------------------------
// 1. 信号定义
//-------------------------------------------------------------------------
// 时钟与复位
reg clk;
reg resetn;
// Slave 接口 (写入端)
reg s_axis_tvalid;
wire s_axis_tready;
reg [7:0] s_axis_tdata;
reg s_axis_tlast;
// Master 接口 (读取端)
wire m_axis_tvalid;
reg m_axis_tready;
wire [7:0] m_axis_tdata;
wire m_axis_tlast;
// 状态信号
wire [31:0] axis_wr_data_count;
wire [31:0] axis_rd_data_count;
wire almost_empty;
wire almost_full;
//-------------------------------------------------------------------------
// 2. DUT (Device Under Test) 实例化
//-------------------------------------------------------------------------
axis_data_fifo_0 dut (
    .s_axis_aresetn (resetn), // input wire s_axis_aresetn
    .s_axis_aclk (clk), // input wire s_axis_aclk
    // 写端口 (Slave)
    .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
    // 读端口 (Master)
    .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_wr_data_count (axis_wr_data_count), // output wire [31 : 0] axis_wr_data_count
    .axis_rd_data_count (axis_rd_data_count), // output wire [31 : 0] axis_rd_data_count
    .almost_empty (almost_empty), // output wire almost_empty
    .almost_full (almost_full) // output wire almost_full
);
//-------------------------------------------------------------------------
// 3. 时钟生成 (100MHz)
//-------------------------------------------------------------------------
initial begin
    clk = 0;
    forever #5 clk = ~clk; // 周期 10ns
end
//-------------------------------------------------------------------------
// 4. 辅助任务:发送数据包
//-------------------------------------------------------------------------
// 参数:发送的数据个数
task write_packet(input [31:0] length);
integer i;
begin
    @(posedge clk); // 同步到时钟沿
    wait(resetn == 1);
    $display("[Writer] Start writing packet of length %0d at time %0t", length, $time);
    for (i = 0; i < length; i = i + 1) begin
        s_axis_tvalid <= 1'b1;
        s_axis_tdata <= i[7:0]; // 数据内容就是简单的 0, 1, 2...
        // 如果是最后一个数据,拉高 tlast
        if (i == length - 1) s_axis_tlast <= 1'b1;
        else s_axis_tlast <= 1'b0; // 等待握手成功 (tvalid & tready 均为高)
        do begin
            @(posedge clk);
        end while (s_axis_tready == 1'b0); // 如果 FIFO 满,tready 会拉低,这里会阻塞等待
    end
    // 发送完毕,拉低信号
    s_axis_tvalid <= 1'b0;
    s_axis_tlast <= 1'b0;
    $display("[Writer] Packet writing finished at time %0t", $time);
end
endtask
//-------------------------------------------------------------------------
// 5. 主测试激励 (Stimulus)
//-------------------------------------------------------------------------
initial begin
    // 初始化信号
    resetn = 0;
    s_axis_tvalid = 0;
    s_axis_tdata = 0;
    s_axis_tlast = 0;
    m_axis_tready = 0;
    // 初始状态下不读取数据,为了测试 Full 信号
    // 1. 复位序列
    $display("--- Test Start: Reset ---");
    #100;
    resetn = 1;
    #20;
    // 2. 写入测试:在不读取的情况下写入数据
    // 假设 FIFO 深度较小,或者我们只是为了观察 Wr_count 增加
    // 此时 m_axis_tready = 0,数据会堆积在 FIFO 中
    $display("--- Test Phase 1: Write only (Fill FIFO) ---");
    write_packet(16); // 写入 16 个数据
    // 观察一段时间状态
    #50;
    $display("Status Check: WR Count = %0d, RD Count = %0d, Almost Full = %b", axis_wr_data_count, axis_rd_data_count, almost_full);
    // 3. 读取测试:打开读使能,排出数据
    $display("--- Test Phase 2: Enable Read (Drain FIFO) ---");
    @(posedge clk);
    m_axis_tready = 1; // 允许读取
    // 等待数据读完(简单起见,延时等待)
    wait(axis_rd_data_count == 0 && m_axis_tvalid == 0);
    #100;
    // 4. 并发读写测试
    $display("--- Test Phase 3: Concurrent Read & Write ---");
    m_axis_tready = 1; // 保持读取开启
    write_packet(32); // 再次写入 32 个数据
    #200;
    $display("--- Test Finished ---");
    $stop;
end
//-------------------------------------------------------------------------
// 6. 监控模块 (Monitor):打印读出的数据
//-------------------------------------------------------------------------
always @(posedge clk) begin
    if (m_axis_tvalid && m_axis_tready) begin
        $display("[Reader] Read Data: %h (Last: %b) at time %0t", m_axis_tdata, m_axis_tlast, $time);
    end
end
endmodule

仿真结果:

image

符合预期。其实就是两个 AXI 接口分别负责读和写,stream 相对来说比较简单。

目录

  1. Vivado AXI4-Stream Data FIFO 核配置与测试详解
  2. 自测
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 统一 OpenAI API 格式调用 20+ 主流大模型方案
  • 扣子(Coze)Skills+OpenClaw 实战:构建 AI 智能体自动化技能
  • 基于 Web 的校园活动管理系统设计与实现
  • VirtualBox 搭建 Ubuntu 虚拟机完整实战指南
  • 浏览器端 AI 绘画:Deeplearn.js 风格迁移技术解析
  • Stable Diffusion 3 发布:20 亿参数 Medium 模型与 MMDiT 架构解析
  • ChatGPT / Gemini / Spotify 教育权益自动化验证指南
  • 零基础入门网络安全学习路径与实战指南
  • GLM-4 开源发布:9B 模型性能超越 Llama-3
  • 网络安全行业自学、跳槽与转行建议
  • 网络安全自学指南:从基础到实战的系统化学习路径
  • 网络安全基础概念、核心领域及常见威胁解析
  • ChatGPT、Gemini 与 Spotify 教育版权益介绍
  • 数据结构与算法实战:LeetCode 移除元素与合并有序数组
  • 数据结构:栈、队列、二叉树与哈希表
  • 使用 Telegram 机器人自动化完成 SheerID 身份认证获取教育权益
  • 2026 年值得关注的十大 JavaScript 框架
  • AI Agent 架构:基础组成模块深度解析
  • 基于 AI 辅助的在线考试系统全流程开发实战
  • MasterGo 设计稿转前端代码:基于 TRAE CN 与 MCP 协议实战

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online