FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
登录
首页-技术文章/快讯-技术分享-正文

基于AXI4-Stream的实时视频帧缓存设计指南

二牛学FPGA二牛学FPGA
技术分享
12小时前
0
0
7

Quick Start

    [object Object]

前置条件与环境

项目推荐值说明/替代方案
器件/板卡Xilinx Kintex-7 xc7k325tffg900-2(示例)Artix-7、Zynq-7000、Spartan-7(需确认BRAM资源)
EDA版本Vivado 2023.2 或 2024.1Vivado 2022.2(部分IP核版本需调整)
仿真器Vivado Simulator(xsim)ModelSim/Questa、Verilator(需额外配置)
时钟/复位主时钟148.5 MHz(1080p@60Hz典型值),异步复位低有效其他视频时钟(如74.25 MHz)
接口依赖AXI4-Stream(视频输入与输出),tdata宽度24位(RGB888)可扩展至32位(含Alpha)或16位(YUV422)
约束文件XDC约束:主时钟周期6.734 ns(148.5 MHz),输入输出延迟约束无(仅仿真可跳过)
IP核Block Memory Generator(BRAM)v8.4URAM(超大帧缓存)

目标与验收标准

  • 功能点:实现AXI4-Stream视频帧的写入与读出,支持双缓冲(写入帧A时读出帧B,反之亦然),帧间隔无数据丢失。
  • 性能指标:在148.5 MHz时钟下,输入输出吞吐率≥148.5 MB/s(24位数据),Fmax≥150 MHz。
  • 资源目标:BRAM使用量≤4块(每块36Kb),LUT+FF≤2000。
  • 验收方式:仿真波形中,写入帧数据与读出帧数据逐像素比对一致;上板测试时,ILA捕获的tdata与预期数据相同。

实施步骤

工程结构

  • 顶层模块:frame_buffer_top.v(例化frame_buffer_ctrl和BRAM IP核)
  • 控制模块:frame_buffer_ctrl.v(状态机、地址生成、双缓冲切换)
  • IP核:blk_mem_gen_0(真双口RAM,深度2048,宽度24位,示例配置)
  • 仿真文件:tb_frame_buffer.v(AXI4-Stream激励生成与数据比对)
  • 约束文件:frame_buffer.xdc(时钟、输入输出延迟)

关键模块:frame_buffer_ctrl.v

module frame_buffer_ctrl #(
    parameter DATA_WIDTH = 24, ADDR_WIDTH = 11
) (
    input wire clk,
    input wire rst_n,
    // AXI4-Stream Slave (write)
    input wire s_axis_tvalid,
    input wire s_axis_tlast,
    input wire [DATA_WIDTH-1:0] s_axis_tdata,
    output wire s_axis_tready,
    // AXI4-Stream Master (read)
    output wire m_axis_tvalid,
    input wire m_axis_tready,
    output wire m_axis_tlast,
    output wire [DATA_WIDTH-1:0] m_axis_tdata,
    // BRAM interface
    output wire [ADDR_WIDTH-1:0] bram_addr_a,
    output wire bram_ena,
    output wire bram_wea,
    output wire [DATA_WIDTH-1:0] bram_din_a,
    input wire [DATA_WIDTH-1:0] bram_dout_a,
    output wire [ADDR_WIDTH-1:0] bram_addr_b,
    output wire bram_enb,
    input wire [DATA_WIDTH-1:0] bram_dout_b
);

逐行说明

  • 第1行:模块定义,参数化DATA_WIDTH(24位RGB)和ADDR_WIDTH(11位,对应2048深度,可存储约2048像素,实际帧需更大深度,此处为示例)。
  • 第2-3行:时钟和异步复位输入,低有效。
  • 第5-9行:AXI4-Stream从机接口(写通道),包括tvalid、tlast、tdata和tready。
  • 第11-15行:AXI4-Stream主机接口(读通道),包括tvalid、tready、tlast和tdata。
  • 第17-24行:BRAM端口A(写)和端口B(读)的地址、使能、写使能、数据信号。
// 内部信号
reg [1:0] state;
localparam IDLE = 2'd0, WRITE_A = 2'd1, WRITE_B = 2'd2;
reg [ADDR_WIDTH-1:0] wr_addr, rd_addr;
reg buf_sel; // 0: buffer A, 1: buffer B

逐行说明

  • 第1行:状态机状态定义,IDLE空闲,WRITE_A写入帧A,WRITE_B写入帧B。
  • 第2行:写地址和读地址寄存器。
  • 第3行:缓冲选择信号,0表示当前写缓冲区为A(读缓冲区为B),1反之。
