原创 23.我与FPGA的恋爱之VGA显示

2016-4-24 20:51 1273 23 23 分类: FPGA/CPLD 文集: 我与FPGA的恋爱

VGA(Video Graphics Array,视频图形阵列), 是 IBM 于 1987 年提出的一个使用类比讯号的电脑显示标准。 VGA 是最多制造商所共同支持的一个低标准,个人电脑在加载自己的独特驱动程式之前,都必须支持 VGA 的标准

VGA 扫描方式
    显示器扫描方式分为逐行扫描和隔行扫描:逐行扫描是扫描从屏幕左上角一点开始,从左向右逐点扫描,每扫描完一行, 电子束回到屏幕的左边下一行的起始位置,在这期间, CRT 对电子束进行消隐,每行结束时,用行同步信号进行同步;当扫描完所有的行,形成一帧,用场同步信号进行场同步,并使扫描回到屏幕左上方,同时进行场消隐,开始下一帧。 隔行扫描是指电子束扫描时每隔一行扫一线,扫完一屏后再返回来扫描剩下的线,隔行扫描的显示器闪烁快速,可能会使使用者眼睛疲劳( 本实验采用逐行扫描的方式)扫描原理清楚以后,紧接着大家再来看看 VGA 的行、列同步时序

 

 

1000001733-6359712719205400004075910.jpg-g560

1000001733-6359712719205500004075910.jpg-g560


 

VGA 中定义行时序和列时序都需要同步脉冲( a 段),显示后沿( b 段)、显示时序段( c 段)和显示前沿( d 段)四部分。 VGA 工业标准显示模式要求:行同步、列同步都为负极性,即同步脉冲要求是负脉冲。由 VGA 行时序可知:每一行都有一个负极性行同步脉冲( a 段),是数据行的结束标志,同时也是下一行的开始标志。在同步脉冲之后为显示后沿( b 段),在显示时序段( c 段)显示器为亮的过程, RGB 数据驱动一行上的每一个像素点,从而显示一行。在一行的最后为显示前沿( d 段)。在显示时间段之外没有图像投射到屏幕,而是插入消隐信号。同步脉冲、显示后沿和显示前沿都是在行消隐间隔内,当消隐有效时, RGB 信号无效,屏幕不显示数据。VGA 的列时序与行时序分析基本一致

2016-04-24_204105.jpg

以红色框图的显示标准 800*600*60Hz 为例。 (800 为列数, 600 为行数,60Hz 为刷新一屏的频率)
行时序:屏幕对应的行数为 628( a+b+c+d=e 段),其中 600( c 段)为显示行;每行均有行同步信号( a 段),为 4 个行周期的低电平;
列时序:每个显示行包括 1056 列( a+b+c+d=e 段),其中 800( c 段)为有效显示区,每一行有一个行同步信号( a 段),为 128 个行周期的低电
平。
扫描时钟频率: 40MHZ

 

设计模块说明:

(1)时钟分频模块
    我们开发板上使用的晶振为 50MHZ,由于我们的显示标准为 800*600*60HZ,所以我们需要分频输出 40MHZ 的系统时钟。时钟分频模块,我们可以通过调用锁相环来实现。
(2)VGA 行列同步控制模块
    VGA 显示标准需要设定行列同步信号,标定出有效显示区域,这也是整个 VGA驱动模块的核心部分
(3)VGA 色彩显示控制模块
    在图像有效显示区域内,输出控制颜色的 r、 g、 b 信号

module VGA_top(
					clk,
					rst_n,
					vga_hs,
					vga_vs,
					vga_r,
					vga_g,
					vga_b
					);
	input clk,rst_n;
	output vga_hs,vga_vs;
	output [2:0] vga_r;
	output [2:0] vga_g;
	output [1:0] vga_b;
	
	wire clk_25;
	wire en;

	pll pll(
				.inclk0(clk),
				.c0(clk_25)
	);
	
	VGA VGA(
				.clk(clk_25),
				.rst_n(rst_n),
				.vga_hs(vga_hs),
				.vga_vs(vga_vs),
				.en(en)
				);
	
	RGB RGB(
				.en(en),
				.vga_r(vga_r),
				.vga_g(vga_g),
				.vga_b(vga_b)
				);
endmodule

