天天看點

fpga學習之vga驅動

一、什麼是vga?

vga:(Video Graphics Array,視訊圖形陣列),是 IBM 于 1987 年提出的一個使用類比訊号的電腦顯示标準。VGA 是最多制造商所共同支援的一個低标準,個人電腦在加載自己的獨特驅動程式之前,都必須支援 VGA 的标準。

二、vga掃描方式

顯示器掃描方式分為逐行掃描和隔行掃描:逐行掃描是掃描從螢幕左上角一點開始,從左向右逐點掃描,每掃描完一行, 電子束回到螢幕的左邊下一行的起始位置,在這期間, CRT 對電子束進行消隐,每行結束時,用行同步信号進行同

步;當掃描完所有的行,形成一幀,用場同步信号進行場同步,并使掃描回到螢幕左上方,同時進行場消隐,開始下一幀。 隔行掃描是指電子束掃描時每隔一行掃一線,掃完一屏後再傳回來掃描剩下的線,隔行掃描的顯示器閃爍快速,可能會使使用者眼睛疲勞。在實際應用中,多數使用逐行掃描,本實驗就采用逐行掃描。

三、vga的顯示标準

fpga學習之vga驅動

四、vga顯示時序

1、行掃描時序:

fpga學習之vga驅動

2、場掃描時序

fpga學習之vga驅動

根據上述顯示器的掃描參數以及掃描時序,例如 800[email protected] 的顯示模式,60 指得是顯示器圖像的重新整理頻率,時鐘 40MHz 指得是一個像素輸出的頻率。800600 為 VGA 的分辨率,指有效顯示區域為時序中的 c 段隻有 800600,也就是行計數在[216,1016],列計數在[27,627],在這個範圍内,給 RGB 色值才會有效。

2、顯示時序要求(顯示步驟):以800600 為 VGA 的分辨率

行:行同步信号上電拉高,在行同步計數為 0 時拉低 a 個時鐘周期,即 128,之後拉高,在行同步計數到 1055 時,

行同步計數器清零,場同步計數器加 1。在行掃描時序中,掃描計數時,周期就是一個像素點的時間。

場:在場同步計數為 0 時拉低場同步 a 個時鐘周期,即 4,之後拉高,在場同步計數到 627 時,場同步計數器清零。

3、三基色的控制(R,G,B)既是:紅,綠,藍。

在vga接口中,還需要控制三個接口,即三基色。它們使用8bit,16bit的最多(我們在本實驗中采用八位,16位跟八位沒什麼本質上的差別),8bit的三基色:R為3bit,G為3bit,B為2bit,可以顯示2^8種顔色 ;

16bit的三基色:R為5bit,G為6bit,B為5bit。分别可以顯示2^16種顔色;

fpga學習之vga驅動

四、設計目的及源碼設計

1、設計目的:

本設計選擇的 VGA 顯示标準為 800*[email protected],實作點亮整個螢幕,并顯示為全綠色。

2、源碼設計:

a、rtl原理圖

fpga學習之vga驅動

b、源碼設計

頂層設計

module vga_display (	
	input 				clk   	  ,    //系統時鐘50Mhz
	input 				rst_n      ,    //系統時鐘複位
	output 				vga_vs     ,    //VGA場同步信号
	output 				vga_hs     ,	 //VGA行同步信号
	output [7:0]	 	vga_rgb	      //VGA場紅綠藍三基色
	);
	
	
	//----------------VGA時序-----------------------------------
	//		顯示模式	  	時鐘	   
	//		800*[email protected]  40MHz	
	//行/場	同步(a)	消隐後沿(b)	有效顯示(c)	消隐前沿(d)	掃描時間(e)
	//hs		128		88				800			40				1056
	//vs		4			23				600			1				628	
	
	wire vga_clk;
	
	//鎖相環分頻子產品
	vga_pll vga_pll_dut(
		.areset(~rst_n),
		.inclk0(clk),
		.c0(vga_clk)
	);
	
	//vga驅動控制子產品
	vga_control vga_control_dut(
		.vga_clk(vga_clk), 
		.rst_n(rst_n), 
		.vga_hs(vga_hs),
		.vga_vs(vga_vs),
		.vga_rgb(vga_rgb)
	);
	
endmodule 
           

vga控制子產品設計

