這次學習我主要掌握了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顏色搭配