/***************************************************
	VGA:	1440(行)*900(列)*60(刷新)  
			扫描时钟 106Mhz
			
			同步(a)	后沿(b)	有效(c)	前沿(d)	周期(e)
	hs	:	
	vs	:	
	
***************************************************/
module VGA(
				clk,
				rst_n,
				vga_hs,
				vga_vs,
				en
				);
	input clk,rst_n;
	output reg vga_hs;//列同步信号
	output reg vga_vs;//行同步信号
	output en;//显示有效区域的使能信号640*480
	
	parameter
			//vga_hs
			hs_a 	=	10'd96,
			hs_b	=	10'd48,
			hs_c	=	10'd640,
			hs_d	= 	10'd16,
			hs_e	=	10'd800,
			//vga_vs
			vs_a	=	10'd2,
			vs_b	=	10'd33,
			vs_c	=	10'd480,
			vs_d	=	10'd10,
			vs_e	=	10'd525;
	
	reg [9:0] cnt_hs;//列计数器
	reg [9:0] cnt_vs;//
//------------------扫描计数----------------	
	always @(posedge clk or negedge rst_n)
	if(!rst_n)
		cnt_hs <= 10'd0;
	else if(cnt_hs == (hs_e - 1))//所有列扫描完
		cnt_hs <= 10'd0;
	else
		cnt_hs <= cnt_hs + 1'b1;
	
	always @(posedge clk or negedge rst_n)
	if(!rst_n)
		cnt_vs <= 10'd0;
	else if(cnt_vs == (vs_e - 1))//所有行扫描完
		cnt_vs <= 10'd0;
	else if(cnt_hs == (hs_e - 1))//所有列扫描完
		cnt_vs <= cnt_vs + 1'b1;//行计数器加1

//-------------------------------------------
	always @(posedge clk or negedge rst_n)
	if(!rst_n)
		vga_hs <= 1'b1;
	else if(cnt_hs == 1'b0)//列开始扫描
		vga_hs <= 1'b0;
	else if(cnt_hs == hs_a)//同步(a)
		vga_hs <= 1'b1;
	
	always @(posedge clk or negedge rst_n)
	if(!rst_n)
		vga_vs <= 1'b1;
	else if(cnt_vs == 1'b0)//行开始扫描
		vga_vs <= 1'b0;
	else if(cnt_vs == vs_a)//同步(a)
		vga_vs <= 1'b1;
	
	wire [10:0] en_1,en_2;
	//列有效区域
	assign en_1 = ( (cnt_hs >= hs_a + hs_b) && (cnt_hs <= hs_a + hs_b + hs_c) )?(cnt_hs - hs_a - hs_b):11'd0;
	//行有效区域
	assign en_2 = ( (cnt_vs >= vs_a + vs_b) && (cnt_vs <= vs_a + vs_b + vs_c) )?(cnt_vs - vs_a - vs_b):11'd0;
	//列,行有效区域
	assign en = (en_1>0 && en_2>0)?1'b1:1'b0;
	
endmodule

//vga颜色控制
module RGB(
				en,
				vga_r,
				vga_g,
				vga_b
				);
	input en;
	output [2:0]vga_r,vga_g;
	output [1:0]vga_b;//红,绿,蓝各三位
	
	assign vga_r = en?3'b111:3'b000;
	assign vga_g = 3'b000;
	assign vga_b = 2'b00;

endmodule

`timescale 1ns/1ns
`define clock_period 20

module VGA_top_tb;
	reg clk,rst_n;
	wire vga_hs,vga_vs;
	wire [2:0] vga_r,vga_g;
	wire [1:0] vga_b;
	
	VGA_top VGA_top(
					.clk(clk),
					.rst_n(rst_n),
					.vga_hs(vga_hs),
					.vga_vs(vga_vs),
					.vga_r(vga_r),
					.vga_g(vga_g),
					.vga_b(vga_b)
					);
					
	initial clk =1;
	always #(`clock_period/2) clk = ~clk;
	
	initial begin
		#1;//Difference clock edge
		rst_n = 1'b0;
		#(`clock_period*5) 
		rst_n = 1'b1;
		#(`clock_period);
		
		//#(`clock_period*200);
		//$stop;
		
	end
	

endmodule

 

RTL结构实现

2016-04-24_103301.jpg

仿真波形图

2016-04-23_223130.jpg

 

实验效果图:

2016-04-24_204642.jpg

vga输出一端口波形

2016-04-24_204712.jpg

附件为在网上找的VGA文档,介绍的比较全面!有兴趣的可以下载看看

"VGA驱动与Verilog实现"

vga

文章评论0条评论)

登录后参与讨论
我要评论
0
23
关闭 站长推荐上一条 /2 下一条