Tabla de contenido:

Sistema de mejora de imagen Zynq: 7 pasos
Sistema de mejora de imagen Zynq: 7 pasos

Video: Sistema de mejora de imagen Zynq: 7 pasos

Video: Sistema de mejora de imagen Zynq: 7 pasos
Video: Desarrollo de Aplicaciones con FPGA Zynq 7000 2024, Noviembre
Anonim
Sistema de mejora de imagen Zynq
Sistema de mejora de imagen Zynq
Sistema de mejora de imagen Zynq
Sistema de mejora de imagen Zynq

Como probablemente pueda deducir del título, el objetivo de este proyecto es crear un sistema de mejora de imagen utilizando ZYNQ ApSOC. Más específicamente, deseamos construir un sistema que pueda despejar la niebla de imágenes o videos. Este sistema tomará datos visuales en malas condiciones como entrada, los procesará utilizando técnicas de mejora de imagen y luego generará el resultado.

El proyecto fue construido y probado en la placa Digilent Zybo, pero otros dispositivos ZYNQ también deberían funcionar.

Dividiremos este proyecto en 3 partes:

1) ENTRADA = Imagen de entrada a través de Ethernet desde la computadora / cámara

2) PROCESO = Procesar la imagen

3) SALIDA = Salida de la imagen a través de una interfaz HDMI

De una manera muy contraria a la intuición, comenzaremos con la parte de salida del proyecto (esto nos dará mejores posibilidades de depuración en el camino), continuaremos con la entrada y terminaremos con la parte de procesamiento.

Paso 1: Materiales

Materiales
Materiales

Para completar este proyecto necesitará:

HARDWARE

- cualquier placa ZYNQ con HDMI y Ethernet debería funcionar / Estoy usando Digilent Zybo

- Cable USB de USB A a micro B

- Cable HDMI

- Cable de ethernet

- Pantalla con entrada HDMI

SOFTWARE

- Xilinx Vivado

- SDK de Xilinx

Paso 2: SALIDA - Controlador VGA Parte 1

SALIDA - Controlador VGA Parte 1
SALIDA - Controlador VGA Parte 1

Emitiremos nuestros datos visuales utilizando el puerto HDMI presente en la placa. El puerto HDMI está conectado al lado PL (Programmable Logic = FPGA) del ZYNQ y necesitaremos diseñar un controlador en VHDL para ello. Si alguna vez ha diseñado un controlador VGA, lo encontrará muy similar. Los tiempos para HDMI y VGA son en realidad los mismos, de hecho, puede construir sobre un controlador VGA existente para obtener un controlador HDMI.

Para comprender mejor lo que realmente está sucediendo, primero diseñaremos un controlador VGA

Queremos mostrar a una resolución de 1920 x 1080.

El controlador VGA es responsable de transmitir los datos de píxeles (en formato RGB) secuencialmente, píxel a píxel a la pantalla. Fuera del área de visualización real de 1920 x 1080 también hay algunas áreas de "borde", a saber: porche delantero, porche trasero y retroceso. El tamaño en píxeles de estas áreas es estándar y específico para cada resolución. Estas áreas NO aparecen en la pantalla, pero son obligatorias y el color de los píxeles en esta área debe ser negro. Una pregunta válida sería por qué se necesitan estas áreas adicionales. Esta pregunta desafía el propósito de este instructivo, pero si tiene curiosidad, lo animo a que investigue más en línea.

Este es un buen video que explica la interfaz VGA

En nuestro caso, queremos mostrar a una resolución de 1920 * 1080, y estos son los tiempos:

Área de visualización horizontal = 1920 píxeles

Porche frontal horizontal = 88 píxeles

Porche trasero horizontal = 148 píxeles

Retroceso horizontal = 44 píxeles

Área de visualización vertical = 1080 píxeles

Porche frontal vertical = 4 píxeles

Porche trasero vertical = 36 píxeles

Retroceso vertical = 5 píxeles

