FPGA--VGA驱动

发布时间:2024年01月21日

一.VGA显示原理

1.VGA的显示不是直接让图像在屏幕上显示出来,而是通过扫描的方式,将构成图像的像素点,在行场同步时序信号的控制下,按照从上到下,从左到右的顺序显示在屏幕上,其具体的流程可表示为如下的步骤”

1.在行场同步的作用下,扫描坐标定位到坐上角的第一个像素点坐标;

2.自左上角第一个像素坐标,向右逐个像素点进行扫描;

3.扫描到第一行最后一个数据,一行图像扫描完成吗,进行图像的消隐,之后开始第二行的第一个像素坐标自左向右的扫描;

4.重复若干次之后到最后一行的行尾,一帧图像扫描完成,进行消隐,之后跳到第一行,再次进行。

框图:(这一部分参考的野火教程,侵权就删)只用于自我学习的笔记加总结。
在这里插入图片描述

二.VGA时序

在这里插入图片描述

2.1 行场同步时序图

在这里插入图片描述
注:这里的行场时序一样,所以用一个图来表示

三.verilog代码实现

功能:驱动七寸800*480的lcd屏幕并显示彩条

3.1框图

在这里插入图片描述

3.2时序图

在这里插入图片描述

3.3verilog代码实现

module vga_ctrl(
    input wire          pexil_clk    ,
    input wire          sys_rst      ,
    input wire [15:0]   pexil_data   ,

    output wire         Hsync        ,
    output wire         Vsync        ,
    output wire [9:0]   pexil_x      ,
    output wire [9:0]   pexil_y      ,
    output wire [15:0]  rgb_data    
);

reg [9:0] Cnt_H         ;
reg [9:0] Cnt_V         ;
wire      rgb_valid     ;
wire      pexil_data_req;

/****************************************************************************
#参数定义:@行信号参数定义
			@场信号参数定义
			@数据信号的定义
*****************************************************************************/

parameter  H_SYNC  = 10'd96,
            H_BACK  = 10'd40,
            H_LEFT  =  10'd8,
            H_VALID =  10'd640,
            H_RIGHT =   10'd8,
            H_FRONT =   10'd8,
            H_TOTAL =  H_SYNC + H_BACK + H_LEFT + H_VALID + H_RIGHT + H_FRONT;
                       
parameter  V_SYNC  =  10'd2,
            V_BACK  =  10'd25,
            V_UP    =   10'd8,
            V_VALID = 10'd480, 
            V_DOWN  =  10'd8,
            V_FRONT =   10'd2,
            V_TOTAL = V_SYNC + V_BACK + V_UP + V_VALID + V_DOWN + V_FRONT;

parameter  WHITE      =    16'hffff      ,
			BLACK      =    16'h0000      ,
			RED        =    16'hf800      ,
			GREEN      =    16'h07E0      ,
			BLUE       =    16'h001f      ;          
/************************************************
#模块说明:行信号计数器,用于表示行信号的周期循环
           在时钟的上升沿加一,用于计数行信号。
           单位:像素

************************************************/
always @(posedge pexil_clk or negedge sys_rst) begin
    if(!sys_rst)
        Cnt_H <= 10'b0;
    else if(Cnt_H == H_TOTAL - 10'd1 )
        Cnt_H <= 10'b0;
    else    
        Cnt_H <= Cnt_H + 10'd1;
end
/************************************************
#模块说明:场信号计数器,用于表示场信号的周期循环
            在时钟的上升沿加一,用于计数场信号。
            单位:行

************************************************/
always @(posedge pexil_clk or negedge sys_rst) begin
    if(!sys_rst)
        Cnt_V <= 10'b0;
    else if((Cnt_V == V_TOTAL - 10'd1)&&(Cnt_H == H_TOTAL - 10'd1))
        Cnt_V <= 10'b0;
    else  if(Cnt_H == H_TOTAL - 10'd1)  
        Cnt_V <= Cnt_V + 10'd1;
    else 
        Cnt_V <= Cnt_V;
end


// 数据显示有效标志位:当Cnt_H范围在[同步信号+后沿+左边框,同步信号+后沿+左边框+显示的有效区域)
                //       Cnt_V范围在[同步信号+后沿+上边框,同步信号+后沿+左边框+显示的有效区域)时,该信号拉高
assign rgb_valid = ((Cnt_H >= H_SYNC + H_BACK + H_LEFT)
                        &&(Cnt_H < H_SYNC + H_BACK + H_LEFT + H_VALID )
                            &&(Cnt_V >= V_SYNC +V_BACK +V_UP)
                                &&(Cnt_V < V_SYNC +V_BACK +V_UP + V_VALID)) 
                                ? 1'b1 :1'b0 ;

// 数据显示请求有效标志位:当Cnt_H范围在[同步信号+后沿+左边框-1,同步信号+后沿+左边框+显示的有效区域-1)
                //              Cnt_V范围在[同步信号+后沿+上边框,同步信号+后沿+左边框+显示的有效区域)时,该信号拉高,
                        //            以达到提前一个时钟周期的效果
assign pexil_data_req = ((Cnt_H >= H_SYNC + H_BACK + H_LEFT - 1'b1)
                        &&(Cnt_H < H_SYNC + H_BACK + H_LEFT + H_VALID - 1'b1 )
                            &&(Cnt_V >= V_SYNC +V_BACK +V_UP)
                                &&(Cnt_V < V_SYNC +V_BACK +V_UP + V_VALID)) 
                                ? 1'b1 :1'b0 ;

// 有效显示区域坐标
assign pexil_x =  (pexil_data_req==1'b1) ? (Cnt_H - (H_SYNC + H_BACK + H_LEFT - 1'b1 )):10'd0;
assign pexil_y =   (pexil_data_req==1'b1) ? (Cnt_V - (V_SYNC + V_BACK + V_UP)  ):10'd0;


//同步信号拉高
assign  Hsync = (Cnt_H <= H_SYNC - 10'd1) ? 1'b1:1'b0;

assign  Vsync = (Cnt_V <= V_SYNC - 10'd1) ? 1'b1:1'b0;



assign rgb_data  =   (rgb_valid == 1'b1) ? pexil_data:16'h0000;

/************************************************
//下面是数据生成模块

always @(posedge pexil_clk or negedge sys_rst) begin 
    if(!sys_rst)
       pexil_data <=BLACK;
    else if((pexil_x >= 10'd0) && (pexil_x < (H_VALID /5)))
        pexil_data <= WHITE;
    else if((pexil_x >= (H_VALID /5)) && (pexil_x < (H_VALID /5)*2))
        pexil_data <= BLACK;
    else if((pexil_x >= (H_VALID /5)*2) && (pexil_x < (H_VALID /5)*3))
        pexil_data <= RED;
    else if((pexil_x >= (H_VALID /5)*3) && (pexil_x < (H_VALID /5)*4))
        pexil_data <= GREEN;
    else if((pexil_x >= (H_VALID /5)*4) && (pexil_x < H_VALID))
        pexil_data <= BLUE;
    else 
    	pexil_data <= BLACK;
end
***/







endmodule 

注:最后的数据生成模块意思是,可以在此模块中直接生成,而不需要外部的数据输入,当然代码也要进行相关的修改。

文章来源:https://blog.csdn.net/qq_52245062/article/details/135721173
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。