1、引言

FPGA是一种现场可编程逻辑门阵列,其并行的特点让其在图像处理、数字通信等领域有广泛的应用。FPGA缺点是不擅长流程控制,对于IIC、SPI等通信方式,往往需要用到状态机。ZYNQ7000是赛灵思推出的一款带有ARM核的FPGA,包含了两个ARM A9的核以及FPGA资源,分为PS端和PL端。在运用ZYNQ做图像处理之前,有必要先搭建环境。我用的是ZYNQ7010,vivado是2018.3版本的。

2、显示环境硬件搭建

2.1 工程框架

利用ZYNQ7010显示图像,其工程的框架我们可以参照赛灵思应用手册xapp742,手册中有这样一张图,描述了 整个工程的各个模块。它是基于FPGA K7开发板搭建的,其实对于ZYNQ也相似。VDMA是video direct memory access,是一种可以将数据从地址映射转为数据流的IP核,RGB to YCrCb、OSD等式图像处理模块,这里未用到,VTC和Stream to video bridge是一起使用的,VTC是动态时钟管理,用于给Stream to video bridge提供时钟信号,Stream to video bridge则是将VDMA的数据流转换成RGB格式可以供LCD屏或者HDMI屏幕显示,具体可以看手册。

2.2 设计目标和工程建立

这里我们需要先在PS端往DDR中写入数据,之后通过VDMA在hdmi显示屏上显示一个彩条图案。在知道了设计的基本框架和目标后,我们画出这个工程的简图,之后创立vivado工程。
这里我自己画了一个工程的简化后的框图,PS端主要完成了DDR的配置,以及串口通信还有往DDR中写入彩条数据。PL端与PS端通过GP和HP接口进行交互,HP接口读取DDR中数据,传输到VDMA,VDMA实现地址映射到数据流转换,VIDEO OUT实现axi数据流到显示屏可以显示的数据转换。这里GP接口是配置,VDMA的一些参数,VTC和PLL分别是时钟配置和锁相环。

工程这边就按照自己的开发板型号来建立即可,之间创建block design,第一步添加ZYNQ IP核如下。需要对他做一些简单的配置,包括DDR、UART等,DDR和串口根据自己板子型号设置即可,这边为了能让传输快一些,将FCLK时钟频率改为了100M,此外,还添加了HP接口来作为数据的传输接口。

修改完成之后的zynq IP核如下图所示。

2.3 VDMA ip核简介和配置

创建完了工程后,根据框架简图,首先添加VDMA IP核如下图所示。关于VDMA IP核的使用可以参考塞琳思的手册pg020。

AXI VDMA IP核提供了一种高带宽的地址映射到数据流的转换,这个IP的基本框图如下图所示,左边是地址映射接口,可以将DDR数据读取出来,右边是数据流格式,AXI4-Lite可以对IP核进行配置。

之后对该IP核进行配置,其配置完了的界面如下图所示。address width是地址长度,frame buffer是帧缓存。由于这里只是读取ddr数据进行显示,所以只勾选了VDMA的读通道,读通道包含四个参数地址映射宽度、最大突发长度、数据流格式、行缓存深度。数据流是24位是因为传输的是RGB888的图像,一个像素24位,行缓存深度是2048,一般大于你的显示屏即可,我这边使用的是1024×768的hdmi屏。


配置完了IP后我们将VDMA ip和ZYNQ连接起来,如下图所示。可以看到,vivado为我们填加了三个额外的IP,分别是同步复位、AXI互联接口、AXI智慧互联接口。这样子,我们就实现了从PS端到VDMA的地址映射数据传输的模块搭建。

2.4 VTC ip核与Video OUT ip核简介与配置

这两个IP核的参考手册分别是PG016和PG044。针对手册内容,不在过多叙述,这里直接vivado添加了这两个IP。Video out ip如下图所示,其主要接口为video_in:接入vdma输出的数据流,vtiming_in:用于接收VTC IP给出的时序,此外,还有两组时钟和复位信号。主要的输出端口vid_io_out:输出LCD屏幕可以显示的信号,包括行同步、场同步等。


