FPGA-based VGA control output display (using GM7123 HD video encoding chip)

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)

Insert picture description here

(2) Frame timing (number of rows)

Insert picture description here

Display specifications:

Insert picture description here

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.

Guess you like

Origin blog.csdn.net/qq_33231534/article/details/108583972