FPGA 20个例程篇:19.OV7725摄像头实时采集送HDMI显示(四)

news2024/9/23 1:39:07

第七章 实战项目提升,完善简历

19.OV7725摄像头实时采集送HDMI显示(四)

        在介绍完OV7725初始化配置和视频采集模块后,就到了整个项目的核心部分即DDR3乒乓存储图像模块,为了实现整个FPGA项目工程当中良好的实时性,乒乓操作在广泛应用在FPGA视频加速处理和数字信号处理中。

       关于乒乓操作,有很多的FPGA相关书籍都多多少少做了一些介绍,但是相信和大部分朋友一样,笔者在最初学习FPGA的时候也阅读了不少相关介绍乒乓操作的书籍,可以说几乎连描述性文字都大同小异,从头到尾来回读上很多遍也没能体会到乒乓操作存在的意义和具体地实现方式,只能体会到书籍作者想要表达对于BRAM空间或者DDR3/SDRAM颗粒不同内存地址需要来回切换读写。

      在这里大家可以从下面几个地方去思考,这也是实际项目工程实施落地中所必须面对的:1.为什么要做乒乓操作;2. 什么时候做乒乓操作;3. 怎么去做乒乓操作;4.什么是局部乒乓和全局乒乓;5.在FPGA视频研发当中,乒乓操作和多帧缓存有何异同。

      借助这个例程来逐一解答上面的这些问题,大家可以先简单地把整个视频图像采集系统理解成:输入OV7725实时采集到的视频是640*480*30帧数据流,其时钟频率是12Mhz,而输出的HDMI实时显示的视频源是640*480*60帧数据流,其时钟频率是25Mhz。

       整个设计中就存在大量跨时钟域的数据需要同步,为了方便理解我们去进一步简化模型,假设采集图像和显示图像两者同时进行,因为HDMI读取外部内存的速度近乎快于OV7725摄像头写入外部内存的速度的两倍。

       那么不妨站在HDMI显示角度来看整个模型,也是假设采集和显示完完全全时钟同步,如图1所示,T0时刻结束时,因为只有1/2个图像帧数据存储写入外部内存中,屏幕去读取外部内存就显示了空白和1/2帧数据图像;在T1时刻结束,屏幕刚好显示完全第一帧数据图像;在T2时刻结束,屏幕显示了1/2第一帧图像和1/2第二帧图像;在T3时刻结束,HDMI刚好显示完全第二帧数据图像。

       但是回归到现实在实际工程当中,首先不能保证采集和显示时钟是完全同步的,这只是一种理想的模型;其次项目当中使用的摄像头种类不尽相同,这也就意味者未必是刚好每秒采集30帧图像;再次两者写入和读取外部内存时,往往是以两端读写FIFO的数据数量作为判断的条件,而两个FIFO也是相互独立,所以如果我们不做任何处理,单纯使用外部内存进行单帧存储图像的话,各个时刻内HDMI显示的图像,图像之间帧与帧几乎必然会交错在一起。

图1 DDR3/SDRAM进行单帧存储示意图

        通过上面的模型分析,这也就回答了第一个和第二个问题,如果我们不做乒乓操作的话,因为采集图像和显示图像之间显然存在各种不同步性,也必然将导致图像显示会时时刻刻出现帧与帧之间的交错现象,那么对于一个采集处理显示系统来说没有任何实时性可言。

        当一个系统需要良好的实时性比如在视频加速处理实时显示时,在数模转换芯片DAC实时计算并输出波形时,通常便会考虑到流水线设计、乒乓操作、多帧缓存等技术,让用户完全感觉不出FPGA在做并行运算处理过程中所产生的不连贯,极大地提高了整个系统实时可靠性,这也就是FPGA设计当中经常说到的以空间换时间。

      然后再来结合这个例程,回答第三个问题即怎么去做乒乓操作,如图2所示是片外DDR3/SDRAM乒乓读写示意图,豌豆开发板上板载了一颗存储大小是128Mb的镁光原装DDR3颗粒,因为DDR3颗粒的读写数据速度要远远快于12Mhz和25Mhz,所以完全可以作为乒乓操作片外读写数据的缓存。

       OV7725 CMOS Sensor实时采集图像数据,再通过图像输入数据选择模块先写入DDR3颗粒Bank0地址空间,而图像输出数据选择模块在这段时间会一直读取DDR3颗粒Bank1地址空间的数据传输给下游,接着按照HDMI送显的时序显示Bank1中所存储的图像数据,在一帧640像素*480像素的数据写入Bank0地址空间完毕后,这时候切换读写内存的地址空间,即新的一帧640像素*480像素的数据会去写入Bank1地址空间,而图像输出数据选择模块在这段时间会一直读取DDR3颗粒Bank0地址空间的数据,HDMI在这段时间又在显示Bank0中所存储的图像数据,来回交替重复依次循环。

