去年参加全国FPGA设计竞赛时,我选择了视频拼接这个既经典又充满挑战的题目。不同于常见的两路视频拼接,这次需要同时处理四路不同规格的视频源:一路HDMI(1920x1080@60Hz)、一路摄像头(960x540@30Hz)和一路以太网视频(960x540),其中HDMI信号需要复用一次。最终这个设计获得了国家二等奖,今天就来详细拆解其中的技术实现。
选择紫光同创盘古-50K开发板主要基于三点考虑:首先,其内置的50K逻辑单元足够处理四路视频的实时拼接;其次,开发板提供了丰富的视频接口,包括HDMI输入输出、摄像头接口和以太网PHY;最重要的是,作为国产FPGA平台,其性价比和供货稳定性都很有保障。
系统采用三级流水线架构:
这种架构的优势在于:
系统涉及四个时钟域:
我们采用异步FIFO进行跨时钟域处理,关键参数设置如下:
| 信号类型 | FIFO深度 | 阈值设置 |
|---|---|---|
| HDMI数据 | 1024 | 800-200 |
| 摄像头数据 | 512 | 400-100 |
| 网络数据 | 512 | 400-100 |
特别注意:FIFO的读写时钟比要严格匹配视频帧率,例如摄像头30fps对应输出60fps时,写时钟是读时钟的一半
以HDMI输入为例,核心代码如下:
verilog复制module hdmi_input (
input wire hdmi_clk,
input wire [23:0] hdmi_data,
input wire hdmi_hsync,
input wire hdmi_vsync,
output reg [23:0] rgb_out,
output reg hs_out,
output reg vs_out,
output reg de_out
);
// 消隐区处理
always @(posedge hdmi_clk) begin
if (!hdmi_vsync || !hdmi_hsync) begin
rgb_out <= 24'h0;
de_out <= 1'b0;
end else begin
rgb_out <= hdmi_data;
de_out <= 1'b1;
end
hs_out <= hdmi_hsync;
vs_out <= hdmi_vsync;
end
// 色彩空间转换(可选)
wire [7:0] y, cb, cr;
rgb2ycbcr u_rgb2ycbcr(
.clk(hdmi_clk),
.r(hdmi_data[23:16]),
.g(hdmi_data[15:8]),
.b(hdmi_data[7:0]),
.y(y),
.cb(cb),
.cr(cr)
);
endmodule
采用乒乓缓冲机制,关键设计要点:
地址映射示例:
verilog复制// 输出像素坐标到各视频源的映射
always @(*) begin
if (out_x < 1920) begin
if (out_y < 1080) begin
// 区域1:HDMI原始信号
hdmi_rd_addr = {out_y[9:0], out_x[10:0]};
rd_sel = 2'b00;
end else begin
// 区域3:摄像头信号
cam_rd_addr = {(out_y-1080)[8:0], out_x[9:0]};
rd_sel = 2'b01;
end
end else begin
// 区域2和4的处理类似
end
end
针对不同分辨率视频源的拼接,我们采用以下处理流程:
插值算法实现:
verilog复制// 双线性插值核心代码
always @(posedge clk) begin
// 计算权重
wx <= x_pos[3:0]; // 取小数部分
wy <= y_pos[3:0];
// 像素加权计算
pixel_out <= (p11*(16-wx)*(16-wy) +
p12*wx*(16-wy) +
p21*(16-wx)*wy +
p22*wx*wy) >> 8;
end
多视频源同步是最大挑战,我们的解决方案:
同步状态机设计:
verilog复制parameter SYNC_IDLE = 2'b00;
parameter SYNC_WAIT = 2'b01;
parameter SYNC_RUN = 2'b10;
always @(posedge sys_clk) begin
case(sync_state)
SYNC_IDLE:
if (hdmi_vsync && cam_vsync && eth_vsync)
sync_state <= SYNC_WAIT;
SYNC_WAIT:
if (frame_cnt >= 3) // 等待3帧稳定
sync_state <= SYNC_RUN;
SYNC_RUN:
if (err_cnt > 10) // 错误超过阈值
sync_state <= SYNC_IDLE;
endcase
end
在盘古50K上实现时,我们采用了以下优化策略:
BRAM分区使用:
DSP48E1高效利用:
时序优化:
最终实现的资源占用情况:
| 资源类型 | 使用量 | 总量 | 利用率 |
|---|---|---|---|
| LUT | 23,456 | 53,840 | 43% |
| FF | 18,923 | 107,680 | 17% |
| BRAM | 48 | 140 | 34% |
| DSP | 16 | 120 | 13% |
功耗测试结果(室温25℃):
画面撕裂问题:
色彩失真问题:
时序违例问题:
在调试视频时序时,我们总结出以下方法:
典型HDMI时序参数实测:
基于现有框架,还可以实现更多高级功能:
动态布局切换:
智能分析功能:
多屏协同:
在盘古50K上,这些扩展约需要额外15-20%的逻辑资源。如果考虑升级到盘古100K平台,还可以加入H.264编码等更复杂的功能模块。