此外,还需要添加VTC模块如下图所示。其主要输入接口包括了时钟、复位、使能,输出包括时序信号输出等。对它的配置如下,首先是取消勾选了AXI接口,因这里没有用到;然后关闭了detection。之后,因为这这边显示屏是768p的,所以选择1024×768。



在添加完了IP后,继续在block design中连线完成设计,连接完的框图如下图所示。将VDMA的流数据接到Video out,VTC为Video out提供显示的时序信号。Video out的aclk为100M,此外还注意到,video out和VTC还有一个显示屏显示时钟,这个时钟得根据不同的显示屏来确定。

2.5 PLL ip和DVI ip添加和配置

因为显示屏显示是需要具体的时钟信号,所以我们这里手动添加了一个PLL ip核,用于给VTC和Video out提供显示时钟。除此之外,Video out的时序是LCD的,还需要添加一个自定义的IP核来完成lcd到hdmi的转换。添加的两个IP如下图所示。这边用锁相环产生了两个时钟,一个是65MHz,对应我的显示屏,另一个是325MHz,是65MHz的5倍,满足hdmi的时序对时钟信号的要求。最后完成连线如下图所示,之后对工程综合实现生成bit流导入到sdk进行软件设计。


3、显示环境软件程序

整个程序也十分简单,在sdk中导入vdma显示的例程。利用run_triple_frame_buffer函数初始化VDMA,初始化的参数包括了VDMA实例、VDMA的ID、宽度、高度、vdma起始地址。之后写入彩条数据即可。

#include "stdio.h"
#include "xparameters.h"
#include "xaxivdma.h"
#include "vdma_api.h"
#include "xil_cache.h"#define VDMA_ID XPAR_AXIVDMA_0_DEVICE_ID
#define BASE_ADDR   XPAR_PS7_DDR_0_S_AXI_BASEADDR
#define WIDTH   1024
#define DEPTH   768int vdma_addr=(BASE_ADDR+0x1000000);int main()
{int i,j;u8* vdma_buffer;XAxiVdma vdma_inst;vdma_buffer=(u8*) vdma_addr;run_triple_frame_buffer(&vdma_inst,VDMA_ID, WIDTH,DEPTH,vdma_addr,0,0);for(j=0;j<DEPTH;j++){for(i=0;i<WIDTH;i++){if(i>=0 && i<WIDTH/3){*(vdma_buffer+j*WIDTH*3+3*i+0)=0x00;*(vdma_buffer+j*WIDTH*3+3*i+1)=0x00;*(vdma_buffer+j*WIDTH*3+3*i+2)=0xff;}else if(i>=WIDTH/3 && i<WIDTH/3*2){*(vdma_buffer+j*WIDTH*3+3*i+0)=0x00;*(vdma_buffer+j*WIDTH*3+3*i+1)=0xff;*(vdma_buffer+j*WIDTH*3+3*i+2)=0x00;}else if(i>=WIDTH/3*2 && i<WIDTH){*(vdma_buffer+j*WIDTH*3+3*i+0)=0xff;*(vdma_buffer+j*WIDTH*3+3*i+1)=0x00;*(vdma_buffer+j*WIDTH*3+3*i+2)=0x00;}}}Xil_DCacheFlush();return 0;
}

4、VDMA彩条显示效果图

5、添加动态时钟IP核的工程

上面的一个工程针对的是某个固定的屏幕,当我们想要更换屏幕时,底层的模块就要重新配置,然后再重新生成比特流,比较麻烦。因此,下述的框架对上面的工程做了修改,首先是删除了锁相环IP核,添加了动态时钟配置模块;其次,打开VTC模块的AXI接口,使其可以通过PS端进行配置;然后VTC、Video out以及DVI模块的时钟由动态时钟模块提供。最后完成所有连线。

