VGA协议介绍
VGA是常用的视频协议,该协议中的信号是模拟信号,与之相对应的协议是HDMI协议,HDMI协议是数字协议。数字信号具有抗干扰的效果,如果做过较多的VGA协议的实现可以发现VGA协议会有模糊现象的出现,而HDMI协议可以很好的改善这点。我们会先写VGA协议,然后在VGA协议的基础上写HDMI协议,由此我们也可以发现,VGA协议是HDMI协议的基础,所以我们先学习VGA协议,在学习HDMI协议的书写。
VGA协议有很多分辨率,不同的分辨率又有不同的刷新速率,常见的分辨率如下:
我们这次以最常见的640480 @60Hz为例进行讲解,该分辨率下的详细情况如下:
其中:
1、是VGA的时钟频率,该时钟频率近似即可不需要特别严格的设置
2、每秒钟刷新60张图片,每张图片的分辨率是640480
技术手册中的时序图如下:
联立上面两张图,可以清楚的知道上面每一部分所占像素的大小。
上图数据代表VGA每个像素的位数
VGA协议时序图
VGA系统常见的系统框图如下:
该分辨率情况下的像素位宽每个位的意义如下:
cnt_h(144,783)&&cnt_v(35,194)红色区域
cnt_h(144,783)&&cnt_v(195,354)绿色区域
cnt_h(144,783)&&cnt_v(355,514)红色区域
整个显示数据在整个VGA控制时序中的位置如下:
VGA协议的时序图如下:
上面各个信号的含义如下:
分辨率:640x480
刷新率:60hz
pixel 频率(时钟):25mhz
hsync:行同步信号
vsync:场同步信号
VGA驱动代码
废话不多说结合上面对VGA时序的简单介绍与下面的代码,相信同学们可以很好的完成对VGA时序的理解
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : [email protected]
// Website :
// Module Name : vga_drive.v
// Create Time : 2020-02-03 20:08:42
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module vga_drive(
input vga_clk ,
input rst_n ,
output reg hsync ,
output reg vsync ,
output reg [ 7:0] vga_data
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
localparam H_TOTAL_TIME = 800 ;
localparam H_ADDR_TIME = 640 ;
localparam H_SYNC_TIME = 96 ;
localparam H_BACK_PORCH = 40 ;
localparam H_LEFT_BORDER = 8 ;
localparam V_TOTAL_TIME = 525 ;
localparam V_ADDR_TIME = 480 ;
localparam V_SYNC_TIME = 2 ;
localparam V_BACK_PORCH = 25 ;
localparam V_LEFT_BORDER = 8 ;
reg [12:0] cnt_h ;
reg [12:0] cnt_v ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
always @(posedge vga_clk or negedge rst_n)
if(rst_n == 1'b0)
cnt_h <= 13'd0;
else if(cnt_h == (H_TOTAL_TIME-1'd1))
cnt_h <= 13'd0;
else
cnt_h <= cnt_h + 1'b1;
always @(posedge vga_clk or negedge rst_n)
if(rst_n == 1'b0)
cnt_v <= 13'd0;
else if(cnt_v == (V_TOTAL_TIME-1'b1) && cnt_h == (H_TOTAL_TIME-1'd1))
cnt_v <= 13'd0;
else if(cnt_h == (H_TOTAL_TIME-1'd1))
cnt_v <= cnt_v + 1'b1;
else
cnt_v <= cnt_v;
always @(posedge vga_clk or negedge rst_n)
if(rst_n == 1'b0)
hsync <= 1'b1;
else if(cnt_h == (H_TOTAL_TIME-1'd1))
hsync <= 1'b1;
else if(cnt_h >= (H_SYNC_TIME-1'b1))
hsync <= 1'b0;
else
hsync <= hsync;
always @(posedge vga_clk or negedge rst_n)
if(rst_n == 1'b0)
vsync <= 1'b1;
else if(cnt_v == (V_TOTAL_TIME-1'b1) && cnt_h == (H_TOTAL_TIME-1'd1))
vsync <= 1'b1;
else if(cnt_v >= (V_SYNC_TIME-1'b1) && cnt_h == (H_TOTAL_TIME-1'd1))
vsync <= 1'b0;
else
vsync <= vsync;
always @(posedge vga_clk or negedge rst_n)
if(rst_n == 1'b0)
vga_data <= 8'd0;
else if(cnt_h >= (H_SYNC_TIME+H_BACK_PORCH+H_LEFT_BORDER-1'b1) && cnt_h < (H_SYNC_TIME+H_BACK_PORCH+H_LEFT_BORDER+H_ADDR_TIME-1'b1))begin
if(cnt_v >= (V_SYNC_TIME+V_BACK_PORCH+V_LEFT_BORDER) && cnt_v < (V_SYNC_TIME+V_BACK_PORCH+V_LEFT_BORDER+13'd160))
vga_data <= 8'b111_000_00;
else if(cnt_v >= (V_SYNC_TIME+V_BACK_PORCH+V_LEFT_BORDER+160) && cnt_v < (V_SYNC_TIME+V_BACK_PORCH+V_LEFT_BORDER+13'd320))
vga_data <= 8'b000_111_00;
else if(cnt_v >= (V_SYNC_TIME+V_BACK_PORCH+V_LEFT_BORDER+320) && cnt_v < (V_SYNC_TIME+V_BACK_PORCH+V_LEFT_BORDER+13'd480))
vga_data <= 8'b000_000_11;
else
vga_data <= 8'd0;
end else
vga_data <= 8'd0;
endmodule
VGA测试代码
与前面我们的习惯一样,如果只给出模块代码没有测试代码将会很影响我们的学习,所以这里我们将继续给出测试代码,如下:
`timescale 1ns / 1ps
`define CLOCK 40
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : [email protected]
// Website :
// Module Name : vga_tb.v
// Create Time : 2020-02-03 21:05:31
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module vga_tb;
reg vga_clk ;
reg rst_n ;
wire hsync ;
wire vsync ;
wire [ 7:0] vga_data ;
initial begin
vga_clk = 1'b0;
rst_n <= 1'b0;
#(`CLOCK*100)
rst_n <= 1'b1;
end
always #(`CLOCK/2) vga_clk = ~vga_clk;
vga_drive vga_drive_inst(
.vga_clk (vga_clk ),
.rst_n (rst_n ),
.hsync (hsync ),
.vsync (vsync ),
.vga_data (vga_data )
);
endmodule
经过上面的知识,相信大家可以很好的学会VGA时序,接下来会有一两个VGA时序的例子,然后讲解HDMI协议。
总结
创作不易,认为文章有帮助的同学们可以收藏点赞支持。(工程也都在群中)对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群: