Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Curso de VHDL

Descargar como docx, pdf o txt
Descargar como docx, pdf o txt
Está en la página 1de 71

Contenido de los Videos sobre VHDL

CURSO DE PROGRAMACIÓN BÁSICO EN VHDL PARA SISTEMAS DIGITALES .......... 3


Temas para tratar: ...................................................................................................................... 3
INTRODUCCIÓN A LA LÓGICA PROGRAMABLE ............................................................... 3
TECNOLOGÍAS DE FABRICACIÓN EN CIRCUITOS INTEGRADOS .................................. 3
Dispositivos lógicos programables (PLD) ............................................................................ 4
Estructura interna de un PLD ................................................................................................ 5
Arreglos OR .......................................................................................................................... 6
EL PAL ................................................................................................................................. 6
FPGA......................................................................................................................................... 8
Diferencia entre un CPLD y FPGA....................................................................................... 8
CARACTERISTICAS DE LA FPGA ................................................................................... 8
CAMPOS DE APLICACIÓN ............................................................................................. 10
VENTAJAS......................................................................................................................... 11
GHDL.......................................................................................................................................... 11
COMENTARIOS DEL VIDEO SOBRE GHDL .................................................................... 11
Descripción ......................................................................................................................... 11
Dispositivos ......................................................................................................................... 12
Eladio Delgado (Autor de la placa) ..................................................................................... 14
HERRAMIENTAS DE SOFTWARE PARA PROGRAMACIÓN DE VHDL ......................... 14
QUARTUS BÁSICO .............................................................................................................. 16
Primer capitulo .................................................................................................................... 16
ESTRUCTURA FÍSICA DE LA FPGA ..................................................................................... 19
Estructura lógica de la FPGA .................................................................................................. 19
SINTÁCTICA DE VHDL ........................................................................................................... 23
Elementos sintácticos del VHDL ............................................................................................ 23
Identificadores de las entidades............................................................................................... 23
Reglas ...................................................................................................................................... 23
Palabras Reservadas ................................................................................................................ 24
Operadores y expresiones........................................................................................................ 24
Lógicos ................................................................................................................................ 24
Aritméticos .......................................................................................................................... 25
Relacionales ........................................................................................................................ 25
Desplazamientos.................................................................................................................. 25
Concatenación ..................................................................................................................... 25

1
Tipos de Datos en VHDL ........................................................................................................ 25
Arquitecturas ........................................................................................................................... 26
Tipos de datos estándar ........................................................................................................... 29
Tipos de caracteres .................................................................................................................. 29
Tipo Srtring ............................................................................................................................. 30
Tipos de datos Estándar lógico................................................................................................ 30
Tipos de Datos de Punto Fijo y Punto Flotante ....................................................................... 32
Punto Flotante: .................................................................................................................... 33
RESUMEN DE LOS TIPOS DE DATOS PREDIFINIDOS. ................................................. 34
Tipos de datos definidos por el usuario. .............................................................................. 34
Tipos Enteros. ..................................................................................................................... 34
Tipos Enumerados. .............................................................................................................. 35
ESTRUCTURA BASICA DEL CODIGO EN VHDL ............................................................... 38
Librerías .................................................................................................................................. 38
Arquitectura............................................................................................................................. 39
Estructura Básica de un código en VHDL .............................................................................. 42
Declaración de la arquitectura ................................................................................................. 43
Arquitectura Flujo de Datos ................................................................................................ 44
Arquitectura funcional......................................................................................................... 47
Arquitectura estructural ....................................................................................................... 58
VERIFICACIÓN DE LOS REBOTES: ...................................................................................... 65

2
CURSO DE PROGRAMACIÓN BÁSICO EN VHDL PARA
SISTEMAS DIGITALES

Temas para tratar:

 Comienzo de la tecnología
 Que es una FPGA y su función paralela
 Origen VHDL y su desarrollador
 ID’s de desarrollo

INTRODUCCIÓN A LA LÓGICA PROGRAMABLE


Los PLD’s favorecen la integración de aplicaciones más grandes y uso de desarrollos
lógicos mediante el empaquetamiento de las funciones de un circuito integrado por que
ya no se usara los circuitos integrados que constaban de algunas compuertas AND y OR.
Por lo que ahora únicamente vamos a tener un chip en el que vamos a implementar y
simular todo el comportamiento de los circuitos lógicos.

El diseño se basa en bibliotecas y/o en mecanismos específicos de funcionamiento que


según el diseñador cree por que otorga una ventaja flexible al evitar comprar cierta
cantidad de compuertas físicas, aquí podemos desarrollar cualquier cantidad de cosas que
nosotros queramos dependiendo solamente de la programación.

TECNOLOGÍAS DE FABRICACIÓN EN CIRCUITOS


INTEGRADOS

3
La diferencia entre las dos categorías es que los totalmente a la media son aquellos que
están echo para productos que se va a hacer en masa, para productos finales que solo
funcionen de cierta manera y que no cambien su programación y forma de
funcionamiento, estos son los que llamamos full costo y semi costo.

- El ful costo tiene total libertad de diseño, pero tiene una programación final que
no se puede alterar.
- El semi costo tiene la posibilidad que, a través de una estructura básica de
transistores, pero se lo puede medianamente personalizar con las últimas etapas
del circuito.

Celdas estándares pre- caracterizadas: permite hacer una libertad de diseño a través de las
funciones de la biblioteca, pero el desarrollo exige un diseño de fabricación complejoa.

Lógica programable: Dispositivos totalmente flexibles, la FPGA es un sistema complejo


de CPLD’s que se comunican entre ellos para al final llegar a los pines de salidas. Para
las FPGA’s y CPLD’s podemos utilizar el VHDL como lenguaje de descripción en
hatware pero también existen otros como el ADELE y VERY SOFT, cada uno de ellos
con distintas ventajas.

VHDL debido por la estandarización de la IEEE se hizo que la forma de desarrollo sea
un poco compleja el lenguaje

Dispositivos lógicos programables (PLD)


Se va a tener programado todos los circuitos integrados de SSi pequeña, mediana y gran
escala (VLCI), pero todo esto en un espacio reducido (en un chip), ya no se tendrá una
gran cantidad de circuitos integrados que se los colocaba el protoboard para hacer las
aplicaciones:

- Memoria PROM
- PLA

4
- PAL
- GAL
- CPLD
- FPGA
La memoria PROM es una FPGA que tiene un espacio de memoria que a través de lo que
digamos podemos hacer que saque cierta parte de la memoria a través de los pines que
tenga la memoria prom. AL momento de quemar la tarjeta no solamente se queman los
datos de la memoria sino también le podemos quemar que dependiendo de las entradas
que tenga en sus pines pueda sacar ciertos elementos a través de sus pines de salida.

 Las PLA y PAL son arreglos lógicos programables, tienen una solo oportunidad
de programación que no se puede alterar.
 Las GAL son parecidas a las PLA y PAL pero con si se puede volver a programar,
es decir son reutilizables.
 Los CPLD es un dispositivo complejo lógico programables que conecta los arrays
lógicos.
 Las FPGA toma los CPLD como bloque inicial o básico para luego conectarlos
haciendo que la cantidad de unidades lógicas que se puede tener adentro sean más
grande de lo que se tenía en CPLD.

Estructura interna de un PLD


Los dispositivos PLA, PAL y GAL están formados por arreglos o matrices que pueden
ser fijos o programables, mientras que las CPLD y FPGA se encuentran estructuradas
mediante bloques lógicos configurables y celdas lógicas de alta densidad
respectivamente.

La arquitectura básica de una PLD está formada por un arreglo de compuertas AND y
OR conectadas a las entradas y salidas del dispositivo. La finalidad de cada una de ella se
describe a continuación.

5
Lo que tienen es que todo está conectado con todo, absolutamente todo está conectado
con todo, y al momento de programarle lo que hacen ellos es quita los caminos que no
necesita y deja solamente los caminos que necesitamos en la programación de la
aplicación, entonces también aquí lo que podemos ver es que aquí se puede verificar la
propiedad de que esto todo se ejecuta digamos es paralelo ya que cualquier cambio aquí
en esta entrada va causar un cambio en esta salida y en esta salida de manera simultánea
porque como es hardware eso va a cambiar digamos de manera instantánea de manera
simultánea para todas la operaciones que impliquen a la a la entrada involucrada, si, ese
concepto de cambio de una entrada que va a ejecutar un camino de hardware se tiene que
tomar en cuenta al primer momento de comenzar hacer código en VHDL ya que ese es
uno de los conceptos básicos que tiene VHDL para comprender como se va a ir ejecutando
las líneas del código porque aunque el código sigue escribiéndose en líneas separadas,
esas líneas se va ejecutando de manera simultánea.

Arreglos OR
Estos arreglos OR

Las PALS más que nada pueden utilizar también arreglos de compuertas OR pero las
compuertas OR de las PALS en adelante a partir de las CALS solamente van a servirnos
para hacer la suma final de los productos que decíamos:

Y vamos a ver los esquemas de los otros circuitos que podemos tener solamente así en la
parte final tenemos las compuertas OR.

EL PAL
¿Qué es el PAL? Arreglos matriciales de fusibles y diodos que van a representar una
cierta lógica que puede llegar a desempeñar cualquier función booleana. Como hemos
visto al final todo es una función lógica, lo que tenemos es que consisten en términos
AND programables que se alimentan de OR fijos, también tenemos una distinción entre
que partes se puede programar y que partes no, como lo decíamos el OR la parte final
suele ser la parte fija y la parte de AND es la que comienza hacerse los fusiles o los
caminos entre ellos, dependiendo de esa clasificación , bueno aquí vemos un esquemático
de una PAL, como vemos la parte de aquí es la parte variable porque se puede ir
6
quemando los fusibles como nosotros queramos pero al final tenemos siempre una OR
que va a comenzar a unir toda las operaciones AND.

Bueno aquí podemos ver que las AND no tenemos varias entradas como solíamos
nosotros dibujar en sistemas digitales normalmente teníamos una AND de dos entradas
de tres entradas o de cuatro y dependiendo de eso teníamos que cada una tenía una
numeración diferente, aquí en los esquemáticos de estos circuitos lógicos programables
tenemos una sola entrada para la AND, esta una sola entrada nos va a representar una
múltiples entradas a la AND no indica cuantas entrada puede soportar una AND no la
encontrado exactamente cuantas entradas podría tener una AND solita, lo único que nos
dice es que son por múltiples entradas que tenemos.

Viene las GALA como les decía, las GAL se crean para superar las limitaciones de la
PAL de que solo era una sola programación y que daba ahí por siempre esa programación
y no eran reutilizables por lo tanto las GAL vienen con un arreglo de AND programable
ya no es que se queman los fusibles y una parte de OR fijo con una salida lógica
programable, la principal diferencia entre los GALs y los PALs radican en que el primero
es reprogramable es decir los GALs son reprogramable y el otro el PAL, no, tenía
directamente los fusiles quedaban fijos ahí, aquí podemos ver, entonces aquí ya no
aparece este símbolo de un fusible si no aparece estos de aquí estos loger lógicos que me
permiten conectar o desconectar a las diferentes líneas y con eso tiene la GAL tiene la
oportunidad de poderse reprogramar, la GAL aquí en el país como comentario la GAL
para que lo utilizamos, la GAL aquí se sigue utilizando en las empresas textiles igual que
las PROM entonces esos dos circuitos lógicos programables se siguen utilizando y suelen
venir acá al laboratorio para que les renueven o les vuelvan a programar esos dispositivos
ya que no se cual es exactamente el motivo que se les suele desconfigurar y se les suele
ir la programación, entonces estos dispositivos son muy parecidos a las compuertas
lógicas normales que nosotros hemos visto que eran de 16 patitas, esas compuertas AND
que teníamos las chiquitas para poner en proto, el único inconveniente que tenemos con
esas memorias PROM y con las GALs es que nos traen, es que necesitan un programador
para este tipo de circuitos, para ello utilizamos programadores normales de
microprocesadores que tenemos aquí en el laboratorio y que les ayudan a ellos, cada año
suelen venir ahí con eso porque ellos siguen utilizando ahí en sus máquinas estos circuitos
porque estos circuitos dicen cómo funcionan la máquina, entonces esto es un dato
interesante que indica que estos GALs si sirven pero para cosas pequeñitas ya que no
tienen una gran cantidad de compuertas lógicas internamente, las GALs son circuitos
integrados igualitos a una compuerta lógica si no que nos permiten dar solución a cosas
muy pequeñitas.

Circuitos complejos o los dispositivos programadores lógicos complejos es un arreglo de


múltiples PLD pero todos hechos en un arreglo, estos contienen varios bloques lógicos
conectados por medio de señales canalizadas atreves de estos bloques llamados PI o
interconexiones programables. Esta unidad de PI lo único que hace conecta las dos fases,
entonces tenemos bloques lógico y tenemos un PI este PI lo único que hace, nos permite
interconectar varios bloques lógicos, pero que tenemos dentro de un bloque lógico, lo que

7
un bloque lógico tiene es: va a tener compuertas AND que pueden ser reprogramadas que
al final del bloque lógico lo que tenemos es una compuerta OR, también lo que tenemos
un bloque más, ese bloque más va a estar hecho de flip flop y multiplexores esto hace
tomar los datos de todas las OR que se conecten en el bloque lógico he irlos sacando a
través de un bon de un bafer a las entradas y salidas que teníamos al final , así de esta
manera la cantidad de compuertas lógicas que podemos tener en un circuito integrado
subió muchísimo, por eso se utiliza para aplicaciones más complejas.

FPGA
Las FPGA están compuestas de CLB en circuitos lógico-programables que al final de
cuentas son como los CPLDs, y tiene interfases de entrada y salida que son las interfases
directamente a los pines y los canales de comunicación entre los CPLDs o lo bloques
lógicos programables.

Cada FPGA contiene esta matriz de bloques lógicos idénticos que están conectados en
una cuadricula a través de líneas metálicas que corren por todo de manera vertical y
horizontal.

Cada uno contiene un CPLD un PLD complejo es decir tiene muchas compuertas o
bloques lógicos se están intercomunicando por un PI y de este PI sale a las líneas de
comunicación y comienzan a comunicarse entre CPLDs.

Diferencia entre un CPLD y FPGA


 El CPLD son PLD pequeños que están unidos mientras que el FPGA son similares
a los arreglos de compuertas.
 El FPGA tiene una memoria RAM, ya que entre bloques también tenemos una
pequeña memoria de salida.
 El CPLD trabaja a frecuencia superiores a 200Mhz a diferencia del FPGA que
depende de la aplicación
 El CPLD se aplica en contadores rápidos mientras el que FPGA se emplea en
procesadores digitales de señales.

CARACTERISTICAS DE LA FPGA
Bueno aquí podemos ver en la parte central nuestra FPGA.

Tiene ya conectado esta tarjeta de desarrollo algunos elementos como son pulsadores,
Dip Switch un puerto VGA, tenemos un puerto JTAG, bueno tenemos leds para cosas
simples, un display de 7 segmentos pero 4 displays en un solo encapsulado, también
tenemos la parte de un emisor infrarrojo, más bien es un sensor receptor infrarrojo y lo
más importante que vimos para poder adquirir esta de aquí es que tiene estos pines de
salida directos, estos pines de salida nos van a permitir poder usar la FPGA y su pines de
otras formas que no estén conectadas directamente a estos sino que de manera paralela
podríamos usar un pin que esté usando aquí en un pulsador podríamos usarlo como una
salida para otro led digamos que queremos tener 10 leds aquí solo tenemos 4 nos faltarían
6 entonces los sacamos directamente de estos pines también de estos pines sacamos la
alimentación y tierra entonces esta es la ventaja que tiene esta tarjeta de desarrollo la

8
desventaja que les comentaba es que si queremos usar el puerto vga para conectarnos a
un monitor , queremos usar el receptor de rf tendríamos que nosotros mismo desarrollar
o tener ya la librería digamos para poder usar estos de aquí ,entonces tenemos que hacer
tener un desarrollo desde 0 pero en base que está hecho para un laboratorio en el que
tienen que desarrollar software ellos mismo, esta perfecta para nuestras necesidades , tal
vez hasta ahorita alguna inquietud.

Sigamos, ¿cuál es la ventaja de usar FPGAS?, el grado de paralelismo es decir que como
hemos visto todo se hace de manera paralela lo que hace que tengamos una alta velocidad
Dígame ¿más o menos cuanto se demora por ejemplo desde que yo pongo una entrada de
la FPGA y tengo una salida? Depende del canal, depende de la complejidad del camino
que sigamos como sabíamos, una depende de eso y dos depende de la velocidad del reloj
que le estemos poniendo porque le podemos poner un reloj de 50 Mhz pero si le podemos
poner al mismo un reloj de unos 200 Mhz sube la velocidad de reloj y pasa más rápido la
señal ¿y en función de la tarjeta o de lo que tenga los bloques hay una forma a priori de
calcular más o menos en la peor condición que tiempo se demora ? si, si hay como a
través ,las interfaces de desarrollo me permiten verificar los tiempos porque como les
decía en aplicaciones más complejas que dependa , digamos que tenemos 3 bloques
grandes de cosas , bloque 1, bloque 2 y el tercer bloque que es el bloque final depende
de los 2 primeros , el bloque uno no es tan complejo y tiene una salida más pronta porque
no tiene que pasar por tantas compuertas digamos mientras que el bloque 2 es mucho más
complejo y su salida tiene que pasar por unas 100 compuertas y el otro solo por 10
entonces esta salida y esta salida de la cual dependen este tienen que estar más o menos
sincronizados por que como todo es en hardware todo tiene que ir sincronizado par que
no tenga ningún problema, ahí viene la parte de análisis de tiempo ahí sí se puede ver en
el mismo simulador o en la interfaz de desarrollo usted le dice primero voy a trabajar con
esta FPGA , la FPGA tal con eso ya tiene las características de la FPGA y el mismo id
le dice vea el tiempo podremos ir haciendo por partes, que tiempo se demora esto tanto,
se demora este tanto y luego podremos hacerle completa la aplicación, entonces si nos
puede decir cuánto , cual es el análisis del tiempo que podría durar cierto bloque de cosas
que se tiene que ejecutar entonces si podemos tener ese dato.

9
 La asignación de pines flexibles como les decía podemos asignar un pin que sea
una entrada o una salida todos son entradas digitales así que no habría problema
podremos usarlas todas.
 Las interfaces multi-estandar esto de ahí podemos usar en interfaces está el JTAG
que es la interfaz que nosotros utilizamos para hacer la quemada, la programación
digamos de la FPGA es una interfaz completamente estándar utiliza
microprocesadores, las FPGA’S todos los circuitos integrados que tengan que
programarse tienen una interfaz JTAG, asi que un programador JTAG puede
utilizarse para estas FPGAS.
 Reconfigurabilidad y reutilización: como hemos visto al ser programables
podemos crear cualquiera cosa, tiene una gran flexibilidad, es la forma más fácil
de crear un hardware pero realmente son utilizando software.
 Escalabilidad en el flujo de desarrollo: por que decimos esto porque dependiendo
del lenguaje que estemos utilizando si es un lenguaje estandarizado con el VHDL
podemos coger una caso que fue hecha para cierta aplicación y reutilizarla siempre
para otras aplicaciones, que es lo que vamos a ver aquí que vamos a reutilizar
ciertas partes de códigos para poder hacer cosas más complejas.
 Procesamiento en tiempo real: cuando nos indique en tiempo real bueno tiene un
pequeño delay hasta que las señales se propaguen por toda las compuertas lógicas
pero es lo más rápido que se pueda tener sea en procesamiento el FPGA como es
paralelo todo se hace de manera más rápida que un procesamiento que se
secuencial.

CAMPOS DE APLICACIÓN
Bueno ya hemos mencionado algunos, pero bueno aquí tenemos como ya hemos dicho
en procesamiento de señales más que todo en el área de telecomunicaciones es importante
que sea un procesamiento de señal digamos que inmediata.

Podemos implementar interfaces de: interfaces seriales, interfaces VGA’s, interfaces


seriales las r232 podemos ponerle cualquier cosa que nosotros queramos, pero tenemos
que definirlo en software.

Generación de señales de sincronismo: al poder crear señales, podemos sacar señales de


reloj directamente por sus pines digitales así que podríamos crea una señal de sincronismo
para sincronizar digamos varios dispositivos o varios sensores que es lo que indicaba
anteriormente que es lo que se quiero utilizar aquí en un proyecto de investigación de
física sincronismo de sensores para detección de rayos cósmicos que es justo que utilizan
FPGAS y necesitan ayuda en eso.

Técnicas de mitigación de errores en proyectos espaciales: esto de aquí no tengo mucho


conocimiento de cómo se pueda relacionar.
Adquisición y procesamiento de imágenes: como se puede procesar cualquier cosa digital
esto puede procesar audio, imágenes o cualquier clase de dato digital que ingrese como
aquí indicaba el doctor aquí se puede hacer las convoluciones, las ft’s claro todas de
manera con algoritmos de manera digital aquí vamos a poder ver unas aplicaciones: aquí

10
se muestra el uso de FPGA’s en el exterior esta difundido, podemos utilizar para
cualquier clase de dispositivo ya no necesitamos realmente microprocesadores sino que
con FPGA’s podemos hacerlo

Como podemos observar en procesos de manufactura. El otro es puramente aplicación


del uso de FPGA’s

VENTAJAS
Solo necesitamos usar el integrador, saber cuántas unidades básicas tiene y programar los
nosotros queramos y no necesitamos saber que fabricante. El problema es que las casas
fabricantes de los FPGA’s cerraron los compiladores, aunque VHDL sirve para cualquier
fabricante, el compilador que toma este VHDL lo convierte en las rutas lógicas que tienen
que programarse dentro de las unidades lógicas ese compilador que hace ese paso estaba
completamente cerrado y eso es lo que causaba que no pueda difundirse el uso de las
FPGA’s de manera rápida.

GHDL
Hasta ahora se ha visto, el primer capítulo en la parte teórica de las GAL, PLD, FPGA,
los campos de filtración de los FPGA’s, como segundo capítulo lo que se va a ver son los
simuladores y primeros pasos para usarlos. El XILINX, QUARTUS, GTK WEB y
GHDL.

(VIDEO DE DESARROLLO DE PLATAFORMAS LIBRES): Gonzales, J. [Juan


Gonzales Gómez]. (2017, Oct 24). Electrónica digital para makers con FPGAs
libres (3/31). Recuperado de https://www.youtube.com/watch?v=X0tTh7tYOZg

COMENTARIOS DEL VIDEO SOBRE GHDL


Descripción
Las placas de los fabricantes tienen todos estos componentes internos, además de un
medio secreto y por lo tanto los compiladores también, la única manera para poder crear
el compilador y poder tener estos ID’s nuevos es por el trabajo realizado durante tres años
por estos desarrolladores. El problema es que como cada fabricante es diferente este
compilador nos sirve solamente para el FPGA IC40, las otras siguen siendo cerradas
completamente y necesitamos las licencias para poder programar las FPGA’s de más alto
nivel, las otras FPGA’s de bajo nivel como las que tenemos aquí, los cyclones de familia
4 o posteriores son las que permiten de manera libre su programación a través de los ID’s
de desarrollo de los fabricantes.

Ahora son placas de desarrollo las que tiene soportado ICESTUDIO que es el líder de
desarrollo libre, otra cosa que podemos destacar es el bajo costo de estas tarjetas de
desarrollo, 20 USD cuesta la tarjeta de desarrollo que se muestra en el video y también
depende de donde la compren, en el exterior tienen bajo costo.

Aquí en el país lamentablemente y debido a que los vendedores de electrónica deben


importar el precio sube a los 120 USD, los dispositivos que son baratos tienen un alto
costo aquí y no se pude hablar de las grandes tarjetas de desarrollo como las que tienen

11
VIRTEX, ya que estas tienen un alto costo. Vamos a ver en el video que estas pequeñas
FPGA’s con pequeñas capacidades pueden ser usadas para cosas medianamente
complejas

Además, lo que se puede recalcar del video es que todas estas placas y sus componentes
tienen un PCB creado que es completamente libre; se puede bajar eso, crear su propia
placa o también existe la opción de apoyar a los desarrolladores comprando la placa. Las
placas vistas en el video que fueron desarrolladas por la competencia de Madrid son
libres, lo que nos da opción de tomarlas y seguir haciendo las mismas o tomarlas como
base para crear nuevas placas de desarrollo.

Dispositivos
ICOBOARD. Dispositivo que sirve para sintetizar hardware los entornos de desarrollo
solo corren Intel y como mucho se puede generar limit stream pero no se puede sintetizar
directamente desde una BlackBerry la icoboard si lo puede hacer por lo cual se pueden
generar cosas sumamente interesantes

Olimex ICE40HX1K-EVB. con un costo de 22 euros