图2 片外DDR3/SDRAM乒乓读写示意图

        接着我们再来回答第四个问题,这也是非常重要的概念,即什么是局部乒乓和全局乒乓,不少FPGA书籍对此隐隐约约提及到,但是不作为重点也没有展开描述,其实真正搞清楚这个概念,对于整体设计层面上的理解会有很大帮助。

       “局部乒乓”就是说只站在数据写入端去看整个设计,当写完一帧完整的图像数据到数据缓存区Bank0就直接切换地址去写入另外一块Bank1;而“全局乒乓”则是说站在数据写入端和数据读取端去看整个设计,当写完一帧完整的图像数据到数据缓存区Bank0并且数据读取端也从Bank1读完了一帧完整的图像数据后,这时候再去切换读写地址,实际项目工程中通常会去使用“全局乒乓”,虽然可能代码层面上设计比较麻烦些,但是通过“全局乒乓”的操作,可以很大程度上保证画面显示的完整性,不会因为像“局部乒乓”一样,因为一帧图像写入完全而另一帧图像没有读取完全的时候,如果去强行进行乒乓切换读写DDR3内存地址,会导致画面有交错的可能性,这一点会在设计DDR3乒乓存储图像模块代码时去展开进一步说明。

       最后就是第五个问题了即在FPGA视频研发当中,乒乓操作和多帧缓存有何异同,相信这是很多朋友们非常关心的问题,这也是笔者在学习实践FPGA过程中被困扰了很久的问题,乒乓操作这个思想真的非常好,也充分发挥了FPGA并行加速的硬件特点,但是大家再仔细想想看它真正从根本上完全解决了图像输入端和输出端之间不匹配或者说不同步的问题了吗。

       “乒乓操作”只能说是从某种层度上缓解了这个问题,通过全局乒乓的操作很好地避免了因对外部存储器地址来回交替读写而导致图像帧与帧之间的交错现象,可以让用户看到640像素*480像素的实时图像,但是却不可避免地会造成帧与帧读写完成之间的等待,使得整个视频流尤其是当分辨率很高或者对图像前后处理过多时,图像流畅度方面就会大打折扣,因为图像分辨率高了或者图像前处理多了,跨时钟域读写数据自然而然就增多了,那么整体设计上读写等待的时间就不可避免的变长了,这时两帧缓存的乒乓操作在项目实施落地过程中就会显得力不从心,因为会存在肉眼可见的视频卡顿。

       为了能更好地欺骗人眼,使得FPGA视频加速处理的项目更好实施落地,所以就引入了多帧缓存的技术,大家可以简单地理解成是两帧缓存乒乓操作的升级版,多帧缓存主要就是为了解决视频流畅度的问题,但是多帧缓存对外部存储资源的要求也很高,为了保证对外部存储器的读写速度,动则就需要多颗DDR3外部存储颗粒的硬件支持,笔者自己也曾尝试过三帧缓存的处理方案,使用外挂2颗DDR3外部存储颗粒的XC7A100T开发板作为硬件平台,程序中也有些图像前处理,实际测试在分辨率1024*768的情况下视频显示的效果非常流畅,同时6层PCB板2颗DDR3的硬件配置也比较节约,有兴趣的朋友们也可以在学习实践过该例程后尝试进行更高分辨率的三帧缓存技术。

      如表1所示是ddr3_control_pingpang模块的信号列表,在这个模块中主要去实现上游cmos_capture摄像头采样和下游video_driver显示屏送显模块间大批量跨时钟域数据的缓存,其实和前面的例程中ddr3_control模块设计大同小异,主要就是带入了乒乓操作使能信号即ddr3_pingpang_en,相应地就设定了wr_addr_page写地址页和rd_addr_page读地址页,这里设定了一次性读写突发长度是BURST_NUM_128BIT是64(对一颗DDR3内存颗粒MIG IP核一次性最少读写地址是8),所以一帧640像素*480像素RGB565的图像需要640*480*16bit/64*128bit=600次突发读写才能完成,wr_addr_page在写完一副图像数据后即置返切换,而rd_addr_page在读完一副图像数据后即切换为~wr_addr_page,这样确保了该地址段的图像数据是完整的一帧图像,如图3所示是DDR3乒乓切换驱动模块的代码设计。

信号列表

信号名

I/O

位宽

clk_200m

I

