FPGA视频4分屏项目 - 系统架构详细讲解
FPGA视频4分屏项目 - 系统架构详细讲解
一、系统整体架构
┌─────────────────────────────────────────────────────────────────────┐ │ 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 rw_fifo_ctrl.v (读写FIFO控制器)
功能: 控制读写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模块例化
写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) + 时钟域转换 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_m.v (AXI主机模块)
功能: 单个AXI主机,实现与DDR3的数据交互
2.2.1 参数说明
parameter integer VIDEO_LENGTH = 1920 // 图像宽度 parameter integer VIDEO_HIGTH = 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页) 2.2.2 地址构成
28位地址 = [27:22 基址] + [21:20 页号(2bit)] + [19:0 页内偏移(20bit)] 例: VIDEO_BASE_ADDR=0, r_wr_addr_page=0, r_wr_addr_cnt=0 M_AXI_AWADDR = {4'b0, 2'b00, 2'b00, 20'b0} = 28'h0000000 地址空间分配(以1920×1080为例):
- 单帧大小: 1920×1080×16bit = 33,177,600 bits = 4,147,200 字节
- DDR地址数: 4,147,200 / 4 = 1,036,800 = 0x100800
- 页号分配: 0-3页,每页存放一帧数据
2.2.3 写流程 (摄像头 → DDR)
状态机: IDLE → WRITE_START → WRITE_ADDR → WRITE_DATA
关键信号:
| 信号 | 方向 | 说明 |
|---|---|---|
| M_AXI_AWADDR | 输出 | 写地址 |
| M_AXI_AWVALID | 输出 | 写地址有效(主机向从机) |
| M_AXI_AWREADY | 输入 | 从机就绪应答 |
| wfifo_rd_water_level | 输入 | 写FIFO中有效数据数量 |
| wfifo_rd_req | 输出 | 写FIFO读请求 |
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 = 8组数据 = 256×8 = 2048bit = 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个数据的突发传输 2.2.4 读流程 (DDR → 显示)
状态机: IDLE → READ_START → READ_ADDR → READ_DATA
关键特点:
// 读启动条件 if(DDR_INIT_DONE && r_fram_done) // 必须DDR初始化完 + 写帧完成 r_fifo_state <= READ_START; // 读启动阈值 if(rfifo_wr_water_level < VIDEO_LENGTH*PIXEL_WIDTH/128) r_fifo_state <= READ_ADDR; // 含义: 读FIFO中数据少于1行时,向DDR申请新数据 // VIDEO_LENGTH*PIXEL_WIDTH/128 = 1920*32/128 = 480 (256bit单位) 2.2.5 页号管理 (帧缓冲)
双缓冲原理:
// 写端维护 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 // 读端切换逻辑 if(r_rd_done) // 读完一帧后 begin r_rd_addr_page <= r_wr_last_page; // 切换到最新写完的页 if(r_rd_addr_page == r_wr_addr_page) // 如果即将写入该页 r_rd_addr_page <= r_rd_last_page; // 保持在旧页 end 2.2.6 VS同步复位
// 竖同步信号处理 always @(posedge M_AXI_ACLK) begin r_vs_in_d0 <= vs_in; r_vs_in_d1 <= r_vs_in_d0; end // 上升沿检测 if(r_vs_in_d0 && (!r_vs_in_d1)) // 上升沿 r_wr_rst <= 1'b1; // 复位释放 if(r_wr_addr_cnt == wr_addr_min) // 地址计数器回到最小值 r_wr_rst <= 1'b0; // 说明: 每帧开始时重置地址和状态,形成帧同步机制 2.3 axi_m_arbitration.v (仲裁层)
功能: 4个AXI主机的仲裁 + 4组FIFO的统一管理
2.3.1 仲裁原理
写仲裁 (轮询): M0 → M1 → M2 → M3 → M0
// 写状态机 case(arbitration_wr_state) M0_WRITE: begin if(M0_AXI_WLAST) // 第一个主机写完 arbitration_wr_state <= M1_WRITE; // 切换到第二个 else if((!(wfifo0_state == 'd3)) && // 写FIFO不在写数据阶段 (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 ... end 读仲裁 (更复杂):
// 分为两个阶段 // 阶段1: 预初始化 (rfifo_pre_write_init == 0) // 轮流向4个读FIFO写入第一行数据 if(!rfifo_pre_write_init) begin if(rfifo0_wr_water_level < ZOOM_VIDEO_LENGTH*PIXEL_WIDTH/256*2) arbitration_rd_state <= M0_READ; else if(rfifo1_wr_water_level < ...) arbitration_rd_state <= M1_READ; ... else rfifo_pre_write_init <= 1'd1; // 全部预写完毕 end // 阶段2: 正常传输 (rfifo_pre_write_init == 1) // 根据显示模块的读取请求分配读FIFO else if(r_video0_rd_en_d0) // 象限0需要读 arbitration_rd_state <= M0_READ; else if(r_video1_rd_en_d0) // 象限1需要读 arbitration_rd_state <= M1_READ; 2.3.2 仲裁信号多选
// 写地址信号多选 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; // 写地址 assign M_AXI_AWADDR = (arbitration_wr_state == M0_WRITE) ? M0_AXI_AWADDR : (arbitration_wr_state == M1_WRITE) ? M1_AXI_AWADDR : ... // 从机反馈给主机 assign M0_AXI_AWREADY = (arbitration_wr_state == M0_WRITE) ? M_AXI_AWREADY : 1'b0; // 说明: 只有被选中的主机才能与从机通信,其他主机收到'0'信号 2.3.3 核心信号连接
// 写FIFO → DDR wfifo0_rd_req ───────> AXI_FULL_M0 ──> M_AXI_WDATA ──> AXI总线 ──> DDR wfifo1_rd_req ───────> AXI_FULL_M1 ─┐ wfifo2_rd_req ───────> AXI_FULL_M2 ─┼> 仲裁器多选 wfifo3_rd_req ───────> AXI_FULL_M3 ─┘ // DDR → 读FIFO DDR ──> AXI总线 ──> M_AXI_RDATA ──> 仲裁器多选 ──> rfifo0_wr_req ──> 读FIFO0 rfifo1_wr_req ──> 读FIFO1 rfifo2_wr_req ──> 读FIFO2 rfifo3_wr_req ──> 读FIFO3 三、AXI协议详解
3.1 AXI总线信号汇总
3.1.1 写地址通道 (Write Address Channel)
| 信号名 | 位宽 | 方向 | 含义 | 说明 |
|---|---|---|---|---|
| AWID | 4 | M→S | 写事务ID | 区分不同写请求 |
| AWADDR | 28 | M→S | 写地址 | DDR目标地址 |
| AWLEN | 4 | M→S | 突发长度-1 | 本代码未用 |
| AWSIZE | 3 | M→S | 数据宽度 | 本代码未用 |
| AWBURST | 2 | M→S | 突发类型 | 本代码未用 |
| AWUSER | 1 | M→S | 用户信号 | 本代码=0 |
| AWVALID | 1 | M→S | 地址有效 | 握手信号 |
| AWREADY | 1 | S→M | 从机就绪 | 握手信号 |
握手时序:
时钟边界: │ │ │ │ │ AWVALID: ───┬────────┬────────────────┬─────── │ │ │ AWREADY: ───────┬────────┬─────────────────── 传输发生: ↑握手1 ↑握手2 说明: - AWVALID=1 && AWREADY=1: 地址成功传输 - 最少传输1个地址,最多传输4个地址(4页缓冲) 3.1.2 写数据通道 (Write Data Channel)
| 信号名 | 位宽 | 方向 | 含义 | 说明 |
|---|---|---|---|---|
| WID | 4 | M→S | 数据ID | 可选 |
| WDATA | 256 | M→S | 写数据 | 256bit = 8×32bit |
| WSTRB | 32 | M→S | 字节使能 | 本代码全1 |
| WLAST | 1 | M→S | 最后数据 | 突发控制 |
| WUSER | 4 | M→S | 用户信号 | 本代码未用 |
| WVALID | 1 | M→S | 数据有效 | 握手信号 |
| WREADY | 1 | S→M | 从机就绪 | 握手信号 |
数据握手时序:
突发长度 = 8 时钟边界: │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ WVALID: ────────────────────────────────────────────────── WREADY: ───────┬──────┬──────┬──────┬──────┬──────┬──────┬── WLAST: 0 0 0 0 0 0 0 1 数据编号: #1 #2 #3 #4 #5 #6 #7 #8 说明: - 每个时钟周期传1个256bit数据 - WLAST=1标记最后一个数据 - 8个数据后自动回到IDLE准备下一次突发 3.1.3 读地址通道 (Read Address Channel)
与写地址通道类似,信号为ARID/ARADDR/ARVALID/ARREADY
3.1.4 读数据通道 (Read Data Channel)
| 信号名 | 位宽 | 方向 | 含义 |
|---|---|---|---|
| RID | 4 | S→M | 数据ID |
| RDATA | 256 | S→M | 读数据 |
| RRESP | 2 | S→M | 响应(OK/错误) |
| RLAST | 1 | S→M | 最后数据 |
| RVALID | 1 | S→M | 数据有效 |
| RREADY | 1 | M→S | 主机就绪(本代码自动=1) |
3.2 写流程完整时序
┌─────────────────────────────────────────┐ │ 主机侧: AXI_FULL_M │ │ 写FIFO数据 ↓ │ └──────────────┬────────────────────────┘ │ wfifo_rd_water_level > 8 ▼ ┌─────────────────┐ │ WRITE_START │ │ 状态机 │ └────────┬────────┘ │ 条件满足 ▼ ┌──────────────────────┐ │ WRITE_ADDR 状态 │ │ 1. r_m_axi_awvalid │ │ <= 1'b1 │ └────────┬─────────────┘ │ │ 地址握手: │ M_AXI_AWVALID && M_AXI_AWREADY ▼ ┌──────────────────────┐ │ WRITE_DATA 状态 │ │ 2. 开始发送数据 │ │ wfifo_rd_req = 1 │ └────────┬─────────────┘ │ 8个数据传输完(M_AXI_WLAST=1) ▼ ┌──────────────────────┐ │ 返回WRITE_START │ │ 准备下一批数据 │ └──────────────────────┘ 3.3 关键握手机制
写地址握手
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 写数据握手
write_ddr_fifo FIFO的内部处理: - 当 wfifo_rd_req = 1 时,每个时钟周期输出1个256bit数据 - 同时产生 M_AXI_WVALID = 1 - 当接收到 M_AXI_WREADY = 1 时,完成1个数据握手 WLAST 由 AXI从机产生,标记8个数据的末尾 四、数据流转完整描述
4.1 发送流程 (摄像头 → 显示)
第1步: 摄像头采集 ┌─────────────┐ │ CMOS摄像头 │ 16bit/像素 @ 27MHz │ 1920×1080 │ HREF/VSYNC └──────┬──────┘ │ 第2步: 图像预处理 (4路) ┌──────────────────────────────────────┐ │ 4个预处理模块 (并行处理) │ │ - cam1_filter: 降噪 │ │ - cam2_bin: 二值化 │ │ - cam3_filter: 滤波 │ │ - cam4_gamma: 伽马校正 │ │ 输出: 16bit/像素 @ 各自的像素时钟 │ └──────┬───────────────────────────────┘ │ 第3步: 写入写FIFO (4组独立FIFO) ┌──────────────────────────────────────┐ │ rw_fifo_ctrl (4组) │ │ 输入: 32bit @ 像素时钟 │ │ 输出: 256bit @ DDR时钟 │ │ 功能: 32→256宽度转换 + 时钟域转换 │ └──────┬───────────────────────────────┘ │ wfifo_rd_water_level 第4步: AXI主机仲裁 ┌──────────────────────────────────────┐ │ axi_m_arbitration │ │ - 写仲裁 (M0→M1→M2→M3) │ │ - 地址管理 (4页循环) │ │ - 状态机 (WRITE_ADDR/WRITE_DATA) │ └──────┬───────────────────────────────┘ │ 第5步: AXI总线写入DDR ┌──────────────────────────────────────┐ │ AXI总线握手 │ │ AWADDR: 写地址 (28bit) │ │ WDATA: 写数据 (256bit×8 = 突发) │ │ 每个主机写完1帧后轮换 │ └──────┬───────────────────────────────┘ │ 存储到DDR 第6步: DDR读取 ┌──────────────────────────────────────┐ │ 当写完1帧后 (r_fram_done=1) │ │ 开始读取上一帧数据 │ │ 读地址自动循环: 0→1→2→3→0 │ │ 保证写入和读取不冲突 │ └──────┬───────────────────────────────┘ │ 第7步: 写入读FIFO ┌──────────────────────────────────────┐ │ rw_fifo_ctrl 读FIFO │ │ 输入: 256bit @ DDR时钟 │ │ 输出: 32bit @ 像素时钟 │ │ 256→32宽度转换 │ └──────┬───────────────────────────────┘ │ 第8步: 时序转换 ┌──────────────────────────────────────┐ │ sync_generator │ │ 生成4分屏时序信号 │ │ - VS, HS, DE 同步脉冲 │ │ - 数据路由到4个象限 │ └──────┬───────────────────────────────┘ │ 第9步: HDMI输出 ┌──────────────────────────────────────┐ │ 4个象限并行输出 @ 27MHz │ │ HDMI驱动生成最终视频信号 │ └──────────────────────────────────────┘ 4.2 关键时序点
| 时间点 | 事件 | 信号变化 |
|---|---|---|
| 帧开始 | VSYNC上升沿 | vs_in上升 |
| 帧内 | 写地址握手 | AWVALID && AWREADY |
| 帧内 | 数据握手 | WVALID && WREADY (×8) |
| 帧内 | WLAST=1 | 突发结束 |
| 帧末 | 写完成 | r_wr_done=1 |
| 帧末 | 页号切换 | r_wr_addr_page++ |
| 帧末 | r_fram_done=1 | 允许读取 |
| 后续帧 | 读启动 | r_fifo_state → READ_START |
五、地址与页号管理
5.1 地址计算
总地址28bit = [27:22 保留] + [21:20 页号] + [19:0 页内偏移] 每帧存储空间: 1920×1080×16bit = 33,177,600 bits = 4,147,200字节 = 1,036,800×4字节 = 0xF_D20_0 (20bit地址) 页号循环: 页0: 地址 0x0000000 ~ 0x0F_D1FF 页1: 地址 0x0100000 ~ 0x0FE_D1FF 页2: 地址 0x0200000 ~ 0x0FE_D1FF 页3: 地址 0x0300000 ~ 0x0FE_D1FF 页内偏移递增规则: 每次AXI握手 → r_wr_addr_cnt += 64 (=M_AXI_BRUST_LEN × 8) 64个地址单位 = 64×4字节 = 256字节 = 8×256bit = 8个AXI数据 5.2 双缓冲机制
同时有4个页面: 当前写入 下一帧将写 已完成 等待读 ┌──────────────┬──────────────┬──────────────┬──────────────┐ │ 写端指针 │ 准备页 │ 完成页 │ 读端指针 │ │ wr_addr_page │ │ wr_last_page │ rd_addr_page │ └──────────────┴──────────────┴──────────────┴──────────────┘ 安全机制: - 写端不能覆盖读端正在读的页 - 读端不能读未写入的页 - 总是读"上一次写完的页" (wr_last_page) 示例: 第1帧: 写→页0 读→等待 第2帧: 写→页1 读→页0 第3帧: 写→页2 读→页1 第4帧: 写→页3 读→页2 第5帧: 写→页0 读→页3 六、控制流程和约束条件
6.1 写流程状态转移
初始化后: IDLE ──(DDR_INIT_DONE=1)──> WRITE_START WRITE_START 等待条件: 1. wfifo_rd_water_level > 8 (至少8个256bit数据) OR 2. (接近末尾) && (wfifo_rd_water_level >= 7) 满足条件 → WRITE_ADDR WRITE_ADDR: 发送第一个地址,等待握手 M_AXI_AWVALID && M_AXI_AWREADY → WRITE_DATA WRITE_DATA: 持续发送数据,直到WLAST=1 → 返回WRITE_START 当 r_wr_addr_cnt >= wr_addr_max - 64: 最后一批数据,写完后: - r_wr_addr_cnt 回到 wr_addr_min - r_wr_done = 1 (一帧完成标志) - r_fram_done = 1 (允许读取信号) - 页号递增 6.2 读流程状态转移
前提条件: DDR_INIT_DONE = 1 && r_fram_done = 1 (至少有一帧已写入) IDLE ──> READ_START (首次有效数据时) READ_START 等待条件: rfifo_wr_water_level < 1行数据量 说明: 当读FIFO中数据少于1行时,向DDR申请新行数据 满足条件 → READ_ADDR READ_ADDR: 发送读地址,等待握手 M_AXI_ARVALID && M_AXI_ARREADY → READ_DATA READ_DATA: 接收数据,直到RLAST=1 → 返回READ_START 当 r_rd_addr_cnt >= wr_addr_max - 64: 最后一批数据,读完后: - r_rd_addr_cnt 回到 wr_addr_min - r_rd_done = 1 - 页号递增 七、关键参数计算
// FIFO水位阈值 (多少数据后开始传输) wfifo_rd_water_level > M_AXI_BRUST_LEN = wfifo_rd_water_level > 8 意义: 至少累积8个256bit数据(2048bit=256字节)后开始写DDR // 读FIFO启动条件 rfifo_wr_water_level < VIDEO_LENGTH * PIXEL_WIDTH / 128 = 1920 * 32 / 128 = 480 (以256bit为单位) 意义: 当读FIFO中数据少于1行时,申请新行 // 地址递增量 M_AXI_BRUST_LEN * 8 = 8 * 8 = 64 意义: 每次突发传输地址增加64 (256字节) // 末尾判断 r_wr_addr_cnt >= wr_addr_max - M_AXI_BRUST_LEN * 8 = r_wr_addr_cnt >= wr_addr_max - 64 意义: 剩余少于64个地址时,本次传输后回零 // 读启动延迟 r_fram_done = 1: 至少1帧写入DDR rfifo_wr_water_level < 1行: 读FIFO不满 这两个条件确保有足够数据供读取 八、常见问题解析
Q1: 为什么需要4个页面?
A: 两个理由: 1. 防止冲突: 读写独立操作,需要分离的存储区域 2. 流水处理: 4页允许最多4路摄像头独立存储,不会相互等待 Q2: WLAST信号如何产生?
A: 由DDR从机产生: - 主机声明突发长度(AWLEN/ARLEN) - 从机根据长度在第N个数据后自动产生WLAST/RLAST - 本设计固定突发长度=8,所以第8个数据时WLAST=1 Q3: 为什么地址增量是64?
A: 64 = M_AXI_BRUST_LEN × 8 - 突发长度 = 8 - 每个地址代表4字节 - 总传输 = 8 × 256bit = 8 × 32字节 = 256字节 = 64个地址单位 Q4: 如何确保先写后读?
A: 通过以下机制: 1. r_fram_done: 写完一帧才允许读 2. 页号分离: 读取上一帧(wr_last_page),写入当前帧(wr_addr_page) 3. 防护检查: if(r_wr_addr_page == r_rd_addr_page) 阻止覆盖 九、总结
这个系统是一个典型的流水线视频处理架构:
- 采集阶段: 双摄像头 → 预处理 → 4路写FIFO
- 传输阶段: 仲裁选择 → AXI协议 → DDR存储
- 回读阶段: DDR读取 → 仲裁路由 → 4路读FIFO
- 输出阶段: 时序转换 → 4分屏合成 → HDMI输出
核心特点:
- ✅ 异步双缓冲: 读写独立进行,无冲突
- ✅ AXI突发传输: 高效DDR数据交互
- ✅ 动态仲裁: 智能分配总线资源
- ✅ 帧同步机制: VS/HS精确对齐
- ✅ 可扩展性: 易于添加更多处理模块