Está en la página 1de 47

UNIVERSIDAD MAYOR DE SAN ANDRES

FACULTAD DE INGENIERIA

CARRERA INGENIERIA ELECTRONICA

VIDEOJUEGO PONG EN VHDL


UTILIZANDO TARJETA XILINX SPARTAN-3AN

MATERIA : PROYECTO II

DOCENTE: ING. ROBERTO OROPEZA CRESPO

ESTUDIANTE:

Américo Álvarez Surci

GESTION 2011

LA PAZ - BOLIVIA
A mis Padres que nunca dejaron de apoyarme

y Ana una persona muy especial.

II
Resumen

“PONG”, un video juego sencillo, es la representación del deporte de TENIS, que consiste

en hacer botar el balón en una paleta a otra sin equivocarse. En el presente proyecto
describimos el movimiento del balón y de la paleta en un campo diseñado para tal

cometido. Analizamos el monitor VGA para poder describir un controlador del mismo,

utilizando la descripcion de hardware que nos brinda el VHDL.

Por ultimo mostraremos como el monitor brinda el campo de juego y también hara de
interfas entre el juego y el jugador.

Abstract

"PONG", a simple video game, is the representation of the sport of tennis, which consists of

bouncing the ball on a pallet to another without making a mistake. In this project, we
describe the movement of the ball and paddle in a field designed for that purpose. We

analyze the VGA monitor to describe the same controller, using the hardware description

that gives us the VHDL.

Finally we show how the monitor provides the playing field and will make the interface

between the game and the player.

III
LISTA DE FIGURAS

Figura 1: Consola ATARI-PONG

Figura 2: Videojuego original pong. Museo Vienna-1998

Figura 3: Recursos de descripción VHDL

Figura 4: Analogía de entidad y arquitectura

Figura 5: Compuerta and de 2 entradas

Figura 6: Ejemplo de descripción en VHDL

Figura 7: Modelo Esquemático

Figura 8: Diagrama conceptual de un monitor TRC

Figura 9: Trazado del Haz de electrones, en un monitor TRC

Figura 10: Diagrama de bloques de un simple controlador VGA

Figura 11: Diagrama de tiempos de un barrido horizontal

Figura12: Diagrama de tiempos de un barrido vertical

Figura13: Tarjeta XILINX Spartan-3AN

Figura 14: Monitor TRC

Figura 15: Conexión VGA, con salidas del FPGA

Figura 16: Flujo grama, Videojuego PONG

Figura 17: diagrama de bloques conceptual, de un trazador de objetos

Figura 18: Elementos primitivos del videojuego PONG

Figura 19: Mapeo de bits de un Redondo

IV
Figura 20: Movimiento del balón en Rebotes de Esquina

LISTA DE TABLAS

Tabla 1 : Combinación a 3 bits, RGB

Tabla 2: Modulo de Sincronia en VHDL

Tabla 3: Modulo Generador de pixeles, 3 objetos cuadrados.

Tabla 4: Modulo Prueba 1.

Tabla 5: Generador de Pixeles, con animación

Tabla 6: Modulo Final, videojuego PONG en VHDL

V
INDICE GENERAL

Resumen/Abstract III

Lista de Figuras IV

Lita de Tablas V

Capitulo 1: ANTECEDENTES Y PROPOSITOS

1.1 Introducción 1

1.2. Objetivos 2

1.2.1 Objetivo principal

1.2.2 Objetivos secundarios

Capitulo 2: MARCO TEORICO

2.1. Antecedentes: Descripción de Hardware 3

2.1.1. Lenguajes Precursores: CDL, DDL, AHPL, ISPS, TI-HDL

2.1.2. Lenguajes Actuales: VERILOG, UDL/I, VHDL

2.2 VHDL 6

2.2.1. Entidad y Arquitectura

2.2.2 Unidad de Diseño y Librerías

2.2.3. Modelo de Diseño Básico

2.3 VGA. 10

2.3.1 Señales de Sincronización. Hsync y Vsync

2.3.2 Timing de Señales de Sincronización VGA

VI
2.3.3 Generador de Pixeles

Capitulo 3: DESARROLLO DEL PROYECTO

3.1 Hardware empleado: 17

XILINX Spartan 3an, Monitor VGA

3.2 Descripción del Sistema: Ping Pong 19

3.2.1 Diagrama de Flujo

3.3 Elaboración y Ejecución del Videojuego “PONG” 20

3.3.1 Señales de sincronismo: VGA SYNC

3.3.2 Generador de pixeles: PONG_GRAPH

 Objetos Rectangulares

3.3.3 Objetos no Rectangulares

3.3.4 Animacion: PONG_GRAPH_ANIMADO

3.4 Programa Principal: JUEGO_PONG 36

Capitulo 4: CONCLUSIONES Y MEJORAS

4.1 Conclusiones 38

4. 2 Mejoras 39

5. BIBLIOGRAFÍA 39

6. ANEXOS 40

VII
Capitulo 1

ANTECEDENTES Y PROPOSITOS

1.1 INTRODUCCION

Pong fue el primer juego desarrollado por Atari Inc. Originalmente la placa de “Pong”

utilizaba transistores, condensadores, resistencias, etc. ocupando un espacio de unos

cuantos metros cuadrados. Aunque ya existía el primer microprocesador, hecho por Intel

en 1970, no fue utilizado aún, por su reciente lanzamiento al mercado, alto coste y
ausencia de documentación.

Atari Pong fue una consola creada por Atari en 1975, es la segunda videoconsola de la

historia. No llevaba cartuchos, sino que tenía sólo un juego, el PONG.

Figura1: Consola ATARI-PONG

El jugador controla en el juego una paleta que tiene un movimiento rectilíneo, haciendo las

veces de paleta para que la pelota rebote en esta y en las paredes del espacio de juego.

El jugador pierde en cuanto más falle en hacer botar el balón en la paleta.

Se utilizara un lenguaje de descripción de hardware para el cometido de reproducir el


juego propuesto.

1
1.2. OBJETIVOS

Con el presente trabajo se trata de enfocar los siguientes objetivos:

1.3.1 Objetivo Principal

 Mediante lenguaje de descripción de hardware, implementar el video

juego PONG en la tarjeta fpga XILINX.

1.3.2 Objetivos Secundarios

 Conocer y definir un circuito controlador básico de sincronismo.

 Conocer y definir un circuito generador de pixeles. A base de

contadores.

 Utilizar el monitor VGA, y dar pautas para futuros diseños.

Figura 2: Videojuego original pong. Museo Vienna-1998

2
Capitulo 2

MARCO TEORICO

Con la creciente complejidad de los diseños digitales ha aparecido una necesidad de

describir un circuito de la forma más eficiente y práctica posible. Un lenguaje de

programación ofrece la posibilidad de un alto nivel de abstracción y es la solución


adecuada para dicha tarea.

2.1 ANTECEDENTES: DESCRIPCIÓN DE HARDWARE

Los lenguajes de descripción hardware son lenguajes de alto nivel con una sintaxis similar

a los de programación (C, ADA, Pascal, Modula, etc.) y una semántica que permite el
modelado y simulación de los dispositivos hardware a diferentes niveles de abstracción.

Los primeros lenguajes de este tipo sólo pretendían servir de vehículo de comunicación

del diseño. Los actuales lenguajes han adquirido un alto grado de estandarización y han

adoptado los nuevos conceptos de la ingeniería de software, permitiendo la verificación de

la especificación del diseño mediante simulación.

2.1.1 Lenguajes Precursores: CDL, DDL, AHPL, ISPS, TI-HDL

CDL (Computer Design Language)

Fue desarrollado por Yaohan Chu a comienzo de los años 60 bajo el principio de

separación de la componente lógica y electrónica de un computador digital. CDL refleja

directamente el hardware y sus operaciones, es decir, existe una correspondencia uno-a-

uno entre los objetos y operaciones hardware (registros, RAMs, relojes, suma, cuenta,

etc.) y las construcciones del lenguaje. La primera versión del simulador CDL para IBM
7090 estuvo disponible en 1968, y la versión tercera para Univac pocos años más tarde.