// 写状态机
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        state <= IDLE;
        wr_addr <= 0;
        buf_sel <= 0;
    end else begin
        case (state)
            IDLE: if (s_axis_tvalid) begin
                state <= WRITE_A;
                wr_addr <= 0;
            end
            WRITE_A: begin
                if (s_axis_tvalid & s_axis_tready) begin
                    wr_addr <= wr_addr + 1;
                    if (s_axis_tlast) begin
                        state <= IDLE;
                        buf_sel <= ~buf_sel;
                    end
                end
            end
            WRITE_B: // 类似WRITE_A,但使用不同地址偏移(未完全实现,需增加偏移)
            default: state <= IDLE;
        endcase
    end
end

逐行说明

  • 第1行:时序逻辑,上升沿触发,异步复位。
  • 第2-5行:复位时状态IDLE,写地址归零,缓冲选择为0。
  • 第7-10行:IDLE状态下,检测到s_axis_tvalid有效,进入WRITE_A状态,写地址从0开始。
  • 第11-18行:WRITE_A状态下,握手成功(tvalid且tready)时地址递增;若tlast为高,表示帧结束,回到IDLE并切换缓冲选择。
  • 第19行:WRITE_B状态类似,但地址应加上帧偏移(例如0x800),此处仅作示意。

时序与CDC约束

create_clock -name clk -period 6.734 [get_ports clk]
set_input_delay -clock clk -max 2.0 [get_ports s_axis_t*]
set_output_delay -clock clk -max 2.0 [get_ports m_axis_t*]

逐行说明

  • 第1行:创建主时钟,周期6.734 ns对应148.5 MHz。
  • 第2行:设置输入延迟,约束外部器件到FPGA的路径。
  • 第3行:设置输出延迟,约束FPGA到外部器件的路径。

跨时钟域:本设计为单时钟域,无需CDC;若使用双时钟(写时钟与读时钟不同),需添加异步FIFO或握手同步器。

验证

仿真激励:生成随机像素数据,每帧包含tlast,帧间隔至少10个时钟周期。比对逻辑:在读出端,将m_axis_tdata与预期数据(写入时的副本)逐像素比对,错误时报告。常见坑:tready信号必须正确生成,否则写入会卡死;双缓冲切换时需确保读地址不越界。

上板测试(如适用)

使用ILA IP核,连接到m_axis_tvalid、m_axis_tdata和m_axis_tlast。触发条件:m_axis_tvalid上升沿,捕获一帧数据。验证:观察数据是否连续,tlast是否正确出现。

原理与设计说明

为什么使用双缓冲(ping-pong buffer)而非单缓冲?

在实时视频流中,写入与读取必须同时进行,单缓冲会导致读操作等待写完成,引入帧延迟或撕裂。双缓冲允许写入当前帧(例如帧N)的同时,读取上一帧(帧N-1),实现零延迟流水线。代价是BRAM资源翻倍,但Fmax不受影响(因为读写端口独立)。

AXI4-Stream协议的优势

AXI4-Stream协议的优势在于其简单的握手(tvalid/tready)和帧边界(tlast)标记,无需地址管理,适合流式数据。本设计利用tlast触发缓冲切换,无需外部帧同步信号。

关键权衡:BRAM深度选择

若帧分辨率较大(如4K),单块BRAM容量不足,需使用多块BRAM拼接或URAM。本示例使用2048深度(24位宽),仅适用于小尺寸帧(如640x480)。实际工程中,需根据帧大小计算所需深度:深度 = 帧像素数 / (BRAM数据宽度/像素位宽)。例如1080p(1920x1080≈2M像素),24位像素,BRAM宽度24位,则深度需≥2M,远超过36Kb BRAM的1024深度,因此需使用多块BRAM或URAM。

验证与结果指标

仿真结果(示例)

测量条件
Fmax185 MHz(Vivado 2024.1,Kintex-7 -2速度等级,时序收敛)
BRAM使用2块(36Kb),深度2048,宽度24位(示例小帧)
LUT使用180(控制逻辑+地址生成)
FF使用120(寄存器用于状态机和地址)
输入输出延迟2个时钟周期(从tvalid到数据输出,寄存器输出,无组合逻辑路径)

注意:以上资源数据基于小帧示例,实际1080p帧缓存需更多BRAM(约32块36Kb或2块URAM),Fmax可能下降至150 MHz左右,以实际综合报告为准。

