基于AXI4-Stream的实时视频缩放IP设计指南
本指南详细描述如何在Xilinx FPGA上利用Video Processing Subsystem IP实现基于AXI4-Stream接口的实时视频缩放功能。文中的步骤、代码与约束均基于Vivado 2024.2及以上版本,并针对1920×1080输入至1280×720输出的典型场景展开。读者可参照本文完成从工程创建、模块设计到仿真验证与上板测试的全流程。
Quick Start
- 安装Vivado 2024.2或更高版本,确保工具链支持AXI4-Stream接口与Video Processing Subsystem IP。
- 创建Vivado工程,选择目标器件(如Xilinx Artix-7或Kintex-7系列,以实际板卡为准)。
- 添加Video Processing Subsystem IP,配置为Scaler Only模式,输入分辨率设为1920×1080,输出分辨率设为1280×720。
- 添加AXI4-Stream Data FIFO IP作为输入缓冲,深度设为2048。
- 编写顶层RTL,将FIFO输出连接到Video Processing Subsystem的s_axis_video端口,子系统输出连接到m_axis_video端口。
- 添加时钟与复位:子系统需要两个时钟(axi_clk 150MHz, video_clk 148.5MHz),复位低有效。
- 运行综合与实现,检查时序是否满足(video_clk周期6.734ns,setup slack > 0)。
- 生成比特流,下载到板卡,通过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.2 | Vivado 2023.1+ |
| 仿真器 | Vivado Simulator | 内建,支持AXI4-Stream VIP | ModelSim / Questa |
| 时钟 | axi_clk 150MHz, video_clk 148.5MHz | axi_clk用于配置与FIFO,video_clk用于视频像素 | 根据分辨率调整 |
| 复位 | 低有效 | 全局复位同步到axi_clk与video_clk | 高有效(需取反) |
| 接口依赖 | HDMI输入输出(通过DVI/HDMI IP) | 提供视频源与显示 | Camera Link / SDI |
| 约束文件 | XDC:时钟周期约束、输入输出延迟 | 必须约束所有时钟与复位 | 自动约束(不推荐) |
目标与验收标准
- 功能点:AXI4-Stream视频流输入,实时缩放后输出,分辨率从1920×1080降至1280×720(或其他比例)。
- 性能指标:视频帧率60fps,像素时钟148.5MHz,无帧丢失,无行撕裂。
- 资源与Fmax:LUT使用率合理,axi_clk频率150MHz,video_clk Fmax > 148.5MHz。
- 验收方式:仿真中验证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行:模块声明,输入板载100MHz时钟与低有效复位。
- 第2-3行:输入AXI4-Stream接口,包括数据(tdata)、有效(tvalid)、就绪(tready)、行结束(tlast)、帧起始(tuser)。
- 第4-5行:输出AXI4-Stream接口,同样包含所有信号。
- 第6-7行:内部时钟与复位信号声明。
- 第8-13行:实例化时钟生成IP,生成axi_clk(150MHz)与video_clk(148.5MHz),locked信号指示PLL锁定。
- 第14-15行:生成两个时钟域的复位信号,低有效复位取反后与locked相与,确保复位在时钟稳定后释放。
- 第16-17行:AXI4-Stream FIFO实例化,输入时钟域为axi_clk,输出时钟域为video_clk,实现跨时钟域同步。
- 第18-19行:FIFO连接,注意aresetn为低有效,因此取反rst_axi。
- 第20-21行:Video Processing Subsystem实例化,配置为Scaler,输入输出均为video_clk域。
- 第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行:创建axi_clk时钟,周期6.667ns对应150MHz,从PLL输出引脚获取。
- 第2行:创建video_clk时钟,周期6.734ns对应148.5MHz。
- 第3行:将复位寄存器标记为异步寄存器,避免CDC误报。
- 第4行:设置输入延迟2ns,模拟外部器件输出延迟。
- 第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行:仿真initial块开始,用于驱动测试序列。
- 第2-3行:通过AXI-Lite配置Video Processing Subsystem的输入/输出分辨率(代码省略,实际需调用驱动函数)。
- 第4行:等待1000个时间单位,确保配置完成。
- 第5行:外层循环,遍历1080行(输入分辨率高度)。
- 第6行:内层循环,遍历1920列(输入分辨率宽度)。
- 第7行:生成测试像素数据,此处为红色(RGB 24-bit)。
- 第8行:置位tvalid,表示数据有效。
- 第9行:当x为1919(行末)时,置位tlast表示行结束。
- 第10行:当x为0且y为0时,置位tuser表示帧起始(SOF)。
- 第11行:等待一个axi_clk时钟周期,完成像素驱动。
- 第12行:内层循环结束。
- 第13行:外层循环结束。
- 第14行:清空tvalid,停止发送数据。
- 第15行:等待5000个时间单位,让缩放处理完成。
- 第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进行调整。

评论 0