VGA(Video Graphics Array)是IBM在1987年随PS/2机一起推出的一种视频传输标准,具有分辨率高、显示速率快、颜色丰富等优点,在彩色显示器领域得到了广泛的应用。不支持热插拔,不支持音频传输。fpga vga 显示

fpga vga 显示

VGA接口

fpga vga 显示

行同步时序

fpga vga 显示

场同步时序

fpga vga 显示

分辨率

fpga vga 显示

 

硬件简介

fpga vga 显示

fpga vga 显示

 

 

   VGA接口信号HS(1bit),VS(1 bit), R(8bit), G(8bit), B(1bit)。VGA显示器常用的分辨率为640x480,即操作的时候FPGA想办法向VGA显示器输出640行480列个点位数据(共307200个数据)。那具体是如何操作的呢?
基本操作流程:VS叫场扫描信号或者帧扫描信号,首先VS发一个负脉冲,告诉显示器我要开始发送一副图片了,你准备接收。然后,HS行扫描信号,发一个负脉冲,告诉显示器我要开始发送第一行数据了,准备接受。跟在HS负脉冲信号后,接着就每个一个时钟周期发送一组R,G,B点位的数据,一直发送640组。接下来HS再发一个负脉冲,告诉显示器我要开始发送第二行数据了,准备接收,然后发送第2行的640组R,G,B数据,以此类推,第3行,第4行。一直发送到第480行结束后,所有307200个数据就发送完全了。然后VS信号再发一个负脉冲,发第二幅图片的信息。以此类推。

 

具体时序数据:下图就对应了具体行扫描和场扫描阶段每个操作具体所需要的周期数。一目了然。注意HS,VS负脉冲后要等待几个周期才正式发送数据这是为了满足VGA的器件要求而定的。下图给了周期数,然后计算VGA的时钟频率。一般VGA显示器的刷新频率为60帧/s,每一秒显示60幅图片,即一帧数据需要1/60s发送。由下图可知,完整发送一帧数据(一副图片)需要800*525=420000个周期。则VGA时钟频率为420000/(1/60)=25.2MHZ。近似等于25MHZ。开发板上的主频时钟为50MHZ,所以只要二分频就OK啦。
代码如下:
module vga( 
		output      [7:0]  VGA_B,
      output             VGA_BLANK_N,
      output             VGA_CLK,
      output      [7:0]  VGA_G,
      output             VGA_HS,
      output      [7:0]  VGA_R,
      output             VGA_SYNC_N,
      output             VGA_VS,
		input              CLOCK_50,
		input              KEY
		
 );
 
 wire[8:0] q;
rom2     rom_inst (
       .address( address ),
       .clock( CLOCK_50 ),
       .rden( ~rdn ),
       .q ( q )
       );


assign VGA_BLANK_N=~rdn;
wire[23:0]datain={q[8:6],5'd0,q[5:3],5'd0,q[2:0],5'd0};
wire[18:0]rd_a;
wire[18:0]address=(rd_a[18:10]*640)+rd_a[9:0];
wire rdn;
wire vga_clk;
assign VGA_CLK=vga_clk;
vga_c u0(
.clk(CLOCK_50),//50MHZ
.clrn(KEY),
.datain(datain),
.h_count(),
.v_count(),
.vga_clk(vga_clk),
.rdn(rdn), //read enable"0"active
.rd_a(rd_a),//read_address={row(9),col(10bit)}
.hs(VGA_HS),
.vs(VGA_VS),
.r(VGA_R),
.g(VGA_G),
.b(VGA_B));
endmodule

  

`timescale 1ns/1ns
module vga_c(
input clk,                                    // 系统时钟50MHZ
input clrn,                                  //复位信号
input [23:0]datain,                       //输入R,G,B数据24bit
output rdn,                                 //读使能信号,低电平有效。
output [18:0]rd_a,                       //读地址,read_address={row(9),col(10bit)}
output reg[9:0]h_count=10'd0,      //列计数器 0-799
output reg[9:0]v_count=10'd0,     //行计数器  0-524
output reg vga_clk=1'b0,           //vga时钟 25MHZ  
//VGA接口信号
output hs,                                        //行扫描信号
output vs,                                          //场扫描信号
output [7:0]r,g,b                          //R,G,B输出信号
);

//refreshrate=25*10^6/((96+48+640+16)*(480+2+33+10))=59.5=60

//1.VGA时钟生成,vga_clk:25MHZ   
always @( negedge clrn or posedge clk  )
vga_clk<=(!clrn)?1'b0: ~vga_clk;

//2.计数器v_count(0-524) and h_count(0-799)
always @( negedge clrn or posedge vga_clk  )
     if(!clrn) begin v_count<=10'd0;
                      h_count<=10'd0;
                end
         else if(v_count==10'd524)
          v_count<=10'd0;
         else
         begin
         if(h_count==10'd799)
                begin h_count<=10'd0;      
                     v_count<=v_count+1'b1;
                     end
         else
                h_count<=h_count+1'b1;   
         end


// 3.锁存输入数据data_in,rdn=0时,外部有存储器有40ns的时间提供datain数据
reg video_out=1'b0;
reg [23:0]data_reg=24'd0;

always @(negedge clrn or posedge vga_clk)
              if(!clrn)
                            begin video_out<=1'b0;
                                     data_reg<=24'd0;
                                     end
              else
                            begin video_out<=~rdn; 
                                     data_reg<=datain;
                                     end


//4.接口信号生成   
assign hs=(h_count>=96);               //HS波形输出
assign vs=(v_count>=2);               //VS波形输出
wire [9:0]rol=v_count-10'd35;        //计算行地址
wire [9:0]col =h_count-10'd143;     //计算列地址
assign rd_a={rol[8:0],col[9:0]};    //行列地址拼接成一个rd_a
assign rdn=~(((h_count>=10'd143)&&(h_count<10'd783))&&((v_count>=10'd35)&&(v_count<10'd515)));                                            //只有在有效的数据位rdn才置0
assign r=(video_out)?data_reg[23:16]:8'd0;
assign g=(video_out)?data_reg[15:8]:8'd0;
assign b=(video_out)?data_reg[7:0]:8'd0;

endmodule

rom ip设置

fpga vga 显示

fpga vga 显示

 

图片数据mif文件生成:可以使用工具或MATLAB

 fpga vga 显示

相关文章: