我今年大三,准备参加2026年全国大学生FPGA大赛,想做一个基于Zynq的实时人脸检测项目。现在手头有Zynq-7020开发板,但不知道怎么把摄像头采集、图像预处理、人脸检测算法和HDMI显示串起来。有没有大佬分享过从零搭建AXI4-Stream流水线的经验?特别是怎么优化检测算法的延迟和资源占用,还有怎么处理多帧连续检测的稳定性?求详细步骤和避坑指南!
2026年,FPGA大赛备赛时如何从零搭建一个基于Zynq的实时人脸检测加速器?从摄像头驱动到AXI4-Stream流水线全流程讲解
提问
回答 6

说实话,你这个需求在Zynq上落地,最容易被忽略的不是算法本身,而是摄像头输入的时序匹配。很多人一上来就写HLS的人脸检测核,结果发现摄像头输出的像素时钟和数据valid信号跟AXI4-Stream握手规则对不上,要么丢帧要么整条流水线卡死。我的建议是:先把OV5640或者类似摄像头通过MIPI转并行接口接到PL端,用VDMA把原始帧写入DDR,再用AXI4-Stream把图像数据从DDR读出来喂给检测核——这样隔离了摄像头的不稳定时钟域。检测核建议分两级:第一级用肤色检测或Haar-like特征做粗筛,只输出候选区域的坐标和尺寸到BRAM,第二级用小型CNN(比如只有两层卷积+一层全连接)对候选区做二分类。粗筛部分用纯Verilog写,资源占用极低,流水线可以做到每个时钟输出一个像素;CNN部分用HLS写,但要手动给循环加pipeline和dataflow directive,否则综合出来的延迟会超过一帧时间。关于多帧稳定性:你需要在PS端维护一个简单的状态机,当检测到人脸后,锁定该区域的位置并做平滑滤波,防止下一帧因为光照或抖动突然丢失检测结果。另外,HDMI输出端建议用AXI4-Stream to Video Out IP核,配合OSD叠加一个矩形框,这样调试时肉眼就能看到效果。避坑指南里最重要的一条:先不要急着上人脸检测算法,先把摄像头的输入通过VDMA直接回显到HDMI上,确认整个像素通路和时序没问题,再一步步加入处理逻辑。你手头的是7020,逻辑资源大概53K LUT,做两级检测加显示绰绰有余,但BRAM很紧张,要优先给粗筛模块用。追问一句:你打算用哪款摄像头模块?是MIPI接口的OV5640还是并口的OV7670?这直接决定了PL端要不要额外加一个MIPI D-PHY接收IP,影响整个项目的前期进度。

先别想AXI4-Stream怎么搭,先拿一个简单的直通工程(摄像头进、HDMI出)跑通,再往里面塞你的检测核。否则你连摄像头帧率都调不对,后面全是白搭。

我去年备赛时踩过类似的坑,说一个核心取舍:不要在PL端做完整的人脸检测算法,尤其不要用HLS写复杂的CNN,7020的DSP slice只有220个,跑一次全图卷积延迟高到没法实时。建议把检测任务拆成PL粗筛加PS细判:PL端用滑动窗口加简单的肤色直方图判断,输出候选窗口的坐标列表到DDR,然后PS端用OpenCV的级联分类器(已移植到ARM)对每个候选窗口做最终判断。这样AXI4-Stream流水线只需要处理像素到直方图累加器的传输,非常规整。AXI4-Stream的关键是控制好tvalid/tready的握手机制,尤其是当检测核处理速度跟不上输入像素速率时,要用一个FIFO做背压缓冲。HDMI输出端直接用Video Timing Controller生成时序,把检测结果通过GPIO映射到OSD叠加层。多帧稳定性方面,PS端做个简单的卡尔曼滤波对检测框坐标做预测,能有效抑制抖动。另外,记得在PL端加一个帧中断信号给PS,用来同步帧计数,防止跨帧数据错乱。你目前是打算用HLS还是纯Verilog来写检测核?这个选择会决定你后续的仿真和调试工具链,建议早点定下来。

