[X]关闭

2.VGA时序与模拟彩条实现

文档创建者:自恋狂vip
浏览次数:5819
最后更新:2015-12-22
图像显示模块是我们最重要的环节之一,因为图像显示是将我们图像处理后的结果进行可视化显示,我们可以很直观的看到是否为我们预期处理的效果。我们使用VGA接口来驱动液晶屏。
VGA(Video Graphics Array,视频图像阵列)是一种视频传输标准,具有分辨率高、颜色饱和丰富以及刷新速率快等优点,主要作为计算机显卡传输图像到显示器的桥梁,将显卡处理后的图像传输给显示器进行实时显示。VGA接口作为一种视频图像信号传输的标准接口,被广泛使用在各类视频显示场合。
VGA接口采用15针的D型接口,分三排,一排五个管脚。如下图为VGA接口公头(左)和母头(右),下表为对应的管脚说明。
VGA管脚说明

编号
管脚名
详情
  
1
  
  
RED
  
  
红色信号输入线
  
  
2
  
  
GREEN
  
  
绿色信号输入线
  
  
3
  
  
BLUE
  
  
蓝色信号输入线
  
  
4
  
  
ID Bit
  
  
地址码线
  
  
5
  
  
Self_Test
  
  
自测试信号线
  
  
6
  
  
RGND
  
  
红基色信号地线
  
  
7
  
  
GGND
  
  
绿基色信号地线
  
  
8
  
  
BGND
  
  
蓝基色信号地线
  
  
9
  
  
RESERVED
  
  
保留
  
  
10
  
  
SGND
  
  
数字信号地线
  
  
11
  
  
ID0
  
  
显示器标志位0
  
  
12
  
  
ID1
  
  
显示器标志位1
  
  
13
  
  
HSYNC
  
  
行同步信号线
  
  
14
  
  
VSYNC
  
  
场同步信号线
  
  
15
  
  
ID3
  
  
显示器标志位3
  
VGA时序及驱动
VGA最重要的信号是:RED、GREEN、BLUE及HSYNC和VSYNC,其中前面三种是数据信号,后面两种是控制信号,数据信号的传输是靠控制信号来进行同步控制的,下面介绍行和场控制信号如何对数据信号进行同步的。
一个完整行的扫描周期由a、b、c、d四部分组成,其中H_SYNC(a)为行同步阶段,对行扫描地址进行复位;H_BACK(b)为行消隐后肩,是扫描地址转移后的准备期;H_DISP(c)为行显示阶段,此阶段像素数据为有效;H_FRONT(d)为行消隐前肩,为扫描地址转移的准备期;H_TOTAL(e)为完成一次行扫描的总时间。扫描时候,先进行行同步,然后才进行数据的传输,其时序如下图。
VGA行扫描时序图

场扫描与行扫描时序类似,场扫描周期由n个行扫描周期组成,并且一次场扫描周期有其自身的时序规律,完成一定行数的行扫描后,进行一次场同步
该行数与VGA分辨率有关,如下图为VGA场扫描时序图。
VGA行扫描时序图
VGA显示分辨率与刷新频率是紧密联系的,是VGA时序标准,下表为VGA常用分辨率和刷新频率及场行时序之间的关系。
VGA常见显示模式时序表
  
显示模式
时钟
  
(MHZ)
行时序(像素数)
帧时序(行数)
a
b
c
d
e
o
p
q
r
s
640x480@60
25.175
96
48
640
16
800
2
33
480
10
525
640x480@75
31.5
64
120
640
16
840
3
16
480
1
500
800x600@60
40.0
128
88
800
40
1056
4
23
600
1
628
800x600@75
49.5
80
160
800
16
1056
3
21
600
1
625
1024x768@60
65
136
160
1024
24
1344
6
29
768
3
806
1024x768@75
78.8
176
176
1024
16
1312
3
28
768
1
800
1280x1024@60
108.0
112
248
1280
48
1688
3
38
1024
1
1066
1280x800@60
83.46
136
200
1280
64
1680
3
24
800
1
828
1440x900@60
106.47
152
232
1440
80
1904
3
28
900
1
932
根据前面VGA显示模式时序表,我们在Vivado里使用Verilog编写相应的代码,生成相应的驱动时序,这里我们通过经典的模拟彩条来进行对VGA进行驱动与验证。
为了方便测试不同分辨率(不同帧率)下的驱动情况,我们将不同显示模式都保存在一个.v文件中,使用 `include "VGA_para.v" 来包含常用的场行时序常数,然后通过宏定义来选择不同的分辨率。
下面是选择640x480的宏定义代码。
//------------------------------------
//vga parameter define
`define  VGA_640_480_60FPS_25MHz
//`define       VGA_800_600_72FPS_50MHz
//`define       VGA_1024_768_60FPS_65MHz
//`define       VGA_1440_900_60FPS_105MHz
//`define       VGA_1280_1024_60FPS_105MHz
//---------------------------------
根据前面选择的宏定义,下面的代码便是640x480的时序生成。
//---------------------------------
//    640 * 480
`ifdef    VGA_640_480_60FPS_25MHz
`define  H_FRONT   11'd16
`define  H_SYNC    11'd96
`define  H_BACK    11'd48
`define  H_DISP       11'd640
`define  H_TOTAL   11'd800      
                                 