Se utilizó en universidades y en la industria del radar y aeronáutica.

3
DDL (Digital systems Design Language)

Se desarrolló a mediados de los 60 en la Universidad de Wisconsin con varios objetivos:

precisión y concisión para facilitar la especificación de los diseños, potencia suficiente

para modelar sistemas complejos, independencia respecto a cualquier tecnología o


procedimiento de diseño, capacidad de especificación a diferentes niveles de abstracción

y, finalmente, una sintaxis y una semántica que permitieran la documentación jerárquica

del diseño.

AHPL (A Hardware Programming Language)

Fue propuesto por F.J. Hill y G.R. Peterson unos meses más tarde que el CDL y DDL, y

apareció publicado por primera vez en 1973 en la edición original de Digital Systems:

Hardware Organization and Design. Los autores concibieron AHPL como un lenguaje de

síntesis: todo dispositivo síncrono que pudiese ser implementado en hardware debía ser
expresable en AHPL de manera tal que se pudiese traducir a una realización física

siguiendo un conjunto simple de reglas. En opinión de uno de sus autores, F.J. Hill, que

participó como miembro del grupo de trabajo que formuló las especificaciones originales

para VHDL, la existencia de AHPL favoreció la incorporación de mecanismos para permitir

el proceso de síntesis en VHDL.

ISPS (Instruction Set Processor Specifications)

Con este lenguaje se dio un paso importante hacia la formalización del proceso de diseño
a niveles de comportamiento. Además de la simulación y la síntesis, ISPS se utilizó en la

generación de software, la verificación de programas y la evaluación de arquitecturas.

ISPS favoreció los aspectos de comportamiento sobre los estructurales pero sin

eliminarlos completamente.

TI-HDL (Texas Instruments-HDL)

Es un lenguaje de descripción jerárquica del diseño, estructurado en bloques y basado en

texto, que se ha utilizado principalmente en el diseño de circuitos integrados. Procede de

4
antiguos lenguajes usados allá por 1968, concretamente el TIBSD (TI Boolean System

Description), desarrollado como lenguaje de entrada de datos para un sistema CAD de

circuitos impresos, y Fusim (Functional Simulator), utilizado para describir modelos de alto

nivel de microprocesadores y para generar prototipos de patrones de tests.

2.1.2 Lenguajes Actuales: VERILOG, UDL/I, VHDL

Verilog

Es un lenguaje de descripción hardware diseñado por la compañía Cadence Design

Systems Inc., que se ha venido utilizando como lenguaje del simulador digital Cadence. El

uso de Verilog está promovido por la Open Verilog International (OVI), que publicó en

octubre del 91 la primera versión del Hardware Description Language Reference Manual.

En Verilog la unidad de diseño fundamental es el módulo, que describe un componente

hardware con su interfaz y contenido. Desde un punto de vista funcional, un módulo


Verilog contiene la información de una entidad y su correspondiente arquitectura VHDL.

Verilog no proporciona compilación independiente de módulos: todos los módulos

relacionados con el mismo diseño y simulación deben estar en el mismo archivo.

UDL/I (Unified Design Language for Integrated circuits)

Es un lenguaje de descripción hardware que se viene desarrollando desde 1989 por la

Japan Electronic Industry Development Association, dependiente de importantes

compañías japonesas tales como NTT. Una de las características de UDL/I es que
pretende ser específico para modelar circuitos integrados. La única unidad de diseño

existente en UDL/I es la descripción de diseño, que comprende varias sub-entidades

denominadas descripciones de módulos. Una descripción de diseño contiene el modelo

de un circuito integrado que consta de varias subunidades o módulos, cada uno de los

cuales está especificado por una descripción de módulo.

VHDL (VHSIC Hardware Description Language)

Se aborda en el siguiente subtitulo.

5
2.2 VHDL

Very High Speed Integrated Circuit Hardware Description Language (VHSIC HDL).

Desarrollado por el Departamento de Defensa de los Estados Unidos a finales de la

década de los 70's. El propósito era hacer un estándar para diseñar, modelar, y
documentar circuitos complejos de manera que un diseño desarrollado por una empresa

pudiera ser entendido por otra, además, que pudiera ser procesado por software para

propósitos de simulación.

En diciembre de 1987 VHDL se estableció como el estándar IEEE-1076. En 1993 el


estándar IEEE-1076 se actualizó y un estándar adicional, el IEEE-1164, fue adoptado. En

1996, el estándar IEEE-1076.3 se convirtió en un estándar de VHDL para síntesis siendo

este el que se utiliza en el diseño de sistemas digitales.

Lo que ha hecho que VHDL sea en un tiempo tan corto el lenguaje de descripción de
hardware más utilizado por la industria electrónica, es su independencia con la

metodología de diseño utilizada por cada programador, su capacidad de descripción a

diferentes niveles de abstracción (Fig.3), y en definitiva la posibilidad de poder reutilizar en

diferentes módulos en cualquier aplicación futura.

Figura 3: Recursos de descripción VHDL

6
Si queremos definir cualquier elemento digital tenemos que enfocarnos en 2 bloques de

descripción: 1. Entidad, 2 Arquitectura; que conforman una unidad mínima de diseño.

Además tenemos la posibilidad de utilizar librerías definidas por usuario.

2.2.1 Entidad y Arquitectura

La realización del modelo hardware de un dispositivo en VHDL consiste en la elaboración

de dos unidades de código VHDL: una Declaración de Entidad y un Cuerpo de

Arquitectura.

La Declaración de Entidad es la unidad de diseño VHDL que sirve para especificar el

interfaz de los dispositivos. Cumple, por tanto, funciones equivalentes a las de los

símbolos en las representaciones gráficas.

Figura 4: Analogía de entidad y arquitectura

El Cuerpo de Arquitectura es la unidad de diseño VHDL que sirve para especificar el

funcionamiento de un dispositivo identificado por una determinada Declaración de

Entidad, por lo que se puede considerar el equivalente a las tablas de verdad o a los

cronogramas.

7
En la Declaración de Entidad se define el nombre del dispositivo y sus puertos; en el

Cuerpo de Arquitectura su funcionamiento, en la fig.5 el uso mediante una sentencia que

utiliza un operador lógico AND de 2 entradas.

Figura 5: Compuerta and de 2 entradas

La construcción del modelo de un dispositivo en un entorno VHDL finaliza, en principio, en

el momento en que las unidades VHDL que lo describen quedan almacenadas en una

librería VHDL. Para ello hay que editar las unidades y compilarlas. En el proceso de
compilación se comprueba que no se incumplen una serie de reglas sintácticas y

semánticas.

2.2.2 Unidades de Diseño y librerías

Un modelo VHDL se compone de un conjunto de unidades de diseño. Una unidad de

diseño es la mínima sección de código compilable separadamente.

Las unidades de diseño VHDL se construyen combinando construcciones del lenguaje

(sentencias, declaraciones, etc.). Estas unidades son descritas con la declaración Entidad

y el cuerpo de Arquitectura (descritos en el anterior apartado).

Las librerías de vhdl, representa la unión de varias unidades de diseño mínimas, para

describir un sistema más complejo. Cuando se utilizan varias unidades de diseño se

8
deberá tener un modulo principal que haga el llamado a cualquier modulo según sea el

caso.

Hay que mencionar además que hay que incluir las librerías, en la declaración de

paquetes a utilizar en nuestra descripción en VHDL.

2.2.3. Modelo de Diseño Básico

A continuación se describirá un programa básico en vhdl.

Figura 6: Ejemplo de descripción en VHDL

En la fig. 6 observamos la descripción de un pequeño programa vhdl, que describe el


circuito de la fig. 7, para este descripción se utilizo una entidad, una arquitectura, además

de una librería creada por usuario. Cabe mencionar que los componentes de “milibreria”

9
no se los aprecia, pero son descripciones básicas de una compuerta and de 3 entradas y

una or de n entradas (utilizados en líneas 24,27-30 respectivamente).

Figura 7: Modelo Esquemático

2.3 VGA

El término Video Graphics Array (VGA) Sistema gráfico de pantallas para PC que se

comercializó por primera vez en 1988 por IBM.