module vga_control (
	input 				   vga_clk    , 	//系統時鐘40Mhz
	input 				   rst_n  	  ,    //系統複位
	output 	reg			vga_vs     ,    //VGA場同步信号
	output 	reg 			vga_hs     ,	   //VGA行同步信号
	output [7:0]	 	   vga_rgb	     //VGA場紅綠藍三基色
);
	
	//----------------VGA時序-----------------------------------
	//		顯示模式	  	時鐘	   
	//		800*[email protected]  40MHz	
	//行/場	同步(a)	消隐後沿(b)	有效顯示(c)	消隐前沿(d)	掃描時間(e)
	//hs		128		88				800			40				1056
	//vs		4			23				600			1				628	
	
	//	行(Horizontal)掃描	Parameter (像素)
	parameter	H_A	=	128;
	parameter	H_B	=	80;
	parameter	H_C	=	800;
	parameter	H_D	=	40;
	parameter	H_E   =	1056;
	
	
	//	場(Vertical)掃描	Parameter (行數)
	parameter	V_A	=	4;
	parameter	V_B	=	23;
	parameter	V_C	=	600;
	parameter	V_D	=	1;
	parameter	V_E	=	628;
	
	//行掃描計數器, 
	reg [10:0] hcnt;
	
	always @ (posedge vga_clk  or negedge rst_n)
	begin
		if (!rst_n)
			hcnt <= 11'd0;
		else
			begin
				if (hcnt == (H_E - 1'b1)) //掃描完一行像素
					hcnt <= 11'd0;
				else
					hcnt <= hcnt + 1'b1;
			end 
	end 
	
	//場掃描計數器
	reg [12:0] vcnt;  
	
	always @ (posedge vga_clk  or negedge rst_n)
	begin
		if (!rst_n)
			vcnt <= 11'd0;
		else if (vcnt == (V_E - 1'b1)) 
			vcnt <= 11'd0;
		else if (hcnt == (H_E - 1'b1))
			vcnt <= vcnt + 1;
	end 	

	//行同步輸出
	always @ (posedge vga_clk  or negedge rst_n)
	begin
		if (!rst_n)
			vga_hs <= 1'b1;
		else if (hcnt < H_A)
			vga_hs <= 1'b0;
		else
			vga_hs <= 1'b1;
	end 
	
	//場同步輸出
	always @ (posedge vga_clk  or negedge rst_n)
	begin
		if (!rst_n)
			vga_vs <= 1'b1;
		else if (vcnt < V_A)
			vga_vs <= 1'b0;
		else
			vga_vs <= 1'b1;
	end 
	
	wire rgb_en;
	
	assign rgb_en = (hcnt >= H_A + H_B  && hcnt < H_A + H_B + H_C) && 
						(vcnt >= V_A + V_B  && vcnt < V_A + V_B + V_C) ? 1'b1 : 1'b0;
	
	//判斷使能信号是否有效,1有效顯示綠色,0無效顯示黑色
	assign vga_rgb = rgb_en ? 8'b000_111_00 : 8'b0000_0000;
	
endmodule 
           

仿真子產品設計

`timescale 1ns/1ps  //仿真時間精度時間機關

module vga_display_tb;
	
	reg            clk				;   	 //系統時鐘
	reg				rst_n				; 		//系統複位
	wire 			   vga_vs			;    //VGA場同步信号
	wire  			vga_hs			;	  //VGA行同步信号
	wire 	[7:0] 	vga_rgb			;	 //VGA場紅綠藍三基色
	
	//初始化資料,并附相應初值
	initial begin
		clk = 0;
		rst_n = 0;  
		#200.1 rst_n = 1;  
	end 

	vga_display vga_display_inst (
		.clk(clk), 
		.rst_n(rst_n), 
		.vga_hs(vga_hs),
		.vga_vs(vga_vs),
		.vga_rgb(vga_rgb)
	);
	
	always #10 clk = ~clk;  //50MHz時鐘描述

endmodule
           

仿真圖

fpga學習之vga驅動

注:本實驗的分頻子產品采用pll(鎖相環分頻),是以需要添加ip核,否則會出錯。這是基本的vga驅動,大家可以在這個基礎上做一些好玩的東西,例如利用vga顯示漢字,顯示圖檔,顯示數字等。。。。。。,大家可以思考一下噢!