目录
FPGA 图像缩放,串口指令控制输出分辨率,贴近真实项目,提供2套工程源码和技术支持
1、前言
没玩过图像缩放和视频拼接都不好意思说自己玩儿过FPGA,这是CSDN某大佬说过的一句话,鄙人深信不疑。。。本文使用Xilinx的Kintex7 FPGA实现图像缩放方案,视频源有两种,分别对应开发者手里有没有摄像头的情况,一种是使用廉价的OV5640摄像头模组或者HDMI输入接口;如果你的手里没有摄像头或者没有摄像头输入接口,则可使用代码内部生成的动态彩条模拟摄像头视频;视频源的选择通过代码顶层的`define宏定义进行选择,工程1默认使用ov5640作为视频源,工程2默认使用HDMI作为视频源;提供2套vivado2019.1版本的工程源码,2套工程源码的不同点在于默认的视频输入源不同,工程1默认使用ov5640作为视频源,输入分辨率为1280x720@30Hz,工程2默认使用HDMI作为视频源,输入分辨率为1920x1080@60Hz;
FPGA采集到输入视频后将其送入跨时钟FIFO,然后送入纯verilog代码实现的图像缩放模块,该模块支持任意尺寸的图像缩放,本例程设计了一个串口指令解析模块,通过上位机发送串口指令来控制图像缩放的输出分辨率,当然,输出分辨率是任意的,这取决于你的串口指令怎么控制;FPGA缩放后的视频,用我常用的FDMA套路进行图像缓存,缓存的介质为DDR3,然后读出视频,生成标准的1920x1080分辨率的VGA时序,再用纯verilog实现的RGB转HDMI模块将视频输出到显示器显示;项目工程高度贴近现实项目,不是实验室项目可以比拟的;
本博客详细描述了FPGA 图像缩放,串口指令控制输出分辨率的设计方案,工程代码可综合编译上板调试,可直接项目移植,适用于在校学生、研究生项目开发,也适用于在职工程师做学习提升,可应用于医疗、军工等行业的高速接口或图像处理领域;
提供完整的、跑通的工程源码和技术支持;
工程源码和技术支持的获取方式放在了文章末尾,请耐心看到最后;
版本更新说明
此版本为第2版,根据读者的建议,对第1版工程做了如下改进和更新:
1:增加了输入视频静态彩条的选择,有的读者说他手里没有OV5640摄像头或者摄像头原理图和我的不一致,导致在移植过程中困难很大,基于此,增加了静态彩条,它由FPGA内部产生,不需要外接摄像头就可以使用,使用方法在后文有说明;
2:优化了FDMA,之前的FDMA内AXI4的数据读写突发长度为256,导致在低端FPGA上带宽不够,从而图像质量不佳,基于此,将FDMA内AXI4的数据读写突发长度改为128;
3:优化了HDMI输出模块,之前用的自定义IP,有读者说IP无法更新,虽能正常使用,但看源码不方便,基于此,将HDMI输出模块改为纯verilog实现的,直接了当;
给读者的一封信
FPGA作为当今热门行业,入行门槛很高,工资待遇不错,一时间引无数英雄尽折腰,但很多初学者甚至工程师都还有很多误区,现给读者一封信如下:
1、矮要承认挨打站稳
要学FPGA,甚至吃这碗饭,每个人都是从零基础开始的,你对自己有自信,认为你行,就自学;你不自信,就找别人学;和古代拜师学艺是一回事儿;首先思维要符合逻辑;
2、基础问题需要自己解决
最基础的知识,比如:verilog语法、vivado工具使用、模电数电基础常识、电脑使用、计算机基本结构。。。这些基础知识在网上都是免费的,既有文字资料也有视频资料;这些基础知识你一定要具备,因为这是你能获得的性价比最高的东西了,首先它免费;其次它简单,只需要你花时间,不需要花脑子;最后它重要,这是你干FPGA的基础;
3、有了源码等于零
你可能认为,我有了源码就能做项目了,我可以肯定的告诉你,该醒醒了;原子弹的详细原理和原料配方甚至生产工艺流程在网上都是公开的,为啥全世界就那联合国几大流氓能造出来的?同样的,源码给你,你看得懂吗?你知道怎么用吗?看不懂不会用的源码,跟废物有什么区别?你需要的是源码+工程,最完美的是源码+工程+技术支持;有了源码,就有了可开发的底层架构,有了工程就知道源码或者模块怎么使用,有了技术支持就可以根据源码修改开发自己的项目;
4、先学会爬在学会跑
对于初学者,没有资格研究代码,你首先需要做的是对工程进行复现;比如给你一个图像的工程,你首先在自己的开发板上复现这个工程的功能,然后再去阅读理解代码,然后对代码的功能部分做小幅修改,比如改一下接口,增加几个输出接口,比如加一个LED输出;小幅修改后再慢慢增加修改幅度,以符合自己的需求;
5、学FPGA要不求甚解
学FPGA要不求甚解,甚至不需要理解,这句话咋听着有点不符合逻辑呢?对于很多功能性模块而言,你不需要理解它怎么实现的,你只需要知道怎么使用它,比如一个图像缩放模块,这种东西都是很老的知识,以你目前的知识水平,该模块的代码你怎么看也看不懂的,但你只要知道怎么使用它就行了,知道怎么使用,就能做项目,就能在公司呆下去了,原因很简单,老板招你来是干活儿的,不是招你来学习的,那是学校的事儿;如果要等什么都懂了才干活儿,那公司早垮了,学FPGA就是在实践中学习,先上前线去干活,边干边学,在实践中遇到问题,并主动去查资料问大佬理解问题,才是成长最快的,而不是一味的咬文嚼字刨根问底;
FPGA就业高端项目培训计划
鉴于目前的FPGA就业和行业现状,本博推出了FPGA就业高端项目培训:纯verilog图像缩放 工程解决方案的计划,该计划旨在让一部分人先学会FPGA纯verilog图像缩放,提高从业者的技术水平和工资待遇,详细计划如下:
FPGA就业高端项目培训计划细节:
1、我发你上述17套工程源码和对应的工程设计文档网盘链接,你保存下载,作为培训的核心资料;
2、你根据自己的实际情况安装好对应的开发环境,然后对着设计文档进行浅层次的学习;
3、遇到不懂的随时问我,包括代码、职业规划、就业咨询、人生规划、战略规划等等;
4、每周末进行一次腾讯会议,我会检查你的学习情况和面对面沟通交流;
5、你可以移植代码到你自己的FPGA开发板上跑,如果你没有板子,你根据你自己的需求修改代码后,编译工程,把bit发我,我帮你下载到我的板子上验证;
免责声明
本工程及其源码即有自己写的一部分,也有网络公开渠道获取的一部分(包括CSDN、Xilinx官网、Altera官网等等),若大佬们觉得有所冒犯,请私信批评教育;基于此,本工程及其源码仅限于读者或粉丝个人学习和研究,禁止用于商业用途,若由于读者或粉丝自身原因用于商业用途所导致的法律问题,与本博客及博主无关,请谨慎使用。。。
2、相关方案推荐
本工程是图像缩放和视频拼接的整合版,在此之前,我分别推出过FPGA图像缩放方案和FPGA视频拼接方案,所以推荐如下:
FPGA图像缩放方案推荐
该方案使用纯verilog代码实现任意尺寸图像缩放,详细请参考我之前的博客,博客链接如下:
直接点击前往
FPGA视频拼接方案推荐
该方案使用纯verilog代码实现多路视频拼接,详细请参考我之前的博客,博客链接如下:
4路视频拼接方案参考博客链接如下:直接点击前往
8路视频拼接方案参考博客链接如下:直接点击前往
16路视频拼接方案参考博客链接如下:直接点击前往
FPGA串口指令解析方案推荐
本设计使用串口发送指定协议的指令帧来控制图像缩放的输出分辨率,这是一个由本人独立设计开发的具有个人特色的串口指令帧,具体协议可以自定义,这个FPGA串口指令解析方案目前已经更新到了第四版本,本设计正是使用的此版本,之前写过一篇博客,感兴趣的可以前往查看,博客链接如下:直接点击前往
3、设计思路框架
提供2套vivado2019.1版本的工程源码,2套工程源码的不同点在于默认的视频输入源不同,工程1默认使用ov5640作为视频源,输入分辨率为1280x720@30Hz,工程2默认使用HDMI作为视频源,输入分辨率为1920x1080@60Hz;
FPGA采集到输入视频后将其送入跨时钟FIFO,然后送入纯verilog代码实现的图像缩放模块,该模块支持任意尺寸的图像缩放,本例程设计了一个串口指令解析模块,通过上位机发送串口指令来控制图像缩放的输出分辨率,当然,输出分辨率是任意的,这取决于你的串口指令怎么控制;FPGA缩放后的视频,用我常用的FDMA套路进行图像缓存,缓存的介质为DDR3,然后读出视频,生成标准的1920x1080分辨率的VGA时序,再用纯verilog实现的RGB转HDMI模块将视频输出到显示器显示;项目工程高度贴近现实项目,不是实验室项目可以比拟的;
工程1设计框图如下:
工程2设计框图如下:
视频源选择
视频源有两种,分别对应开发者手里有没有摄像头的情况,一种是使用廉价的OV5640摄像头模组或者HDMI输入接口;如果你的手里没有摄像头或者没有摄像头输入接口,则可使用代码内部生成的动态彩条模拟摄像头视频;视频源的选择通过代码顶层的宏定义进行选择,工程1默认使用ov5640作为视频源,工程2默认使用HDMI作为视频源;
视频源的选择通过代码顶层的`define宏定义进行;如下:
工程1和工程2的视频源选择逻辑代码部分分别如下:
选择逻辑如下:
当(注释) define USE_SENSOR时,输入源视频是动态彩条;
当(不注释) define USE_SENSOR时,工程1的输入源视频是ov5640摄像头;工程2的输入源视频是HDMI;
OV5640摄像头配置及采集
OV5640摄像头需要i2c配置才能使用,需要将DVP接口的视频数据采集为RGB565或者RGB888格式的视频数据,这两部分均用verilog代码模块实现,代码位置如下:
其中摄像头配置为分辨率1280x720,如下:
摄像头采集模块支持RGB565和RGB888格式的视频输出,可由参数配置,如下:
RGB_TYPE=0输出本RGB565格式;
RGB_TYPE=1输出本RGB888格式;
设计选择RGB565格式;
IT6802解码芯片配置及采集
IT6802解码芯片需要i2c配置才能使用,关于IT6802解码芯片的配置和使用,请参考我往期的博客,博客地址:点击直接前往
IT6802解码芯片配置及采集这两部分均用verilog代码模块实现,代码位置如下:
代码中配置为1920x1080分辨率;
动态彩条
动态彩条可配置为不同分辨率的视频,视频的边框宽度,动态移动方块的大小,移动速度等都可以参数化配置,工程1配置为辨率1280x720,工程2配置为辨率1920x1080;动态彩条模块代码位置和顶层接口和例化如下:
工程1和工程2分别例化如下:
缓冲FIFO
缓冲FIFO的作用是为了解决跨时钟域的问题,当视频不进行缩放时不存在视频跨时钟域问题,但当视频缩小或放大时就存在此问题,用FIFO缓冲可以使图像缩放模块每次读到的都是有效的输入数据,注意,原视频的输入时序在这里就已经被打乱了;
图像缩放模块详解
设计框图
本设计将常用的双线性插值和邻域插值算法融合为一个代码中,通过输入参数选择某一种算法;代码使用纯verilog实现,没有任何ip,可在Xilinx、Intel、国产FPGA间任意移植;代码以ram和fifo为核心进行数据缓存和插值实现,设计架构如下:
视频输入时序要求如下:
输入像素数据在dInValid和nextDin同时为高时方可改变;
视频输出时序要求如下:
输出像素数据在dOutValid 和nextdOut同时为高时才能输出;
代码框图
代码使用纯verilog实现,没有任何ip,可在Xilinx、Intel、国产FPGA间任意移植;
图像缩放的实现方式很多,最简单的莫过于Xilinx的HLS方式实现,用opencv的库,以c++语言几行代码即可完成,关于HLS实现图像缩放请参考我之前写的文章HLS实现图像缩放
网上也有其他图像缩放例程代码,但大多使用了IP,导致在其他FPGA器件上移植变得困难,通用性不好;相比之下,本设计代码就具有通用性;代码架构如图;
其中顶层接口部分如下:
2种插值算法的整合与选择
本设计将常用的双线性插值和邻域插值算法融合为一个代码中,通过输入参数选择某一种算法;
具体选择参数如下:
input wire i_scaler_type //0-->bilinear;1-->neighbor
通过输入i_scaler_type 的值即可选择;
输入0选择双线性插值算法;
输入1选择邻域插值算法;
关于这两种算法的数学差异,请参考我之前写的文章HLS实现图像缩放
图像缓存
经常看我博客的老粉应该都知道,我做图像缓存的套路是FDMA,他的作用是将图像送入DDR中做3帧缓存再读出显示,目的是匹配输入输出的时钟差和提高输出视频质量,关于FDMA,请参考我之前的博客,博客地址:点击直接前往
需要注意的是,为了适应本工程需求,我对之前的FDMAA控制器做了修改并重新封装,新的FDMA控制器如下:
串口指令解析和控制
本方案使用串口指令来控制图像缩放的输出分辨率,串口指令由PC端通过串口调试助手发送,在嵌入式项目中,也可以通过Linux、单片机、DSP、ARM等软件发送,串口指令以帧的格式发送,指令帧协议如下:
串口协议帧控制缩放分辨率协议如下:
串口协议帧的数据段的高两个字节决定输出分辨率的宽;
串口协议帧的数据段的低两个字节决定输出分辨率的高;
比如:
有效数据0x05,0x00,0x02,0xd0表示输出1280x720的视频;
有效数据0x03,0x20,0x02,0x58表示输出800x600的视频;
有效数据0x07,0x80,0x04,0x38表示输出1920x1080的视频;
出于测试目的,我在FPGA代码里仅设置了如下几种分辨率供串口指令控制,如下:
串口协议帧的数据段=0x050002d0-->输出分辨率1280x720@60Hz
串口协议帧的数据段=0x03200258-->输出分辨率800x600@60Hz
串口协议帧的数据段=0x028001e0-->输出分辨率640x480@60Hz
串口协议帧的数据段=0x05000400-->输出分辨率1280x1024@60Hz
串口协议帧的数据段=0x0690041a-->输出分辨率1680x1050@60Hz
串口协议帧的数据段=0x07800438-->输出分辨率1920x1080@60Hz
串口发送指令控制缩放模块逻辑如下:
always @(*) begin
if(~rst_n) begin
disp_h='d1280;
disp_v='d720;
end
else if(o_rx_data==32'h050002d0) begin //1280x720
disp_h='d1280;
disp_v='d720;
end
else if(o_rx_data==32'h03200258) begin //800x600
disp_h='d800;
disp_v='d600;
end
else if(o_rx_data==32'h028001e0) begin //640x480
disp_h='d640;
disp_v='d480;
end
else if(o_rx_data==32'h05000400) begin //1280x1024
disp_h='d1280;
disp_v='d1024;
end
else if(o_rx_data==32'h0690041a) begin //1680x1050
disp_h='d1680;
disp_v='d1050;
end
else if(o_rx_data==32'h07800438) begin //1920x1080
disp_h='d1920;
disp_v='d1080;
end
else begin //1280x720
disp_h='d1280;
disp_v='d720;
end
end
具体操作如下:
上电后默认输出原图分辨率为1280x720;
串口指令分辨率参数同时传递给图像缩放模块、FDMA控制器和VGA时序模块;
如果串口指令分辨率小于原图,则控制图像缩放模块做缩小操作;将缩小后的分辨率给FDMA将制定分辨率的图片写入DDR3缓存后输出,同时VGA时序模块只输出制定大小的有效图像,即缩小后的分辨率图像;
如果串口指令分辨率大于原图,则控制图像缩放模块做放大操作;将缩小后的分辨率给FDMA将制定分辨率的图片写入DDR3缓存后输出,同时VGA时序模块只输出制定大小的有效图像,即放大后的分辨率图像;
下面给出串口指令发送举例:
视频输出
视频从FDMA读出后,经过VGA时序模块和HDMI发送模块后输出显示器,VGA时序模块受串口指令控制;代码位置如下:
VGA时序配置为1280X720,HDMI发送模块采用verilog代码手写,可以用于FPGA的HDMI发送应用,关于这个模块,请参考我之前的博客,博客地址:点击直接前往
4、vivado工程1:OV5640输入版本
开发板FPGA型号:Xilinx–Kintex7–xc7k325tffg676-2;
开发环境:Vivado2019.1;
输入:OV5640摄像头或动态彩条,分辨率1280x720;
输出:HDMI,串口控制图像缩放输出分辨率;
工程应用:FPGA 串口控制图像缩放输出分辨率;
工程BD如下:
工程代码架构如下:
工程的资源消耗和功耗如下:
5、vivado工程2:HDMI输入版本
开发板FPGA型号:Xilinx–Kintex7–xc7k325tffg676-2;
开发环境:Vivado2019.1;
输入:笔记本电脑模拟HDMI视频输入或者动态彩条,IT6802解码,分辨率1920x1080;
输出:HDMI,串口控制图像缩放输出分辨率;
工程应用:FPGA 串口控制图像缩放输出分辨率;
工程BD如下:
工程代码架构如下:
工程的资源消耗和功耗如下:
6、工程移植说明
vivado版本不一致处理
1:如果你的vivado版本与本工程vivado版本一致,则直接打开工程;
2:如果你的vivado版本低于本工程vivado版本,则需要打开工程后,点击文件–>另存为;但此方法并不保险,最保险的方法是将你的vivado版本升级到本工程vivado的版本或者更高版本;
3:如果你的vivado版本高于本工程vivado版本,解决如下:
打开工程后会发现IP都被锁住了,如下:
此时需要升级IP,操作如下:
FPGA型号不一致处理
如果你的FPGA型号与我的不一致,则需要更改FPGA型号,操作如下:
更改FPGA型号后还需要升级IP,升级IP的方法前面已经讲述了;
其他注意事项
1:由于每个板子的DDR不一定完全一样,所以MIG IP需要根据你自己的原理图进行配置,甚至可以直接删掉我这里原工程的MIG并重新添加IP,重新配置;
2:根据你自己的原理图修改引脚约束,在xdc文件中修改即可;
3:纯FPGA移植到Zynq需要在工程中添加zynq软核;
7、上板调试验证并演示
准备工作
你需要有以下装备才能移植并测试该工程代码:
1:FPGA开发板;
2:OV5640摄像头,如果没有也可以,就选择动态彩条;
3:HDMI传输线;
4:HDMI显示,要求分辨率支持1920x1080;
5:串口调试助手,我已放在资料包中,并将串口调试助手配置如下:
静态演示
工程1:串口指令控制ov5640摄像头图像缩放输出如下:
工程1:串口指令控制动态彩条图像缩放输出如下:
工程2:串口指令控制HDMI图像缩放输出如下:
动态演示
动态视频演示如下:
FPGA图像缩放-串口-16比9
8、福利:工程源码获取
福利:工程代码的获取
代码太大,无法邮箱发送,以某度网盘链接方式发送,
资料获取方式:私,或者文章末尾的V名片。
网盘资料如下:
此外,有很多朋友给本博主提了很多意见和建议,希望能丰富服务内容和选项,因为不同朋友的需求不一样,所以本博主还提供以下服务: