赞
踩
开发平台:vivado 2020.1
芯片:xc7k410tffv900-2
VGA (Video Graphics Array)视频图形阵列是BM 于1987 年提出的一个使用模拟信号的电脑显示标准。VGA接口即电脑采用 VGA 标准输出数据的专用接口。VGA 接口共有15 针,分成3 排,每排5个孔,早期在显卡上应用最为广泛的接口类型。它传输红、绿、蓝模拟信号以及同步信号(水平和垂直信号)。如图所示:
每个管脚具体的作用如下:
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次,时序图如下:
其中,vsync是由hsync组成:
所以一幅图像在显示器真实的情况是这样:
不同分辨率的不同参数不同,大致分辨率表如下:
显示模式 | 时钟/Mhz | 行同步hsync | 行后沿 | 行有效 | 行前沿 | 行总共 | 场同步vsync | 场后沿 | 场有效 | 场前沿 | 场总共 |
---|---|---|---|---|---|---|---|---|---|---|---|
640×480@60Hz | 25.2 | 96 | 48 | 640 | 16 | 800 | 2 | 33 | 480 | 10 | 525 |
800×600@60Hz | 40 | 128 | 88 | 800 | 40 | 1056 | 4 | 23 | 600 | 1 | 628 |
1024×768@60Hz | 65 | 136 | 160 | 1024 | 24 | 1344 | 6 | 29 | 768 | 3 | 806 |
1280×720@60Hz | 74.25 | 40 | 220 | 1280 | 110 | 1650 | 5 | 20 | 720 | 5 | 750 |
1280×1024@60Hz | 108 | 112 | 248 | 1280 | 48 | 1688 | 3 | 38 | 1024 | 1 | 1066 |
1920×1080@60Hz | 148.5 | 44 | 148 | 1920 | 88 | 2200 | 5 | 36 | 1080 | 4 | 1125 |
3840×2160@60Hz | 594 | 88 | 296 | 3840 | 196 | 4400 | 10 | 72 | 2160 | 8 | 2250 |
时钟怎么算的呢?比如1920×1080@60hz的时钟=2200×1125×60=148.5M,其他的同理。
本次显示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
显示效果:
再次修改一下程序,让屏幕中间显示一个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
显示效果:
至此,VGA的接口时序以及用FPGA实现了,后续我们可以用这个模块做很多功能。
双线性插值缩放算法原理以及matlab与verilog的实现(一)
双线性插值缩放算法原理以及matlab与verilog的实现(二)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。