• fpga vga 显示


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

    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设置

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

     
  • 相关阅读:
    you must restart adb and eclipse的相关解决办法
    配有Tesla K40c的服务器新装Ubuntu16.04并安装CUDA8.0、Anaconda3、Matlab2016a、OPENCV3.1、CuDNN5.1、MXNet
    MXNet在64位Win7下的编译安装
    [Kinect]XBox One Kinect连接Windows
    64位Win7下编译Python3的计算机视觉库:OpenCV
    64位Win7下安装并配置Python3的深度学习库:Theano
    Noah的学习笔记之Python篇:命令行解析
    Noah的学习笔记之Python篇:函数“可变长参数”
    Noah的学习笔记之Python篇:装饰器
    linux下安装MySQL5.6记录
  • 原文地址:https://www.cnblogs.com/fcfc940503/p/10872409.html
Copyright © 2020-2023  润新知