1. Principio VGA
1. Introducción a la interfaz VGA
El nombre completo de VGA es Video Graphics Array, que es un estándar para la transmisión de video mediante señales analógicas. Los primeros monitores CRT solo pueden recibir entrada de señal analógica debido a razones de diseño y fabricación, por lo que la tarjeta gráfica dentro de la computadora es responsable de la conversión digital a analógica, y la interfaz VGA es la interfaz para emitir señales analógicas en la tarjeta gráfica. Aunque los monitores LCD pueden recibir señales digitales directamente en la actualidad, para ser compatibles con la interfaz VGA de la tarjeta gráfica, la mayoría de ellos también admiten el estándar VGA.
En la pantalla VGA, FPGA necesita generar cinco señales: la señal de sincronización horizontal HS, la señal de sincronización vertical VS, R, G y B tres señales de colores primarios.
En el estándar de transmisión de video VGA, la imagen de video se descompone en las tres señales de colores primarios de rojo, verde y azul. Después de la conversión digital a analógica, se transmite en tres canales independientes bajo la sincronización de las señales de sincronización horizontal (HSYNC) y sincronización vertical (VSYNC). El tiempo de sincronización de VGA en el proceso de transmisión se divide en tiempo de línea y tiempo de campo.
2. Principio de visualización VGA
En la pantalla VGA, FPGA necesita generar cinco señales: la señal de sincronización horizontal HS, la señal de sincronización vertical VS, R, G y B tres señales de colores primarios.
Codificación de colores de tres colores primarios:
color | negro | azul | púrpura | verde | claro | amarillo | Blanco |
---|---|---|---|---|---|---|---|
R | 0 | 0 | 1 | 1 | 0 | 0 | 1 |
GRAMO | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
si | 0 | 1 | 0 | 1 | 0 | 1 | 0 |
De hecho, para la pantalla, las tres señales RGB son en realidad señales analógicas y el nivel de su nivel puede indicar la profundidad del color.
Secuencia de escaneo:
(1) Tiempo de línea (número de píxeles)
(2) Tiempo de fotograma (número de filas)
Especificaciones de pantalla:
Tome 640 * 480 @ 60 como ejemplo, el tiempo requerido para un cuadro: 1s / 60 = 0.017s. El tiempo requerido para 1 línea: 0.017s / 525 = 32.39us. El tiempo requerido para la unidad "elemento": 32.39us / 800 = 40.5ns, la frecuencia de reloj requerida es: 1s / 40.5ns = 24.69MHZ, redondeado a 25MHZ Para cumplir con los requisitos, la FPGA que utilicé tiene un reloj de 125MHZ, por lo que solo necesito dividirlo entre cinco.
2. Módulo VGA
Aquí está el módulo de pantalla VGA de Xiaomei Ge, que usa un chip de codificación de video de alta definición GM7123 de 3 canales. La función principal del chip es convertir los datos de color de RGB888 en una señal de voltaje analógica y luego enviarla a las 3 R de la interfaz VGA. , G, interfaz B, como datos RGB888, los datos de color finales son de 24 bits, un total de 2 ^ 24 colores. Por supuesto, este chip también es adecuado para RGB565, RGB555, RGB444 y otros tipos de datos de imagen.
El módulo Xiaomeige VGA se muestra en la figura:
Los puertos principales que lleva el chip de codificación de video GM7123 son los siguientes:
R0 ~ R7: canal rojo;
G0 ~ G7: canal verde;
B0 ~ B7: canal azul;
reloj: reloj de entrada;
BLK: señal de cancelación de sombras.
Las principales señales derivadas de la interfaz VGA son:
VGA_HS: señal de sincronización de línea;
VGA_VS: señal de sincronización de cuadros.
Tres, diseño de interfaz VGA
1. Requisitos de diseño
Elija 640x480 píxeles, una frecuencia de cuadro de 60 Hz de frecuencia de actualización y utilice un reloj de 25 MHz.
2. Diseño e implementación
Código:
(1) módulo de control VGA
// 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) Módulo de nivel superior
// 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
Código de prueba:
`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
Gráficos de simulación:
Un cuadro de imagen:
Una línea de datos de imagen:
3. Obtenga resultados
Cuatro, resumen
Posteriormente, los datos de video de la cámara OV7670 se transmitirán a la pantalla a través de la interfaz VGA.