1

rst_n

I

1

ddr3_dq

I/O

16

ddr3_dqs_p

I/O

2

ddr3_dqs_n

I/O

2

ddr3_addr

O

14

ddr3_ba

O

3

ddr3_ras_n

O

1

ddr3_cas_n

O

1

ddr3_we_n

O

1

ddr3_reset_n

O

1

ddr3_ck_p

O

1

ddr3_ck_n

O

1

ddr3_cke

O

1

ddr3_dm

O

2

ddr3_odt

O

1

ddr3_init_done

O

1

ddr3_pingpang_en

I

1

ddr3_wr_clk

I

1

wr_load

I

1

ddr3_wr_din

I

128

ddr3_wr_din_vld

I

1

ddr3_rd_rdy

I

1

ddr3_rd_clk

I

1

rd_load

I

1

ddr3_rd_dout

O

128

ddr3_rd_dout_vld

O

1

表1 ddr3_control_pingpang模块信号列表

图3 DDR3乒乓切换驱动模块的代码设计

       如下图4所示是OV7725摄像头实时采集送HDMI显示顶层模块的代码设计,因为video_driver模块和前面例程相同所以笔者在这里就不过度赘述了,顶层模块中把各个模块的相关信号例化到一起即可,这里同样的用一颗LED作为指示灯,当OV7725 CMOS Sensor和DDR3内存颗粒均初始化完成后被点亮,因为在两者都初始化完成后cmos_capture摄像头视频采集模块才开始工作,所以把其例化到该模块的复位信号。

       当然OV7725 CMOS Sensor需要一个XCLK驱动这里采用手册推荐的24Mhz,另外还需要一个200Mhz时钟驱动MIG IP核,25Mhz作为640*480分辨率的VGA驱动时钟,125Mhz作为HDMI串并转换的驱动时钟,这里统一用PLL IP核分频或者倍频产生。

图4 OV7725摄像头实时采集送HDMI显示顶层模块的代码设计

       如图5所示当我们把OV7725 CMOS Sensor摄像头插到豌豆开发板接口处,可以发现板载的LED灯点亮即初始化完成,很快通过HDMI接口,屏幕即显示出OV7725 CMOS Sensor实时采集到的视频数据。

图5 OV7725 CMOS Sensor摄像头实时采集上板现象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/176565.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

会议论文分享-FSE20-基于学习的状态修剪策略

基于学习的状态修剪策略1.引言2.Homi算法2.1.概率修剪策略2.2.Homi2.2.1.Collecting Promising Data2.2.2.Generating Features.2.2.3.Learning Distribution2.2.4.Sampling Values2.2.5.总结3.实验3.1.实验设置3.2.有效性3.3.候选状态数量3.4.与朴素方法的对比4.代码实操4.1.代…

5、IDEA详细配置

文章目录5、IDEA详细配置5.1 如果打开详细设置界面5.2 系统设置1 默认启动项目配置2 取消自动更新5.3 设置整体主题1 选择主题2 设置菜单和窗口字体大小3 设置IDEA背景图5.4 设置编辑器主题样式1 编辑器主题2 字体大小3 注释的字体颜色5.5 显示行号与方法分隔符5.6 代码智能提示…

2023mac电脑系统第三方清理软件CleanMyMacX

认识 CleanMyMac X 4.12.2! 此版本有哪些亮眼的更新? “更新程序”模块之前曾出现重复推送已安装更新的情况。 小的可用性问题。 任何一部电子设备在使用多年之后都会出现性能下降的问题,苹果的Mac计算机自然也不例外。当你发现Mac运行缓慢&#xff…

Tkinter的Menu与Messagebox

菜单控件Menu 在当前界面的左上角创建一个菜单,可创建二级菜单、三级菜单等等 具体语法: 创建一个菜单,并命名为menu menutkinter.Menu(root) 创建menu菜单的列表,并命名为filemenu filemenutkinter.Menu(menu,tearoff0) 在…

jar包导入失败/配置国内源的方法

注意:idea 的settings分为当前项目设置和新建项目设置两个部分,注意一些设置这两个地方都要调整。下面的步骤 修改好settings后,new projects 里的settings也要同样方法进行修改Maven中央仓库默认使用的是国外的,而国外访问速度很慢&#xff…

SpringBoot基础入门

简介 官网:https://spring.io/projects/spring-boot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程。 SpringBoot不是Spring官方的框架模式,而是一个团队在Spring4.0版本上二次开发并开源…

《深入浅出计算机组成原理》学习笔记 Day8

