本节将和大家一起使用FPGA驱动底板上的8色VGA接口实现8色彩条显示功能。


硬件说明

VGA(video graphics array)即视频图形阵列,是IBM在1987年随PS/2一起推出的使用模拟信号的一种视频传输标准。VGA接口分公口和母口,如下图:

VGA接口引脚定义如下:

一个标准的VGA接口应该有以下端口:

  • 红绿蓝三色信号(R\G\B)
  • 行场同步信号(HS\VS)
  • 以及很多的地屏蔽;

三色信号都是模拟信号,行场同步信号都是数字信号;
对于VGA的接口模拟电压,为0~0.714V,0代表无色,0.714代表满色,FPGA输出3.3V,所以还必须要经过DAC的转换。现今有两种比较成熟的方法:电阻分压方式和DAC转换方式。
我们的底板上就是采用的电阻分压的方式,因VGA显示器端有75欧的下拉电阻,为了得到0.714V的电压我们给RGB信号线上串入270欧的电阻,3.3V*75/(270+75)=0.717V。如下

VGA驱动显示器用的是扫描的方式,逐行扫描the HS (Horizontal Synchronization)逐行扫描是扫描从屏幕的左上角一点开始,由左向右逐点扫描,每扫描完一行,电子束回到屏幕的左边下一行的起始位置,在这期间CRT(阴极射线显像管)对电子束进行消隐,每行结束时,用行同步信号进行同步;当扫描完所有行之后形成一帧,用场同步信号进行同步,并使扫描回到屏幕左上方,同时进行场消隐,开始下一帧。VGA一直在扫描,每一场的扫描包括了若干行扫描,依次循环;
VGA显示时序如下:
VGA显示区域和消隐区域:
常见的VGA显示模式:


Verilog代码

// --------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// --------------------------------------------------------------------
// Module: Param_define
// 
// Author: Step
// 
// Description: Param_define
// 
// Web: www.stepfpga.com
//
// --------------------------------------------------------------------
// Code Revision History :
// --------------------------------------------------------------------
// Version: |Mod. Date:   |Changes Made:
// V1.1     |2016/10/30   |Initial ver
// --------------------------------------------------------------------
`timescale 1ns / 1ns
 
//VGA显示器驱动只需要5个信号即可(行同步、场同步、红色、绿色、蓝色信号)
//红绿蓝三色信号为模拟信号,输入电压范围为0.0V~0.7V
//VGA时序中行同步和场同步都分为四个阶段(同步脉冲、后廊、有效线数、前廊)
//VGA显示有很多模式,每种模式都是有固定的时钟和时序参数,需要根据要求控制
 
`ifdef VGA_800X600_60Hz	//不同VGA显示模式相应的参数
//---------------------------------------------------------------------------
//-- Horizonal timing information
`define HSYNC_A   16'd128	// 128
`define HSYNC_B   16'd216	// 128 + 88	
`define HSYNC_C   16'd1016	// 128 + 88 + 800
`define HSYNC_D   16'd1056	// 128 + 88 + 800 + 40 //行同步脉冲+后廊+有效线数+前廊
//-- Vertical  timing information
`define VSYNC_O   16'd4		// 4 
`define VSYNC_P   16'd27	// 4 + 23
`define VSYNC_Q   16'd627	// 4 + 23 + 600
`define VSYNC_R   16'd628	// 4 + 23 + 600 + 1 //场同步脉冲+后廊+有效线数+前廊
//---------------------------------------------------------------------------
`endif
 
`ifdef VGA_640X480_85Hz	//不同VGA显示模式相应的参数
//---------------------------------------------------------------------------
//-- Horizonal timing information
`define HSYNC_A   16'd48	// 48
`define HSYNC_B   16'd160	// 48 + 112
`define HSYNC_C   16'd800	// 48 + 112 + 640
`define HSYNC_D   16'd832	// 48 + 112 + 640 + 32 //行同步脉冲+后廊+有效线数+前廊
//-- Vertical  timing information
`define VSYNC_O   16'd3		// 3 
`define VSYNC_P   16'd28	// 3 + 25
`define VSYNC_Q   16'd508	// 3 + 25 + 480
`define VSYNC_R   16'd509	// 3 + 25 + 480 + 1 //场同步脉冲+后廊+有效线数+前廊
//---------------------------------------------------------------------------
`endif
// --------------------------------------------------------------------
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
// --------------------------------------------------------------------
// Module: Vga_Module
// 
// Author: Step
// 
// Description: Vga_Module
// 
// Web: www.stepfpga.com
//
// --------------------------------------------------------------------
// Code Revision History :
// --------------------------------------------------------------------
// Version: |Mod. Date:   |Changes Made:
// V1.1     |2016/10/30   |Initial ver
// --------------------------------------------------------------------
`define		VGA_800X600_60Hz	//定义使用的VGA显示模式
 
`ifdef		VGA_800X600_60Hz	//根据VGA显示模式的定义调用相应的参数
`include	"Param_define.v"	//调用Param_define.v文件中的全局定义
`endif	
 
module Vga_Module
(
input 					clk_in,				//40MHz系统时钟
input 					rst_n_in,			//系统复位,低有效
output 	reg				sync_v,				//VGA场同步sync_v
output 	reg				sync_h,				//VGA行同步sync_h
output  reg		[2:0]	vga_data			//VGA数据MSB~LSB = {R,G,B}
);
 
reg 			[15:0] 	x_cnt;
reg 			[15:0] 	y_cnt;
reg 					vga_valid;	
 
//对时钟计数标识VGA一次行扫描需要的时间
always @ (posedge clk_in or negedge rst_n_in)
	if(!rst_n_in) x_cnt <= 16'd0;	//复位时初始值
	else if(x_cnt >= `HSYNC_D) x_cnt <= 16'd0;	//一次行扫描需要1056个时钟(128+88+800+40)
	else x_cnt <= x_cnt + 1'b1;
 
//对行扫描计数标识VGA一次场扫描需要的时间
always @ (posedge clk_in or negedge rst_n_in)
	if(!rst_n_in) y_cnt <= 16'd0;	//复位时初始值
	else if(x_cnt == `HSYNC_D) begin	//每次行扫描时
		if(y_cnt >= `VSYNC_R) y_cnt <= 16'd0;	//每次场扫描包含628次行扫描
		else y_cnt <= y_cnt + 1'b1;
	end else y_cnt <= y_cnt;	//在每次行扫描过程中场扫描计数器保持不变
 
//按照显示模式的参数产生行同步扫描的脉冲
always @ (posedge clk_in or negedge rst_n_in)
	if(!rst_n_in) sync_h <= 1'b1;
	else if(x_cnt < `HSYNC_A) sync_h <= 1'b0;	
	else sync_h <= 1'b1;	
 
//按照显示模式的参数产生场同步扫描的脉冲
always @ (posedge clk_in or negedge rst_n_in)
	if(!rst_n_in) sync_v <= 1'b1;
	else if(y_cnt < `VSYNC_O) sync_v <= 1'b0;
	else sync_v <= 1'b1;	
 
//根据行场同步信号的有效线数确定有效显示区域
always @ (posedge clk_in or negedge rst_n_in)
	if(!rst_n_in) 
		vga_valid <= 1'b0;
	else if((x_cnt > `HSYNC_B) && (x_cnt <`HSYNC_C) && (y_cnt > `VSYNC_P) && (y_cnt < `VSYNC_Q))
		vga_valid <= 1'b1; //有效显示区域中vga_valid标志为1
	else
		vga_valid <= 1'b0;	
 
//在VGA有效显示区域不同的段显示不同的颜色
always @ (posedge clk_in or negedge rst_n_in)
begin
	if(!rst_n_in) vga_data = 3'b111;
	else if(vga_valid)begin	//在有效显示区域内
		if((x_cnt > `HSYNC_B) && (x_cnt <= `HSYNC_B + 10'd100))					
			vga_data = 3'b100;			//红色
		else if((x_cnt > `HSYNC_B + 10'd100) && (x_cnt <= `HSYNC_B + 10'd200))	
			vga_data = 3'b010;			//绿色
		else if((x_cnt > `HSYNC_B + 10'd200) && (x_cnt <= `HSYNC_B + 10'd300))	
			vga_data = 3'b001;			//蓝色
		else if((x_cnt > `HSYNC_B + 10'd300) && (x_cnt <= `HSYNC_B + 10'd400))	
			vga_data = 3'b110;			//黄色
		else if((x_cnt > `HSYNC_B + 10'd400) && (x_cnt <= `HSYNC_B + 10'd500))	
			vga_data = 3'b101;			//紫色
		else if((x_cnt > `HSYNC_B + 10'd500) && (x_cnt <= `HSYNC_B + 10'd600))	
			vga_data = 3'b011;			//青色
		else if((x_cnt > `HSYNC_B + 10'd600) && (x_cnt <= `HSYNC_B + 10'd700))	
			vga_data = 3'b111;			//白色
		else if((x_cnt > `HSYNC_B + 10'd700) && (x_cnt <= `HSYNC_B + 10'd800))	
			vga_data = 3'b000;			//黑色
		else
			vga_data = 3'b111;			//白色
	end else
		vga_data = 3'b111;				//白色
end
 
endmodule

小结

本节主要为大家讲解了VGA显示的原理、时序及软件设计,需要大家掌握的同时自己创建工程,通过整个设计流程,生成FPGA配置文件加载测试。
如果你对Diamond软件的使用不了解,请参考这里:Diamond的使用


相关资料

使用STEP-MXO2第二代的VGA显示驱动程序: 后续会有下载连接 待更新
使用STEP-MAX10的VGA显示驱动程序: 后续会有下载连接 待更新