当前位置:   article > 正文

VGA接口时序以及FPGA实现

vga接口时序

开发平台:vivado 2020.1
芯片:xc7k410tffv900-2


一、引言

  VGA (Video Graphics Array)视频图形阵列是BM 于1987 年提出的一个使用模拟信号的电脑显示标准。VGA接口即电脑采用 VGA 标准输出数据的专用接口。VGA 接口共有15 针,分成3 排,每排5个孔,早期在显卡上应用最为广泛的接口类型。它传输红、绿、蓝模拟信号以及同步信号(水平和垂直信号)。如图所示:

在这里插入图片描述
每个管脚具体的作用如下:

  1. 红基色 red
  2. 绿基色 green
  3. 蓝基色 blue
  4. 地址码 ID Bit
  5. 自测试( 各家定义不同 )
  6. 红接地
  7. 绿接地
  8. 蓝接地
  9. 保留 ( 各家定义不同 )
  10. 数字接地
  11. 地址码
  12. 地址码
  13. 行同步
  14. 场同步
  15. 地址码

二、显示原理以及时序

  VGA 显示关键的是三个颜色,即红基色、绿基色和蓝基色,就是我们物理课上常说的三原色。
在这里插入图片描述

  VGA 的显示效果取决于RGB 三个分量的位数(即:色深),最高24位(即RGB各8位),16位(即R5位,G6位,B6位),12位(即RGB各4位) 。色深越高能显示的颜色就越多,显示图片越鲜艳,现在主流的手机和电脑显示器都是8bit色深和10bit色深。

RGB信号在使用时的位宽有三种常见格式,具体跟显示器的设置有关:
1.RGB332,即R: G: B = 3: 3: 2
2. RGB565,即R: G: B = 5: 6: 5
3. RGB888,即R: G: B = 8: 8: 8
(ps:本次显示器支持的是RGB888)

所以想要正确的显示图像,只需要在显示器每个像素点上给出正确的RGB数值,就能达到想要的显示效果。

  显示器能显示的原理是根据电子束扫描的方式:逐行扫描是扫描从屏幕左上角第一点开始,从左至右逐点扫描,每扫描完一行,电子束回到屏幕的左边下一行的起始位置,在这期间,CRT 对电子束进行消隐,每行结束时,用行同步信号进行同步;当扫描完所有的行,形成一帧,用场同步信号进行帧同步,并使扫描回到屏幕左上方,同时进行场消隐,开始下一帧。
在这里插入图片描述

  那么我要显示一个19201080的画面,那只需要扫描19201080次吗? 因为根据显示器扫描原理可知道,电子束每扫描一行或者一帧后,都需要时间进行消隐(我个人的理解就是电子束需要时间重置位置),所以实际上的扫描次数大于1920*1080次,时序图如下:
在这里插入图片描述

  • sync是同步信号长度,hsync为行同步信号,vsync就为场同步信号
  • backporch是后沿消隐长度
  • active video 就是实际的显示画面长度
  • front porch 是前沿消隐长度

  其中,vsync是由hsync组成:
在这里插入图片描述
  所以一幅图像在显示器真实的情况是这样:
在这里插入图片描述
  不同分辨率的不同参数不同,大致分辨率表如下:

显示模式时钟/Mhz行同步hsync行后沿行有效行前沿行总共场同步vsync场后沿场有效场前沿场总共
640×480@60Hz25.296486401680023348010525
800×600@60Hz40128888004010564236001628
1024×768@60Hz6513616010242413446297683806
1280×720@60Hz74.2540220128011016505207205750
1280×1024@60Hz1081122481280481688338102411066
1920×1080@60Hz148.5441481920882200536108041125
3840×2160@60Hz59488296384019644001072216082250

  时钟怎么算的呢?比如1920×1080@60hz的时钟=2200×1125×60=148.5M,其他的同理。

三、FPGA实现

  本次显示RGB888,1920×1080@60Hz的纯色绿画面,所以外部输入时钟为148.5M。

 //显示纯绿色图片
module vga_ctrl
(
    input                              clk ,    //输入148.5M时钟
		
    output  reg                        vs  ,	//输出vsync信号
    output  reg                        hs  ,	//输出hsynv信号
    output  reg     [23:0]             data 	//输出RGB数据,共24位  
    );
    
    parameter       hcnt_max=2200;	//行扫描计数器等于行同步+行前沿+行有效+场后沿
    parameter       vcnt_max=1125;	//列扫描计数器等于场同步+场前沿+场有效+场后沿

	parameter       H_SYNC_TIME     =44;	//行同步信号时间
	parameter       H_BACK_PORCH    =148;	//行消隐后沿时间
    parameter       H_ACTIVE        =1920; 	//行数据有效时间
    parameter       H_FRONT_PORCH   =88; 	//行前沿时间
   
	parameter       V_SYNC_TIME     =5; 	//场同步信号时间
	parameter       V_BACK_PORCH    =36;	//场后沿时间
    parameter       V_ACTIVE        =1080;	//场数据有效时间
    parameter       V_FRONT_PORCH   =4 ; 	//场前沿时间

	reg             [12:0]             hcnt ='d0    ;//行计数器
    reg             [12:0]             vcnt ='d0    ;//列计数器
    
	//对行扫描进行计数
	always @(posedge clk)begin
		if(hcnt == hcnt_max - 1 )
            hcnt <= 0;
		else
            hcnt <= hcnt +'d1;		
	end
	//对列扫描进行计数,每一行计数完成,vcnt+1
    always @(posedge clk)
		begin
			if((vcnt == vcnt_max-1)&&(hcnt == hcnt_max -1))
				vcnt <= 0;
			else if(hcnt == hcnt_max -1)
				vcnt <= vcnt +'d1;
			else
				vcnt <= vcnt;
		end
	
	//行同步信号
	always@(posedge clk)begin
		if(hcnt < H_SYNC_TIME)
			hs <= 1;
		else
			hs <= 0;
	end
	//场同步信号
	always@(posedge clk)begin
		if(vcnt < V_SYNC_TIME)
			vs <= 1;
		else
			vs <= 0;
	end	
