### 基于STEP FPGA的8色VGA功能驱动
本节将和大家一起使用FPGA驱动底板上的8色VGA接口实现8色彩条显示功能。
---
#### 硬件说明
VGA(video graphics array)即视频图形阵列,是IBM在1987年随PS/2一起推出的使用模拟信号的一种视频传输标准。VGA接口分公口和母口,如下图:
\\
{{ :vga接口.jpg?400 |}}
\\
VGA接口引脚定义如下:
\\
{{ :vga接口定义.jpg?800 |}}
\\
一个标准的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接口电路.png?800 |}}
\\
VGA驱动显示器用的是扫描的方式,逐行扫描the HS (Horizontal Synchronization)逐行扫描是扫描从屏幕的左上角一点开始,由左向右逐点扫描,每扫描完一行,电子束回到屏幕的左边下一行的起始位置,在这期间CRT(阴极射线显像管)对电子束进行消隐,每行结束时,用行同步信号进行同步;当扫描完所有行之后形成一帧,用场同步信号进行同步,并使扫描回到屏幕左上方,同时进行场消隐,开始下一帧。VGA一直在扫描,每一场的扫描包括了若干行扫描,依次循环;
\\
VGA显示时序如下:
{{ :vga时序.png?800 |}}
\\
VGA显示区域和消隐区域:
{{ :vga显示区域.png?800 |}}
\\
常见的VGA显示模式:
{{ :常见的vga显示模式.png?800 |}}
---
#### 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软件的使用不了解,请参考这里:[[lattice_diamond的使用|Diamond的使用]]。
---
#### 相关资料
使用[[STEP-MXO2第二代]]的VGA显示驱动程序: 后续会有下载连接 待更新
\\
使用[[STEP-MAX10]]的VGA显示驱动程序: 后续会有下载连接 待更新
\\