当前位置:首页 > 新闻资讯 > FPGA之家动态 >

FPGA基础设计之VGA显示方法(文字、图形、波形)

时间:2025-09-21      来源:FPGA_UCY 关于我们 0

概述

VGA是一种学习FPGA最常见的基础实验。虽然现在的显示屏大多已经采用DVI和HDMI方案,但其实VGA在另一个地方还有应用,那就是大屏的LCD。目前4.3寸以上的TFT基本都是VGA接口,这样在完成一个FPGA系统设计时,选择一个VGA接口的TFT用来显示便是最简单方便的方案。

现在2017年全国大学生电子设计大赛还有不到一个月,熟练的使用VGA显示各种图形、文字、波形还是很重要的,而不是停留在只能显示彩条的入门实验上。这篇博文便致力于解决这个问题。

VGA显示驱动

目前常见的电路板上的VGA接口是这样的,单独使用R、G、B三条线控制颜色:

FPGA

或者是这样的,增加一个电阻网络来使可以控制的颜色更加丰富:

FPGA

现在应该很少会看到专门使用VGA驱动芯片的了。使用电阻网络已经能获得不错的显示效果。FPGA需要处理的信号有行同步信号HSYNC和场同步信号VSYNC,以及R、G、B三组颜色控制信号。在驱动VGA之前,我们首先要确定自己的显示参数,分辨率及刷新率,比如800*600@60Hz的显示方式其时序参数如下所示:

FPGA

不同的分辨率和刷新率有不同的参数,这个数据可以在这个网页中查到。进下来就进行VGA的时序驱动,我的习惯是先将关键性数据用parameter定义出来:

//-------------------------------------------------//

// 扫描参数的设定 640*480 60Hz VGA

//-------------------------------------------------//

parameter H_SYNC_END = 96; //行同步脉冲结束时间

parameter V_SYNC_END = 2; //列同步脉冲结束时间

parameter H_SYNC_TOTAL = 800; //行扫描总像素单位

parameter V_SYNC_TOTAL = 525; //列扫描总像素单位

parameter H_SHOW_START = 144; //显示区行开始像素点

parameter V_SHOW_START = 35; //显示区列开始像素点

VGA的时序驱动部分是相当固定的,只要我们使用VGA,肯定会加入下面这段代码。主要方法是定义两个计数器,一个管理行扫描,一个管理列扫描;当行扫描计数器扫描完行同步脉冲后置高HSYNC信号;同理,当列扫描计数器扫描完列同步脉冲后置高VSYNC信号。

//水平扫描

always@(posedge clk_25M or negedge RSTn)

if(!RSTn) x_cnt 《= ‘d0;

else if (x_cnt == H_SYNC_TOTAL) x_cnt 《= ’d0;

else x_cnt 《= x_cnt + 1‘b1;

//垂直扫描

always@(posedge clk_25M or negedge RSTn)

if(!RSTn) y_cnt 《= ’d0;

else if (y_cnt == V_SYNC_TOTAL) y_cnt 《= ‘d0;

else if (x_cnt == H_SYNC_TOTAL) y_cnt 《= y_cnt + 1’b1;

else y_cnt 《= y_cnt;

//H_SYNC信号

always@(posedge clk_25M or negedge RSTn)

if(!RSTn) hsync 《= ‘d0;

else if (x_cnt == ’d0) hsync 《= 1‘b0;

else if (x_cnt == H_SYNC_END) hsync 《= 1’b1;

else hsync 《= hsync;

//_SYNC信号

always@(posedge clk_25M or negedge RSTn)

if(!RSTn) vsync 《= ‘d0;

else if (y_cnt == ’d0) vsync 《= 1‘b0;

else if (y_cnt == V_SYNC_END) vsync 《= 1’b1;

else vsync 《= vsync;

由于VGA需要一个时钟来管理扫描的速度,因此这个时钟大小就应当为扫面面积*刷新率,如上例中的640*480@60Hz的显示方式需要的VGA时钟大小为800*525*60=25.2MHz(扫描时不仅包括显示区域,还有同步脉冲、显示前沿和显示后沿,因此整个区域要大于分辨率)。VGA时钟可以用PLL或分频等方法产生,通常要求不会太严苛,上例取整为25MHz即可。

为了后面的显示方便,一种实用的方法是再定义两个寄存器,专门存储显示区域的坐标,即以可以显示的第一个像素点为坐标(0,0)。

assign x_pos = x_cnt - H_SHOW_START;

assign y_pos = y_cnt - V_SHOW_START;

这样上例中行扫描计数器和列扫描计数器的范围分别为800和525,而显示区域的坐标x_pos和y_pos范围只有640和480。

VGA显示图形、波形、文字

其实在得到了显示区域的坐标后,我们控制显示图像的方法就是当计数器扫描到指定位置后,为R、G、B三组信号赋值得到对应的图形。以前面写的“FPGA综合系统设计(一):贪吃蛇游戏(VGA+键盘)”这个工程中的显示部分代码为例:

always@(posedge clk_25M)

if (area) //坐标处于显示分数的区域内,80*80

begin

case(pop)

0: color_out 《= data0 ? 3‘b111 : 3’b000;

1: color_out 《= data1 ? 3‘b111 : 3’b000;

2: color_out 《= data2 ? 3‘b111 : 3’b000;

3: color_out 《= data3 ? 3‘b111 : 3’b000;

4: color_out 《= data4 ? 3‘b111 : 3’b000;

5: color_out 《= data5 ? 3‘b111 : 3’b000;

6: color_out 《= data6 ? 3‘b111 : 3’b000;

7: color_out 《= data7 ? 3‘b111 : 3’b000;

8: color_out 《= data8 ? 3‘b111 : 3’b000;

9: color_out 《= data9 ? 3‘b111 : 3’b000;

10: color_out 《= data10 ? 3‘b111 : 3’b000;

11: color_out 《= data11 ? 3‘b111 : 3’b000;

12: color_out 《= data12 ? 3‘b111 : 3’b000;

default : color_out 《= 3‘b000;


注明:本内容来源网络,不用于商业使用,禁止转载,如有侵权,请来信到邮箱:429562386ⓐqq.com 或联系本站客服处理,感谢配合!

用户登陆

    未注册用户登录后会自动为您创建账号

提交留言