`define  V_FRONT   11'd10
`define  V_SYNC    11'd2  
`define  V_BACK    11'd33
`define  V_DISP      11'd480  
`define  V_TOTAL   11'd525
`endif
//---------------------------------
同理,如果想要使用1440x900的分辨率,我们只需将VGA常见显示模式时序表中的时序常数对应修改,便可以转换到相应的分辨率显示模式。
因为我们的开发板上VGA的接口预留的是RGB444,因此我们需要定义颜色分量值,下面代码是定义不同颜色的RGB值。
//define colors RGB--4|4|4
`define RED      12'h800   /*1111,0000,0000 */
`define GREEN 12'hF0   /*0000,1111,0000 */
`define BLUE         12'h00F  /*0000,0000,1111*/
`define WHITE        12'hFFF   /*1111,1111,1111*/
`define BLACK       12'h000   /*0000,0000,0000 */
`define YELLOW     12'hFF0   /*1111,1111,0000*/
`define CYAN        12'hF0F  /*1111,0000,1111*/
`define ROYAL       12'h0FF   /*0000,1111,1111*/
对于场行同步信号的生成,我们只需编写相应的时序即可,下面是其代码。
//----------------行扫描进程-------------------
always@(posedge clk_out)
begin
   if(hcount == `H_TOTAL)      // 行计数结束
          hcount_ov <= 1;         // 行计数结束标志
      else
          hcount_ov <= 0;
end
always@(posedge clk_out)
begin
  if(hcount_ov == 1)
     hcount <= 12'b0;           //行计数从新开始
else
     hcount <= hcount + 1;   
end
//----------------行同步信号的生成-------------------
//always@(hcount)
always@(posedge clk_out)
begin
    if(hcount > `H_SYNC)
          hsync <= 1;
    else
          hsync <= 0;    //低电平同步
end
//----------------场扫描进程---------------------
always@(posedge clk_out)
begin
    if(vcount == `V_TOTAL)     // 场计数结束
          vcount_ov <= 1;         // 场计数结束标志
       else
         vcount_ov <= 0;
end
always@(posedge clk_out)
begin
    if(hcount_ov == 1)   begin
          if(vcount_ov == 1)
                vcount <= 12'b0;      //场计数从新开始
             else
                vcount <= vcount + 1;
       end
end
//----------------场同步信号生成-------------------
always@(posedge clk_out)
begin
    if(vcount > `V_SYNC)
        vsync <= 1;
       else
        vsync <= 0;             //低电平同步
end
我们选择640x480@60显示模式,也就是驱动时钟为25MHz,场行消隐以及有效显示都应该严格符合时序表中的时序要求。下面为VGA彩条显示代码。
always@(posedge clk) begin
if((hcounter < H_DISP) && (vcounter< H_DISP))begin
      if (hcounter <= H_DISP /5)     begin   colour <= `C_RED;    end
     else if(hcounter <= 2* H_DISP /5)  begin  colour <= `C_GREEN;  end
     else if(hcounter <= 3* H_DISP /5)  begin  colour <= `C_BLUE;   end
     else if(hcounter <= 4* H_DISP /5)  begin  colour <= `C_WHITE;  end
     else begin  colour <= `C_BLACK;  end
     end  else
         colour <= `C_BLACK;
end
最终运行我们的VGA模拟彩条驱动代码,运行在我们开发板上的显示效果如下图所示,可以看得出我们代码是正确的。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

发表评论已发布 1

宋桓公

发表于 2015-12-22 19:45:10 | 显示全部楼层

不错~~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则