1. 从摄像头到显示器:一个视频处理系统的诞生
大家好,我是老张,一个在FPGA和视频处理领域摸爬滚打了十多年的工程师。今天想和大家聊聊一个非常具体、也非常有实战价值的项目:如何在安路FPGA上,利用米联客的FDMA IP核,搭建一个稳定高效的视频数据缓存系统。说白了,就是怎么把摄像头拍到的画面,通过FPGA,稳稳当当地存进DDR内存里,然后再流畅地显示到屏幕上。
你可能觉得这听起来像是FPGA开发的“标配”任务,但真上手做,坑可不少。数据流怎么对齐?DDR带宽怎么用满?时序怎么保证不丢帧?这些问题每一个都能让你调试好几天。我当初也是踩了无数坑,才慢慢摸清了门道。这次,我们就以安路的PH1A系列FPGA,搭配米联客的CAM001-CS500摄像头,来构建这个系统。核心的“搬运工”就是米联客自研的AXI-FDMA IP核,以及它的好搭档FDMA-DBUF(uidbuf)IP。它们俩一个负责和DDR“打交道”,一个负责把用户杂乱的数据流整理成规整的“包裹”,配合起来天衣无缝。
这篇文章,我不会只给你看干巴巴的框图和数据手册。我会带你深入到代码层面,把FDMA IP和uidbuf IP的源码掰开揉碎了讲,告诉你每个状态机跳转的意义,每个关键参数设置的考量。目标很简单:让你看完之后,不仅能理解原理,更能直接上手,在你的安路FPGA板子上复现这个完整的视频流水线。无论你是刚接触FPGA视频处理的新手,还是想优化现有方案的老手,相信都能从中找到有用的东西。我们这就开始,从系统框架搭起,一步步走进代码的细节世界。
2. 系统核心:AXI-FDMA IP核深度解析
2.1 FDMA IP:你的专属数据“快递员”
先来认识一下今天的主角之一:AXI-FDMA IP核。你可以把它想象成一个极其专业、高效的“数据快递员”。它的任务很明确:在FPGA的用户逻辑(PL侧)和DDR内存之间,快速、准确地搬运数据。为什么需要它?因为直接去操作复杂的AXI4总线协议,就像让你去开一架大型客机,仪表盘复杂,操作流程繁琐,稍有不慎就“机毁人亡”(数据出错、系统挂死)。
米联客的FDMA IP核,就是对AXI4-FULL总线协议进行了一层精妙的封装。它把那些让人头疼的AW、AR、W、R、B通道信号,打包成了几个非常简单的用户接口:地址、请求、数据大小、忙状态、有效信号和准备好信号。对你来说,你只需要告诉FDMA:“帮我把这一批数据,从内存的这个地址开始,搬运这么多字节”,或者“从内存的这个地址,给我读这么多数据出来”,剩下的复杂握手、突发(Burst)拆分、错误响应,全部交给FDMA内部的状态机去处理。
这带来的好处是巨大的。首先,代码可移植性极强。无论你用的是Xilinx、Intel还是安路的FPGA,只要它们的DDR控制器提供了标准的AXI4从机接口,这个FDMA IP核就能直接对接上去,你的用户逻辑代码几乎不用改。其次,极大降低了开发门槛。你不再需要去深入研究AXI4协议那几百页的规范,可以把精力集中在自己的视频算法或数据处理逻辑上。我在多个跨平台项目里复用这套IP,节省了大量的适配时间。
这个IP核有一个关键参数:MAX_BURST_LEN(最大突发长度)。AXI4协议本身支持的最大突发长度是256,但FDMA允许你通过用户接口设置任意大小的传输数据量(fdma_wsize/fdma_rsize)。IP内部会自动帮你把大的数据量,拆分成若干个不超过MAX_BURST_LEN的小突发传输。这个设计非常贴心,比如你要传输262个数据,而MAX_BURST_LEN设为256,FDMA会先发起一个256长度的突发,再发起一个6长度的突发,整个过程对你完全透明。这个机制在优化总线利用率时非常有用,我们后面会详细说。
2.2 庖丁解牛:FDMA写操作时序与源码
光说概念不够,我们直接看代码。FDMA的写操作时序是其核心,理解了写,读也就触类旁通了。用户接口的关键信号如下:
I_fdma_wareq: 用户发出的写请求信号。拉高表示“我要开始一次写传输了”。I_fdma_waddr: 本次传输的起始内存地址。I_fdma_wsize: 本次要写入的数据总量(单位:字节)。I_fdma_wdata: 要写入的数据。I_fdma_wready: 用户侧数据准备好信号。用户需要保证在O_fdma_wvalid有效时,数据是稳定可用的。O_fdma_wvalid: FDMA发出的数据有效信号。当这个信号为高时,FDMA正在从I_fdma_wdata上读取数据。O_fdma_wbusy: FDMA忙信号。为高时表示FDMA正在处理一次传输,此时用户不应发起新的请求。
一次完整的写传输流程是怎样的呢?我们结合源码里的状态机来看(虽然源码是状态机,但我们可以用流程来描述):
- 空闲等待: 用户先将
I_fdma_wready置1,表示自己随时可以接收数据。同时监测O_fdma_wbusy,当它为0时,表示FDMA“快递员”空闲。 - 发起请求: 用户设置好起始地址
I_fdma_waddr和传输大小I_fdma_wsize,然后将I_fdma_wareq拉高一个时钟周期。FDMA捕获到这个请求后,内部fdma_wstart_locked信号会锁存,O_fdma_wbusy随之变高,告诉外界“我开始忙了”。


733

被折叠的 条评论
为什么被折叠?



