VGA图像显示总结(彩条显示、方块移动、字符显示、基于ROM的图片显示)

VGA显示器成像原理

           

        图像显示的时候,是采用逐行扫描的方式,从左到右,从上到下,每次扫描一个点的时候发送一个数据,然后那个像素点就会把这个数据对应的颜色发送到屏幕上,在每一次回扫的过程中,不能影响屏幕上既有图像的颜色,所以就是消隐信号(BLK)存在的意义,在每次回扫时,消隐信号启动,此时屏幕上没有新的数据输入,也就不会影响原本的颜色,消隐分为场扫描和行扫描。

VGA时序    

 行扫描:根据上图进行分析,首先需要一个行同步信号,根据这个行同步信号用来指导消隐信号的变化,以及数据的传输,行同步信号(HSYC)的一个周期包含的时间有行同步时间(Sync Pulse)、Back Porch(回扫时间)、Left Border(显示器左侧黑边的扫描的时间)、Visible area(数据传输的有效时间)、Right Border(显示器右侧黑边的扫描的时间)、Front Porch(产生消隐信号用的时间)

 场扫描:根据上图进行分析,首先需要一个场同步信号,根据这个场同步信号用来指导消隐信号的变化,以及数据的传输,场同步信号(VSYC)的一个周期包含的时间有场同步时间(Sync Pulse)、Back Porch(回扫时间)、Left Border(显示器左侧黑边的扫描的时间)、Visible area(数据传输的有效时间)、Right Border(显示器右侧黑边的扫描的时间)、Front Porch(产生消隐信号用的时间)

行扫描和场扫描类似,相关点在于每次扫描一行,场即竖直方向上扫描一个点,所以说场扫描时的那个时间其实根据行扫描来变化的。

根据时序来看,其实也就只有在Visible area这个区域是有效的数据传输时间,其他位置数据都不传输,可以直接让消隐信号启动,不输入数据就完事了。

然后对模块的端口分析一下

VGA_HS:就是行同步信号,根据上面所述的时间周期来控制VGA_HS的变化

VGA_VS:就是场同步信号,根据上面所述的时间周期来控制VGA_VS的变化

R/G/B:就是输入的数据(在数据传输的有效时间输入)

CLOCK:VGA模块的驱动时钟,根据不同的像素和刷新频率而不同,具体为多少要查询相关手册

VGA_BLK:消隐信号、根据上面所述的时间周期来控制VGA_HS的变化

上面所述的时间具体为多少呢?也是根据不同的像素而不同,具体为多少要查询相关手册

一、GM7123芯片

在VGA图像显示时,采用的是GM7123芯片

 在驱动GM7123时有多种数据传输方式

 

 

 

 

 我采用的是RGB888格式的数据传输。

下面就是VGA驱动模块的程序部分啦,我采用的是1920*1080像素的显示模式,根据下图中参数进行编写

当0时刻时 ,行同步信号为下降沿开始,当44时,行同步信号拉高,当44(行同步信号脉冲时间)+148(H_Back_Porch)+0(H_Left_Border)=192是开始发送有效数据,当192+1920(有效数据时间)=2112时有效数据发送完成,2112+0(H_Right_Borde)+88(H_Front_Porch)=2200时,一个周期结束。只有在有效数据发送时,才不会启动消隐信号,其余时间不发送数据,可以让消隐信号始终有效。

场同步信号和行同步信号类似,但是要注意,只有扫描完一行时,场同步信号才会+1。


