通过本实验了解VGA接口的工作原理,熟悉VGA接口的编程方法。

本实验要求将保存在FPGA内部存储器中的静态图像通过VGA接口显示在显示器上。



2.1 VGA接口电路原理图

在介绍VGA接口的工作原理之前,先介绍一下本实验的VGA接口电路图,如图18-1所示。其中U18为VGA控制芯片ADV7123,而J21为VGA接口。实验中通过FPGA控制U18来实现图像的输出。 图18-1 实验原理图

图18-1 实验原理图

2.2 VGA接口

VGA接口是计算机领域常用的一种常用的显示接口,在计算机中一般都由VGA显示卡来实现VGA接口。VGA显示卡系统一般由控制电路、显示缓存区和视频BIOS程序三个部分组成。控制电路如图18 2所示。控制电路主要完成时序发生、显示缓冲区数据操作、主时钟选择和D/A转换等功能;显示缓冲区提供显示数据缓存空间;视频BIOS作为控制程序固化在显示卡的ROM中。

图18-2 通用VGA显示卡控制电路原理

图18-2 通用VGA显示卡控制电路原理

2.3 VGA时序分析

本实验需要在显示器上显示一个640*480分辨率的静态图像,同时根据VGA接口需要产生相应的场行消影信号,具体信号比例如图18-3所示。

图18-3 有效信号和场行消影信号所占的比例

图18-3 有效信号和场行消影信号所占的比例


控制VGA接口要解决数据来源、数据存储、时序实现等问题,其中关键还是如何实现VGA时序。 VGA的行时序如图 18-4所示,其中包括同步脉冲(Sync a)、显示后沿(Back porch b)、显示时序段(Display interval c)和显示前沿(Front porch d)四个部分。

图18-4 VGA行时序参考图

图18-4 VGA行时序参考图

行时序中各个部分持续时钟周期分别为:同步脉冲96像素点周期,显示后沿48像素点周期,显示时序段640像素点周期,显示前沿16像素点周期,一共800个像素点周期。在程序中对应的参数为:

 
parameter	H_SYNC_CYC	=	96;
parameter	H_SYNC_BACK	=	48;
parameter	H_SYNC_ACT	=	640;	
parameter	H_SYNC_FRONT=	16;
parameter	H_SYNC_TOTAL=	800;

图18-5   VGA场时序参考图

图18-5 VGA场时序参考图


场时序和行时序不同的是,行时序以像素点周期为单位,而场时序则以行周期为单位。场时序也分为四个部分组成,如图 18 5所示,各个部分持续行周期数分别为:帧同步脉冲2个行周期,帧显示后沿32个行周期,帧显示时序段个480个行周期,帧显示前沿11个行周期,一共525个行周期。在程序中对应的参数为:

 
parameter	V_SYNC_CYC	=	2;
parameter	V_SYNC_BACK	=	32;
parameter	V_SYNC_ACT	=	480;	//	484
parameter	V_SYNC_FRONT=	11;
parameter	V_SYNC_TOTAL=	525;

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.1 总体架构

整个程序由5个模块组成,如图18-6所示:
1. TE3Default是顶层模块,实例化各子模块并连接各子模块。
2. Reset
Delay使系统延时20’hFFFFF个时钟周期(50MHz)后才开始工作,延时主是为了防止系统上电初期的不稳定性。
3. VGAController模块产生图 18 4和图 18 5所示的接口时序,同时控制VGAOSDRAM模块,读取VGAOSDRAM模块中ROM内保存的图像数据值,并将该图像通过VGA接口输出。
4. VGA
OSDRAM模块存储待显示的图像。
5. VGA
PLL模块产生频率为25.2MHz的VGA接口所需的主时钟。 图18-6 程序总体架构

图18-6 程序总体架构

3.2 TE3_Default模块(TE3_Default.v)

