基于STEP FPGA的8色VGA功能驱动
本节将和大家一起使用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显示驱动程序: 后续会有下载连接 待更新