概述:
共有5根线组成,HS(行同步),VS(场同步),R(3bit),G(3bit),B(2bit),一共可以显示256种颜色。
基本时序:
从左上方开始扫描,扫描完一行之后,电子束回到下一行起始位置,重新开始扫描,直到右下角最后一个点。
每扫描完一行,生成行同步信号,每扫描完一帧,生成场同步信号,常见的显示器参数,60Hz就是指每秒60帧。
下面是一个典型的行时序:
几个概念:
- 同步脉冲:行同步、场同步信号;
- 显示后沿:同步脉冲的后面;
- 显示前沿:同步脉冲的前面;
- 显示时续段:实际显示时间或区域;
需要注意的是,上述参数与显示器的分辨率以及刷新率有关,参考以下网址:
http://www.tinyvga.com/vga-timing
Verilog实现思路:
- 根据显示器参数,设定基本频率;
- 根据显示器参数,设计行同步、场同步信号;
- 根据同步信号,设计需要显示的信号;
代码如下:
module VGA(clk,rst,hsync,vsync,rgb);
input clk;//系统时钟
input rst;//系统复位
output reg hsync;//行同步
output reg vsync;//场同步
output reg [2:0] rgb;//输出RGB
reg clk_25m;//25M时钟
reg [9:0] hcnt,vcnt;//像素点计数值(800,525,1024)
parameter H_SYNC_END = 96; //行同步脉冲结束时刻
parameter H_SYNC_TOTAL = 800; //行扫描像素点
parameter H_SHOW_START = 140; //行扫描有效开始(可以调整)
parameter H_SHOW_END = 800; //行扫描有效结束(可以调整)
parameter V_SYNC_END = 2; //列同步脉冲结束时刻
parameter V_SYNC_TOTAL = 525; //列扫描像素点
parameter V_SHOW_START = 35; //列扫描有效开始(可以调整)
parameter V_SHOW_END = 513; //列扫描有效结束(可以调整)
always @ (posedge clk or negedge rst) begin//生成25M时钟
if(!rst) begin
clk_25m <= 1'b0;
end
else begin
clk_25m <= ~clk_25m;
end
end
//水平扫描
always @ (posedge clk_25m or negedge rst) begin
if(!rst) hcnt <= 10'd0;
else if(hcnt == H_SYNC_TOTAL) hcnt <= 10'd0;
else hcnt <= hcnt + 1;
end
//垂直扫描
always @ (posedge clk_25m or negedge rst) begin
if(!rst) vcnt <= 10'd0;
else if(vcnt == V_SYNC_TOTAL) vcnt <= 10'd0;
else if (hcnt == H_SYNC_TOTAL) vcnt <= vcnt + 1;
else ;
end
//H_SYNC信号
always @ (posedge clk_25m or negedge rst) begin
if(!rst) hsync <= 1'b0;
else if(hcnt == 10'd0) hsync <= 1'b0;
else if(hcnt == H_SYNC_END) hsync <= 1'b1;
else ;
end
//VSYNC信号
always @ (posedge clk_25m or negedge rst) begin
if(!rst) vsync <= 1'b0;
else if(vcnt == 10'd0) vsync <= 1'b0;
else if(vcnt == V_SYNC_END) vsync <= 1'b1;
else ;
end
always @ (posedge clk_25m or negedge rst) begin//显示
if(!rst) begin
rgb <= 3'b000;
end
else begin
if((vcnt >= 200) && (vcnt <= 300)) begin
if((hcnt >= 200) && (hcnt < 300)) rgb <= 3'h1;
else if((hcnt >= 300) && (hcnt < 400)) rgb <= 3'h2;
else if((hcnt >= 400) && (hcnt < 500)) rgb <= 3'h3;
else if((hcnt >= 500) && (hcnt < 600)) rgb <= 3'h4;
else rgb <= 3'h0;
end
else rgb <= 3'h0;
end
end
endmodule
需要注意的地方:
- 显示后沿和前沿必须设置为全0,否则不能正常显示。