(Aquí puede encontrar tiempos para otras resoluciones

Entonces, nuestra resolución real será 2200 x 1125. Queremos 60 fps (cuadros por segundo), por lo que nuestro reloj de píxeles será 60 * 2200 * 1125 = 148.5 MHz. En la placa Zybo se proporciona un reloj de 125 Mhz. Usaremos una IP MMCM para generar el reloj de píxeles de 148.5 MHz que necesitamos.

Paso 3: SALIDA - Controlador VGA Parte 2

SALIDA - Controlador VGA Parte 2
SALIDA - Controlador VGA Parte 2

Con los antecedentes teóricos del paso anterior, debería poder diseñar su propio controlador VGA. Le proporcionaré un proyecto de Vivado que lo haga, pero le aconsejo que al menos intente hacerlo por su cuenta primero.

La mayoría de los puertos VGA no le brindan 8 bits por canal de color por píxel (vea la imagen de arriba), por lo que deberá adaptar el diseño a la cantidad de pines por color que proporciona la placa (aunque esto no es un problema para el HDMI).

El Diseño pintará toda la pantalla de azul, excepto el píxel superior izquierdo que será rojo. Cabe señalar que este proyecto utiliza las restricciones para la Junta de ZYBO. Entonces, si desea ejecutar este proyecto en otro tablero, debe actualizar el archivo de restricciones y adaptar el número de pines por color.

Eche un vistazo a la figura nr. 2. Recuerde que si bien nuestro controlador VGA genera 5/6 bits por color, esos bits se convierten en una señal analógica para cada canal de color (rojo, verde y azul) antes de pasar por el cable.

Paso 4: SALIDA - Controlador HDMI Parte 1

SALIDA - Controlador HDMI Parte 1
SALIDA - Controlador HDMI Parte 1

Ahora que sabemos cómo funciona el controlador VGA y tenemos un diseño funcional, podemos continuar con el controlador HDMI. El controlador HDMI realmente utilizará todo el código que desarrollamos en el controlador VGA. HDMI y VGA utilizan los mismos tiempos y las mismas señales. La diferencia aparece en los pines de salida.

Mientras que VGA usa un cable para cada color y transmite una señal analógica a través de él, HDMI transmite los datos digitalmente 1 bit a la vez para cada color y usa señalización diferencial. La señalización diferencial significa que para cada bit, el HDMI tiene 2 pines, uno opuesto al otro. Entonces, si quisiéramos transmitir una señal '1', transmitiríamos '1' en un cable y '1' negado en el otro cable. Esto garantiza la integridad de la señal y puede leer más sobre esto aquí https://goo.gl/6CPCzB. Tenemos uno de estos canales para cada color, ROJO, VERDE y AZUL y uno para el reloj. Debido a las características específicas de la señalización diferencial, las señales que enviamos a través de hdmi deben estar balanceadas en CC, lo que significa que el número de unos y ceros debe ser aproximadamente igual en una determinada ventana de tiempo. Para lograr esto usaremos codificación 8b / 10b. Puede aprender mucho sobre cómo funciona la señalización diferencial y la codificación 8b / 10b de la especificación DVI aquí https://goo.gl/hhh8Ge (DVI y HDMI usan las mismas señales de video).

Paso 5: SALIDA - Controlador HDMI Parte 2

SALIDA - Controlador HDMI Parte 2
SALIDA - Controlador HDMI Parte 2

Basta de teoría, vayamos a nuestro proyecto. Mientras que en el Controlador VGA nos salimos con un reloj de 148.5 MHz, aquí tendremos que proporcionar 10 veces esa frecuencia porque queremos transmitir 8 bits para cada color y usando la codificación 8b / 10b que se traduce en 10 bits por píxel y 10 * 148,5 MHz = 1485 MHz. Esa es una frecuencia enorme que no se puede obtener en el tablero Zybo. Afortunadamente, tenemos algunos trucos bajo la manga. Podemos administrar 5 * 148.5MHz = 742.5MHz y usaremos una IP OSERDES (serializador) para transmitir datos tanto en el borde ascendente como en el descendente del reloj de 742.5Mhz, por lo que en realidad obtendremos datos transmitidos a 1485MHz. Vivado nos dará algunas advertencias de tiempo y siempre puede optar por una resolución más baja con un reloj más pequeño, pero como funciona, realmente no nos importa por ahora (las advertencias están relacionadas con el hecho de que los búferes del reloj no funcionan oficialmente admite frecuencias superiores a 464 MHz).

Entonces, lo que debemos hacer es codificar los datos de la salida de nuestro controlador VGA en formato 8b / 10b y luego serializarlos como se mencionó anteriormente. También necesitaremos agregar otro MMCM al proyecto para generar el reloj de 742.5MHz para la serialización.

Adjunté a continuación los archivos vhdl para el codificador y el serializador. Primero debe codificar los canales RGB y luego serializarlos.

Ejemplo para el canal rojo:

TMDS_encoder_RED: TMDS_encoder

mapa de puertos (clk148, red_channel_8bits, c_red, video_on, encoded_red_10bits);

Serialiser_RED: Serialiser10_1

mapa de puertos (clk148, clk742, encoded_red_10bits, reset, red_serial_1bit);

La entrada "c" del TMDS_encoder es "00" para rojo y verde y "vsync & hsync" para azul (esto es parte de la especificación DVI

Paso 6: Visualización de imágenes desde la RAM

Visualización de imágenes desde la RAM
Visualización de imágenes desde la RAM

El propósito del controlador HDMI es mostrar las imágenes procesadas. Ahora, con el controlador implementado y listo para funcionar, deberíamos pensar en alimentar este controlador con datos. Dado que gran parte del proceso de mejora de la imagen se llevará a cabo en el PS (Sistema de procesamiento = Procesador ARM) y las imágenes resultantes residirán en la RAM DDR. Entonces, necesitamos una forma de llevar los datos de la RAM al controlador HDMI.

Para lograr esto, necesitará 3 direcciones IP:

1) VDMA (acceso directo a memoria de video)

2) VTC (controlador de tiempo de video)

