VGA 基础知识

VGA 基础知识VGA Video Graphics Array 是视频图像阵列 通常指代 VGA 接口 就是常见的老式电脑中 主机和显示器相连的带有左右两个螺丝的连接线 虽然现在的显示屏大多已经采用 DVI 和 HDMI 方案 但其实 VGA 在另一个地方还有应用 那就是大屏的 LCD 目前 4 3 寸以上的 TFT 基本都是 VGA 接口

大家好,我是讯享网,很高兴认识大家。

VGA(Video Graphics Array) 是视频图像阵列,通常指代VGA接口。就是常见的老式电脑中,主机和显示器相连的带有左右两个螺丝的连接线。虽然现在的显示屏大多已经采用DVI和HDMI方案,但其实VGA在另一个地方还有应用,那就是大屏的LCD。目前4.3寸以上的TFT基本都是VGA接口,这样在完成一个FPGA系统设计时,选择一个VGA接口的TFT用来显示便是最简单方便的方案。

VGA的内部信号


讯享网

最重要的 5 个信号,分别是R 、G、 B 红绿蓝三色的模拟信号,以及行同步信号和场同步信号。 其他信号一般来说板子自己已经帮我们在内部接好了,我们不用去给它信号。

行和场 就可以类比于 显示屏的 宽和高

如上图所示的这样的VGA接口其实是通过模拟VGA接口连接,计算机内部以数字方式生成图像信息。这里最主要的就是要实现R、G、B 三原色信号的数模转换。

电脑屏幕上的所有颜色,都由这红色绿色蓝色三种色光按照不同的比例混合而成的。一组红色绿色蓝色就是一个最小的显示单位。屏幕上的任何一个像素点颜色都可以由一组RGB值来记录和表达。

在电脑中,RGB的所谓“多少”就是指亮度,并使用整数来表示。通常情况下,RGB各有256级亮度,用数字表示为从0、1、2…直到255。

RGB的格式:

对一种颜色进行编码的方法统称为 色彩空间

RGB555:RGB555是一种16位的RGB格式,但是只有用到了5+5+5,剩下的一位其实是没有用到的。R、G、B 每个分量都用5位表示。


RGB565:RGB565使用16位表示一个像素,这16位中的5位用于R,6位用于G,5位用于B。这个比555好在 更加充分利用16位的资源

 

RGB888(也叫RGB24):RGB分量都用8位表示,取值范围为0-255。

RGB444:每个颜色通道用4位来表示,

virtex5用的RGB888。

 

 

 参考:http://t.csdn.cn/7uHis

VGA显示器一般从左上角开始扫描,从左向右逐点扫描,每扫描完一行后,向下移动一行,继续扫描。在这期间,CRT对电子束进行消隐,每行结束时,用行同步信号进行同步;当扫描完所有行,形成一帧图片时,用场同步信号进行同步,使扫描回到屏幕的左上角,同时进行消隐,开始下一帧。

完成一行扫描的时间为水平扫描时间,倒数为行频率;完成一帧的扫描时间为垂直扫描时间,倒数为场频率。基本上用场频率来表示显示屏的刷新频率。

当计算设计的FPGA的时钟频率时需要考虑到无效显示区。

行时序/场时序都需要同步脉冲、显示后沿、显示时序段和显示前沿四部分。VGA工业标准显示模式要求:行同步,场同步都为负极性,即同步脉冲要求是负脉冲。

对于我们输入不同的行和场的同步信号,显示器会自动匹配我们的信号 产生图像。但我们的输入应该满足如下的配置。

现在以640*480,60hz编写相应的程序

`timescale 1ns / 1ps //VGA Format 640*480@60HZ `define H_ACTIVE 640 `define H_FRONT_PORCH 16 `define H_SYNCH_PULSE 96 `define H_BACK_PORCH 48 `define H_TOTAL ( `H_SYNCH_PULSE + `H_BACK_PORCH + `H_ACTIVE + `H_FRONT_PORCH ) //800 // pixels `define V_ACTIVE 480 `define V_FRONT_PORCH 11 `define V_SYNCH_PULSE 2 `define V_BACK_PORCH 31 `define V_TOTAL (`V_SYNCH_PULSE + `V_BACK_PORCH + `V_ACTIVE + `V_FRONT_PORCH ) //524 // lines module vga_driver( input pixel_clk , input rst , output reg de , output reg h_sync , output reg v_sync , output reg [10:0] y_cnt , output reg [10:0] x_cnt ); //=========== 行计数器 ================ always@(posedge pixel_clk)begin if(rst) x_cnt <= 0; else if( x_cnt == (`H_TOTAL-1) ) x_cnt <= 0; else x_cnt <= x_cnt + 1; end //========== 场计数器 ================== always@(posedge pixel_clk)begin if(rst) y_cnt <= 0; else if(x_cnt == (`H_TOTAL-1))begin if(y_cnt == (`V_TOTAL - 1) ) y_cnt <= 0; else y_cnt <= y_cnt + 1; end end //======== 判断输出有效信号 ========== reg h_en; always@(posedge pixel_clk)begin if(x_cnt == (`H_TOTAL-1) ) h_en <= 1; else if(x_cnt == (`H_ACTIVE-1)) h_en <= 0; end reg v_en; always@(posedge pixel_clk)begin if(x_cnt == (`H_TOTAL-1)) begin if(y_cnt == (`V_TOTAL-1) ) v_en <= 1; else if(y_cnt == (`H_ACTIVE-1)) v_en <= 0; end end always@(posedge pixel_clk) begin de <= v_en & h_en; end //================ 设置SYN的时间段为低电平================ always@(posedge pixel_clk)begin if(x_cnt == (`H_ACTIVE+`H_FRONT_PORCH-1)) h_sync <=0; else if(x_cnt == (`H_ACTIVE+`H_FRONT_PORCH+`H_SYNCH_PULSE-1) ) h_sync <=1; end always@(posedge pixel_clk)begin if(rst) v_sync <=1; else begin if(x_cnt == `H_TOTAL-1) begin if(y_cnt == (`V_ACTIVE+`V_FRONT_PORCH-1)) v_sync <=0; else if(y_cnt == (`V_ACTIVE+`V_FRONT_PORCH+`V_SYNCH_PULSE-1) ) v_sync <=1; else v_sync<=v_sync; end else v_sync <=v_sync; end end endmodule 

讯享网

 测试程序:

讯享网`timescale 1ns / 1ps module vga_driver_tb; reg clk,rst; wire de; wire hs,vs; wire [10:0] x_cnt; wire [10:0] y_cnt; vga_driver u0( . pixel_clk ( clk ) , .rst ( rst ) , .de ( de ) , .h_sync ( hs ) , .v_sync ( vs ) , .y_cnt ( y_cnt ) , .x_cnt ( x_cnt ) ); always #30 clk=~clk; initial begin clk = 0; rst = 1; #100 rst = 0; end endmodule 

ise仿真:

使用ise自带的仿真。

看 hs什么时候低电平 什么时候重新拉高,如果是理想情况,一个是x_cnt到达h_active+h_front_porch-1 的时候也就是(640+16)-1=656-1=655的时候拉低,再过h_sync_pause=96 也就是(656+96)-1=752-1=751的时候拉高。

现在写一个顶层模块,同时把RGB颜色输出,但是,在此之前,我们应该给出一个60MHZ的时钟才行,注意,这里的60是根据我们之前讨论的 在不同分辨率下的VGA时序参数那里得到的。此处我们可以用ise自带的时钟IP核来完成时钟频率的转换。

1、DCM实际上就是一个DLL,可以对输入时钟进行相位移动,补偿,产生倍频和分频时钟,但是5以及以后的产品不用了。

2、PLL相对于DCM,除了不能相移时钟,其它的都一样,但是PLL产生时钟的频率比DCM更加精准,而且时钟的jitter也更好。

3、MMCM实际上就是PLL+DCM相移功能的结合体。7系列的FPGA还会在临近I/O部分放置一些PLL,专门给MIG来产生DDR时钟。

这里使用PLL

 这里使用PLL出现了很多问题,一个问题是ERROR:Xst:2035 - Port <clk> has illegal connections. This port is connected to an input buffer and other components.关于这个问题,采取了网上的办法,关掉XST里的IO Buffers。随之会出现io口无缓冲的问题,还有个问题,忘了,和clk有关,最后的解决方法是clk独立的作为一线,然后根据PLL生成60MHZ和33MHZ(本身)时钟,最后XST还是有感叹号,虽然最后编译成功。

top文件:

module top( output [7:0] R,G,B, output h_sync,v_sync, input clk,rst ); wire clk60M ; wire clk33M; wire de ; clock u1 ( .CLKIN1_IN(clk), .RST_IN(1'b0), .CLKOUT0_OUT(clk60M), .CLKOUT1_OUT(clk33M), .LOCKED_OUT() ); wire [10:0]x_cnt ; wire [9:0]y_cnt ; vga_driver u0( . pixel_clk ( clk60M ) , .rst ( rst ) , .de ( de ) , .h_sync ( h_sync ) , .v_sync ( v_sync ) , .y_cnt ( y_cnt ) , .x_cnt ( x_cnt ) ); reg[3:0] Rr , Gr , Br ; always@ (posedge clk33M) case ( x_cnt ) //对于x_cnt在不同的位置,我们赋予不同的颜色,就会形成彩条 80*0 : { Rr , Gr , Br } <={ 8'b00000000 , 8'b00000000 , 8'b00000000 } ; 80*1 : { Rr , Gr , Br } <={ 8'b00000000 , 8'b00000000 , 8'b } ; 80*2 : { Rr , Gr , Br } <={ 8'b00000000 , 8'b , 8'b00000000 } ; 80*3 : { Rr , Gr , Br } <={ 8'b00000000 , 8'b , 8'b } ; 80*4 : { Rr , Gr , Br } <={ 8'b , 8'b00000000 , 8'b00000000 } ; 80*5 : { Rr , Gr , Br } <={ 8'b , 8'b00000000 , 8'b } ; 80*6 : { Rr , Gr , Br } <={ 8'b , 8'b , 8'b00000000 } ; 80*7 : { Rr , Gr , Br } <={ 8'b , 8'b , 8'b } ; endcase assign B = ( de == 0 ) ? 0 : Br ; assign G = ( de == 0 ) ? 0 : Gr ; assign R = ( de == 0 ) ? 0 : Rr ; endmodule

编写约束文件:

讯享网# PlanAhead Generated physical constraints NET "B[7]" LOC = AD7; NET "B[6]" LOC = AC7; NET "B[5]" LOC = AB5; NET "B[4]" LOC = AA5; NET "B[3]" LOC = AB7; NET "B[2]" LOC = AB6; NET "B[1]" LOC = AC5; NET "B[0]" LOC = AC4; # PlanAhead Generated IO constraints NET "B[7]" IOSTANDARD = LVCMOS33; NET "B[6]" IOSTANDARD = LVCMOS33; NET "B[5]" IOSTANDARD = LVCMOS33; NET "B[4]" IOSTANDARD = LVCMOS33; NET "B[3]" IOSTANDARD = LVCMOS33; NET "B[2]" IOSTANDARD = LVCMOS33; NET "B[1]" IOSTANDARD = LVCMOS33; NET "B[0]" IOSTANDARD = LVCMOS33; # PlanAhead Generated physical constraints NET "G[7]" LOC = AE6; NET "G[6]" LOC = AD6; NET "G[5]" LOC = Y7; NET "G[4]" LOC = AA6; NET "G[3]" LOC = AD5; NET "G[2]" LOC = AD4; NET "G[1]" LOC = Y9; NET "G[0]" LOC = Y8; # PlanAhead Generated IO constraints NET "G[7]" IOSTANDARD = LVCMOS33; NET "G[6]" IOSTANDARD = LVCMOS33; NET "G[5]" IOSTANDARD = LVCMOS33; NET "G[4]" IOSTANDARD = LVCMOS33; NET "G[3]" IOSTANDARD = LVCMOS33; NET "G[2]" IOSTANDARD = LVCMOS33; NET "G[1]" IOSTANDARD = LVCMOS33; NET "G[0]" IOSTANDARD = LVCMOS33; # PlanAhead Generated physical constraints NET "R[7]" LOC = W11; NET "R[6]" LOC = Y11; NET "R[5]" LOC = AG6; NET "R[4]" LOC = AH5; NET "R[3]" LOC = V7; NET "R[2]" LOC = W7; NET "R[1]" LOC = AF5; NET "R[0]" LOC = AG5; # PlanAhead Generated IO constraints NET "R[7]" IOSTANDARD = LVCMOS33; NET "R[6]" IOSTANDARD = LVCMOS33; NET "R[5]" IOSTANDARD = LVCMOS33; NET "R[4]" IOSTANDARD = LVCMOS33; NET "R[3]" IOSTANDARD = LVCMOS33; NET "R[2]" IOSTANDARD = LVCMOS33; NET "R[1]" IOSTANDARD = LVCMOS33; NET "R[0]" IOSTANDARD = LVCMOS33; # PlanAhead Generated physical constraints NET "clk" LOC = AH17; NET "v_sync" LOC = Y6; NET "h_sync" LOC = AE7; NET "rst" LOC = AK6; # PlanAhead Generated IO constraints NET "clk" IOSTANDARD = LVCMOS33; NET "h_sync" IOSTANDARD = LVCMOS33; NET "rst" IOSTANDARD = LVCMOS33; NET "v_sync" IOSTANDARD = LVCMOS33;

 生成bit流下载到板子上,再连接显示器观察。

小讯
上一篇 2025-01-10 09:01
下一篇 2025-03-25 15:52

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/51915.html