目录
- 1、前言
- 2、任意分辨率视频输出理论基础
- 3、VDMA实现数据缓存
- 4、工程1:Kintex7使用VDMA
- 5、工程2:Zynq7100使用VDMA
- 6、上板调试验证并演示
- 7、福利:工程代码的获取
1、前言
之前写过一篇FPGA纯verilog实现任意分辨率视频输出显示,高度贴近真实项目,提供工程源码和技术支持的文章,讲述了基于AXI协议的FDMA实现任意分辨率视频输出显示,但对于习惯使用zynq或者Microblaze的兄弟来说,更喜欢用VDMA,本设计就是基于VDMA实现任意分辨率视频输出显示,高度贴近真实项目,适用于医疗、军工等图像相关项目。
2、任意分辨率视频输出理论基础
关于理论部分,请参考我之前写的文章:点击查看:任意分辨率视频输出
3、VDMA实现数据缓存
VDMA是Xilinx发布的基于AXIS数据流的图像缓存方案,该IP使用稳定、方便,仅需简单界面配置加SDK配置即可使用,关于VDMA的讲解,Xilinx有官方文档,网上也有各种文档,感兴趣的可以去详细读读,但恕我直言,说多了都是扯淡,读了半天不知道怎么用有意义吗?先用起来再说,在使用过程中去慢慢理解才是最有效的学习方式,就算最后还是不懂也没关系,能用就行,VDMA本身就是一个黑箱IP,你本来就看不到源码,怎么可能真正理解,Xilinx根本就没想让你真正理解;
 VDMA界面配置如下:
 
 
 VDMA配置界面几乎不需要更改,保持官方默认配置已经够了,只是buffer深度需要关注一下,比如1080P视频可以适当将buffer深度增大到1024或者2048;还有就是选择缓存帧数,如果嫌延迟太高了可以选择缓存2帧;
 拿我的工程去就能直接把VDMA用起来,该IP简单来说就是实现视频到DDR的三帧缓存,使得读写错开,输出完美视频,仅此而已;
4、工程1:Kintex7使用VDMA
开发板:Xilinx Kintex7开发板;
 开发环境:Vivado2019.1;
 输入:Ov5640摄像头,分辨率由SDK配置;
 输出:HDMI,分辨率1920x1080;
 Kintex7使用VDMA需要引入Microblaze软核,图像缓存进DDR3;
 工程BD如下:
 
 导出硬件后的代码架构如下:
 
 SDK主函数如下:
int main(){
	XGpioCfg = XGpio_LookupConfig(AXI_GPIO_DEVICE_ID);
	XGpio_CfgInitialize(&led_gpio, XGpioCfg, XGpioCfg->BaseAddress);
	XGpio_SetDataDirection(&led_gpio, 1, 0);	//output
	XGpio_DiscreteWrite(&led_gpio, 1, 0);
	oak_i2c_init(OV5640_IIC_BASEADDR, 1000000, 0x78>>1, IIC_REG_LEN16, IIC_DATA_LEN8);
	OV5640_Init(OV5640_IIC_BASEADDR,1280,720);
	helai_vdma();
	while(1){
		usleep(500000);
		XGpio_DiscreteWrite(&led_gpio, 1, 1);
		usleep(500000);
		XGpio_DiscreteWrite(&led_gpio, 1, 0);
	}
}
5、工程2:Zynq7100使用VDMA
开发板:Xilinx Zynq7100开发板;
 开发环境:Vivado2019.1;
 输入:Ov5640摄像头,分辨率由SDK配置;
 输出:HDMI,分辨率1920x1080;
 VDMA运行与PL端,图像缓存进PS端DDR3,PL端系统时钟由PS提供;
 工程BD如下:
 
 导出硬件后的代码架构如下:
 
 SDK主函数如下:
void main()
{
	// Initialize OV5640 regesiter
	I2C_config_init();
	//璁剧疆鍐呭瓨涓殑鑳屾櫙
	for(i=0;i<SUM;i++){
		Xil_Out16((VIDEO_BASEADDR0 + i), 0x00);
		Xil_Out16((VIDEO_BASEADDR1 + i), 0x00);
		Xil_Out16((VIDEO_BASEADDR2 + i), 0x00);
	}
	//VDMA_WRITE
	Xil_Out32((VDMA_BASEADDR + 0x030), 0x108B);// enable circular mode
	Xil_Out32((VDMA_BASEADDR + 0x0AC), VIDEO_BASEADDR0);	// start address
	Xil_Out32((VDMA_BASEADDR + 0x0B0), VIDEO_BASEADDR1);	// start address
	Xil_Out32((VDMA_BASEADDR + 0x0B4), VIDEO_BASEADDR2);	// start address
	Xil_Out32((VDMA_BASEADDR + 0x0A8), (H_STRIDE*3));		// h offset (H_STRIDE* 3) bytes
	Xil_Out32((VDMA_BASEADDR + 0x0A4), (H_ACTIVE*3));		// h size (H_ACTIVE * 3) bytes
	Xil_Out32((VDMA_BASEADDR + 0x0A0), V_ACTIVE);			// v size (V_ACTIVE)
	//VDMA_READ
	Xil_Out32((VDMA_BASEADDR + 0x000), 0x8B); 		// enable circular mode
	Xil_Out32((VDMA_BASEADDR + 0x05c), VIDEO_BASEADDR0); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x060), VIDEO_BASEADDR1); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x064), VIDEO_BASEADDR2); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x058), (H_STRIDE*3)); 		// h offset (H_STRIDE * 3) bytes
	Xil_Out32((VDMA_BASEADDR + 0x054), (H_ACTIVE*3)); 		// h size (H_ACTIVE * 3) bytes
	Xil_Out32((VDMA_BASEADDR + 0x050), V_ACTIVE); 			// v size (V_ACTIVE)
	while (1) ;
}
6、上板调试验证并演示
以工程1为例,动态ov5640分辨率500x500演示如下:
K7 500X500 VDMA
以工程2为例,静态ov5640分辨率1280x720演示如下:
 
动态ov5640分辨率500x500演示:
FPGA基于VDMA实现任意分辨率视频输出显示
7、福利:工程代码的获取
福利:工程代码的获取
 代码太大,无法邮箱发送,以某度网盘链接方式发送,
 资料获取方式:私,或者文章末尾的V名片。
 网盘资料如下:
 



