TE3Default是顶层模块,实例化各模块。TE3Default输入输出接口如下:

 
input		CLOCK_27				//27 MHz时钟。
input		CLOCK_50				//50 MHz时钟。
output	VGA_CLK  				//VGA时钟,25.2MHz。
output	VGA_HS					//VGA行同步信号线H_SYNC
output	VGA_VS;				//VGA场同步信号线V_SYNC
output	VGA_BLANK;			//VGA空白信号指示信号BLANK
output	VGA_SYNC;				//VGA SYNC
output	[9:0]	VGA_R;   			//VGA Red[9:0]
output	[9:0]	VGA_G;	 			//VGA Green[9:0]
output	[9:0]	VGA_B;   			//VGA Blue[9:0]

3.3 Reset_Delay模块(Reset_Delay.v)

系统延时20’hFFFFF个系统周期后才开始工作。具体程序如下所示:

 
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

3.4 VGA_Controller模块(VGA_Controller.v)

VGA_Controller模块主完成两部分工作:产生图 18 4和图 18 5所示的时序;产生像素值存储的地址信息。其接口为如下所示:

 
//	Host Side
output	reg	[19:0]	oAddress;//输出像素值存储的地址信号
output	reg	[9:0]	oCoord_X;  //行内像素序号
output	reg	[9:0]	oCoord_Y;  //场内行周期序号
 
input		[9:0]	iRed;//红色信号
input		[9:0]	iGreen;
input		[9:0]	iBlue;
//	VGA Side
output		[9:0]	oVGA_R;
output		[9:0]	oVGA_G;
output		[9:0]	oVGA_B;
output	reg			oVGA_H_SYNC; //	VGA H_SYNC:行同步信号线
output	reg			oVGA_V_SYNC; //VGA V_SYNC:帧同步信号线
output				oVGA_SYNC; //VGA同步信号
output				oVGA_BLANK; //VGA BLANK: 空白信号指示信号
output				oVGA_CLOCK; //	VGA时钟:25.2MHz
//	Control Signal
input				iCLK; //	输入时钟:25.2MHz
input				iRST_N;//全局同步复位
VGA_Controller模块产生图 18 4和图 18 5所示时序的程序如下所示:
assign	oVGA_BLANK	=	oVGA_H_SYNC & oVGA_V_SYNC;
assign	oVGA_SYNC		=	1'b0;
assign	oVGA_CLOCK	=	iCLK;
//根据25.2Mhz的时钟生成行同步信号
always@(posedge iCLK or negedge iRST_N) begin
	if(!iRST_N)
	begin
		H_Cont			<=	0; //像素点计数器
		oVGA_H_SYNC	<=	0; //行同步信号
	end
	else begin		
		if( H_Cont < H_SYNC_TOTAL )// H_Cont小于行周期800,一直增加。
			H_Cont	<=	H_Cont+1;
		else
			H_Cont	<=	0;
		if( H_Cont < H_SYNC_CYC ) // 生成行同步信号
			oVGA_H_SYNC	<=	0;
		else
			oVGA_H_SYNC	<=	1;
	end
end
 
//	根据行同步信号产生帧同步信号
always@(posedge iCLK or negedge iRST_N) begin
	if(!iRST_N) begin
		V_Cont			<=	0;//行计数器
		oVGA_V_SYNC	<=	0; //帧同步信号
	end
	else begin
		//	When H_Sync Re-start
		if(H_Cont==0) begin
			if( V_Cont < V_SYNC_TOTAL )// V_Cont小于行周期525,一直增加。
				V_Cont	<=	V_Cont+1;
			else
				V_Cont	<=	0;
			if(	V_Cont < V_SYNC_CYC ) // 生成场同步信号
				oVGA_V_SYNC	<=	0;
			else
				oVGA_V_SYNC	<=	1;
		end
	end
end
VGA_Controller模块产生像素值存储地址的程序如下所示:
//	生成地址信息
always@(posedge iCLK or negedge iRST_N) begin
	if(!iRST_N) begin
		oCoord_X	<=	0;//当前像素点在当前行内的序号。
		oCoord_Y	<=	0;//当前像素所在行在当前帧内的序号。
		oAddress		<=	0; //产生的地址信号。
	end
	else begin
		if(	H_Cont>=X_START && H_Cont<X_START+H_SYNC_ACT &&
			V_Cont>=Y_START && V_Cont<Y_START+V_SYNC_ACT )
		begin
			oCoord_X	<=	H_Cont-X_START;
			oCoord_Y	<=	V_Cont-Y_START;
            //根据所处的行数和所处的行中的像素数生成当前像素存储的地址。
			oAddress	<=	oCoord_Y*H_SYNC_ACT+oCoord_X-3;
		end
	end
