基于AXI4-Stream的实时视频缩放IP设计指南(2026年7月版)

FPGA小白
文章2026-07-01
34 0 0 0

基于AXI4-Stream的实时视频缩放IP设计指南

本指南详细描述如何在Xilinx FPGA上利用Video Processing Subsystem IP实现基于AXI4-Stream接口的实时视频缩放功能。文中的步骤、代码与约束均基于Vivado 2024.2及以上版本,并针对1920×1080输入至1280×720输出的典型场景展开。读者可参照本文完成从工程创建、模块设计到仿真验证与上板测试的全流程。

Quick Start

  1. 安装Vivado 2024.2或更高版本,确保工具链支持AXI4-Stream接口与Video Processing Subsystem IP。
  2. 创建Vivado工程,选择目标器件(如Xilinx Artix-7或Kintex-7系列,以实际板卡为准)。
  3. 添加Video Processing Subsystem IP,配置为Scaler Only模式,输入分辨率设为1920×1080,输出分辨率设为1280×720。
  4. 添加AXI4-Stream Data FIFO IP作为输入缓冲,深度设为2048。
  5. 编写顶层RTL,将FIFO输出连接到Video Processing Subsystem的s_axis_video端口,子系统输出连接到m_axis_video端口。
  6. 添加时钟与复位:子系统需要两个时钟(axi_clk 150MHz, video_clk 148.5MHz),复位低有效。
  7. 运行综合与实现,检查时序是否满足(video_clk周期6.734ns,setup slack > 0)。
  8. 生成比特流,下载到板卡,通过HDMI输出观察缩放后图像(预期:1920×1080输入,1280×720输出,无撕裂)。

前置条件与环境

项目推荐值说明替代方案
器件/板卡Xilinx Artix-7 XC7A200T支持Video Processing Subsystem,LUT资源充足Kintex-7 / Zynq-7000
EDA版本Vivado 2024.2包含Video Processing Subsystem v8.2Vivado 2023.1+
仿真器Vivado Simulator内建,支持AXI4-Stream VIPModelSim / Questa
时钟axi_clk 150MHz, video_clk 148.5MHzaxi_clk用于配置与FIFO,video_clk用于视频像素根据分辨率调整
复位低有效全局复位同步到axi_clk与video_clk高有效(需取反)
接口依赖HDMI输入输出(通过DVI/HDMI IP)提供视频源与显示Camera Link / SDI
约束文件XDC:时钟周期约束、输入输出延迟必须约束所有时钟与复位自动约束(不推荐)

目标与验收标准

  1. 功能点:AXI4-Stream视频流输入,实时缩放后输出,分辨率从1920×1080降至1280×720(或其他比例)。
  2. 性能指标:视频帧率60fps,像素时钟148.5MHz,无帧丢失,无行撕裂。
  3. 资源与Fmax:LUT使用率合理,axi_clk频率150MHz,video_clk Fmax > 148.5MHz。
  4. 验收方式:仿真中验证tvalid/tready握手,检查输出分辨率;上板通过HDMI观察图像质量,使用ChipScope抓取AXI4-Stream信号确认时序。

实施步骤

工程结构

创建Vivado工程,添加以下源文件:顶层模块(top.v)、时钟生成模块(clk_wiz.xci)、Video Processing Subsystem IP(v_vid_scale.xci)、AXI4-Stream FIFO(axis_fifo.xci)。约束文件(top.xdc)包含所有时钟与复位约束。仿真文件(tb_top.sv)提供AXI4-Stream激励与检查。

关键模块:顶层RTL

module top (
    input wire clk_100m,          // 板载100MHz时钟
    input wire rst_n,             // 低有效复位
    // AXI4-Stream 输入(来自HDMI RX)
    input wire [23:0] s_axis_tdata,
    input wire s_axis_tvalid,
    output wire s_axis_tready,
    input wire s_axis_tlast,
    input wire s_axis_tuser,      // SOF
    // AXI4-Stream 输出(到HDMI TX)
    output wire [23:0] m_axis_tdata,
    output wire m_axis_tvalid,
    input wire m_axis_tready,
    output wire m_axis_tlast,
    output wire m_axis_tuser
);

// 时钟与复位生成
wire axi_clk, video_clk, clk_locked;
clk_wiz_0 u_clk_wiz (
    .clk_in1 (clk_100m),
    .clk_out1 (axi_clk),      // 150MHz
    .clk_out2 (video_clk),    // 148.5MHz
    .locked (clk_locked)
);

