我是文章摘要….
【集创赛】紫光同创杯国一的心路历程
1 写在前面
好多佬们问我开不开源,这个等我考完研吧,先写一篇学习路线给大家参考,同时鼓励大家多多参与科创竞赛,相信自己,只要肯学,都会有的。
up算是一个小白,用了八个月时间全栈过了一遍FPGA,上位机开发,YOLO模型部署,本来以为能够稳3争2, 没想到拿了国一,也算是运气比较好吧。当然也付出了相当多的努力,别人开始考研的时候我还在学FPGA,每天早上8点学到晚上11点,有时候会熬夜加班,分赛区决赛和全国总决赛基本上通宵干活的。
//************************************************防杠声明**************************************************//
up只是小白,如果文中有技术错误or讲不清楚的地方,欢迎各位大佬评论区批评指正
//************************************************防杠声明**************************************************//
1.1 专业背景
up是微电子学院,集成电路设计与集成系统专业的,大二(2022年)有FPGA的专业课,学习了一些基础的verilog语法,用zynq7020做了一个硬件串口。
实际上up的基础一般,跟视频相关,接口相关(VESA HDMI PCIE ETH HSST)也是一点点学起来的,大家大可以把我当作小白。
因为对FPGA有那么点熟悉,所以集创赛选择赛道的时候选择了FPGA赛道,又对视频处理有那么一点点兴趣,所以选择了紫光同创杯。
1.2 团队分工
三人小队原始分工:
up本人:FPGA数据链路和算法;
队友A:PCIe上位机;
队友B:上位机YOLO模型部署;
实际分工:
up本人:全栈过了一遍FPGA设计,上位机设计,YOLO模型部署和优化;
队友A:六七月去了夏令营,PCIe上位机没做完,被up接手了,八月回来做上位机GUI优化和一部分视频算法;
队友B:前期完成了yolo的部署和部分功能的实现,另一方面为三人小队顶住了课业压力(小学期实习课程团队答辩),七八月暑假回家了,在他指导下up一周速通了yolo的环境搭建和部署,后续又做了软件的优化,模型的量化和加速;
1.3 心路历程
原谅我垃圾的版本控制(雾
- 1~2月:选定赛题,开始学习FPGA(可以看看我B站笔记的),学习VESA规格,X家的DMA IP,VDMA IP等等,初步了解帧缓存、AXI协议等等;
- 3月:忙着开学考试、做学院的PPT,我们跟组委会借了板子,也自己买了一块,三月底开始尝试PDS和板子的一些基础功能,跟着奇哥复习AXI总线(奇哥的AXI真的讲的很透彻,建议大家都看看,资料汇总我放在后面),三月底基本上了解紫光DDR IP的使用,开始尝试经过DDR帧缓存的环回;
- 4月:四月初做完了一路AXI主机的DDR缓存,实现了HDMI视频环回;然后开始了解视频缩放,根据双线性插值算法,自己写了verilog逻辑(有点费资源);四月中下旬完善了四路AXI主机和AXI仲裁器,做完了HDMI四路的视频环回,后续买了双目摄像头,又改成了摄像头输入两路,不过bug不断,debug了很长时间;四月下旬开始学习PCIe协议,同时了解紫光PCIe IP的使用;这个时候视频环回的链路已经基本实现了;
- 5月:校运会来了,学生会忙起来了,做项目时间减少,同时五月底还有专业课考试,忙起来了;继续研究PCIe,写了几个PCIe demo让队友做测试(有点像黑箱,一点点试,不过看紫光IP核给的仿真会清晰很多,配置过程,DMA过程等等,笔记放后边);初赛交作品前已经实现了PCIe抓取单帧图片传输并保存为bmp文件,不过由于当初没考虑到大小端转换,所以传的图片有撕裂,而且色彩有问题;另外没有考虑好上位机怎么和YOLO传输数据;
- 6月:一边开发FPGA的以太网UDP协议,一边摸鱼,等分赛区决赛结果,跟着正点原子过了MDIO,RGMII转GMII,ARP和UDP协议;进分赛区决赛后开始加足马力继续肝项目,这时候队友A去夏令营了,所以PCIe上位机被我接手了,摸清楚上位机结构之后,修修补补实现了PCIe抓取视频流并显示,通过虚拟摄像头传递给YOLO识别(这里是GPT提醒我们能够使用v4l2,队友B最后通过ffmpeg实现了视频流传递)
- 7月:一边是小学期生产实习课程压力(这里感谢队友B帮我顶住了小组答辩的压力,让我有时间专注项目),一边是继续肝项目,在紫光PCIe测试平台的基础上,up改了一套测试平台v2.0,另外以太网遇到了点问题,分赛区决赛前没调出来(国赛也没调出来);分赛区决赛,东北赛区五进一,没想到我们完成度相对来说很高,此时已经实现了HDMI输入,双目OV5640输入拼接,HDMI输出,PCIE输出,上位机能够顺利抓取和给YOLO识别,识别帧率40FPS左右(已经通过TensorRT加速),最后一等奖进了国赛。七月下旬队友B放假回家,我留校继续做项目,一个周速通YOLO,一个周对软件代码做了优化,帧率从40FPS提高到60FPS。
- 8月:放假了,专注项目,队友A回归,开始做视频算法,做了直方图均衡,但是对彩色的并不友好,放弃了,做了简单的RGB YUV转换,在Y分量上操作,简单的视频增强,接着去做上位机GUI优化;我继续用一个周调网口,环回输入没调出来,但是做了以太网上位机;我继续用三天速通了光口,参考IEEE 802.3写了握手协议。最后只给了半个周来做PPT和文档完善,时间实在不够,我一边做文档一边又再看yolov8,最后提供了多种模型以供选择,19号从大连飞重庆,在机场延误四个小时,差点没交上作品,PPT和文档没做好是遗憾之一。
2 FPGA设计
2.1 结构框图
提供了两种设计方案,由于PLG50H只有一个HSST资源,所以PCIE 光口不可兼得。
以双板方案为例,开发板1负责视频采集和拼接,提供了HDMI输入、缩放后通过光口环回,两路视频输入,OV5640两路视频输入,通过四路AXI主机仲裁实现帧缓存,输出时对四路画面进行拼接;开发板2负责图传,视频信号通过HDMI与开发板1连接,有一路AXI主机帧缓存,提供HDMI、PCIE、ETH三种输出方式。
单板设计方案:
双板设计方案:
输入视频规格:
视频链路 | 分辨率 | 刷新率 | 色彩格式/色深 |
---|---|---|---|
HDMI | 1920x1080 | 60Hz | RGB888 |
OV5640 | 960x540 | 30Hz | RGB565 |
内部数据链路 | - | 与视频源相同 | 32bits |
*HSST光纤环回 | 960x540 | 60Hz | RGB565 |
2.2 双线性插值算法
双线性插值算法是根据网上的原理来写的,用了RAM资源来缓存,主要是确保好RAM或者FIFO预读出正确就行,保证de和像素数据同步,最后实现了1080P->540P,但是我这样写似乎比较浪费资源,有大佬有更好的写法
2.3 AXI主机仲裁器与帧缓存
为了保证视频正常输出,通过DDR缓存是必要的,紫光的DDR IP是精简的AXI FULL接口,所以AXI协议肯定要整明白,建议大家啃ARM的手册,另外可以和奇哥学,B站有视频(FPGA奇哥,链接放后面),讲的很透彻。
使用四路帧缓存设计,AXI主机能够实现地址自增、帧缓存切换等功能,同时读写状态机独立设计
为了保证四路视频正确缓存,还需要有序地把AXI主机接入DDR IP,多路视频缓存可以参考正点原子双目OV5640的例程,看看他的状态机设计和接入方法,这里我是自己写了仲裁器的读写状态机,对于不同的输入都有较好的兼容性。仲裁器根据每路FIFO的水位控制AXI握手。
这里debug了好久,修修补补,所以整体跳转逻辑有点乱。
帧缓存设计:
AXI写仲裁:
AXI主机写操作:
AXI读仲裁:
AXI主机读操作:
2.4 视频拼接和HDMI输出
这里是用了一个能够产生VESA时序的模块(本质上是计数器),能供提供vs,hs,de和输出扫描的xy坐标,根据上述信号控制每路读FIFO输出即可。要控制好输出像素和de信号对应,不然输出会出现倾斜或者错位。
2.5 PCIe接口
这部分可以算是比赛的一个难点之一,但是大家进国赛了基本上都做出来了。
首先是要学习PCIe协议,这里推荐一个大佬写的:http://blog.chinaaet.com/justlxy/p/5100053251,主要要理解PCIe TLP 和 Header类型,发送数据用Mwr 32比较多
然后还要看紫光的PCIe怎么用,这里要看他仿真的过程,RC如何配置EP,RC如何操控EP进行DMA,仿真看懂了可以上板子,通过debug核抓信号,进一步验证。最后再自己魔改,写verilog和上位机,发送符合协议要求的TLP包,紫光这个PCIe IP给的是AXI-S接口,还算好用。
另外要多看IP手册,了解引脚定义和功能,以及例程的相关说明;
而且PCIe需要搭配上位机食用,上位机主要涉及配置PCIe,分配DMA空间,控制FPGA采集,释放DMA空间。
2.6 以太网接口
以太网可以跟着正点原子的FPGA课程学习,了解MDIO、RGMII转GMII、ARP、UDP等,RGMII转GMII可以参考小眼睛官方给的例程。
这里遇到的一个问题,就是开发板的两个网口对接之后(本来想做环回的),一个网口gmii转出来的rx_error信号一直拉高,另一个网口gmii的valid信号一直拉高,根本没法用,但是跟电脑网口或者其他开发板网口对接就没有这种问题。这个问题困扰了两个月,一直没有解决。决赛答辩的时候问了这个问题,徐工说可能是rx_delay设置的问题,这个还没有尝试。
由于上面这个问题,环回输入没做成,想让开发板和另一块开发板做远端环回的,但是存在断连的情况,有时候发送着发送着灯就灭了,画面停顿,过了几秒两个网口重新自协商继续传输。
最后只做了以太网发送视频到上位机,基于UDP协议,实现540P视频的发送,但是丢包严重,不得不在每个UDP包里面加上序号保证丢包不会造成大规模画面撕裂;
2.7 HSST 光模块
首先是看IP手册,然后看例程的仿真,观察HSST怎么工作的。
这里有个坑点是HSST IP不完整,还需要用户自己实现握手,在复位后发送有序集和组码进行握手,字节对其,参考IEEE 802.3 36小节。
在这基础上可以把HSST当成一个提供了GMII接口的PHY芯片,我在上面又套了一个UDP协议。
3 上位机设计
3.1 GUI设计
紫光的PCIe测试平台魔改过来的,可视化界面用的gtk库,用法和QT很像,照猫画虎地增加了很多功能。
3.2 PCIe上位机
紫光原本提供的PCIe测试平台只能在ubuntu16.04使用,后来我迁移到了ubuntu23.04,主要是linux PCIe分配DMA内存和释放内存的函数有了更新,旧版函数没办法在新系统里面使用。
PCIe上位机主要是要看懂官方给的代码和功能对应的关系,如何分配内存,如何通知FPGA开始DMA操作,看懂了才能魔改驱动。原本限制DMA大小4096Byte,我们改成了DMA大小是4096x1024Byte,刚好大于1920x1080x2Byte,可以用于视频传输。
上位机同样是用了帧缓存设计,根据PCIe TLP包带的数据判断哪一帧是最新帧,从而让程序把数据从内核态传递给用户态,再在用户态对视频数据做处理。
3.3 以太网上位机
以太网上位机比PCIe上位机好写多了,由于底层驱动网卡厂家给你写好了,只需要会用socket编程就行,网上大把资料,用socket绑定好网口之后接手就行。
另外如果有能力可以用ARP和开发板交换一下IP和MAC,不然用静态IP也行。
3.4 上位机的数据链路
在GPT的提醒下,我们使用了V4L2和FFMPEG,将视频流传递给/dev/video0,YOLO和其他应用调用虚拟摄像头就可以读取到视频流。
上位机集成的YOLO开关通过.sh脚本实现C对python的调用。
4 AI算法部署
4.1 模型选择和数据集处理
这里我们选择了YOLO的模型,提供了YOLO V5S V5M V8N V8S V8M多个模型以供调用,均训练了150轮。(下面这个图我们费了老大劲了,在AUTODL平台上租了卡连着跑了好久,虽然理论上v8要好不少,但是实际检测的时候感觉v5效果更好一些)
关于YOLO,CSDN上有很多资料,保姆级手把手教你配环境,标注,划分数据集,训练,检测。部署好YOLO之后可以看看YOLO检测代码(detect.py)的解读,如果不需要深入理解,看懂检测代码也就够了。
另外YOLO V8把各种功能都封成API了,所以建议参考YOLO官方文档,看懂了v5,学v8也很快。
我们选用了官方提供的交通灯数据集(VOC数据集中的一个小类好像),但是确实一般,训练好后map只有0.65+,国一的几支队伍好像没用官方给的,而是直接用了COCO。
4.2 模型量化和加速
量化主要是将FP32转换为FP16,上面的图可以看见速度提高了很多;
加速使用了英伟达的TensorRT推理框架,原理不多介绍,在降低一些精度的情况下大幅提高了推理速度,部署CSDN上也有很多。
另外16:9输入的视频,在YOLO选择输入图片参数的时候可以将640x640改成384x640,这样速度会快很多,反正宽度不够的也是补无用数据。
4.3 软件优化
其实v5官方提供的代码有一个问题,用opencv库进行数据的载入和显示(cv2.read()和cv2.imshow()),这很吃CPU和内存,通过line_profiler性能分析工具可以分析每段代码的用时,尝试了多种方法之后发现子线程输入,主线程推理,子进程显示的帧数最高,从40FPS提高到了60FPS,这算是我们一个创新点。
这里补充一句,Python的效率是不如C++的,不过up是小白,Python会比较友好,用C++写YOLO性能会好不少。
ps.赛题完成情况:
5 学习资料汇总
5.1 他山之石,可以攻玉
- 小眼睛官方例程
- 紫光IP手册(不管是谁家,手册肯定是要啃的)
- 正点原子FPGA开发指南(正点原子资料开源,而且对新手友好,很多设计可以参考),视频教程:https://www.bilibili.com/video/BV1Ec411K791/?spm_id_from=333.999.0.0&vd_source=789bfbff82733918b995c9c278a70ea0
- 各种协议的原始文档(如AMBA IEEE 802.3等)
- AXI和其他FPGA设计学习资料:FPGA奇哥
- PCIe学习资料:http://blog.chinaaet.com/justlxy/p/5100053251
- 手把手搭建yolov5:https://www.bilibili.com/video/BV1f44y187Xg/?spm_id_from=333.999.top_right_bar_window_custom_collection.content.click&vd_source=789bfbff82733918b995c9c278a70ea0(这个up在CSDN有图文教程)
- 一行行读懂yolov5:https://www.bilibili.com/video/BV1Dt4y1x7Fz/?spm_id_from=333.337.top_right_bar_window_custom_collection.content.click&vd_source=789bfbff82733918b995c9c278a70ea0(看懂了就可以瞎改v5了)
5.2 UP自己的笔记
我认为养成做工程写blog的习惯很重要,所以一路上做了很多笔记,之前是在b站记的,但是感觉编辑器不友好,所以改用有道云了。
防杠声明,由于笔记是随着工程一点点写的,早期工程有bug,后续改进后笔记没更新,大家做个参考即可。
1.紫光DDR IP与Modelsim的安装与使用:
https://note.youdao.com/s/9yuHHCgu
2.VESA Monitor Timing Standard 时序实现与HDMI输出:
https://note.youdao.com/s/ExhGhZTu
3.基于紫光FIFO IP和DDR IP的HDMI环回实验
https://note.youdao.com/s/KmRKDEAm
4.基于FPGA的双线性插值法实现视频缩放
https://note.youdao.com/s/LZGig5Lo
5.AXI多主机单从机仲裁器与四路视频环回
https://note.youdao.com/s/XnX3b3fq
6.解构紫光PCIE IP
https://note.youdao.com/s/U6H3m1a6
7.以太网接口与协议
https://note.youdao.com/s/aGw6AUt2
8.解构紫光HSST IP
https://note.youdao.com/s/BCYt4itk
*PDS啸寄巧:
https://note.youdao.com/s/G8B3qWwS
写完了,希望大家给up一个关注+三连!!!有问题可以在b站留言,有道云的评论不一定能看到。
2023.9.22 尝试在github搭建了blog,后续可能会考虑更细其他blog或者项目上去,欢迎大家关注啊
Hello World
Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.
Quick Start
Create a new post
1 | $ hexo new "My New Post" |
More info: Writing
Run server
1 | $ hexo server |
More info: Server
Generate static files
1 | $ hexo generate |
More info: Generating
Deploy to remote sites
1 | $ hexo deploy |
More info: Deployment