end

3.5 VGA_OSD_RAM模块(VGA_OSD_RAM.v)

这里需要说明的是因为FPGA内部的RAM大小有限,无法存储10位三基色的图像数据,所以这里只存储了黑白2值图像。VGAOSDRAM模块根据读取出来的2值图像的值,也即是根据读取出来的是0还是1而给出相应的10位的三基色。其接口如下所示:

 
output	reg	[9:0]	oRed;//输出像素色彩信号
output	reg	[9:0]	oGreen; //输出像素色彩信号
output	reg	[9:0]	oBlue; //输出像素色彩信号
input	[18:0]		iVGA_ADDR; //输出像素值存储的地址信号
input				iVGA_CLK; //	VGA时钟:25.2MHz
input	[18:0]		iWR_ADDR; //输入写地址信号
input				iWR_DATA;//输入待写入数据
input				iWR_EN;//输入写使能
input				iWR_CLK;//输入写时钟
input	[9:0]	iON_R;//当存储的像素点数据位1’b1时,对应的RGB三色值
input	[9:0]	iON_G;
input	[9:0]	iON_B;
input	[9:0]	iOFF_R; //当存储的像素点数据位1’b0时,对应的RGB三色值
input	[9:0]	iOFF_G;
input	[9:0]	iOFF_B;
input				iRST_N;
具体程序如下所示:
reg		[2:0]		ADDR_d;//存储输入地址信号的低3位
reg		[2:0]		ADDR_dd;//为时序需要将ADDR_d延时一个时钟周期
always@(posedge iVGA_CLK or negedge iRST_N) begin
	if(!iRST_N) begin
		oRed	<=	0;
		oGreen	<=	0;
		oBlue	<=	0;
		ADDR_d	<=	0;
		ADDR_dd<=	0;
 
	end
	else begin
		ADDR_d	<=	iVGA_ADDR[2:0];
ADDR_dd	<=	~ADDR_d;  
		oRed	<=	ROM_DATA[ADDR_dd]?	iON_R : iOFF_R; //根据该像素对应
//在存储器的值为0还是为1,输出项对应的10为RGB三色信号
 
		oGreen	<=	ROM_DATA[ADDR_dd]?	iON_G : iOFF_G;
		oBlue	<=	ROM_DATA[ADDR_dd]?	iON_B : iOFF_B; 	
end
end
//存储了图像的RAM。
Img_RAM 	u0	(	//写入接口,目前没有使用
					.data(iWR_DATA),
					.wren(iWR_EN),
					.wraddress({iWR_ADDR[18:3],~iWR_ADDR[2:0]}),
					.wrclock(iWR_CLK),
					//	Read Out Side
					.rdaddress(iVGA_ADDR[18:3]),
					.rdclock(iVGA_CLK),
					.q(ROM_DATA));

读取出来的数据为8位宽,而8位宽的数据中的每一位对应一个像素点,同时8位位宽数据的低位对应的像素应该先显示在屏幕上,截取输入地址信号iVGA_ADDR的低3位作为MUX,输出相应的像素信息。



通过SignalTap看到的FPGA内部场行同步信号如图 18 7所示,其中VGAHS为图 18 4所示时序,而VGAR为红色信号线,而VGA_VS为场同步信号线。

图18-7 运行结果

图18-7 运行结果



文件名功能
TE3Default.v|顶层模块。| |ResetDelay.v延时模块。
VGAController.v|VGA控制逻辑模块| |VGAOSDRAM.v|存储显示数据模块。| |VGAPLL.v产生频率为25.2MHz的VGA时序所需的主时钟。



演示设备:核心板、扩展板、带VGA接口的显示器。

演示方法:将显示器连接到开发板上面的VGA接口上,然后把程序下载到开发板上既可以看到显示器上显示的图像。