module VGA_CTRL(
    clk,
    Rst_n,
    data_in,
    
    Hcounter,
    Vcounter,
    VGA_HS,
    VGA_VS,
    VGA_BLK,
    VGA_RGB  
    ); 
    
    input clk;
    input Rst_n;
    input [23:0] data_in;
    
    output  [11:0] Hcounter;
    output  [10:0] Vcounter;
    output reg VGA_HS;
    output reg VGA_VS;
    output reg VGA_BLK;
    output [23:0] VGA_RGB;  
    
    reg [11:0] Hcnt;
    reg [10:0] Vcnt;
    
    parameter HS_End      = 44;
    parameter VS_End      = 5;
    parameter Hdata_Begin = 192;
    parameter Vdata_Begin = 41;
    parameter Hdata_End   = 2112;
    parameter Vdata_End   = 1121;    
    parameter Hsync_End   = 2200;
    parameter Vsync_End   = 1125;
    
    //行扫描计数器
    always @ (posedge clk or negedge Rst_n)
        if(!Rst_n)
            Hcnt<=12'd0;
        else if (Hcnt == Hsync_End - 1)
            Hcnt<=12'd0;
        else Hcnt<=Hcnt+1'b1;
     
  //场扫描计数器   
     always @ (posedge clk or negedge Rst_n)
        if(!Rst_n)
            Vcnt<=11'd0;
        else if(Hcnt == Hsync_End - 1)
        begin
            if (Vcnt == Vsync_End - 1)
                Vcnt<=11'd0;
            else Vcnt<=Vcnt+1'b1;
        end
        
    //行同步信号赋值    
    always @ (posedge clk or negedge Rst_n)
        if(!Rst_n) 
            VGA_HS<=1'b0;
        else if (Hcnt >= HS_End)
            VGA_HS<=1'b1;
        else   VGA_HS<=1'b0;

     //场同步信号赋值  
    always @ (posedge clk or negedge Rst_n)
        if(!Rst_n) 
            VGA_VS<=1'b0;
        else if (Vcnt >= VS_End)
            VGA_VS<=1'b1;
        else   VGA_VS<=1'b0;
     
  //消隐信号的赋值
    always @ (posedge clk or negedge Rst_n)
        if(!Rst_n) 
            VGA_BLK<=1'b0;
        else if(Hcnt > Hdata_Begin-1 && Hcnt<= Hdata_End-1 && Vcnt>Vdata_Begin-1 && Vcnt<=Vdata_End-1)
            VGA_BLK<=1'b1;
        else  VGA_BLK<=1'b0;
      
    //RGB赋值
           assign VGA_RGB=(VGA_BLK == 1'b1)?data_in:24'd0;
           
    //像素横坐标
           assign Hcounter=(VGA_BLK == 1'b1)? (Hcnt - 12'd192-1'b1): 12'd0;
    //像素纵坐标
           assign Vcounter=(VGA_BLK == 1'b1)? (Vcnt - 11'd41) : 11'd0;           
 endmodule 

注意这里的驱动模块多了两个端口,Hcounter和Vcounter引出这两个输出是为了方便根据有效数据时段的像素点赋值。

下面就是做的四个小小的简单小实验

彩条显示实验

彩条显示时将屏幕分成八等分,每一块显示不同的颜色

代码如下

module VGA_display(
    clk,
    Rst_n,
    
    VGA_Clk,
    VGA_HS,
    VGA_VS,
    VGA_BLK,
    VGA_RGB 
    );

    input clk;
    input Rst_n;
    
    output VGA_Clk;
    output  VGA_HS;
    output  VGA_VS;
    output  VGA_BLK;
    output [23:0] VGA_RGB;
    
    reg  [23:0] data_in;
    wire  [11:0] Hcounter;
    wire  [10:0] Vcounter;
    wire H0,H1,V0,V1,V2,V3;
    
  //颜色设置
  parameter BLACK   = 24'h000000, //黑色
            BLUE    = 24'h0000FF, //蓝色
            RED     = 24'hFF0000, //红色
            PURPPLE = 24'hFF00FF, //紫色
            GREEN   = 24'h00FF00, //绿色
            CYAN    = 24'h00FFFF, //青色
            YELLOW  = 24'hFFFF00, //黄色
            WHITE   = 24'hFFFFFF; //白色
            
  //像素块设置
    assign H0 =(Hcounter>= 12'd0 && Hcounter <= 12'd959)? 1'b1:1'b0;
    assign H1 =(Hcounter>= 12'd960 && Hcounter <= 12'd1919)? 1'b1:1'b0;
    assign V0 =(Vcounter>= 11'd0 && Vcounter <= 11'd269)? 1'b1:1'b0;    
    assign V1 =(Vcounter>= 11'd270 && Vcounter <= 11'd539)? 1'b1:1'b0;            
    assign V2 =(Vcounter>= 11'd540 && Vcounter <= 11'd809)? 1'b1:1'b0;            
    assign V3 =(Vcounter>= 11'd810 && Vcounter <= 11'd1079)? 1'b1:1'b0;
    
VGA_CLOCK VGA_CLOCK(
    .inclk0(clk),
    .c0(VGA_Clk)
);    
VGA_CTRL VGA_CTRL(
                    .clk(VGA_Clk),
                    .Rst_n(Rst_n),
                    .data_in(data_in),
                    
                    .Hcounter(Hcounter),
                    .Vcounter(Vcounter),
                    .VGA_HS(VGA_HS),
                    .VGA_VS(VGA_VS),
                    .VGA_BLK(VGA_BLK),
                    .VGA_RGB (VGA_RGB) 
); 
    always @ (*)
        case({H0,H1,V0,V1,V2,V3})
            6'b101000:data_in=BLACK;
            6'b100100:data_in=RED;
            6'b100010:data_in=GREEN;
            6'b100001:data_in=YELLOW;
            6'b011000:data_in=BLUE;
            6'b010100:data_in=PURPPLE;
            6'b010010:data_in=CYAN;
            6'b010001:data_in=WHITE;            
            default:data_in=BLACK;
        endcase 
  endmodule
     
  

方块移动实验

  • 2
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值