Figura 8: Diagrama conceptual de un monitor TRC

En un monitor monocromo (Fig.8), el generador de electrones (cátodo), genera un haz de

electrones enfocado que atraviesa un tubo al vacio, y finalmente llega a una pantalla

10
fluorescente. La pantalla se ilumina en el instante en que el rayo de electrones incide con

los puntos de fosforo que tiene la pantalla. Una bobina de deflexión vertical y otra vertical,

generan campos magnéticos variables que controlan la dirección del haz de electrones, y

así poder realizar el trazado de toda la pantalla. Ósea que siguen un patrón fijo de

izquierda a derecha de arriba abajo como se muestra en la Fig.9.

Figura 9: Trazado del Haz de electrones, en un monitor TRC

Osciladores internos del monitor generan formas de onda diente de sierra para controlar

las dos bobinas de deflexión. Por ejemplo, si el haz de electrones se mueve desde el

borde izquierdo al borde derecho, la tensión aplicada a la bobina de deflexión horizontal

se incrementa gradualmente. Después de alcanzar el borde derecho, el haz vuelve


rápidamente a la orilla izquierda.

El funcionamiento básico de un monitor RGB (a color) es muy similar al visto,

exceptuando que tiene 3 haces de electrones que inciden en los puntos de fósforo rojo,

verde y azul en la pantalla. Los tres puntos se combinan para formar un píxel. Podemos
ajustar los niveles de tensión de la entrada de video de tres señales para obtener el color

del pixel deseado.

11
Tabla 1: Combinación a 3 bits, RGB

El puerto VGA tiene cinco señales activas: señales de sincronización horizontal y vertical
(hsync y vsync), y tres señales de vídeo para el rojo, verde y azul. Un controlador de

vídeo genera todas estas señales. Un diagrama de bloques simplificado de un controlador

de VGA se muestra en la Fig.10. Contiene un circuito de la sincronización, con el nombre

vga_sync, y un circuito de generación de píxel.

Figura 10: Diagrama de bloques de un simple controlador VGA

2.3.1. Señales de Sincronización: Hsync y Vsync

El circuito de la sincronización de vídeo genera la señal hsync, que especifica el tiempo

necesario para el recorrido (exploración) una fila, y la señal vsync, que especifica el

12
tiempo necesario para el recorrido transversal (scan) toda la pantalla. Las discusiones

posteriores se basan en una pantalla VGA 640 por 480, con una tasa de píxel de 25 MHz,

lo que significa que 25 millones de píxeles son procesadas en un segundo.

SEÑAL DE SINCRONIA HORIZONTAL: HSYNC

Figura 11: Diagrama de tiempos de un barrido horizontal

En la figura anterior se observa que se trabaja con 800 pixeles, esto se debe a que

usualmente los monitores CRT tienen un borde negro, conocidos como Backporch y

frontporch, que son el borde izquierdo y derecho respectivamente.

13
 Display: Región en que los pixeles son observables. Longitud de 640 pix.
 Retrace: Región en la que los haces de electrones regresan a la izquierda. La
señal de video debe de estar desactivada. Longitud 96 pix.

 Right Border: Borde derecho. La señal de video desactivada. Longitud de 48px


 Left Border: Borde izquierdo. La señal de video desactivada. Longitud de 96 px.

La señal de Hsync se puede obtener con un contador modulo 800. El backporch y el

frontporch pueden variar entre marcas de monitores.

SEÑAL DE SINCRONIA VERTICAL: VSYNC

Figura12: Diagrama de tiempos de un barrido vertical

Durante la exploración vertical, el haz de electrones se mueven gradualmente de arriba

hacia abajo y luego vuelve arriba. Esto traza toda la pantalla fila a fila. Hay mucho

parecido a la señal HSYNC. La unidad de tiempo del movimiento está representada en

términos de líneas de exploración horizontal. Un período de

de la señal vsync es de 525 pixeles.

 Display: Región en la que son observables las líneas horizontales. Longitud de


480pix.

14
 Retrace: Región en la que los haces de electrones regresan a la parte superior
de la pantalla. La señal de video debe de estar desactivada. Longitud 2 pix.

 Bottom Border: Borde inferior. La señal de video desactivada. Longitud de


10px

 Top Border: Borde Superior. La señal de video desactivada. Longitud de 33 px.

La señal de Vsync se puede obtener con un contador modulo 525. El Bottom y top border

puede variar entre marcas de monitores.

2.3.2. Timing de Señales de Sincronización VGA

Como se mencionó anteriormente, se supone que la tasa de píxel es de 25 MHz. Está

determinada por tres parámetros:

p: El número de píxeles de una línea de exploración horizontal.


pixels
p  800
line

L: El número de líneas de trazado de una pantalla


lines
L  525
screen

s: El número de pantallas (imágenes) por segundo. Tasa de refresco.


screens
s  60
seconds

El parámetro “s” especifica la rapidez con la pantalla debe ser restaurada. Para un ojo
humano, la frecuencia de actualización debe ser al menos 30 pantallas por segundo para

un movimiento continuo debe de ser 60 pantallas por segundo.

El cálculo del timing para las señales de sincronización se lo realiza de la siguiente

manera:

pixels
pixel _ rate  p  L  s  25M
second

15
2.3.3. Generador de Pixeles

El circuito de generación de de píxeles genera la señal RGB de 3 bits para el puerto VGA.

Es necesario especificar el contenido de la pantalla a través de los pixel_x y pixel_y.

Las señales de sincronización VGA (vga_sync), nos proporcionar las coordenadas


actuales de cada pixel.

Existen tres grandes grupos en los que podemos dividir los generadores de pixeles:

 Esquemas de mapa de bits: Se traza gráficos desde una memoria, pixel a pixel. Esto

consume mucha memoria, ya que cada grafico debe de estar guardado en mapa de

bits

 Esquema modular: Se agrupan conjunto de bits para formar un mosaico, y utilizar

varios de estos para formar imágenes.

 Esquema trazador de objetos: Se crea elementos (figuras), por separado siguiendo


un régimen para mostrar objeto a objeto utilizando un multiplexor para este cometido.

Este sistema es el que utilizaremos de aquí en adelante para describir el video juego

planteado.

16
Capitulo 3

DESARROLLO DEL PROYECTO

3.1 HARDWARE EMPLEADO:

XILINX SPARTAN-3AN

Se emplea como elemento base un kit de desarrollo FPGA comercial referencia

UG334 familia Spartan® 3A/3AN de XILINX.

Figura13: Tarjeta XILINX Spartan-3AN

Este kit de desarrollo posee:

o 1 FPGA XC3S700A de la familia Spartan3 de XILINX.


o Puerto USB para programar FPGA

o 4-Mbyte SRAM

o 64-Mbyte ddr2 SDRAM.

o 8-Mbyte Flash memory

o 4 MByte Flash paralelo

o 4 pushbutton, posicionados a manera de arriba, abajo, derecha, izquierda.

17
o 4 switches deslizables

o 8 salidas en LEDs verdes

o 1 pantalla Lcd de 16x2

o 1 Osciladores de 50-MHz.

o 1 SMA para oscilador externo

o 1 puerto VGA.
o 10/100 controlador de red con su conector

o USB Host/Slave Controller.

o Conector I/O para audio externo.

o 2 puertos de 9 pines para comunicación RS-232

o Connector PS/2 mouse/keyboard

o 1 core microblaze
o 4 salidas de DAC

o 2 entradas a ADC

o 2 expansiones de salidas de 40 pines

Además se utilizo el software para la utilización de esta tarjeta de estudio el software

empleado fue el ISE WEB PACK de Xilinx.

Monitor VGA

Figura 14: Monitor TRC

18
Fig.15: Conexión VGA, con salidas del FPGA

3.2 DESCRIPCIÓN DEL SISTEMA: PING PONG

El sistema emulara el juego de pong para un jugador, los push-button de la tarjeta a

manera de mando (control 1 player), que manejara la paleta donde botara la pelota del

juego, además todo esto se observara en un monitor (vga).

3.2.1 Diagrama de Flujo


Inicio

Enviar

Reset

