基于STEP FPGA的8色VGA功能驱动

 行业动态     |      2023-12-04 13:54:56    |      作者

硬件说明

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

VGA接口引脚定义如下:

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

  • 红绿蓝三色信号(RGB)
  • 行场同步信号(HSVS)
  • 以及很多的地屏蔽;

三色信号都是模拟信号,行场同步信号都是数字信号;对于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代码

//-------------------------------------------------------------------- //>>>>>>>>>>>>>>>>>>>>>>>>>COPYRIGHTNOTICE<<<<<<<<<<<<<<<<<<<<<<<<< //-------------------------------------------------------------------- //Module:Param_define // //Author:Step // //Description:Param_define // //-------------------------------------------------------------------- //CodeRevisionHistory: //-------------------------------------------------------------------- //Version:|Mod.Date:|ChangesMade: //V1.1|2016/10/30|Initialver //-------------------------------------------------------------------- `timescale1ns/1ns //VGA显示器驱动只需要5个信号即可(行同步、场同步、红色、绿色、蓝色信号) //红绿蓝三色信号为模拟信号,输入电压范围为0.0V~0.7V //VGA时序中行同步和场同步都分为四个阶段(同步脉冲、后廊、有效线数、前廊) //VGA显示有很多模式,每种模式都是有固定的时钟和时序参数,需要根据要求控制 `ifdefVGA_800X600_60Hz //不同VGA显示模式相应的参数 //--------------------------------------------------------------------------- //--Horizonaltiminginformation`defineHSYNC_A16'd128 //128`defineHSYNC_B16'd216 //128+88 `defineHSYNC_C16'd1016 //128+88+800`defineHSYNC_D16'd1056 //128+88+800+40 //行同步脉冲+后廊+有效线数+前廊 //--Verticaltiminginformation`defineVSYNC_O16'd4 //4`defineVSYNC_P16'd27 //4+23`defineVSYNC_Q16'd627 //4+23+600`defineVSYNC_R16'd628 //4+23+600+1//场同步脉冲+后廊+有效线数+前廊 //--------------------------------------------------------------------------- `endif`ifdefVGA_640X480_85Hz //不同VGA显示模式相应的参数 //--------------------------------------------------------------------------- //--Horizonaltiminginformation`defineHSYNC_A16'd48 //48`defineHSYNC_B16'd160 //48+112`defineHSYNC_C16'd800 //48+112+640`defineHSYNC_D16'd832 //48+112+640+32 //行同步脉冲+后廊+有效线数+前廊 //--Verticaltiminginformation`defineVSYNC_O16'd3 //3`defineVSYNC_P16'd28 //3+25`defineVSYNC_Q16'd508 //3+25+480`defineVSYNC_R16'd509 //3+25+480+1 //场同步脉冲+后廊+有效线数+前廊 //--------------------------------------------------------------------------- `endif

//-------------------------------------------------------------------- //>>>>>>>>>>>>>>>>>>>>>>>>>COPYRIGHTNOTICE<<<<<<<<<<<<<<<<<<<<<<<<< //-------------------------------------------------------------------- //Module:Vga_Module // //Author:Step // //Description:Vga_Module // //-------------------------------------------------------------------- //CodeRevisionHistory: //-------------------------------------------------------------------- //Version:|Mod.Date:|ChangesMade: //V1.1|2016/10/30|Initialver //-------------------------------------------------------------------- `define VGA_800X600_60Hz //定义使用的VGA显示模式 `ifdef VGA_800X600_60Hz //根据VGA显示模式的定义调用相应的参数 `include "Param_define.v" //调用Param_define.v文件中的全局定义 `endif moduleVga_Module ( input clk_in, //40MHz系统时钟 input rst_n_in, //系统复位,低有效 output reg sync_v, //VGA场同步sync_v output reg sync_h, //VGA行同步sync_h outputreg [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@(posedgeclk_inornegedgerst_n_in) if(!rst_n_in)x_cnt<=16'd0; //复位时初始值 elseif(x_cnt>=`HSYNC_D)x_cnt<=16'd0; //一次行扫描需要1056个时钟(128+88+800+40) elsex_cnt<=x_cnt+1'b1;//对行扫描计数标识VGA一次场扫描需要的时间 always@(posedgeclk_inornegedgerst_n_in) if(!rst_n_in)y_cnt<=16'd0; //复位时初始值 elseif(x_cnt==`HSYNC_D)begin //每次行扫描时 if(y_cnt>=`VSYNC_R)y_cnt<=16'd0; //每次场扫描包含628次行扫描 elsey_cnt<=y_cnt+1'b1; endelsey_cnt<=y_cnt; //在每次行扫描过程中场扫描计数器保持不变 //按照显示模式的参数产生行同步扫描的脉冲 always@(posedgeclk_inornegedgerst_n_in) if(!rst_n_in)sync_h<=1'b1; elseif(x_cnt<`HSYNC_A)sync_h<=1'b0; elsesync_h<=1'b1; //按照显示模式的参数产生场同步扫描的脉冲 always@(posedgeclk_inornegedgerst_n_in) if(!rst_n_in)sync_v<=1'b1; elseif(y_cnt<`VSYNC_O)sync_v<=1'b0; elsesync_v<=1'b1; //根据行场同步信号的有效线数确定有效显示区域 always@(posedgeclk_inornegedgerst_n_in) if(!rst_n_in) vga_valid<=1'b0; elseif((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@(posedgeclk_inornegedgerst_n_in)begin if(!rst_n_in)vga_data=3'b111; elseif(vga_valid)begin //在有效显示区域内 if((x_cnt>`HSYNC_B)&&(x_cnt<=`HSYNC_B+10'd100)) vga_data=3'b100; //红色 elseif((x_cnt>`HSYNC_B+10'd100)&&(x_cnt<=`HSYNC_B+10'd200)) vga_data=3'b010; //绿色 elseif((x_cnt>`HSYNC_B+10'd200)&&(x_cnt<=`HSYNC_B+10'd300)) vga_data=3'b001; //蓝色 elseif((x_cnt>`HSYNC_B+10'd300)&&(x_cnt<=`HSYNC_B+10'd400)) vga_data=3'b110; //黄色 elseif((x_cnt>`HSYNC_B+10'd400)&&(x_cnt<=`HSYNC_B+10'd500)) vga_data=3'b101; //紫色 elseif((x_cnt>`HSYNC_B+10'd500)&&(x_cnt<=`HSYNC_B+10'd600)) vga_data=3'b011; //青色 elseif((x_cnt>`HSYNC_B+10'd600)&&(x_cnt<=`HSYNC_B+10'd700)) vga_data=3'b111; //白色 elseif((x_cnt>`HSYNC_B+10'd700)&&(x_cnt<=`HSYNC_B+10'd800)) vga_data=3'b000; //黑色 else vga_data=3'b111; //白色 endelse vga_data=3'b111; //白色endendmodule


小结

本节主要为大家讲解了VGA显示的原理、时序及软件设计,需要大家掌握的同时自己创建工程,通过整个设计流程,生成FPGA配置文件加载测试。