您当前的位置: 首页 >  缓存

9527华安

暂无认证

  • 0浏览

    0关注

    35博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

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

9527华安 发布时间:2022-05-22 23:17:06 ,浏览量: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工程如下: 在这里插入图片描述 总体上移植的米联客的例程,只是HDMI输出控制器是我自己根据正点原子的控制器加上VGA时序再封装的,如下: 在这里插入图片描述 FDMA数据位宽设置为128位,如图: 在这里插入图片描述 关于FDMA的操作时序,可以去米联客官网查看,这里的手写的是FDMA的控制器; 三帧缓存的原理框图大概是这样的,我讲的不够详细,建议去看正点原子的讲解。 在这里插入图片描述 首先要准备两个FIFO,一个叫写fifo,一个叫读fifo,用作数据的跨时钟, 比如,摄像头输出的像素时钟是50M,DDR3的用户时钟是100M,想要把50M的摄像头数据写入DDR3就需要用到写fifo,写fifo设置为异步时钟,深度设置为2048,以此兼容1080P, 写fifo应该具有如下配置: 写数据位宽32位,虽然像素是24位的,但为了和AXI规定的数据位宽程倍数关系,所以设置为32位; 写数据深度2048,以此兼容1080P的行有效像素1920; 读数据位宽128位,与FDMA数据位宽一致; 使能读计数器,为了控制写发起FDMA写请求的时机,很重要; 写fifo配置如图: 在这里插入图片描述 在这里插入图片描述 同理,读fifo配置应有: 写数据位宽128位,与FDMA数据位宽一致; 写数据深度2048,以此兼容1080P的行有效像素1920; 读数据位宽32位,输出给显示器; 使能写计数器,为了控制写发起FDMA读请求的时机,很重要; 读fifo配置如图: 在这里插入图片描述 在这里插入图片描述 接下来是代码设计,设计思路如下: 写fifo先缓存一行图像,然后发起FDMA写请求,等待写完一帧图像后,再切换写图像的基地址; 读fifo检测到已写像素小与一行图像时发起FDMA读请求,同时根据写图像基地址指针切换读地址,从而实现三帧缓存; 先看参数: 在这里插入图片描述 这里哟有个参数FDMA_TRANS_DIV = 2必须要解释一下,AXI4的单次突发地址被限制为4K,即4096byte,如果我的输入分辨率是720P,那一行图像占的地址就是1280X4=5120,超过了AXI4规定的4K边界,显然是非法的,所以解决方案就是分两次AXI突发,那么单次突发地址就是2560,小与4K,这样的设计也试用于1080P分辨率,计算如下:(1920X4÷2=3840)。 由此产生的FDMA突发写的几个本底宏定义如下: 在这里插入图片描述 接下来就是常规操作,采集输入图像场同步上升沿: 在这里插入图片描述 写过程状态机如下: 在这里插入图片描述 下面重点讲解其中的细节: 1、根据场同步来切换写地址 在这里插入图片描述 因为场同步信号既是一帧图像的开始,也是一帧图像的结束信号,当上一帧写完后下一帧当然要切换地址; 2、异步fifo复位: 在这里插入图片描述 这里很重要,有两个点,第一,fifo复位专门当做一个状态来写是为了解决视频中断后再输入的问题,试想,如果你的输入信号突然断了然后再恢复,而你的输出图像还是原来的,老板看到这样的设计会不会fire you?其次,这里复位20个时钟周期后才进入写数据状态,是因为Xilinx异步fifo必须复位一段时间后才能操作,这是官方给的建议,至于复位多少时间后才能操作,我没有在官方数据手册中看到; 3、写请求时机的掌握 在这里插入图片描述 写fifo的写入侧是比如50M,读出侧是100M,如果写一个读一个必然是读比写快,为了解决这个问题,必须等写到一行数据了再发起FDMA写请求,这里的控制如下: 在这里插入图片描述 FDMA读与写的套路差不多,这只给出区别点: 1、FDMA读地址的切换是根据写指针来的,如下: 在这里插入图片描述 2、发起FDMA读请求的时机如下: 在这里插入图片描述 读fifo的读接口是持续不断的,当检测到写数据小于1行时才发起一次FDMA读请求,一次保证fifo不堵。 最后看看成果: 在这里插入图片描述 这里的图像中间部分有绿色,是因为输出HDMI的rgb顺序反了,调过来就好了。 最后:整个源代码并未给出,目的是给兄弟们一个练手的机会,,如果你在自身尝试的基础上,实在搞不出来,可以私,我也可以给你适当的技术支持,教你怎么写。

关注
打赏
1659431378
查看更多评论
立即登录/注册

微信扫码登录

0.0388s