12
MyStorm blackice. (Muy usada en Reino Unido La cual tiene una latix de modelo 4k está
entre las medias de las que tiene 1k y otras que tiene 8k en esta caben más de un Arduino
y tiene un procesador ARM.

IceZum
Es una placa que tiene el mismo tamaño que un Arduino 1 de hecho es un diseño derivado
de un Arduino, se le ha quitado el procesador y se le a implementado una FPGA libre una
Ace 40 con el modelo mas pequeño que hay que es la de 1k el mismo que tiene el
AceSteck, tiene 8 leds para poder visualizar los bits, 1 conector micro USB para ser
alimentada a través de la computadora o también se le puede alimentar de manera
autónoma a través de una batería mediante un conector que se encuentra alado de este.
Tiene un interruptor para subir y apagar los periféricos pero manteniendo encendida la
FPGA de manera que al conectar un robot si le hemos metido en algún circuito lo
podemos desconectar y podemos seguir cargándole circuitos pero los conectores van ha
estar apagados, se alimenta entre 6v y 17v, el regulador puede dar hasta 3A lo cual esta
bien ya que puede alimentar todo tipo de circuitos, es compatible con Arduino es decir
podemos meterle chips de Arduino, En la parte derecha tiene 4 canales que van alimentar
mas de un chip analógico digital los cuales envían información a la FPGA, todos los pines
están replicados en la parte superior con conectores de tipo macho para conectar de forma
muy sencilla los distintos periféricos

13
Eladio Delgado (Autor de la placa)

Dicha persona desarrollo el Ace estudio con personas especializadas de la Universidad


Complutense de Madrid

La Ace estudio utiliza la misma FPGA que la Latix 40 pero en diferentes versiones de
capacidad de unidades lógicas

Los esquemáticos de las FPGA están completamente libres es decir para el acceso al
público para replicar o cambiar a la manera que otro diseñador desee.

El Ace estudio no es tan potente como los IDES de desarrollo de Quartus en cuanto a la
parte de verificación de tiempos o el uso de VHDL de manera directa. El Ace estudio está
elaborado más para alentar a las personas, estudiantes a utilizar FPGA para usar circuitos
digitales, la interfaces de desarrollo se basan en diagramas de flujos que están
representados en pines que muestran el 0 y el 1 dependiendo de cómo se desarrolla el
diagrama de flujo a través de bloques de decisión, bloques para imprimir, bloques para
iniciar y finalizar a través de LUBS, la desventaja es que es muy básico para cuando se
elabora algo más preciso y complejo

Herramientas de software para programación de VHDL


Descargar la carpeta GHDL/GTKWave

GHDL es el compilador y simulador (la ventaja es que todo lo que ocuparemos sirve para
una computadora de muy bajos recursos técnicos como un Intel o un Celeron) ya que

14
trabaja en una mediana complejidad, todo esto se opera a través de la consola, para poder
mostrar el resultado de las simulaciones utilizamos el software GTKWave.
Como primer paso copiamos la carpeta GHDL y la pegamos en el disco C.
Para poder ejecutar a través del CMD necesitamos que el ejecutable se encuentre dentro
de las variables de entorno de Windows.

Dentro del material existe un README, en el cual se encuentra la documentación, las


páginas de wiki, las fuentes donde se encuentran las actualizaciones del GHDL.

Hay dos formas de poder poner en la parte de las variables de entorno en el computador
para poder ejecutar en cualquier parte del CMD, la más fácil es ejecutar un archivo.mat,
el inconveniente es que el los archivo presentados en el material presentan falencias, y la
otra forma se la puede realizar de manera manual.

Dos elementos del hardware no podrían llamarse de la misma manera, por ende, se suele
escribir el nombre del archivo con el nombre de la entidad, de esta manera se puede
conocer que dentro de este archivo se está desarrollando el código para describir ese
dispositivo, pero puede ser cualquier nombre, el nombre del archivo por ejemplo
And_Gate y es no daría problema en la compilación tanto en GHDL como en cualquier
otro compilador, lo que, si tiene que verificarse, es que el nombre sea único.
El segundo archivo se lo a colado el nombre de And_Gate_TB, las siglas TB representa
que el archivo a tratar es un TEST BENCH, este Tb permite simular y dar unos valores
de entrada al dispositivo que queremos probar, el dispositivo a probar es el And_Gate,
entonces para probarle sin tener un hardware en cual nosotros quemar y mandar
directamente a través de pulsadores o alguna señal externa señales a esta compuerta And
que hemos creado, lo que se utiliza es el Test BENCH, lo que hace es lo siguiente:

A través de las variables permite dar valores a las entradas A, B y C que se tenía y le
dice por tantos nanosegundos se tendrá los valores de 0 en A 0 en B 0 en C, aquí hemos
hecho una de todas las posibilidades que hemos podido y esto lo que va hacer es alimentar
a la compuerta And y mi compuerta And me va a ofrecer una salida y al final esa señal
de salida es la que nosotros vamos a poder ver en la realidad de cómo se comporta mi
dispositivo que acabo de crear, más detalles de cómo se puede hacer test Bench se podría
ver más adelante, y realmente el código, una explicación más destallada de código VHD
para crear dispositivos vamos a ver en las siguientes clases, ahorita como solo estamos
viendo compiladores vamos hacer una introducción de que hace cada uno de los archivos,
los Test BENCH tienen una aspecto importante, el Test BENCH no es necesario realizarlo
en Quartus para nada, en GHDL y en el Sylings para hacer simulaciones sí. El Quartus
me permite dar directamente valores a las entradas, digamos dibujar la señal que
queremos tener a las entradas, en este caso una señal a la entrada A. B, C, y con las señales
dibujadas se simula y se crea la señal de salida. En el sylings para comenzar la simulación
se necesita crear un test bench el sylings nos da la ventaja que solo se crea un esqueleto
del test bench, y nosotros tenemos que ponerle las señales de manera manual, tenemos
que escribirle las señales de entrada y salida que utilizaremos para la simulación.

15
Dentro del material preparado también se tiene un README, en el README se tiene el
código GHDL que se podría utilizar para pequeñas futuras simulaciones en VHDL que
se quiera realizar, si no se cuenta instalados simuladores como son el Quartus o el sylings
. En este README se encuentra una manu indicando cuales son los pasos necesarios
para; primero de analizar la sintaxis que es lo que los IDS nos dan de manera gráfica, en
este caso como es de consola se analiza a través de un comando y nos envía como
respuesta que es lo que está mal. También indica dos cosas importantes que tenemos que
hacer antes de realizar un GHDL, para esto tenemos que ejecutar dos comandos en la
consola que queramos que se ejecute el GHDL, lo que hace estos comandos es enlaza las
librerías para analizar el código, tener en cuenta de no copiar con el signo de dólar ya que
esto nomas indica el comienzo de la librería, al ejecutar se demora un poquito en enlazar
todo.

Lo que dice es fghdl gilmart el nombre del archivo, entonces para no tener que escribir
todo el nombre del archivo que podríamos hacer, ingresar a la carpeta de código prueba,
estamos dentro de la carpeta del código prueba y vemos que ahí estan nuestros dos
archivos el And_Gate.vhd y el And_Gate_tb.vhd, entones verifiquemos solo asi ghdl-a
ponemos la a y podemos dar tabulador para que se autocomplete y aparece todo el nombre
que queríamos ghdl.vhd damos enter y si no nos da nada es que está bien veamos qué
pasa si es que yo daño el archivo, ya voy a dañar, a ver, voy a dañar el archivo para ver,
código prueba y le voy a dañar, voy a poner digamos que me equivoque y que aquí yo le
puse 1 y que aquí no le puse el mismo nombre debería ser and_gate1 and_gate1 and_gate1
pongamos ctrl+s, le voy otra vez a analizar la sintaxis y salió nuestro error, y sale nuestro
error no dice en la línea 13 en el espacio 5 está mal escrito and_gate1 se esperaba
and_gate1, veamos en la línea 13 espacio 5 veamos acá, en la misma nos dice que de aquí
en adelante en este espacio se esperaba angey1 entonces de esa manera es la que nos va
dar los errores.

De una manera muy similar, pero en un entorno grafico nos darán los errores los otros
simuladores, exactamente igual es línea espacio, entonces le voy a corregir solo era para
demostrar que este de aquí si nos puede dar una verificación de errores y le voy a dar
enter para que ya quede analizado esto, de una vez voy a hacer el otro And_Gate_tb.vhd
el tech bent listo, tenemos los dos analizados sus sintaxis, veamos que más dice nuestro,
talvez hubo algún problema, a ver veamos…

QUARTUS BÁSICO
Primer capitulo
Funcionamiento de placas FPGAs libres, herramientas que han desarrollado se necesita
una licencia Ciclón de la familia 4 es unaa herramienta libre para crear, existen
aproximadamente 600 placas.

La Icezum Alhambra y otras placas con FPGAs libres, se pueden utilizar en esquemas
abiertos y está disponible toda información a nivel de electrónica general es decir todas
sus partes internas, para que un programador lo sepa a detalle, si es de información pública
se dice que es una FPGAs libre.

16
Actualmente las últimas FPGAs libres que hay son de la familia ICE40 Lattice y
desgraciadamente no son libres, pero no por culpa del fabricante, sino que la
documentación estaba disponible públicamente, Clifford Wolf a través del proyecto
IceStorm hizo ingeniería inversa y público toda la información estuvo tres años sacando
toda la información interna, y una vez publicado creo herramientas libres, que puedan
crear un software para facilitar su uso, como Icestudio.

Ahora veamos las distintas etapas de Icestudio podemos observar varias placas
seleccionando placa y se puede ver todas las placas que en la actualidad existen o las
normalmente soportadas por Icestudio la idea es colocar documentación para que
cualquier persona pueda introducir más placas.

Una placa es la Lattice Icestick esta es la placa que utilizó Clifford Wolf para hacer
ingeniería inversa, de la familia ICE40HX-1K y por eso es una pieza de coleccionista: es
la primera placa en la que se sintetizó hardware usando sólo herramientas libres su precio
es de $20.

Otra placa considerada la más grande de 8PGA Lattice Breakout Board precio de $43
procesadores de gama libres, Nandland Go Board placa americana su precio de $60
tiene 4 leds verdes, 2 displays de 7 segmentos, 4 pulsadores, 1 conector VG, Kéfir I autor
Salvador E. Tropea Instituto Nacional de Tecnología Industrial, Argentina Icoboard
puede sintetizar hadware SRAM 8Mx16, 3 leds 2 pulsadores.

Hay otras placas que aún no están soportadas por Icestudio pero que desean que lo estén
Olimex iCE40HX1K-EVB valorado en 22 euros otra Mystorm BlackIce SRAM
256Kx16, 6 LEDs, 3 Pulsadores modelo ICE40Hx4K.

La placa que se va utilizar también para los robots autónomos y cargar circuitos 8 LEDs,
2 pulsadores, 4 canales A/D , Hardware libre, compatible arduino se utilizara en muchos
tutoriales, Eladio Delgado Eladio vive en Pinos del Valle, un pueblo de la provincia de
Granada, de 700 habitantes, desde allí hace todos sus diseños, su casa es conocida en el
ambiente maker como el Rural Workshop

Kicad la Icezum Alhambra es una placa libre. Todos sus ficheros fuente y de fabricación
están disponibles, la versión 1.0 la hizo Eladio en Altium y yo la migré a Kicad, que es
una herramienta libre de diseño de PCBs, impulsada por el CERN la organización
Europea de Investigaciones Nucleares.
La versión actual es la 1.1, que tiene unos ligeros cambios y correcciones, y se hicieron
también con Altium, y están pendientes de migrarse a Kicad pero el fichero fuente en
Altium y los ficheros de fabricación Gerbers, para ver el esquema, clonamos el repositorio
del github en nuestro ordenador.

Nos vamos a la carpeta src-kicad y abrimos el fichero icezum.pro con Kicad, se nos abre
la ventana principal de Kicad, con el proyecto de la placa, en la parte de la izquierda,
hacemos doble click en el elemento icezum.sch para ver el esquema, nos aparece
primero la hoja índice.

17
Se nos abre la ventana principal de Kicad, con el proyecto de la placa, en la parte de la
izquierda, hacemos doble click en el elemento icezum.sch para ver el esquema, nos
aparece primero la hoja índice podemos pinchar en cualquiera de los 6 bloques para ver
los detalles, y curiosear lo que queramos, para volver a la hoja índice pinchamos en el
icono Leave sheet de la parte superior placa de circuito impreso.

Para ver el diseño de la placa de circuito impreso (PCB) hacemos doble click
en icezum.kicad_pcb en la ventana principal de Kicad También podemos obtener
el modelo 3D de la placa, para ello nos vamos a View/3D Viewer y se nos abre una
ventana con el modelo virtual de la placa, movemos rotar y desplazar la cámara para
observar los detalles de la placa.

FreeCAD es una aplicación libre de Diseño 3D , todos los componentes de la Icezum


Alhambra se han modelado con Freecad, y están disponibles en la biblioteca de piezas
de Freecad, en Github, no sólo disponemos de los modelos para usarlos en nuestras placas,
sino que tenemos los ficheros fuentes para aprender cómo están hechos.

En este enlace podemos encontrar una tabla con todos los componentes y sus ficheros
fuente podemos descargar cualquiera de ellos y abrirlo con Freecad, por ejemplo, vamos
a ver el conector micro-usb, descargamos el fichero USB-micro-B.fcstd existen
algunos accesorios 3D libres para imprimir.

Para la Icezum Alhambra, diseñados con FreeCAD Soporte para la Icezum Alhambra,
con y sin las letras de FPGAwars soporte con protección de Antonio Andújar Soporte
para la Icezum Alhambra con protección de cortocircuito

Mediada complejidad los resultados de las simulaciones que tengan web GHD de toda la
carpeta le copiamos y nos vamos al disco c y debe aparece GHDLL para poder utilizar el
ejecutable se encuentre en Windows remi está todo lo necesario se puede ver la
documentación donde se encuentra las páginas de wiki y actualizaciones del GHD
variables de nuestro entorno uno es la parte donde se va ejecutándose toca realizar de
manera manual poder abrir variables de entorno buscamos PATH variables de entorno.

18
Estructura física de la FPGA
La fig. 1 muestra la FPGA que se tiene en el laboratorio de sistemas digitales.

Fig. 1 FPGA Cyclone IV

Antes de poder usar y programar la FPGA, primero necesitamos energizarla y para ello
usamos el cable celeste que se puede observar en la fig. 1 en la parte superior derecha.
Este cable tiene dos usb, en el un extremo tenemos un usb común que va conectado a la
computadora, mientras que en el otro extremo hay un usb tipo b, este se conecta en el
puerto que está a lado derecho del botón rojo de la FPGA.

Luego de alimentar la FPGA, tomamos el usb blaster que se puede observar en la fig. 1 y
2, este dispositivo usa dos cables. Uno de ellos de color negro que tiene en un extremo un
usb normal que va conectado a la computadora y el otro extremo que va a este usb blaster,
el otro cable es un bus que igualmente un extremo va al usb blaster mientras que el otro
se conecta a la interfaz de la FPGA llamada JTAG.

Una vez realizada estas acciones, presionar el botón rojo que se mencionó anteriormente
para encender la FPGA y comenzar a usarla para programar.

Nota: Una vez encendida la FPGA, comenzará a titilar los 4 leds que tiene. Por lo que no
debe preocuparse, esto es un estado por defecto.

Estructura lógica de la FPGA


Por medio del programa Quartus, se ha realizado la programación de una compuerta AND
de tres entradas. Sin embargo, nunca se especificaron los pines de la FPGA que se van a
usar, para ello damos click en la pestaña ASSIGNMENTS y buscamos la opción PIN
PLANNER, damos click en esta y se abrirá una nueva ventana que se muestra en la fig.
4

19
Fig. 4 Ventana pin planner

Como se puede observar en la fig. 4 nos aparece un modelo con todos los pines que posee
la FPGA (del modelo que hayamos escogido) y en lado inferior aparecen todas las
entradas y salidas del programa que hayamos realizado. Es importante aclarar, que para
que aparezcan están variables de entrada y salida se debe compilar por lo menos una vez
el código, ya que caso contrario el programa no sabe de la existencia de estas variables
creadas y nos las muestra.

Luego debemos localizar cada unas de estas variables a un pin específico de la FPGA,
pero hay un inconveniente los botones y switches, con los que cuenta la FPGA, ya están
rooteadas a pines específicos y por ello debemos pedirle al fabricante como están hechas
estas conexiones. Estos dos documentos por parte del fabricante se entregarán en el
laboratorio. Uno de ellos un PDF que muestra todos los componentes que están
conectados a la FPGA. Nos centraremos en la parte donde se encuentran los leds, botones
y switches.

En esta parte aparecen los leds con sus respectivos nombres en la FPGA para poder
diferenciarlos. Estos leds están conectados de tal manera que al ingresar un cero lógico
se prenden con el fin de evitar sacar corriente a la FPGA. Entonces para que funcione con

20
una lógica positiva, debemos negar la salida de nuestro código para que cuando
ingresemos un uno lógico los leds se enciendan. Por último, también se puede observar
las conexiones del dip switch y pulsadores, estos se encuentran conectados a unos pines
llamado KEY y por lo tanto están en paralelo. Entonces para que funcionen solamente los
pulsadores o botones, tenemos que poner al dip switch en estado ON (para funcionen los
pulsadores como tierra).

Se debe tomar en cuenta, los elementos se los conecta a los nombres de los mismos, pero
en el Quatus para el pin planer solo se tendrán números por ejemplo pin 33, 21, 31 y 11.
Para poder asosiar los nombres de la FPGA a los números de Pin se deberá abrir el Excel
que se encuentra en la misma carpeta, en esta carpeta se muestra la asociación del nombre
y el número de pines. Se puede ver asi que el Key1 es el pin 88 y el Key2 el pin 89

Entonces, si usamos los tres primeros estarán en el 88, 89 y 90 y esto se colocará en el


pin planner.

Para colocarlos se usará el mouse, haciendo doble clic sobre la columna “location”.
Haciendo esto aparecerá un cuadro de texto para ingresar el número de pin, se escribirá
como ejemplo de la siguiente manera “PIN_88” y así el resto de pines. Ingresamos
también los leds que será el pin 85.

En ocasiones si no se ingresa la dirección de los pines en el “pin planner” entonces por


defecto se enviaran los pines que el programa ingresa por defecto, como esto como ya
existen algunos pines conectados a algo dentro de la FPGA, como por ejemplo el
BUZZER, este comenzara a sonar.

Una vez hecho esto se cierra y se compila nueva mente para que se creen nuevas rutas
hasta los pines nuevos ya ingresados.

Luego de que se termine de compilar estará listo el programa para ser quemado en la
FPGA (recordando conectar correctamente el quemador y la fuente a la PC), es
importante si se ve que el led del quemador se pone de un color diferente al que debe

21
tener, desconectarlo de la PC y de la FPGA ya que indica que esta quemado y puede
reiniciar la PC.

El proceso de quemado del programa se lo realizara en la pestaña con el icono que dice
“programer”. Se abrirá una nueva ventana como se muestra en la figura.

Al momento de que esté conectada la FPGA, en el cuadro de Hardware se mostrara “USB


Blaster”, si no está escrito esto entonces se deberá hacer clic en el botón “Hardware
Setup” y en la pantalla que aparezca deberá salir “USB Blaster”.

En caso de que no aparezca quiere decir que el driver no está instalado y se tendrá que
instalar, este driver está dentro de la misma carpeta que el Quartus.

22
Una vez se vea que los datos están correctos se podrá hacer clic en “START” para pasar
el programa a la FPGA, si todo funcionó correctamente saldrá en la parte superior derecha
una barra con un 100% verde.

Luego de esto se puede ver si funciona el programa en la FPGA, en el programa


implementado para el ejemplo se ve que si se suben los tres “dip Switc” se apagan los
leds, y si se bajan los tres se encienden los leds que es la manera en que funciona la
compuerta AND.
Estos serían los pasos a seguir para poder crear un programa básico en Quartus y la FPGA.

Sintáctica de VHDL
Elementos sintácticos del VHDL
 Comentarios
Se inician por un doble guion medio (--)

 Símbolos especiales
Son operadores lógicos (<,>, =), de asignación (<=,>=) y símbolos matemáticos (+, -, /,
*, **)

 Números

Se representan en base 10, se pueden expresar en otra base anteponiendo el símbolo de


numeral, y por el frente la base y terminándolo en numeral, por ejemplo: 2#1100#
(binario), 8#CF3A# (hexadecimal).

 Caracteres
Se representan entre comillas simples, por ejemplo ‘1’, ‘a’ toma el valor ASCII que
representan esos números.

 Cadenas
Se representan con comillas dobles, pueden ser de texto o de números binarios.

 Cadenas de Bits
No necesariamente se debe convertir a binario ya que puede estar sujeta a la siguiente
notación: B”1110001”, también puede estar representada de la forma octal representada
por la letra O, o hexadecimal con la letra X.

Identificadores de las entidades


Son cadenas de caracteres para identificar una variable, señal, proceso o también una
entidad.

Reglas
 No importa si está escrito en mayúsculas o minúsculas
Salida=SALIDA

23
 Los nombres pueden contener números, pero no puede empezar el nombre de la
entidad con un número.
78N(Incorrecto),
N78(Correcto)
 Los nombres pueden tener un guion bajo, pero no puede empezar con guion bajo
y no se pueden tener dos guiones seguidos a la vez en el mismo nombre de la
entidad.
Multiplicador_bits. (Correcto)
_multiplicador. (Incorrecto)
 Los nombres no pueden tener caracteres especiales.
Multiplicador & suma (Incorrecto)

 No se puede usar como identificador una palabra reservada por VHDL.

Palabras Reservadas
Son aquellas palabras que tienen un único significado en todo el lenguaje VHDL, realizan
alguna operación o sirven para iniciar alguna sección del código de VHDL.
TABLA I. Tabla de variables reservadas por VHDL

Operadores y expresiones
 Lógicos
Actúan sobre tipos de datos bit, bit_vector,, std_logic, std_logic_vector y boleanas. El
tipo de datos se da de acuerdo a las versiones. En el caso de utilizar este tipo de operadores
en un vector la operación se realizará bit a bit. Son:

24
NOT, AND, OR, NAND, NOR, XOR, XNOR, cada una tiene una precedencia siendo el
número más bajo el de mayor precedencia.
Se recomienda usar std_logic, std_logic_vector

 Aritméticos
Los operadores aritméticos como el exponencial, valor absoluto, multiplicación, división,
modulo, sumas, restas, etc., tienen una presencia específica y un símbolo de
representación, en el caso del signo de sumas y restas tienen 2 significados, o bien
representa un número positivo o la operación de sumar, al igual que la resta representa un
número negativo o la operación de restar, esto depende de cómo se exprese en el código.

 Relacionales
Por ultimo tenemos los relacionales que al igual que las operaciones lógicas, tienen un
valor de TRUE o FALSE, esto es lo que arrojan además tienen una precedencia de valor
4, entonces podemos decir que la de mayor precedencia es la compuerta NOT, luego
vienen las relacionales y luego todo el resto de operaciones lógicas normales y corrientes.

 Desplazamientos
Se pueden hacer sobre los STD_LOGIC_VECTOR que son los arrays de bits,
dependiendo de la operación en las diapositivas se puede observar un ejemplo del
funcionamiento de cada una de las operaciones además de su símbolo representativo.

Por ejemplo, el SCL es un recorrido lógico hacia la izquierda, si tenemos la variable X


que es un vector de bits y le aplicamos el SCL de esta forma X SCL 4 le estamos diciendo
que se recorran 4 espacios hacia la izquierda tomando todo el valor de los 4 bits más
significativos de la variable y se reemplazan por ceros.

En el caso del Shift Left Arithmetic el cual hace un movimiento hacia la izquierda
aritmético, pero ahora se replica el ultimo bit de los bits más significativos, el SRA hace
lo mismo solo que replica el bit más significativo del lado izquierdo.

Por ultimo tenemos el Rotate Left que toma los 4 primeros bits y los pasa a la última
posición, el ROR hace lo mismo, pero toma los 4 últimos bits y los mueve a las primera
posiciones.

 Concatenación
Si se desea concatenar 2 vectores o un vector con un bit, esto se lo realiza con la operación
&, por ejemplo, tenemos 2 vectores A y B de diferentes longitudes, si escribimos
C<=A&B, con esto asignamos a C un valor de mismo tipo de A y B y de magnitud tal
que pueda guardar A y B. Si C tiene una longitud diferente a la suma de A y B debemos
colocar una especificación de en qué posiciones debe guardarse A y B.

Tipos de Datos en VHDL


Se clasifican en 2 grandes grupos, los predefinidos ya por el lenguaje y los que el usuario
pueda definir, como advertencia el usuario debe saber cómo definir el tipo de datos, que
tipo de datos están permitidos, como especificarlos y cómo usarlos, ciertos tipos de datos

25
permiten la operación entre ellos y otros no, por ejemplo, sobre datos de tipo
STD_LOGIC se puede hacer operaciones lógicas, pero no de tipo aritméticas, pero se
puede hacer un casting a este dato de tipo STD_LOGIC se convierta en algo parecido a
un dato de tipo entero y con eso hacer una operación aritmética sobre él y luego regresar
al tipo de dato original.

Como decíamos al inicio VHDL tiene 2 categorías de tipos de datos, en los predefinidos
que son parte del lenguaje y se encuentran en las bibliotecas, todas estas bibliotecas se
derivan de la IEEE, ya que la IEEE es la que documenta y da soporte a VHDL, la
biblioteca revisada es la 1164, la cual nos permite hacer operaciones lógicas, relaciones
y concatenación, las operaciones aritméticas están dadas por otra librería, la numeric
estándar, también debemos saber que existe una librería antigua llamada estándar logic
aritmetic la cual no se debe usar ya que son muy antiguas, por ultimo tenemos el tipo de
datos creados por el usuario los cuales son para casos especiales, se basan en los
predefinidos para crear algún tipo de dato especial por ejemplo, una matriz de 2 o 3
dimensiones de tipos de datos std logic vector o de algún otro tipo.
Los tipos de datos que incluye en VHDL son:

o Tipos enumerados predefinidos


o Tipos enumerados definidos por el usuario
o Tipos de vector de bits
o Tipos de enteros
o Tipos de arreglos multidimensionales
o Tipos de registros

Arquitecturas
 Funcional
 Estructural
 Flujo de datos

Las diferentes matrices con diferentes dimensiones y tipos de registros que eran conjuntos
de datos de diferentes tipos, no solamente INTEGER, puede ser un INTEGER en un
digamos que una fila de cosas, sería un Integer con una cadena de caracteres y un
booleano, ese sería un tipo de dato tipo registro, entonces:

¿Cómo se les puede clasificar?


Para ayudar a entender los tipos de datos se les ha clasificado como:

Por la fuente de declaración, que hemos visto que son los predefinidos y los definidos por
el usuario o dependiendo de la naturaleza de sus elementos, que pueden ser los tipos
numéricos. Estos tipos numéricos pueden ser: de punto fijo o punto flotante, es decir, se
puede usar también floats y punto fijo serían los integer, y acorde al número de elementos,
pueden ser elementos escalares, un solo elemento, es decir que tiene un solo bit o un solo

26
carácter, por ejemplo: para un tipo char y tipos compuestos, es decir, que incluyen las
categorías llamadas tipos array o arreglos que tiene una colección de elementos del mismo
tipo. Y un tipo record, colección de escalares y/o arreglos de elementos que pueden ser
de diferentes tipos.

También puede ser otra clasificación dependiendo del número de bits que tengan: escalar
para un solo bit, array de una sola dimensión para un arreglo que tenga un solo número,
un solo arreglo de bits; ó 1D por 1D es decir una pila de vectores uno sobre otro, es decir
tenemos ahí por ejemplo una variable que tiene asignado dos vectores y que tendría dos
índices, uno para identificar la fila y otro para identificar la columna. También tenemos
arrays de 2 dimensiones, por ejemplo, ahí podemos ver y un bloque de 3 dimensiones, ahí
podríamos ver como se vería gráficamente esto, un escalar, una dimensión, una división
por una dimensión, es decir, tenemos un array, un array y un array del mismo tipo o de
dos dimensiones que cada elemento está colocado en un puesto completamente solito el
elemento, y el de 3 dimensiones, bueno, el de una dimensión sería en 3 conjuntos,
digamos, estaría una dimensión cada uno de ellos y al final, el de 3 dimensiones que sería
el compuesto entre 1D, 1D y 1D y uno de 2D, ya vamos a ver uno ejemplos de cómo
hacer uno de ellos.

Acorde al paquete de origen, los tipos estándar, los tipos estándar lógico, los con y sin
signo, y los de punto flotante. Ahí podemos ver de dónde salen las librerías, los tipos
estándar son las librerías o las bibliotecas que comienzan con STAND STD; los tipos
estándar lógico vienen dentro del paquete 1164 que era la librería que vimos el día anterior
que salió a partir del 93 que es un paquete de la biblioteca IEEE. Las con y sin signo, que
viene parte del estándar LOGIC ARITHMETIC que le decíamos que este era el paquete
antiguo y también tenemos el estándar NUMERIC que también tienen las operaciones
con y sin signo, que son equivalentes pero la estándar LOGIC ARITHMETIC es más
antigua; y la de tipo fijo o flotante que vienen en esos dos paquetes, estos dos de aquí no
vamos a ver, ya que vamos a ver que necesitamos paquetes adicionales para colocarle
dentro de los binarios, digamos, del VHDL para que funcione el paquete flotante o el fijo.

Los tipos de datos estándar, como vimos es el bit, aquí en este ejemplo podemos ver, esta
de aquí es la definición de un bit, le decimos tipo bit puede ser 1 o 0, esta es la definición
como está en el VHDL y de esta misma manera podemos nosotros definir nuevos tipos
de datos. De la misma manera ponemos tipo, ponemos el nombre luego ponemos IS y le
decimos qué puede ser; podríamos ponerle tipo alfabeto es y aquí podríamos poner los
caracteres del alfabeto normal que usamos nosotros (a, b, c, d,…, z) y ese tipo de dato
sería un tipo de dato definido por usuario; este de aquí es un tipo de dato predefinido,
porque esta partecita de aquí ya viene en el VHDL definido, que el bit solo puede tomar
un número 0 o un número 1 como bits. En el ejemplo que vemos aquí, podemos ver que
estamos creando 3 señales: señal A, señal X y una señal Y. Todas estas señales a través
de este “:”, le estamos diciendo que va a ser de tipo bit, entonces A, X y Y son del tipo
bit, por lo tanto, aquí le estamos diciendo, X qué valor va a ponerse, le vamos a poner el
valor de un bit o bit 1, bit en 1, le asignamos a X; y acá le estamos diciendo que le estamos
negando A y le asignamos a Y. Como las 3 variables son del mismo tipo no habría

27
problema en hacer esto de aquí, esta operación NOT sobre un tipo bit si hay como hacerlo,
como dijimos es un tipo bit o un estándar LOGIC, podemos hacer una operación lógica y
este de aquí como también es del mismo tipo del resultado de este de acá no habría
problema; entonces, que nomás podemos ver aquí en este ejemplito chiquito. Podemos
ver que este símbolo de “<=” es la forma de asignar un valor a una señal, también de esta
manera podemos asignar un valor a un PIN de entrada o a un PIN de salida, y vamos a
ver que las variables no podemos ponerlas así porque las variables al ser de un distinto
tipo de objeto tenemos que hacerlo con otra clase de asignación de valor, entonces
“<=”solo sirve para señales y sirve para los pines de salida.

Los BIT VECTOR, como decíamos el bit vector es un array de bits, es un vector formado
por elementos tipo bit; soporta operaciones lógicas, de comparación, de corrimiento y de
concatenación. Como hemos visto, todas las operaciones que vimos en la presentación
anterior, pero no soporta las sumas ni las restas, ni todas las operaciones aritméticas. La
definición dice que el tipo BIT VECTOR es un arreglo (qué significa esto de NATURAL
RANGE, primero NATURAL también es un tipo de dato predefinido por VHDL que
significa que es un número entero no negativo).
Estaría expresado al revés, lo normal y lo que he visto es que solo se utiliza el DOWNTO
ya que es más intuitivo para el programador ya que es como nos enseñan a escribir un
número binario a mano, lo que si ser recomienda es que si comenzamos a usar el
DOWNTO o el TO, desde un principio tenemos que mantener la misma forma de
expresión de todos los vectores, ya que si en algún rato cambiamos todas las operaciones
van a tener que cambiar, eso nada más.

El tipo de dato booleano, puede tener TRUE o FALSE, en termino de número de bits es
un escalar ya que solo puede tener true o false, es decir un 1 o un 0, soporta solo
operaciones lógicas y de comparación, nada más. Se está creando una señal llamada
READY que es del tipo booleano y le estamos haciendo una operación WHEN ELSE
(está operación será vista en la arquitectura FLUJO DE DATOS), solo para adelantar dice
que X (señal anterior) del tipo STD_LOGIC_VECTOR porque va a tomar el valor de 111
solo cuando READY (del tipo booleano), es decir cuando sea TRUE; caso contrario X va
a tomar el valor de 000, ese es un condicional para flujo de datos, ¿Por qué se dice que es
de flujo de datos? Porque toda la línea está ejecutada en un solo tiempo, si tuviéramos
otro WHEN ELSE en la línea siguiente de otra cosa, los dos WHEN ELSE se estarían
ejecutando al mismo tiempo, sería como un camino en las NAND o en las AND, una línea
sería como un camino a la salida y el otro WHEN ELSE sería otro camino hacia otra
salida y los dos se estarían haciendo de manera paralela. El valor de X cambia de 000 a
111, cuando READY es igual a TRUE.

El tipo de dato INTEGER, como les decía esto va de 32 bits, de -2^31-1 a 2^31-1, este de
aquí soporta operaciones aritméticas y de comparación; la definición dice que el
INTEGER puede ser de -2^31-1 a 2^31-1. Aquí podemos encontrar que existe los
atributos de INTEGER, por ejemplo, el LOW y el HIGH, también todos los tipos de datos
tienen atributos. Las señales, digamos que es una señal tipo bit tiene también el atributo
evento que nos indica cuando el bit cambio y nos permite verificar, una operación cada

28
ves de cambia el reloj y este está justo en el pin de entrada, el bit de entrada se llama
clock, si clock coma evento sucedió y clock es igual a uno, significa que el flanco que
estamos observando para una operación es el flanco de subida porque estamos esperando
que sea 1 y que clock cambie, esperamos de cera a uno para que cambie, si queremos el
flanco de bajada lo único que tenemos que cambiar es que clock debería ser igual a cero
y con eso estamos esperando un cambio y que clock termine siendo cero, estos atributos
vienen escritos luego de una comilla simple, este atributo me permite poner el limite bajo
este número negativo de aquí, y el limite alto nos estaría expresando el numero 2 millones,
aquí viene una nota importante debido a que si nosotros solo definimos una señal tipo
contado es igual a inger, ¿cuántos bits estarían yendo a ese in?, si lo definimos sin colocar
un rango va a utilizar lo que 32 bits para representarlos, tenemos un entero pero no nos
dice de donde a donde por lo tanto debería ser toto el límite de negativos a positivos y ese
seria un desperdicio de espacio y nosotros solo querremos contar hasta el 10, entonces lo
que nos indica aquí es que tenemos que definir un rango, si queremos contar hasta 10
tenemos que poner la señal contador de tipo i del cero al 10 y con esos estaríamos por
ejemplo en la señal A si solo va a contar del cero al 15 va a ser de un rango del 0 al 15 y
va a ocupar solamente 4 bits y de la misma manera los demás ejemplos, aquí podemos
ver que A mas B se pueden sumar pero el lo toma como un numero entonces no
tendríamos una restricción como lo teníamos antes en las operaciones lógicas de los
vectores ya que debían ser de la misma longitud , aquí tenemos 2 números de diferente
longitud que ocupa en el espacio pero son tomamos como números por lo tanto solo se
nos suman sin restricciones

¿Qué pasa si el total de la suma de los números excede el espacio? No lo tenemos que ver
como un espacio sino más bien como un número que x debe ser mayor o igual a estos dos
por eso de 15 a 15 da 30 y él le puso hasta el 31

¿En el caso de java me equivoco me va a dar error o el número máximo? Le va a dar el


error como de sintaxis diciéndole que esta fuera de rango

Tipos de datos estándar


Aquí viene los números los números naturales positivos estos vienen como ven es un
subtipo de lincher por lo tanto puede tener los mismos tipos de líneas aritméticas y de
comparación, pero son enteros no negativos, los positivos son muy parecidos y soporta
las mismas operaciones enteros positivos, la única diferencia entre el positivo y el natural
es que este viene desde el cero y el otro viene desde el 1. El inteling vector tiene un arreglo
1v1v es decir cada fila tiene un número, pero todas esas filas están sobre las mismas
variables que sea tipo inteling vector, estaríamos hablando de este tipo de arreglo aquí
yendo un inteling sucesivamente.

Tipos de caracteres
Los caracteres tipo aski y aquí se define todos los tipos de caracteres el día de ayer se
mencionamos que si copia vamos y pegábamos avía unos caracteres que no asomaban
son estos que no hay como borrarles con un editor de texto normal, si algún día les pasa
algo de esto podrían abrirles con el editor de texto subrine ya que este suele dejarnos ver
o al menos nos deja borrar esos tipos de caracteres no visibles ya que otros editores no

29
dejan ni interactuar con estos tipos de caracteres, los de 256 son los de 8 bits y el yltimo
es el 11111… siendo el 255 los primeros 128 símbolos corresponden al código aski
regular, podemos observar como crear un tipo chan y un tipo bin igual aplicamos el when
else como una aplicación pueden soportar la operación de comparación siendo la única.

¿qué pasaría si le pongo mayor char 1 mayo a A? Estaría comparando a partir de la b en


adelante es decir cualquiera menos la A, y casi siempre daría verdad ya que a es la primera
en el alfabeto nos daría todo menos la A.

Tipo Srtring
Es un vector de caracteres es un arreglo 1d1d tenemos un ejemplo es un rango positivo
es decir los índices de rango del string estarían desde 1 ya que no tienen el cero como
pueden ver esta del 1 al 4

Tipos de datos Estándar lógico.


Los tipos de datos estándar logic son STD_LOGIC y STD_LOGIC_VECTOR ambos
están en el paquete std_logic_1164 que es el que usamos son los estándares de la industria.

La definición de STD_LOGIC está en función de STD_lOGIC B primero es un tipo de


dato tipo resuelto y el ultimo es no resuelto es decir que este de los que son resueltos
pueden ser sacados por un pin se convierte el final en ceros o unos o binarios y podemos
sacarlo como un estado alto o bajo de señal en un bit. El estándar LOGIC es el estándar
resulto del ULOGIC nos está diciendo estos caracteres u, x, 0, 1, w, z, r y el signo de
menos.
Significado
U= es que no está inicializado un pin o aun pin de salida nunca le pusimos un pin en
nuestro código por lo tanto no saldrá en nuera simulación

X= al final tomamos una señal o variable asignamos a nuestra salida, pero esta tiene un
comportamiento extraño que nunca cambio o se hizo nada y nosotros le pusimos esa
variable a x, es decir que nos da x esta desconocida y el simulador no sabe en qué estado
esta esa salida.
Esto bajo y alto que son los normales. Estado de alta impedancia.

“Z”: Estado de alta impedancia


“W”: Desconocido débil
“L”: Bajo débil
“H”: Alto débil
“-”: No importa

El estado no importa podría ayudarnos en un caso de hacer operaciones lógicas, las cuales
fueron las que más se vieron en la EPN al ver el tema correspondiente a Mapas de

30
Karnaugh, mismas en las que se colocaba en cada X las permutaciones de 1 y 0 formando
combinaciones de las mismas.

La principal característica de STD_LOGIC comparada con el tipo de dato BIT, es la


inclusión de los valores “Z” (Alta impedancia) y “-” (no importa). El de alta impedancia
permite la construcción de un buffer de tercer estado y el segundo una mejor optimización
de las tablas de búsqueda.

En los “text bench” se puede ocupar una tabla definida en el código para hacer text bench
con las entidades que queremos probar. Ahí es donde se ocupa las tablas de búsqueda y
donde se puede poner los signos de segmento geométrico.

Se dice que el STD_LOGIC es un tipo de estado resulto, ya que, si más de una fuente
maneja un nodo común, el resultado de un nivel lógico está determinado por una función
de resolución.

A continuación, se muestra la función de resolución para STD_LOGIC transcrito del


paquete std_logic_1164.

Aquí podemos buscar en la tabla de resolución a través de un índice. El índice de “i”,


siendo “s” un STD_LOGIC_VECTOR. En sí, es como hacer una búsqueda lo que está
haciendo esta función. Bueno, aquí está una explicación de la función esta de SOLVE.

El STD_LOGIC_VECTOR sabemos que es tipo natural, puede ser del 0 a un número


positivo. El paquete std_logic_1164 (biblioteca) define los operadores lógicos para el
STD_(U)LOGIC o el STD_(U)LOGIC_VECTOR. Se declara el paquete como
std_logic_(unsigned o signed), entonces permiten unas operaciones aritméticas de
corrimiento y de comparación.

No sé si recordábamos que hemos dicho ya unas dos veces que los vectores de
STD_LOGIC_VECTOR no permitían operaciones aritméticas. Existe una definición de
estos de aquí que son tipo STD_(U)LOGIC que vienen adentro de esta librería, en laque
si queremos sin signo sería sin el “un”, sin signo sería con el unsigned. Estos de aquí
siguen siendo vectores, pero pueden, es lo que se hace, permiten operaciones aritméticas
de corrimiento y de comparación. Cosa que en las aritméticas no podíamos hacer con los
vectores normales y corrientes. Entonces cuando nosotros estamos trabajando, todos
estamos trabajando con vectores, y quisiéramos que ese vector haga una operación
aritmética con un número. Digamos que a ese vector queremos irle sumando 1 1 1 1 en
un lazo. ¿Qué podríamos hacer? Podríamos hacer un casting. Es decir, pasar del tipo
STD_LOGIC_VECTOR a un tipo std_logic_(unsigned o signed). Si estamos haciendo
solo un contador normal podríamos hacer solo un unsigned. Le ponemos (unsigned) en la
parte izquierda, y todo el vector el vector se convertiría en un tipo de dato
std_logic_(unsigned) y por tanto permitiría hacer una operación aritmética +1 o más(+)
lo que quiera. Y para retornar, digamos que queremos retornar al c normal, tenemos otra

31
vez lo que salió volverle a hacer un casting hacia un STD_LOGIC_VECTOR. ¿Cómo lo
hacemos? Solo ponemos STD_LOGIC_VECTOR y el resultado de la operación anterior
de la suma, y se convertiría nuevamente en un vector. Entonces eso vamos a ver en un
ejemplo.

Bueno, ahí vemos con signo y sin signo, están definidos los paquetes std_logic y el
std_logic_aritmetic. Estos paquetes son parcialmente equivalentes, por lo tanto, solo uno
de ellos debería declararse o puede declararse en el código. Podemos poner los dos y no
suele dar problemas. Yo he visto en internet que ponen los dos, porque no sabe de qué es
cada cual. No sabe dar mucha información sobre esto, así muy explícita en internet si
buscamos. Pero lo que sabemos es que el std_logic_aritmetic es el antiguo y el
numeric_std es el nuevo. Entonces el numeric_std es el que nosotros vamos a utilizar.

El rango para el tipo de datos sin signo es -2n-1 a 2n-1-1 limitado por el límite alto del
INTEGER, donde n es el número de bits. Igual el rango para el tipo de dato con signo son
los límites del INTEGER. -231-1 hasta 231-1, y están representados eso sí en
“Complemento de 2” para poder representar el signo.

Aquí lo que nos dice una nota es que puede existir una confusión entre el unsigned y el
signed debido a los nombres que tienen estas librerías. Estos paquetes solo definen los
operadores aritméticos sin signo o con signo, para un STD_LOGIC_VECTOR, y no los
tipos signed y unsigned. En otras palabras, los dos paquetes definen como el operador
trata sus operando. Por ejemplo, digamos “a” y “b” son STD_LOGIC_VECTOR, como
vimos en el ejemplo que estábamos hablando y el signo “+” operador suma. Si se usa el
paquete std_logic_(unsigned) el operador suma trata “a” y “b” como datos sin signo. Por
su parte si se usa el std_logic_(signed), el operador suma trata “a” y “b” como datos con
signo.

Entonces, con el casting nos ahorramos alguna que otra cosa y no debemos poner el
unsigned ni el signed, solo le ponemos que utilizamos el std_logic_1164 que nos permite
usar el STD_LOGIC_VECTOR, hacemos el casting, el cual no tiene nada que ver con
nuestras librerías unsigned y signed, y por lo tanto la suma solo va a tomar en cuenta el
tipo de dato que está sumando. Como le ponemos unsigned, el vector asume que el tipo
es unsigned y va a hacer una suma sin signo.

Tipos de Datos de Punto Fijo y Punto Flotante

A partir de 2008 son necesarios ciertos paquetes de VHDL (lista de paquetes), para poder
usar con punto fijo o flotante. En la diapositiva se encuentran las definiciones con signo
y sin signo de los tipos fijos para versiones anteriores a la de 1993 y 2012 (las 2 más
comunes). SIMS tiene la de 1993 y la de 2012. En Quartus no está especificado en qué
versión está.

Para versiones anteriores de VHDL son necesarios los siguientes archivos:


32
 fixed_pkg_c.vhd
 fixed_float_hypes_c.vhd

Para implementar versiones previas se debe crear una carpeta que se llame ieee_proposed
en el directorio de bibliotecas y pegar los archivos antes mencionados.

Aquí se ve un ejemplo de número de punto fijo, valor decimal fijo:

2 DOWNTO -3 significaría que va del 2 al 0 para la parte positiva, que serían los 3 bits
de la izquierda que al final expresándolo en binario daría 4.375 (como vemos en el
ejemplo 1). En el caso de los números con signo son lo mismo, pero expresados en
complemento de 2 (ejemplo 2).

Punto Flotante: Los tipos de datos de punto flotante son de 32, 64 o 128bits.

A continuación, se enlistan las definiciones de tipo flotante y sus subtipos:

Los datos de punto flotante también requieren paquetes adicionales, en el caso de


VHDL_2008, son:
 float_pkg.vhdl
 float_generic_pkg.vhdl
 float_generic_pkg-body.vhdl
 fixed_flotat_hypes.vhdl

Para versiones previas de VHDL se requieren los siguientes archivos:

Para implementar circuitos de punto flotante en versiones anteriores de VHDL se requiere


crear una carpeta llama ieee.proposed en el directorio de biblioteca de VHDL y copiar los
archivos antes mencionados.

33
Representación de un Punto Flotante de 32 bits

En un punto flotante podemos tener 23 bits para la fracción, 8 bits para el exponente y 1
bit para el signo. Si el bit de signo está en 0 significa que el número es positivo, y si está
en 1 significa que es negativo.

El cálculo a través del exponente y la fracción es el siguiente:

Sea x un número en punto flotante. Su valor está dado por x={-1}S(1+F)2E-N. Donde S es
el signo (0 cuando es positivo y 1 cuando es negativo). F es la fracción (mantisa) y E es
el exponente. N es el factor de normalización, dado por N={[EMax+1]/2}-1.

RESUMEN DE LOS TIPOS DE DATOS PREDIFINIDOS.


Estándar logic: es un 1 o un 0
Std logic pueden ser 1 o D porque serian un arreglo de estándar logic de unos y ceros

El std logic signed y el logic unsigned sabemos hacer operaciones aritméticas y de


comparación.

El numeric standar unsigned ese es nuevo del 2008 y es solo para operadores de
comparación.

Este de aquí lógicas de comparación y aritméticas, aquí solo de comparación y lógicas,


aritméticas comparación y relación. Y bueno al final tenemos los signed y unsigned que
son los bits y los puntos flotantes que vimos al final

TIPOS DE DATOS DEFINIDOS POR EL USUARIO.


Estos tipos de datos son predefinidos y vienen en el VHDL, ahora hay que crear los tipos
de datos, tipos de datos definidos por el usuario.

Tipos Enteros.
El tipo INTEGER es sintetizacion sin restricciones. Todos los tipos derivados de
INTEGER son referidos a tipos enteros y pueden ser declarados usando la sintaxis esta:
TYPE type_name IS RANGE range_specifications:
Como decíamos tipo, nombre y en que rango.

Por ejemplo si queremos un INTEGER que se llame negativos ese tipo de datos y que
tenga un rango desde el INTEGER LOW que representaba el limite bajo de los INTEGER
hasta el menos 1.
Entonces si nosotros creamos una señal de tipo de tipo negativo ¿Cuántos bits va a usar?

Son 32, 32 bit nos toca, ya que estamos usando toda la parte negativa del INTEGER y
necesitamos 32 bits para ponerle el número y el negativo, si, si no que estamos, en vez de
ponerle directamente un INTEGER del INTEGER LOW hasta el -1. Le estamos creando

34
un tipo de dato que se llame negativo y ese va hacer para los negativos en ese rango del
INTEGER.

Por ejemplo, aquí estamos creando un tipo temperatura, que este usando los grados kelvin,
y dice que ese solo va a poder ser de 0 a 273.

Eso sería ahorrarse un pasito en una declaración de una señal o una variable porque para
declarar una variable así ¿Qué podríamos hacer?

Lo mismo que podríamos hacer, porque podríamos hacer es digamos es signal a dos
puntos y si le pongo aquí temperatura, ya estaría definido todo no, que va del 0 273 porque
temperatura fue un tipo de dato que va definido del 0 al 273.

Esto de aquí sin definir este tipo de dato ¿Cómo quedaría? A dos puntos debería ser tipo
INTEGER y luego ponemos un rango de ¿Dónde? Del 0 al 273. Estos serían equivalentes,
si claro que este más largo, pero serian equivalentes, sería lo mismo si no definiéramos el
tipo temperatura en este caso, pero es solo un ejercicio ¿no? Eh si fuéramos a ocupar el
mismo tipo de dato, lo definimos no, y tendríamos que estar haciendo esto no, pero son
equivalentes estos dos.

Tipos Enumerados.
Los tipos enumerados es decir representa por símbolos es decir pueden ser listados, es
decir los enumerados contiene una lista que puede ser.

Hasta ahora un enumerado que hemos visto era el CHART, porque el CHART decíamos
puede ser a,b,c,d,e,f y g y solo pueden ser esos.

Por ejemplo, el boolean es un tipo enumerado porque solo puede tener false o true el bit
también porque solo puede tener 0 o 1, es decir nosotros le ponemos aquí dentro la lista
que podría tomar de valores validos que podría tomar.

Por ejemplo aquí tenemos un tipo analógico 0 1 0 significa que solo puede tomar 0 1 y 0
o este estado, solo puede tomar estados tipo a,b,c,d y e.

Por ejemplo, este tipo MAQUINA estado de la maquina puede ser idle, transmitting,
receiving.

Y este de aquí seria la lista en la que puede usarse, aquí podría haber un error porque le
estamos escribiendo así no más, deberíamos escribirles entre comillas dobles para indicar
que son strings.

Los arreglos definidos por usuario, sabíamos bueno, por ejemplo, un arreglo 1 D 1 D, por
ejemplo, este de aquí.

Tipo uno es un array de positivo de enteros, y dice que la constante 1, bueno hasta ahora
vimos señales no, esto estamos creando una constante es decir ya no cambia en el tiempo
nunca más.

Es de tipo 1 que es el tipo de datos tipo 1 que va de 1 hasta 4, es decir solo tiene 4
elementos, y aquí ahí hemos encontrado este símbolo de dos puntos igual.

35
¿para qué me sirve dos puntos igual? Cuando estoy usando señales o constantes, me sirve
para inicializar, en este caso como es una constante inicializo y de una vez defino a la
constante, si quiero una señal estaría inicializando esa señal ya que esa señal podría
cambiar con el tiempo, al hacer una operación lógica o algo.

Y le estamos definiendo un array tipo 1D1D que sería de 5 a -5 de 3 y 0, aquí cada uno
de estos como no hemos definido aquí el INTEGER el rango que tiene que ser, estamos
teniendo de 32 bits cada uno de esos valores no, ese 5 el -5 el 3 y el 0 ocupan 32 bits de
espacio de memoria porque aquí no le definimos aquí luego de esto, no le definimos de
donde a donde tiene que ir, entonces ahí va concatenando todo lo que hemos visto.

Otro tipo de dato tipo 2 dice que es un array del 0 al 3 pero es de tipo natural, los naturales
sabemos que van del 0 al límite máximo del INTEGER, e igual de esta misma manera
estaría ocupando 32 bits y como es una constante le estamos definiendo o inicializando
digamos.
Haber… los tipos 1D1D ¿Cómo eran esos 1D1D? Eran ese que el dibujito era así.
Así y por ultimo teníamos así.

Ese era el 1D1D serían como en las matrices del MATLAB teníamos 3 dimensiones
digamos, serian dimensión 1, dimensión 2, dimensión 3 y cada uno tendría un valor de
un array.
El tipo 2 es un array de 0 a 3 de tipo natural.

El tipo 3 es un array de 1 a 2 ¿de quién? del tipo 2 por lo tanto ahí ya estamos construyendo
el array de dos dimensiones en este caso, por que va de 1 a 2 no más, es decir este sería
solamente hasta aquí, así, ¿no cierto? por que va de 1 a 2 y cada una de ellas es de este
tipo este sería la negra y la numero dos seria la D.

Los enumerados este tipo está restringido por esta forma de definición veamos un
enumerado…

Veamos un ejemplo de un enumerado, tipo 1 es un array de tipo natural de un rango sin


restricciones, pero es tipo estándar logic, si damos una constante de tipo 1 y como se le
está poniendo un límite del 0 al 4 o 4 downto 0, estamos definiendo de donde a donde por
lo cual decimos que son los enumerados. De la misma manera podemos hacer otros tipos,
tipo 4 1D 1D que es del 1 al 4 de un estado logic vector, pero todos los estados logic
vector van a ser de 3 elementos.
Para acceder a un arreglo, a una posición de un arreglo, tenemos este tipo de int rough
que está en el rango de 1 a 3 en un columb va tipo enlistado en lo que va únicamente a b
c d para la enumeración de la columna, y una matriz, dicha matriz será un array que va a
tener filas enumeradas del 1 al 3 y columnas que van a estar simbolizadas por las letras a
b c d, todos estos cuadros van a contener únicamente 1 bit que va a ser de tipo standar
logic.

36
Inicializamos la constante, z101, significa que cada uno de ellos va a tener una
identificación única por fila y columna, el primero sería el 1a la primera fila primera
columna, el segundo seria primera fila segunda columna y así sucesivamente. Se tiene 3
filas y así se puede encontrando las demás.

Los registros son colecciones de elementos de diferentes tipos, los tipos pueden ser
predefinidos o definidos por el usuario, aquí se muestra un tipo de registro, tipo memory
acces, es tipo record de registro, va a tener un adress que va a ser un integer de 0 a 255
un block que va a ser de 0 -3 y una data que va a ser un bit vector de 15 DOWNTO 0.

Veamos un ejemplo de un enumerado, tipo 1 es un array de tipo natural de un rango sin


restricciones, pero es tipo estándar logic, si damos una constante de tipo 1 y como se le
está poniendo un límite del 0 al 4 o 4 downto 0, estamos definiendo de donde a donde por
lo cual decimos que son los enumerados. De la misma manera podemos hacer otros tipos,
tipo 4 1D 1D que es del 1 al 4 de un estado logic vector, pero todos los estados logic
vector van a ser de 3 elementos.

Para acceder a un arreglo, a una posición de un arreglo, tenemos este tipo de int rough
que está en el rango de 1 a 3 en un columb va tipo enlistado en lo que va únicamente a b
c d para la enumeración de la columna, y una matriz, dicha matriz será un array que va a
tener filas enumeradas del 1 al 3 y columnas que van a estar simbolizadas por las letras a
b c d, todos estos cuadros van a contener únicamente 1 bit que va a ser de tipo standar
logic.

Inicializamos la constante, z101, significa que cada uno de ellos va a tener una
identificación única por fila y columna, el primero sería el 1a la primera fila primera
columna, el segundo seria primera fila segunda columna y así sucesivamente. Se tiene 3
filas y así se puede encontrando las demás.
Los registros son colecciones de elementos de diferentes tipos, los tipos pueden ser
predefinidos o definidos por el usuario, aquí se muestra un tipo de registro, tipo memory
acces, es tipo record de registro, va a tener un adress que va a ser un integer de 0 a 255
un block que va a ser de 0 -3 y una data que va a ser un bit vector de 15 DOWNTO 0.

Los subtipos son tipos de datos con restricciones a partir de un tipo de dato anterior, por
ejemplo, los subtipos vistos previamente son los naturales y los positivos que son subtipos
de un integer.
La principal razón de usar subtipos en vez de especificar un nuevo tipo es que entre las
operaciones entre diferentes tipos de datos no están permitidas, si lo están entre subtipos
y el tipo de dato del cual derivo. Un subtipo puede estar declarado en la misma parte de
un tipo, pero usualmente se lo hace en la parte declarativa de la arquitectura.

Como ejemplo tenemos un tipo standar logic y un subtipo milogic que va del 0 al set, es
decir, toma 0, 1 y set como el rango que tome a partir del standar logic. El tipo color que
tiene una lista que puede ser Red, green, blue y White, micolor solo toma desde el verde
al azul.

37
Conversión de tipo de datos o casting, puede existir una conversión automática, en el caso
de que se trate directamente de una base bit o bit vector, tiene el mismo tipo de base bit
que un bit vector, por ejemplo, BV0 que es un bit vector, le estamos diciendo que al bit
cero de este bit vector le asignamos este bit, ahí está haciendo una conversión automática,
ya que como son el bit cero de un bit vector es tipo bit se puede asignar directamente y
eso se refiere a conversión automática.

El casting es lo que se hacía colocando el assigned adelante, el assigned o signed tiene la


misma base del standar logic e ingresado natural como el standar logic vector, la
conversión entre tipo de hace de la siguiente manera: se pone el assigned con un
argumento entre paréntesis, donde el argumento será un standar logic vector y para pasar
de un natural a un standar logic vector colocamos standar logic vector argumento, en
donde el argumento es un tipo de dato assigned para poderle dar una suma con un vector,
primero se pasa a natural luego sumamos y finalmente regresamos al vector.

En la tabla podemos observar algunas funciones de conversión, entre ellas el signed,


assigned, logic vector y también se tiene para los tipos flotante y los números de punto
fijo, etc.

Existen tres tipos de arquitecturas: flujo de datos (orden de ejecución), funcional y


estructural.

Explicaciones del uso del When else y el with select para la implementación de dos
decodificadores: binario a bcd y bcd a 7 segmentos.

Utilizando el software Logisim permite obtener los mapas de Karnnaugh únicamente


ingresando las tablas de verdad, yaque el software nos arroja directamente la solución.
Estructuras de control y repetición: when else, with select, if, iflse, etc
La estructura básica del código en VHDL consta de: librerias; entidad y arquitectura.

ESTRUCTURA BASICA DEL CODIGO EN VHDL


Librerías
library ieee; --libraría estándar ieee

use std_logic_1164.all; --librería estándar de operaciones aritméticas sobre datos


estándar logic cuando se las pasa al casting

Implementación de una entidad (entity)


-- modela un dispositivo físico. Se definen los pines de entrada y salida de un
dispositivo físico –
Como ejemplo se diseñará una compuerta XOR
entity nombre_entidad is (el nombre_entidad siempre debe tener primero una
letra o guion bajo)

38
port ( A: in std_logic;
B: in std_logic;
O: out std_logic);
end nombre_entidad;

Arquitectura
--define el comportamiento que va a tener el dispositivo modelado (entidad)
arquitecture nombre_arquitectura of nombre_entidad is
– antes del begin se puede definir señales locales, constantes, componentes
begin
end nombre_arquitectura;
La arquitectura tiene un “BEGIN” y tiene un “END”, y terminamos con el “;”.

En las diapositivas anteriores se mencionó que hay un espacio de definición dentro de la


arquitectura definición de variables de señales este espacio de definición es justo el
espacio que esta la línea 12 y 14 donde comienza el nombre de la arquitectura y el BEGIN.
¿Qué se puede poner ahí? se puede definir señales locales, signal a de las diapositivas
anteriores, se puede definir además constantes, además se pueden definir componentes.

Hasta ahora se hemos visto cómo hacer señales y constantes, ahora lo que se va a ver es
en la arquitectura estructural el uso de componentes.

Las arquitecturas no solamente son excluyentes entre ellas, pueden mezclarse las tres en
un mismo código, entonces se pone los nombres solamente para indicar como se escribe
el código en diferentes arquitecturas, pero se pueden juntar en un mismo código, no son
excluyentes entre ellas la forma de escribir el código se lo puede hacer de la forma que se
desee.

Para ejemplificar creamos una señal local, signal pongámosle TEMPO, posteriormente
se pone “:”, una señal local el ámbito de esa señal será dentro del cuadro, por lo tanto, no
es necesario poner que es de entrada o de salida, ya que nunca saldrá, solo los puertos
tocan definir como entrada o de salida, luego de los dos puntos únicamente se pone el
tipo de dato, se pone el mismo tipo de dato en este caso por comodidad.

Es posible inicializar las señales locales y las constantes por medio de “: =”, e
inicializamos en cero, para poner un solo bit se escribe con comilla simple, y listo tenemos
la señal local.

La señal local únicamente se encuentra dentro de ese dispositivo y no puede salir de ahí,
también, en la parte de definiciones de la arquitectura se puede poner señales locales,
constantes y componentes.

39
Pongamos una constante, constate “c”, la constante c le vamos a poner de tipo de dato
“integer”, para que el integer sea una constante y almacene por ejemplo solo el número
5, si no quiero que ocupe 32 bits de memoria solo en el número 5 se debe poner un rango,
por lo cual ponemos “range” y tomamos entre 0 y 5, se toma desde el cero ya que es
necesario que tome los bits. Luego inicializamos e igualamos a 3 para que se distinga.

Lo que se ah echo es que el integer tenga un rango de 0-5 y que tenga igual a 3 a pesar
que se tiene un bit más, el 3 no va entre comillas ya que es un número, entre comillas
simples únicamente se pone a los bits o a los caracteres únicos y entre comillas dobles se
coloca los vectores de bits y los strings.

Ya tenemos entre el Begin y el end de la arquitectura, es decir entre la línea 17 y 20, ahí
se tiene que definir las operaciones que va a hacer mi entidad Hello Word, entonces aurita
se debe escribir lo que se va a hacer, ya que “f” es una salida puedo asignarle un valor,
para lo cual se lo realiza con “≤”, luego es necesario poner las operaciones que nos toque,
en este caso: a XOR b.

No es posible hacer a la variable a lo de la línea 18 ya que es una entrada, y a las entradas


solo puedo leerlas, no puedo cambiarles o escribirlas, a diferencia de la variable f que es
una salida a ella si puedo cambiarle o escribirle. A las señales locales, ya que no son
entradas ni salidas, por lo cual a ellas puedo leerlas o escribirlas, esa es una ventaja de la
señal local.

Digamos que se va a ocupar TEMPO, vamos a hacer f tempo, antes de continuar este
es el ejemplo más básico de una arquitectura de flujo de datos, es una flujo de datos
porque todo se va haciendo al mismo tiempo y solo tenemos operaciones lógicas y
máximo operaciones aritméticas, pero son operaciones por líneas, podemos tener unas
operaciones de verificación, sin embargo es lo más básico de flujo de datos, es necesario
entender cómo y cuándo se disparan cada una de las líneas o que funcionen las líneas, la
línea 18 y 19 por la forma en la que está escrito ese código serán paralelas. Ya que lo que
puede cambiar aquí son las dos entradas entonces si cambia a o cambia b o ambas cambian
la línea 18 se disparará, es decir, se ejecutará, al estar TEMPO asociado también
cambiara, XOR funciona cuando son iguales es cero y cuando son distintos es 1, entonces
sabiendo eso graficamos el eje del tiempo en el cual vamos graficando diferentes
instantes, ubicamos t1, t2, t3 digamos que en “a” colocamos 0,0, luego 1,1 y finalmente
0,1, dependiendo de esto en los instantes de tiempo en las salidas tendríamos: de 0,0
saldría t1=0, de 1,1 saldría t2=0, y de 0,1 saldría t3=1.

¿Cómo se ejecutarán estas dos líneas de código? En el primer instante de tiempo se


ejecutará 0,0 por ser el primero, y se ejecuta la primera línea 18 y TEMPO cambia y
puesto que tempo cambia también se ejecuta la otra línea de código, pero las dos
paralelamente, casi instantáneamente se ejecutan las dos. Por lo tanto, f toma el valor de
cero.
El siguiente instante ya que a y b cambia, o cualquiera de las dos cambia, se dispara la
línea 18, TEMPO no cambio de valor por lo cual la línea 19 no se ejecuta ya que el lado
derecho no cambio. Por ultimo en el instante 3, ya que al menos un cambio, eso quiere

40
decir que la línea 18 otra vez se ejecuta y puesto que TEMPO cambio se ejecuta la línea
19.

Las señales que se encuentran a la derecha son señales sensitivas o de strig, son llamadas
así ya que al ver que cambian se ejecutan las cosas.

Los subtipos son tipos de datos con restricciones a partir de un tipo de dato anterior, por
ejemplo, los subtipos vistos previamente son los naturales y los positivos que son subtipos
de un integer.

La principal razón de usar subtipos en vez de especificar un nuevo tipo es que entre las
operaciones entre diferentes tipos de datos no están permitidas, si lo están entre subtipos
y el tipo de dato del cual derivo. Un subtipo puede estar declarado en la misma parte de
un tipo, pero usualmente se lo hace en la parte declarativa de la arquitectura.

Como ejemplo tenemos un tipo standar logic y un subtipo milogic que va del 0 al set, es
decir, toma 0, 1 y set como el rango que tome a partir del standar logic. El tipo color que
tiene una lista que puede ser Red, green, blue y White, micolor solo toma desde el verde
al azul.

Conversión de tipo de datos o casting, puede existir una conversión automática, en el caso
de que se trate directamente de una base bit o bit vector, tiene el mismo tipo de base bit
que un bit vector, por ejemplo, BV0 que es un bit vector, le estamos diciendo que al bit
cero de este bit vector le asignamos este bit, ahí está haciendo una conversión automática,
ya que como son el bit cero de un bit vector es tipo bit se puede asignar directamente y
eso se refiere a conversión automática.
El casting es lo que se hacía colocando el assigned adelante, el assigned o signed tiene la
misma base del standar logic e ingresado natural como el standar logic vector, la
conversión entre tipo de hace de la siguiente manera: se pone el assigned con un
argumento entre paréntesis, donde el argumento será un standar logic vector y para pasar
de un natural a un standar logic vector colocamos standar logic vector argumento, en
donde el argumento es un tipo de dato assigned para poderle dar una suma con un vector,
primero se pasa a natural luego sumamos y finalmente regresamos al vector.

En la tabla podemos observar algunas funciones de conversión, entre ellas el signed,


assigned, logic vector y también se tiene para los tipos flotante y los números de punto
fijo, etc.

¿Cuál es la analogía en hardware de porque la señal no pasa? En hardware es como si se


tuviera un tiempo, y las líneas de entrada cambian en cada instante, y hay una línea de
salida que nunca cambio por lo tanto nunca se ejecutara mientras la línea de código no se
ejecute

En hardware la señal no se propaga, porque sigue siendo la misma, y no tiene que


propagarse de nuevo.
¿Sería más eficiente quitando la variable en ese tiempo? Si sería más eficiente, sin
embargo, se lo ha puesto así para ejemplificar cuando la señal es sensitiva.

41
¿Da lo mismo cambiar las líneas? Si da lo mismo porque se junta en paralelo, únicamente
sería un poco diferente porque el tiempo ya está inicializado.

¿En qué estado estará f de lo que se vio en standar logic? Recordando los estados U, el
eje x, el z el 1 y 0 que son los más importantes, y que f recién inicia.

A y B en la simulación podría estar sin asignar, en la realidad ya no porque va a estar


conectado a un dipswitch, a un fotón o a algo tiene que estar conectado, porque se sabe
que es una entrada lógica, y no pueden estar sin asignar en la realidad, f en un principio
por un momento pequeño va a estar sin asignar, por eso lo que se suele hacer es crear un
retardo que le diga espere por 100ns que es el de reseteo, para que espere un momento y
pueda leer las entradas, propagar la señal y tener una salida lista, y no en el programa
directamente.

Estructura Básica de un código en VHDL

1. Las librerías que se van a usar

2. Definición de la entidad y los puertos, recordando que se ha visto dos tipos entrada
y salida, y a futuro se verá que puede ser de dos tipos más, y definir el tipo de dato
que tiene este puerto

a. Los tipos de datos que se pueden tener los puertos tienen que ser
sintetizables, ya que estos pueden traducirse en ceros y unos, que son
estados lógicos que pueden interpretarse como altos y bajos, en este caso
se utilizara el std_logic que es el más fácil de usar.
ENTITY nombre IS
[GENERIC(lista de parámetros);]
[PORT(lista de puertos);]
END [ENTITY] nombre;

3. Se tiene que tener una arquitectura, y dentro de la arquitectura se define el


comportamiento de la entidad que se está modelando, y esta arquitectura puede
tener cualquier nombre.
a. Una arquitectura de otro sistema que se esté modelando puede tener el
mismo nombre, teniendo en cuenta que el nombre de la arquitectura se
define por su comportamiento interno, por lo tanto, si puede tener el
nombre, pero el ámbito para poner su nombre, sin embargo el nombre de
una entidad no puede ser el mismo de otra
b. Antes del begin de la arquitectura se pueden definir variables locales, que
no podrán ser usadas como entradas y salidas, constantes y componentes

42
c. Dentro del begin hasta el end se colocan las operaciones logicas,
operaciones aritméticas o lo que se quiera hacer, para que se modele el
comportamiento de la entidad o dispositivo que se va a usar

Un puerto es un objeto de información, el cual, puede ser usado en expresiones, y al cual


se le pueden asignar valores. A cada puerto se le tiene que asignar un nombre valido.

Seguido del nombre del puerto separado por dos puntos (:) viene el tipo de puerto que va
a ser. El modo describe la dirección en la cual la información es transmitida a través del
puerto. Estos solo pueden tener 4 valores (in, out, buffer, inout)

Por último, se tiene que definir el tipo de dato que puede ser el puerto. Este debe ser de
un tipo de dato que pueda ser sintetizable (bit std_logic integer carácter boolean float y
sus derivados)
Los derivados son los naturales, los dispositivos, el bit_vector, std_logic_vector

La entrada inout puede ser entrada y salida a su vez, ya que en algunos casos se requiere
que pueda ser salida, pero que también pueda ser utilizada como entrada, ya que las
salidas no se las puede leer, únicamente las entradas Si se quiere hacer una operación
dentro de la arquitectura de esta entidad, leyendo lo que este ahí se tiene que utilizar un
inout
IN: Son señales de entrada, las cuales solo se pueden leer, pero no se pueden asignar a
ningún valor que poseen. Por lo tanto, su funcionamiento es similar al de las constantes.

OUT: Corresponden a señales de salida, en este caso su valor puede ser modificado, pero
en este caso no pueden leerse, es decir que no pueden ser utilizado como argumentos en
la asignación de cualquier elemento.

INOUT: Es un tipo de mezcla de los dos anteriores, puede ser utilizado tanto como para
escritura como para lectura.

BUFFER: Es idéntico al anterior, con la diferencia que solo una fuente puede modificar
su valor, además solo puede conectarse a otro puerto buffer de otro dispositivo, este buffer
permite el envio controlado de datos de una entidad a otra

Una forma de abreviar las entradas y salidas, se declaran todas las que sean entradas en
una misma línea.

Declaración de la arquitectura
El comportamiento que va a tener el dispositivo que está definido dentro de la sección
arquitectura.

Todas las sentencias dentro de la arquitectura se ejecutan al mismo tiempo por lo tanto es
concurrente. Después de esta línea pueden aparecer varias instrucciones para indicar la
declaración de señales, componentes, funciones, etc. Estas señales son internas, es decir,

43
a ellas no se puede acceder desde la entidad, por los que los circuitos de nivel superior no
podrían acceder a ellas.

ARCHITECTURE nombre OF nombre_entidad IS [declaraciones]


BEGIN [sentencias concurrentes]
END [ARCHITECTURE] [nombre];

El siguiente comando Begin da comienzo a la descripción del código mediante sentencias


ya antes mencionadas.

En VHDL es posible declarar componentes dentro de un diseño mediante la


palabra COMPONENT. Un componente se corresponde con una entidad que ha sido
declarada en otro módulo del diseño, o incluso en alguna biblioteca, la declaración de este
elemento se realizará en la parte declarativa de la arquitectura del módulo que se está
desarrollando. La sintáxis para declarar un componente es muy parecida a la de una
entidad.
COMPONENT nombre [IS]
[GENERIC(lista_parametros);]
[PORT(lista_de_puertos);]
END COMPONENT nombre;

Arquitectura Flujo de Datos


VHDL es un lenguaje concurrente, por lo tanto, no seguirá el orden en que están escritas
las sentencias, es decir, puede que dos instrucciones se ejecuten al mismo tiempo. Para
realizar una sentencia lógica básica de ejecución concurrente se utiliza el símbolo <=,
para facilitar la asignación dentro de VHDL existen elementos de alto nivel como
instrucciones condicionales, de selección, etc.

 Sentencias Concurrentes

 When….Else: es una sentencia de selección, es necesario indicar todas las


opciones posibles terminando con una sentencia else. Es decir en el caso de que
no cumpla ninguna de las condiciones se asignará el último valor indicado por
else a la señal.
Ejemplo:

44
Se tiene una señal output que es un vector de 3 bits, mostrará “000” cuando la señal inp
es 0 o la entrada reset esta en 1, mostrará “001” en la salida si la entrada clt esta en 1 y en
cualquier otro caso outp muestra un valor de “010”.

Construcción de un multiplexor de 4 entradas a una salida:

 With….. Select …… When: La asignación se realiza según el contenido de un


objeto o resultado de una expresión:

Ejemplo: Multiplexor utilizando sentencias with_select_when

45
Ejemplo desarrollado:
Conversor de un número binario de 4 bits a un BCD de 5 bits:

Debido a que con un número binario de 4 bits es posible representar un número decimal
hasta 15, es necesario dos números BCD para las decenas y las unidades, en el caso de
las decenas ya que varía únicamente entre 0 y 1 solo se toma un bit y los cuatro bits de
las unidades. Mediante la sentencia with/select/when es posible un diseño intuitivo de un
conversor, se observa que para la asignación de when others se indica una salida igual a
“00000” debido a que con esto evita errores por desconexión o estados inválidos en la
entrada, además, como se explicó previamente en un dato tipo std_logic es posible asignar
valores de no importa “_” o alta impedacia “z”, dependiendo del caso con el fin de evitar
errores por el hardware.

CASE:
Es muy semejante al if, debido a que ejecuta también un bloque condicional, pero se
evalúa una expresión (valor o vector) dada en lugar de una condición, y a la vez existe
una condición final en la que se incluyen todas las expresiones restantes con la sentencia
WHEN OTHERS.
CASE <expresión> IS
WHEN <valor1> => [sentencias1]
WHEN <valor2> => [sentencias2]
WHEN <rango de valores> => [sentenciasN]
WHEN OTHERS => [sentenciasM]
END CASE;

46
LOOP:
LOOP es la forma de hacer bucles en VHDL. Sería el equivalente a un FOR o WHILE
de un lenguaje convencional. Es necesario elegir la condición para que se ejecute el lash,
además se tiene las sentencias EXIT para finalizar el loop, y el NEXT para no ejecutar
líneas posteriores. Su estructura es:
[etiqueta:] [WHILE <condición> | FOR <condición>] LOOP
[sentencias]
[exit;]
[next;]
END LOOP [etiqueta];

ARQUITECTURA FUNCIONAL
Ejemplo con Arquitectura Funcional
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;

ENTITY Mod3210 IS

PORT (clk: IN std_logic;


reset: IN std_logic;
enable: IN std_logic;
count: OUT std_logic_vector(11 DOWNTO 0)
);
END Mod3210;

ARCHITECTURE arch1 OF Mod3210 IS


SIGNAL cnt: UNSIGNED(11 DOWNTO 0);
BEGIN
pSeq: PROCESS (clk,reset,enable) IS
BEGIN

47
IF reset='1' or cnt =3210 THEN
cnt <= (others => '0');
ELSIF clk' AND clk='1' THEN
IF enable <='1' THEN
cnt <= cnt+1;
END IF;
END IF;
END PROCESS;
count<= std_logic_vector(cnt);
END arch1;

Hacer un barrido de display, entonces tenemos dos salidas, una para la activación, cada
salida para activarse debería ser con cero y el BCD a 7 segmentos tendríamos que pasarlo
a esta salida, tendríamos que coger una entrada que este en 7 segmentos y solamente
ponerle en la salida apropiada, pero deberíamos tener cuatro entradas de arrays de 8 bits,
cada una sería el código en 7 segmentos para cada uno de los displays, y lo único que
tendríamos que hacer es tener también una señal de clock, la cual nos serviría para que
vaya apareciendo de manera automática el valor que nos corresponde, y cada vez que el
clock cambie se seguirá barriendo lo que esté en la entrada de 7 segmentos.

Definición
La diferencia con la otra. es que nos permite a nosotros poder programar de la manera
como sabíamos en C, con IFs, con FORs, con WHILEs.

¿Cuál es la ventaja de hacer eso? Como hemos visto en la arquitectura anterior, la


arquitectura flujo de datos teníamos que encontrar una función lógica y dependiendo de
la función lógica, teníamos todas las posibilidades, porque hacíamos mapas de Karnaugh
y en el mapa de Karnaugh poníamos todas las posibilidades como podía actuar un circuito
y dependiendo de eso iba hacer la salida, la ventaja e hacer con IFs es que uno solo dice
“Sí, la entrada es esto, la salida es esto” y se ahorra todo el proceso de diseño en
secuencias lógicas.

Por eso en el laboratorio en la parte de sistemas digitales se les enseña esto, pero se les
dice “no lo usen”, porque si no ustedes solo ponen: Sí, la entrada es 100, entonces prende
el led 1, si es lo siguiente prende el led 2 y se va toda la parte de digitales, entonces esta
de aquí, más que todo nos sirve para implementaciones rápidas e implementaciones de
cosas que tal vez no podamos nosotros diseñarlas como un sistema digital.

A todo esto, la salida será esto a través de los IFs, entonces la arquitectura funcional,
como dice tal vez la forma concurrente como se hacen las cosas en VHDL, a veces no es

48
la mejor forma de abordar un problema, entonces VHDL incorpora programación en
serie, es decir secuencial, la cual se define en bloques indicados por la sentencia Process,
en el mismo diseño puede haber varios bloques de estos Process, cada uno de estos
bloques corresponderá a una instrucción concurrente, eso hay que tener en cuenta, dentro
del Process se abarca toda la parte que es de manera secuencial, es decir el IF, luego viene
la línea 1, luego se ejecute la línea 2, luego la 3, pero todo el Process en sí, se ejecuta en
paralelo con cualquier otra cosa que está ahí en paralelo en la arquitectura, es decir si
tengo Process 1, Process 2 y Process 3, los 3 Process se ejecutan de manera paralela, pero
internamente el código dentro de cada uno de esos bloques Process se ejecuta línea a
línea, como hemos visto en otras programaciones secuenciales, entonces es decir
internamente la ejecución de las instrucciones de los Process es en serie es decir línea a
línea, pero entre los bloques es concurrente, a continuación veamos las estructuras más
comunes de programación serie y sus características, ahí podemos ver la forma general,
de construir estos bloques Process

PROCESS[lista de sensibilidad]

[Declaración de variables]

BEGIN

[Sentencia secuenciales]

END PROCESS:

Entonces este proceso puede o no puede tener a lado derecho de la palabra Process puede
o no puede tener está lista de sensibilidad, el día de ayer se vio que la lista de sensibilidad
son las variables sensitivas que vimos ayer, eran aquellas que permitían que se ejecuten
o no se ejecuté una de esas líneas en el flujo de datos, entonces en los Process también
podemos poner esto, no es necesario que se ponga siempre, un Process puede o no puede
tener una variable sensitiva. ¿Para qué le va a servir? La variable sensitiva entonces le va
servir para ejecutarse cuando esa variable sensitiva cambio, igualito a como teníamos ayer
en la estructura flujo de datos. Cuando cambia se ejecuta todo el bloque en este caso. En
el caso de que el Process no tenga una variable sensitiva justo al lado de la palabra
Process, necesitamos usar una sentencia llamada “WAIT”.

Este WAIT me va a servir de una forma parecida a la variable sensitiva lo que le va a


decir: cuando pase esto o espere hasta que pase esto y ejecute lo siguiente. Entonces este
WAIT va a convertirse como si fuera la variable sensitiva es como un reemplazo cuando
no se tiene ahí, el problema es que no hay como usar las 2 cosas, variables sensitivas y
WAITs al mismo tiempo en el Process, eso está prohibido en VHDL, no nos dejan usar
así justo luego de la línea de Process y antes de su BEGIN podemos declarar variables.
Hasta ahora hemos visto que podemos declarar señales locales y constates. Vamos a ver
¿Cuál es la diferencia entre una señal local usada dentro del Process y una variable dentro
de ese Process? Que se comportan completamente distinto y luego debajo del BEGIN

49
vienen las sentencias secuenciales ahí si vienen los IFs y todas las líneas que se ejecutan
de manera ordenada desde la parte superior hacía abajo. Entonces ahí viene:

La lista de sensibilidad es una serie de señales que al cambiar de valor hacen que se
ejecute todo el Process.

ENTITY ejemplo
port (c: IN std_logic:
d: OUT std_logic:);
AND ENTITY;
ARCHITECTURE ejemploarch OF ejemplo IS
SIGNAL a,b : std_logic;
BEGIN
PROCESS(c)
VARIABLE z: std_logic;
a <= c AND d; -- Asignacion de señales, despues de
--ejecutarse esta línea a seguirá valiendo lo mismo, solo se
--actualiza al acabar el PROCESS
z := a OR c; --Asignación de variables, en el momento de ejecutarse esta línea
--z valdrá a OR c (El valor que tenía cuando empezó el PROCESS)
END PROCESS;
END ARCHITECTURE;
Ahí vemos todo un dispositivo de tirar, donde tenemos una entrada c y una salida llamada
d, tenemos unas señales a y b que son del mismo tipo que las señales de entrada y
comenzamos dentro del BEGIN hemos creado un Process, como pueden ver ese Process
tiene como variable sensitiva a c, ya que se es ahorita,ahí en ese caso c es lo único que
podría cambiar, porque nada más está cambiando en ese código y c es la variable de
entrada, luego tenemos una variable que hemos creado dentro del process y hemos
llamado z, esta variable z también es del mismo tipo que las otras variables que es
std_logic luego les dice a que es en este caso una señal local va a tomar el valor de c AND
b, esas líneas se ejecutan de forma serializada primero la de arriba y después la de abajo,
aunque tienen la misma sintaxis que teníamos en el flujo de datos, el único cambio es que
estas sentencias están dentro de una parte que se ejecuta de manera serial y luego tenemos
otra operación acá de la variable, dice ahora la variable en este caso la forma de asignación
de valores siempre a una variable es con “: =” . Anteriormente teníamos que las señales
locales y las señales de salida todas ella teníamos con “<=”. Ahora solamente las variables
siempre son con “: =” para asignarles un valor, este valor va a hacer de esta operación a
OR c. ¿Cuál es la diferencia entre estas 2? Como podemos ver en el texto “a seguirá
valiendo lo mismo solo se actualizará al acabar el Process, mientras que z la asignación
de variables en el momento de ejecutarse esta línea”. Justo al ejecutarse esta línea z valdrá
lo que salga de esa operación, el valor que tenía cuando empezó el Process.

Entonces la diferencia es que la señal local o una señal de salida solamente actualizada
su valor cuando llega al final de Process, mientras que una variable que está aquí dentro
ya cambia su valor apenas se ejecuta la línea. Esa es la gran diferencia ¿Para qué serviría
lo uno y lo otro? Osea digamos que solo usamos que haga esta operación y hace cualquier

50
otra cosa, pero no depende de que este de aquí cambié. Digamos que luego de hacer esta
línea nosotros aquí ponemos un IF y dice si: Si, a es igual a 1 entonces, digamos que
tenemos otra salida más e también va hacer igual a 1, entonces el problema es que a es
una señal local, este IF no funcionaría bien ¿Por qué? Porque como esta señal a no se va
actualizar de manera inmediata este IF estará evaluando el valor anterior que debió tener
esa señal y no el que realmente saco después de la operación, eso es un problema aquí
que hay que tener en cuenta. Si tuviéramos que hacer algo así, que las operaciones
siguientes dependa de una operación anterior, como la operación de ahí. Al usar variables,
con variables aquí adentro, estas como ya cambian de valor las otras sentencias ya se
ejecutan con los valores actuales, no con los valores anteriores y ahí se podría solucionar
ese error que podríamos tener. Eso es lo más raro que tiene el Process la parte de cómo
se actualizan las señales locales y las señales de salida y las variables.

El ámbito de la variable la variable z y el ámbito en el que vive, es dentro del Process, es


decir al salir del Process la variable z desaparece.

Ejemplo: MUX
Cogemos y lo ponemos en el en el espacio de trabajo y conectamos cosas entonces esa ya
conectados conectamos unos bloques para entradas especificadas y para salida, como el
código no tiene ni entradas ni salidas van a servir las señales para poder meter cosas al
componente, entonces se debe crear adentro las señales locales Ejemplo:

signal entradaMUX std_logic_vector (3 downto 0);


signal seleccionMUX std_logic_vector (3 downto 0); --señal de selección

Ya tenemos los bloques que nos permiten dar valores, lo que hemos tenido digamos una
analogía Proteus es que tenemos un MUX de 4 a 1 en la lista, de la lsita ya tenemos puesto
para usar el mux y tenemos definido las entradas de selección las salidas y las entradas,
al crear estas dos señales locales lo que hemos hecho el mux listo para usar y los bloques
listos para poner los valores lógicos, nos falta conectar y poner una salida.

Creemos una salida que también será otra señal local y falta la conexión, entonces
necesito una señal de salida:

signal salidaMUX std_logic;

Lo que falta hacer son las líneas de conexiones, entonces para hacer las conexiones se
hace con la sentencia port map, la xcual va afuera del process ya que el process va a servir
para dar valores, mientras que el port map va a servir de conexión entre las señales que
guardaron los valores y la entidad.

La forma más fácil de hacer las conexiones es poner los nombres de esta manera, en el
mismo orden entonces entradas va a conectarse con entradamux, luego va la entrada de
selección y se conecta la señal seleccionMUX, luego iria la salidaMUX, crearemos en la
parte de sales la salida negada y finalmente iria la salida negada mux

signal salidaMUX, salidanegMUX std_logic;

51
Port map (entradaMUX, seleccionMUX, salidaMUX, salidanegMUX);

Se está escribiendo de manera abreviada la conexión entre entradaMUX y entrada, debe


observar que se pone exactamente en el mismo orden que en el port principal de la
entidad, entradaMUX es de tipo de 3 a 0 entonces va con entradas de tipo 3 a 0.
EntradaMUX que es de tipo de 2 bits con la de selección, la salida de una sola con
salidaMUX y salidanegMUX con salida negada, esa es la forma abreviada de hacer eso.
La otra forma que se puede encontrar en libros es la siguiente:

Port map (entradas <= entradaMUX, selección <= seleccionMUX, salida <=salidaMUX,
salidaneg <= salidanegMUX);

Esta sería la forma no abreviada de escribir lo mismo, el caso anterior es lo mismo, pero
con menos sentencias, con menos palabras poniéndolas exactamente en el mismo orden,
en la segunda forma se puede poner en cualquier orden que se quiera, no debe estar de
manera especificada el orden.

Entonces con esa línea creamos als conexiones y está casi listo, lo único que falta es dar
valores, en una compuerta lógica solo se da valores a las entradas, la salida debe ejecutarse
sola.

Se debe ar valores a entradaMUX y a seleccionMux, a entradaMUX como es un vector


debe asignársele el valor entre comillas dobles el valor “0000”, luego se pondrá que la
otra señal local seleccionMux que también es un vector el valor “00”

pr1: process
begin

entradaMUX = "0000"; seleccionMUX = "00";

Con eso hemos puesto un valor a las entradas y un valor a selección pero hay que recordar
que en las señales lógicas que vemos a la salida, se debe esperar un tiempo para que pueda
verificar como cambia la salida, ahí viene el uso del wait for porque no se necesita que
cambie nada solo que vaya cambiando en cierto tiempo.

entradaMUX = "0000"; seleccionMUX = "00"; wait for 10ns;

Se pone wait for en las entradas y en las entradas de selección, y espera 10 nanosegundos.
La propia entidad va a crear la salida y como ya está conectada las dos slaidas ella le da
valores a salidaMUX y a salidanegMUX. Solo cambia porque la entidad tiene su lógica
interna y saca un valor a las salidas y como ya están conectadas la salida normal esta
conextada a salidaMUX, la salidaneg a salidanegMUX entonces aquí va a asalir lo que
ya proceso la entidad que estamos probando. Ya procesado saca las respuestas en las dos
señales locales salidaMUX y salidanegMUX .
Digamos que queremos probar cuatro posibilidades

52
entradaMUX = "0000"; seleccionMUX = "00"; wait for 10ns;
entradaMUX = "0010"; seleccionMUX = "10"; wait for 10ns;
entradaMUX = "0100"; seleccionMUX = "01"; wait for 10ns;

entradaMUX = "1000"; seleccionMUX = "11"; wait ;

Solo se debe notar una cosa más, la última de ellas se le pone un wait sin tiempo ni nada,
se lo pone para indicar al process que cuando encuentre ese wait sin tiempo como infinito
diga que ya llego al final del process y salga del bloque, caso contrario si no se pone el
wait si no un wait for 10ns, va a esperar los 10ns, pero luego se queda ahí, no sabe que
acabo el process y se queda colgado.
Código completo:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity MUX4a1_tb is

end MUX4a1_tb;

architecture behaviour of MUX4a1_tb is

component Mux4a1 is
Port (entradas in std_logic_vector (3 downto 0);
seleccion in std_logic_vector (1 downto 0);
salida out std_logic;
salidaneg out std_logic);
end component;

signal entradaMUX std_logic_vector (3 downto 0);


signal seleccionMUX std_logic_vector (3 downto 0); --señal de
selección
signal salidaMUX, salidanegMUX std_logic;

begin
port map (entradaMUX, seleccionMUX, salidaMUX,
salidanegMUX);
-- port map (entradas <= entradaMUX, selección <=
seleccionMUX, salida <=salidaMUX, salidaneg <= salidanegMUX);

pr1: process
begin

53
entradaMUX = "0000"; seleccionMUX = "00"; wait for 10ns;
entradaMUX = "0010"; seleccionMUX = "10"; wait for 10ns;
entradaMUX = "0100"; seleccionMUX = "01"; wait for 10ns;
entradaMUX = "1000"; seleccionMUX = "11"; wait;

end process;

end behaviour;

No sabe que acabo el proceso y se queda colgado, se queda ahí hasta que de alguna forma
acabe el proceso. Por eso es importante el último wait sin nada, para indicarle que
llegamos al final y que tiene que terminar. Si queremos que cambie cuando alguna entrada
cambie, podemos poner wait on entrada mux (0), entonces mientras no cambie va a
permanecer en ese estado. Cuando se tiene en vectores tienen que ser de la misma
dimensión por lo que no se puede igualar a un std_logic, tampoco se puede comparar una
salida mux si fuera una salida, pero si es una salida loca si puede ser leída y comparar.
Quartus nos quita el proceso crear esto de aquí, esto podría servirnos si queremos que nos
de algún mensaje, poniendo salida específicas creando un array con las salidas correctas
e ir comparando lo que sale en las salidas y lo que debería salir según el índice que le toca
y cuando una cosa no salga mandar a otra consola donde nos aparezca el mensaje de En
la iteración 10 hubo un error y con eso estaríamos probando todas las posibilidades de
manera automática y nos dice el error cosa que no se podría hacer en el University
Program View.

Barrido de display
La entidad va a ser del barrio de display, necesitamos primero que lleguen códigos de 7
segmentos, como el barrido de display es automático también necesitamos una señal de
reloj. Necesitamos 4 entradas de código de 7 segmentos porque necesitamos uno para
cada display que tenemos en la tarjeta de desarrollo lo cuales tienen que ser
std_logic_vector lo cuales tiene que ser de 8 bits (7 downto 0). Hemos creado las entradas
necesarias, solo tenemos una salida la cual es tipo std_logic_vector (7 downto 0), y por
último necesitamos nuestra variable de barrido la cual va a ser tipo std_logic_vector(3
downto 0) de 4 bits. De entradas tenemos el clock para que sea automático, los cuatro
códigos en 7 segmentos que teneos que poner en cada uno de los displays y como es un
barrido tiene una sola salida y tenemos una salida que sea de barrido de 4 bits. Recuerde
que este barrido se activa cada display con 0 lógico y la entidad de código de bcd a 7
segmentos ya nos da listo para este tipo de display para conectarle nada más. Solo para
probar se crea señales auxiliares que contengan números en 7 segmentos: num7seg1,
num7seg2, num7seg3 y num7seg4, todos ellos tienen que ser tipo std_logic_vector (7
downto 0), para inicializar no se los pone todos iguales por lo que podemos inicializar
cada uno.

54
Esta parte solo sirve aquí debido a que no se tiene una señal de entrada, simplemente
vamos a poner directamente los números para comprobar si funciona y ver si sale los
numero bien en el FPGA.

Ahora viene la parte secuencial y para esto se necesita crea un process que tenga variables
sensitivas. Estas variables sensitivas a definir son: el cambio de process mediante una
señal de reloj y lo que debe ponerse cuando se cambia las entradas (en caso de que las
entradas cambien).
Architecture arch1 of barridoDisplay is
Signal num7segm1 num7segm2 num7segm3 num7segm4
num7segm1 := “10110000”; -3
num7segm2 := “10100100”; -2
num7segm3 := “10010010”; -5
num7segm4 := “10000000”; -8
Begin
Process(clk, num7segm1, num7segm2, num7segm3, num7segm4)
Begin
End process;
End archi;

El problema que se presenta es que solo se está simulando y todas las entradas van a ser
cero. Si fuera normalmente para dejarlo funcionando basta con dejar el código planteado
tal cual estaba anteriormente, pero como no se quiere hacer la parte de binario a BCD y
de este a 7 segmentos se pone todas las entradas dentro del process. La solución
simplemente es dejar la variable clk dentro de process porque no se tiene las entradas
necesarias para realizar esta actividad.
Architecture arch1 of barridoDisplay is
Signal num7segm1 num7segm2 num7segm3 num7segm4
num7segm1 := “10110000”; -3
num7segm2 := “10100100”; -2
num7segm3 := “10010010”; -5
num7segm4 := “10000000”; -8
Begin
Process(clk)
Begin

55
If clk’event and clk = ‘1’ them
If cnt= them
barrido <= auxBarrido;
cod7seg_out <= num7seg4;
auxBarrido <=”1101”;
cnt = cnt + 1 ;
elsif cnt=1 them
barrido <= auxBarrido;
cod7seg_out <= num7seg3;
auxBarrido <=”1011”;
cnt = cnt + 1 ;
elsif cnt=2 them
barrido <= auxBarrido;
cod7seg_out <= num7seg2;
auxBarrido <=”0111”;
cnt = cnt + 1 ;
else
barrido <= auxBarrido;
cod7seg_out <= num7seg1;
auxBarrido <=”1101”;
cnt = cnt + 1 ;
End process;
End archi;

En este momento se empieza a escribir la función del clock. Necesitamos que la actividad
se realice cada vez que el clock cambie y este a subes se produzca en el flanco de subida.
Ahora se comienza a escribir cada uno del caso, esto se puede hacer mediante el uso de
un if o un case. Para este caso se utiliza un case ya que podemos decirle como van las
cosas. “barrido” es la señal que tiene que salir por lo que se crea una señal auxiliar “aux
barrido” de tipo stdlogic_vector de 4 bits. A esta variable se la inicializa en el valor
“1110”.

56
Luego se procede a crear un contador ‘cnt’ de tipo integer que vaya desde el 0 a 3. Si el
contador es 0 la señal de barrido va a ser igual a la señal auxiliar de barrido. Luego este
variable debe actualizarse para que el valor cero de ‘1110’ cambie a ‘1101’. Finalmente
se debe aumentar la señal del contador en 1. Se copia esta condición 4 veces y se mueve
el valor de cero del contados hasta que sea de nuevo ‘1110’. Aquí la variable ‘cnt’ nos
dirá cuál es el display que va a prenderse, en este caso los display se prenden de derecha
a izquierda. La variable ‘’ barrido también debe irse actualizando conjunto con los 7
segmentos de salida. En un principio el auxiliar de barrido se encuentra en una posición,
al momento que se ejecuta el process se prende los 7 segmentos de la izquierda. Luego se
actualiza el aux barrido para que la siguiente vez que entre se ejecute, se active el siguiente
7 segmentos. Esto sucede hasta que la variable auxiliar vuelva a tener su estado original.
Aquí se tiene el comportamiento de las señales y de las entradas que se actualizaban al
final del process para realizar la operación del barrido de un display.
¿Qué pasa si no se hace cero la variable cnt al final y se le pone cnt=cnt+1?

En el rango se tiene que cnt variable de 0 a 3, por o tanto solo se ocupa dos bits. Si se
sube más de una variable de dos bits se suma un uno más en binario y el valor extra se
iría al carry y por tanto puede que la variable se haga cero. La desventaja de esto es que
si alguien externo quiere analizar el código tal vez no entienda lo que sucede en esa parte
del código
Divisor de Frecuencia
El problema del led que se usan en las tarjetas es que no fusionan a una frecuencia de
50MHz sino a una frecuencia menor de 30MHz y con eso se puede visualizar como se
prende y se apaga el led caso contrario este queda encendido opacamente. Para esto es
necesario bajar la frecuencia para que todo el barrido del display funcione a frecuencias
más bajas y se logre ver bien los números.

En este caso se requiere bajar la frecuencia de 50MHz a 1MHz. Se sabe que lo más básico
para hacer un divisor de frecuencia es hacer un contador, ya que cada cuenta va hacer que
la frecuencia baje en al menos en 2. Entonces para este ejemplo se hace un contador que
va a dividir los 50MHz para cuanto estemos poniéndole el máximo del contador. En este
caso si divido 50MHz para 500 obtenemos una frecuencia de 100KHz. Si se quiere poner
a 1MHz se tiene que dividir 50MHz para 50 y con eso se obtiene la frecuencia deseada.
En este caso el contador ira contando hasta que el valor sea menor a la cuenta máxima,
que en el ejemplo son 50, y cada vez que llegue a la cuenta máxima, se cambiara el estado
del reloj y por último el contador se estaría haciendo 0.

Al cambiar la señal local de valor, se activaría un process que tomaria el clok state y lo
saca or la salida clko y asi básicamente estaríamos haciendo un divisor de frecuencia. El
rango del contador es desde 0 hasta la máxima cuenta que en este caso es 50.

Architecture behaviour of clk_1MHZ is


constant max_count: INTEGER := 50; --50 000 000 / 50 = 1 000 000

57
signal count: INTEGER range 0 to max_count;
signal clk_state: STD_LOGIC := “0”;
begin
gen_clock: process(clk50mhz)
begin
if clk50mhz” and clk50mhz= “1” then if clk50mhz event end clk5mhz
if count < max_count then
count <= count+1;
else
clk_state <= not clk_state;
count <= 0;
end if;
end if;
end process;

Para que funcione el FPGA necesitamos dos cosas: el divisor de frecuencia y el barrido
del display.

¿Cómo se usan las dos cosas al mismo tiempo? Es necesario utilizar un componente con
otra entidad que utilice tanto el barrido como el divisor de frecuencia.

Arquitectura estructural
La arquitectura estructural lo que decimos es que al aumentar la complejidad de los
dispositivos a modelar podemos hacer usos de aquellos dispositivos ya creados
anteriormente y unirnos en un elemento más complejo, que es al final lo que tiene la
arquitectura estructural. Para ello esta arquitectura se basa en los componentes que hemos
visto, mismos que se declaran entre el Begin y la declaración de la arquitectura, una vez
definido este componente se usa un mapeo de señales locales con nuevo componente a
usarse dentro de esta arquitectura, La forma básica para crear un componente, como ya
hemos visto es, el componente, el nombre del componente y los puertos que tiene creados,
esos puertos tiene creados el componente anterior tiene que estar exactamente con los
mismo nombres y en el mismo orden que el componente anterior, caso contrario dará
error. Por ello es que cada vez que creamos un componente lo único que hacíamos es
copiar el componente anterior o el original y pegábamos en la parte en la que se declaraba
el componente.

58
COMPONENT nombre [IS]
[GENERIC (lista_parametros);]
[PORT (lista_de_puertos);]
END COMPONENT nombre;

Ejemplo component

Architecture benhaviour of Bin2_BCD_11bits is


Component IC74185 is
Port( a : IN Std_Logic_vector(4 downto 0);
Y : Out Std_logic_vector(5 downto 0));
End component;
Begin

Como se puede ver en el ejemplo un componente creado, con su nombre y los puertos de
entrada y salida con los cuales está constituido.

PORT MAP
Luego tenemos que hacer el mapeo, atreves de un port map, para hacer el mapeo de los
puertos necesitamos una etiqueta, es decir cualquier nombre, luego el nombre del
componente , luego la sentencia ‘’port map’’ y entre paréntesis colocamos las señales
locales que nos van a permitir hacer conexiones, lo que decíamos es que estas señales
deben estar en el mismo orden y tienen que ser del mismo tipo de dato y extensión que
los puertos de entrada y salida de los puertos que queremos mapear.

Architecture benhaviour of Bin2_BCD_11bits is


Component IC74185 is
Port(a : IN Std_Logic_vector(4 downto 0);
Y: Out Std_logic_vector(5 downto 0));

End component;
Signal auxU1, auxU2, auxU3;
Signal auxIU2, auxIU3;

Begin
u1: port map (B(11 downto 7),auxU1)

59
En este caso IC75185 tenemos como puerto de entrada un vector de 5 bits, como vemos
en la parte inferior B, que es un puerto de entrada de la entidad que esta usando este
componente, le estamos diciendo que este puerto de entrada vamos a tomar solamente
desde el 11 hasta el 7, es decir 5 bits, y debe ser del mismo tipo, es decir std_logic_vector.
Mientras que auxU1 que es una señal local y std_logic_vector también, va a ser igual de
6 bits. De esta manera es una forma abreviada de hacer un mapeo de componentes.

Desarrollo de ejemplo de Arquitectura Estructural


Desarrollo de un ejemplo usando Arquitectura Estructural de un multiplexor de 8 a 1, a
partir de multiplexores de 2 a 1, que sería lo más básico para crear una arquitectura
estructural.

En la imagen podemos ver de qué componentes lógicos está conformado un multiplexor


2 a 1, en este caso está conformado por compuertas and, una compuerta not y una or.
Toda esa estructura estaría expresada como una estructura flujo de datos una sola línea, y
con eso obtendríamos un multiplexor 2 a 1.

Para crear un multiplexor lo que tendríamos que hacer es hacer una conexión de manera
secuencial entre multiplexores 2 a 1, para crear un multiplexor 8 a 1.

Para tener un multiplexor de 8 a 1, tendríamos que tener creado un componente llamado


mux 2 a 1 para poder crear un componente llamado mux 8 a 1, tendríamos que
interconectar 7 mux de 2 a 1, obteniendo el mux de 8 a 1 que se puede ver en la imagen.

60
Para hacer esas conexiones utilizamos señales locales, ya que al hacer el mapeo sabíamos
que tendríamos que poner todas las entradas y salidas de las que estaba creado el
componente mux de 2 a 1, la señal de salida del mux 2 a 1 debería estar conectada a una
señal local, tipo std_logic que me sirva para mantener el valor del bit del componente y
esa misma señal colocara como entrada del siguiente componente. Por lo tanto, se deberá
crear señales locales para la conexión entre componentes, pero no se necesitaría crear
estas señales para las entradas de control, ya que estas pueden ir conectadas directamente
mediante el port map a cada uno de los mux 2 a 1.

Para crear el componente del mux 2 a 1 se utiliza la estructura flujo de datos y como se
indica en el siguiente código:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity mux2a1 is
port( A,B,S : IN STD_LOGIC;
Y : OUT STD_LOGIC);
end mux2a1;

architecture behaviour of mux2a1 is


begin
Y <= (A and not S) or (B and S);
end behaviour;

Ahora creemos un mux 8 a 1, a partir del grafico podemos determinar cómo entradas un
vector de 8 bits y el selector de 3 bits, y por último la salida que va a ser tipo std_logic.
Creado ya la entidad, lo que nos faltaría es crear los componentes de la forma vista
anteriormente, ahora debemos hacer el mapeo de los puertos, este mapeo se lo hace en la
parte del ‘’ Begin’’, para ello primero se debía poner un nombre a cada uno de los mux
como nombrarlos del 1 al 7 y luego se procede realizar a las etiquetas, se coloca que tipo
de componente se desea usar en este caso un 2x1 y a ese se va a mapear, se lo coloca:
entradas, selector, salida la cual estaría conectada a una señal auxiliar entonces se la
procede a crear, con esto estaría listo un mux 8 a 1.

library IEEE;
use IEEE.STD_LOGIC_1164.all;

61
entity mux8a1 is
port (entrada: IN STD_LOGIC_VECTOR (7 downto 0);
seleccion: IN STD_LOGIC_VECTOR (2 downto 0)
Y: OUT STD_LOGIC);
end mux2a1;
architecture behaviour of mux8a1 is
component mux2a1 is
port (A, B, S: IN STD_LOGIC;
Y: OUT STD_LOGIC);

end component;
signal aux_mux1, aux_mux2, aux_mux3, aux_mux4, aux_mux5,
aux_mux6: STD_LOGIC;

begin
mux1: mux2a1 port map (entrada (0), entrada (1), seleccion (0),
aux_mux1);

mux2: mux2a1 port map (entrada (2), entrada (3), seleccion (0),
aux_mux2);

mux3: mux2a1 port map (entrada (4), entrada (5), seleccion (0),
aux_mux3);

mux4: mux2a1 port map (entrada (6), entrada (7), seleccion (0),
aux_mux4);

mux5: mux2a1 port map (aux_mux1, aux_mux2, seleccion (1),


aux_mux5);

mux6: mux2a1 port map (aux_mux3, aux_mux4, seleccion (1),


aux_mux6);
mux7: mux2a1 port map (aux_mux5, aux_mux6, seleccion (2), Y);

end behaviour;

Si se desea conectar entre componentes internos se necesitaría crear usar señales locales
que sirvan como los auxiliares como en este caso, existe la posibilidad que no se use
ciertas señales que deban estar en el mapeo en esta situación se debe crear estas señales
auxiliares, aunque no se las utilice o se generaría un error

62
Prueba de barrido de display

Entonces esta prueba de barrido de display necesita tener puertos de salidas, pero no de
entradas ya que en la otra entidad previa ya se puso un valor a unas entradas virtuales; a
excepción del clock(clk) que si es una entrada requerida para las componentes. Las salidas
son dos, una será una llamada cod7seg_out que es del tipo out y del tipo std_logic_vector,
es de 8 bits; y necesitamos de uno que se llame barrido de tipo igual al anterior, pero de
3 bits, y así quedaría listo nuestra prueba de barrido.

En la definición de la arquitectura, como vamos a utilizar los otros componentes que se


acaba de crear, se tiene que ponerle los componentes. Las componentes que vamos a
utilizar se llama barridodeDisplay con todo el código de la entidad anterior, copiamos
igual dentro de la arquitectura y el único cambio que realizamos es que en vez de poner
end barridodeDisplay se pone end component.

El otro componente a utilizar se llama clk_1Mhz, que es otorgado por el instructor, es


decir que asumimos que ya está creado; esta componente tiene dos puertos, un clk de 50
Mhz como entrada std_logic y de salida tengo un clk de 1Mhz también std_logic.

Entonces lo que tenemos es una entidad grande que va a conectada al display con una
sola entrada que es el clk. Dentro de esta entidad se tiene uno que se llama
barridodeDisplay el cual tiene que conectarse sus salidas, el reloj va primero a otro al
clk_1Mhz, que lo que hace al entrar un clk de 50 Mhz nos da a la salida un reloj de 1
Mhz, y ese es el reloj que debemos conectar al display.

Se necesita una señal intermedia ya que el clck de 50MHZ va como entrada al bloque o
entidad del barrido…

Y aquí esta salida que tenemos que conectarle, aquí le vamos a poner en una señal local
pongámosle aux clock, ya, en este otro se va a guardar momentáneamente lo que salga de
esto y esta le ponemos como entrada de esta de acá, estamos? , y ahí si estos de acá como
ya tienen.. eh, directamente la salida estas de acá, estas ponemos como argumento en la
parte del PORT_MAP, le conectamos directo al port_map de este y al portmap de este. y
quedaría… porque este de aquí como no tiene más entradas, porque pusimos esas entradas
virtuales que le ponemos nosotros mismo los números no tenemos entradas, solo tenemos
salida, salida y listo…Si? Hasta ahorita tenemos eso.
Entonces ahora si claro esa parte…
Entonces ahora sí con esa parte clara de lo que estamos haciendo, veamos aquí…
Entonces tenemos que crear una señal auxiliar que se llamaba aux_clock…. Una señal
local llamada aux_clock que es tipo std_logic nada más…

Entonces aquí comenzaríamos a poner lo que necesitamos, entonces vamos a crear


primerito el reloj, entonces vamos a poner como etiqueta clock de que tipo es, se llama
clock_1MHz y vamos a comenzar a hacer las conexiones azules que son ahí no, en el
gráfico, clock 1MHz, portmap y que le pongo, este tiene una señal de entrada de 50 MHz,

63
la señal de entrada de 50 MHz es esta verde que se llama solamente CLOCK…. Clock y
tiene una señal de salida Clock_Aux que iba a ser mi auxiliar Clock y ya está creada la…
creado el primer componente que teníamos ahí arriba, luego necesitamos uno que se llame
barrido… pongámosle display nomás para que no… así se va a llamar este otro
componente de que tipo va a ser?, de tipo barrido_display… Y le ponemos, y le
comenzamos a… vamos a comenzar a conectar las cosas, ¿qué tiene este barrido de
display? Lo que tiene aquí arriba podemos ver es un clock que tiene que ser de 1MHz, el
Clock de 1 MHz es el auxiliar… Entonces le ponemos primero este luego dice que tiene,
un 7 segmentos de salida, ese 7 segmentos de salida, a cuál tiene que conectarse? A este
de aquí que le he llamado igualito, ¿no cierto? A través de esas líneas azules es lo que
estamos haciendo ahorita, las líneas azules de salida a las de salida a esos pines de salida
y luego, ¿qué me falta?, dice que tiene barrido y aquí hay un barrido que se va igualito…
¿Y tendré que hacer algo más? ¿O ya está hecho todo?

¿Ya está hecho todo no cierto? Porque todo esto ya está conectado e interconectado entre
las varias entidades también y ya está creado todo esto ya está listo, lo único que me falta
hacer, bueno es todo esto pasarle al QUARTUS y qué más?... Y hacer en el quartus el
PIN PLANER para coger ya y conectar a los pines.

Esto es lo principal, como la principal y al que usamos todos los componentes se llama
PRUEBA BARRIDO DE DISPLAY, así se va a llamar el proyecto, digo que es así y así,
de ahí voy a seleccionar cuál…. Solo necesito este, es que solo quiero el archivo VHDL
del Clock 1MHz que ya estaba listo, le asigné y le extraje de otro lado y ahí le pongo el
C8, voy a copiar y pegar… solo voy a copiar y pegar. CtrlA y CtrlC..

Entonces creo un archivo VHDL CtrlV CtrlS, le guardo aquí… Se llama Prueba Barrido
Display.
Ya está listo, ahora vamos a crear el otro, otro VHDL.
Bueno, Una vez ya hecha la revisión de la arquitectura estructural y de cómo es que
funciona podemos proseguir al cuarto punto de este curso.

El punto A de la estructura física y nomenclatura La que se refiere a la comprensión de


cómo está el esquemático, es decir, este que hemos visto ya en unas ocasiones para ver la
parte del barrio del display, la parte de los deep switchs y los pulsadores y también la
comprensión de cómo verificar o que significa nuestro excel que contiene los nombres
que tenemos en el esquemático del PDF, aquí están estos nombres y a que pin
corresponden;

estos pines no servían para poder crear el PINPLANER y poder conectar nuestras entradas
y salidas directamente a pines físicos de la fpga.

¿De eso tenemos alguna inquietud?, de una vez para..., porque eso solamente era él
PINPLANER, ¿no?
...eh listo, bueno como no hay inquietudes podríamos seguir.
...eh estos dispositivos ya eran los últimos ya no necesitamos.

64
Ahora sí, el punto B es ya hacer pruebas en el Hardware.

El primer punto que corresponde a la prendida de un LED y el uso de pulsadores con el


uso del PINPLANER, esto ya lo hicimos en el primer día.

Verificación de los rebotes:

Los rebotes como ya lo hemos visto, para un sistema digital que sea de alta velocidad va
a ser de mucha importancia tener un control sobre los rebotes ya que los rebotes podrían
dar falsos positivos sobre una pulsación en algún botón. entonces aquí sólo vemos cómo
los rebotes aparecen y desaparecen al pulsar un botón entonces esa cantidad de rebotes
puede ser percibida por el Hardware como si fueran pulsaciones individuales hechas por
el usuario, aunque realmente sólo son rebotes.

Este PDF que mostramos ahora nos permite ver cuánto es que se demora en estabilizarse
la señal y desaparece los rebotes, como vemos aquí cada una de las letras corresponden
a un tipo distinto de pulsador y tenemos que en el peor de los casos estamos entre 10
milisegundos y 12 milisegundos de duración en el caso de cerrar el pulsador, en el caso
de abrir el pulsador estamos entre 5 y 6 milisegundos, entonces lo que tenemos que hacer
es crear mediante software una entidad que me permita hacer una espera para que pasen
los 10 milisegundos, que normalmente duran los rebotes para que la señal se estabilice y
tomar la señal luego de esos 10 milisegundos momo la señal que es real y ya con eso
evitar que los rebotes afecten mi aplicación.

Entonces aquí podemos ver una identidad que se encarga de hacer una espera de 10
milisegundos verificando el estado del pin, entonces lo que se hace es un contador, en
este caso vamos a hacer un contador de 20 bits sabiendo que tenemos un reloj de 50
megahertzios como en realidad el contador no va a contar hasta el final sino hasta que el
bit más significativo sea uno podemos utilizar un valor n que lo igualamos a 19 para una
aproximación aceptable, es decir, cuando el numerador 20, numerados desde el 0 hasta
el 19 se vuelva 1, significa que 2 elevado a la 19 qué es el que equivaldría a ese bit
dividido para los 50 megahertzios nos va a dar un valor de de 10.5 milisegundos que es
el valor que tenemos que esperar ,es decir, vamos a tener un contador que vamos a ir
verificando el último bit, cuando es el último bien se vuelva uno significa que vamos a
estar alrededor de los 10.5 milisegundos al usar un reloj de 50 megahertzios, esta fórmula
tendría que ser cambiada si usaramos relojes distintos, entonces estamos dejando un
margen de 10 milisegundos para que se estabilice la señal del pulsador lo que es un valor
razonable para un pulsador normal qué es lo que hemos visto en el PDF anterior, que ese
tiempo es bastante razonable.

Entonces lo que tiene esta identidad “debouncing” o antirrebote es un route, este route
nos va a servir para hacer verificaciones automáticas cada ciclo de rebote por lo tanto este
reloj va a ser el reloj de 50 megahertzios de nuestra tarjeta de desarrollo. Tenemos un
botón de entrada es decir la señal que vamos tomando desde el botón, tenemos una señal
llamada botón de salida que va a ser la señal a la que vamos a tomar en cuenta toda la

65
aplicación ya que la señal botón de entrada va a ser la señal que va a contener todos los
rebotes y la señal botón de salida es la que va a ser completamente sin rebotes va a ser
estable.

Entonces en esta arquitectura lo que tenemos es la definición de un contador, de un


tamaño de contador que en este caso va a ser de 19 bits; una señal local llamada botón
previo va a usarse como una señal intermedia que va a contener valores de botones de
entrada y al hacer una comparación entre la señal previa y el valor del botón de entrada
actual si son diferentes significa que todavía habrá rebotes pero si son iguales significa
que la señal se mantendría estable y se acabarían los rebotes, y el contador que es un std
logic vector que va a ir desde el valor o del tamaño que queremos de 19 bits hasta 0,
bueno 20 bits hasta 0, y todos van a ser, eh... este contador va a estar encerado.

Aquí, bueno no se ve, voy a copiar esta línea para que se vea la parte vector que está
puesta en color negro, esta sería la línea que tenemos en la 56, aquí tenemos un process
que va a ir verificando cada vez que el clock cambie lo que va a verificar es lo siguiente:
en los flancos de subida qué dice aquí, cuando exista un evento en el clock y este en 1
vamos a verificar a través de una función lógica xor entre el botón previo y el botón de
entrada cuando el botón previo sea igual al botón de entrada, está eh.., o cuando sean
diferentes va a ser igual a 1 significa que todavía la señal no está estabilizada por lo tanto
el contador debería encerarse para que se siga contando hasta el 19 y poder llegar a los
10 milisegundos, y actualizamos el valor del botón previo con el valor del botón actual.
caso contrario cuando estas dos señales sean iguales significa que: podría ser que el estado
ya estaría, el estado de la señal del botón se estaría estabilizando, significa que tendríamos
que comenzar a contar los 10 milisegundos qué tenemos que esperar y estamos esperando
a través de este else if, que el bit número 19 del contador mientras permanezcan 0 seguirá
contando cuando estés llega al 1 lo que va a pasar es que el botón de salida o la señal de
salida que ya va a ser estabilizada va a tomar el valor del botón previo porque ya está
estabilizada la señal y con eso acabaríamos esta identidad de anti rebote.

...Tal vez tiene inquietudes de porqué es cómo funciona esto, para explicarles luego el
anti rebote?

Entonces resumiendo esto, lo que hace, tiene una señal de entrada que es la señal que
entra del, tenemos una señal local que es una señal intermedia que nos permite poder
verificar el valor de la señal. Entonces tendríamos que. digamos que va de 1 a 0 , así,
pero en este momento en la señal aquí aparecen los rebotes y luego de un rato la señal se
estabiliza y se hace así, lo que hace el botón inicial es sacar este valor ir tomando los
valores y el botón previo sería de este otro k, este sería el de entrada y el previo, mientras
se mantengan distintos los valores ,es decir, cuando está xor de igual a 1 porque son
distintos ,este de aquí el contador se va a detener en 0, porque significa que, eh no va a
detenerse en 0 sino que para reinicializarse a cero, porque tiene que de aquí, cuando esto
al fin se estabilice y este de aquí en la entrada, que esté aquí y el previo que esté acá estén
iguales porque puede ser que por aquí haya rebotes, digamos que cogemos en esos dos
puntos y los rebotes estaban ahí, en ese caso si es que le dijéramos que ya es un estado
estable porque estos dos fueron iguales, pero aquí realmente todavía había rebotes, eh..

66
fuera un falso positivo, por eso solamente cuando en ningún punto estos dos son
diferentes...

Ahí le decimos que siga contando es decir que ya en este punto de por acá, cuando ya los
rebotes desaparecieron, el de entrada y este sería el previo, ahí en este punto de aquí en
adelante esperamos diez mili segundos porque ahí ya no entramos a este punto que encera
al contador si no que comenzamos y mientras el contador no llegue el ultimo bit a ser uno
este contador sigue, sigue sigue, y cuando llega el ultimo bit a 1 saltamos a este punto de
acá, en el que el botón previo es decir este que ya está completamente estable en la señal
va a salir al botón de salida que sería la señal estable y con eso evitamos los falsos
positivos y todos los rebotes, esa es la lógica de funcionamiento de ese código

si es que tendríamos otro reloj más rápido tendríamos que cambiar el tamaño del contador
es decir ese 19 podría cambiarse con respecto a la fórmula que vimos al principio, para
que siempre nos dé al menos 10 milisegundos de espera desde el punto que ya estabilizó
la señal. Ese es toda la lógica de un anti-rebote hecho por software.

Ahora lo que nos dice es verificación de los rebotes y creación de entidad anti-rebote que
sería esto de aquí, que bueno ya les voy a pasar esa entidad entera. El trabajo entorno es
un contador binario de 4 bits usando la arquitectura funcional, que se incremente cuando
pulse un botón y comprobar con y sin rebotes, entonces lo que tendríamos que hacer
ahorita es crear un contador binario de 4 bits es decir que vaya contando y que nos permita
ver a través de solamente estos leds la función de un contador que vaya aumentando, es
decir el clock de ese contador va a ser mi pulsador que pase flanco de bajada, de bajada
me parece que está el datasheet de este, y ver qué pasa con el contador, el contador al
momento que tengamos rebotes esto va a ser super inestable, pero al memento que le
pongamos la entidad anti-rebotes este ya va a ser completamente estable y va a contar
entre 4 bits a 4 bits.

Entonces hagamos eso, hagamos juntos esto de aquí. Entonces hagamos el contador, el
contador podemos usar el contador que ya hicimos alguna vez y le hacemos solamente
para que sea de 4 bits, reutilicemos el código, teníamos una arquitectura funcional y
teníamos un contador, que era el contador 3210 en este caso 5374, copiemos todo y
cambiémosle un poquito… Qué sería un contador módulo 16 le voy a poner en este que
dice anti-rebote, enter… todo este módulo solo va a ser 16, todo el módulo 16… El reset
y el neibolt podríamos quitarlos solo en este caso, solo que dependa del clock, siendo el
clock en este caso ahora el pulsador, la cuanta solamente como es de 16, ahora debería ir
de 4 bits del 3 al 0. Aquí le voy a cambiar el nombre, de aquí arquitectura, y vamos a
crear un contador solamente de 4 bits.

En el proceso, el proceso ya no debería de depender del preset ni del reser, solamente del
clock, por lo tanto, este if ya no dependería del resert solo dependería del contador, que
el contador cuando se haga 16 el contador se haga 0 ya que el módulo es del 0 al 15, listo,
veamos el flanco que es esto, aquí tenemos cuando pulsamos uno de los eh, tenemos un
pulsador, aquí le cerramos pararía de ver un 1 lógico a ver un 0 lógico, este punto de aquí.
Entonces sería por flanco de bajada, entonces veamos por flanco de bajada que sería

67
cambiarle aquí de 1 a 0, este neibolt ya no tendríamos que poner este neibolt y tampoco
tendríamos este if, y solo tendríamos que el contador es igual al contador más 1, acabamos
el proceso y acabamos asignando el contador de 3 bits sin signo a el contador que es la
salida, hagamos más grandecito para que se vea ahí tendríamos listo nuestro contador de
módulo 16.

Ahora la entidad principal, lo que tenemos que hacer es usar el contador módulo 16 y usar
la anti-rebote, entonces hagamos esta entidad nueva. Llamémosle no se…
- cómo le llamamos a esto?
- Anti-rebote
- Anti-rebote 16, Contador con anti-rebote

A ver que nomás no va, esto nomás no iría y esto tampoco. Esto se llama contador con
anti-rebote… y listo, lo que me dice acá el proyecto es que vamos a tener un error y si
tiene razón, que aquí el rato que le ponemos 16 al contador, para poner 16 necesitaríamos
5 bits entonces aquí debería ponerle 4 y a este de acá para que solo se vayan las 3, debería
poner 3 down to 0 para que no de error el otro tiene 4 bits, este tiene 5 y este tiene
solamente 4 y solo esos 4 le creo y le mando al común, para poder hacer esto de 16 si no
daría error… ahí estaría, listo, a ver entonces el contador anti-rebote lo que tenemos como,
como entradas, el clock va a ser el pulsador y las salidas van a ser los leds de mi contador
anti-rebote porque ya le voy a poner valores que me digan a que van a estar conectados,
el pulsador va a ser de un solo bit mientras que los leds van a ser de 4 bits porque voy a
usar los 4 leds.

Aquí debería crear las componentes que voy a usar, entonces sería componente, ¿Qué
componente voy a usar?, el contador módulo 16. Aquí debo copiar los puertos, puertos
de entrada y salida de este contador módulo 16….

Luego de copiar los puertos de entrada y salida del contador módulo 16, lo que se procede
a hacer realizar es el antirrebote, para esto utilizamos la función “COMPONENT”. El
componente del antirrebote debe tener las entradas y salidas del tipo que se hayan
declarado anteriormente en el código de esa entidad.

Después de finalizar con la declaración del componente a utilizar se empieza a conectar


con el comando ‘port map’, como entrada del antirrebote vamos a conectar el pulsador,
que es la entrada principal de la entidad mayor del contador, y se conecta el pulsador
porque es el que mantiene la señal con los rebotes. Ese pulsador se pone agrega en el ‘port
map’ del antirrebote, además el código del antirrebote tiene una entrada (la primera en
ser ingresada) que es un reloj, el cual va a detectar algún cambio en el pulsador y envía
ese valor a la señal de salida, como segunda entrada tenemos el botón que va a ser el
pulsador y como último valor se tiene una señal de salida que nos va a mantener la señal
ya estabilizada. Al no tener una variable en la cual guardar esta señal, se crea una señal
auxiliar en donde ya se puede asignar la salida del antirrebote, esta señal auxiliar es del
tipo ‘std_logic’.
¿Qué pasa si yo nunca pulso el antirrebote?

68
La señal del reloj va a cambiar, por lo tanto, todo dentro del código del antirrebote
depende del reloj, entonces la señal de salida del antirrebote va a ser igual a cero ya que
el botón previo en algún caso va a ser = 0. Como estamos esperando que exista algún
cambio, entonces cuando se produzca el primer cambio en el pin de entrada, la salida del
antirrebote va a tomar ese valor, y al empezar el pulsador en cero, entonces la salida
también va a empezar en cero; sin embargo, cuando recién empiece, si el pulsador ya está
en uno como todo depende del clock, la salida del antirrebote va a tener el valor de 1 o si
tiene el valor de cero, la salida va a tener ese valor.

Finalmente, sólo falta agregar el contador, para esto uso el ‘port map’, el contador módulo
16 depende de una señal de reloj y tiene una salida, el reloj va a ser la salida de la señal
sin rebotes y la señal de salida qué es de 4 bits va a ser directamente conectada a los leds
y con eso terminaríamos toda aplicación.

Si queremos el contador módulo 16 funcione sin el antirrebote simplemente eliminamos


el componente del antirrebote y conectamos directamente el pulsador que sería la señal
de reloj, sin pasar por el eliminador de rebotes, para el contador de módulo 16.

La parte final que nos toca ver, es como trabajar con los flipflops, el problema
básicamente que hay, es como habíamos visto en digitales que hay una realimentación
entre la entrada y la salida y esta al hacer una comparación da problemas en la lógica de
flujo de datos, asi que lo que hacemos para construir un flipflop jk, lo que utilizamos
básicamente en la lógica funcional, en la que hacemos es copiar la Tablet

1. Detectamos un franco de bajada que es la forma como/ trabaja el 7476 que


podemos utilizar tanto falling_edge y detectar el evento de cambio en el reloj, en
caso de que queremos variar la lógica de funcionamiento, podríamos utilizar un
rising_edge(raisenet), y en caso de contadores asincrónicos nos permitiría para
cambia la lógica de contadores ascendentes a descendentes y lo único que
hacemos es por medio de condicionales darle una estructura similar a la que tiene
el 7476 como sabemos, lo que nos acordamos de digitales, tanto el set como el
reset funcionan en bajo por eso se da la condición cuando el reset es igual a cero
y cuando el set es igual a cero, y las otra cuatro condiciones simplemente es la
tabla del j y k.

Como sabemos para el contador asincrónico tanto j como k tienen que estar en uno para
que vaya contando progresivamente, nosotros utilizo activa vhdl porque me permite
explicar un poco más gráfica, ya que es más similar a proteus, y puedo ir desde los
gráficos a generar códigos, primero la parte funcional lo hice por códigos, ahora en la
siguiente parte lo que voy hacer es concatenar esto con un componente, pero de manera
gráfica. Los archivos de extensión pde que básicamente son logicdiagram de VHDL lo
que me permite es crear cada uno de los componentes, irlos asociando de manera gráfica
tal como se lo hace en proteus, los signos marcados son porque la simulación está
corriendo.
Básicamente lo que se procede hacer es concatenar tres flipflops jk para conseguir un
contador y hacemos las conexiones como normalmente se trabaja, esta forma es más

69
similar como se trabaja con proteus. Como podemos ver en el gráfico, Q0 Q1 Y Q2, que
son siempre en VDHL, la señales intermedias necesarias para comunicarnos y esa las
comunico a la salida mediante un bus de datos que va al Q2 y al marcador, después de
haber realizado este grafico lo que procedemos a copilarlo y al copilarlo da un código que
se autogenera a partir de un archivo de extensión VVE, se crea el componente de cada
uno de los fliplops y en este caso para hacer un poco similar a lo que se trabajaba
originalmente en proteus usamos constantes para no utilizar 1 y 0 sino una notación
electrónica un poco más similar utilizar gsd y gdb y esas constantes en la parte final de
código están declaradas en 1 y 0, esto solo por semántica para que el grafico se vea más
amigable. Para mi parecer yo utilizo el format complet, porque hay varias situaciones en
que no necesitamos todas las variables y al declarar a la variable que yo voy a asignar en
un orden preciso puedo utilizar un mismo componente sin utilizar todos los atributos,
como lo vamos a ver en el siguiente componente armado.

Para armar este proyecto también necesite armar un comparador, que básicamente es un
comparador básico, que me indica si es que A es mayor que B, A es menor que B, o A es
igual a B, lo único que hago es asignar a las variables mayor, menor o igual, el valor 1 o
0 dependiendo de que si se cumplen la condición o no, podemos realizar la función de un
comparador básico, o como en digitales lo conocemos como 7485, y el otro bloque que
se creó es un decodificador, este decodificador lo único que hace es transformar el igual
en una E, el mayor en una A, y el menor en una B. La idea de este trabajo final era indicar
en un display quien está ganando o si había a algún empate, A significaría que el grupo
A esta ganando, B significaría que el grupo B está ganando, y E que hay un caso de
empate. Cuando queremos ingresar datos en un hexadecimal, ponemos primero la X y
después el valor para hacer una variación y finalmente lo que utilizamos es el armado del
proyecto para lo que voy a utilizar una FORMA GRAFICA, cada uno de los archivos hdl,
se me compilan en una librería, tengo las operaciones lógico normales, y aparte tengo
cada uno de los que cree, y los voy relacionando para hacer una estructura un poco más
similar, a lo que es trabajar con proteus. Básicamente lo único que hago es comparo dos
números, transformo esa comparación a algo tangible, que sería que está ganando A, esta
ganado B, o tenemos un empate, y los dos comparadores lo que hago es comparar con
una constante. El contador que creamos originalmente iba de cero a siete, pero en el
ejemplo íbamos a decir que era un contador de tenis, en tener cada tiempo es de seis, así
que lo que hago es que en caso de que uno de los equipos haya llego a seis, paro el sistema,
como sabemos por medio de un cero, siempre va a dar a la salida cero, y con eso los
contadores ya no seguirían contando, y llegarían a detenerse, esa era la idea abreviada del
proyecto en general. Esto sería el diagrama de prueba, originalmente ambos equipos están
en cero, estaríamos en un empate, después vemos que A hace un punto, A estaría ganando,
B empata, B hace dos puntos, B estaría ganando, esta lógica iría hasta que un equipo
llegara a seis, y terminaría el juego.

Finalmente, la idea sería utilizar dos pulsadores de entrada, y utilizar los cuatro leds, para
mostrar la letra en hexadecimal, y con esto terminaríamos todo. Faltaría mencionar
porque utilizar la estructura del componente completo, al final del proyecto tengo un
componente que se llama comparador, que tiene cinco atributos, pero pueden utilizar el

70
comparador solo con tres, la ventaja de declarar en ambos lados y en un orden adecuado,
me permite utilizar solo las variables que necesito, generalmente las que no son necesarias
siempre las declaro al último.

71

También podría gustarte