FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码

米联客推出了FDMA3.0,下载试用了将近一个月,感觉还行,总体比较平衡,相比于FDMA1.0操作也更简单,适用于基于AXI4_FULL的数据缓存方案,源码可以去米联客官网下载。
其实这种ASXI MASTER的再封装代码,源头都是opencores上的源码,黑金也下载并用到了自家开发板例程上,不同的是黑金原封不动的用,米联客做了自己的改动,使得对AXI4的操作变得更加简单,但也带来一个问题,那就是对AXI4总线的不熟悉。
总体来说,通过FDMA3.0先用起来,解决功能问题,再去理解AXI4总线会更好。
虽然我一直FDMA3.0用起来很丝滑,但总觉得遗憾,那就是代码不是我写的,不完美,所以今天花了一天时间,自己根据FDMA3.0的操作时序,结合米联客的例程,手写了一个图像三帧缓存的控制器。
图像输入:OV5640摄像头吧,720P分辨率;
图像输出:HDMI;
开发板:MA703FA,A7的板子;
开发环境:vivado2019.1;
BD工程如下:
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第1张图片
总体上移植的米联客的例程,只是HDMI输出控制器是我自己根据正点原子的控制器加上VGA时序再封装的,如下:
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第2张图片
FDMA数据位宽设置为128位,如图:
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第3张图片
关于FDMA的操作时序,可以去米联客官网查看,这里的手写的是FDMA的控制器;
三帧缓存的原理框图大概是这样的,我讲的不够详细,建议去看正点原子的讲解。
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第4张图片
首先要准备两个FIFO,一个叫写fifo,一个叫读fifo,用作数据的跨时钟,
比如,摄像头输出的像素时钟是50M,DDR3的用户时钟是100M,想要把50M的摄像头数据写入DDR3就需要用到写fifo,写fifo设置为异步时钟,深度设置为2048,以此兼容1080P,
写fifo应该具有如下配置:
写数据位宽32位,虽然像素是24位的,但为了和AXI规定的数据位宽程倍数关系,所以设置为32位;
写数据深度2048,以此兼容1080P的行有效像素1920;
读数据位宽128位,与FDMA数据位宽一致;
使能读计数器,为了控制写发起FDMA写请求的时机,很重要;
写fifo配置如图:
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第5张图片
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第6张图片
同理,读fifo配置应有:
写数据位宽128位,与FDMA数据位宽一致;
写数据深度2048,以此兼容1080P的行有效像素1920;
读数据位宽32位,输出给显示器;
使能写计数器,为了控制写发起FDMA读请求的时机,很重要;
读fifo配置如图:
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第7张图片
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第8张图片
接下来是代码设计,设计思路如下:
写fifo先缓存一行图像,然后发起FDMA写请求,等待写完一帧图像后,再切换写图像的基地址;
读fifo检测到已写像素小与一行图像时发起FDMA读请求,同时根据写图像基地址指针切换读地址,从而实现三帧缓存;
先看参数:
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第9张图片
这里哟有个参数FDMA_TRANS_DIV = 2必须要解释一下,AXI4的单次突发地址被限制为4K,即4096byte,如果我的输入分辨率是720P,那一行图像占的地址就是1280X4=5120,超过了AXI4规定的4K边界,显然是非法的,所以解决方案就是分两次AXI突发,那么单次突发地址就是2560,小与4K,这样的设计也试用于1080P分辨率,计算如下:(1920X4÷2=3840)。
由此产生的FDMA突发写的几个本底宏定义如下:
在这里插入图片描述
接下来就是常规操作,采集输入图像场同步上升沿:
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第10张图片
写过程状态机如下:
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第11张图片
下面重点讲解其中的细节:
1、根据场同步来切换写地址
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第12张图片
因为场同步信号既是一帧图像的开始,也是一帧图像的结束信号,当上一帧写完后下一帧当然要切换地址;
2、异步fifo复位:
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第13张图片
这里很重要,有两个点,第一,fifo复位专门当做一个状态来写是为了解决视频中断后再输入的问题,试想,如果你的输入信号突然断了然后再恢复,而你的输出图像还是原来的,老板看到这样的设计会不会fire you?其次,这里复位20个时钟周期后才进入写数据状态,是因为Xilinx异步fifo必须复位一段时间后才能操作,这是官方给的建议,至于复位多少时间后才能操作,我没有在官方数据手册中看到;
3、写请求时机的掌握
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第14张图片
写fifo的写入侧是比如50M,读出侧是100M,如果写一个读一个必然是读比写快,为了解决这个问题,必须等写到一行数据了再发起FDMA写请求,这里的控制如下:
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第15张图片
FDMA读与写的套路差不多,这只给出区别点:
1、FDMA读地址的切换是根据写指针来的,如下:
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第16张图片
2、发起FDMA读请求的时机如下:
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第17张图片
读fifo的读接口是持续不断的,当检测到写数据小于1行时才发起一次FDMA读请求,一次保证fifo不堵。
最后看看成果:
FPGA图像三帧缓存,手写米联客FDMA3.0控制器,逐行讲解代码_第18张图片
这里的图像中间部分有绿色,是因为输出HDMI的rgb顺序反了,调过来就好了。
最后:整个源代码并未给出,目的是给兄弟们一个练手的机会,,如果你在自身尝试的基础上,实在搞不出来,可以加我VX要工程源码:(hllsq22) 我也可以给你适当的技术支持,教你怎么写。

你可能感兴趣的:(缓存,fpga开发,图像处理)