加法器1. 异或门与半加器2. 全加器3. 总结参考1. 异或门与半加器 异或门就是实现一个最简单的整数加法所需要使用的基本门电路。 当输入两位都是 11 的时候,还需要向更左侧的一位进行进位。这个就对应一个与门,也就是当加数和被加数都是 1 的时候&…

【数据结构之二叉树系列】二叉树的基本知识

目录前言一、树1、树的相关概念(1)结点(2)结点的度(3)叶结点(4)分支结点(5)父亲结点(6)子节点(7)树的度&#…

Java标准输入输出流(in/out)

文章目录前言标准输入流标准输出流前言 Java通过系统类System实现标准输入/输出的功能,在Java中输入输出数据一般(图形化界面例外)要用到标准输入输出流 System.in 标准输入:通常指从键盘输入数据System.out 标准输出&#xff1…

VueJs中如何使用Teleport组件

前言在DOM结构相对比较复杂,层级嵌套比较深的组件内,需要根据相对应的模块业务处理一些逻辑,该逻辑属于当前组件但是从整个页面应用的视图上看,它在DOM中应该被渲染在整个vue应用外部的其他地方,不能影响组件的结构比较常见的应用场景:就是全屏的模态框,控制元素的位置,也是可以…

分享124个ASP源码,总有一款适合您

ASP源码 分享124个ASP源码,总有一款适合您 下面是文件的名字,我放了一些图片,文章里不是所有的图主要是放不下..., 124个ASP源码下载链接:https://pan.baidu.com/s/1MLzeod5DblXbW3sZAeTsEQ?pwd9jfe ​​​​​​​…

连续系统的数字PID控制仿真-2

被控对象为三阶传递函数,采用Simulink模块与M函数相结合的形式,利用ODE45的方法求解连续对象方程,主程序由Simulink模块实现,控制器由M函数实现。输入指令信号为正弦信号0.05sin(2Tt)。采用PID方法设计控制器,其中kp …

casbin权限和配置文件的理解

官方文档 基础权限模型 下图为我基于个人理解画出来的(关于多租户RBAC模型可能有误) 发现一篇博客讲的还行Casbin权限模型,看他的权限系统设计模型分析部分 casbin配置文件内容的结构解释 注意matchers可以设置多个。我在知道这个之前一直疑惑为什么需要policy_…

【设计模式】我终于读懂了外观模式。。。

今天是正月初二,在这里给大家拜年啦! 祝愿大家:兔年大吉大利,兔年顺顺利利,兔年快快乐乐,兔气十足十足,兔年富富满堂,兔年财源广进,兔年步步高升,兔年梦想成真…

【大数据hive】hive ddl语法使用详解

一、前言 DDL,也叫数据定义语言 (Data Definition Language, DDL),是SQL语言集中对数据库内部的对象结构进行创建,删除,修改等的操作语言,这些数据库对象包括database、table等,使用过mysql的同学应该对此很…

抗积分饱和PID控制算法及仿真

积分饱和现象所谓积分饱和现象是指若系统存在一个方向的偏差,PID 控制器的输出由于积分作用的不断累加而加大,从而导致执行机构达到极限位置Xmax(例如阀门开度达到最大),如图所示,若控制器输出u(k)继续增大,阀门开度不…

STL - 常用算法

常用遍历算法 for_each #include <algorithm> #include <functional> #include <iostream> #include <vector>using namespace std;//常用遍历算法 - for_each//普通函数 void print01(int val) {cout << val << " "; } //仿函数…

【每日一题Day95】LC1815得到新鲜甜甜圈的最多组数 | 状态压缩dp 记忆化搜索

得到新鲜甜甜圈的最多组数【LC1815】 有一个甜甜圈商店&#xff0c;每批次都烤 batchSize 个甜甜圈。这个店铺有个规则&#xff0c;就是在烤一批新的甜甜圈时&#xff0c;之前 所有 甜甜圈都必须已经全部销售完毕。给你一个整数 batchSize 和一个整数数组 groups &#xff0c;数…

LeetCode刷题模版:187-189、198-200

目录 简介187. 重复的DNA序列188. 买卖股票的最佳时机 IV【未理解】189. 轮转数组198. 打家劫舍199. 二叉树的右视图200. 岛屿数量结语简介 Hello! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出~ ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简…

【论文翻译】Attention Is All You Need

【论文】Attention is All you Need (neurips.cc) 摘要 主要的序列转换模型是基于复杂的循环或卷积神经网络&#xff0c;其中包括一个编码器和一个解码器。表现最好的模型还通过注意机制连接编码器和解码器。我们提出了一个新的简单的网络架构&#xff0c;Transformer&#xf…