Movimiento balon

Boton
Arriba

Mueve Paddle Arriba Mueve paddle Abajo

Actualiza Datos VGA

Figura16: Flujo grama, Videojuego PONG

19
3.3 ELABORACION Y EJECUCION DEL VIDEOJUEGO PONG

Por lo descrito anteriormente se procederá a elaborar el controlador del vga, modulo a

modulo, siguiendo el esquema de la Figura 10. Luego se procederá a la mejora del código

y posteriormente a la animación.

3.3.1. Señales de sincronismo: VGA SYNC

El circuito de sincronía VGA descrito en la sección 2.3.1. Trabaja con una frecuencia de

25Mhz. El circuito esta implementado con 2 contadores: uno de modulo 800 para el

escaneo horizontal, y otro de modulo 525 para el escaneo vertical.

La tarjeta Xilinx Spartar-3an tiene un oscilador interno de 50Mhz. Por lo que se procederá

a generar una oscilación de 25Mhz, utilizando un contador modulo 2 (signal: mod2); se

definen además 2 contadores para el mapeo horizontal y vertical (signal: h_count y

v_count); además incluimos 2 señales de finalización h_end y v_end que indican la


finalización de cada etapa. Los valores constantes de cada región mostrada en las figuras

11 y 12 (márgenes, display, top, bottom, etc) son indicados y pueden ser cambiados

fácilmente si se requiere.

Para evitar fallas potenciales, se incluye buffers a la salida de las señales hsync y vsync,
esto nos llevara a un retraso de ciclo de reloj, que se corregirá posteriormente añadiendo

otro buffer a la salida vga, que observaremos en el generador de pixeles más adelante.

VHDL del modulo de sincronización:

1 -----------------------------------------------------------------
2 -- Modulo_ señales de sincronía monitor VGA
3 -- Américo Alvarez Surci
4 -----------------------------------------------------------------
5 library ieee;
6 use ieee.std_logic_1164.all;
7 use ieee.numeric_std.all;
8
9 entity vga_sync is
10 port(
11 clk,reset: in std_logic;
12 hsync,vsync: out std_logic; --señales de syncronismo
13 video_on, p_tick: out std_logic;
14 pixel_x,pixel_y: out std_logic_vector(9 downto 0) --contador de pixels 800x525
15 );

