VGA(Video Graphics Array,视频图形阵列), 是 IBM 于 1987 年提出的一个使用类比讯号的电脑显示标准。 VGA 是最多制造商所共同支持的一个低标准,个人电脑在加载自己的独特驱动程式之前,都必须支持 VGA 的标准
VGA 扫描方式
显示器扫描方式分为逐行扫描和隔行扫描:逐行扫描是扫描从屏幕左上角一点开始,从左向右逐点扫描,每扫描完一行, 电子束回到屏幕的左边下一行的起始位置,在这期间, CRT 对电子束进行消隐,每行结束时,用行同步信号进行同步;当扫描完所有的行,形成一帧,用场同步信号进行场同步,并使扫描回到屏幕左上方,同时进行场消隐,开始下一帧。 隔行扫描是指电子束扫描时每隔一行扫一线,扫完一屏后再返回来扫描剩下的线,隔行扫描的显示器闪烁快速,可能会使使用者眼睛疲劳( 本实验采用逐行扫描的方式)扫描原理清楚以后,紧接着大家再来看看 VGA 的行、列同步时序
VGA 中定义行时序和列时序都需要同步脉冲( a 段),显示后沿( b 段)、显示时序段( c 段)和显示前沿( d 段)四部分。 VGA 工业标准显示模式要求:行同步、列同步都为负极性,即同步脉冲要求是负脉冲。由 VGA 行时序可知:每一行都有一个负极性行同步脉冲( a 段),是数据行的结束标志,同时也是下一行的开始标志。在同步脉冲之后为显示后沿( b 段),在显示时序段( c 段)显示器为亮的过程, RGB 数据驱动一行上的每一个像素点,从而显示一行。在一行的最后为显示前沿( d 段)。在显示时间段之外没有图像投射到屏幕,而是插入消隐信号。同步脉冲、显示后沿和显示前沿都是在行消隐间隔内,当消隐有效时, RGB 信号无效,屏幕不显示数据。VGA 的列时序与行时序分析基本一致
以红色框图的显示标准 800*600*60Hz 为例。 (800 为列数, 600 为行数,60Hz 为刷新一屏的频率)
行时序:屏幕对应的行数为 628( a+b+c+d=e 段),其中 600( c 段)为显示行;每行均有行同步信号( a 段),为 4 个行周期的低电平;
列时序:每个显示行包括 1056 列( a+b+c+d=e 段),其中 800( c 段)为有效显示区,每一行有一个行同步信号( a 段),为 128 个行周期的低电
平。
扫描时钟频率: 40MHZ
设计模块说明:
(1)时钟分频模块
我们开发板上使用的晶振为 50MHZ,由于我们的显示标准为 800*600*60HZ,所以我们需要分频输出 40MHZ 的系统时钟。时钟分频模块,我们可以通过调用锁相环来实现。
(2)VGA 行列同步控制模块
VGA 显示标准需要设定行列同步信号,标定出有效显示区域,这也是整个 VGA驱动模块的核心部分
(3)VGA 色彩显示控制模块
在图像有效显示区域内,输出控制颜色的 r、 g、 b 信号
module VGA_top( clk, rst_n, vga_hs, vga_vs, vga_r, vga_g, vga_b ); input clk,rst_n; output vga_hs,vga_vs; output [2:0] vga_r; output [2:0] vga_g; output [1:0] vga_b; wire clk_25; wire en; pll pll( .inclk0(clk), .c0(clk_25) ); VGA VGA( .clk(clk_25), .rst_n(rst_n), .vga_hs(vga_hs), .vga_vs(vga_vs), .en(en) ); RGB RGB( .en(en), .vga_r(vga_r), .vga_g(vga_g), .vga_b(vga_b) ); endmodule /*************************************************** VGA: 1440(行)*900(列)*60(刷新) 扫描时钟 106Mhz 同步(a) 后沿(b) 有效(c) 前沿(d) 周期(e) hs : vs : ***************************************************/ module VGA( clk, rst_n, vga_hs, vga_vs, en ); input clk,rst_n; output reg vga_hs;//列同步信号 output reg vga_vs;//行同步信号 output en;//显示有效区域的使能信号640*480 parameter //vga_hs hs_a = 10'd96, hs_b = 10'd48, hs_c = 10'd640, hs_d = 10'd16, hs_e = 10'd800, //vga_vs vs_a = 10'd2, vs_b = 10'd33, vs_c = 10'd480, vs_d = 10'd10, vs_e = 10'd525; reg [9:0] cnt_hs;//列计数器 reg [9:0] cnt_vs;// //------------------扫描计数---------------- always @(posedge clk or negedge rst_n) if(!rst_n) cnt_hs <= 10'd0; else if(cnt_hs == (hs_e - 1))//所有列扫描完 cnt_hs <= 10'd0; else cnt_hs <= cnt_hs + 1'b1; always @(posedge clk or negedge rst_n) if(!rst_n) cnt_vs <= 10'd0; else if(cnt_vs == (vs_e - 1))//所有行扫描完 cnt_vs <= 10'd0; else if(cnt_hs == (hs_e - 1))//所有列扫描完 cnt_vs <= cnt_vs + 1'b1;//行计数器加1 //------------------------------------------- always @(posedge clk or negedge rst_n) if(!rst_n) vga_hs <= 1'b1; else if(cnt_hs == 1'b0)//列开始扫描 vga_hs <= 1'b0; else if(cnt_hs == hs_a)//同步(a) vga_hs <= 1'b1; always @(posedge clk or negedge rst_n) if(!rst_n) vga_vs <= 1'b1; else if(cnt_vs == 1'b0)//行开始扫描 vga_vs <= 1'b0; else if(cnt_vs == vs_a)//同步(a) vga_vs <= 1'b1; wire [10:0] en_1,en_2; //列有效区域 assign en_1 = ( (cnt_hs >= hs_a + hs_b) && (cnt_hs <= hs_a + hs_b + hs_c) )?(cnt_hs - hs_a - hs_b):11'd0; //行有效区域 assign en_2 = ( (cnt_vs >= vs_a + vs_b) && (cnt_vs <= vs_a + vs_b + vs_c) )?(cnt_vs - vs_a - vs_b):11'd0; //列,行有效区域 assign en = (en_1>0 && en_2>0)?1'b1:1'b0; endmodule //vga颜色控制 module RGB( en, vga_r, vga_g, vga_b ); input en; output [2:0]vga_r,vga_g; output [1:0]vga_b;//红,绿,蓝各三位 assign vga_r = en?3'b111:3'b000; assign vga_g = 3'b000; assign vga_b = 2'b00; endmodule `timescale 1ns/1ns `define clock_period 20 module VGA_top_tb; reg clk,rst_n; wire vga_hs,vga_vs; wire [2:0] vga_r,vga_g; wire [1:0] vga_b; VGA_top VGA_top( .clk(clk), .rst_n(rst_n), .vga_hs(vga_hs), .vga_vs(vga_vs), .vga_r(vga_r), .vga_g(vga_g), .vga_b(vga_b) ); initial clk =1; always #(`clock_period/2) clk = ~clk; initial begin #1;//Difference clock edge rst_n = 1'b0; #(`clock_period*5) rst_n = 1'b1; #(`clock_period); //#(`clock_period*200); //$stop; end endmodule
RTL结构实现
仿真波形图
实验效果图:
vga输出一端口波形
附件为在网上找的VGA文档,介绍的比较全面!有兴趣的可以下载看看
"VGA驱动与Verilog实现"
文章评论(0条评论)
登录后参与讨论