1. VGA principle
1. Introduction to VGA interface
The full name of VGA is Video Graphics Array, which is a standard for video transmission using analog signals. Early CRT monitors can only receive analog signal input due to design and manufacturing reasons, so the graphics card inside the computer is responsible for digital-to-analog conversion, and the VGA interface is the interface for outputting analog signals on the graphics card. Although LCD monitors can directly receive digital signals today, in order to be compatible with the VGA interface on the graphics card, most of them also support the VGA standard.
In VGA display, FPGA needs to generate five signals: the horizontal synchronization signal HS, the vertical synchronization signal VS, R, G, and B three primary color signals.
In the VGA video transmission standard, the video image is decomposed into the three primary color signals of red, green and blue. After digital-to-analog conversion, it is transmitted in three independent channels under the synchronization of the horizontal synchronization (HSYNC) and vertical synchronization (VSYNC) signals. The synchronization timing of VGA in the transmission process is divided into line timing and field timing.
2. VGA display principle
In VGA display, FPGA needs to generate five signals: the horizontal synchronization signal HS, the vertical synchronization signal VS, R, G, and B three primary color signals.
Color coding of three primary colors:
colour | black | blue | purple | green | clear | yellow | White |
---|---|---|---|---|---|---|---|
R | 0 | 0 | 1 | 1 | 0 | 0 | 1 |
G | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
B | 0 | 1 | 0 | 1 | 0 | 1 | 0 |
In fact, for the display, the three RGB signals are actually analog signals, and the level of their level can indicate the depth of the color.
Scanning sequence:
(1) Line timing (number of pixels)
(2) Frame timing (number of rows)
Display specifications:
Take 640*480@60 as an example, the time required for one frame: 1s/60=0.017s. The time required for 1 line: 0.017s/525=32.39us. The required time for the unit “element”: 32.39us/800=40.5ns, the required clock frequency is: 1s/40.5ns=24.69MHZ, rounded to 25MHZ To meet the requirements, the FPGA I used has a 125MHZ clock, so I just need to divide it by five.
2. VGA module
Here is the VGA display module of Xiaomei Ge, using a GM7123 3-channel high-definition video encoding chip. The main function of the chip is to convert the color data of RGB888 into an analog voltage signal, and then send it to the 3 Rs of the VGA interface. , G, B interface, such as RGB888 data, the final color data is 24 bits, a total of 2^24 colors. Of course, this chip is also suitable for RGB565, RGB555, RGB444 and other image data types.
The Xiaomeige VGA module is shown in the figure:
The main ports that GM7123 video encoding chip lead out are as follows:
R0~R7: red channel;
G0~G7: Green channel;
B0~B7: blue channel;
clock: input clock;
BLK: Shadow cancellation signal.
The main signals derived from the VGA interface are:
VGA_HS: line synchronization signal;
VGA_VS: Frame synchronization signal.
Three, VGA interface design
1. Design requirements
Choose 640x480 pixels, a frame rate of 60Hz refresh rate, and use 25MHz clock.
2. Design and implementation
Code:
(1) VGA control module
// Company :
// Engineer :
// -----------------------------------------------------------------------------
// https://blog.csdn.net/qq_33231534 PHF's CSDN blog
// -----------------------------------------------------------------------------
// Create Date : 2020-09-14 11:06:48
// Revise Data : 2020-09-14 11:06:48
// File Name : VGA_ctrl.v
// Target Devices : XC7Z015-CLG485-2
// Tool Versions : Vivado 2019.2
// Revision : V1.1
// Editor : sublime text3, tab size (4)
// Description : VGA控制模块,使用GM7123 3通道高清视频编码电路
module VGA_ctrl(
input clk_25M ,
input rst_n ,
input [23:0] data_in ,
output wire VGA_clk ,//25MHz
output wire[23:0] VGA_RGB ,
output wire VGA_HS ,
output wire VGA_VS ,
output wire VGA_BLK ,
output wire[9:0] hcount ,//VGA行扫描计数器
output wire[9:0] vcount ,//VGA场扫描计数器
output wire dat_act
);
parameter VGA_HS_end = 10'd95,
hdat_begin=10'd143,
hdat_end=10'd783,
hpixel_end=10'd799,
VGA_VS_end=10'd1,
vdat_begin=10'd34,
vdat_end=10'd514,
vline_end=10'd524;
assign VGA_clk = clk_25M;
reg [9:0] hcount_r ;
reg [9:0] vcount_r ;
wire add_hcount ;
wire add_vcount ;
assign hcount = dat_act?(hcount_r-hdat_begin):10'd0;
assign vcount = dat_act?(vcount_r-vdat_begin):10'd0;
assign VGA_BLK = VGA_HS && VGA_VS;
always @(posedge clk_25M or negedge rst_n) begin
if (!rst_n) begin
hcount_r <= 10'd0;
end
else if (add_hcount) begin
hcount_r <= 10'd0;
end
else begin
hcount_r <= hcount_r + 1'b1;
end
end
assign add_hcount = hcount_r==hpixel_end;
always @(posedge clk_25M or negedge rst_n) begin
if (!rst_n) begin
vcount_r <= 10'd0;
end
else if (add_hcount) begin
if (add_vcount) begin
vcount_r <= 10'd0;
end
else begin
vcount_r <= vcount_r + 1'b1;
end
end
end
assign add_vcount = vcount_r==vline_end;
assign dat_act = ((hcount_r>=hdat_begin)&&(hcount_r<hdat_end))
&&((vcount_r>=vdat_begin)&&(vcount_r<vdat_end));
assign VGA_RGB = dat_act ? data_in:24'h000000;
assign VGA_HS = (hcount_r>VGA_HS_end);
assign VGA_VS = (vcount_r>VGA_VS_end);
endmodule
(2) Top-level module
// Company :
// Engineer :
// -----------------------------------------------------------------------------
// https://blog.csdn.net/qq_33231534 PHF's CSDN blog
// -----------------------------------------------------------------------------
// Create Date : 2020-09-14 13:52:17
// Revise Data : 2020-09-14 13:53:18
// File Name : VGA_top.v
// Target Devices : XC7Z015-CLG485-2
// Tool Versions : Vivado 2019.2
// Revision : V1.1
// Editor : sublime text3, tab size (4)
// Description : 通过VGA模块使显示器显示彩条
module VGA_top(
input clk ,
input rst_n ,
output wire VGA_clk ,
output wire[23:0] VGA_RGB ,
output wire VGA_HS ,
output wire VGA_VS ,
output wire VGA_BLK
);
parameter VGA_HS_end = 10'd95;
parameter hdat_begin = 10'd143;
parameter hdat_end = 10'd783;
parameter hpixel_end = 10'd799;
parameter VGA_VS_end = 10'd1;
parameter vdat_begin = 10'd34;
parameter vdat_end = 10'd514;
parameter vline_end = 10'd524;
wire dat_act ;
wire[9:0] hcount ;//VGA行扫描计数器
wire[9:0] vcount ;//VGA场扫描计数器
pll inst_pll (.inclk0(clk), .c0(clk_25M));
VGA_ctrl #(
.VGA_HS_end(VGA_HS_end),
.hdat_begin(hdat_begin),
.hdat_end(hdat_end),
.hpixel_end(hpixel_end),
.VGA_VS_end(VGA_VS_end),
.vdat_begin(vdat_begin),
.vdat_end(vdat_end),
.vline_end(vline_end)
) inst_VGA_ctrl (
.clk_25M (clk_25M),
.rst_n (rst_n),
.data_in (data_in),
.VGA_clk (VGA_clk),
.VGA_RGB (VGA_RGB),
.VGA_HS (VGA_HS),
.VGA_VS (VGA_VS),
.VGA_BLK (VGA_BLK),
.hcount (hcount),
.vcount (vcount),
.dat_act (dat_act)
);
reg [23:0] data_in;
wire clk_25M;
always @(posedge clk_25M or negedge rst_n) begin
if (!rst_n) begin
data_in <= 24'h000000;
end
else if (dat_act) begin
if (hcount<80) begin
data_in <= 24'hffffff;
end
else if (hcount>=80&&hcount<160) begin
data_in <= 24'h0000ff;
end
else if (hcount>=80&&hcount<160) begin
data_in <= 24'hff0000;
end
else if (hcount>=160&&hcount<240) begin
data_in <= 24'hff00ff;
end
else if (hcount>=240&&hcount<320) begin
data_in <= 24'h00ff00;
end
else if (hcount>=400&&hcount<480) begin
data_in <= 24'h00ffff;
end
else if (hcount>=480&&hcount<560) begin
data_in <= 24'hffff00;
end
else if (hcount>=560&&hcount<640) begin
data_in <= 24'hffffff;
end
else begin
data_in <= 24'h000000;
end
end
end
endmodule
Test code:
`timescale 1ns/1ns
module VGA_ctrl_tb (); /* this is automatically generated */
reg rst_n;
reg clk_25M;
parameter VGA_HS_end = 10'd95;
parameter hdat_begin = 10'd143;
parameter hdat_end = 10'd783;
parameter hpixel_end = 10'd799;
parameter VGA_VS_end = 10'd1;
parameter vdat_begin = 10'd34;
parameter vdat_end = 10'd514;
parameter vline_end = 10'd524;
localparam clk_period = 20;
reg [23:0] data_in;
wire VGA_clk;
wire [23:0] VGA_RGB;
wire VGA_HS;
wire VGA_VS;
wire VGA_BLK;
wire [9:0] hcount;
wire [9:0] vcount;
wire dat_act;
VGA_ctrl #(
.VGA_HS_end(VGA_HS_end),
.hdat_begin(hdat_begin),
.hdat_end(hdat_end),
.hpixel_end(hpixel_end),
.VGA_VS_end(VGA_VS_end),
.vdat_begin(vdat_begin),
.vdat_end(vdat_end),
.vline_end(vline_end)
) inst_VGA_ctrl (
.clk_25M (clk_25M),
.rst_n (rst_n),
.data_in (data_in),
.VGA_clk (VGA_clk),
.VGA_RGB (VGA_RGB),
.VGA_HS (VGA_HS),
.VGA_VS (VGA_VS),
.VGA_BLK (VGA_BLK),
.hcount (hcount),
.vcount (vcount),
.dat_act (dat_act)
);
initial clk_25M = 0;
always #(clk_period/2) clk_25M = ~clk_25M;
initial begin
#2;
rst_n = 0;
data_in = 24'd0;
#(clk_period*20);
rst_n = 1;
#(clk_period*20);
end
always@(posedge clk_25M) begin
if (hcount>0&&vcount>0) begin
data_in <= hcount;
end
else begin
data_in <= 0;
end
end
endmodule
Simulation graphics:
One frame of image:
One line of image data:
3. Achieve results
Four, summary
Later, the video data of the OV7670 camera will be transmitted to the display through the VGA interface.