1. 项目概述:四路视频拼接系统设计
这个FPGA视频拼接项目实现了一个相当实用的多路视频处理系统,能够将三种不同规格的视频源(HDMI 1920x1080@60、摄像头960x540@30、以太网960x540)实时处理并拼接成统一的四画面输出。其中HDMI信号被复用一次,形成两个画面源。整个系统基于紫光同创的盘古-50K FPGA开发平台,使用PDS 2022.1开发工具链实现。
在实际工程应用中,这种视频拼接技术常见于安防监控、视频会议和多画面展示等场景。与市面上现成的视频处理IP核不同,这个方案从底层开始构建,对视频流的处理更加灵活可控,特别适合需要高度定制化的应用场景。
2. 系统架构设计
2.1 整体数据流设计
系统采用典型的三级流水线架构:
- 前端输入处理:负责不同视频源的接收和格式统一
- 中间存储缓冲:通过DDR3实现视频帧缓存
- 后端拼接输出:生成最终的四画面拼接视频
这种架构的优势在于:
- 解耦了输入处理和输出显示,使系统能够处理不同步的视频源
- 通过DDR3缓冲解决了不同帧率视频源之间的同步问题
- 各模块可以独立优化,提高整体性能
2.2 硬件平台选型考量
选择紫光同创盘古-50K平台主要基于以下几点考虑:
- 资源充足:50K LUTs规模足够实现复杂的视频处理流水线
- DDR3支持:板载DDR3颗粒提供足够带宽处理四路视频流
- 丰富IO:支持多种视频输入输出接口
- 国产化:符合当前国产芯片替代的趋势
3. 核心模块实现细节
3.1 视频缩放模块
视频缩放是系统第一个关键环节,需要将不同分辨率的输入统一为960x540。以HDMI信号处理为例:
verilog复制scaler #(
.IN_WIDTH(1920),
.IN_HEIGHT(1080),
.OUT_WIDTH(960),
.OUT_HEIGHT(540)
) hdmi_scaler (
.clk(hdmi_clk),
.rst_n(!hdmi_vsync),
.pixel_in(hdmi_data),
.pixel_out(scaled_hdmi)
);
这个缩放模块内部采用双线性插值算法,核心设计要点包括:
- 使用两个LineBuffer存储相邻两行像素
- 横向缩放系数采用16位定点数表示
- 权重累加器需要处理溢出情况
- 垂直缩放通过行选择逻辑实现
特别注意:缩放模块的首行延迟必须精确控制,否则会导致拼接后的画面出现错位。建议在仿真阶段特别验证不同分辨率切换时的边界情况。
3.2 DDR3存储控制器
四路视频流共享DDR3存储空间,需要精心设计存储策略:
verilog复制always @(posedge axi_clk) begin
case(wr_state)
2'b00: if(video1_ready) begin
awaddr <= 32'h1000_0000;
awlen <= 8'd63; //突发64次
wr_state <= 2'b01;
end
2'b01: if(wready) begin
wdata <= video1_fifo_out;
wr_state <= (awlen==0) ? 2'b10 : 2'b01;
awlen <= awlen - 1;
end
//...其他状态机分支
endcase
end
关键设计考量:
- 每个视频通道分配独立的内存区域
- 采用突发传输模式提高带宽利用率(BL8模式)
- 动态调整仲裁优先级,防止低帧率通道饿死
- 写入地址需要按DDR3的bank和row进行优化
实测中发现,当四路视频同时写入时,DDR3控制器需要至少1200MHz的有效带宽才能保证不丢帧。
3.3 视频拼接引擎
拼接引擎是系统的核心创新点,通过坐标映射表实现灵活的布局控制:
verilog复制reg [15:0] pos_x_table[0:3] = '{960,0,960,0}; //X坐标偏移量
reg [15:0] pos_y_table[0:3] = '{0,540,0,540}; //Y坐标偏移量
always @(posedge vga_clk) begin
for(int i=0; i<4; i++) begin
if( (hcount >= pos_x_table[i]) && (hcount < pos_x_table[i]+960) &&
(vcount >= pos_y_table[i]) && (vcount < pos_y_table[i]+540) )
begin
active_ch <= i;
break;
end
end
end
这个设计有几个精妙之处:
- 使用Block RAM存储布局配置,支持动态重配
- 区域检测逻辑与DDR3预读取机制协同工作
- 处理四画面交界处的特殊仲裁逻辑
- 支持运行时修改拼接布局
4. 时序收敛与布局优化
4.1 跨时钟域处理
系统涉及多个时钟域:
- HDMI输入时钟(148.5MHz)
- 摄像头输入时钟(27MHz)
- DDR3控制器时钟(200MHz)
- 输出显示时钟(74.25MHz)
关键同步策略:
- 使用异步FIFO隔离不同时钟域
- 重要的控制信号采用握手协议
- 数据路径上的跨时钟域信号添加两级寄存器同步
4.2 物理布局约束
在PDS工具中需要手动添加位置约束:
code复制# HDMI相关逻辑约束
set_property PACKAGE_PIN AD12 [get_ports {hdmi_clk}]
set_property IOSTANDARD LVDS_25 [get_ports {hdmi_clk}]
set_property PACKAGE_PIN AE12 [get_ports {hdmi_data[0]}]
...
# 摄像头接口约束
set_property PACKAGE_PIN C17 [get_ports {cam_clk}]
set_property IOSTANDARD LVCMOS18 [get_ports {cam_clk}]
...
# DDR3接口约束
set_property PACKAGE_PIN G13 [get_ports {ddr3_dq[0]}]
set_property IOSTANDARD SSTL15 [get_ports {ddr3_dq[0]}]
...
布局建议:
- HDMI相关逻辑锁定在Bank12附近
- 摄像头接口放在Bank34
- DDR3控制器尽量靠近存储器物理位置
- 时钟相关逻辑使用全局时钟资源
5. 调试经验与性能优化
5.1 DDR3校准问题排查
常见问题及解决方法:
- 校准失败:调整AXI时钟相位偏移(建议0.3UI)
- 数据错误:检查DQ/DQS走线长度匹配
- 稳定性问题:优化VREF电压设置
- 带宽不足:调整仲裁策略和突发长度
5.2 视频撕裂问题处理
视频撕裂通常由以下原因导致:
- DDR3读取延迟不匹配
- 预读取机制未正确配置
- 内存带宽不足
- 输出时序生成错误
解决方案:
- 提前两个时钟周期发出读请求
- 优化DDR3读取调度算法
- 增加输出FIFO深度
- 精确计算像素流水线延迟
5.3 资源利用率优化
针对盘古-50K的资源特点:
- 使用DSP块实现缩放计算
- 合理分配Block RAM作为行缓冲
- 关键路径考虑寄存器复制
- 状态机采用二进制编码节省LUT
实测资源占用:
- LUTs: 42%
- FFs: 38%
- BRAM: 60%
- DSP: 45%
6. 系统扩展与改进方向
6.1 动态布局重配置
通过软件接口可以实时修改:
- 各画面位置
- 画面大小
- 显示层级
- 透明度混合
6.2 视频叠加功能
未来可扩展:
- 实时OSD叠加
- 动态弹幕显示
- 画中画效果
- 视频特效处理
6.3 多平台适配
相同架构可移植到:
- 其他紫光同创FPGA平台
- Xilinx/Intel FPGA
- 定制化ASIC方案
在实际部署这个系统时,我发现最关键的还是DDR3控制器的优化。通过实测,将突发长度设置为64,仲裁策略改为基于帧率的动态优先级调整后,系统稳定性显著提高。另一个实用技巧是在PDS布线时,对视频数据路径手动添加位置约束,可以避免工具自动布局导致的时序问题。