这次学习我主要掌握了vga的基本运行原理。
vga基本概念:
VGA时序主要包括两条信号线(HS,VS)的输出——行扫描和场扫描。VGA采用逐行扫描,每个像素对应的点扫描。行与行之间存在消隐以及显示时期,场与场之间也类似。行扫描可分为以下几个阶段:同步、消隐后肩、显示期、消隐前肩再到下个周期同步为一个循环,对应的是屏幕上的一行。场同步类似,对应为屏幕显示的一帧。标准的VGA屏幕比例为4:3有固定的帧率以及扫描场频率的标准。
常见的4:3 vga时序表:
网上找的场和行的时序表:
这里可以看出,想要实现基本的vga其实 不难,只需要用verilog描述出:同步脉冲、后沿、前沿、和有效显示区域即可
接下来是代码
module vga(
input clk,
input rst,
output hsync, // 行同步信号
output vsynv, // 场同步信号
output vga_r,
output vga_g,
output vga_b
);
reg [10:0]x_cnt; //行坐标计数器 0~1039-1
reg [9:0]y_cnt; //列坐标计数器 0~666-1
always @(posedge clk or negedge rst)
begin
if(!rst)
x_cnt <= 0;
else if(x_cnt == 11'd1039 - 1)
x_cnt <= 0;
else
x_cnt <= x_cnt + 1;
end
always @(posedge clk or negedge rst)
begin
if(!rst)
y_cnt <= 0;
else if(y_cnt == 10'd666 - 1)
y_cnt <= 0;
else if(x_cnt == 11'd1039 - 1)
y_cnt <= y_cnt + 1;
end
wire valid; //有效显示区域来临的标志
assign valid = (x_cnt >= 11'd187) && (x_cnt < 11'd987)
&& (y_cnt >= 10'd31 ) && (y_cnt < 10'd631);
wire [9:0] xpos,ypos; // 有效的显示区域 800 * 600
assign xpos = x_cnt - 11'187; // 从0开始计数
assign ypos = y_cnt - 10'd31;
reg r_hsync,r_ysync; // 同步信号的产生
always @(posedge clk or negedge rst)
begin
if(!rst)
r_hsync <= 1'b1;
else if(x_cnt == 11'd0)
r_hsync <= 0;
else if(x_cnt == 11'd120 - 1)
r_hsync <= 1'b1
end
always @(posedge clk or negedge rst)
begin
if(!rst)
r_ysync <= 1'b1;
else if(y_cnt == 10'd0)
r_ysync <= 0;
else if(y_cnt == 10'd6 - 1)
r_ysync <= 1'b1
end
assign hsync = r_hsync;
assign vsync = r_vsync;
最后,我让vga在屏幕的左边显示黑色,右边显示蓝色:
always @(*)
begin
if(xpos <= 400) // 黑
vga_r = 0;
vga_g = 0;
vga_b = 0;
else
vga_r = 0; // 蓝
vga_g = 0;
vga_b = 1;
end
最后附上vga颜色搭配