wire rst_axi, rst_video;
assign rst_axi   = ~rst_n | ~clk_locked;
assign rst_video = ~rst_n | ~clk_locked;

// AXI4-Stream FIFO 输入缓冲
wire [23:0] fifo_tdata;
wire fifo_tvalid, fifo_tready, fifo_tlast, fifo_tuser;
axis_data_fifo_0 u_fifo (
    .s_axis_aclk    (axi_clk),
    .s_axis_aresetn (~rst_axi),
    .s_axis_tdata   (s_axis_tdata),
    .s_axis_tvalid  (s_axis_tvalid),
    .s_axis_tready  (s_axis_tready),
    .s_axis_tlast   (s_axis_tlast),
    .s_axis_tuser   (s_axis_tuser),
    .m_axis_aclk    (video_clk),
    .m_axis_aresetn (~rst_video),
    .m_axis_tdata   (fifo_tdata),
    .m_axis_tvalid  (fifo_tvalid),
    .m_axis_tready  (fifo_tready),
    .m_axis_tlast   (fifo_tlast),
    .m_axis_tuser   (fifo_tuser)
);

// Video Processing Subsystem (Scaler)
wire [23:0] scaler_tdata;
wire scaler_tvalid, scaler_tready, scaler_tlast, scaler_tuser;
v_vid_scale_0 u_scaler (
    .aclk               (video_clk),
    .aclken             (1'b1),
    .aresetn            (~rst_video),
    .s_axis_video_tdata  (fifo_tdata),
    .s_axis_video_tvalid (fifo_tvalid),
    .s_axis_video_tready (fifo_tready),
    .s_axis_video_tlast  (fifo_tlast),
    .s_axis_video_tuser  (fifo_tuser),
    .m_axis_video_tdata  (scaler_tdata),
    .m_axis_video_tvalid (scaler_tvalid),
    .m_axis_video_tready (scaler_tready),
    .m_axis_video_tlast  (scaler_tlast),
    .m_axis_video_tuser  (scaler_tuser)
);

// 输出直接连接(可添加输出FIFO)
assign m_axis_tdata  = scaler_tdata;
assign m_axis_tvalid = scaler_tvalid;
assign scaler_tready = m_axis_tready;
assign m_axis_tlast  = scaler_tlast;
assign m_axis_tuser  = scaler_tuser;

endmodule

逐行说明

  1. 第1行:模块声明,输入板载100MHz时钟与低有效复位。
  2. 第2-3行:输入AXI4-Stream接口,包括数据(tdata)、有效(tvalid)、就绪(tready)、行结束(tlast)、帧起始(tuser)。
  3. 第4-5行:输出AXI4-Stream接口,同样包含所有信号。
  4. 第6-7行:内部时钟与复位信号声明。
  5. 第8-13行:实例化时钟生成IP,生成axi_clk(150MHz)与video_clk(148.5MHz),locked信号指示PLL锁定。
  6. 第14-15行:生成两个时钟域的复位信号,低有效复位取反后与locked相与,确保复位在时钟稳定后释放。
  7. 第16-17行:AXI4-Stream FIFO实例化,输入时钟域为axi_clk,输出时钟域为video_clk,实现跨时钟域同步。
  8. 第18-19行:FIFO连接,注意aresetn为低有效,因此取反rst_axi。
  9. 第20-21行:Video Processing Subsystem实例化,配置为Scaler,输入输出均为video_clk域。
  10. 第22-23行:子系统输出直接连接到顶层输出,tready从外部输入。

时序与CDC约束

# 时钟约束
create_clock -name axi_clk -period 6.667 [get_pins u_clk_wiz/inst/clk_out1]
create_clock -name video_clk -period 6.734 [get_pins u_clk_wiz/inst/clk_out2]

# 复位约束
set_property ASYNC_REG true [get_cells -hier -filter {NAME =~ *rst_axi*}]
set_property ASYNC_REG true [get_cells -hier -filter {NAME =~ *rst_video*}]

# 输入输出延迟(示例值,以实际PCB为准)
set_input_delay -clock [get_clocks axi_clk] 2.0 [get_ports s_axis_*]
set_output_delay -clock [get_clocks video_clk] 2.0 [get_ports m_axis_*]

逐行说明

  1. 第1行:创建axi_clk时钟,周期6.667ns对应150MHz,从PLL输出引脚获取。
  2. 第2行:创建video_clk时钟,周期6.734ns对应148.5MHz。
  3. 第3行:将复位寄存器标记为异步寄存器,避免CDC误报。
  4. 第4行:设置输入延迟2ns,模拟外部器件输出延迟。
  5. 第5行:设置输出延迟2ns,模拟外部器件建立时间要求。

验证:仿真测试

// 仿真顶层简化片段
initial begin
    // 配置Video Processing Subsystem(通过AXI-Lite)
    // 设置输入分辨率1920x1080,输出1280x720
    // 此处省略AXI-Lite驱动代码
    #1000;
    // 发送一帧视频数据
    for (int y=0; y<1080; y++) begin
        for (int x=0; x<1920; x++) begin
            // 生成测试像素数据(如彩条)
            s_axis_tdata <= {8'hFF, 8'h00, 8'h00}; // 红色
            s_axis_tvalid <= 1;
            s_axis_tlast <= (x == 1919) ? 1 : 0;
            s_axis_tuser <= (x == 0 && y == 0) ? 1 : 0;
            @(posedge axi_clk);
        end
    end
    s_axis_tvalid <= 0;
    // 等待输出完成
    #5000;
    $finish;
end

逐行说明

  1. 第1行:仿真initial块开始,用于驱动测试序列。
  2. 第2-3行:通过AXI-Lite配置Video Processing Subsystem的输入/输出分辨率(代码省略,实际需调用驱动函数)。
  3. 第4行:等待1000个时间单位,确保配置完成。
  4. 第5行:外层循环,遍历1080行(输入分辨率高度)。
  5. 第6行:内层循环,遍历1920列(输入分辨率宽度)。
  6. 第7行:生成测试像素数据,此处为红色(RGB 24-bit)。
  7. 第8行:置位tvalid,表示数据有效。
  8. 第9行:当x为1919(行末)时,置位tlast表示行结束。
  9. 第10行:当x为0且y为0时,置位tuser表示帧起始(SOF)。
  10. 第11行:等待一个axi_clk时钟周期,完成像素驱动。
  11. 第12行:内层循环结束。
  12. 第13行:外层循环结束。
  13. 第14行:清空tvalid,停止发送数据。
  14. 第15行:等待5000个时间单位,让缩放处理完成。
  15. 第16行:结束仿真。

验证结果

仿真中应观察到以下行为:

  • 输入AXI4-Stream握手正常,tvalid与tready交替有效。
  • 输出分辨率正确:每帧行数720,每行像素1280。
  • 输出tlast与tuser信号与帧/行边界对齐。
  • 无数据丢失或重复像素。

上板测试时,通过HDMI显示器观察,图像应清晰无撕裂,缩放比例正确。

排障

  • 时序违例:检查时钟约束是否正确,PLL输出频率是否匹配,必要时降低video_clk频率或增加流水线级数。
  • 图像撕裂:确认FIFO深度足够(至少能缓存一行像素),检查tuser信号是否在帧首正确置位。
  • 无输出:使用ChipScope观察scaler_tvalid与scaler_tready,确认握手是否进行;检查复位信号是否释放。
  • 分辨率错误:验证AXI-Lite配置寄存器写入值是否正确,特别是输入/输出宽度与高度。

扩展

  • 多分辨率支持:通过AXI-Lite动态修改Video Processing Subsystem的配置寄存器,实现运行时切换分辨率。
  • 色彩空间转换:在缩放前后添加Color Correction或Gamma校正IP,提升图像质量。
  • 输出FIFO:在Scaler输出与HDMI TX之间添加FIFO,隔离时钟域或匹配带宽。
  • 多通道缩放:使用多个Video Processing Subsystem实例,实现画中画或分屏显示。

参考

  • Xilinx PG231: Video Processing Subsystem v8.2 Product Guide
  • Xilinx UG902: Vivado Design Suite User Guide: Using Constraints
  • Xilinx PG085: AXI4-Stream Infrastructure IP Suite v3.0

附录

本指南中使用的IP版本与Vivado 2024.2绑定。若使用更早版本,部分IP接口名称或配置选项可能略有差异,请参考对应版本的Product Guide进行调整。

分类
技术分享
标签
AXI4-StreamIP设计实时视频缩放
浏览 34收藏 0赞 0评论 0
分享:

相关推荐

同频道 · 相近分类

暂无相关推荐

作者

FPGA小白查看主页

同分类阅读

文章

延伸阅读与实操

  • 文章 + 课程联动深度文章常对应体系课章节,可一键选课。
  • 学习产出可参考笔记与作业案例在学习产出广场持续更新。

探索全站