**这是本文档旧的修订版!**
VGA接口实验
1. 实验内容
通过本实验了解VGA接口的工作原理,熟悉VGA接口的编程方法。
本实验要求将保存在FPGA内部存储器中的静态图像通过VGA接口显示在显示器上。
2. 实验原理
2.1 VGA接口电路原理图
在介绍VGA接口的工作原理之前,先介绍一下本实验的VGA接口电路图,如图 18 1所示。其中U18为VGA控制芯片ADV7123,而J21为VGA接口。实验中通过FPGA控制U18来实现图像的输出。
图18-1 实验原理图
2.2 VGA接口
VGA接口是计算机领域常用的一种常用的显示接口,在计算机中一般都由VGA显示卡来实现VGA接口。VGA显示卡系统一般由控制电路、显示缓存区和视频BIOS程序三个部分组成。控制电路如图18 2所示。控制电路主要完成时序发生、显示缓冲区数据操作、主时钟选择和D/A转换等功能;显示缓冲区提供显示数据缓存空间;视频BIOS作为控制程序固化在显示卡的ROM中。
图18-2 通用VGA显示卡控制电路原理
2.3 VGA时序分析
本实验需要在显示器上显示一个640480分辨率的静态图像,同时根据VGA接口需要产生相应的场行消影信号,具体信号比例如图 18 3所示。
图18-3 有效信号和场行消影信号所占的比例
控制VGA接口要解决数据来源、数据存储、时序实现等问题,其中关键还是如何实现VGA时序。 VGA的行时序如图 18-4所示,其中包括同步脉冲(Sync a)、显示后沿(Back porch b)、显示时序段(Display interval c)和显示前沿(Front porch d)四个部分。
图18-4 VGA行时序参考图
行时序中各个部分持续时钟周期分别为:同步脉冲96像素点周期,显示后沿48像素点周期,显示时序段640像素点周期,显示前沿16像素点周期,一共800个像素点周期。在程序中对应的参数为:
<code verilog>
parameter HSYNCCYC = 96;
parameter HSYNCBACK = 48;
parameter HSYNCACT = 640;
parameter HSYNCFRONT= 16;
parameter HSYNCTOTAL= 800;
</code>
图18-5 VGA场时序参考图
场时序和行时序不同的是,行时序以像素点周期为单位,而场时序则以行周期为单位。场时序也分为四个部分组成,如图 18 5所示,各个部分持续行周期数分别为:帧同步脉冲2个行周期,帧显示后沿32个行周期,帧显示时序段个480个行周期,帧显示前沿11个行周期,一共525个行周期。在程序中对应的参数为:
<code verilog>
parameter VSYNCCYC = 2;
parameter VSYNCBACK = 32;
parameter VSYNCACT = 480; 484
parameter VSYNCFRONT= 11;
parameter VSYNCTOTAL= 525;
</code>
#### 2.4 VGA时序实现
根据帧刷新频率以及每一帧的行数和每一行的像素个数来确定主时钟频率,确定主时钟之后,在FPGA中利用计数器,以计算出的各时序段时钟周期数为基准,产生不同宽度和周期的脉冲信号,再利用它们的逻辑组合构成图 18 4和图 18 5中的a、b、c、d各时序段以及D/A转换器的空白信号BLANK和同步信号SYNC。在行同步期间和场同步期间空白信号BLANK有效,而同步信号SYNC一直拉低。
在本实验中设计刷新率为60Hz/s,每帧包含525行,而每行包含800个像素点,在VGA主时钟频率为:60X525X800=25200000Hz,即25.2MHz。
### 3. 程序设计
#### 3.1 总体架构
整个程序由5个模块组成,如图18-6所示:
1. TE3Default是顶层模块,实例化各子模块并连接各子模块。
2. ResetDelay使系统延时20’hFFFFF个时钟周期(50MHz)后才开始工作,延时主是为了防止系统上电初期的不稳定性。
3. VGAController模块产生图 18 4和图 18 5所示的接口时序,同时控制VGAOSDRAM模块,读取VGAOSDRAM模块中ROM内保存的图像数据值,并将该图像通过VGA接口输出。
4. VGAOSDRAM模块存储待显示的图像。
5. VGAPLL模块产生频率为25.2MHz的VGA接口所需的主时钟。
图18-6 程序总体架构
#### 3.2 TE3Default模块(TE3Default.v)
TE3Default是顶层模块,实例化各模块。TE3Default输入输出接口如下:
<code verilog>
input CLOCK27 27 MHz时钟。
input CLOCK50 50 MHz时钟。
output VGACLK VGA时钟,25.2MHz。
output VGAHS VGA行同步信号线HSYNC
output VGAVS; VGA场同步信号线VSYNC
output VGABLANK; VGA空白信号指示信号BLANK
output VGASYNC; VGA SYNC
output [9:0] VGAR; VGA Red[9:0]
output [9:0] VGAG; VGA Green[9:0]
output [9:0] VGA_B; VGA Blue[9:0]
</code>
#### 3.3 ResetDelay模块(Reset_Delay.v)
系统延时20’hFFFFF个系统周期后才开始工作。具体程序如下所示:
<code verilog>
module Reset_Delay(iCLK,oRESET);
input iCLK;
output reg oRESET;
reg [19:0] Cont;
always@(posedge iCLK) begin
if(Cont!=20'hFFFFF) begin
Cont ⇐ Cont+1;
oRESET ⇐ 1'b0;
end
else
oRESET ⇐ 1'b1;
end
endmodule
</code>
#### 3.4 VGAController模块(VGAController.v)
VGA_Controller模块主完成两部分工作:产生图 18 4和图 18 5所示的时序;产生像素值存储的地址信息。其接口为如下所示:
<code verilog>
Host Side
output reg [19:0] oAddress;输出像素值存储的地址信号
output reg [9:0] oCoordX; 行内像素序号
output reg [9:0] oCoord_Y; 场内行周期序号
input [9:0] iRed;红色信号
input [9:0] iGreen;
input [9:0] iBlue;
VGA Side
output [9:0] oVGAR;
output [9:0] oVGAG;
output [9:0] oVGAB;
output reg oVGAHSYNC; VGA HSYNC:行同步信号线
output reg oVGAVSYNC; VGA VSYNC:帧同步信号线
output oVGASYNC; VGA同步信号
output oVGABLANK; VGA BLANK: 空白信号指示信号
output oVGACLOCK; VGA时钟:25.2MHz
Control Signal
input iCLK; 输入时钟:25.2MHz
input iRSTN;全局同步复位
VGAController模块产生图 18 4和图 18 5所示时序的程序如下所示:
assign oVGABLANK = oVGAHSYNC & oVGAVSYNC;
assign oVGASYNC = 1'b0;
assign oVGACLOCK = iCLK;
根据25.2Mhz的时钟生成行同步信号
always@(posedge iCLK or negedge iRSTN) begin
if(!iRSTN)
begin
HCont ⇐ 0; 像素点计数器
oVGAHSYNC ⇐ 0; 行同步信号
end
else begin
if( HCont < HSYNCTOTAL ) HCont小于行周期800,一直增加。
HCont ⇐ HCont+1;
else
HCont ⇐ 0;
if( HCont < HSYNCCYC ) 生成行同步信号
oVGAHSYNC ⇐ 0;
else
oVGA_H_SYNC ⇐ 1;
end
end
根据行同步信号产生帧同步信号
always@(posedge iCLK or negedge iRSTN) begin
if(!iRSTN) begin
VCont ⇐ 0;行计数器
oVGAVSYNC ⇐ 0; 帧同步信号
end
else begin
When HSync Re-start
if(HCont==0) begin
if( VCont < VSYNCTOTAL ) VCont小于行周期525,一直增加。
VCont ⇐ VCont+1;
else
VCont ⇐ 0;
if( VCont < VSYNCCYC ) 生成场同步信号
oVGAVSYNC ⇐ 0;
else
oVGAVSYNC ⇐ 1;
end
end
end
VGAController模块产生像素值存储地址的程序如下所示:
生成地址信息
always@(posedge iCLK or negedge iRSTN) begin
if(!iRSTN) begin
oCoordX ⇐ 0;当前像素点在当前行内的序号。
oCoordY ⇐ 0;当前像素所在行在当前帧内的序号。
oAddress ⇐ 0; 产生的地址信号。
end
else begin
if( HCont>=XSTART && HCont<XSTART+HSYNCACT &&
VCont>=YSTART && VCont<YSTART+VSYNCACT )
begin
oCoordX ⇐ HCont-XSTART;
oCoordY ⇐ VCont-YSTART;
根据所处的行数和所处的行中的像素数生成当前像素存储的地址。
oAddress ⇐ oCoordY*HSYNCACT+oCoord_X-3;
end
end
end
</code>
### 4. 仿真结果
### 5. 演示程序文件说明
### 6. 演示程序使用