3) Stream to Video Out (lo llamaremos S2VO de ahora en adelante)

S2VO en realidad proporcionará una señal RGB 24BIT a la salida y las señales HSYNC y VSYNC necesarias. Entonces podemos dejar esa parte del controlador HDMI fuera.

Debe agregar estas direcciones IP a su diseño, configurarlas y realizar las conexiones adecuadas.

Finalmente, debería obtener algo parecido al esquema anterior.

Paso 7: SALIDA - FIN DEL SDK

SALIDA - FIN DEL SDK
SALIDA - FIN DEL SDK

Con todo el hardware configurado y listo para funcionar, ahora debemos compilar el software en la PS. Exportaremos el hardware y el flujo de bits y lanzaremos el SDK.

1) Archivo -> Exportar -> Exportar hardware -> Marque Incluir Bitstream y presione OK

2) Archivo -> Iniciar SDK

En el SDK, cree un nuevo proyecto de aplicación.

3) Archivo -> Nuevo -> Proyecto de aplicación

4) Elija un nombre para su proyecto y presione Siguiente

5) Seleccione la plantilla "Hola mundo" y presione Finalizar

La aplicación en el SDK deberá programar el VDMA. Hay algunas funciones estándar que se utilizan para lograr esto (entraré en detalles cuando tenga tiempo).

Para probar nuestro diseño, usaremos la función SDK Restore (Xilinx Tools -> Dump / Restore) para poner una imagen en la memoria RAM DDR y mostrarla usando nuestro controlador HDMI. Puede cargar la imagen en cualquier lugar que desee (excepto algunas pequeñas áreas restringidas al comienzo de la memoria). Para nuestro ejemplo, elegimos la dirección 16777216 y el tamaño de archivo 8294400 = 1920 * 1080 * 4 (4 canales = RGB + alfa).

Funciona !

Continuará

Recomendado: