跳到主要内容FPGA 视频 4 分屏系统架构详解 | 极客日志C算法
FPGA 视频 4 分屏系统架构详解
本文解析 FPGA 视频 4 分屏系统的整体架构,涵盖 CMOS 采集、预处理、AXI 总线传输及 DDR3 缓存机制。重点阐述读写 FIFO 控制、双缓冲页号管理、AXI 协议握手时序以及仲裁逻辑。通过流水线设计实现多路摄像头数据并发处理与 HDMI 输出,确保帧同步与数据完整性。
WenxuanMa0 浏览 FPGA 视频 4 分屏系统架构详解
一、系统整体架构概览
整个系统采用典型的流水线设计,从摄像头采集到 HDMI 输出,数据流经过预处理、缓存、总线传输和时序生成。核心在于利用 DDR3 作为多帧缓冲,配合 AXI 总线实现高速读写。
┌─────────────────────────────────────────────────────────────────────┐
│ CMOS 摄像头 (双路) │
│ (CMOS1/2 采集 8bit 数据) │
└────────────┬────────────────────────────────────────────────────────┘
│ ▼
┌─────────────────────────────────────────────────────────────────────┐
│ 图像预处理模块 (4 路处理) │
│ (cam_pre_process / process_filter / process_gamma 等) │
│ 输出 16bit 图像数据到写 FIFO │
└────────────┬────────────────────────────────────────────────────────┘
│ ▼
┌────────────────────────────────┐
│ 写 FIFO 缓存 (4 组,每组 256bit) │
│ 从 16bit 摄像头数据到 256bit │
│ 宽度转换和缓冲处理 │
└────────┬───────────────────────┘
│ ▼
┌─────────────────────────────────────────────────────────────────────┐
│ AXI 主机仲裁层 (axi_m_arbitration.v) │
│ 4 个 AXI 主机 + 仲裁器 + FIFO 控制器 │
│ 读写状态机 & 突发长度控制 & 地址管理 │
└──────────┬──────────────────────────────────────────────────────────┘
│ ▼
┌─────────────────────────────────────────────────────────────────────┐
│ AXI 总线接口 (axi_m.v - 4 个 AXI_FULL_M 主机模块) │
│ • 写地址通道 (AWADDR/AWVALID/AWREADY) │
│ • 写数据通道 (WDATA/WVALID/WREADY/WLAST) │
│ • 读地址通道 (ARADDR/ARVALID/ARREADY) │
│ • 读数据通道 (RDATA/RVALID/RLAST) │
└──────────┬──────────────────────────────────────────────────────────┘
│ ▼
┌──────────────────┐
│ DDR3 SDRAM │
│ (多帧缓存区) │
│ 4 页双缓冲 │
└──────────┬───────┘
│ ▼
┌─────────────────────────────────────────────────────────────────────┐
│ AXI 读取 + 读 FIFO (4 组,每组 256bit) │
│ 从 DDR3 读取数据宽度转换为 32bit │
└──────────┬──────────────────────────────────────────────────────────┘
│ ▼
┌─────────────────────────────────────────────────────────────────────┐
│ sync_generator (时序生成器) │
│ 生成 HDMI 时序信号 (VS, HS, DE) │
│ 数据并行输出到 4 个象限 │
└──────────┬──────────────────────────────────────────────────────────┘
│ ▼
┌──────────────────┐
│ HDMI 输出 │
│ (4 分屏显示) │
└──────────────────┘
二、关键模块功能解析
2.1 读写 FIFO 控制器 (rw_fifo_ctrl.v)
这个模块主要负责时钟域转换和数据宽度适配。摄像头端通常是像素时钟,而 DDR 端是系统时钟,两者不同步,必须通过 FIFO 隔离。
| 信号 | 方向 | 位宽 | 说明 |
|---|
| wfifo_wr_en | 输入 | 1 | 写 FIFO 写使能 |
| wfifo_wr_data32_in | 输入 | 32 | 从摄像头输入的 32bit 数据 |
| wfifo_rd_water_level | 输出 | 9 | 写 FIFO 读端水位 (256bit 单位) |
| wfifo_rd_data256_out | 输出 | 256 | 写 FIFO 读端 256bit 数据 |
| rfifo_wr_req | 输入 | 1 | 读 FIFO 写请求 (来自 AXI) |
| rfifo_wr_data256_in | 输入 | 256 | 来自 DDR 的 256bit 数据 |
| rfifo_rd_data32_out | 输出 | 32 | 输出到 HDMI 的 32bit 数据 |
写 FIFO 负责将 32bit 像素数据打包成 256bit 供 DDR 使用,同时完成跨时钟域;读 FIFO 则反向操作,从 DDR 取回数据并还原为 32bit 供显示。
// 写 FIFO (write_ddr_fifo)
// 写端:32bit @ wfifo_wr_clk (摄像头时钟)
// 读端:256bit @ ddr_clk (DDR 时钟)
// 功能:宽度转换 (32→256) + 时钟域转换
// 读 FIFO (read_ddr_fifo)
// 写端:256bit @ ddr_clk (DDR 时钟)
// 读端:32bit @ rfifo_rd_clk (像素时钟)
// 功能:宽度转换 (256→32) + 时钟域转换
帧同步复位是关键,利用竖同步信号 (VSYNC) 的上升沿来重置 FIFO 状态,确保每一帧的数据边界清晰。
// 检测竖同步信号上升沿,生成复位脉冲
// vs_in: 写 FIFO 的竖同步输入
// vs_out: 读 FIFO 的竖同步输入
// 时序处理:使用移位寄存器生成多周期复位
always @(posedge wfifo_wr_clk)
r_vs_in_d1 <= {r_vs_in_d1[14:0], r_vs_in_d0};
if(r_vs_in_d1[0] && !r_vs_in_d1[14])
r_wr_rst <= 1'b1;
2.2 AXI 主机模块 (axi_m.v)
这是与 DDR 交互的核心,每个摄像头通道对应一个 AXI Master 实例。
参数配置
parameter integer VIDEO_LENGTH = 1920; // 图像宽度
parameter integer VIDEO_HEIGHT = 1080; // 图像高度 (修正原拼写错误)
parameter integer PIXEL_WIDTH = 32; // 像素位宽 (32bit=2 个 16bit 像素)
parameter integer CTRL_ADDR_WIDTH = 28;// 地址宽度
parameter integer DQ_WIDTH = 32; // DDR 数据宽度 (32bit)
parameter integer M_AXI_BRUST_LEN = 8; // 突发长度 (8 个 256bit 数据)
parameter integer VIDEO_BASE_ADDR = 2'd0; // 基地址页号 (0-3 页)
地址空间规划
28 位地址被划分为基址、页号和偏移量。单帧数据量约为 4MB,我们将其分为 4 页进行双缓冲管理,避免读写冲突。
- 单帧大小: 1920×1080×16bit = 4,147,200 字节
- 页号分配: 0-3 页,每页存放一帧数据
写流程 (摄像头 → DDR)
状态机在 IDLE、WRITE_START、WRITE_ADDR、WRITE_DATA 之间流转。关键在于握手信号的判断,只有当 AXI 从机准备好时,才发送下一个地址或数据。
// WRITE_ADDR 阶段:地址握手
if (M_AXI_AWVALID && M_AXI_AWREADY) begin
r_m_axi_awvalid <= 1'b0; // 清除有效标志
r_wr_addr_cnt <= r_wr_addr_cnt + M_AXI_BRUST_LEN * 8; // 地址 +8
end
// 地址自动递增规则:每次传输突发长度×8 = 256 字节
// WRITE_DATA 阶段:数据握手
assign wfifo_rd_req = M_AXI_WLAST ? 1'b0 : M_AXI_WREADY;
// 含义:
// - 当 M_AXI_WLAST=0(未到最后) 且 M_AXI_WREADY=1 时,继续读 FIFO
// - 当 M_AXI_WLAST=1(最后数据) 时,停止读 FIFO
// - 这形成了 8 个数据的突发传输
页号管理与双缓冲
双缓冲机制允许写入当前帧的同时读取上一帧,极大提高了带宽利用率。写指针和读指针需要严格错开,防止覆盖正在使用的数据。
// 写端维护
r_wr_addr_page: 当前写入的页号 (0-3)
r_wr_last_page: 上一次写完的页号
// 读端维护
r_rd_addr_page: 当前读取的页号
r_rd_last_page: 上一次读完的页号
// 页切换时机
if(r_wr_done) begin
r_wr_last_page <= r_wr_addr_page;
r_wr_addr_page <= r_wr_addr_page + 1;
if(r_wr_addr_page == r_rd_addr_page) // 不能覆盖正在读的页
r_wr_addr_page <= r_wr_addr_page + 1;
end
2.3 仲裁层 (axi_m_arbitration.v)
由于有 4 路摄像头数据竞争同一个 DDR 总线,仲裁器负责公平调度。写操作通常采用轮询方式,读操作则根据显示需求动态分配。
按顺序检查各通道 FIFO 水位,优先满足数据积压较多的通道。
// 写状态机
case(arbitration_wr_state)
M0_WRITE: begin
if(M0_AXI_WLAST) // 第一个主机写完
arbitration_wr_state <= M1_WRITE; // 切换到第二个
else if((!(wfifo0_state == 'd3)) &&
(wfifo0_rd_water_level < M_AXI_BRUST_LEN) &&
(wr_addr_cnt0 < wr_addr_max - M_AXI_BRUST_LEN * 8))
arbitration_wr_state <= M1_WRITE; // 提前切换
end
...
endcase
仲裁器通过多路选择器将选中的主机信号连接到共享的 AXI 总线上,未被选中的主机信号会被屏蔽。
// 写地址信号多选
assign M_AXI_AWVALID = (arbitration_wr_state == M0_WRITE) ? M0_AXI_AWVALID :
(arbitration_wr_state == M1_WRITE) ? M1_AXI_AWVALID :
(arbitration_wr_state == M2_WRITE) ? M2_AXI_AWVALID :
(arbitration_wr_state == M3_WRITE) ? M3_AXI_AWVALID : 1'b0;
三、AXI 协议握手细节
理解 AXI 协议的握手机制对于调试时序问题至关重要。这里重点看写地址和写数据通道的交互。
3.1 写地址通道
握手条件是 AWVALID 和 AWREADY 同时为高。一旦握手成功,地址即被传输,随后计数器更新。
// 握手时序
if(M_AXI_AWVALID && M_AXI_AWREADY) begin
r_m_axi_awvalid <= 1'b0;
r_wr_addr_cnt <= r_wr_addr_cnt + 64; // 8 个 256bit = 2048bit = 256 字节
end
3.2 写数据通道
数据通道同样遵循握手原则,但 WLAST 信号用于标记突发传输的结束。本设计中固定突发长度为 8,因此第 8 个数据后 WLAST 置 1。
// 数据握手时序
// 突发长度 = 8
// 每个时钟周期传 1 个 256bit 数据
// WLAST=1 标记最后一个数据
// 8 个数据后自动回到 IDLE 准备下一次突发
四、数据流转全流程
为了更直观地理解,我们将数据从采集到显示的完整路径梳理一遍:
- 采集: 双路 CMOS 摄像头以 27MHz 频率采集 1920×1080 分辨率的 16bit 图像。
- 预处理: 4 路独立处理模块分别执行降噪、二值化、滤波和伽马校正,输出 16bit 像素流。
- 写 FIFO: 数据进入 4 组独立的写 FIFO,在此处完成 32bit 到 256bit 的宽度打包及跨时钟域转换。
- AXI 仲裁: 仲裁器根据 FIFO 水位和轮询策略,决定哪个通道获得 DDR 访问权。
- DDR 写入: 通过 AXI 总线将数据写入 DDR3,采用页循环策略,每帧占用一页。
- DDR 读取: 当一帧写入完成后,触发读流程,读取上一帧数据进行显示。
- 读 FIFO: 数据从 DDR 读出,再次经过 FIFO 转回 32bit 像素格式。
- 时序生成:
sync_generator 生成 HDMI 所需的行场同步信号,并将数据路由到 4 个显示象限。
- HDMI 输出: 最终合成 4 分屏画面并通过 HDMI 接口输出。
五、内存管理与页号机制
5.1 地址计算
[27:22]: 保留
[21:20]: 页号 (2bit)
[19:0]: 页内偏移 (20bit)
每帧占用约 0xF_D20_0 字节,页内偏移每次增加 64 个地址单位(对应 256 字节)。
5.2 双缓冲安全机制
- 写端不能覆盖读端正在读的页。
- 读端总是读取'上一次写完的页' (
wr_last_page)。
- 若检测到页号即将冲突,写端会自动跳过该页。
- 第 1 帧:写→页 0,读→等待
- 第 2 帧:写→页 1,读→页 0
- 第 3 帧:写→页 2,读→页 1
- ...以此类推
六、控制流程与约束
6.1 写流程状态转移
初始化后进入 IDLE,等待 DDR 就绪。当 FIFO 水位超过阈值(至少 8 个 256bit 数据)时,启动 WRITE_ADDR。握手成功后进入 WRITE_DATA,持续发送直到 WLAST=1。一帧结束后,页号递增,r_fram_done 拉高通知读端。
6.2 读流程状态转移
读流程依赖于 r_fram_done 信号,确保至少有一帧已写入。当读 FIFO 水位低于 1 行数据量时,向 DDR 申请新数据。读完后同样更新页号,形成闭环。
七、常见问题与优化建议
Q1: 为什么需要 4 个页面?
A: 主要是为了支持 4 路摄像头独立存储,避免相互等待,同时提供足够的双缓冲余量,防止读写冲突。
Q2: WLAST 信号如何产生?
A: 由 DDR 控制器根据预设的突发长度自动生成。本设计固定为 8,所以第 8 个数据周期后自动拉高。
Q3: 地址增量为什么是 64?
A: 因为突发长度是 8,每个地址代表 4 字节,一次传输 8×32 字节 = 256 字节,即 64 个地址单位。
Q4: 如何确保先写后读?
A: 依靠 r_fram_done 信号锁存帧完成状态,配合页号分离机制,物理上隔离了读写区域。
八、总结
这套 FPGA 视频处理系统展示了典型的硬件流水线架构优势:
- 异步双缓冲: 读写完全解耦,最大化带宽利用率。
- AXI 突发传输: 减少总线开销,提升 DDR 读写效率。
- 动态仲裁: 智能分配资源,保证多路视频流的稳定性。
- 帧同步机制: 精确控制 VS/HS 信号,确保显示无撕裂。
- 可扩展性: 模块化设计便于后续增加更多路数或处理算法。
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
- JSON 压缩
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online