20
16 end vga_sync;
17
18 architecture rtl of vga_sync is
19
20 --vga 640 por 480, parametros de sirncronia
21 constant HD: integer:=640; --trazado horizontal
22 constant HR:integer:=96; --recarga horizontal
23 constant HF:integer:=16; --margen derecho
24 constant HB:integer:=48; --margen izquierdo
25 constant VD:integer:=480; --trazado vertical
26 constant VR:integer:=2; --recarga vertical
27 constant VF:integer:=10; --margen inferior
28 constant VB:integer:=33; --margen superior
29 --Contador modulo 2
30 signal mod2_reg, mod2_next:std_logic;
31 --señal de contadores para la sincronia vertical y horizontal
32 signal v_count_reg, v_count_next: unsigned(9 downto 0);
33 signal h_count_reg, h_count_next: unsigned(9 downto 0);
34 --salidas buffer
35 signal v_sync_reg, v_sync_next: std_logic;
36 signal h_sync_reg, h_sync_next: std_logic;
37 --señales de estados
38 signal h_end, v_end, pixel_tick: std_logic;
39
40 begin
41 --registros
42 process(clk,reset)
43 begin
44 if(reset='1') then
45 mod2_reg <= '0';
46 v_count_reg <= (others => '0');
47 h_count_reg <= (others => '0');
48 v_sync_reg <= '0';
49 h_sync_reg <= '0';
50 elsif(clk'event and clk='1') then --flancos subida
51 mod2_reg <= mod2_next;
52 v_count_reg <= v_count_next;
53 h_count_reg <= h_count_next;
54 v_sync_reg <= v_sync_next;
55 h_sync_reg <= h_sync_next;
56 end if;
57 end process;
58 -- generador de 25Mhz con enable tick
59 mod2_next <= not mod2_reg;
60 -- 25Mhz con pixel tick
61 pixel_tick <= '1' when mod2_reg='1' else '0'; -- stado
62 h_end <= '1' when h_count_reg=(HD+HR+HF+HB-1) else '0';
63 --finaliza contador horizontal(799) y pone en cero
64 v_end <= '1' when v_count_reg=(VD+VR+VF+VB-1) else '0';
65 --finaliza contador vertical(524) y pone en cero
66 --contador modulo 800, para sincronismo horizontal
67 process(h_count_reg, h_end, pixel_tick)
68 begin
69 if(pixel_tick='1') then
70 if(h_end='1') then
71 h_count_next <= (others=>'0');
72 else
73 h_count_next <= h_count_reg+1;
74 end if;
75 else
76 h_count_next <= h_count_reg;
77 end if;
78 end process;
79 --contador modulo 525, para sincronismo vertical

21
80 process(v_count_reg, h_end, v_end, pixel_tick)
81 begin
82 if(pixel_tick='1'and h_end='1') then
83 if(v_end='1') then
84 v_count_next <= (others=>'0');
85 else
86 v_count_next <= v_count_reg + 1;
87 end if;
88 else
89 v_count_next <= v_count_reg;
90 end if;
91 end process;
92 --tope horizontal y verticcal, para evitar fallos
93 h_sync_next <= '1' when (h_count_reg>=(HD+HF)) --656
94 and (h_count_reg<=(HD+HR+HF-1)) else '0'; --751
95 v_sync_next <= '1' when (v_count_reg>=(VD+VF)) --690
96 and (v_count_reg<=(VD+VR+VF-1)) else '0'; --491
97
98 --VIDEO ON/OFF
99 video_on <= '1' when ((h_count_reg < HD) and (v_count_reg < VD)) else '0';
100 --Señales de Salida
101 hsync <= h_sync_reg;
102 vsync <= v_sync_reg;
103 pixel_x <= std_logic_vector(h_count_reg);
104 pixel_y <= std_logic_vector(v_count_reg);
105 p_tick <= pixel_tick;
106 end rtl;
107

Tabla 2: Modulo de Sincronia en VHDL

3.3.2. Generador de Pixeles: PONGH_GRAPH

Utilizando el Esquema Trazador de Objetos, visto en la sección 2.3.3, describiremos en

primera instancia los elementos a mostrar en la pantalla objeto a objeto.

Figura17: diagrama de bloques conceptual, de un trazador de objetos

22
Definimos 3 objetos: WALL: pared de rebote, PADDLE: paleta de juego, BALL: balón de

juego.

OBJETOS RECTANGULARES

Figura 18: Elementos primitivos del videojuego PONG

Un objeto rectangular puede ser definido por sus límites en coordenadas de pantalla y-

axis y x-axis(ejes Y y X respectivamente). El juego Básico cuenta con tres objetos como
muestra la figura 19, la pared (wall), el balón (ball), y la paleta (paddle).

WALL: definamos la generación de la pared, definiendo dos constantes WALL_X_L y


WALL_X_R tendremos los limites izquierdo como derecho de esta, además incluimos 2

señales de Salida, wall_on que será la señal que habilita el dibujo por pixeles de la pared

cuando se va muestreando horizontalmente, y la señal wall_rgb que sera la señal que

defina su color en combinatorio de 3 bits (ver Figura 10).


constant WALL_X_L: integer:=32;
constant WALL_X_R: integer:=35;

-- definiendo pixel a pixel linea vertical izquierda (wall)
wall_on <= '1' when (WALL_X_L<=pix_x) and (pix_x<=WALL_X_R) else '0';

23
-- definiendo salida rgb (wall)
wall_rgb <= "001"; -- azul
Segun el codigo escrito tenemos un ancho en pixeles de la pared de 4, desde el pixel 32

hasta el 35. Además se define el color de la pared, color azul.

PADDLE: Es una barra vertical (bar) que se define de igual manera que wall, con el
agregado que aparte de tener límites horizontales (X), también se tiene límites verticales

(Y) superior e inferior, en semejanza se tiene además las señales bar_on y bar_rgb que

será el trazador de dibujo y la señal del color respectivamente.


-- limites derecho e izquierdo
constant BAR_X_L: integer:=600; --left
constant BAR_X_R: integer:=603; --rigth
-- limites superior e inferior
constant BAR_Y_SIZE: integer:=72; --tamaño del paddle
constant BAR_Y_T: integer:=MAX_Y/2-BAR_Y_SIZE/2; --204
constant BAR_Y_B: integer:=BAR_Y_T+BAR_Y_SIZE-1; --204 (variable)

-- definiendo pixel a pixel linea vertical bar (paddle)
bar_on <= '1' when (BAR_X_L<=pix_x) and (pix_x<=BAR_X_R) and
(BAR_Y_T<=pix_y) and (pix_y<=BAR_Y_B) else '0';
-- definiendo salida rgb (bar)
bar_rgb <= "010"; --verde
Cabe mencionar que el código muestra una paleta de 72 pixeles verticales por 4

horizontales, las constantes BAR_Y_T y BAR_Y_B, son los limites superior e inferior.

Podríamos haber definido como un valor integer solamente, pero se opto con elementos a

manera de variables, por que el paddle se moverá de arriba y abajo, así que no tenemos

limites superior (top) e inferior (bottom) fijos.

BALL: De manera similar al paddle(bar), se define el balón.


constant BALL_SIZE: integer:=8;
-- limites derecho e izquierdo
constant BALL_X_L: integer:=580;
constant BALL_X_R: integer:=BALL_X_L+BALL_SIZE-1; --587
-- limites superior e inferior
constant BALL_Y_T: integer:=238;
constant BALL_Y_B: integer:=ball_Y_T+BALL_SIZE-1; --594 (variable)

-- definiendo pixel a pixel el balon cuadrado (sq_ball)
sq_ball_on <= '1' when (BALL_X_L<=pix_x) and (pix_x<=BALL_X_R) and
(BALL_Y_T<=pix_y) and (pix_y<=BALL_Y_B) else '0';
-- definiendo salida rgb (sq_ball)
ball_rgb <= "100";

24
Como los limites vertical y horizontal cambiaran en el movimiento del balon, se utiliza

variables para definirlos.

El circuito de selección y la multiplexación, que examina las señales de los tres objetos y

rutas de la señal RGB (rgb_mux: figura 18), y que traza los 3 objetos es:
process(video_on, wall_on, wall_rgb, bar_on, bar_rgb, sq_ball_on, ball_rgb)
begin
if (video_on='0') then
graph_rgb<="000";
else
if (wall_on='1') then graph_rgb<=wall_rgb;
elsif (bar_on='1') then graph_rgb<=bar_rgb;
elsif (sq_ball_on='1') then graph_rgb<=ball_rgb;
else graph_rgb<="110"; --fondo amarillo
end if;
end if;
end process;
En los casos en los que no este trazando ningún objeto, el fondo se mostrara color

amarillo, teniendo de esta manera un background de nuestra pantalla.

Entonces el Código en Vhdl para definir nuestro generador de pixeles será el siguiente:

1 -----------------------------------------------------------------
2 -- Modulo_generador de pixeles
3 --figuras cuadradas
4 -- Americo Alvarez Surci
5 -----------------------------------------------------------------
6 library ieee;
7 use ieee.std_logic_1164.all;
8 use ieee.numeric_std.all;
9
10 entity pong_graph is
11 port(
12 video_on: in std_logic;
13 pixel_x, pixel_y: in std_logic_vector(9 downto 0);
14 graph_rgb: out std_logic_vector (2 downto 0)
15 );
16 end pong_graph;
17
18 architecture rtl of pong_graph is
19
20 -- coordenadas de X y Y (0,0) a (639,479), para resolucion 640x480
21 signal pix_x, pix_y: unsigned (9 downto 0);
22 constant MAX_X: integer:=640;
23 constant MAX_Y: integer:=480;
24
25 -- variables para linea vertical (wall)
26 -- limites derecho e izquierdo
27 constant WALL_X_L: integer:=32;

25
28 constant WALL_X_R: integer:=35;
29
30 -- variables para linea vertical (paddle)
31 -- limites derecho e izquierdo
32 constant BAR_X_L: integer:=600; --left
33 constant BAR_X_R: integer:=603; --rigth
34 -- limites superior e inferior
35 constant BAR_Y_SIZE: integer:=72; --tamaño del paddle
36 constant BAR_Y_T: integer:=MAX_Y/2-BAR_Y_SIZE/2; --204
37 constant BAR_Y_B: integer:=BAR_Y_T+BAR_Y_SIZE-1; --204 (variable)
38
39 -- variables para ball cuadrado
40 constant BALL_SIZE: integer:=8;
41 -- limites derecho e izquierdo
42 constant BALL_X_L: integer:=580;
43 constant BALL_X_R: integer:=BALL_X_L+BALL_SIZE-1; --587
44 -- limites superior e inferior
45 constant BALL_Y_T: integer:=238;
46 constant BALL_Y_B: integer:=ball_Y_T+BALL_SIZE-1; --594 (variable)
47
48 -- otras señales
49 signal wall_on, bar_on, sq_ball_on:std_logic;
50 signal wall_rgb, bar_rgb, ball_rgb: std_logic_vector(2 downto 0);
51
52 begin
53 pix_x <= unsigned(pixel_x);
54 pix_y <= unsigned(pixel_y);
55
56 -- definiendo pixel a pixel linea vertical izquierda (wall)
57 wall_on <= '1' when (WALL_X_L<=pix_x) and (pix_x<=WALL_X_R) else '0';
58 -- definiendo salida rgb (wall)
59 wall_rgb <= "001"; --
60 azul
61
62 -- definiendo pixel a pixel linea vertical bar (paddle)
63 bar_on <= '1' when (BAR_X_L<=pix_x) and (pix_x<=BAR_X_R) and
64 (BAR_Y_T<=pix_y) and (pix_y<=BAR_Y_B) else '0';
65 -- definiendo salida rgb (bar)
66 bar_rgb <= "010"; --verde
67
68 -- definiendo pixel a pixel el balon cuadrado (sq_ball)
69 sq_ball_on <= '1' when (BALL_X_L<=pix_x) and (pix_x<=BALL_X_R) and
70 (BALL_Y_T<=pix_y) and (pix_y<=BALL_Y_B) else '0';
71 -- definiendo salida rgb (sq_ball)
72 ball_rgb <= "100"; --rojo
73
74 --rgb mux (multiplexor para elegir rgb)
75 process(video_on, wall_on, wall_rgb, bar_on, bar_rgb, sq_ball_on, ball_rgb)
76 begin
77 if (video_on='0') then
78 graph_rgb<="000";
79 else
80 if (wall_on='1') then graph_rgb<=wall_rgb;
81 elsif (bar_on='1') then graph_rgb<=bar_rgb;
82 elsif (sq_ball_on='1') then graph_rgb<=ball_rgb;
83 else graph_rgb<="110"; --fondo amarillo
84 end if;
85 end if;
86 end process;
87 end rtl;

Tabla 3: Modulo Generador de pixeles, 3 objetos cuadrados.

26
Realizado nuestro generador de pixeles, definimos el circuito completo uniendo los

elementos de vga_sync y pong_graph.

Se define una señal pixel_tick, que cuando está habilitada carga la señal rgb al buffer

definido para la salida al monitor, esta señal sirve para sincronizar la salida RGB con las

señales vsync y hsync.

1 -----------------------------------------------------------------
2 -- Modulo_PRUEBA…
3 --Observando Figuras Cuadradas
4 -- Americo Alvarez Surci
5 -----------------------------------------------------------------
6 library ieee;
7 use ieee.std_logic_1164.all;
8
9 entity pong_esquema is
10 port(
11 clk, reset: in std_logic;
12 hsync, vsync: out std_logic;
13 rgb: out std_logic_vector(2 downto 0)
14 );
15 end pong_esquema;
16
17 architecture rtl of pong_esquema is
18 signal pixel_x, pixel_y: std_logic_vector(9 downto 0);
19 signal video_on, pixel_tick: std_logic;
20 signal rgb_reg, rgb_next: std_logic_vector(2 downto 0);
21 begin
22 -- modulo vga_sync
23 vga_sync_unidad: entity work.vga_sync
24 port map(clk=>clk, reset=>reset, hsync=>hsync, vsync=>vsync, video_on=>video_on, p_tick=>pixel_tick,
25 pixel_x=>pixel_x, pixel_y=>pixel_y);
26
27 --modulo pong_graph (pixel generator)
28 pong_graph_unidad: entity work.pong_graph
29 port map(video_on=>video_on, pixel_x=>pixel_x, pixel_y=>pixel_y, graph_rgb=>rgb_next);
30
31 --buffer de salida RGB
32 process (clk)
33 begin
34 if (clk'event and clk='1') then
35 if (pixel_tick='1') then
36 rgb_reg <= rgb_next;
37 end if;
38 end if;
39 end process;
40 rgb <= rgb_reg;
41 end rtl;

Tabla 4: Modulo Prueba 1.

Los códigos de la tabla 2 y tabla 3 son el modulo de sincronía y el generador de pixeles

para objetos cuadrados, ambos códigos no se pueden observar físicamente en su

27
funcionamiento cuando se los carga por separado en el kit de desarrollo xilinx, porque

solo son contadores (modulo de sincronía), y habilitador de pixeles cuando está en cierta

cuenta (generador de pixeles). Por lo que para realizar nuestra primera prueba y observar

que estas descripciones son correctas se procedió a escribir el código presentado en la

tabla 4 que será implementada en la tarjeta.

Observando que nuestros códigos anteriores no tiene errores continuamos con el


desarrollo de nuestro proyecto.

3.3.3. Objetos no rectangulares

El diseño directo de un objeto no rectangular utilizando limites en coordenadas es

complicado, una alternativa es especificar el modelo en mapa de bits. Si queremos

obtener un circulo utilizaremos un modelo de 8 por 8 pixels (figura 20). Para la generación

del balón redondo seguimos el siguiente procedimiento:


 En la exploración, comprobamos si se traza el balón rectángulo de 8x8 pix.

 Si esta en el caso de trazar un cuadrado (visto en anterior inciso), se obtiene el

mapa de bits para generar el balón redondo.

 Usando la activación del círculo, obtenemos una señal para habilitar el rgb para

colorear el círculo.

Figura 19: Mapeo de bits de un Redondo

De igual manera que hicimos en la sección 2.3.2, se definen todos los parámetros con las

modificaciones siguientes: Para implementar el sistema con balón redondo, tenemos que

28
incluir un ROM para almacenar el patrón del mapa de bits de nuestra forma. El

BALL_ROM tiene por longitud de palabra 8 bits en 8 direcciones. Traza el círculo dentro

del cuadrado cuando se activa el rd_ball_on.

constant BALL_SIZE: integer:=8;


-- limites derecho e izquierdo
signal ball_x_l, ball_x_r: unsigned(9 downto 0);
-- limites superior e inferior
signal ball_y_t, ball_y_b: unsigned(9 downto 0);
--Imagen de BALL redondo utilizando ROM
type rom_type is array (0 to 7) of std_logic_vector(0 to 7);
--definiendo nuestra rom para la forma de balon
constant BALL_ROM: rom_type:=
(
"00111100", -- ****
"01111110", -- ******
"11111111", -- ********
"11111111", -- ********
"11111111", -- ********
"11111111", -- ********
"01111110", -- ******
"00111100" -- ****
);
signal rom_addr, rom_col: unsigned (2 downto 0);
signal rom_data: std_logic_vector(7 downto 0);
signal rom_bit: std_logic;
-- señal que indica el mapeo del redondo dentro del cuadrado 8x8
signal rd_ball_on: std_logic;

Además tendremos que modificar la parte de generación de pixeles para obtener nuestro

circulo:

-- definiendo pixel a pixel el balón (habilitando señal de mapeo)


sq_ball_on <= '1' when (ball_x_l<=pix_x) and (pix_x<=ball_x_r) and
(ball_y_t<=pix_y) and (pix_y<=ball_y_b) else '0';
-- mapeando el balon segun la ROM (redondo)
rom_addr <= pix_y(2 downto 0) - ball_y_t(2 downto 0);
rom_col <= pix_x(2 downto 0) - ball_x_l(2 downto 0);
rom_data <= BALL_ROM(to_integer(rom_addr));
rom_bit <= rom_data(to_integer(rom_col));
-- habilitando el balon redondo
rd_ball_on <= '1' when (sq_ball_on='1') and (rom_bit='1') else '0';
-- definiendo salida rgb del balon
ball_rgb <= "100"; --rojo

29
Si sq_ball esta en uno se empieza el mapeo de la región cuadrada 8x8 en la pantalla,

dentro de esta región mediante la ROM se obtiene las coordenadas de exploración.

Restando los tres LSB desde el límite superior (es decir, de ball_y_t) proporciona la fila

correspondiente del ROM (es decir, rom_addr), y restando los tres LSB desde el limite

izquierdo (es decir, ball_x_l), establece la columna ROM (es decir, rom_col).

Finalmente tenemos que hacer modificaciones al circuito de multiplexacion rgb

process(video_on, wa…
begin

elsif (rd_ball_on='1') then graph_rgb<=ball_rgb;

end process;

Todas las modificaciones al código de las tablas 2 y 3 descritas en este subtitulo, se las

incluirá en la siguiente subseccion.

3.3.4. Animación: PONG_GRAPH_ANIMADO

Cuando un objeto cambia su ubicación “poco a poco” en cada exploración en pantalla, se

crea la ilusión de movimiento (se anima). Para ello, podemos usar registros para

almacenar los límites de un objeto y la actualización de su valor en cada ciclo reloj. En el

juego de ping pong, la paleta es controlada por dos

pulsadores y se puede mover arriba y abajo, y la pelota puede moverse y rebotar en todas
las direcciones. Estos 2 elementos son los que presentaran animación.

Si bien el controlador VGA es controlado por una tasa de píxel de 25 MHz, la pantalla del

monitor VGA sólo se actualiza 60 veces por segundo. Por tal razón los registros se deben

actualizar a este ritmo. Definimos una señal refr_tick que afirma 60Hz en cada segundo.

Examinemos en primer lugar nuestro generador de pixeles para el paddle, debemos que

cambiar las constantes bar_y_t y bar_y_b por señales (límite superior e inferior de la
paleta), y además crear un registro bar_y_reg para almacenar el valor actual del límite

superior y su actualización. Si uno de los botones del control del juego es presionado

30
bar_y_reg aumenta o disminuye, en un valor constante BAR_V que representa la

velocidad de movimiento de la paleta.

Si btn(1) y btn(0) hacen que la paleta se desplace arriba y abajo, el segmento de código

para la actualización del bar_y_reg es:

-- nueva posicion en Y del paddle.


process (bar_y_reg, bar_y_t, refr_tick, btn)
begin
bar_y_next <= bar_y_reg; --no se mueve
if (refr_tick='1') then
if (btn(1)='1') and (bar_y_b<(MAX_Y-BAR_V-1)) then
bar_y_next <= bar_y_reg + BAR_V; --movimiento hacia abajo
elsif (btn(0)='1') and (bar_y_t>BAR_V) then
bar_y_next <=bar_y_reg - BAR_V; --movimiento hacia arriba
end if;
end if;
end process;

Ahora enfoquemos el problema del balón, tenemos que cambiar las cuatro constantes

limite por cuatro señales y crear 2 registros ball_x_reg y ball_y_reg para obtener los
movimientos horizontales y verticales del balón, actualizando valores de posición del

balón. El balón se mueve a velocidad constante en una misma dirección, la dirección

puede cambiar cuando bota en las paredes o en el paddle pero no cambia la velocidad.

La velocidad la descomponemos en componentes X y componentes Y, cuyos valores de

velocidad pueden ser positivos BALL_V_P, o negativos BALL_V_N. Los valores actuales

de las componentes las guardamos en registros x_delta_reg y y_delta_reg; el segmento

de código para la actualización de ball_x_reg y ball_y_reg es:


-- posicionando el balon en pantalla
ball_x_next <= ball_x_reg + x_delta_reg when refr_tick='1' else ball_x_reg;
ball_y_next <= ball_y_reg + y_delta_reg when refr_tick='1' else ball_y_reg;

y el segmento de código para la actualización, teniendo en cuenta la velocidad del balón


guardado en registros delta:

-- posicionando por velocidad


process(x_delta_reg, y_delta_reg, ball_y_t, ball_x_l, ball_x_r, ball_y_b, bar_y_t, bar_y_b)
begin
x_delta_next <= x_delta_reg;

31
y_delta_next <= y_delta_reg;
if (ball_y_t < 1) then -- alcance superior
y_delta_next <= BALL_V_P;
elsif (ball_y_b > (MAX_Y-1)) then -- alcance inferior
y_delta_next <= BALL_V_N;
elsif (ball_x_l <= WALL_X_R) then -- alcance del wall
x_delta_next <= BALL_V_P;
elsif (BAR_X_L<=ball_x_r) and (ball_x_r<=BAR_X_R) then
if (bar_y_t<=ball_y_b) and (ball_y_t<=bar_y_b) then
x_delta_next <= BALL_V_N; -- registro de mov.
end if;
end if;
end process;

Cabe mencionar que igual que el juego, cuando fallamos en acertarle al balón con la
paleta esta seguirá su curso perdiéndose posteriormente.

A continuación se presenta el código del generador de pixeles, con animación:


1 -----------------------------------------------------------------
2 -- Modulo_ Generador de pixeles
3 --Genera 2 objetos rectangulare (wall, paddle) además de
4 --un objeto redondo. INCLUYE ANIMACION
5 -- Americo Alvarez Surci
6 -----------------------------------------------------------------
7 library ieee;
8 use ieee.std_logic_1164.all;
9 use ieee.numeric_std.all;
10
11 entity pong_graph_animado is
12 port(
13 clk, reset: std_logic;
14 btn: std_logic_vector(1 downto 0);
15 video_on:in std_logic;
16 pixel_x, pixel_y: in std_logic_vector(9 downto 0);
17 graph_rgb: out std_logic_vector(2 downto 0)
18 );
19 end pong_graph_animado;
20
21 architecture rtl of pong_graph_animado is
22 signal refr_tick: std_logic;
23 -- coordenadas de X y Y (0,0) a (639,479), para resolucion 640x480
24 signal pix_x, pix_y: unsigned (9 downto 0);
25 constant MAX_X: integer:=640;
26 constant MAX_Y: integer:=480;
27
28 -- variables para linea vertical (wall)
29 -- limites derecho e izquierdo
30 constant WALL_X_L: integer:=32;
31 constant WALL_X_R: integer:=40;
32
33 -- variables para linea vertical (paddle)
34 -- limites derecho e izquierdo
35 constant BAR_X_L: integer:=600; --left
36 constant BAR_X_R: integer:=608; --rigth
37 -- limites superior e inferior
38 signal bar_y_t, bar_y_b: unsigned (9 downto 0); --xxxxxxxxxxxxxxxxxxx

32
39 constant BAR_Y_SIZE: integer:=72; --tamaño del paddle
40 -- registro mov. limite superior (posicion x fija)
41 signal bar_y_reg, bar_y_next: unsigned (9 downto 0);
42 -- movimiento del paddle cuando se preciona button (velocidad)
43 constant BAR_V: integer:=4;
44
45 -- variables para ball cuadrado (movimientos basicos no visual)
46 constant BALL_SIZE: integer:=8;
47 -- limites derecho e izquierdo
48 signal ball_x_l, ball_x_r: unsigned(9 downto 0);
49 -- limites superior e inferior
50 signal ball_y_t, ball_y_b: unsigned(9 downto 0);
51 -- registro mov. izquierda + limite superior
52 signal ball_x_reg, ball_x_next: unsigned (9 downto 0);
53 signal ball_y_reg, ball_y_next: unsigned (9 downto 0);
54 -- registro mov. de la velocidad del ball
55 signal x_delta_reg, x_delta_next: unsigned (9 downto 0);
56 signal y_delta_reg, y_delta_next: unsigned (9 downto 0);
57 -- velocidad de ball segun la posicion o registro
58 constant BALL_V_P: unsigned (9 downto 0):=to_unsigned(2,48);
59 constant BALL_V_N: unsigned (9 downto 0):=unsigned(to_signed(-2,48));
60
61 --Imagen de BALL redondo utilizando ROM
62 type rom_type is array (0 to 7) of std_logic_vector(0 to 7);
63 --definiendo nuestra rom para la forma de balon
64 constant BALL_ROM: rom_type:=
65 (
66 "00111100", -- ****
67 "01111110", -- ******
68 "11111111", -- ********
69 "11111111", -- ********
70 "11111111", -- ********
71 "11111111", -- ********
72 "01111110", -- ******
73 "00111100" -- ****
74 );
75 signal rom_addr, rom_col: unsigned (2 downto 0);
76 signal rom_data: std_logic_vector(7 downto 0);
77 signal rom_bit: std_logic;
78
79 -- otras señales
80 signal wall_on, bar_on, sq_ball_on, rd_ball_on: std_logic;
81 signal wall_rgb, bar_rgb, ball_rgb: std_logic_vector(2 downto 0);
82
83 begin
84 -- registros
85 process(clk, reset)
86 begin
87 if (reset='1') then
88 bar_y_reg <= (others=>'0');
89 ball_x_reg <= (others=>'0');
90 ball_y_reg <= (others=>'0');
91 x_delta_reg <= ("0000000100");
92 y_delta_reg <= ("0000000100");
93 elsif(clk'event and clk='1') then
94 bar_y_reg <= bar_y_next;
95 ball_x_reg <= ball_x_next;
96 ball_y_reg <= ball_y_next;
97 x_delta_reg <= x_delta_next;
98 y_delta_reg <= y_delta_next;
99 end if;
100 end process;
101 pix_x <= unsigned (pixel_x);
102 pix_y <= unsigned (pixel_y);

33
103 refr_tick <= '1' when (pix_y=481) and (pix_x=0) else '0';
104
105 -- definiendo pixel a pixel linea vertical izquierda (wall)
106 wall_on <= '1' when (WALL_X_L<=pix_x) and (pix_x<=WALL_X_R) else '0';
107 -- definiendo salida rgb (wall)
108 wall_rgb <= "001"; --azul
109
110 -- definiendo el bar (paddle)
111 -- limites
112 bar_y_t <= bar_y_reg;
113 bar_y_b <= bar_y_t+BAR_Y_SIZE-1;
114 -- habilitando el paddle
115 bar_on <= '1' when (BAR_X_L<=pix_x) and (pix_x<=BAR_X_R) and
116 (bar_y_t<=pix_y) and (pix_y<=bar_y_b) else '0';
117 -- definiendo salida rgb (bar)
118 bar_rgb <= "010"; --verde
119
120 -- nueva posicion en Y del paddle.
121 process (bar_y_reg, bar_y_t, bar_y_b, refr_tick, btn)
122 begin
123 bar_y_next <= bar_y_reg; --no se mueve
124 if (refr_tick='1') then
125 if (btn(1)='1') and (bar_y_b<(MAX_Y-BAR_V-1)) then
126 bar_y_next <= bar_y_reg + BAR_V; --movimiento hacia abajo
127 elsif (btn(0)='1') and (bar_y_t>BAR_V) then
128 bar_y_next <=bar_y_reg - BAR_V; --movimiento hacia arriba
129 end if;
130 end if;
131 end process;
132
133
134 -- definiendo balon
135 -- limites
136 ball_x_l <= ball_x_reg;
137 ball_y_t <= ball_y_reg;
138 ball_x_r <= ball_x_l + BALL_SIZE - 1;
139 ball_y_b <= ball_y_t + BALL_SIZE - 1;
140 -- definiendo pixel a pixel el balon (habilitando señal de mapeo)
141 sq_ball_on <= '1' when (ball_x_l<=pix_x) and (pix_x<=ball_x_r) and
142 (ball_y_t<=pix_y) and (pix_y<=ball_y_b) else '0';
143 -- mapeando el balon segun la ROM (redondo)
144 rom_addr <= pix_y(2 downto 0) - ball_y_t(2 downto 0);
145 rom_col <= pix_x(2 downto 0) - ball_x_l(2 downto 0);
146 rom_data <= BALL_ROM(to_integer(rom_addr));
147 rom_bit <= rom_data(to_integer(rom_col));
148 -- habilitando el balon redondo
149 rd_ball_on <= '1' when (sq_ball_on='1') and (rom_bit='1') else '0';
150 -- definiendo salida rgb del balon
151 ball_rgb <= "100"; --rojo
152 -- posicionando el balon en pantalla
153 ball_x_next <= ball_x_reg + x_delta_reg when refr_tick='1' else ball_x_reg;
154 ball_y_next <= ball_y_reg + y_delta_reg when refr_tick='1' else ball_y_reg;
155 -- posicionando por velocidad
156 process(x_delta_reg, y_delta_reg, ball_y_t, ball_x_l, ball_x_r, ball_y_b, bar_y_t, bar_y_b)
157 begin
158 x_delta_next <= x_delta_reg;
159 y_delta_next <= y_delta_reg;
160 if (ball_y_t < 1) then -- alcance superior
161 y_delta_next <= BALL_V_P;
162 elsif (ball_y_b > (MAX_Y-1)) then -- alcance inferior
163 y_delta_next <= BALL_V_N;
164 elsif (ball_x_l <= WALL_X_R) then -- alcance del wall
165 x_delta_next <= BALL_V_P;
166 elsif (BAR_X_L<=ball_x_r) and (ball_x_r<=BAR_X_R) then

34
167 if (bar_y_t<=ball_y_b) and (ball_y_t<=bar_y_b) then
168 x_delta_next <= BALL_V_N; --MOV. registro
169 end if;
170 end if;
171 end process;
172
173 --rgb mux (multiplexor para elegir rgb)
174 process(video_on, wall_on, bar_on, rd_ball_on, wall_rgb, bar_rgb, ball_rgb)
175 begin
176 if (video_on='0') then
177 graph_rgb<="000"; --negro
178 else
179 if (wall_on='1') then graph_rgb<=wall_rgb;
180 elsif (bar_on='1') then graph_rgb<=bar_rgb;
181 elsif (rd_ball_on='1') then graph_rgb<=ball_rgb;
182 else graph_rgb<="011"; --fondo amarillo
183 end if;
184 end if;
185 end process;
186 end rtl;

Tabla 5: Generador de Pixeles, con animación

Para lo rebotes del balón en las paredes horizontales y verticales, se utilizo los registros:
x_delta_reg, x_delta_next, y_delta_reg, y_delta_next; que son registros que actualizaran los

de posición de balón ball_x_reg y ball_y_reg.

Figura 20: Movimiento del balón en Rebotes de Esquina

35
3.4 PROGRAMA PRINCIPAL: JUEGO_PONG

En la anterior sección se mostro todo el procedimiento que se siguió en la elaboración de

este videojuego, se presento en primera instancia el diseño de un circuito de

sincronización VGA_SYNC, luego se procedió a definir un generador de pixeles básico

para este juego, que mostraba en pantalla 3 elementos rectangulares PONG_GRAPH

además en este mismo apartado se mostro la descripción completa de este modulo


pong_graph con el modulo vga_sync a manera de depurar posibles errores cometidos con

la elaboración de alguna de estas descripciones, PONG_ESQUEMA fue el modulo con el

que verificamos esto, además nos dio un avance de cómo sería nuestro programa

principal utilizando 2 módulos.

Luego se procedió a mejorar el aspecto visual, y realizar un balón redondo, utilizando

como base de referencia nuestro pong_graph. Una vez definido como realizaremos el
balón redondo se procedió a realizar nuestro generador de pixeles con un agregado

importante “la animación”, PONG_GRAPH_ANIMADO nos da la base principal de un

sistema de juego planteado en nuestro problema.

A continuación se presenta programa principal (modulo juego_pong), que será la

culminación del presente trabajo, incluye los módulos vga_sync y el pong_graph_animado:


1 library ieee;
2 use ieee.std_logic_1164.all;
3
4 entity juego_pong is
5 port(
6 clk, reset:in std_logic;
7 btn:in std_logic_vector(1 downto 0);
8 hsync, vsync: out std_logic;
9 rgb: out std_logic_vector(2 downto 0)
10 );
11 end juego_pong;
12
13 architecture rtl of juego_pong is
14 signal pixel_x, pixel_y: std_logic_vector(9 downto 0);
15 signal video_on, pixel_tick: std_logic;
16 signal rgb_reg, rgb_next: std_logic_vector(2 downto 0);
17
18 begin
19 unidad_sincronia_vga: entity work.vga_sync
20 port map(clk=>clk, reset=>reset, video_on=>video_on, p_tick=>pixel_tick, hsync=>hsync, vsync=>vsync,
21 pixel_x=>pixel_x, pixel_y=>pixel_y);
22
23 unidad_pong_graph_animado: entity work.pong_graph_animado
24 port map(clk=>clk, reset=>reset, btn=>btn, video_on=>video_on, pixel_x=>pixel_x, pixel_y=>pixel_y,

36
25 graph_rgb=>rgb_next);
26
27 -- definiendo salida rgb en flancos subida de periodo de clock
28 process (clk)
begin
29 if (clk'event and clk='1') then
30 if (pixel_tick='1') then
31 rgb_reg <= rgb_next;
end if;
32 end if;
33 end process;
34 rgb <= rgb_reg;
35 end rtl;
36
37
38
39
40
41
42
43
44
Tabla 6: Modulo Final, videojuego PONG en VHDL

37
Capitulo 4

CONCLUSIONES Y MEJORAS

4.1 CONCLUSIONES

Se describió un monitor CRT para computadora y se trabajo directamente en el puerto de

salida VGA de la tarjeta Xilinx.

Se definió cada señal del conector vga. La señal de sincronismo se la trato en un

principio, y se la definió con contadores distintos.

El circuito generador de pixeles se lo trato en diferentes niveles, primeramente generando


figuras básicas, luego con figuras definidas en una ROM. Además se vio que para la

animación se utilizo registros varios.

Con el avanzar, de prueba y error en código vhdl, se pudo implementar de manera exitosa

el videojuego en la tarjeta XILINX spartan-3an.

Se dio bases para futuros experimentos en tarjetas fpga, ya que el código en VHDL

planteado se lo escribió de la manera más desglosada y explicando todas las sentencias y

valores críticos. Los módulos presentados son aptos para la síntesis, ya que muchas

líneas son reducibles y fusionarles.

38
4.1 MEJORAS

El sistema descrito en este proyecto, es a manera de introducción a proyectos mas


grandes utilizando la tarjeta XILINX, por lo que se puede incluir muchas mejoras a este

modulo de juego.

1. Incluir otro jugador, para que se parezca más al juego de PING-PONG de 2

jugadores.

2. Incluir un interfaz de juego. Un teclado ps2 para que 2 jugadores lo utilicen como

controles de juego.
3. Incluir texto al esquema generador de pixeles. Además de un texto que indique los

puntos de ambos jugadores.

4. Mediante la memoria RAM de la tarjeta, incluir una presentación en imágenes de

mapa de bits. A manera de modo de espera.

5. Además mediante la RAM también definir una imagen de fondo, a manera de

escenario de juego (background).


6. Incluir sonidos, para el bote del balón en las paletas, además música de fondo en

midi.

5. BIBLIOGRAFIA

 Digital Logic And Microprocessor Design With VHDL - Hwang

 Circuit Design with VHDL (2005) - MIT Press

 http://members.optusnet.com.au/jekent/FPGA.htm#Section5.1

 http://hoper3d.blogspot.com/2008/09/vhdl-pong.html

 http://es.scribd.com/doc/55055785/pingpong

39
6. ANEXOS

 Implementacion en laboratorio utilizando Tarjeta XILINX Spartan 3AN

 Campo de Juego el videojuego implementado

40

También podría gustarte