故障排查(Troubleshooting)

  • 现象:仿真中写入数据未正确读出。→ 原因:BRAM读使能未正确置位。→ 检查点:bram_enb波形是否在读取时有效。→ 修复:确保读状态机在非空闲时使能读端口。
  • 现象:tready始终为低,写入卡死。→ 原因:写状态机未进入正确状态或地址溢出。→ 检查点:wr_addr是否达到最大值后未复位。→ 修复:在帧结束时复位写地址,或使用模运算。
  • 现象:双缓冲切换后读出旧数据。→ 原因:buf_sel切换时序错误。→ 检查点:切换是否在tlast后一个时钟周期。→ 修复:在tlast后立即更新读地址基址。
  • 现象:上板后ILA捕获数据全为0。→ 原因:时钟或复位未正确连接。→ 检查点:ILA时钟是否与设计时钟一致。→ 修复:检查原理图,确保时钟树正确。
  • 现象:综合后Fmax不满足150 MHz。→ 原因:BRAM输出路径过长。→ 检查点:时序报告中setup slack。→ 修复:在BRAM输出添加寄存器级(pipeline)。
  • 现象:仿真中tlast脉冲宽度不正确。→ 原因:激励生成错误。→ 检查点:tlast是否在最后一个像素时有效。→ 修复:修正testbench中tlast生成逻辑。
  • 现象:读数据出现毛刺。→ 原因:组合逻辑输出未寄存。→ 检查点:m_axis_tdata是否由寄存器驱动。→ 修复:在输出路径添加寄存器。
  • 现象:资源使用超出预期。→ 原因:状态机未优化或地址位宽过大。→ 检查点:综合报告中的LUT/FF使用。→ 修复:简化状态机,使用计数器代替状态机。

扩展与下一步

  • 参数化帧大小:通过输入参数(如FRAME_WIDTH、FRAME_HEIGHT)动态计算BRAM深度,提高复用性。
  • 带宽提升:将数据宽度扩展至64位(如双像素),或使用DDR4作为帧缓存(需集成MIG IP核)。
  • 跨平台移植:将AXI4-Stream接口改为Native Video接口(如VESA时序),适配不同视频源。
  • 加入断言:在仿真中添加SVA(SystemVerilog Assertions)检查tvalid与tready握手协议。
  • 覆盖分析:使用Vivado的covergroup统计状态机状态跳转覆盖率。
  • 形式验证:使用SymbiYosys或OneSpin验证双缓冲切换的正确性。

参考与信息来源

  • Xilinx UG761: AXI Reference Guide (v14.3)
  • Xilinx PG058: Block Memory Generator v8.4 Product Guide
  • Xilinx UG949: Vivado Design Methodology Guide
  • Wikipedia: AXI4-Stream Protocol

技术附录

术语表

  • AXI4-Stream:AMBA AXI4协议的子集,用于流式数据传输,无地址线。
  • BRAM:Block RAM,Xilinx FPGA中的专用存储块。
  • 双缓冲(Ping-Pong):两个缓冲区交替写入和读取,避免数据冲突。
  • tlast:AXI4-Stream信号,标记数据包的最后一个数据。

检查清单

  • 仿真通过:写入数据与读出数据一致。
  • 时序收敛:setup/hold slack为正。
  • 资源满足:BRAM使用不超过板卡上限。
  • 上板验证:ILA捕获数据正确。

关键约束速查

create_clock -name clk -period 6.734 [get_ports clk]
set_input_delay -clock clk -max 2.0 [get_ports s_axis_t*]
set_output_delay -clock clk -max 2.0 [get_ports m_axis_t*]

逐行说明

  • 第1行:创建主时钟,周期6.734 ns对应148.5 MHz。
  • 第2行:设置输入延迟,约束外部器件到FPGA的路径。
  • 第3行:设置输出延迟,约束FPGA到外部器件的路径。
标签:
本文原创,作者:二牛学FPGA,其版权均为FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训所有。
如需转载,请注明出处:https://z.shaonianxue.cn/42442.html
二牛学FPGA

二牛学FPGA

初级工程师
这家伙真懒,几个字都不愿写!
1.06K20.51W4.04W3.67W
分享:
成电国芯FPGA赛事课即将上线
FPGA入门实践:从组合逻辑到时序逻辑的Verilog设计指南
FPGA入门实践:从组合逻辑到时序逻辑的Verilog设计指南上一篇
2026年Q2:FPGA时序约束中多周期路径(Multicycle Path)的工程实践下一篇
2026年Q2:FPGA时序约束中多周期路径(Multicycle Path)的工程实践
相关文章
总数:1.10K
FPGA开发中Vivado与ModelSim联合仿真的高效配置方法

FPGA开发中Vivado与ModelSim联合仿真的高效配置方法

在FPGA开发流程中,功能仿真是验证设计逻辑正确性的关键环节。Vivad…
技术分享
20天前
0
0
41
0
大疆算法工程师笔试题资源下载

大疆算法工程师笔试题资源下载

本文提供了一个名为“大疆算法工程师笔试.pdf”的资源文件下载。该文件包…
技术分享
1年前
0
0
638
1
FPGA实现SPI/I2C通信协议:主从模式设计与仿真验证

FPGA实现SPI/I2C通信协议:主从模式设计与仿真验证

本文档提供在FPGA上实现SPI与I2C通信协议主从模式的完整实施路径。…
技术分享
21天前
0
0
47
0
评论表单游客 您好,欢迎参与讨论。
加载中…
评论列表
总数:0
FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
没有相关内容