//RGB有效信号
     always @(posedge clk) begin
        if((hcnt >= H_SYNC_TIME +H_BACK_PORCH)&&(hcnt < H_SYNC_TIME +H_BACK_PORCH +H_ACTIVE))
			if((vcnt >=V_SYNC_TIME + V_BACK_PORCH)&&(vcnt<V_SYNC_TIME+V_BACK_PORCH+V_ACTIVE))
				data <= {8'h10,8'hB6,8'h19};  //绿色的RGB分量分别是8'h10,8'hB6,8'h19
       		else
            	data <= {8'h80,8'h00,8'h00};  //其它消隐区显示黑色,RGB分量分别是8'h80,8'h00,8'h00
         else
            data <= {8'h80,8'h00,8'h00};  
        end
    end
		
endmodule 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71

显示效果:
在这里插入图片描述
再次修改一下程序,让屏幕中间显示一个100×100的绿色块,其它为黑色代码如下:

//显示100*100绿色方块
module vga_ctrl
(
    input                              clk ,    //输入148.5M时钟
		
    output  reg                        vs  ,	//输出vsync信号
    output  reg                        hs  ,	//输出hsynv信号
    output  reg     [23:0]             data 	//输出RGB数据,共24位  
    );

    parameter       hcnt_max=2200;	//行扫描计数器等于行同步+行前沿+行有效+场后沿
    parameter       vcnt_max=1125;	//列扫描计数器等于场同步+场前沿+场有效+场后沿

	parameter       H_SYNC_TIME     =44;	//行同步信号时间
	parameter       H_BACK_PORCH    =148;	//行消隐后沿时间
    parameter       H_ACTIVE        =1920; 	//行数据有效时间
    parameter       H_FRONT_PORCH   =88; 	//行前沿时间
   
	parameter       V_SYNC_TIME     =5; 	//场同步信号时间
	parameter       V_BACK_PORCH    =36;	//场后沿时间
    parameter       V_ACTIVE        =1080;	//场数据有效时间
    parameter       V_FRONT_PORCH   =4 ; 	//场前沿时间
    
 	reg             [12:0]             hcnt ='d0    ;	//行计数器
    reg             [12:0]             vcnt ='d0   	; 	//列计数器
    reg             [12:0]             pix_x='d0    ;	//显示区域的横坐标
    reg             [12:0]             pix_y='d0   	; 	//显示区域的纵坐标
    reg								   de			;	//数据有效使能
	
    
	//对行扫描进行计数
	always @(posedge clk)begin
		if(hcnt == hcnt_max - 1 )
            hcnt <= 0;
		else
            hcnt <= hcnt +'d1;		
	end
	//对列扫描进行计数,每一行计数完成,vcnt+1
    always @(posedge clk)
		begin
			if((vcnt == vcnt_max-1)&&(hcnt == hcnt_max -1))
				vcnt <= 0;
			else if(hcnt == hcnt_max -1)
				vcnt <= vcnt +'d1;
			else
				vcnt <= vcnt;
		end
	
	//行同步信号
	always@(posedge clk)begin
		if(hcnt < H_SYNC_TIME)
			hs <= 1;
		else
			hs <= 0;
	end
	//场同步信号
	always@(posedge clk)begin
		if(vcnt < V_SYNC_TIME)
			vs <= 1;
		else
			vs <= 0;
	end	
//RGB有效信号
     always @(posedge clk) begin
        if((hcnt >= H_SYNC_TIME +H_BACK_PORCH)&&(hcnt < H_SYNC_TIME +H_BACK_PORCH +H_ACTIVE))
			if((vcnt >=V_SYNC_TIME + V_BACK_PORCH)&&(vcnt<V_SYNC_TIME+V_BACK_PORCH+V_ACTIVE))
				de <= 1'b1;
       		else
            	de <= 1'b0;
         else
            de <= 1'b0;
        end
    end
 //显示区域
 always@(posedge clk)begin
        if(de == 1'b1)begin
            pix_x <= hcnt - H_SYNC_TIME - H_BACK_PORCH;  // 在有效区域内开始计数
            pix_y <= vcnt - V_SYNC_TIME - V_BACK_PORCH;
        end
        else begin
            pix_x <= 'd0;
            pix_y <= 'd0;
        end
    end
//显示颜色
always @(posedge clk) begin
        if((pix_x >= 960)&&(pix_x <1060)&&((pix_y >=540)&&(pix_y <= 640))) //在屏幕中心 (960,540)开始显示矩形块
             data <= {8'h10,8'hB6,8'h19};  //绿色的RGB分量分别是8'h10,8'hB6,8'h19
        else
            data <= {8'h80,8'h00,8'h00};  //其它消隐区显示黑色,RGB分量分别是8'h80,8'h00,8'h00   
    end
		
endmodule 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93

显示效果:
在这里插入图片描述
  至此,VGA的接口时序以及用FPGA实现了,后续我们可以用这个模块做很多功能。


双线性插值缩放算法原理以及matlab与verilog的实现(一)
双线性插值缩放算法原理以及matlab与verilog的实现(二)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/799345
推荐阅读
相关标签
  

闽ICP备14008679号