我去年做类似项目时走过一个弯路,就是太早开始调AXI4-Stream的握手时序,结果摄像头还没跑通就卡在仿真里好几天。说一个实际点的拆分思路:你可以把系统分成三个独立验证的阶段,不用一上来就追求全流水线。第一阶段,只做摄像头到DDR的写入,用VDMA把原始帧存进去,然后通过HDMI回显到显示器,验证传感器配置和像素时钟是否对劲。第二阶段,在PS端用OpenCV跑一个简单的Haar cascade,从DDR读帧处理后写到另一块缓存,再输出到HDMI,这一步帮你确认人脸检测的算法逻辑在ARM上能跑通。第三阶段,把检测核移植到PL,用AXI4-Stream代替原来PS端的像素读写。这样每一步都有可观测的输出,出了问题也能定位是驱动问题还是算法bug。另外,关于多帧连续检测的稳定性,常见做法是在PS端维护一个帧号寄存器,每次检测核完成一帧处理后写回一个完成标志,PS检测到新帧到来且上一帧已完成才下发下一帧的起始地址,否则丢弃当前帧。这样能避免流水线被一帧卡住导致后续帧全部丢掉的死锁情况。你目前摄像头型号定了吗?如果用的是MIPI接口的模块,还得加一个MIPI转并行桥,这个在7020上资源比较吃紧。

你问的是2026年比赛,现在还有大把时间,我觉得最值得投入的方向不是抄别人的流水线代码,而是把Zynq的异构计算思维吃透。很多参赛队最后做出来的东西看上去功能完整,但面试官一问为什么这里用PL不用PS、为什么选这个带宽的AXI总线,就答不上来。我建议你从两个角度深挖:第一个是数据流量的瓶颈分析。人脸检测的典型场景是1280×720@60fps,每个像素24bit,算下来每秒大概124MB的数据量。如果你的检测核只在PL端做一次pass,那么PL到PS的通信只传几千字节的坐标列表,压力很小;但如果你把整帧图像通过AXI4-Lite或者不合理的DMA配置来回搬运,带宽就会爆。所以设计流水线之前,先画一张数据流图,标清楚每个环节的带宽和存储需求,再决定哪些模块需要FIFO深度多少、时钟域是否跨接。第二个是资源换延迟的取舍。7020的BRAM只有4.9Mb,如果你用滑动窗口做肤色检测,每个窗口的直方图累加器如果全存在BRAM里,很快就撑爆了。一个替代方案是把图像切成tile,逐tile处理,tile的直方图存在分布式RAM里,这样多消耗一点LUT但节省BRAM。再比如CNN部分,如果你坚持要在PL端跑小型网络,可以考虑用二值化权重(BNN),资源占用能降到原来的十分之一,但精度大概从95%掉到88%左右。比赛评分一般看重实时性大于精度,你可以在答辩时明确说这是为了满足60fps的trade-off。最后,给一个学习路径的建议:不要直接从人脸检测开始,先做一个简单的边缘检测加速器——摄像头进、Sobel滤波、HDMI出,把VDMA、AXI4-Stream、FIFO背压、时钟域同步这四样东西跑通,再换复杂算法。你目前verilog和HLS哪个更熟?如果HLS经验不多,纯Verilog写检测核的工程周期会拉长很多,你得提前评估时间。

看到你选了7020这个片子,我多说一句容易被忽视的事:你的VDMA配置里,帧缓存的地址对齐和行间距(Stride)设置,直接决定了AXI4-Stream流水线能不能稳定跑多帧。很多人在单帧调试时没问题,一开连续检测就图像撕裂或检测框抖动,通常不是算法写错了,而是VDMA把下一帧数据写到了上一帧还没读完的地址上。建议你给VDMA配至少三个帧缓存(ping-pong-pang),PS端通过中断维护一个帧号寄存器,每次VDMA写完成中断后,PS把当前帧号写入一个AXI GPIO,PL端的检测核根据这个帧号去读对应缓存。这样流水线里每一帧的数据都是完整的,不会出现半帧混叠。另外,AXI4-Stream的TUSER信号可以用来传递帧起始和行起始,很多人只用TVALID和TLAST,结果像素数据和行列位置对不齐,检测窗口滑偏了。把TUSER拉高一个时钟作为帧同步,再配合TLAST做行同步,你的滑动窗口累加器就能准确复位,多帧检测的框位才能稳定。别一上来就调CNN,先把这三缓存的帧同步逻辑在ILA里抓到波形确认,再谈算法加速。你现在的摄像头接口是MIPI还是并行DVP?这个决定你前端时钟域处理的第一步。
发表回答
登录后可在本页底部提交回答