最后进行SDK软件设计,其代码如下所示,配置VDMA以及彩条显示与上面的代码相似。差别是添加了一些Display controller的函数对VTC模块和Dyclk模块进行配置和初始化。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xil_types.h"
#include "xil_cache.h"
#include "xparameters.h"
#include "xaxivdma.h"
#include "xaxivdma_i.h"
#include "display_ctrl/display_ctrl.h"
#include "vdma_api/vdma_api.h"//宏定义
#define BYTES_PIXEL        3                          //像素字节数,RGB888占3个字节
#define DYNCLK_BASEADDR    XPAR_AXI_DYNCLK_0_BASEADDR //动态时钟基地址
#define VDMA_ID            XPAR_AXIVDMA_0_DEVICE_ID   //VDMA器件ID
#define DISP_VTC_ID        XPAR_VTC_0_DEVICE_ID       //VTC器件ID//函数声明
void colorbar(u8 *frame, u32 width, u32 height, u32 stride);//全局变量
XAxiVdma     vdma;
DisplayCtrl  dispCtrl;
VideoMode    vd_mode;
//frame buffer的起始地址
unsigned int const frame_buffer_addr = (XPAR_PS7_DDR_0_S_AXI_BASEADDR + 0x1000000);
unsigned int lcd_id=0;        //LCD IDint main(void)
{vd_mode=VMODE_1024x768;//配置VDMArun_vdma_frame_buffer(&vdma, VDMA_ID, vd_mode.width, vd_mode.height,frame_buffer_addr,0, 0,ONLY_READ);//初始化Display controllerDisplayInitialize(&dispCtrl, DISP_VTC_ID, DYNCLK_BASEADDR);//设置VideoModeDisplaySetMode(&dispCtrl, &vd_mode);DisplayStart(&dispCtrl);//写彩条colorbar((u8*)frame_buffer_addr, vd_mode.width,vd_mode.height, vd_mode.width*BYTES_PIXEL);return 0;
}//写彩条函数(彩虹色)
void colorbar(u8 *frame, u32 width, u32 height, u32 stride)
{u32 color_edge;u32 x_pos, y_pos;u32 y_stride = 0;u8 rgb_r, rgb_b, rgb_g;color_edge = width * BYTES_PIXEL / 7;for (y_pos = 0; y_pos < height; y_pos++) {for (x_pos = 0; x_pos < (width * BYTES_PIXEL); x_pos += BYTES_PIXEL) {if (x_pos < color_edge) {                                           //红色rgb_r = 0xFF;rgb_g = 0;rgb_b = 0;} else if ((x_pos >= color_edge) && (x_pos < color_edge * 2)) {     //橙色rgb_r = 0xFF;rgb_g = 0x7F;rgb_b = 0;} else if ((x_pos >= color_edge * 2) && (x_pos < color_edge * 3)) { //黄色rgb_r = 0xFF;rgb_g = 0xFF;rgb_b = 0;} else if ((x_pos >= color_edge * 3) && (x_pos < color_edge * 4)) { //绿色rgb_r = 0;rgb_g = 0xFF;rgb_b = 0;} else if ((x_pos >= color_edge * 4) && (x_pos < color_edge * 5)) { //青色rgb_r = 0;rgb_g = 0xFF;rgb_b = 0xFF;} else if ((x_pos >= color_edge * 5) && (x_pos < color_edge * 6)) { //蓝色rgb_r = 0;rgb_g = 0;rgb_b = 0xFF;} else if ((x_pos >= color_edge * 6) && (x_pos < color_edge * 7)) { //紫色rgb_r = 0x8B;rgb_g = 0;rgb_b = 0xFF;}frame[x_pos + y_stride + 0] = rgb_b;frame[x_pos + y_stride + 1] = rgb_g;frame[x_pos + y_stride + 2] = rgb_r;}y_stride += stride;}Xil_DCacheFlush();     //刷新Cache,数据更新至DDR3中xil_printf("show color bar\r\n");
}

最后显示的效果如下图,从左到右依次红橙黄绿青蓝紫。

ZYNQ图像处理(1)——vdma_hdmi显示环境搭建相关推荐

  1. Python opencv图像处理基础总结(一) 环境搭建 基础操作

    学过的知识,会过时.会遗忘,但在努力过程中学会的处事态度和做事习惯,都会留在骨子里,变成我们的一部分. Open Source Computer Vision Library,OpenCV于 1999 ...

  2. Python3与OpenCV3.3 图像处理(一)--环境搭建与简单DEMO

    https://blog.csdn.net/qq_32811489/article/details/78636049 https://blog.csdn.net/gangzhucoll/article ...

  3. Zynq7000开发系列-5(OpenCV开发环境搭建:Ubuntu、Zynq)

    操作系统:Ubuntu14.04.5 LTS 64bit OpenCV:OpenCV 3.1.0.opencv_contrib gcc:gcc version 4.8.4 (Ubuntu 4.8.4- ...

  4. OpenCV图像处理--Qt+OpenCV环境搭建

    LinuxQt+Opencv 环境搭建参照 LinuxQT+第三方库配置 WindowsQt+OpenCV环境搭建 一.下载opencv环境 opencv环境下载 2.Qt+OpenCV环境测试 新建 ...

  5. ZYNQ图像处理(4)——灰度图像转二值化图像

    1.二值化图像简介 前面已经完成了摄像头图像的采集和显示,以及RGB图像转灰度图.二值化图像在图像处理领域同样有广泛的应用,本节介绍如何用FPGA实现灰度转二值化图形.灰度实现二值化的原理很简单,只需 ...

  6. python环境安装opencv,Python环境搭建之OpenCV的步骤方法

    一.openCV介绍 Open Source Computer Vision Library.OpenCV于1999年由Intel建立,如今由Willow Garage提供支持.OpenCV是一个基于 ...

  7. 图像识别DM8127开发攻略——开发环境搭建

    经过两年多的爆炸性出货(针对我们这种小公司),目前稍微停顿了一下,现在难得有点时间继续写自己的博客,其实自己一直想静下心来做点东西,可惜做TI DAVINCI(ARM+DSP)这方面的人不太好招,本人 ...

  8. TI Davinci DM6446开发攻略——开发环境搭建

    TI DAVINCI DM6446的开发环境搭建不像三星S3C2410,S3C2440,ATMEL的AT91SAM9260之类的单核ARM那么简单,因为DM6446还有DSP端的开发环境,以及双核之间 ...

  9. Python环境搭建之OpenCV(转载)

    转自https://www.cnblogs.com/lclblack/p/6377710.html 一.openCV介绍 Open Source Computer Vision Library.Ope ...

最新文章

  1. 《2020城市大脑全球标准研究报告》全文正式开放申领
  2. X431 元征诊断枪
  3. Python_note6 组合数据类型+jieba库+文本词频统计
  4. mysql 工具图形学_[计算机图形学]贝塞尔曲线
  5. jdbc oracle thin@localhost 1521 XE
  6. python3 通过列表作为键 产生字典
  7. javascript基础:函数参数与闭包问题
  8. springboot+IntelliJ IDEA实现热部署
  9. Java实现身份证号码的验证,JAVA后台验证身份证号码
  10. Spring Cloud云架构 - commonservice-sso服务搭建(一)
  11. Linux解压tar.gz、zip、tar.bz2 文件与对应的命令
  12. FFA 2021 专场解读 - 实时数据湖
  13. 人脸识别demo使用教程
  14. 数字孪生,开启3D智慧园区管理新篇章
  15. pc模式 华为mate30_很实用!华为Mate?30全系支持PC模式,无线充+投屏更方便!
  16. 同相加法器电路图_反相加法器电路图_运放加法器电路图解析
  17. TMS570LS1224PWM的生成及捕获
  18. 词语提取小工具开放啦
  19. “三天打鱼,两天晒网”问题
  20. Cuba studio6.9 图文安装

热门文章

  1. 智能机器人与智能系统(大连理工大学庄严教授)——5.仿生机器人
  2. java图表库_美丽的Java图表类库
  3. Solaris10下Telnet、SSH、ftp使用root登录
  4. html5 苹果 代码,iOS 8 HTML5性能测试:苹果有多爱HTML5?
  5. 网站集成QQ号登录-QQ互联审核(附涉及不良信息解决办法)
  6. 一起学ORBSLAM2(11)ORBSLAM的localmapping
  7. mc服务器cpu占用过高怎么办,我的世界崩服无报错 传送导致CPU爆满
  8. Python换行与不换行输出方式
  9. Pythom模块之random模块
  10. java web 文件下载