01_VGA display driver design and verification
1. VGA
1.1 Introduction to VGA
1.2 VGA interface and pin definition
1.3 VGA display principle
1.4 VGA Timing Standards
1.4.1 Hsync line synchronization
The unit of the line scanning period is the pixel
1.4.2 Vsync field synchronization
The unit of field scanning period is line, a complete line scanning period
1.4.3 The overlapping part is the display part
1.5 VGA display mode and related parameters
640 * 480 @ 60
640: One line: 640 pixels in the horizontal scan cycle.
480: Each frame image has 480 lines.
60: In this mode, the image is displayed 60 times per second and refreshed 60 times.
Calculation of Clock Frequency
2. Experimental objectives
Experiment goal: write VGA driver, use FPGA development board to drive VGA display to display ten-color equal-width color bars, VGA display mode is 640x480@60.
3. Principles of VGA hardware resources
Weight resistor network digital to analog conversion
RGB 565 r:5 g:6 b:5 16 bits wide [15:0]
4. Functional modules
4.1 Top-level modules
The block diagram of the entire system
locked is active high
4.2 Clock Generation Module
This experiment uses the classic VGA display mode 640x480@60, and the theoretical clock frequency should be 25.175MHz. In order to facilitate clock generation, we use a 25MHz clock instead of a 25.175MHz clock, which will not affect the experiment. In this experimental project, the incoming clock frequency of the board crystal oscillator is 50MHz. The role of the clock generation module is to divide the 50MHz crystal oscillator clock into 25MHz VGA working clock.
4.3 VGA timing control module
Generate line and field signals, and output the input image information pix_data to output rgb
Pix_x, Pix_y is the coordinates in the video image used to generate the image
4.4 Image data generation module
5. Waveform diagram
5.1 VGA timing control module
It can be seen from the timing standard that the line and field signals are pulled high during the synchronization phase, and the line and field signal counters are set.
Effective signal of image
It can be known from the above that the image will be displayed correctly only when the image data is sent into the effective display area of VGA, so when can the image data be sent in? We can declare a valid signal, assign a high level to the effective display area of the image, and assign a low level to the non-effective display area of the image, use this signal as a constraint condition, control the correct input of the image signal, and define this signal as the effective signal for image display (rgb_valid).
When the two counters count to the effective display area of the image, rgb_valid assigns a high level, otherwise it assigns a low level. 0-34, 0-144
pix_x
pix_y, scan the line first, and then scan
the RGB
of the scanning field because this experiment is a display of VGA multi-color bar. The image data generation module VGA_PIC needs to assign the PIX_DATA signal with the coordinates (pix_x, pix_y) as the constraint. The assignment of X_Data will be lagging behind to meet the clock cycle at a time, showing that there will be problems with the image.
In order to solve this problem, we need to declare a new image data request signal pix_data_req, which should be
one clock cycle ahead of the image display valid signal (rgb_valid) to offset the problem caused by pix_data timing logic assignment.
5.2 Image data generation module
6. RTL
6.1 vga_ctrl
module vga_ctrl(
input wire vga_clk , //输入工作时钟,频率 25MHz
input wire sys_rst_n , //输入复位信号,低电平有效
input wire [15:0] pix_data , //输入像素点色彩信息
output wire [9:0] pix_x , //输出有效显示区域像素点 X 轴坐标
output wire [9:0] pix_y , //输出有效显示区域像素点 Y 轴坐标
// pix_x 和 pix_y 目的就是为了 rgb 的有效显示
output wire [15:0] rgb, //输出像素点色彩信息
output wire hsync , //输出行同步信号
output wire vsync //输出场同步信号
);
//parameter define
parameter H_SYNC = 10'd96 , //行同步
H_BACK = 10'd40 , //行时序后沿
H_LEFT = 10'd8 , //行时序左边框
H_VALID = 10'd640 , //行有效数据
H_RIGHT = 10'd8 , //行时序右边框
H_FRONT = 10'd8 , //行时序前沿
H_TOTAL = 10'd800 ; //行扫描周期
parameter V_SYNC = 10'd2 , //场同步
V_BACK = 10'd25 , //场时序后沿
V_TOP = 10'd8 , //场时序上边框
V_VALID = 10'd480 , //场有效数据
V_BOTTOM = 10'd8 , //场时序下边框
V_FRONT = 10'd2 , //场时序前沿
V_TOTAL = 10'd525 ; //场扫描周期
//wire define
wire rgb_valid ; //VGA 有效显示区域
wire pix_data_req ; //像素点色彩信息请求信号
//reg define
reg [9:0] cnt_h ; //行同步信号计数器
reg [9:0] cnt_v ; //场同步信号计数器
//cnt_h:行同步信号计数器
always@(posedge vga_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_h <= 10'd0 ;
else if(cnt_h == H_TOTAL - 1'd1)
cnt_h <= 10'd0 ;
else
cnt_h <= cnt_h + 1'd1 ;
//hsync:行同步信号
assign hsync = (cnt_h <= H_SYNC - 1'd1) ? 1'b1 : 1'b0 ;
//cnt_v:场同步信号计数器
always@(posedge vga_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_v <= 10'd0 ;
else if((cnt_v == V_TOTAL - 1'd1) && (cnt_h == H_TOTAL-1'd1))
cnt_v <= 10'd0 ;
else if(cnt_h == H_TOTAL - 1'd1)
cnt_v <= cnt_v + 1'd1 ;
else
cnt_v <= cnt_v ;
//vsync:场同步信号
assign vsync = (cnt_v <= V_SYNC - 1'd1) ? 1'b1 : 1'b0 ;
//rgb_valid:VGA 有效显示区域
assign rgb_valid = (((cnt_h >= H_SYNC + H_BACK + H_LEFT)
&& (cnt_h < H_SYNC + H_BACK + H_LEFT + H_VALID))
&&((cnt_v >= V_SYNC + V_BACK + V_TOP)
&& (cnt_v < V_SYNC + V_BACK + V_TOP + V_VALID)))
? 1'b1 : 1'b0;
//pix_data_req:像素点色彩信息请求信号,超前 rgb_valid 信号一个时钟周期
assign pix_data_req = (((cnt_h >= H_SYNC + H_BACK + H_LEFT - 1'b1)
&& (cnt_h<H_SYNC + H_BACK + H_LEFT + H_VALID - 1'b1))
&&((cnt_v >= V_SYNC + V_BACK + V_TOP)
&& (cnt_v < V_SYNC + V_BACK + V_TOP + V_VALID)))
? 1'b1 : 1'b0;
//pix_x,pix_y:VGA 有效显示区域像素点坐标
assign pix_x = (pix_data_req == 1'b1)
? (cnt_h - (H_SYNC + H_BACK + H_LEFT - 1'b1)) : 10'h3ff;
assign pix_y = (pix_data_req == 1'b1)
? (cnt_v - (V_SYNC + V_BACK + V_TOP)) : 10'h3ff;
//rgb:输出像素点色彩信息
assign rgb = (rgb_valid == 1'b1) ? pix_data : 16'b0 ;
endmodule
6.2 vga_pic
module vga_pic(
input wire vga_clk , //输入工作时钟,频率 25MHz
input wire sys_rst_n , //输入复位信号,低电平有效
input wire [9:0] pix_x , //输入有效显示区域像素点 X 轴坐标
input wire [9:0] pix_y , //输入有效显示区域像素点 Y 轴坐标
output reg [15:0] pix_data //输出像素点色彩信息
);
parameter H_VALID = 10'd640 , //行有效数据
V_VALID = 10'd480 ; //场有效数据
parameter RED = 16'hF800, //红色
ORANGE = 16'hFC00, //橙色
YELLOW = 16'hFFE0, //黄色
GREEN = 16'h07E0, //绿色
CYAN = 16'h07FF, //青色
BLUE = 16'h001F, //蓝色
PURPPLE = 16'hF81F, //紫色
BLACK = 16'h0000, //黑色
WHITE = 16'hFFFF, //白色
GRAY = 16'hD69A; //灰色
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//pix_data:输出像素点色彩信息,根据当前像素点坐标指定当前像素点颜色数据
always@(posedge vga_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
pix_data <= 16'd0;
else if((pix_x >= 0) && (pix_x < (H_VALID/10)*1))
pix_data <= RED;
else if((pix_x >= (H_VALID/10)*1) && (pix_x < (H_VALID/10)*2))
pix_data <= ORANGE;
else if((pix_x >= (H_VALID/10)*2) && (pix_x < (H_VALID/10)*3))
pix_data <= YELLOW;
else if((pix_x >= (H_VALID/10)*3) && (pix_x < (H_VALID/10)*4))
pix_data <= GREEN;
else if((pix_x >= (H_VALID/10)*4) && (pix_x < (H_VALID/10)*5))
pix_data <= CYAN;
else if((pix_x >= (H_VALID/10)*5) && (pix_x < (H_VALID/10)*6))
pix_data <= BLUE;
else if((pix_x >= (H_VALID/10)*6) && (pix_x < (H_VALID/10)*7))
pix_data <= PURPPLE;
else if((pix_x >= (H_VALID/10)*7) && (pix_x < (H_VALID/10)*8))
pix_data <= BLACK;
else if((pix_x >= (H_VALID/10)*8) && (pix_x < (H_VALID/10)*9))
pix_data <= WHITE;
else if((pix_x >= (H_VALID/10)*9) && (pix_x < H_VALID))
pix_data <= GRAY;
else
pix_data <= BLACK;
endmodule
6.3 vga_colorbar
module vga_colorbar(
input wire sys_clk , //输入工作时钟,频率 50MHz
input wire sys_rst_n , //输入复位信号,低电平有效
output wire hsync , //输出行同步信号
output wire vsync , //输出场同步信号
output wire [15:0] rgb //输出像素信息
);
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//wire define
wire vga_clk ; //VGA 工作时钟,频率 25MHz
wire locked ; //PLL locked 信号
wire rst_n ; //VGA 模块复位信号
wire [9:0] pix_x ; //VGA 有效显示区域 X 轴坐标
wire [9:0] pix_y ; //VGA 有效显示区域 Y 轴坐标
wire [15:0] pix_data; //VGA 像素点色彩信息
//rst_n:VGA 模块复位信号
assign rst_n = (sys_rst_n & locked);
//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
//------------- clk_gen_inst -------------
ip_pll ip_pll_inst
(
.areset (~sys_rst_n ), //输入复位信号,高电平有效,1bit
.inclk0 (sys_clk ), //输入 50MHz 晶振时钟,1bit
.c0 (vga_clk ), //输出 VGA 工作时钟,频率 25MHz,1bit
.locked (locked ) //输出 pll locked 信号,1bit
);
//------------- vga_ctrl_inst -------------
vga_ctrl vga_ctrl_inst
(
.vga_clk (vga_clk ), //输入工作时钟,频率 25MHz,1bit
.sys_rst_n (rst_n ), //输入复位信号,低电平有效,1bit
.pix_data (pix_data ), //输入像素点色彩信息,16bit
.pix_x (pix_x ), //输出 VGA 有效显示区域像素点 X 轴坐标,10bit
.pix_y (pix_y ), //输出 VGA 有效显示区域像素点 Y 轴坐标,10bit
.hsync (hsync ), //输出行同步信号,1bit
.vsync (vsync ), //输出场同步信号,1bit
.rgb (rgb ) //输出像素点色彩信息,16bit
);
//------------- vga_pic_inst -------------
vga_pic vga_pic_inst
(
.vga_clk (vga_clk ), //输入工作时钟,频率 25MHz,1bit
.sys_rst_n (rst_n ), //输入复位信号,低电平有效,1bit
.pix_x (pix_x ), //输入 VGA 有效显示区域像素点 X 轴坐标,10bit
.pix_y (pix_y ), //输入 VGA 有效显示区域像素点 Y 轴坐标,10bit
.pix_data (pix_data ) //输出像素点色彩信息,16bit
);
endmodule
7. Testbench
7.1 tb_vga_ctrl
`timescale 1ns/1ns
module tb_vga_ctrl();
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//wire define
wire locked ;
wire rst_n ;
wire vga_clk ;
reg sys_clk ;
reg sys_rst_n ;
reg [15:0] pix_data ;
//********************************************************************//
//**************************** Clk And Rst ***************************//
//********************************************************************//
//sys_clk,sys_rst_n 初始赋值
initial
begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
#200
sys_rst_n <= 1'b1;
end
//sys_clk:产生时钟
always #10 sys_clk = ~sys_clk;
//rst_n:VGA 模块复位信号
assign rst_n = (sys_rst_n & locked);
//pix_data:输入像素点色彩信息
always@(posedge vga_clk or negedge rst_n)
if(rst_n == 1'b0)
pix_data <= 16'h0000;
else
pix_data <= 16'hffff;
//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
//------------- clk_gen_inst -------------
ip_pll ip_pll_inst
(
.areset (~sys_rst_n ), //输入复位信号,高电平有效,1bit
.inclk0 (sys_clk ), //输入 50MHz 晶振时钟,1bit
.c0 (vga_clk ), //输出 VGA 工作时钟,频率 25MHz,1bit
.locked (locked ) //输出 pll locked 信号,1bit
);
//------------- vga_ctrl_inst -------------
vga_ctrl vga_ctrl_inst
(
.vga_clk (vga_clk ), //输入工作时钟,频率 25MHz,1bit
.sys_rst_n (rst_n ), //输入复位信号,低电平有效,1bit
.pix_data (pix_data ), //输入像素点色彩信息,16bit
.pix_x (pix_x ), //输出 VGA 有效显示区域像素点 X 轴坐标,10bit
.pix_y (pix_y ), //输出 VGA 有效显示区域像素点 Y 轴坐标,10bit
.hsync (hsync ), //输出行同步信号,1bit
.vsync (vsync ), //输出场同步信号,1bit
.rgb (rgb ) //输出像素点色彩信息,16bit
);
endmodule
7.2 tb_vga_colorbar
`timescale 1ns/1ns
module tb_vga_colorbar();
//********************************************************************//
//****************** Parameter and Internal Signal *******************//
//********************************************************************//
//wire define
wire hsync ;
wire [15:0] rgb ;
wire vsync ;
//reg define
reg sys_clk ;
reg sys_rst_n ;
//********************************************************************//
//**************************** Clk And Rst ***************************//
//********************************************************************//
//sys_clk,sys_rst_n 初始赋值
initial
begin
sys_clk = 1'b1;
sys_rst_n <= 1'b0;
#200
sys_rst_n <= 1'b1;
end
//sys_clk:产生时钟
always #10 sys_clk = ~sys_clk ;
//********************************************************************//
//*************************** Instantiation **************************//
//********************************************************************//
//------------- vga_colorbar_inst -------------
vga_colorbar vga_colorbar_inst
(
.sys_clk (sys_clk ), //输入晶振时钟,频率 50MHz,1bit
.sys_rst_n (sys_rst_n ), //输入复位信号,低电平有效,1bit
.hsync (hsync ), //输出行同步信号,1bit
.vsync (vsync ), //输出场同步信号,1bit
.rgb (rgb ) //输出 RGB 图像信息,16bit
);
endmodule