设为首页 加入收藏

TOP

基于FPGA的VGA显示静态图片(一)
2017-10-09 13:55:44 】 浏览:7321
Tags:基于 FPGA VGA 显示 静态 图片

    之前学习了半年的图像处理,所以计划将自己学过的几个图像处理的基础算法,做过的设计记录下来,在OpenHW论坛上发表,计划是这样的,用VGA做显示,使用PC端上位机通过串口发送一幅图片数据到FPGA开发板,FPGA接收数据并做处理最终发送给VGA显示屏显示,计划要写的算法有彩色图像转灰度、均值/中值滤波、Sobel边缘检测等。那么现在这是第一篇,先来写VGA显示的驱动、以及将一幅图片显示到VGA显示屏上。

  第一步是硬件平台的选取,我身边正好有一块Xilinx的ZYNQ开发板,ZYNQ算是Xilinx的一款比较高端的板子了,上面有以太网接口、USB2.0/OTG、HDMI双向接口,SD卡槽,而且板子内部还嵌入了双核ARM Cortex-A9处理器,上面可以跑linux,价格也不菲。ZYNQ是一款全可编程逻辑开发板(All Programmable)。什么是全可编程逻辑开发板,就是可以用硬件描述语言变成,可用C语言、Python等软件编程语言编程。这款开发板有PS(Processor Subsystem)和PL(Programmable Logic)两部分,当然我这里这回用到PL部分资源。通过查阅手册和实验确定ZYNQ在PL(Programmable Logic)模式下,开发板引脚L16连接系统时钟晶振为125Mhz,VGA为16位RGB565显示。

         VGA扫描显示其实就是两条线,一个是行扫描,一个是场扫描,在行有效和场有效的时候把数据发送给VGA即可显示了。显示标准就是行分辨率x列分辨率@60hz即一秒屏幕刷新60次,拿640x480@60HZ做例子,即行为640个像素,场为480个像素。

         VGA显示其实就是两条线,一个是行扫描,一个是场扫描,在行有效和场有效的时候把数据发送给VGA即可显示了。显示标准就是@60hz即一秒屏幕刷新60次,拿640x480@60HZ做例子,即行为640个像素,场为480个像素。

显示器扫描方式分为逐行扫描和隔行扫描:逐行扫描是扫描从屏幕左上角一点开始,从左像右逐点扫描,每扫描完一行,电子束回到屏幕的左边下一行的起始位置,在这期间,CRT对电子束进行消隐,每行结束时,用行同步信号进行同步;当扫描完所有的行,形成一帧,用场同步信号进行场同步,并使扫描回到屏幕左上方,同时进行场消隐,开始下一帧。隔行扫描是指电子束扫描时每隔一行扫一线,完成一屏后在返回来扫描剩下的线,隔行扫描的显示器闪烁的厉害,会让使用者的眼睛疲劳。

 

图 – VGA屏幕扫描原理

         行消隐(HBlank)在将光信号转换为电信号的扫描过程中,扫描总是从图像的左上角开始,水平向前行进,同时扫描点也以较慢的速率向下移动。当扫描点到达图像右侧边缘时,扫描点快速返回左侧,重新开始在第1行的起点下面进行第2行扫描,行与行之间的返回过程称为水平消隐。一幅完整的图像扫描信号,由水平消隐间隔分开的行信号序列构成,称为一帧。扫描点扫描完一帧后,要从图像的右下角返回到图像的左上角,开始新一帧的扫描,这一时间间隔,叫做垂直消隐,也称场消隐(VBlank)。我们称行同步、场同步。

         行场消隐信号:是针对老式显像管的成像扫描电路而言的。电子枪所发出的电子束从屏幕的左上角开始向右扫描,一行扫完需将电子束从右边移回到左边以便扫描第二行。在移动期间就必须有一个信号加到电路上,使得电子束不能发出。不然这个回扫线会破坏屏幕图像的。这个阻止回扫线产生的信号就叫作消隐信号,场信号的消隐也是一个道理。

图 – 行扫描

图 – 场扫描

图 – VGA扫描时序

        那么扫描时钟是多少呢?这个其实是可以计算出来的,根据一帧(即扫描一次屏幕需要60分之1秒)需要的时间可以计算出每一个像素点需要的时间。我这里就不计算了直接用官方给出的数据就行了,我这里直接给出官方手册,可以自己查阅。如图所示的一些参数和其几种显示格式的显示参数还有RGB的几种颜色的显示组合,我都会给出来,

  我这里选用的是640X480@60HZ分辨率显示,ZYBO的板子晶振是125Mhz,所以首先要先进行分频,我这里直接用Vivado调用PLL。还没有过用Vivado调用PLL的博客,现在总结一下吧,以防后面忘记。

点击IP catalog进行IP设置

为了快速找到想要的IP,在右上角直接搜索Clocking,然后就会出现如图所示界面,双击clocking wizard,进行PLL的配置

弹出如图所示界面后,一次按上图进行配置,在component name中写下IP的名字,把show disabled ports勾选为空,在primitive中选择MMCM,在input clock information中选择输入时钟。这里的MMCM我查了一下就是他包含了PLL,所以我们直接选择MMCM。但是有时候如果选择PLL也会出现错误,所以一般首选MMCM。

这里设置输出时钟,还可以设置相位和占空比。

选择复位为低电平触发、选择locked

这里可以自定义端口名

点击OK,Generate,即可生成PLL IP Core

点击IP source、找到后缀为.veo的文件,双击打开

里面的内容就是可以直接实例化调用的端口生成。

         这样便完成了VGA驱动时钟的生成,这里我把其他几种显示格式的参数和RGB显示的参数贴出来,这样便省去了不少事情。然后就是把你要显示的数据在行扫描有效和场扫描有效的时候输出,即可在显示屏显示了。其实这个显示并不难,那我为什么要专门写篇博客记录呢?因为以前老是看别人的代码,看的多了,自己的能力还是没有多大提升,但这部分显示图片是完全我自己分析时序显示出来的,所以有很大的成就感。学习这个东西还是得有人教导,从我学习FPGA以来,都是自己一个人瞎琢么,学习了一年了还没有一个好的画时序图的习惯,到仿真的时候再凑出时序图,还是要从基础抓起,不能只会敲代码。时序设计是关键,设计思想必须有。

         要显示一个彩色条纹也是比较简单的,例如在前一百五十行给VGA的数据为白色的,中间180行给VGA的数据为绿色,后面相同的方法。我这里要做的实验是在显示屏的左上角开一个200x200的框,最后将一幅200x200的图片显示进去,首先开一个200x200的正方形框,实现的方法就是控制行有效计数器计到需要显示正方形框的时候紫色的数据给lcd_data,行计数器为0-200,其他情况还是前面显示条纹的数据,同样的场有效计数器也从0-200计数时显示紫色数据带lcd_data,这样就会在显示屏左上角形成一个正方形的

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇串口发送模块——1字节数据发送 下一篇FPGA计算3行同列数据之和

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目