Sie sind auf Seite 1von 155

Lenguajes de descripción hardware - VHDL -

Lenguajes de descripción Hardware

VHDL VHDL
Este es un libro electrónico diseñado para Internet en el cual podrás
Presentación
aprender uno de los Lenguajes de Descripción de Hardware estándar en
el mundo: VHDL.
Índice
Con este tutorial conocerás a fondo todos los secretos de la sintaxis, qué
pasos deberemos dar para crear nuestros primeros ejemplos, cómo
Teoría simularlos y hasta implementarlos en un dispositivo de lógica
programable.
Prácticas
Selecciona en el menú de la izquierda la parte del tutorial a la que deseas
acceder.
DET
COMIENZO
EUITI

Links VHDL

http://det.bp.ehu.es/vhdl/pagina/inicio.htm [03/04/02 13:42:16]


Derecha de Lenguajes de descripción Hardware VHDL

Lenguajes de descripción Hardware


VHDL
Este es un libro electrónico diseñado para Internet en el cual podrás aprender uno de los
Lenguajes de Descripción de Hardware estándar en el mundo: VHDL.

Con este tutorial conocerás a fondo todos los secretos de la sintaxis, qué pasos deberemos
dar para crear nuestros primeros ejemplos, cómo simularlos y hasta implementarlos en un
dispositivo de lógica programable.

Selecciona en el menú de la izquierda la parte del tutorial a la que deseas acceder.

COMIENZO

http://det.bp.ehu.es/vhdl/pagina/indexde.htm [03/04/02 13:42:22]


Elige el modo de aprender

Con nuestras prácticas podrás La parte teórica profundiza en la


aprender VHDL de una forma sintaxis del lenguaje, explicando
rápida y práctica, con sólo tener cada sentencia y cada cláusula
de conocimientos de Electrónica minuciosamente, con ejemplos
Digial y de Programación comentados

Teoría
La parte teórica profundiza en la sintaxis del lenguaje, explicando cada sentencia y cada cláusula
minuciosamente, con ejemplos comentados

Práctica
Con nuestras prácticas podrás aprender VHDL de una forma rápida y práctica, con sólo tener de
conocimientos de Electrónica Digial y de Programación

http://det.bp.ehu.es/vhdl/pagina/elegir.htm [03/04/02 13:42:33]


Índice del modo Express

Con nuestras prácticas podrás La parte teórica profundiza en la


aprender VHDL de una forma sintaxis del lenguaje, explicando
rápida y práctica, con sólo tener cada sentencia y cada cláusula
de conocimientos de Electrónica minuciosamente, con ejemplos
Digial y de Programación comentados

Prácticas
En esta parte del tutorial aprenderás VHDL de una forma sencilla y rápida
practicando desde el principio y con posibilidad de simular los diseños explicados
desde esta misma página web. Las prácticas son las siguentes:

0. Conocimientos Básicos (y necesarios)

1. Multiplexor

2. Demultiplexor

3. Codificador

4. Decodificador

5. Comparador

6. Cuádruple Sumador Total

7. Restador

8. Multiplicador

9. Flip-flops

10. Contador

11. Secuenciador

http://det.bp.ehu.es/vhdl/pagina/express.htm [03/04/02 13:42:52]


Índice del modo completo

Con nuestras prácticas podrás La parte teórica profundiza en la


aprender VHDL de una forma sintaxis del lenguaje, explicando
rápida y práctica, con sólo tener cada sentencia y cada cláusula
de conocimientos de Electrónica minuciosamente, con ejemplos
Digial y de Programación comentados

Teoría
En esta parte del tutorial aprenderás todos los secretos de la sintaxis del lenguaje
VHDL, en el cual se estudiará de una forma teórica y clara cómo crear un programa
en VHDL. Este apartado consta de 7 lecciones distintas:

1. Introducción
❍ Breve reseña histórica

❍ VHDL vs MSI

❍ Qué es un PLD

❍ Conociendo el lenguaje VHDL

❍ Cocurrencias y señales

2. Unidades básicas de diseño


❍ Cómo se declara una entidad

■ Modos

■ Tipos

❍ Cómo se declara una arquitectura

■ Estilos

❍ Paquetes

❍ Librerías (incluye exposición de librería LPM)

3. Objetos, tipos de datos y operaciones


❍ Objetos

❍ Identificadores

❍ Palabaras reservadas

❍ Símbolos especiales

❍ Tipos de datos

❍ Expresiones y operadores

❍ Atributos de los vectores

4. Gramática del lenguaje I


❍ Sentencias secuenciales

❍ Asignación a señal

❍ Asignación a variable

❍ Sentencia if

❍ Sentencia case

http://det.bp.ehu.es/vhdl/pagina/completo.htm (1 of 2) [03/04/02 13:42:55]


Índice del modo completo

Sentencia loop

❍ Sentencia exit

❍ Sentencia next

❍ Sentencia null

❍ Sentencia wait

❍ Sentencia wait until

5. Gramática del lenguaje II


❍ Sentencias concurrentes

❍ Sentencia process

❍ Asignaciñon concurrente a señal

❍ Asignación concurrente condicional

❍ Asignación concurrente con selección

6. Interface, compilador e implementación


❍ VHDL sintetizable

❍ Galaxy de Cypress

❍ Nova de Cypress

❍ Grabación de nuestros propios diseños

http://det.bp.ehu.es/vhdl/pagina/completo.htm (2 of 2) [03/04/02 13:42:55]


Lección 1: Introducción

Introducción

● Breve reseña histórica

● VHDL

● Qué es un PLD (Dispositivo de Lógica Programable)

● Conociendo el lenguaje VHDL

● Sentencias Concurrentes y secuenciales

Breve reseña histórica

A mediados de los años setenta se produce una fuerte evolución en los procesos de fabricación de los
circuitos integrados, y junto a las tecnologías bipolares, surge la MOS (metal oxide semiconductor ),
principalmente la NMOS, promoviendo el desarrollo de circuitos digitales hasta la primera mitad de los
años ochenta.

En aquellas épocas, el esfuerzo de diseño se concentraba en los niveles eléctricos para establecer
características e interconexiones entre los componentes básicos a nivel de transistor. El proceso de
diseño era altamente manual y tan solo se empleaban herramientas como el PSPICE para
simular esquemas eléctricos con modelos previamente personalizados a las distintas tecnologías.

A medida que pasaban los años, los procesos tecnológicos se hacían más y más complejos. Los
problemas de integración iban en aumento y los diseños eran cada vez más difíciles de depurar y de dar
mantenimiento. Inicialmente los circuitos MSI (Medium Scale Integration ) y LSI (Low Scale
Integration ) se diseñaron mediante la realización de prototipos basados en módulos más sencillos. Cada
uno de estos módulos estaba formado por puertas ya probadas, este método poco a poco, iba quedándose
obsoleto. En ese momento (finales de los años setenta) se constata el enorme desfase que existe entre
tecnología y diseño.

http://det.bp.ehu.es/vhdl/pagina/completo/01.htm (1 of 6) [03/04/02 13:43:12]


Lección 1: Introducción

La considerable complejidad de los chips que se pueden fabricar, implica unos riesgos y costes de
diseño desmesurados e imposibles de asumir por las empresas. Es entonces, cuando diversos grupos de
investigadores empiezan a crear y desarrollar los llamados "lenguajes de descripción de hardware" cada
uno con sus peculiaridades. Empresas tales como IBM con su IDL, el TI - HDL de Texas Instruments,
ZEUS de General Electric, etc., así como los primeros prototipos empleados en las universidades,
empezaron a desarrollarse buscando una solución a los problemas que presentaba el diseño de los
sistemas complejos.

Sin embargo, estos lenguajes nunca alcanzaron el nivel de difusión y consolidación necesarios por
motivos distintos. Unos, los industriales, por ser propiedad de la empresa permanecieron encerrados en
ellas y no estuvieron disponibles par su estandarización y mayor difusión, los otros, los universitarios,
perecieron por no disponer de soporte ni mantenimiento adecuado.

Alrededor de 1981 el Departamento de Defensa de los Estados Unidos desarrolla un proyecto llamado
VHSIC (Very High Speed Integrated Circuit ) su objetivo era rentabilizar las inversiones en hardware
haciendo más sencillo su mantenimiento. Se pretendía con ello resolver el problema de modificar el
hardware diseñado en un proyecto para utilizarlo en otro, lo que no era posible hasta entonces porque no
existía una herramienta adecuada que armonizase y normalizase dicha tarea, era el momento de los
HDL's

VHDL

En 1983, IBM, Intermetrics y Texas Instruments empezaron a trabajar en el desarrollo de un lenguaje


de diseño que permitiera la estandarización, facilitando con ello, el mantenimiento de los diseños y la
depuración de los algoritmos, para ello el IEEE propuso su estándar en 1984.

Tras varias versiones llevadas a cabo con la colaboración de la industria y de las universidades, que
constituyeron a posteriori etapas intermedias en el desarrollo del lenguaje, el IEEE publicó en diciembre
de 1987 el estándar IEEE std 1076-1987 que constituyó el punto firme de partida de lo que después de
cinco años sería ratificado como VHDL.

Esta doble influencia, tanto de la empresa como de la universidad, hizo que el estándar asumido fuera
un compromiso intermedio entre los lenguajes que ya habían desarrollado previamente los fabricantes, de
manera que éste quedó como ensamblado y por consiguiente un tanto limitado en su facilidad de
utilización haciendo dificultosa su total comprensión. Este hecho se ha visto incluso ahondado en su
revisión de 1993.

Pero esta deficiencia se ve altamente recompensada por la disponibilidad pública, y la seguridad que le

http://det.bp.ehu.es/vhdl/pagina/completo/01.htm (2 of 6) [03/04/02 13:43:12]


Lección 1: Introducción

otorga el verse revisada y sometida a mantenimiento por el IEEE.

La independencia en la metodología de diseño, su capacidad descriptiva en múltiples dominios y


niveles de abstracción, su versatilidad para la descripción de sistemas complejos, su posibilidad de
reutilización y en definitiva la independencia de que goza con respecto de los fabricantes, han hecho que
VHDL se convierta con el paso del tiempo en el lenguaje de descripción de hardware por excelencia

Qué es un PLD (Dispositivo de Lógica Programable)

Un dispositivo lógico programable es un circuito integrado, formado por una matriz de puertas lógicas
y flip-flops, que proporcionan una solucion al diseño de forma análogas, a las soluciones de suma de
productos, productos de sumas y multiplexores.

La estructura básica de una PLD permite realizar cualquier tipo de circuito conbinacional basándose en
una matriz formada por puertas AND, seguida de una matriz de puertas OR. Tres son los tipos más
estendidos de PLD's, la PROM, PLA, y la PAL.

PROM (Programmable Read Only Memory)

Este tipo de dispositivo se basa en la utilización de una matriz AND fija, seguida de una matriz OR
programable. La matriz programable esta formada por líneas distribuidas en filas y columnas en las
cuales los puntos de cruce quedaran fijos por unos diodos en serie con unos fusibles que serán los
encargados de aislar las uniones donde no se requiera la funcion lógica.

La fase de programación se realiza haciendo circular una corriente capaz de fundir el fusible en
aquellas uniones donde no se desee continuidad. Por otra parte, para cada combinacion de las señales de
entrada, el codificador activa una única fila y a su vez activa aquella columna a las que esta todavía unida
a travéz del diodo.

PLA (Programmable Logic Array)

Parecido en la dispositivo a la PROM, difiere de esta, en que aquí en la PLD , ambas matrices, la de
puertas And, así como la de puertas Or es programable, por lo que nos vemos habilitados a incrementar
el número de entradas disponibles, sin aumentar el tamaño de la matriz. Esta estructura permite una
mejor utilización de los recursos disponibles en el circuito integrado, de tal forma que se genera el

http://det.bp.ehu.es/vhdl/pagina/completo/01.htm (3 of 6) [03/04/02 13:43:12]


Lección 1: Introducción

mínimo numero de términos necesarios para generar una función lógica .

PAL (Programmable array Logic)

Una PAL es diferente de una PROM a causa de que tiene una red Y programable y una red O fija. Con
un programador Prom podemos obtener los productos fundamentales deseados quemando los eslabones y
luego conseguir la suma lógica de dichos productos mediante las conexiones fijas de salida.

Encapsulado típico de una PLD

Conociendo el lenguaje VHDL

El lenguaje VHDL está creado específicamente para el diseño de hardware, es decir, podremos
implementar con él multitud de circuitos lógicos, tanto combinacionales como secuenciales. Éste
lenguaje también nos permite describir elementos más complejos, como CPU's (Unidad Central de
Procesamiento), manejar ficheros, retrasos en el tiempo, etc. pero no siempre se puede implementarlos;
tan sólo, y en según que casos, se llegará a la simulación. Este libro se centra en el VHDL sintetizable, es
decir, con el que es posible llegar a grabar un dispositivo lógico programable.
Un programa en VHDL consta de dos partes. La primera, la entidad, nos sirve para relacionar nuestro
diseño con el mundo exterior, es decir, analizamos lo que tratamos de crear como una "caja negra", de la

http://det.bp.ehu.es/vhdl/pagina/completo/01.htm (4 of 6) [03/04/02 13:43:12]


Lección 1: Introducción

que sólo conocemos sus entradas, sus salidas y la disposición de las mismas. La segunda parte, la
arquitectura, describe como trata el circuito la infomación correspondiente a las entradas para obtener las
salidas.

Sentencias concurrentes y secuenciales

Para iniciarnos correctamente en el aprendizaje y manejo de VHDL es importante que comprendamos


desde un principio la diferencia entre concurrente y secuencial.

El concepto de concurrencia, se ve claramente graficado en los circuitos electrónicos donde los


componentes se encuentran siempre activos, existiendo una asociación intrínseca, entre todos los eventos
del circuito; ello hace posible el hecho de que si se da algún cambio en una parte del mismo, se produce
una variación (en algunos casos casi instántanea) de otras señales.

Esta comportamiento de los circuitos reales obliga a que VHDL soporte estructuras específicas para el
modelado y diseño de este tipo de especificaciones de tiempos y concurrencias en el cambio de las
distintas señales digitales de los diseños.

Por el contrario, los asignamientos secuenciales, son más bien propios de los SDL (soft design
lenguage) en los que la programación tiene un flujo natural secuencializado, siendo propio de este tipo de
eventos las sentencias case, if, while, loop, etc más propias de estas sintaxis.

Las construcciones concurrentes del lenguaje son usadas dentro de estructuras concurrentes, por
ejemplo una arquitectura tiene una naturaleza eminentemente concurrente (es decir que está activo todo
el tiempo), mientras que el cuerpo de un process es en principio eminentemente secuencial. La
asignacion de eventos secuenciales dentro de una estructura concurrente se ejecutará de forma
concurrente, es decir, al mismo tiempo que las demás sentencias.

VHDL soporta con este motivo, tres típos de objetos, las variables, las constantes y las señales . Como
las variables y las señales pueden variar su valor mientras ejecutamos un programa, serán éstas las
encargadas de almacenar dichos datos, asimismo serán los portadores de la información. Únicamente las
señales pueden tener la connotación de globalidad dentro de un programa, es decir, que pueden ser
empleadas dentro de cualquier parte del programa a diferencia de las variables que solo tienen sentido en
el interior de un process .

Los process son estructuras concurrentes constituidas por sentencias de ejecución secuencial, esto

http://det.bp.ehu.es/vhdl/pagina/completo/01.htm (5 of 6) [03/04/02 13:43:12]


Lección 1: Introducción

provocará que dentro de un process nos encontremos con sentencias similares a las de los SDL (lenguajes
de descripción de software) que nos llevan a emplear VHDL como si de otro lenguaje común se tratara.
Dentro de un process nos podemos encontrar con la declaración y utilización de las variables como
parámetros locales al process .

De ejecución secuencial, las variables evaluan su valor dentro del cuerpo del proceso de forma
inmediata, sin consumir tiempo de ejecución, pero como están dentro de un process, que es una
estructura concurrente, este valor no será asumido, sino hasta el final de la ejecución de dicho process.

Veámos el siguiente ejemplo de asignación concurrente para señales:

w<= not a;
x <= a and b;
y <= c and w;
z <= x or y;

Al producirse un cambio en la parte derecha de la estructura de asignación (<= NOT a) de alguna de


las sentencias, la expresión es evaluada de nuevo en su totalidad, con la siguiente asignación del nuevo
valor a la señal de la izquierda. Esto puede provocar que múltiples asignaciones en el cuerpo de una
arquitecura se activen simultáneamente, como por ejemplo, en la imagen superior, la cual se corresponde
al código situado a su izquierda.

http://det.bp.ehu.es/vhdl/pagina/completo/01.htm (6 of 6) [03/04/02 13:43:12]


Lección 2: Unidades Básicas de Diseño.

Unidades Básicas de Diseño

● Como se declara una Entidad

● Como se declara una Arquitectura

● Paquetes

● Librería LPM (Library of parametrized


modules)

Como se declara una Entidad

En la declaración de entidades, se definen las entradas, salidas y tamaño de un circuito, explicitando


cuales son, de qué tamaño (de 0 a n bits), modo (entrada, salida, ...) y tipo (integer, bit,...) . Las entidades
pueden definir bien las entradas y salidas de un diseño más grande o las entradas y salidas de un chip
directamente. La declaración de entidades es análoga al símbolo esquemático de lo que queremos
implementar, el cual describe las conexiones de un componente al resto del proyecto, es decir, si hay una
entrada o puerto de 8 bits, o dos salidas o puertos de 4 bits, etc. La declaración de entidades tiene la
siguiente forma:

entity circuito_a is Cabecera del programa

Se indica que a continuación viene los puertos (o


port( grupos señales) de entrada y/o salida

http://det.bp.ehu.es/vhdl/pagina/completo/02.htm (1 of 14) [03/04/02 13:43:20]


Lección 2: Unidades Básicas de Diseño.

Aquí se declaran las entradas y/o salidas con la


-- puertos de entradas sintaxis que se verá a continuación. Las líneas
-- puertos de salidas empezadas por dos guiones son ignoradas por el
-- puertos de I/O compilador. Así mismo, recordamos que el
-- puertos de buffers compilador no distingue las mayúsculas de las
minúsculas

Se indica que se ha acabado la declaración de


);
puertos de entrada y/o salida, y que se ha acabado
end circuito_a; la entidad

Como hemos dicho, cada señal en una declaración de entidad está referida a un puerto (o grupo de
señales), el cual es análogo a un(os) pin(es) del símbolo esquemático. 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 debe asignar un nombre válido. A continuación se exponen algunos ejemplos:

nombre_variable: modo tipo; Forma genérica de designar un puerto

El primer puerto es un bit de entrada, y su


puertoa: in bit; nombre es "puertoa"
El segundo puerto es un vector de 8 bits de
puertob: in bit_vector(0 to 7); entrada siendo el MSB el puertob(0) y el LSB
el puertob(7)
El tercer puerto es un vector de 4 bits de
puertoc: out bit_vector(3 downto
salida siendo el MSB el puertoc(3) y el LSB el
0); puertoc(0)

El cuarto puerto es un buffer de un solo bit,


puertod: buffer bit; cuyo nombre es "puertod"

El quinto puerto es una entrada/salida del


puertoe: inout std_logic; tipo estándar logic de un solo bit

Como se puede deducir de los ejemplos anteriores, seguido del nombre del puerto y separado de éste
por dos puntos, se debe indicar el tipo de puerto. El modo describe la dirección en la cual la información
es transmitida a través del puerto: in, out, buffer e inout. Si no se especifica nada, se asume que el puerto
es del modo in.

Modo in: Un puerto es de modo in si la información correspondiente al mismo, entra a


la entidad y se suele usar para relojes, entradas de control (como las típicas load, reset y
enable), y para datos de entrada unidireccionales.

http://det.bp.ehu.es/vhdl/pagina/completo/02.htm (2 of 14) [03/04/02 13:43:20]


Lección 2: Unidades Básicas de Diseño.

Modo out: Un puerto es de modo out si la información fluye hacia fuera de la entidad.
Este modo no permite realimentación ya que al declarar un puerto como out estamos
indicando al compilador que el estado lógico en el que se encuentra no es leíble. Esto le da
una cierta desventaja pero a cambio consume menos recursos de nuestros dispositivos
lógicos programables.

Modo buffer: Es usado para una realimentación interna ,es decir, para usar este puerto
como un driver dentro de la entidad. Este modo es similar al modo out, pero además,
permite la realimentación y no es bidireccional, y solo puede ser conectado directamente a
una señal interna, o a un puerto de modo buffer de otra entidad. Una aplicación muy
común de este modo es la de salida de un contador, ya que debemos saber la salida en el
momento actual para determinar a salida en el momento siguiente.

Modo inout: Es usado para señales bidireccionales, es decir, si necesitamos que por el
mismo puerto fluya información tanto hacia dentro como hacia afuera de la entidad. Este
modo permite la realimentación interna y puede reemplazar a cualquiera de los modos
anteriores, pudiéndose usar este modo para todos los puertos, pero reduciremos la lectura
posterior del código por otra persona, y reduciendo los recursos disponibles de la
dispositivo.

Como se ha comentado más arriba, el lenguaje sólo admite cuatro modos para los puertos, pero puede
haber tantos tipos de señales como queramos, ya que los podemos crear nosotros mismos. VHDL
incorpora varios tipos de forma estándar (por haber sido creado así), pudiendo usar otros definidos en
librerías normalizadas, y las creados por el usuario. La norma internacional IEEE 1076/93 define cuatro
tipos nativos para VHDL como son:

Tipo boolean: puede tomar dos valores: verdadero/true o falso/false. Un ejemplo típico
es la salida de un comparador que da verdadero si los números comparados son iguales y
falso si no lo son:

Sólo puede tomar dos valores: verdadero o falso, y es de


equal:out boolean; salida (darle mas operatividad a la salida de un
comparador sería superfluo)

Tipo bit: Puede tomar dos valores: 0 ó 1 ( o también "low" o "high", según se prefiera).
Es el tipo más usado de los nativos.

Tipo bit_vector: Es un vector de bits. Debemos tener cuidado al definir el peso de los
bits que lo integran, ya que según pongamos la palabra reservada downto o to estaremos

http://det.bp.ehu.es/vhdl/pagina/completo/02.htm (3 of 14) [03/04/02 13:43:20]


Lección 2: Unidades Básicas de Diseño.

diciendo que el bit más significativo es el número más alto o el más bajo del vector,
respectivamente..

En este caso el MSB es numero(0) y numero(7)


numero : bit_vector (0 to 7); el LSB
numero : bit_vector (7 downto En este caso el MSB es numero(7) y numero(0)
0); el LSB

Tipo integer: Para manejar números enteros. Hay que advertir que el uso de enteros
consume muchos recursos del dipositivo de lógica programable, siempre y cuando sea
sintetizable, debido a que está prácticamente creado para la simulación.

Pero ante la necesidad de ampliar la operatividad del tipo bit, la norma IEEE 1164, definió un nuevo
tipo llamado std_logic, std_ulogic, y sus derivados tales como std_logic_vector y std_ulogic_vector.
Como su nombre pretende indicar, es el tipo de tipo lógico estándar, que es el más usado en la actualidad,
así como en la mayoría de ejemplos de este libro.

Como ejemplo, a continuación se incluye la declaración de una entidad correspondiente a un


multiplexor de 2x1 de cuatro bits, con entrada de habilitación o enable. El multiplexor necesita las
entradas de información, la señal de selección, la de enable y las salidas de información.

Cabecera ya estudiada arriba, en la que multi es el


entity multi is port ( nombre de la entidad
enable: in bit;
selec: in bit; ● enable es un bit de entrada (suficiente para
habilitar o no)
in1: in bit_vector(3 downto
● selec es otro bit de entrada, que selecciona
0); la entrada in1 o in2, ambas de 4 bits
in2: in bit_vector(3 downto ● out1 es de salida, que lógicamente, debe ser
0); de la misma longitud que in1 e in2
out1:out bit_vector(3 downto
0)
Notesé que el último puerto no lleva punto y
);
coma al final de la línea. Si lo llevase estaría
end multi; incorrecto

A continuación se muestra otro ejemplo correspondiente a la entidad para un comparador:

entity compa is port ( Cabecera de la entidad, cuyo nombre es compa

http://det.bp.ehu.es/vhdl/pagina/completo/02.htm (4 of 14) [03/04/02 13:43:20]


Lección 2: Unidades Básicas de Diseño.

a,b: in bit_vector(3 downto ● a y b son las entradas de cuatro bits


0); ● igual es la salida de un sólo bit
igual: out bit;
); Se finaliza la entidad con la palabra clave end y el
end compa; nombre de la misma (compa).

Debemos recordar dos puntos más a la hora de dar el nombre a algún puerto, que se tratarán más
adelante en el aprtado de objetos:

VHDL no distingue las letras mayúsculas de las minúsculas, por lo que un puerto
llamado por nosotros "EnTraDA" será equivalente a otro que se llame "ENTRADA" o
"entrada". Pulsa aquí para ir a una práctica donde se demuestra esto.

El primer carácter de un puerto sólo puede ser una letra, nunca un número. Así mismo,
no pueden contener caracteres especiales como $, %, ^, @, ... y dos caracteres de
subrayado seguidos.

Estos dos detalles a tener en cuenta surgieron del comité que creó este lenguaje, por lo que no se debe
considerar como un fallo de nuestra herramienta (WARP2), sino como una característica más del
lenguaje.

Como se declara una Arquitectura

La arquitectura indica el tipo de procesado que se realiza con la información correspondiente a las
señales de entrada, (declarados previamente en la entidad) para llegar a tener los puertos de salida
(también declarados en la entidad). En la declaración de arquitecturas es donde reside todo el
funcionamiento de un circuito, ya que es ahí donde se indica que hacer con cada entrada, para obtener la
salida. Si la entidad es vista como una "caja negra", para la cual lo único importante son las entradas y las
salidas, entonces, la arquitectura es el conjunto de detalles interiores de la caja negra.

La declaración de arquitecturas debe constar de las siguientes partes como mínimo, aunque suelen ser
más:

http://det.bp.ehu.es/vhdl/pagina/completo/02.htm (5 of 14) [03/04/02 13:43:20]


Lección 2: Unidades Básicas de Diseño.

Cabecera de la arquitectura. En ésta, archpro


es un nombre cualquiera (suele empezar por
architecture archpro of programa
"arch", aunque no es necesario) y programa
is es el nombre de una entidad existente en el
mismo fichero
-- declaración de señales y otros Declaraciones de apoyo, que se verán en la
accesorios página siguiente
begin Se da comienzo al programa
Conjunto de sentencias, bucles, procesos,
-- núcleo del programa funciones,... que dan operatividad al programa.
end archpro; Fin del programa

Como podemos apreciar, es una estructura muy sencilla, y que guarda alguna relación con Turbo
Pascal. Las sentencias entre begin y end son las que describen el circuito, y es en lo que se centra tanto
este libro electrónico como cualquier otro que trate sobre VHDL. A continuación, se muestra el código
fuente de un programa en VHDL de un multiplexor (esta es una de las múltiples formas de implementar
un multiplexor en VHDL), el cual debe ir unido a la entidad expuesta en el apartado de la declaración de
entidades, ya que una parte sin la otra carecen de sentido.

Cabecera de la arquitectura. En esta ocasión el


architecture archimulti of multi nombre de la arquitectura es archimulti, y el
is de la entidad es multi, la cual está definida
anteriormente.

-- señales En este programa no se necesitan señales


begin Comienza al programa
process(enable,in1,in2)
begin
if enable='0' then out1<="1111"; Sentencias que hacen que la entidad definida
elsif enable='1' then como multiplexor realice la función propia de
if(selec = '0') then out1<=in1; su nombre. Solo hay que entender la
elsif(selec = '1') then estructura de las arquitecturas en estos
out1<=in2; momentos, por lo que este código no debe ser
objeto de preocupación.
end if;
end if;
end process;
end archimulti; Fin del programa

Para describir una arquitectura podremos usar cuatro estilos, teniendo cada uno, su propio nivel de
abstracción. Los estilos son:

http://det.bp.ehu.es/vhdl/pagina/completo/02.htm (6 of 14) [03/04/02 13:43:20]


Lección 2: Unidades Básicas de Diseño.

Estilo behavioral o comportamiento: Este estilo se caracteriza por incluir las


sentencias y órdenes típicas de un lenguaje de programación (if, then, case,...), sin
importarnos como quedará la distribución de puertas lógicas dentro de la PLD. Es
necesario un proceso al ser una estructura secuencial. El siguiente fragmento de código
describe un comparador (usando una entidad descrita en este mismo tutorial)escrito con el
estilo behavioral o de comportamiento.

architecture behavioral of compa is


begin
comp: process (a, b)
begin Como se puede apreciar en este ejemplo se
utilizan los clásicos if then else de cualquier
if a= b then
lenguaje de programación, y además las
igual<='1'; asignaciones son secuenciales. Esto es lo que
else hace esta arquitectura de comportamiento o
igual<='0'; behavioral.
end if;
end process comp;
end behavioral;

Estilo dataflow o flujo de datos: Este estilo podremos encontrarlo de dos formas
similares, pero ambas implican cómo la información será transferida de señal a señal y de
la entrada a la salida sin el uso de asignaciones secuenciales, sino concurrentes. Es decir,
en este estilo no se pueden usar los procesos. El comparador descrito de forma behavioral
o de comportamiento se puede escribir usando el estilo dataflow de cualquiera de las dos
formas siguientes:

architecture dataflow1 of compa is


Esta arquitectura es del estilo dataflow porque
begin
se especifica como la información pasará a la
igual<='1' when (a=b) else '0'; salida sin usar sentencias secuenciales
end dataflow1;
architecture dataflow2 of compa is
begin
igual<= not(a(0) xor b(0))
Aquí de nuevo las asignaciones son
and not(a(1) xor b(1)) concurrentes, no secuenciales.
and not(a(2) xor b(2))
and not(a(3) xor b(3));
end dataflow2;

Estilo structural o estructural: En él se describe un "netlist" de VHDL, en los cuales

http://det.bp.ehu.es/vhdl/pagina/completo/02.htm (7 of 14) [03/04/02 13:43:20]


Lección 2: Unidades Básicas de Diseño.

los componentes son conectados y evaluados instantáneamente mediante señales. No se


suele usar este estilo únicamente en una arquitectura ya que resulta muy lioso y difícil de
modificar, siendo de verdadera utilidad cuando debemos crear una estructura grande y
deseamos descomponerla en partes para manejarla mejor, y para hacer la simulación de
cada parte más sencilla. Se suele requerir el uso de señales auxiliares, y además paquetes y
librerías accesorios, lo cual, recordemos, debe estar declarado al comienzo de la entidad.

architecture struct of compa is


signal x: bit_vector(0 to 3);
begin Aquí solo se interconexionan
u0: xnor2 port map (a(0),b(0),x(0)); salidas con entradas de
componentes. La salida viene
u1: xnor2 port map (a(1),b(1),x(1));
dada por la operatividad de los
u2: xnor2 port map (a(2),b(2),x(2)); componentes, la cual no se
u3: xnor2 port map (a(3),b(3),x(3)); puede saber si no conocemos el
u4: and4 port map paquete del cual ha sido leída.
(x(0),x(1),x(2),x(3),igual);
end struct;

Estilo mixto: Es el estilo que está compuesto en mayor o menor medida de dos o más
de los estilos descritos anteriormente.

Deberemos tener en cuenta que el código VHDL que escribamos no siempre va a describir una función
de forma óptima, la cual no siempre va a poder ser reducida por la herramienta de compilación. Esto se
traduce en un peor aprovechamiento de los recursos de las PLD's. Por lo tanto, diferentes diseños
producen diferentes, aunque equivalentes, ecuaciones de diseño, pudiéndose dar, sin embargo,
disposiciones diferentes de los recursos.

Es habitual el usar el estilo estructural para descomponer un diseño en unidades manejables,siendo


cada unidad diseñada por equipos de trabajo distintos. El estilo estructural se usa además para tener un
grado de control alto sobre la síntesis.

Para concluir el apartado dedicado a las arquitecturas sólo resta el recordar que tanto la entidad y la
arquitectura deben ir unidas en el mismo fichero, ya que una parte carece de sentido sin la otra. Pulsa
aquí para ver el proceso a seguir en la compilación.

http://det.bp.ehu.es/vhdl/pagina/completo/02.htm (8 of 14) [03/04/02 13:43:20]


Lección 2: Unidades Básicas de Diseño.

Paquetes

Un diseñador de Hardware que utilice frecuentemente la misma tecnología de diseño ha de hacerse,


con el paso del tiempo, con una reseña amplia de procedures, funciones, puertas y, en general, de
componentes que empleará con frecuencia. Los packages permiten agrupar un conjunto de
declaraciones para que puedan ser usadas en el diseño de diferentes circuitos sin ser repetidas en la
declaración de cada uno.

La estructura básica en la declaración de un paquete está dividida en dos partes claramente


diferenciadas:

La declaración del paquete, package: donde obtenemos una visión externa y


simplificada del componente. La declaración del paquete va precedida por la palabra
reservada package y finaliza con end. En el cuerpo de la declaración nos encontramos con
procedures, funciones, componentes, etc. tal y como aparecerían en la parte de la
declaración de una entidad.

package nombre_del_package is

-- declaración de procedures
Esta parte es a una entidad, lo mismo que un
-- declaración de funciones paquete es a un programa normal en VHDL.
-- declaración de tipos, etc...

end nombre_del_package;

La declaración del cuerpo del paquete, package body: especifica el funcionamiento de


procedures, funciones, tipos, etc. que nos permite su implementación, de forma similar a la
arquitectura. Debe llevar las palabras reservadas package body.

package body nombre_del_package


is

-- definición de procedures
Esta parte se corresponde con una arquitectura.
-- definición de funciones
-- definición de tipos, etc.

end nombre_del_package;

http://det.bp.ehu.es/vhdl/pagina/completo/02.htm (9 of 14) [03/04/02 13:43:20]


Lección 2: Unidades Básicas de Diseño.

Todo esto hace posible que una vez declarados los subprogramas dentro de un package, podamos
utilizarlos haciendo únicamente uso de una llamada al proceso, asignándole un nombre y la lista de
parámetros necesarios.

Para poder usar o llamar a un package que ha sido descrito anteriormente, debemos incluir la cláusula
use antes del cuerpo de la arquitectura.

use work.nombre del package.nombre del componente;

Para esto se deben especificar tres cosas:

El nombre de la librería donde se encuentra el paquete

El nombre del paquete

El nombre del componente que se desee habilitar

Hay ocasiones en las que deseamos habilitar todos los componentes declarados en un paquete, ya sea
por comodidad o por no saber exactamente donde se encuentra el recurso que deseamos usar. En tal caso,
haríamos uso de la palabra all de la siguiente forma:

use work.nombre del package.all;

Como ejemplo se muestra a continuación la declaración de un package que contiene a dos


componente, un contador y un decodificador.

--Primero se declaran las librerías que se van a emplear


library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
--Empieza la declaración del package "UNO"
package uno is
component
count port (
clk,reset:in bit;
conta :buffer std_logic_vector(1 downto 0));
end component;
component
decoder port (

http://det.bp.ehu.es/vhdl/pagina/completo/02.htm (10 of 14) [03/04/02 13:43:20]


Lección 2: Unidades Básicas de Diseño.

seleccion :in std_logic_vector(1 downto 0);


enable1,enable2:in bit;
salida :out std_logic_vector(3 downto 0));
end component;
end package;

--Declaración de las estidades


library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
use work.uno.all;
entity count is port (
clk,reset:in bit;
conta:buffer std_logic_vector(1 downto 0));
end count;

architecture archicount of count is


begin
contador :process (clk,reset)
begin
if (reset='1') then conta <= (others => '0') ;
elsif clk'event and clk='1' then conta <= conta + 1;
end if;
end process contador;
end archicount;
--Declaración de las arquitecturas
--Descripcion del decodificador 3/8 (74ls138)
library ieee;
use ieee.std_logic_1164.all;
use work.uno.all;
entity decoder is port (
seleccion :in std_logic_vector(1 downto 0);
enable1,enable2:in bit;
salida :out std_logic_vector(3 downto 0));
end decoder;

--Descripción del decodificador


architecture archidecoder of decoder is
begin
decodificador:process(seleccion,enable1,enable2)
begin
if enable2='1' then salida<=(others=>'0');
elsif enable2='0' and enable1='0' then salida<=(others => '0');

http://det.bp.ehu.es/vhdl/pagina/completo/02.htm (11 of 14) [03/04/02 13:43:20]


Lección 2: Unidades Básicas de Diseño.

elsif(enable1='1') then
case seleccion is
when "00" => salida <= "0001";
when "01" => salida <= "0010";
when "10" => salida <= "0100";
when "11" => salida <= "1000";
when others => salida <="1111";
end case;
end if;
end process decodificador;
end archidecoder;

Para poder hacer uso, de cualquier componente de el package "uno" (el decodificador o el
contador),es necesario que primero se incluya la sentencia:

use work.uno.all;

Librería LPM (Library of parametrized modules)

La LPM fue propuesto en 1990 como una extensión del estándar Electronic Design Interface Format
(EDIF) para permitir al diseñador crear un circuito completo con independencia de la arquitectura,
separando las partes físicas y lógicas del diseño

Cada componente en la librería esta definido por unos parámetros, que le permiten al diseñador de
hardware representar una amplia variedad de variables lógicas, evitando la repetición del trabajo.

Un diseño basado en la utilización de la librería LPM (library of parametrized modules) combina


simultáneamente, los aspectos propios de un diseño en alto nivel, con las mejoras propias de la síntesis
en bajo nivel. Debido a que los componentes descritos en esta librería son aceptados por lo fabricantes,
su consumo de los recurso internos viene previamente optimizado.

La librería LPM System Library, en la cual se nos ofrecen múltiples módulos, ya creados, puede
facilitarnos enormemente nuestro trabajo, ya que incluye desde el generador de constantes más sencillo
hasta contadores y multiplicadores con todas las características opcionales posibles. La lista de
componentes incluida en esta es la siguiente:

http://det.bp.ehu.es/vhdl/pagina/completo/02.htm (12 of 14) [03/04/02 13:43:20]


Lección 2: Unidades Básicas de Diseño.

Nombre del paquete Nombre del componente

MCCSTNT Módulo de constantes

MINV Módulo de inversores

MAND Módulo de AND's

MOR Módulo de OR's

MXOR Módulo de XOR's

MBUSTRI Módulo de bus triestado

MMUX Módulo de multiplexores

MDECODE Módulo de decodificador

Módulo de
MADD_SUB
sumadores/restadores

MCOMPARE Módulo de comparadores

MMULT Módulo de multiplicadores

MCOUNTER Módulo de contadores

MLATCH Módulo de latches

MFF Módulo de flip-flops

MSHFTREG Módulo de registros

Para usar cualquiera de éstos módulos, sólamente deberemos incluir en nuestro fichero de código la
siguiente línea, encima de la declaración de entidades y de arquitecturas:

use work.lpmpkg.all;

Como ejemplo crearemos un multiplicador de 4 bits (a y b), cuyo resultado, obviamente, debe se de 8
bits (p), y que nos permite además sumarle otro número de ocho bits (s) al resultado. Para ello deberemos
invocar previamente a la librería lpmpkg tal y como habíamos dicho:

http://det.bp.ehu.es/vhdl/pagina/completo/02.htm (13 of 14) [03/04/02 13:43:20]


Lección 2: Unidades Básicas de Diseño.

library ieee;
use ieee.std_logic_1164.all;
use work.lpmpkg.all;
entity multi_lpm is port(
a,b: in std_logic_vector(3 downto Llamamos a lpmpkg
0);
s: in std_logic_vector(7 downto Vamos a multiplicar a y b
0); Y vamos a sumar s
p: out std_logic_vector(7 downto El resultado es p
0)
);
end multi_lpm;
Llamamos a lpmpkg
use work.lpmpkg.all;
architecture archimulti of multi_lpm
is
begin Usamos el módulo mmult
a0: mmult generic map(4,4,8,8)
port map(a,b,s,p);
end archimulti;

En este ejemplo hemos hecho uso del módulo mmult, el cual nos exige no sólo introducirle las señales
con las cuales operar (con la sentencia port map) sino también su dimensión (sentencia generic map).
Pulsa aquí para ir al ejemplo del multiplicador.

Como cada módulo tiene unas especificaciones de entradas, salida y dimensiones distintas, tendremos
que consultar el manual de la librería lpmpkg para conocer que entradas y salidas necesita cada módulo.
Podemos acceder a esta documentación siguiendo estos pasos:

Conseguir el programa WARP2 Release 4.2, disponible online en la página de Cypress


Semiconductor Inc. No es neceasrio si ya está instalado en el subdirectorio c:\warp en el
ordenador donde estás leyendo estas líneas. Si no lo tienes, isntalaló en esa dirección.

Descargar el programa gratuito Acrobat Reader y sus plug-ins.

Una vez realizado estos pasos, aparecerá debajo de estas líneas la documentación
sobre la librería lpmpkg, en el capítulo 5 del documento. Si no te aparece puedes bajarlo
desde aqui: refmanl.pdf

http://det.bp.ehu.es/vhdl/pagina/completo/02.htm (14 of 14) [03/04/02 13:43:20]


Lección 3: Objetos,tipo de datos y operaciones

Objetos, tipos de datos y operaciones

Objetos

Identificadores

Palabras reservadas

Símbolos especiales

Tipos de datos

Expresiones y operadores

Atributos de los vectores

Objetos

En un lenguaje de descripción de software (SDL) una variable contiene un valor y puede aceptar un nuevo valor a través de una
asignación secuencial. Por otro lado, las constantes tienen valores prefijados a lo largo de toda la ejecución del programa. Sin embargo,
en VHDL se hace necesaria la utilización de un nuevo tipo de objeto que puede emular las asignaciones concurrentes propias de los
circuitos eléctricos reales; este nuevo tipo de objeto son las señales.

Un objeto en VHDL es un elemento que tiene asignado un valor de un tipo determinado. Según sea el tipo de dato, el objeto poseerá
un conjunto de operaciones que se le podrán aplicar. En general, no será posible realizar operaciones entre dos objetos de distinto tipo,
a menos que definamos previamente un programa de conversión de tipos.

Identificadores

Los identificadores son un conjunto de caracteres dispuestos de una forma adecuada y siguiendo unas normas propias del lenguaje,
para dar un nombre a los elementos en VHDL, por lo que es aconsejable elegir un nombre que sea representativo y que facilite la
comprensión del código.

Las reglas a tener en cuenta a la hora de elegir un identificador son:

Los identificadores deben empezar con un carácter alfabético, no pudiendo terminar con un carácter subrayado, ni

http://det.bp.ehu.es/vhdl/pagina/completo/03.htm (1 of 6) [03/04/02 13:43:39]


Lección 3: Objetos,tipo de datos y operaciones

tener dos o más de estos caracteres subrayados seguidos.

VHDL identifica indistintamente tanto las mayúsculas como las minúculas, pudiéndose emplear por igual el
identificador "sumador" o "SUMADOR". Pulsa aquí para ir a la práctica del sumador, donde se demuestra la indiferencia
de mayúsculas y minúsculas.

El tamaño o extensión del identificador no está fijado por VHDL, siendo recomendable que el usuario elija un
tamaño que confiera sentido y significado al identificador, sin llegar a alcanzar longitudes excesivamente largas.

Los identificadores pueden contener caracteres numéricos del '0' al '9', sin que éstos puedan aparecer al principio.

No puede usarse como identificador una palabra reservada por VHDL.

Palabras reservadas

Las palabras reservadas son un conjunto de identificadores que tienen un significado específico en VHDL. Estas palabras son
empleadas dentro del lenguaje a la hora de realizar un diseño. Por esta razón y buscando obtener claridad en el lenguaje, las palabras
reservadas no pueden ser empleadas como identificadores definidos por el usuario.

Las palabras reservadas por VHDL son:

abs else nand return


access elsif new select
after end next severity
alias entity nor signal
all exit not subtype
and file null then
architecture for of to
array function on transoprt
asser generate open type
attribute generic or units
begin guarded others until
block if out use
body in package variable
buffer inout port wait
bus is procedure when
case label process while
component library range with
configuration linkage record xor
constant loop register
disconnect map rem

http://det.bp.ehu.es/vhdl/pagina/completo/03.htm (2 of 6) [03/04/02 13:43:39]


Lección 3: Objetos,tipo de datos y operaciones

downto mod report

Símbolos especiales

Además de las palabras reservadas empleadas como identificadores predefinidos, VHDL utiliza algunos símbolos especiales con
funciones diferentes y específicas, tales como el símbolo "+" se utiliza para representar la operación suma y, en este caso, es un
operador. El símbolo "- -" es empleado para los comentarios realizados por el usuario, de tal forma que el programa al encontrar una
instrucción precedida por "- -" la saltará ignorando su contenido. De esta forma, el programador puede hacer más comprensible el
código del programa.

Los símbolos especiales en VHDL son:

+ - / ( ) . , : ; & ' < > = | # <= => := --

Para finalizar, recordar que el símbolo más empleado por un programador es el " ; ", símbolo que debe finalizar todas y cada una
de las líneas del código dando por terminada dicha sentencia en el programa.

Tipos de datos

El tipo de datos es un elemento básico en VHDL, ya que delimita que valores puede tenr un objeto y que operaciones podemos
realizar con él. Aparte de los tipos ya creados, podemos crear nuevos tipos y subconjuntos de tipos.

La declaración de un tipo de datos es la sentencia VHDL utilizada para introducir un nuevo tipo. Esta declaración está formada por
un identidificador que nos permitirá usar el nuevo tipo al llamarlo y la descripción del conjunto de valores que forman el tipo de datos.
Para ello usamos la palabra reservada type. La declaración puede tener varios formatos como por ejemplo:

type longitud_maxima is range 2 to 50


type estados is (estado_a, estado_b, estado_c);

Una vez declarado el nuevo tipo podremos usarlo para declarar objetos de este tipo, como por ejemplo:

variable est: estados;


port (entrada: in estados;
salida: out longitud_maxima);

Cada tipo es diferente e incompatible con los demás, aunque estén declarados de la misma forma, por lo cual no podemos asignar a
una señal de un tipo otra de otro tipo distinto, a menos que definamos una función de transformación.

Los tipos pueden ser clasificados según las características de lo que van a determinar:

http://det.bp.ehu.es/vhdl/pagina/completo/03.htm (3 of 6) [03/04/02 13:43:39]


Lección 3: Objetos,tipo de datos y operaciones

Tipos enumerados: En éste se define el conjunto de posibles valores del tipo especificado, presentando una lista que
contiene a todos los valores. El primer identificador es el nombre del tipo y sirve para referenciarlo, y entre paréntesis y
separados por comas se adjuntan todos los valores legales del tipo.

type vocales ('a', 'e', 'i', 'o', 'u');


type direcciones is (izquierda, derecha, arriba, abajo, centro);

Si no está especificado ningún valor inicial, el objeto se inicializa con el valor más a la izquierda de los especificados en
la declaración del tipo. Es decir, un objeto del tipo "vocales" toma el valor 'a' por defecto.

Tipos enteros / reales: Esta modalidad de tipo sirve apra definir un objeto con valores reales y enteros. En VHDL
vienen definidos el tipo integer, que puede ir desde -2147483647 hasta 2147483647, y el tipo real, quepuede ir desde -
1.0e38 hasta 1.0e38. Para definir un tipo de esta naturaleza hay que especificar el rango de valores que puede llegar a
tener asignado un objeto, como en los ejemplos siguientes

type edad is range 0 to 150;


type dias is range 31 downto 0;

Si no está especificado ningún valor inicial, el objeto se inicializa con el valor más a la izquierda de los especificados en
la declaración del tipo. Deberemos tener cuidado si hemos usado la palabra to o la palabra downto para definir el tipo, ya
que se asignará un valor por defecto u otro. En el ejemplo se da por defecto a un objeto del tipo "edad" el valor 0, y a
otro del tipo "dias", el valor 31.

Tipos fisicos: Sirven para representar magnitudes del mundo real como el tiempo, peso, capacidad,... por lo que
llevan, aparte de un literal numérico, la magnitud física a medir. Podemos asignar unidades auxiliares a la predefinida.

type time is range 0 to 1e20;


units
fs;
ps = 1000 fs;
ns = 1000 ps;
us = 1000 ns;
ms = 1000 us;
sec = 1000 ms;
min = 60 sec;
hr = 60 min;
end units;

Si no está especificado ningún valor inicial, el objeto se inicializa con el valor más a la izquierda de los especificados en
la declaración del tipo. Deberemos tener cuidado si hemos usado la palabra to o la palabra downto para definir el tipo, ya
que se asignará un valor por defecto u otro. En el ejemplo se da por defecto a un objeto del tipo "edad" el valor 0, y a
otro del tipo "dias", el valor 31.

Expresiones y operadores

La metodología de programación de un componente, basada en la descripción por comportamiento (behavioral), puede emplear en
su diseño la mayoría de operadores que se encuentran habitualmente útiles en los SDL's ( software design languages)

http://det.bp.ehu.es/vhdl/pagina/completo/03.htm (4 of 6) [03/04/02 13:43:39]


Lección 3: Objetos,tipo de datos y operaciones

En el cuadro adjunto se puede ver una relación de los operadores predefinidos más empleados en VHDL, así mismo se aprecia que
su clasificación atiende al tipo de dato que vaya a manejar:

NOT, AND, OR, Tipo de operador: boolean


OPERADORES LÓGICOS
NAND, NOR, XOR Tipo de resultado: boolean

Tipo de operador: cualquier tipo


OPERADORES RELACIONALES = / < <= > >=
Tipo de resultado: boolean

+ - * / ** Tipo de operador: integer, real, signal


OPERADORES ARITMÉTICOS
MOD, REM, ABS tipo de resultado: integer, real,signal

Tipo de operador: array


OPERADOR CONCADENACIÓN &
tipo de resultado: array

Los operadores lógicos, pueden ser empleados con los tipos predefinidos, BIT y BOOLEAN, dándonos como resultado un valor
booleano del mismo tipo que los operadores.
Para graficar un poco la importancia de emplear correctamente los distintos tipos de operadores, a continuación lo ilustramos con la
ayuda del diseño de un sumador de cuatro bits mas el carry de la etapa anterior. Pulsa aquí para ir a la práctica del Cuádruple Sumador
Total.

En este ejemplo se aprecia una


concatenacion del lemento "a" (que
previamente debe de haber sido
architecture archisumador of sumador is definido como un std_logic_vector),
begin con un "0", dandonos como
process (a,b,cin) resulytado un array en el que la
variable aux:std_logic_vector(4 downto 0); primera poscicion la ocupa el "0" y
begin despues va el elemento "a"
aux:=('0' & a) + ('0' & b);
if cin='1' then aux:=aux+1;
elsif cin='0' then null;
end if; Este mismo ejemplo nos servira para
sum<=aux; graficar la utilización del
end process; operador suma "+", que lo empleamos
end archisumador; para incrementar a la variable aux,
en caso de que cin valga uno.

Los operadores relacionales también nos generaran un resultado de tipo booleano sin importar el tipo de operando con el que lo
empleemos, como nota comentar que el operador "diferente que" viene dado por la combinación " /= ".
Los operandos de tipo aritméticos están en la obligación de ser empleados con elementos del mismo tipo y de devolver un resultado
que a su vez este contenido en el mismo tipo que los operandos.EL signo "+", "-" dará como resultado sumas de unidades es decir que
al elemento sumado le añade uno,(como se aprecia en el anterior ejemplo).
El operador concadenacíon es empleado para concadenar arrays de bit´s, como muestra se grafíca este operador con el siguiente
ejemplo.

aux:=('0' & a)

Los elementos a concadenar deben de ser del mismo tipo. Este tipo de operador es muy empleado a la hora de trabajar con buses o
registros. El resultado que nos devuelve este operador es un array de los elementos de los operandos concatenados. En nuestro ejemplo,
si "a" es un array de cuatro bits, la variable "aux", pasara a tener en su primera poscicion el valor "0" y a continuacion tendra el valor
de los elementos de "a", de forma que "aux" pasa a tener dimension cinco.

http://det.bp.ehu.es/vhdl/pagina/completo/03.htm (5 of 6) [03/04/02 13:43:39]


Lección 3: Objetos,tipo de datos y operaciones

Atributos de los vectores

Un atributo nos proporciona información sobre ciertos elementos como las entidades, arquitecturas, tipos y señales. Hay varios
atributos de para señales que son muy útiles en síntesis, y especialmente en el VHDL simulable (no sintetizable). Ai ae trabaja con
VHDL sintetizable sólo se pueden utilizar algunos atributos como:

Atributo 'left: se usa para manejar al elemento más a la izquierda de un vector.

Si el elemento más a la izquierda de entrada es '0', entonces se


if entrada'left='0' then ... ejecuta lo que sigue al then

Atributo 'right: se usa para manejar al elemento más a la derecha de un vector.

Si el elemento más a la derecha de entrada es '1', entonces se


if entrada'right='1' then ... ejecuta lo que sigue al then

Atributo 'length: se usa para manejar la longitud de un vector.

Si la longitud de entrada (se supone, lógicamente, que es un array o


if entrada'lenght=5 then ... vector) es 5, entonces se ejecuta lo que sigue al then.

Atributo 'event: se usa para conocer si una variable ha cambiado o no, soliéndose usar como variable booleana:

Si hay un cambio en el nivel lógico de la señal entrada, entonces se


if entrada'event=5 then ... ejecuta lo que sigue al then.

http://det.bp.ehu.es/vhdl/pagina/completo/03.htm (6 of 6) [03/04/02 13:43:39]


Lección 4: Gramática del lenguaje I

Gramática del lenguaje I

Sentencia loop
Sentencias secuenciales
Sentencia exit
Asignación a una señal
Sentencia next
Asignación a variable
Sentencia null
Sentencia if
Sentencia wait
Sentencia case
Sentencia wait
until

Sentencias secuenciales

En la mayoría de los lenguajes de descripción de software, todas las sentencias de asignamiento son de
naturaleza secuencial. Esto significa que la ejecución del programa se llevara a cabo de arriba a abajo, es
decir siguiendo el orden en el que se hayan dispuesto dichas sentencias en el programa, por ello es de
vital importancia la disposición de las mismas dentro del código fuente.

VHDL lleva a cabo las asignaciones a señales dentro del cuerpo de un proceso (process) de forma
secuencial, con lo que el orden en el que aparezcan las distintas asignaciones será el tenido en cuenta a la
hora de la compilación. Esto hace que cuando utilicemos modelos secuenciales en VHDL, estos se
comporten de forma parecida a cualquier otro lenguaje de programación como Pascal, C, etc.

http://det.bp.ehu.es/vhdl/pagina/completo/04.htm (1 of 12) [03/04/02 13:43:49]


Lección 4: Gramática del lenguaje I

Asignación a una señal

Podremos asignar un cierto valor a una señal siempre que ésta haya sido declarada en la entidad en el
apartado de declaración de puertos, o bien porque la hayamos creado específicamente dentro de un
process.

La asignación a una señal dentro de un proceso es siempre secuencial, es decir, la señal no cambia su
valor hasta que se ha evaluado el proceso en el cual se incluye. Si no está dentro de un proceso, como por
ejemplo, usando el estilo dataflow, el cambio es concurrente, es decir, la asignación está siempre activa,
y se actualiza instanteneamente. Para hacer una asignación a una señal deberemos usar el operador <=,
estando la señal a asignar a la izquierda y el valor que debe tomar a la derecha.

signal <= signal1 + signal2;

Las señales son el objeto más usado dentro de la síntesis de diseños, teniendo la particularidad de que
los cambios en una señal son programados, no son inmediatos. Esto resulta extraño, sobre todo si
comparamos su comportamiento con el de las variables, y para dejar claro este concepto veamos el
siguiente ejemplo:

process
begin
a <= b; La señal a tendrá el valor b
b <= a; La señal b tendrá el valor a
wait on a,b;
end process; Se acualizan los cambios AQUÍ

En este ejemplo, las dos señales intercambian sus valores, ya que cuando se ejecuta la segunda (b<=a),
el valor de la señal a no ha cambiado todavía aunque esté la sentencia a<=b, ya que ninguna señal
cambia de valor hasta que se hayan evaluado todas las órdenes de un proceso, y es en ese momento
cuando a y b toman el valor que se les ha indicado tomar.

Asignación a variable

http://det.bp.ehu.es/vhdl/pagina/completo/04.htm (2 of 12) [03/04/02 13:43:49]


Lección 4: Gramática del lenguaje I

La asignación a una variable viene totalmente influenciada por su propia naturaleza, la cual hace que
sólo tengan su campo de acción en un proceso o un subprograma (areas secuenciales). Una variable no
retiene sus valores dentro de un subprograma después de cada llamada, soliendo usarse como índices
para ciclos loop y para asignaciones inmediatas. Si queremos usar una variable fuera de un proceso,
deberemos asignar su valor a una señal, y operar con la señal fuera. Para hacer el asignamiento a una
variable deberemos usar el operador := , como se muestra en los ejemplos siguientes.

A diferencia de las señales, el asignamiento de un valor a un variable, no tiene un retardo asociado, de


manera que la variable toma el nuevo valor justo en el momento de la asigación, de forma que las
sentencias que vengan a continuación, la variable recien asignada, tendrá el nuevo valor. De esta forma,
el ejemplo expuesto para señales, al ser usado para variables, no conseguimos el mismo resultado:

a toma el valor b
a := b;
b toma el NUEVO valor de a (el de
b := a;
b)

En esta ocasión, no se intercambiarán los valores de ambas señales, sino que acabarán con el valor
inicial de la variable b. Para conseguir que se intercambien las variables, deberemos usar una variable
temporal de la siguiente forma:

temp toma el valor de a


temp := a;
a toma el valor de b
a := b;
b toma el valor de temp (que era
b := temp;
a)

Deberemos tener en cuenta que una variable se reinicializa siempre al hacer una nueva llamda a un
subprograma.

Sentencia if

La construcción if-then-else es usada para seleccionar un conjunto de sentencias para ser


ejecutadas según la evaluación de una condición o conjunto de condiciones, cuyo resultado debe ser o
true o false. Su estructura es la siguiente:

http://det.bp.ehu.es/vhdl/pagina/completo/04.htm (3 of 12) [03/04/02 13:43:49]


Lección 4: Gramática del lenguaje I

if (condición) then
haz una cosa;
else
haz otra cosa diferente;
end if;

Si la condición entre paréntesis es verdadera, la(s) sentencia(s) secuencial(es) seguidas a la palabra


then son ejecutadas. Si la condición entre paréntesis es falsa, la(s) sentencia(s) secuencial(es) seguidas a
la palabra else son ejecutadas. La construcción debe ser cerrada con las palabras end if.

La sentencia if-then-else puede ser expandida para incluir la sentencia elsif, la cual nos permite incluir
una segunda condición si no se ha cumplido la primera (la cual tiene prioridad). Su estructura es la
siguiente:

if (condición) then
haz una cosa;
elsif (otra condición) then
haz otra cosa diferente;
else
haz otra totalmente diferente;
end if;

Si se da la situación en la cual la primera condición es verdad ejecuta las sentencias que van después
del primer then. Si no es verdadera la primera condición, se pasa a evaluar la segunda, y de ser esta
verdad, ejecuta las sentencias que están a continuación del segundo then. Si ninguna de las dos es
verdadera, se ejecuta lo que está detrás de la palabra else. Nótese que para que se ejecute las sentencias
con el nombre "otra cosas diferente", no solo debe ser la segunda condición verdadera, sino que además
la primera condición debe ser falsa. Un ejemplo de esta sentencia se puede ver a continuación:

entity multi is port( entidad del multiplexor


a, b, c :in bit_vector(3 downto 0); puertos del multiplexor
enable :in bit;
control :in bit_vector(1 downto 0);
d :out bit_vector(3 downto 0)
);
end multi; finaliza la entidad

http://det.bp.ehu.es/vhdl/pagina/completo/04.htm (4 of 12) [03/04/02 13:43:49]


Lección 4: Gramática del lenguaje I

architecture archmul of multi is arquitectura del multiplexor


begin
process (a, b, c, control, enable)
begin
if enable='1' then d<="1111"; si enable es 1 entonces d="1111"
elsif enable='0' then si enable no es 1 y es 0 entonces
case control is sentencia case dentro del if
when "00" => d <= a;
when "01" => d <= b;
when "10" => d <= c;
when "11" => d <= "1111";
end case; se cierra la sentencia case
end if; se cierra la sentencia if con end
end process;
end archmul; finaliza la arquitectura

Deberemos tener cuidado al usar una sentencia if-then-else ya que podemos caer en el error de la
memoria implícita. Si no incluimos la palabra else, y si no se cumple la primera condición, las señales de
salida no cambian, reteniendo el valor previo a la sentencia if. Esto puede ayudarnos (flip-flops) o bien
hacer que un diseño sea totalmente erróneo. Analicémoslo con un ejemplo:

if (clk'event and clk='1') then


Si hay un flanco de subida en la señal clk,
q <= d; entonces q toma el valor de d.
end if;

En este caso se dice que debe ejecutarse si hay un flanco de subida en la señal clk, pero no se dice
nada si no hay cambios o si el flanco es de bajada. Es en este caso se ha definido una memoria implícita,
y VHDL hace que la señal q siga con el valor que tenía antes de ejecutarse la sentencia if. Esto hace que
este código y el que se lista a continuación sean equivalentes:

if (clk'event and clk='1') then


q <= d; Si hay un flanco de subisda en la señal clk,
else entonces q toma el valor de d, si no es así,
q <= q; q sigue manteniendo su valor.
end if;

Esto hace que se recomiende siempre el especificar con else que debe pasar con las señales si no se
cumpla la condición indicada con el if. En la parte práctica hay varios ejemplso con la sentencia if, pulsa
aquí para ir a la parte práctica.

Para evitar la inclusión de memoria implícitas se recomienda especificar siempre el comportamiento

http://det.bp.ehu.es/vhdl/pagina/completo/04.htm (5 of 12) [03/04/02 13:43:49]


Lección 4: Gramática del lenguaje I

del circuito en aquellos casos en los que no se cumple la condicion de una sentencia if, o de una
sentencia case.

Sentencia case

La sentencia case es usada para especificar una serie de aciones según el valor dado de una señal de
selección. Esta sentencia es equivalente a la sentencia with-select-when, con la salvedad que la sentencia
que nos ocupa es secuencial, no combinacional. La estructura es la siguiente:

case (señal a evaluar) is


when (valor 1) => haz una cosa;
when (valor 2) => haz otra cosa;
...
when (último valor) => haz tal
cosa;
end case;

En el caso que la señal a evaluar (situada después del case) tenga el "valor 1", entonces se ejecuta "una
cosa", si tiene el "valor 2", se ejecuta "otra cosa", ... y si tiene el "último valor", se ejecuta "tal cosa". Esta
sentencia parece hecha a la medida para crear multiplexores, como se ve en el siguiente ejemplo, del cual
sólo estudiamos la parte correspondiente a la sentencia case:

entidad del multiplexor


puertos del multiplexor
entity multi is port(
a, b, c :in bit_vector(3 downto 0);
enable :in bit;
control :in bit_vector(1 downto 0);
finaliza la entidad
d :out bit_vector(3 downto 0)
);
end multi;
arquitectura del multiplexor

architecture archmul of multi is


begin
sentencia if que contiene al case
process (a, b, c, control, enable)

http://det.bp.ehu.es/vhdl/pagina/completo/04.htm (6 of 12) [03/04/02 13:43:49]


Lección 4: Gramática del lenguaje I

begin
if enable='1' then d<="1111"; se evalúa la señal control
elsif enable='0' then si control vale "00" entonces
case control is d<=a
when "00" => d <= a; si control vale "01" entonces
when "01" => d <= b; d<=b
when "10" => d <= c; si control vale "10" entonces
when "11" => d <= "1111"; d<=c
end case; si control vale "11" d valdrá
end if; "1111"
end process; se cierra la sentencia case con
end archmul; end
se cierra la sentencia if

finaliza la arquitectura

Esta sentencia es muy típica de los lenguajes de programación y cuenta además con una variante, muy
importante en VHDL, como es dar un valor especificado a la cierta señal si no se contemplan todos los
casos posibles de la señal a evaluar. Para ello se usa la palabra reservada others, que aparece en el
siguiente fragmento de código:

case control is se evalúa la señal control


when "00" => d <= a; si control vale "00" entonces d<=a
when "01" => d <= b; si control vale "01" entonces d<=b
when "10" => d <= c; si control vale "10" entonces d<=c
when others => d <= si control no toma ningún valor de los
"1111"; especificados antes, toma el valor
"1111"
end case; finaliza la arquitectura

Al igual que era recomendable especificar un else dentro de cada if, se recomienda, con más razón el
uso de others dentro de un case aunque en un rpincipio paresca que estan especificados todos los valores
posibles, ya que algunos tipos soportan más valores aparte del nivel uno y cero lógico, como el estado Z
o de alta impedancia. Pulsa aquí para ir a la práctica del multiplexor.

La sentencia case también nos permite especificar un rango de valores posibles de la señal de
selección, para los cuales hacer una asignación, mediante la palabra reservada to. Como ejemplo veamos
dos fragmentos de código que son equivalentes:

http://det.bp.ehu.es/vhdl/pagina/completo/04.htm (7 of 12) [03/04/02 13:43:49]


Lección 4: Gramática del lenguaje I

case control is
when "000" => d <= a;
when "001" => d <= a;
case control is
when "010" => d <= a;
when "000" to "010" => d <= a;
when "011" => d <= b;
when "011" to "110" => d <= b;
when "100" => d <= b;
when "111" => d <= c;
when "101" => d <= b;
when others => d <= null;
when "110" => d <= b;
end case;
when "111" => d <= c;
when others => d <= null;
end case;

Sentencia loop

La sentencia loop (ciclo en castellano) se usa para ejecutar un grupo de sentencias un número
determinado de veces, y consiste tanto en un ciclo for como en un ciclo while. La sentencia for se
ejecuta un número específico de iteraciones basado en el valor de una variable. La sentencia while
continuará ejcutándo una operación mientra una condición de control local sea cierta. Estas sentencias
son muy típicas de los lenguajes más usuales de programación, usándose habitualmente para ello la
variable i. A continuación se listan sendos ejemplos para cada caso:

process (a)
begin
ciclo1: for i in 7 downto 0 loop
entrada(i) <= ( others => '0' Cabecera del ciclo
) Instrucciones a ejecutar 8 veces
end loop; Finalización del ciclo
end process;

Este fragmento de código hace que uno por uno los 8 últimos bits de la señal entrada tengan el valor
lógico cero. Que se indique que deben hacerse cero 8 bits, no quiere decir que la señal entrada esté
formada por más de ocho. El encabezamiento de la sentencia nos dice que se va a repetir ocho veces
seguidas las instrucciones entre loop y end loop. Debemos destacar que en un ciclo for, la variable del
mismo se declara atomáticamente, y no tenemos que incrementarla o inicializarla, ya que el programa lo
hace por nosotros. La etiqueta ciclo1 se usa (aunque es opcional) para dar más posibilidades de
organización al programador.

http://det.bp.ehu.es/vhdl/pagina/completo/04.htm (8 of 12) [03/04/02 13:43:49]


Lección 4: Gramática del lenguaje I

process (a)
variable i: integer := 0;
begin
Mientras i sea menor que 7 =>
ciclo2: while i < 7 loop
ciclo
entrada(i) <= (others => '0');
i := i + 1;
end loop;
Finaliza el ciclo
end process;

En esta ocasión se usa la sentencia while, para lograr el mismo resultado que en el ejemplo anterior, es
decir, inicializar los 8 últimos bits del vector entrada a cero. Esta vez, se ejecutan las líneas entre loop y
end loop mientras la variable i sea menor que siete. Es lógico que esta variable cambie dentro del ciclo,
ya que de no ser así, se ejecutaría para siempre. De forma distinta al ejemplo anterior, la variable del
ciclo while debe ser declarada (como integer), inicializada e incrementada por nosotros, por lo que
requiere más trabajo.

Sentencia exit

Usada siempre dentro de un loop, la sentencia exit nos permite salir del mismo si se alcanza una
condición fijada por nosotros. Su verdadera utilidad la encontramos si diseñamos controladores de
memoria. A continuación analizamos un ejemplo:

process (a)
begin
ciclo1: for i in 7 downto 0 loop
if a'length < i then exit
ciclo1;
entrada(i) <= ( others => '0' );
end loop;
end process;

Ahora se ejecuta el mismo ejemplo que expusimos en el caso de un ciclo for con la salvedad que si la
variable i supera la longitud del vector a el ciclo deja de ejecutarse aunque no se hayan cumplido las
veces pedidas en el encabezamiento.

http://det.bp.ehu.es/vhdl/pagina/completo/04.htm (9 of 12) [03/04/02 13:43:49]


Lección 4: Gramática del lenguaje I

Sentencia next

La sentencia next también debe estar dentro de un ciclo loop, y nos sirve para saltarnos una o más de
las ejecuciones programadas.

process (a)
begin
ciclo1: for i in 7 downto 0 loop
Cabecera del ciclo
if i=4 then next;
Si i vale 4, se salta el ciclo
else
Si no vale 4,...
entrada(i) <= ( others => '0'
... se inicializa entrada
);
end if;
Finaliza el ciclo
end loop;
end process;

Ahora se ejecuta el programa todas las veces programadas, excepto la cuarta, ya que hay una sentencia
if que hace que se pase a la siguiente iteración si la varaibale i vale cuatro.

Sentencia null

La sentencia null se utiliza, al igual que en otros lenguajes de programación, para que dada una
condición especial no pase nada , es decir, que ninguna señal o variable cambie, y que el programa siga
su curso habitual. Su comportamiento dentro de un loop es similar al de la sentencia next.

http://det.bp.ehu.es/vhdl/pagina/completo/04.htm (10 of 12) [03/04/02 13:43:49]


Lección 4: Gramática del lenguaje I

Sentencia wait

La sentencia wait se usa para suspender un proceso si éste no tiene lista sensitiva. Lo único que exige
esta sentencia es estar situada la final del proceso. Para entender mejor ésto, basta con decir que los dos
códigos siguientes son equivalentes.

process
process (a,b,c)
begin
begin
x <= a and b and c;
x <= a and b and c;
wait on a,b,c;
end process;
end process;

Ambos procesos se ejecutarán cuando haya un cambio en la señal a, b o c se muestra en este caso la
equivalencia de una lista sensitiva y una sentencia wait explícita.

Sentencia wait until

No debemos confundir la sentencia wait until con la sentencia wait vista en el apartado anterior. En
esta ocasión, tampoco se puede usar una lsita sensitiva con el proceso, ya que ésta queda definida con la
misma sentencia. Para las descripciones la fórmula wait until debe estar al prncipio del proceso, por lo
que la lógica descrita de esta menera no puede ser reseteada asíncronamente. Veamos su uso en el caso
de la arquitectura de un flip-flop d:

architecture ejemplo of ffd is


begin
process begin
wait until (clk='1');
q <= d;
end process;
end ejemplo;

Este proceso se suspende hasta que la condición siguiente a wait until es verdadera. Una vez que es
verdad, y las asignaciones de señal se han realizado, el proceso vuelve a esperar hasta que la señal clk
vuelve a valer de nuevo 1, es decir, un flanco de subida. Pulsa aquí para ir a la práctica del Flip Flop D.

http://det.bp.ehu.es/vhdl/pagina/completo/04.htm (11 of 12) [03/04/02 13:43:49]


Lección 4: Gramática del lenguaje I

http://det.bp.ehu.es/vhdl/pagina/completo/04.htm (12 of 12) [03/04/02 13:43:49]


http://det.bp.ehu.es/vhdl/pagina/completo/05.htm

Gramática del lenguaje II

Llamada concurrente a
Sentencias concurrentes
subprograma
Sentencia Process
Sentencias estructurales
Asignación concurrente a señal
Subprogramas
Asignación concurrente condicional
Funciones
Asignación concurrente con selección
Procedimientos

Sentencias concurrentes

La naturaleza propia de los circuitos eléctricos obliga a VHDL a soportar un nuevo tipo de asignación de señales, que nos permita
implementar este tipo de operatividad. En ella todas las asignaciones se llevan a cabo en paralelo (al mismo tiempo). En una asignación
concurrente la señal que esté a la izquierda de la asignación es evaluada siempre que alguna de las señales de la derecha modifique su
valor. Como ejemplo tenemos las siguientes sentencias de asignación:

c <= a and b;
s <= a xor b;

Si las señales de entrada (situadas a la derecha), a o b, cambian su valor, las señales de salida (situadas a la izquierda), c y s, son
evaluadas, de forma que su valor se verá modificado si fuese necesario

Sentencia Process

La sentencia process es una de las construcciones típicas de VHDL usadas para agrupar algoritmos. Esta sentencia se inicia (de
forma opcional) con una etiqueta seguida de dos puntos ( : ), después la palabra reservada process y una lista de variables sensibles. La

http://det.bp.ehu.es/vhdl/pagina/completo/05.htm (1 of 10) [03/04/02 13:44:05]


http://det.bp.ehu.es/vhdl/pagina/completo/05.htm

lista sensible, indica que señales harán que se ejecuta el proceso, es decir, qué variable(s) debe(n) cambiar para que se ejecute el
proceso. Dentro de un proceso se encuentran sentencias secuenciales, no concurrentes. Esto hace que el orden de las órdenes dentro de
un proceso sea importante, ya que se ejecuta una después de otra, y los posibles cambios que deba haber en las señales alteradas se
producen después de evaluar todo el ciclo al completo. Esta característica define una de las particularidades de VHDL.

La estructura de un proceso es la siguiente:

etiqueta: process (var1, var2, ...)


begin Si cambia alguna de las variables situadas entre los
sentencias secuenciales paréntesis, se ejecuta el proceso.
end process etiqueta;

Siempre que queramos utilizar sentencias secuenciales se deberá usar un proceso. Como ejemplo del uso de un proceso se muestra el
siguiente fragmento de código correspondiente a un flip-flop d.

contador: process (clock)


begin Si hay un cambio en la señal clock (reloj), se ejecuta el
if (clock'event and clk='1') then process que contiene una sentencia if. Una vez acabado
q <= d; de evaluar todas las sentencias del proceso, se cambian
end if, todas las señales necesarias a la vez.
end process contador;

Es muy importante tener en cuenta dos cosas a la hora de usar un proceso respecto a las señales y las variables. La primera es que las
variables toman instantáneamente el valor especificado y que sólo tienen sentido de existencia dentro de un proceso. La segunda es que
las señales cambian su valor solamente al llegar al final del proceso. Esto se aprecia claramente en los dos ejemplos siguientes,cuyo
comportamiento se pretende que sea el siguiente (suponiendo que hemos cargado el operador +):

Si a tiene el valor "0000", entonces la salida/entrada b deberá incrementar su valor en una unidad, y si después e haber incrementado
la señal b, ésta vale "0001", c deberá valer '1', si no es así deberá valer '0'.

architecture no_funciona of uno is


begin Si hay un cambio en la señal de entrada a, entonces se
process (a) ejecuta el proceso:
begin
if a = "0000" then b <= b + 1; ● b se incrementa cuando se acabe de ejecutar el
end if; proceso (manteniendo el valor actual hasta el end
if b = "0001" then c <= '1'; del mismo) si a vale "1111"
● c vale '1' si b tiene el valor "0001"
else c <='0';
end process;
end no_funciona;

El primer ejemplo no funciona adecuadamente si b tiene le valor inicial de "0000". Veamos porqué: si y a cambia para tomar el
valor "0000", b se incrementará en una unidad al finalizar la evaluación del proceso, por lo que b no valdrá "0001" hasta entonces, por
lo que c no valdrá '1', que no era lo que deseábamos.

http://det.bp.ehu.es/vhdl/pagina/completo/05.htm (2 of 10) [03/04/02 13:44:05]


http://det.bp.ehu.es/vhdl/pagina/completo/05.htm

architecture funciona of uno is


begin
process (a)
variable v: bit_vector(3 downto 0); Si hay un cambio en la señal de entrada a, entonces se
ejecuta el proceso:
begin
v:=b;
● v toma instantaneamente el valor de b
if a = "0000" then v := v + '1'; ● v se incrementa instantaneamente si a vale "1111"
end if; ● c vale '1' si v tiene el valor "0001"
if v = "0001" then c <= '1'; ● b toma el valor de v
else c <='0';
b <= v;
end process;
end funciona;

El segundo ejemplo si que funciona como habíamos especificado para cualquier valor de b. Si a cambia y toma el valor "0000", la
variable v toma instantáneamente el valor inicial de b (esto es "0000"), y se incrementará en una unidad instantáneamente por lo que
valdrá "0001". Entonces c tomará el nivel lógico alto, y seguido a esto, b tomará el valor incrementado de v. Los nuevos valores de b y
c aparecerán a la salida al acabar la evaluación completa del proceso.

Asignación concurrente a señal

En un apartado anterior vimos como era la asignación secuencial a una señal. Pero las asignaciones a señales también pueden ser
concurrentes. La principal forma de ésta asignación es que no se encuentra en los procesos o subprogramas, sino en las arquitecturas.
La sintaxis de asignación tiene la misma forma que si fuese secuencial, es decir, usando el operador <=.

Asignación concurrente condicional

Esta asignación es equivalente a la sentencia if, con la salvedad que es concurrente. La sintaxis a seguir es la siguiente:

señal_uno <= señal_dos when condicion else señal_tres;

En este caso, a señal_uno se le asigna el valor de señal_dos si se cumple lo especificado en condición, y en caso de no cumplirse, se
le asigna el valor de señal_tres. Un ejemplo muy típico para el asignamiento concurrente condicional es el de un multiplexor. Los dos
listados siguientes tienen la misma operatividad:

http://det.bp.ehu.es/vhdl/pagina/completo/05.htm (3 of 10) [03/04/02 13:44:05]


http://det.bp.ehu.es/vhdl/pagina/completo/05.htm

process(control,entrada1,entrada2)
begin
if control='1' then
salida <= entrada1 when control='1' salida<=entrada1;
else entrada2; else
salida<=entrada2;
end if;
end process;

La última asignación también puede llevar condición (sólo a partir de la norma de 1993).

Asignación concurrente con selección

Es la forma compacta y concurrente de la sentencia case, la cual tiene la siguiente sintaxis:

with expresion select


señal1 <= señal2 when valor_expresión_1,
señal3 when valor_expresión_2;

Es muy importante notar que no se incluye el punto y coma (;) habitual más que al final de la sentencia, ya que de otra forma sería
incorrecto. La sentencia asigna a señal1 el valor de señal2 si se da que expresion toma el valor valor_expresión_1, toma el valor
señal3 si expresion toma el valor valor_expresión_2,... pudiendose ampliar esta cadena de condiciones tanto como queramos.

Como ejemplo veamos los siguientes fragmentos de código, ambos equivalentes, que modelan a una simple Unidad Lógica:

process(a, b, operacion)
begin
with operacion select case operación is
resul <= a and b when "00", when "00" => resul <= a and b;
a or b when "01", when "01" => resul <= a or b;
a xor b when "10", when "10" => resul <= a xor b;
not (a and b) "11"; when "11" => resul <= not(a and b);
end case;
end process;

En ambos fragmentos de código se realiza la operación and a las señales a y b siendo el resultado asignado a resul si operacion vale
"00", se realiza la operación or si operación vale "01", etc. La diferencia entre ambas rutinas es que la izquierda es concurrente y la de
la derecha es secuencial.

Llamada concurrente a subprograma

http://det.bp.ehu.es/vhdl/pagina/completo/05.htm (4 of 10) [03/04/02 13:44:05]


http://det.bp.ehu.es/vhdl/pagina/completo/05.htm

La llamada a una función o a un procedimiento (los dos tipos existentes de subprogramas) la podemos encontrar tanto en una
arquitectura como dentro de un proceso, teniendo en ambos casos la misma apariencia. La que nos ocupa ahora es la primera, que es la
concurrente, la cual se ejecuta si cualquiera de los parámetros de entrada cambia. Debemos tener en cuenta que las funciones que
vayamos a usar deben ser visibles para el compilador, es decir, que la librería que las contenga debe estar declarada correctamente. La
sintaxis general es la siguiente:

nombre_de_la_función (entradas, salidas);

Al subprograma llamado nombre_de_la_función se le introduce el objeto entradas y sacamos el objeto salidas. Los objetos de
entrada y salida no tienen porque ser del mismo tipo, ya que dentro del subprograma puede haber cambiado.

Sentencias estructurales

Las sentencias estructurales (o de instantación), son una forma más de hacer llamadas a subprogramas en VHDL. Con ellas se puede
hacer uso de un componente o circuito definido con anterioridad sin necesidad de incluirlo en la descripción que se está realizando; sólo
habrá que hacer una llamda a dicho componente para usarlo con las especificaciones propias del diseño actual. Se aprecia que su
operatividad es muy similar a la de una librería. El lenguaje nos proporciona una serie de sentencias dedicadas a la descripción de la
estructura de hardware que son concurrentes, y aparecen en la arquitectura llamando a un modelo fuera de cualquier proceso. Estas son
las sentencias estructurales, cuyo principal elemento son los componentes con su función port map (mapa de puertos).

Componentes: Para realizar la descripción estructural de un sistema es necesario conocer qué sistemas o componentes lo
forman, indicando la interconexiones entre ellos. Para operar de esta forma, VHDL ofrece los componentes. Para ser usado, un
componente debe estar declarado previamente para poder hacer referencia al mismo. Si se declara un componente en una arquitectura,
podrá ser usado en cualquier parte de la misma, pero si a referencia se hace en un paquete, se podrá lamar en todas las arquitecturas que
llamen a ese paquete.

El estilo estructural es fácilmente reconocible porque la operatividad del programa no se puede leer del código ya que está formado
íntegramente por componentes y las señales que les unen a otros. Es decir, está formado por bloques o cajas negras a los cuales
metemos información y sacamos las salidas, las cuales podrán o no ir a otros bloques. Para esto debemos conocer la operatividad de
estos bloques, los cuales suelen estar en librerías. Para usar las puertas que están en el paquete gatespkg debemos primero invocar a la
librería ieee (léase "i e cubo") como está expuesto en la primera línea de la entidad que debemos usar. Para usar el paquete (o sub-
librería) gatespkg la llamaremos de la forma en que está en la segunda línea. Estas librerías vienen incluidas en la versión 3.5 del
programa WARP, de Cypress Semiconductor. Como ejemplo se lista el código de un multiplexor implementado por descripción
estructural.

http://det.bp.ehu.es/vhdl/pagina/completo/05.htm (5 of 10) [03/04/02 13:44:05]


http://det.bp.ehu.es/vhdl/pagina/completo/05.htm

library ieee; Llamamos a la librería IEEE


use work.gatespkg.all; Llamamos a la librería que tiene las
puertas lógicas
entity multi is port(
a,b : in bit;
control : in bit;
enable : in bit;
c : out bit
);
end multi;

architecture archmul of multi is Cabecera del programa


signal aux0,aux1,aux2,aux3: bit; Declaración de señales
begin Empieza el programa
puerta0:inv port map(control,aux0); Sentencia concurrente
puerta1:and2 port map(b,aux0,aux1); Sentencia concurrente
puerta2:and2 port map(a,control,aux2); Sentencia concurrente
puerta3:or2 port map(aux1,aux2,aux3); Sentencia concurrente
puerta4:and2 port map(enable,aux3,c); Sentencia concurrente
end archmul; Finalizamos el programa

La funcionalidad de este fragmento de código se basa en los elementos "inv", "and2" y "or2", que se encuentran en la librería
gatespkg, que listamos a continuación:

package gatespkg is Incluimos el nombre del paquete


component and2 Empezamos el componente and2
port (
a,b : in bit;
q : out bit
);
end component;

component or2 Empezamos el componente or2


port (
a,b : in bit;
q : out bit
);
end component;

component inv Empezamos el componente inv


port (
a : in bit;
qn : out bit
);
end component;

use work.cypress.all; Empezamos la entidad and2


entity and2 is
port (
a,b : in bit;
q : out bit
);
end and2;
architecture archand2 of and2 is

http://det.bp.ehu.es/vhdl/pagina/completo/05.htm (6 of 10) [03/04/02 13:44:05]


http://det.bp.ehu.es/vhdl/pagina/completo/05.htm

begin
q <= (a and b);
end archand2;

use work.cypress.all;
entity or2 is Empezamos la entidad or2
port (
a,b : in bit;
q : out bit
);
end or2;
architecture archor2 of or2 is
begin
q <= (a or b);
end archor2;

use work.cypress.all;
entity inv is
port (
a : in bit; Empezamos la entidad inv
qn : out bit
);
end inv;
architecture archinv of inv is
begin
qn <= not (a);
end archinv;

Subprogramas

Los subprogramas se usan para describir algoritmos de cualquier tipo que son más tarde usados tantas veces como se desee. Un
subprograma consta de una parte declarativa en la cual se definen los datos de entrada y de salida al mismo, y una parte de sentencias
en la cual se indica que operaciones se realizan sobre los datos.

Los subprogramas constan de dos partes: la definición del subprograma y la definición del cuerpo del subprograma. En la primera se
define el nombre del mismo y los parámetros que son introducidos en él. En la segunda se incluye el algoritmo que va a realizar el
subprograma.

Hay dos tipos de subprogramas, las funciones y los procedimientos, los cuales tratamos en puntos separados a éste.

Funciones

Las funciones están destinadas a realizar cálculos, siendo una nueva forma de definir nuevos operadores que pueden aparecer en una

http://det.bp.ehu.es/vhdl/pagina/completo/05.htm (7 of 10) [03/04/02 13:44:05]


http://det.bp.ehu.es/vhdl/pagina/completo/05.htm

expresión. A las funciones se le pueden introducir todos los valores que se necesiten, pero sólo devuelven un único valor, siendo las
variables internas a ella imposibles de recuperar para otras operaciones.

Una función está formada por:

Parte declarativa: En ella indicamos cuales son los parámetros que introducimos en la función, la cual entenderá que
son constantes, y de modo in (por defecto). Podemos definir, además, todas las estructuras de datos que necesitemos
(tipos, constantes, variables,...), pero sólo existirán cuando la función haya sido llamada y se crean e inicializan cada vez
que esto ocurra. Esta es la razón de no poder incluir señales en la parte declarativa.

Parte de sentencias: En ella se transforman los objetos que introducimos en la función para obtener la salida. En esta
parte podremos usar el valor de señales y variables externas, pero no podremos modificarlas. Tampoco podremos usar la
sentencia wait.

Como ejemplo crearemos una función que realiza una operación tan sencilla como asignar a la salida de la función, suma, la suma de
dos números, a y b.

La parte declarativa sería:

function sumar (a,b: std_logic_vector(3 downto 0))


return std_logic_vector(3 downto 0);

Empieza por la palabra reservada function y seguido va el nombre de la función y entre paréntesis los objetos de entrada con su tipo
correspondiente. Después va la palabra return y el tipo del resultado de la función. Tiene el mismo sentido que las entidades.

La parte de sentencias sería:

function sumar (a,b: std_logic_vector(3 downto 0))


return std_logic_vector(3 downto 0) is
variable suma: std_logic_vector
begin
suma := a + b ;
return suma
end function sumar;

Las primeras líneas de la parte de sentencias coinciden con la parte declarativa, sólo que la primera lleva al final la palabra is, tal y
como se aprecia en el ejemplo. Seguido viene la declaración de tipos, subtipos y variables, etc. en la cual debe incluirse la variable que
va a ser devuelta por la función, que en este caso es suma. Entre la palabra reservada begin y end debemos incluir el algoritmo que
dará un valor a la variable que será el resultado, y la sentencia return suma. Esta última sentencia es imprescindible para definir la
función, ya que de no hacerlo ésta se quedaría sin resultado.

Para llamar a esta función deberemos escribir un código parecido a este en nuestro programa, teniendo en cuenta que la llamada a
una función no es por si misma una sentencia:

process
variable numero1, numero2: std_logic_vector(3 downto 0);
variable salida: std_logic_vector(3 downto 0);
begin
...
salida := sumar (numero1,numero2);
...
end process;

http://det.bp.ehu.es/vhdl/pagina/completo/05.htm (8 of 10) [03/04/02 13:44:05]


http://det.bp.ehu.es/vhdl/pagina/completo/05.htm

En esta ocasión hemos hecho la asignación de las entradas por posición: al ejecutarse la función, el compilador usa el valor de
numero1 como a, ya que numero1 es el primer valor que se introduce en la función y a es el primero incluido en la declaración de la
función. Lo mismo ocurre con numero2 y con b. También podíamos haber hecho el asignamiento por nombre de cualquiera de las
siguientes formas, siendo ambas equivalentes:

salida := sumar ( numero1=>a, numero2=>b );

salida := sumar ( numero2=>b, numero1=>a );

Sea cual sea la forma en la cual asignemos las señales a la entrada del subprograma, éstas deben coincidir en el tipo, es decir, en el
ejemplo no podíamos haber introducido en la función numero1 y numero2 si éstos hubieran sido del tipo entero o bit. De la misma
forma la variable o la señal a la cual asignamos el valor de la función debe coincidir con el tipo del objeto que hemos especificado para
la salida en la función. Es decir, no podemos asignar a salida el valor de la función que hemos creado si es del tipo integer (por
ejemplo), ya que la salida de la función es suma que es del tipo std_logic_vector.

Procedimientos

Los procedimientos están destinados a realizar alteraciones en los datos a los que tienen acceso, tanto internos como externos. De
forma distinta a las funciones, un procedimiento puede devolvernos más de un valor e incluso modificar alguno de los valores que le
introducimos. Un procedimiento o procedure consta al igual que las funciones de una parte declarativa y otra de sentencias:

Parte declarativa: En ella indicamos cuales son los parámetros que introducimos en la procedure, pudiendo ser de
tres modos posibles: in, out, e inout, y son por defecto del modo in. Si el modo de una señal de entrada es in, no
podremos modificar su valor, solamente usarlo, y a ojos de la procedure será una constante. Si el modo es out podrán ser
modificados en la parte de sentencias, pero al igual que pasa en una entidad no podremos leer su valor. Solamente si es de
modo inout podremos leer su valor y además modificarlo. Al igual que en las funciones podremos declarar todos los
tipos, constantes, variables, etc. pero sólo existirán cuando se haga un llamamiento a la procedure y se reinicializarán
cada vez que se vuelva a llamar.

Parte de sentencias: En ella se modifican señales y variables tanto internas como externas al procedure, pudiendo
además usar la sentencia wait.

Para aclarar conceptos, se muestra el siguiente codigo, en el cual se consigue el mismo resultado que en el ejemplo expuesto en el
apartado de funciones. La parte declarativa es la siguiente:

procedure sumar (a,b: std_logic_vector(3 downto 0),


suma: out std_logic_vector(3 downto 0));

Su estructura se asemeja a la de una entidad y empieza con la palabra reservada procedure seguida del nombre que le vamos a
asignar a la misma (en este caso es sumar), y entre paréntesis se declaran los objetos de entrada como si de una entidad se tratase. En
los procedimientos no hace falta usar la palabra return, ya que se especifica cuál de las señales es de entrada y/o salida.

La parte de declaraciones sería como sigue:

http://det.bp.ehu.es/vhdl/pagina/completo/05.htm (9 of 10) [03/04/02 13:44:05]


http://det.bp.ehu.es/vhdl/pagina/completo/05.htm

procedure sumar (a,b: std_logic_vector(3 downto 0),


suma: out std_logic_vector(3 downto 0));
begin
suma <= a + b ;
end procedure sumar;

La primera parte consiste en repetir la parte declarativa y seguidamente, el subprograma con sus algoritmos correspondientes.

Una vez definido el procedimiento podremos usarlo en cualquier parte del programa ya sea secuencial o combinacional como por
ejemplo:

process
variable numero1, numero2: std_logic_vector(3 downto 0);
variable salida: std_logic_vector(3 downto 0);
begin
...
sumar (numero1,numero2,salida);
...
end process;

Al igual que en una función, los tipos de los objetos de entrada y salida a una función deben coincidir con los declarados en el
procedimiento. Es importante notar que una llamada a una procedure es una sentencia, no como una llamada a una función.

En este caso hemos hecho la asignación por posición, ya que al no indicar nada, el compilador supone que queremos asignar el
primer objeto que hemos introducido en la función al primer objeto que habíamos declarado cuando creamos el procedimiento. Esto es
numero1 se corresponde a a, numero2 se corresponde con b, y así sucesivamente. Si queremos asignarlos por nombre deberemos
hacerlo como se describe a continuación:

sumar ( numero1=>a, numero2=>b, salida =>suma );

sumar ( salida=> suma, numero2=>b, numero1=>a );

Ambas formas de llamar al procedimiento son válidas y equivalentes.

http://det.bp.ehu.es/vhdl/pagina/completo/05.htm (10 of 10) [03/04/02 13:44:05]


http://det.bp.ehu.es/vhdl/pagina/completo/06.htm

Interface, compilador e implementación física

VHDL sintetizable

Galaxy de Cypress

Nova de Cypress

Grabación de nuestros
diseños

VHDL sintetizable

En un principo VHDL, al igual que los demás HDL'S, nacieron con el proposito de facilitar la labor de los
diseñadores de circuitos electrónicos, agilizando su diseño y haciendo más flexible su posterior depuración y
mantenimiento. Por este motivo se dotó a VHDL con abundantes instrucciones más orientadas a la simulación
que a la implementación física del diseño. Ello trajo consigo la diferenciacion del VHDL sintetizable del
simulable, siendo este último el más extendido y el que cuenta con más herramientas en los programas. Si
trabajamos con VHDL sintetizable, sólo podremos hacer uso de un conjunto de instrucciones válidas.

El lenguaje nos permite describir circuitos complejos manejando todas las sentencias y herramientas de las que
dispone, pero no siempre se garantiza que se pueda llegar a grabar en un dispositivo de lógica programable
(PLD), ya que ciertas instrucciones no tienen equivalente físico.

Como conclusión, se puede decir que todo el código de un programa en VHDL es simulable, pero no siempre
será sintetizable.

http://det.bp.ehu.es/vhdl/pagina/completo/06.htm (1 of 15) [03/04/02 13:44:51]


http://det.bp.ehu.es/vhdl/pagina/completo/06.htm

Galaxy de Cypress

Dado que el VHDL es el lenguaje estándar, todas las empresas fabricantes de PLD’s y FPGA’s (Cypress,
Xilinx, Altera, Actel, etc.) han desarrollado su propio compilador cada uno con sus propias funciones y
características especiales. Este turorial ha sido realizado basándose en el programa Warp2, del cual se muestran
varias ventanas cortesía de la compañía Cypress Semiconductor.

A pesar de ser un producto no muy pensado de cara al usuario, la herramienta de Cypress es tan potente como
las demás, contando además con un gran soporte técnico vía e-mail. El nombre de la herramienta se llama WARP
2, que actualmente va por su versión 4.3. Este conjunto de programas está orientado a la creación de un fichero
propio de VHDL (*.vhd), para compilarlo (Galaxy) y posteriormente simularlo (Nova).

Para conseguir este software se puede solicitar por correo ordinario o electrónico en la página web de Cypress.

El programa Galaxy es el núcleo de la suite WARP2, ya que nos gestiona los programas creados, nos permite
editarlos y elegir distintas opciones de compilación. Su pantalla principal es la siguiente:

Con este programa podremos describir un circuito en VHDL, compilarlo y simularlo, sin más que usar el menú
adecuado.

Al arrancar por primera vez el programa, nos aparecerá una pantalla que nos gestionará el control de un
proyecto, entendiéndose por proyecto la creación de una serie de PLD’s concernientes al mismo trabajo o tema.
Deberemos introducir en este cuadro de diálogo, la ruta y nombre del proyecto, según nuestras preferencias, y
añadirle la extensión wpr:

http://det.bp.ehu.es/vhdl/pagina/completo/06.htm (2 of 15) [03/04/02 13:44:51]


http://det.bp.ehu.es/vhdl/pagina/completo/06.htm

En este caso hemos creado un proyecto llamado "proyecto.wpr" en la ruta "c:\warp\proyecto".

Una vez hecho esto pasamos a la ventana principal del programa. Si queremos crear un nuevo fichero para
compilar, deberemos llamar al editor de texto, para lo que deberemos pulsar el botón llamado selected o el botón
llamdo new, en la parte de edit, según querramos modificar un fichero ya creado o bien hacer uno nuevo,
respectivamente. Entonces se nos abrirá una ventana similar a la siguiente:

http://det.bp.ehu.es/vhdl/pagina/completo/06.htm (3 of 15) [03/04/02 13:44:51]


http://det.bp.ehu.es/vhdl/pagina/completo/06.htm

En esta ventana crearemos o modificaremos el código fuente de VHDL según lo que queramos realizar. Este
editor tiene una serie de guías para ayudarnos a programar, por si se nos olvida la sintaxis. Una vez escrito todo el
código del programa, lo deberemos guardar, con extensión vhd, en el mismo subdirectorio en el cual hemos
creado el fichero de extensión wpr (en este caso es c:\warp\proyecto) para que pueda ser compilado sin ningún
problema por el programa.

Si queremos crear una librería nueva para este proyecto, deberemos especificarla después de haber creado el
fichero de extensión wpr. Para ello deberemos ir al comando files/libraries y crear una nueva si así lo deseamos.

Una vez creada la librería, deberemos decir al programa qué queremos compilar, para lo cual deberemos ir al
menú files/add y seleccionar el fichero que queramos compilar. Una vez hecho esto, aparecerá el nombre de
dicho fichero en la parte izquierda de la ventana, debajo del menú de comandos.

Antes de pulsar los botones que nos compilarán el programa creado, deberemos seleccionar qué tipo de PLD
vamos a usar, el tipo de optimización, etc. Eta tarea la realizamos con los botones de la parte inferior del
programa: file, set top, generic y device.

El botón file nos servirá para decirle al programa que queremos usar la librería por defecto (es lo más
habitual) o si queremos usar un creada. Su aspecto es el siguiente:

http://det.bp.ehu.es/vhdl/pagina/completo/06.htm (4 of 15) [03/04/02 13:44:51]


http://det.bp.ehu.es/vhdl/pagina/completo/06.htm

El botón set top sirve para indicar cual de los ficheros a compilar es el principal, del cual cuelgan los demás
ficheros. El botón generic nos lleva al menú que nos permitirá elegir ciertas opciones como si deseamos
optimizar la velocidad o el área usada del dispositivo de lógica programable. El aspecto del menú es el siguiente:

http://det.bp.ehu.es/vhdl/pagina/completo/06.htm (5 of 15) [03/04/02 13:44:51]


http://det.bp.ehu.es/vhdl/pagina/completo/06.htm

El botón device nos permitirá elegir el tipo de PLD que usaremos para grabar nuestro diseño, que hacer con las
salidas no usadas, que tipo de FlipFlops queremos usar, etc. El aspecto del menú es el siguiente:

http://det.bp.ehu.es/vhdl/pagina/completo/06.htm (6 of 15) [03/04/02 13:44:51]


http://det.bp.ehu.es/vhdl/pagina/completo/06.htm

Una vez hechas todas estas operaciones habremos dejado todo preparado para empezar a compilar.

Pulsando en los botones selected o smart, de la parte compile, podremos compilar uno o más ficheros de
VHDL simultáneamente. Una vez pulsado cualquiera de los botones de compilación, nos aparecerá una pantalla
con las incidencias de la misma, incluyendo las librerías usadas, fecha, hora, errores, etc.

Desde esta pantalla podremos acceder a las líneas del código erróneas directamente y modificarlas para
solucionar el problema, lo cual es una gran ayuda para eliminar errores de nuestros programas. En esta ventana
apreciamos la forma de trabajar interna del programa, ya que nos dice el nombre de los programas que van
verificando el fichero en busca de errores, y como se va transformando el código original en un fichero que nos
permitirá grabarlo en una PLD. Dicha pantalla tiene el aspecto siguiente:

http://det.bp.ehu.es/vhdl/pagina/completo/06.htm (7 of 15) [03/04/02 13:44:51]


http://det.bp.ehu.es/vhdl/pagina/completo/06.htm

Si en la barra de estados de la ventana de compilación aparece la leyenda "Compilation successful" (como


aparece en la figura), querrá decir que la compilación ha tenido éxito y que el fichero de vectores JEDEC, de
extensión jed, necesario para la grabación de las PLD’s ha sido creado correctamente.

Una vez compilado el programa, llamaremos al programa simulador de ficheros de VHDL compilados (de
extensión jed), llamado Nova, pulsando en el menú "Tools/Nova", tal y como se aprecia en al siguiente figura:

http://det.bp.ehu.es/vhdl/pagina/completo/06.htm (8 of 15) [03/04/02 13:44:51]


http://det.bp.ehu.es/vhdl/pagina/completo/06.htm

Nova de Cypress

El programa Nova es el complemento a Galaxy, ya que nos va a simular los ficheros compilados previamente.
Su aspecto es similar a un analizador lógico, y le podremos introducir las entradas que queramos para ver si las
salidas que vayamos a obtener son las correctas. Su aspecto es el siguiente:

http://det.bp.ehu.es/vhdl/pagina/completo/06.htm (9 of 15) [03/04/02 13:44:51]


http://det.bp.ehu.es/vhdl/pagina/completo/06.htm

Para simular un fichero jed (de vectores JEDEC) deberemos primero abrirlo con el comando "file/open". Lo
siguiente que nos aparece es un cronograma con las entradas y las salidas que admitirá la PLD. Nosotros
podremos introducir las entradas y darle la forma que queramos (nivel lógico alto o bajo, que sea un reloj, que
tenga un pulso,...) según lo que deseemos, sin más que acceder al menú "edit".

Una vez modificada la forma de las entradas, y accediendo al comando "execute" del menú "simulate", el
programa nos ofrecerá en rojo las salidas que hubiéramos obtenido de haber grabado la PLD con este fichero.
Haciendo doble clic en la pare inferior de la ventana nos aparecerá una línea de guía para poder seguir mejor el
resultado de la simulación.

También nos permite el organizar las entradas y salidas en forma de bus para controlar mejor los resultados.
Esto es muy útil si estamos manejando entradas y/o salidas de varios bits de anchura y necesitamos saber su valor
en todo momento.

Un ejemplo de cómo es útil la creación de un bus se muestra en las siguientes imágenes, donde, en la superior
no se usa un bus y en la inferior donde sí se usa. En ambas hemos introducido la misma entrada aleatoria y
queremos saber el resultado de al simulación para las salidas en el instante 50ns.

En el primer caso, sin bus, deberemos analizar cual es el valor de cada uno de los bits de salida, e interpretarlo
para ver que es "111", o bien, "7".

http://det.bp.ehu.es/vhdl/pagina/completo/06.htm (10 of 15) [03/04/02 13:44:51]


http://det.bp.ehu.es/vhdl/pagina/completo/06.htm

Si hemos creado un bus, como en la siguiente imagen. El resultado de los bits de salida los va marcando el
programa sin más que desplazar la guía hasta el instante deseado, para ver que la salida es "00x7". Para crear un
bus hay que ejecutar el comando edit/create bus, y seleccionar que señales queremos que formen parte del bus.

http://det.bp.ehu.es/vhdl/pagina/completo/06.htm (11 of 15) [03/04/02 13:44:51]


http://det.bp.ehu.es/vhdl/pagina/completo/06.htm

Una vez que hayamos dado este paso, estaremos preparados para grabar nuestra PLD en las máquinas
dispuestas a tal efecto.

Grabación de nuestros diseños

Para poder implementar las descripciones realizadas en VHDL en un dispositivo de lógica programable, se
necesita un programador de PLD's y el software de que nos grabará el cirucito usando el fichero compilado por
Warp (de extensión jed). Como ejemplo usaremos el software y la máquina de Advantech Lab Tool, del cual se
muestra a continuación la pantalla principal.

http://det.bp.ehu.es/vhdl/pagina/completo/06.htm (12 of 15) [03/04/02 13:44:51]


http://det.bp.ehu.es/vhdl/pagina/completo/06.htm

Para comenzar, se debe indicar al grabador el tipo de dispositivo en el cual vamos a programar nuestro diseño.
Esto se lleva a cabo pulsando el botón select de la barra de herramientas del Lab Tool. Una vez hecho esto,
aparecerá un cuadro de diálogo en el cual se pide al usuario que elija el tipo de dispositivo a utilizar (tipo, marca y
modelo), como se muestra en la imagen.

http://det.bp.ehu.es/vhdl/pagina/completo/06.htm (13 of 15) [03/04/02 13:44:51]


http://det.bp.ehu.es/vhdl/pagina/completo/06.htm

Una vez seleccionado el dispositivo es conveniente comprobar que el mismo esté en blanco (sin usar),
pulsando el botón blank . En el caso de que el PLD no estuviera vacío, deberemos borrarlo (si se nos permite)
usando el botón erase .

Una vez que se haya seleccionado el tipo de encapsulado y lo hemos verificado, se indica al software grabador
qué queremos implementar en el dispositivo elegido. Para esta tarea deberemos indicar mediante un cuadro de
dialogo estándar de Windows el fichero deseado, como se aprecia a continuación.

http://det.bp.ehu.es/vhdl/pagina/completo/06.htm (14 of 15) [03/04/02 13:44:51]


http://det.bp.ehu.es/vhdl/pagina/completo/06.htm

Cuando se haya elegido el encapsulado y el fichero a programar, con tan sólo pulsar el botón prog se grabará la
PLD de forma automática, y habremos concluido el proceso, yaque el mismo programa, después de grabar el
dispositivo, lo verifica.

http://det.bp.ehu.es/vhdl/pagina/completo/06.htm (15 of 15) [03/04/02 13:44:51]


Práctica 0: Conocimientos básicos para el modo Express

Esta parte del tutorial te permitirá implementar desde el primer momento los ejercicios
propuesto y entender el lenguaje VHDL. Lo único que se necesita para seguir este curso es
saber Electrónica Digital y tener nociones de cualquier lenguaje de programación ya sea
Pascal, C, Basic,...

El lenguaje de descripción hardware VHDL (Very high speed Hardware Description Logic) es
un lenguaje orientado a la descripción de hardware pero con muchos elementos heredados de
otros lenguajes como C o Pascal. Una vez realizado un programa en VHDL (con extensión
VHD) y haberlo compilado con éxito, tendremos un fichero con el mismo nombre y extensión
JED, con el cual podremos grabar una PLD (Dispositivo Lógico Programable) con la misma
operatividad que el fichero VHD.

Al describir cualquier dispositivo en VHDL (desde una simple puerta and hasta un sistema
completo) se deben definir dos elementos principales:

Entidad o entity que es la interfaz del dispositivo con el exterior. Tiene por
objeto decir que señales son visibles o accesibles desde el exterior, es decir los
puertos o ports del dispositivo. Es describir las patillas del circuito que serán
operativas. Su estructura mas general es la siguiente, donde las palabras en
negrita son propias del lenguaje, y las restantes elegidas por el ususrio:

entity entidad is
genericos
puertos
declaraciones
end nombre;

Pero debemos fijarnos en la estructura más habitual de las entidades que es la


siguiente:

entity entidad is
puertos
end entidad;

Arquitectura o arquitecture que es la funcionalidad que realiza el dispositivo,


es decir, qué transformaciones se realizarán sobre los datos que entren por los

http://det.bp.ehu.es/vhdl/pagina/express/conoci.htm (1 of 2) [03/04/02 13:45:03]


Práctica 0: Conocimientos básicos para el modo Express

puertos de entrada para producir la salida. Dentro de este apartado es donde se


dota de operatividad al circuito. Su estructura general es la siguiente, y debe estar
incluida en el mismo fichero de la entidad a la que hace referencia:

arquitecture nombre of nombre_entidad is


declaraciones
begin
sentencias
end nombre;

Para acabar esta introducción deberemos tener en cuenta una serie de detalles más de éste
lenguaje:

VHDL no distingue las mayúsculas de las minúsculas, por lo que deberemos


tener cuidado al asignar nombres a las variables, especialmente si estamos
acostumbrados a trabajar con C.

Las variables deben empezar por una letra, no deben contener ni espacios ni
símbolos como &, %, $, #, !, etc. Su longitud no está limitada, no pueden acabar
con un carácter de subrayado o tener dos subraryados seguidos.

Para representar un número de una sola cifra, deberemos situarlo entre


apóstrofes; así: '1'

Para representar un número de mas de una cifra, lo representaremos así:


"10011"

Es muy probable que en cada práctica encuentres varias entidades y varias


arquitecturas. Tomando como ejemplo al multiplexor, sabemos que no todos
tienen el mismo número de bits o de canales, por eso cada uno tiene una entidad
distinta.

http://det.bp.ehu.es/vhdl/pagina/express/conoci.htm (2 of 2) [03/04/02 13:45:03]


Práctica 1: Multiplexor

Un multiplexor es un dispositivo lógico que recibe información por sus dos o más entradas (de uno o
mas bits de ancho) y mediante una señal de control decidimos cual de la entradas aparece reflejada
en la salida; esto es, un convertidor de paralelo a serie. Si tienen una señal de "enable" esta hace
que el multiplexor esté habilitado o no
Los multiplexores disponibles tienen todos señal de enable menos el primero. Las arquitecturas
están realizadas solo para algunas entidades

Elige en la lista una práctica para empezar, sin más que pinchar en el botón adecuado. Para volver
pulsa el botón que está al lado del título

Multiplexor de un bit y dos canales sin "enable"

Cómo añadir una señal de "enable"

Como aumentar los bits de cada canal

Cómo aumentar el número de canales

Completar la entidad 4 con estilo algorítmico o de


comportamiento

Completar la entidad 2 con estilo flujo de datos

Completar la entidad 2 con estilo estructural

Entidad 1: Multiplexor de un bit y dos canales sin


"enable"
Este primer ejemplo es el más sencillo de todos ya que no se puede concebir un multiplexor con menos operatividad.
Usaremos el tipo bit, que viene predefinido por VHDL, y sirve para indicar que la señal o variable asociada es de un sólo bit.
La nomenclatura usada para designar a los puertos se mantendrá hasta el final de la práctica, no así como el nombre de la
entidad, que lo cambiaremos.

http://det.bp.ehu.es/vhdl/pagina/express/01.htm (1 of 8) [03/04/02 13:45:43]


Práctica 1: Multiplexor

entity multiplexor is port(


a,b : in bit; En este caso, las entradas son a y b (por eso son del modo in),
control : in bit;
la señal de control es control (también del modo in), y la
c : out bit
salida es c (del modo out). Todas son de un bit de ancho.
);
end multiplexor;

Entidad 2: Qué hacer para que tenga señal de "enable"


Para que nuestro diseño tenga una señal de enable, y a efectos de la entidad, solamente debemos incluirla sin más. Más
adelante, en la arquitectura será donde deberemos manejar esta señal para que realice lo que nosotros queramos.

entity multiplexor is port(


a,b : in bit;
control : in bit; En este caso, las entradas son a y b, la señal de control es
enable : in bit; control, la señal de enable es enable, y la salida es c. Todas
c : out bit vuelven a ser de un bit de ancho.
);
end multiplexor;

http://det.bp.ehu.es/vhdl/pagina/express/01.htm (2 of 8) [03/04/02 13:45:43]


Práctica 1: Multiplexor

Entidad 3: Qué hacer para que cada canal sea de mas bits
Si queremos que cada entrada (y la salida, por supuesto), tengan más anchura, es decir, más bits, no nos sirve el tipo bit, ya
que su anchura es de un bit. Para ello deberemos usar vectores de bits, que al igual que bit está predefinida en VHDL. En este
ejemplo usaremos entradas de 4 bits, que para definirlos hay que escribir el número de mayor peso seguido de la palabra
downto y del número de menor peso.

entity multiplexor is port(


a,b:in bit_vector(3 downto 0); En este caso, las entradas son a y b, la señal de control es
control:in bit; control, la señal de habilitación es enable, y la salida es c.
enable :in bit; Ahora, las entradas a y b son de 4 bits de ancho, pero como
c: out bit_vector(3 downto 0) sólo son dos, control debe seguir siendo de un solo bit. La
); salida debe aumentar también para adaptarse a las entradas.
end multiplexor;

http://det.bp.ehu.es/vhdl/pagina/express/01.htm (3 of 8) [03/04/02 13:45:43]


Práctica 1: Multiplexor

Entidad 4: Qué hacer para que tenga más canales


Al igual que cuando queríamos que tuviese señal de enable, si ahora queremos más canales, a efectos de la entidad, sólo
debemos añadirlos.

entity multiplexor is port(


a,b,c: in bit_vector(3 downto 0); En este caso, las entradas son a, b, y c, la señal de control es
control:in bit_vector(1 downto 0); control, la señal de habilitación es enable, y la salida es d.
enable: in bit; Las entradas y la salida siguen siendo de 4 bits de ancho, y al
d: out bit_vector(3 downto 0); haber mas de dos, control debe aumentar su anchura a dos
); bits.
end multiplexor;

control enable d
XX H HHHH
LL L a
LH L b
HL L c
HH L HHHH

Arquitectura 1: Estilo algorítmico o de comportamiento usando la


entidad 4
El estilo algorítmico es una forma de programación en la cual se usan los elementos propios de un lenguaje de programación,
es decir, ciclos for, while, case,... Para un multiplexor, parece hecha a la medida la sentencia case, y para comprobar si la
entrada enable está habilitada un ciclo for. Una forma de implementar el multiplexor correspondiente a la entidad 4 sería la

http://det.bp.ehu.es/vhdl/pagina/express/01.htm (4 of 8) [03/04/02 13:45:43]


Práctica 1: Multiplexor

siguiente:

1 entity multi is port(


2 a, b, c :in bit_vector(3 downto 0);
3 enable :in bit;
4 control :in bit_vector(1 downto 0);
5 d :out bit_vector(3 downto 0)
6 );
7 end multi;
8 architecture archmul of multi is Cabecera del programa
9 begin Empieza el programa
10 process (a, b, c, control, enable) Cabecera de un proceso
11 begin Empieza el proceso
12 if enable='1' then d<="1111"; Sentencia if
13 elsif enable='0' then Sentencia elsif
14 case control is Sentencia case
15 when "00" => d <= a;
16 when "01" => d <= b;
17 when "10" => d <= c;
18 when others => d <= "1111";
19 end case; Acaba sentencia case
20 end if; Acaba sentencia if y elsif
21 end process; Acaba el proceso
22 end archmul; Finaliza el programa

Debemos ver lo siguiente en este ejercicio:

● Entre las líneas 9 y 22 es donde se encuentra toda la operatividad del programa, es decir que hacemos con las entradas
para que se conviertan en las salidas.
● En la línea 10 empieza un proceso (process), el cual acaba en la línea 21. Si alguna de las variables que están dentro
del paréntesis cambia, el proceso se ejecuta. Una vez ejecutado el proceso cambian las señales, no durante él.
● En la línea 12 hay una sentencia que acaba en la línea 20. Si se cumple la condición que está después de la palabra if,
se ejecuta lo que está después de la palabra then. En caso de que la condición no se cumpla, se evalúa lo que está
detrás de la palabra elsif, y si es verdad se ejecuta lo que está después del segundo else. Si se cumple la primera
condición, es decir, que enable valga "1", el multiplexor pasa a tener a la salida el valor "1111". Si no se cumple, pasa
a ejecutarse una case. Pulsa aquí para ver la sentencia if. Pulsa aquí para ver la sentencia case.
● La sentencia case empieza en la línea 14 y acaba en la 29. Según los valores que tome control, la salida d tendrá un
valor u otro.
● Todas las sentencias que se abran deben estar correctamente cerradas con la palabra clave end. Debemos saber que al
cerrar una sentencia if también cerramos a la vez todas las sentencias elsif asociadas a ese if. Lo mismo ocurre con el
programa principal, el cual debemos cerrar con end y el nombre de la arquitectura.
● La sentencia case debe estar siempre dentro de un proceso para que la sintaxis esté correcta.

http://det.bp.ehu.es/vhdl/pagina/express/01.htm (5 of 8) [03/04/02 13:45:43]


Práctica 1: Multiplexor

Arquitectura 2: Estilo flujo de datos usando la entidad 2


El estilo de flujo de datos nos muestra la funcionalidad de un dispositivo mediante ecuaciones ejecutadas concurrentemente,
es decir, todas a la vez. Mediante las sentencias and, xor, not, and,.. transformamos las entradas en las salidas. Para el ejemplo
del multiplexor de dos canales de un bit con "enable" el esquema de puertas lógicas es el siguiente:

1 entity multi is port(


2 a,b : in bit;
3 control : in bit;
4 enable : in bit;
5 c : out bit
6 );
7 end multi;
8 architecture archmul of multi is Cabecera del programa
9 signal aux1,aux2,aux3: bit; Declaración de señales
10 begin Empieza el programa
11 aux1 <= b and (not(control)); Sentencia concurrente
12 aux2 <= a and control; Sentencia concurrente
13 aux3 <= aux1 or aux2; Sentencia concurrente
14 c <= enable and aux3; Sentencia concurrente
15 end archmul; Finaliza el programa

Recordemos que unas sentencias son concurrentes si se ejecutan todas a la vez. De este código debemos destacar estas dos
cuestiones:

● En la línea 9 se declaran las señales aux1, aux2 y aux3, que son señales intermedias que no forman parte de la entrada
ni de la salida y que las utilizamos para hacer más cómodamente la estructuración del programa. Si estas señales, el
código sería más confuso aunque igualmente válido, ya que de no usarlas deberíamos haber sustituido las líneas de la
11 a la 14 por la siguiente:

d <= enable and ( (b and (not(control)) or (a and control) );

● La explicación de las sentencias que están en la línea 11 a la 14 habla por si solas sin más que mirar el código. Con una
simple inspección comprobamos que se corresponde con el gráfico situado sobre el código.

Este tipo de estilo es solo recomendable usarlo en "estado puro" solo para diseños tan sencillos , siendo de verdadera utilidad
al usarlo como complemento del estilo algorítmico y en ocasiones del estructural. A partir de ahora la única forma en que la
veamos será esta: como complemento.

http://det.bp.ehu.es/vhdl/pagina/express/01.htm (6 of 8) [03/04/02 13:45:43]


Práctica 1: Multiplexor

Arquitectura 3: Estilo estructural usando la entidad 2


El estilo estructural es fácilmente reconocible porque la operatividad del programa no se puede leer del código ya que está
formado íntegramente por componentes y las señales que les unen a otros. Es decir, está formado por bloques o cajas negras a
los cuales metemos información y sacamos las salidas, las cuales podrán o no ir a otros bloques. Para esto debemos conocer la
operatividad de estos bloques, los cuales suelen estar en librerías. Para usar las puertas que están en el paquete gatespkg
debemos primero invocar a la librería ieee (léase "i e cubo") como está expuesto en la primera línea de la entidad que
debemos usar. Para usar el paquete (o sub-librería) gatespkg la llamaremos de la forma en que está en la segunda línea. Estas
librerías vienen incluidas en la versión 3.5 del programa WARP, de Cypress Semiconductor.

1 library ieee; Llamamos a la librería IEEE


2 use work.gatespkg.all; Llamamos a la librería que
tiene las puertas lógicas
3 entity multi is port(
4 a,b : in bit;
5 control : in bit;
6 enable : in bit;
7 c : out bit
8 );
9 end multi;
10 architecture archmul of multi is Cabecera del programa
11 signal aux0,aux1,aux2,aux3: bit; Declaración de señales
12 begin Empieza el programa
13 puerta0:inv port map(control,aux0); Sentencia concurrente
14 puerta1:and2 port map(b,aux0,aux1); Sentencia concurrente
15 puerta2:and2 port map(a,control,aux2); Sentencia concurrente
16 puerta3:or2 port map(aux1,aux2,aux3); Sentencia concurrente
17 puerta4:and2 port map(enable,aux3,c); Sentencia concurrente
18 end archmul; Finalizamos el programa
19

En este ejemplo vemos que debemos hacer para usar las librerías que vienen predefinidas con el lenguaje VHDL y más
concretamente con Warp 3.5 de Cypress Semiconductor. Para trabajar con librerías debemos tener en cuenta estos puntos:

● La librería debe estar visible para nuestro programa, es decir, debemos decirle al compilador que lo que no está
definido por defecto en VHDL debe buscarlo en esa librería. Para ello nuestras primeras líneas del programa deben

http://det.bp.ehu.es/vhdl/pagina/express/01.htm (7 of 8) [03/04/02 13:45:43]


Práctica 1: Multiplexor

hacer referencia a la librería que necesitemos. En este ejemplo, se usa la librería ieee. Dentro de la librería está el
paquete de puertas lógicas comunes, que vienen en el fichero gatespkg.vhd. Este paquete es el que debemos invocar
(ya que no vamos a usar la librería en toda sus extensión, sólo una parte). Para esto debemos conocer el paquete, que
utilidades nos puede ofrecer y cual es el orden correcto de las variables entre paréntesis. Para ello no hay más remedio
que ir llevando una lista con las librerías que vayamos conociendo y estudiar la estructura de las librerías por dentro.

● Una vez que hemos cargado la librería, la usamos de la forma expuesta en las líneas de la 13 a la 17, indicando que
parte de la librería usamos (inv, and2, or2,...) seguido de las palabras claves port map, y entre paréntesis las señales
que introducimos en las estructuras de las librerías. En estos casos, la última señal suele ser la que sacamos, aunque no
tiene porque se así. Para más información detén del cursor al lado del icono de ayuda en la línea correspondiente.

Si alguien cambiase el contenido de la librería e hiciese que el bloque and2 dejase de ser una puerta and de dos entradas,
nuestro diseño no sería correcto, ya que no haría lo que nosotros pretendemos en un principio. Por ésto, debemos estar
seguros de que función realiza una parte de una librería antes de usarla.

Al igual que el estilo de flujo de datos, este estilo es poco usado en estado puro, usándose solamente para unir diseños
complejos creados anteriormente.

http://det.bp.ehu.es/vhdl/pagina/express/01.htm (8 of 8) [03/04/02 13:45:43]


Práctica 2: Demultiplexor

Un demultiplexor es un dispositivo lógico que como su nombre indica realiza la operación inversa
al multiplexor; esto es, un convertidor de serie a paralelo. El demultiplexor recibe información por
su única entrada (de uno o mas bits) y una señal de control decide en cual de las salidas se
refleja. Si tienen una señal de "enable" esta hace que el demultiplexor esté habilitado o no

Estos demultiplexores son los inversos a la mayoría de los multiplexores de la práctica anterior.
No hemos usado los estilos de flujo de datos y estructural por no ser "rentable".

Elige en la lista una práctica para empezar, sin más que pinchar en el botón adecuado. Para volver
pulsa el botón que está al lado del título

Demultiplexor de un bit y dos canales sin


"enable"

Cómo añadir una señal de "enable"

Como aumentar los bits de cada canal

Cómo auentar el número de canales

Completar la entidad 4 con estilo algorítmico

Entidad 1: Demultiplexor de un bit y dos canales sin "enable"


Al igual que en la práctica anterior, este es el demultiplexor más sencillo que podemos imaginar, es decir con menos canales y
con menos bits. Tiene una entrada de datos de un bit y dos salidas, también de un bit. Esto hace que la señal de control tenga
la misma anchura..

http://det.bp.ehu.es/vhdl/pagina/express/02.htm (1 of 6) [03/04/02 13:46:09]


Práctica 2: Demultiplexor

entity demultiplexor is port(


entra : in bit;
En este ocasión, la entrada es entra, la señal de control es
control : in bit;
control, y la salidas son a y b. Todas son de un bit de ancho.
a,b : out bit
La última declaración no lleva punto y coma.
);
end demultiplexor;

Entidad 2: Qué hacer para que tenga señal de "enable"


Tal y como vimos en la práctica anterior, para añadir la señal de habilitación o enable, y al estar tratando de momento las
entidades, solamente hay que añadirla a la lista de entradas y salidas. Será cuando construyamos las arquitecturas cuando
deberemos modificar la operatividad del programa para que realice la función que queremos.

entity demultiplexor is port(


entra : in bit;
control : in bit;
Sólamente hemos añadido la señal de enable, que tiene ese
enable : in bit;
nombre, y todas vuelven a ser de un bit de ancho.
a,b : out bit
);
end demultiplexor;

http://det.bp.ehu.es/vhdl/pagina/express/02.htm (2 of 6) [03/04/02 13:46:09]


Práctica 2: Demultiplexor

Entidad 3: Qué hacer para que cada canal sea de mas bits
Si queremos que cada entrada (y la salida, por supuesto), tengan más anchura, es decir, más bits, no nos sirve el tipo bit, ya
que su anchura es de un bit. Para ello deberemos usar vectores de bits, que al igual que bit está predefinida en VHDL. En este
ejemplo usaremos entradas de 8 bits.

entity demultiplexor is port(


entra: in bit_vector(7 downto 0); Esta entidad se diferencia de la anterior en que en vez de ser la
control, enable :in bit; entrada y las salidas de un bit, son de ocho (de siete a cero).
a,b: out bit_vector(7 downto 0) Además hemso puesto a control y a enable en la misma línea
); por ser del mismo tipo, separados por una coma.
end demultiplexor;

http://det.bp.ehu.es/vhdl/pagina/express/02.htm (3 of 6) [03/04/02 13:46:09]


Práctica 2: Demultiplexor

Entidad 4: Qué hacer para que tenga más canales


Al igual que cuando queríamos que tuviese señal de enable, si ahora queremos más canales, a efectos de la entidad, sólo
debemos añadirlos, será luego, en la arquitectura cuando deberemos hacer que tenga la operatividad deseada..

entity demultiplexor is port(


entra: in bit_vector(7 downto 0);
Sólo hemos añadido dos salidas más, que deben ser de la
control:in bit_vector(1 downto 0);
misma anchura que la otras y que la entrada. La señal de
enable: in bit;
control debe ser más ancha porque tiene que controlar a cuatro
a,b,c,d:out bit_vector(7 downto 0)
salidas (a, b, c y d)
);
end demultiplexor;

control enable a b c d
XX H H H H H
LL L entra b c d
LH L a entra c d
HL L a b entra d
HH L a b c entra

Arquitectura 1: Estiloalgorítmico usando la entidad 4


En esta arquitectura usaremos la entidad anterior, y la hemos construido de dos formas, para diferenciar una característica
muy importante de VHDL como es la memoria implícita. Para más ayuda detén el cursor sobre los iconos azules al lado de la
línea correspondiente.

http://det.bp.ehu.es/vhdl/pagina/express/02.htm (4 of 6) [03/04/02 13:46:09]


Práctica 2: Demultiplexor

1 entity demulti is port( La entidad se llama demulti


2 entra: in bit_vector(7 downto 0); y es idémtica a la entidad
3 control: in bit_vector(1 downto 0); anterior
4 enable: in bit;
5 a,b,c,d: out bit_vector(7 downto 0)
6 );
7 end demulti;
8 architecture archdemul of demulti is Cabecera del programa
9 begin Empieza el programa
10 process (entra, control, enable) Cabecera de un proceso
11 begin Empieza el proceso
12 if enable='1' then a<="11111111"; Sentencia if
13 b<="11111111";
14 c<=(others=>'1');
15 d<=(others=>'1');
Sentencia elsif
16 elsif enable='0' then
Sentencia case
17 case control is
18 when "00" => a <= entra;
19 when "01" => b <= entra;
20 when "10" => c <= entra;
21 when others => d <= entra; Finaliza el case
22 end case; Finaliza el if y el elsif
23 end if; Finaliza el proceso
24 end process; Finaliza el programa
25 end archdemul;

Debemos ver lo siguiente en este ejercicio:

● Entre la línea 12 hay una sentencia if que de cumplirse, hace que se ejecuten cuatro instrucciones. La primera y la
segunda son iguales, es decir, hacen que a y b tomen el valor "11111111". Las otras dos hacen lo mismo con las
salidas c y d, pero de otra forma distinta, usando la palabra reservada others. La segunda forma tiene la ventaja de no
importa la anchura de la entrada o salida, por lo que si tenemos que cambiar en la entidad el número de bits por los que
está formado un puerto, no habrá que hacerlo en la arquitectura.
● Cuando se ejecuta la sentencia case, hay que tener en cuenta lo siguiente: si control es "00" está claro que a toma el
valor de entra. Si más adelante control es "01", b toma el valor de entra, pero a sigue con el valor anterior de entra
ya que no hay ninguna instrucción que modifique su valor. Esta memoria está implícita en VHDL, y debemos tener
cuidado con ella, ya que puede ayudarnos (el caso de la memorias) o crearnos problemas. Si queremos que al cambiar
el valor de entra, todas las salidas valgan "00000000" (por ejemplo), excepto la seleccionada, deberemos sustituir las
líneas de la 17 a la 22 por lo siguiente:

http://det.bp.ehu.es/vhdl/pagina/express/02.htm (5 of 6) [03/04/02 13:46:09]


Práctica 2: Demultiplexor

case control is
when "00" => a <= entra;
b <= "00000000";
c <= "00000000";
d <= "00000000";

when "01" => a <= "00000000";


b <= entra;
c <= "00000000";
d <= "00000000";

when "10" => a <= "00000000";


b <= "00000000";
c <= entra;
d <= "00000000";

when others => a <= "00000000";


b <= "00000000";
c <= "00000000";
d <= entra;
end case;

Ahora al cambiar el valor de control, sólamente una salida toma el valor de entra y las otras el valor "00000000", ya que así
lo hemos pedido explícitamente.

http://det.bp.ehu.es/vhdl/pagina/express/02.htm (6 of 6) [03/04/02 13:46:09]


Práctica 3: Codificador

Un codificador es un dispositivo lógico que recibe información por su entrada y la traduce a un


código, el cual depende del tipo de codificador. Tienen una serie de patillas de entrada de las cuales
sólo una se activa, apareciendo el número de la patilla activada a la salida en el código
correspondiente: Aiken, decimal, BCD, BCD+3,...

A partir de ahora crearemos las entidades y arquitecturas a la vez para trabajar de forma normal
prescindiremos de la columna de ayuda de la derecha.

Elige en la lista una práctica para empezar, sin más que pinchar en el botón adecuado. Para volver
pulsa el botón que está al lado del título

Codificador binario 4 a 2 sin prioridad

Codificador binario 4 a 2 sin prioridad

Codificador binario 8 a 3 con prioridad

Codificador binario 8 a 3 con prioridad

Codificador binario 16 a 4 con interrupción

Codificador binario 16 a 4 con interrupción

Entidad 1: Codificador binario de 4 a 2 bits sin prioridad


Este codificador tiene una señal de cuatro bits (numerados del cero al tres) de entrada, y una de salida de dos. Según qué bit
de los cuatro de la entrada esté seleccionado (esto es a nivel alto), saldrá a la salida un número o otro. Por ejemplo, si se
selecciona el bit cero, a la salida tendremos "00", si se selecciona el bit uno, tendremos a la salida "01", y así sucesivamente.

http://det.bp.ehu.es/vhdl/pagina/express/03.htm (1 of 7) [03/04/02 13:46:23]


Práctica 3: Codificador

entity coder is port(


dentro: in bit_vector(3 downto 0);
fuera : out bit_vector(1 downto 0); Necesitamos una entrada de 4 bits (dentro), una salida de
error : out bit dos bits (fuera), y otra de uno llamada error.
);
end coder;

Arquitectura 1: Codificador binario de 4 a 2 bits sin prioridad


Aquí es donde vamos a crear el codificador, pero será (de momento) sin prioridad, es decir, nuestro codificador nos obliga a
que sólo podemos tener seleccionado un sólo bit de entrada. Para detectar si hay más de un bit seleccionado usaremos el
puerto error definido anteriormente. Si hay error, no nos importa el valor que tenga fuera ya que lo ignoraremos.

1 architecture archicoder of coder is


2 begin
3 process (dentro)
4 begin
5 case dentro is
6 when "0001" => fuera <= "00";
7 when "0010" => fuera <= "01";
8 when "0100" => fuera <= "10";
9 when "1000" => fuera <= "11";
10 when others => error <= '1';
11 end case;
12 end process;
13 end archicoder;

http://det.bp.ehu.es/vhdl/pagina/express/03.htm (2 of 7) [03/04/02 13:46:23]


Práctica 3: Codificador

Pero debemos darnos cuenta de que este diseño es del todo incorrecto por la memoria implícita que tiene el lenguaje VHDL,
ya que en el momento en que haya un dos entradas seleccionas a la vez, la señal error permanecería para siempre a nivel
lógico alto, ya que no hay ninguna instrucción que haga que esté a nivel lógico cero. Para corregir esto deberemos escribir el
siguiente código, en el cual, cada vez que hay una entrada correcta la señal error se pone a cero.

1 architecture archicoder of coder is


2 begin
3 process (dentro)
4 begin
5 case dentro is
6 when "0001" => fuera <= "00"; error <= '0';
7 when "0010" => fuera <= "01"; error <= '0';
8 when "0100" => fuera <= "10"; error <= '0';
9 when "1000" => fuera <= "11"; error <= '0';
10 when others => error <= '1';
11 end case;
12 end process;
13 end archicoder;

Entidad 2: Codificador binario de 8 a 3 con prioridad


En esta ocasión, no necesitaremos la señal de error por ser un codificador con prioridad en el cual se especifica que hacer si
hay mas de un bit habilitado. Le dotaremos además de una señal de salida de "enable output" o de codificador habilitado, que
la llamaremos EO. Para conseguir un codificador deberemos cargar la función std_match que sirve para comparar dos
vectores si en uno de ellos hay términos "poco importa". Esta función se encuentra en el paquete std_arith, que está en la
librería ieee. Esta función, std_match, compara vectores del tipo std_logic, no bits, por lo que deberemos usar este nuevo
tipo. El tipo std_logic es el tipo más usado ya que aparte de el '0' y el '1' del tipo bit nos ofrece el "poco importa", estado de
alta impedancia,... Este será el tipo que usaremos a partir de ahora.

dentro fuera EO
HXXXXXXX HHH L
LHXXXXXX HHL L
LLHXXXXX HLH L
LLLHXXXX HLL L
LLLLHXXX LHH L
LLLLLHXX LHL L
LLLLLLHX LLH L
LLLLLLLH LLL L

http://det.bp.ehu.es/vhdl/pagina/express/03.htm (3 of 7) [03/04/02 13:46:23]


Práctica 3: Codificador

LLLLLLLL LLL H

library ieee;
use ieee.std_logic_1164.all;
La primera línea llama a la librería ieee, la cual
use work.std_arith.all;
contiene el paquete std_logic_1164, que lo
entity coder is port(
necesitamos para usar el tipo std_logic_vector, y
dentro: in std_logic_vector(7 downto 0);
dentro de este paquete está std_arith, que nos
fuera : out std_logic_vector(2 downto 0);
proporciona la función std_match. Se usan los
eo : out bit
tipos bits y std_logic.
);
end coder;

Arquitectura 2: Codificador binario de 8 a 3 con prioridad


En este caso, pueden estar dos bits de entrada a nivel alto a la vez, pero sólo se le hace caso al que hemos determinado que sea
el de más peso. En este caso el bit de más peso es dentro(7) y el de menos peso es dentro(0). La librería que hemos cargado
nos permite hacer comparaciones de elementos de los denominados "poco importa" con la función std_match. Para operar
con std_match introducimos dos vectores (de igual longitud) y nos devuelve le valor true o false según sea el resultado de la
comparación. Pulsa aquí para ver la sentencia if.

1 architecture archicoder of coder is


2 begin
3 process (dentro)
4 begin
5 if std_match(dentro,"1-------") then fuera<="111"; eo<='0'; end if;
6 if std_match(dentro,"01------") then fuera<="110"; eo<='0'; end if;
7 if std_match(dentro,"001-----") then fuera<="101"; eo<='0'; end if;
8 if std_match(dentro,"0001----") then fuera<="100"; eo<='0'; end if;
9 if std_match(dentro,"00001---") then fuera<="011"; eo<='0'; end if;
10 if std_match(dentro,"000001--") then fuera<="010"; eo<='0'; end if;
11 if std_match(dentro,"0000001-") then fuera<="001"; eo<='0'; end if;
12 if std_match(dentro,"00000001") then fuera<="000"; eo<='0'; end if;
13 if std_match(dentro,"00000000") then fuera<="000"; eo<='1'; end if;
14 end process;
15 end coder;

Hacer este ejercicio con el estilo de flujo de datos hubiera sido impensable, ya que habría que buscar las ecuaciones lógicas
para cada bit de la salida, lo cual hubiera sido, aparte de complicado, superfluo, ya que VHDL se creó para evitar el hacer esto
precisamente. Como ejemplo de ésto, a continuación se muestran la ecuación lógica para conseguir el bit fuera(0):

http://det.bp.ehu.es/vhdl/pagina/express/03.htm (4 of 7) [03/04/02 13:46:23]


Práctica 3: Codificador

A0 <=((not dentro(1)) and dentro(2) and dentro(4) and dentro(6)) OR


((not dentro(3)) and dentro(4) and dentro(6)) OR
((not dentro(5)) and dentro(6) and) OR
((not dentro(7)));

Se comprueba claramente que este modo es, aparte de complicado, poco legible para una persona que trate de analizar el
código.

Entidad 3: Codificador binario 16 a 4 con interrupción


Este ejemplo lo emplearemos para poder dar muestra de la versatilidad de VHDL para el diseño e implementación de
circuitos, que por sus características peculiares no existen en el mercado, por lo que en condiciones normales nos veríamos
obligados a diseñarlos e implementarlos haciendo uso de varios circuitos MSI que aumentarían la complejidad del "routeado"
y aumentaría la posibilidad de tener fenómenos aleatorios debido a la cantidad de conexiones.

Para este codificador las especificaciones son las siguientes: una entrada de dieciseis bits sin prioridad, activadas por cero,
una salida de cuatro bits activadas por uno (que corresponderían con tecnología CMOS) y una salida de interrupción que
tomará el valor uno cuando una sola de las entradas esté activada. En las especificaciones, se nos dice que aparte de tener una
operatividad especial y única el circuito también requerirá una disposición determinada de sus pines de entrada y de salida
de forma que seremos nosotros los que deberemos especificarle al compilador donde y como queremeos que esten
posicionados. El diseño del dispositivo lógico debe ser el siguiente:

De esta forma la entidad nos queda como sigue:

http://det.bp.ehu.es/vhdl/pagina/express/03.htm (5 of 7) [03/04/02 13:46:23]


Práctica 3: Codificador

library ieee;
use ieee.std_logic_1164.all;
entity coder is
port(
ent: in std_logic_vector(16 downto 1); Al igual que antes, para usar el tipo std_logic o
interr: out std_logic; alguno de sus derivados (como los vectores),
sal: out std_logic_vector(4 downto 1) debemos cargar la librería ieee, y, de ésta, el
); paquete std_logic_1164. La palabra all indica que
cargamos TODO el paquete, no una parte.
attribute pin_numbers of coder:entity is
Para prefijar la dispocicion de las señales en las
"ent(1):3 ent(2):2 ent(3):20 ent(4):19
patillas de la cápsula, hemos usado la sentencia
ent(5):1 ent(6):23 ent(7):22 ent(8):21
attribute pin_numbers, en la cual primero se
ent(9):10 ent(10):11 ent(11):4 ent(12):5
especifica el orden de las entradas y despues el de
ent(13):8 ent(14):9 ent(15):6 ent(16):7 "
las salidas.
&
"sal(1):14 sal(2):15 sal(3):16 sal(4):17
inerr:18 ";

end coder;

Como nota curiosa hay que señalar que el compilador que usamos, el Galaxy / Warp de Cypress no admite que las líneas de la
posición de los pines tengan varias línea, sino sólamente una para las entradas y sólamente una para las salidas. Además entre
la última asignación y las comillas debe existir un espacio.

Arquitectura 3: Codificador binario 16 a 4 con interrupción


Para crear la arquitectura de este codificador deberemos conocer con precisión cuales han de ser sus requerimientos de
funcionamiento.

1 architecture archicodifi of coder is


2 begin
3 code: process (ent)
4 begin
5 case ent is
6 when "1111111111111110" => sal <= "0000"; interr<='1';
7 when "1111111111111101" => sal <= "0001"; interr<='1';
8 when "1111111111111011" => sal <= "0010"; interr<='1';
9 when "1111111111110111" => sal <= "0011"; interr<='1';
10 when "1111111111101111" => sal <= "0100"; interr<='1';
11 when "1111111111011111" => sal <= "0101"; interr<='1';
12 when "1111111110111111" => sal <= "0110"; interr<='1';
13 when "1111111101111111" => sal <= "0111"; interr<='1';
14 when "1111111011111111" => sal <= "1000"; interr<='1';
15 when "1111110111111111" => sal <= "1001"; interr<='1';
16 when "1111101111111111" => sal <= "1010"; interr<='1';

http://det.bp.ehu.es/vhdl/pagina/express/03.htm (6 of 7) [03/04/02 13:46:23]


Práctica 3: Codificador

17 when "1111011111111111" => sal <= "1011"; interr<='1';


18 when "1110111111111111" => sal <= "1100"; interr<='1';
19 when "1101111111111111" => sal <= "1101"; interr<='1';
20 when "1011111111111111" => sal <= "1110"; interr<='1';
21 when "0111111111111111" => sal <= "1111"; interr<='1';
22 when others => sal <= "1111"; interr<='0';
23 end case;
24 end process code;
25 end archicodifi;

Este ejemplo no tiene nada de extraño a estas alturas del tutorial, ya que la sentencia case ha aparecido en muchas ocasiones.
Lo único es que hemos puesto un nombre al proceso (code). Esto es útil para cuando tenemos varios de ellos en el mismo
programa y queremos estructurar la programación para hacerla más legible. Al cerrar un proceso con nombre, hay que
especificarlo, como aparece en la línea 24.

http://det.bp.ehu.es/vhdl/pagina/express/03.htm (7 of 7) [03/04/02 13:46:23]


Práctica 4: Decodificador

Un decodificador es un circuito combinacional cuya característica fundamental es que, para cada


combinación de las entradas, sólo una de las salidas tiene un nivel lógico diferente a las demás.
Este circuito realiza la operación inversa a la de un codificador de datos y es análoga a la de un
demultiplexor, pero sin entrada de información.

Los decodificadores expuestos será una muestra práctica de la versatilidad de VHDL para la
implementación de este tipo de circuitos lógicos.

Elige en la lista una práctica para empezar, sin más que pinchar en el botón adecuado. Para volver
pulsa el botón que está al lado del título

Decodificador 3 a 8

Decodificador 3 a 8

Decodificador de BCD a 7 segmentos

Decodificador de BCD a 7 segmentos

Entidad 1: Decodificador de 3 a 8
Para el diseño de la entidad necesitamos tener una entrada de tres bits, dos entradas de control, y una salida de ocho bits que
en este caso serán activas por nivel bajo. El código no requiere mayor explicación, ya que la entidad es muy sencilla:

http://det.bp.ehu.es/vhdl/pagina/express/04.htm (1 of 5) [03/04/02 13:46:43]


Práctica 4: Decodificador

library ieee;
use ieee.std_logic_1164.all;
entity decoder is
port(
La entrada de información es entrada, las de
entrada: in std_logic_vector(2 downto 0);
control son g1 y g2 y la salida es salida.
g1, g2: in std_logic;
salida: out std_logic_vector(7 downto 0)
);
end decoder;

Arquitectura 1: Decodficador de 3 a 8
Para crear la arquitectura de este decodificador deberemos saber que operatividad exacta le vamos a proporcionar. En este
caso usaremos como modelo del circuito MSI 74138 y traducirla al lenguaje VHDL.

Entrada Salida
g1 g2
(2 a 0) (7 a 0)
X H XXX HHHHHHHH
L L XXX HHHHHHHH
H L LLL LHHHHHHH
H L LLH HLHHHHHH
H L LHL HHLHHHHH
H L LHH HHHLHHHH
H L HLL HHHHLHHH
H L HLH HHHHHLHH
H L HHL HHHHHHLH

http://det.bp.ehu.es/vhdl/pagina/express/04.htm (2 of 5) [03/04/02 13:46:43]


Práctica 4: Decodificador

H L HHH HHHHHHHL

1 architecture archidecoder of decoder is


2 begin
3 decoder: process (entrada,g1,g2)
4 begin
5 if g2='1' then salida<=(others=>'1');
6 elsif g2='0' and g1='0' then salida<=(others=>'1');
7 elsif g2='0' and g1='1' then
8
9 salida <= "01111111" when entrada="000" else
10 "10111111" when entrada="001" else
11 "11011111" when entrada="010" else
12 "11101111" when entrada="011" else
13 "11110111" when entrada="100" else
14 "11111011" when entrada="101" else
15 "11111101" when entrada="110" else
16 "11111110" when entrada="111" else
17 "11111111";
18 end archidecoder;

En este ejemplo introducimos una nueva sentencia, la sentencia when-else que viene a ser como una scesión de sentencias if
anidadas. No debemos olvidar al final la sentencia others en la que se contemplan todos los demás posibles valores qu puede
tomar la entrada, ya que aunque en un principio parecen estar contempladas, no debemos olvidar queel tipo std_logic puede
tener más valores aparte del nivel alto y el nivel bajo, como el de alta impedancia o el don't care (poco importa).

Entidad 2: Decodificador de BCD a 7 segmentos


Éste es un ejemplo muy típico de decodificador, en el cual tenemos 4 bits de entrada por los cuales nos llega un número en
BCD natural y a la salida tenemos 7 bits de salida los cuales contienen decodificado el número de la entrada para que sea
entendido por un display de 7 segmentos. La entidad correspondiente no tiene ningúna complicación, si exceptuamos que
usamos el tipo std_logic, para lo cual hay que cargar un paquete de la librería ieee.

http://det.bp.ehu.es/vhdl/pagina/express/04.htm (3 of 5) [03/04/02 13:46:43]


Práctica 4: Decodificador

library ieee;
use ieee.std_logic_1164.all;
Al igual que antes, para usar el tipo std_logic o alguno
entity convertidor is
de sus derivados (como los vectores), debemos cargar
port(
la librería ieee, y, de ésta, el paquete std_logic_1164.
bcd: in bit_vector(3 downto 0);
La palabra all indica que cargamos TODO el paquete,
led: out bit_vector(6 downto 0)
no una parte.
);
end convertidor;

Arquitectura 2: Decodificador de BCD a 7 segmentos


Para crear la arquitectura de este decodificador deberemos conocer cual es la tabla de verdad del mismo (que se puede
encontrar en cualquier data-book), y traducirla a lenguaje VHDL. Al ver la tabla y el código, comprobamos la similitud entre
ambos. La tabla la siguiente:

Entrada Salida
(BCD) (LED)
LLLL HHHHHHL
LLLH HHLLLLL
LLHL HLHHLHH
LLHH HHHLLHH
LHLL HHLLHLH
LHLH LHHLHHH
LHHL LHHHHHH
LHHH HHLLLHL
HLLL HHHHHHH
HLLH HHHLHHH
LLLL LLLLLLL

http://det.bp.ehu.es/vhdl/pagina/express/04.htm (4 of 5) [03/04/02 13:46:43]


Práctica 4: Decodificador

1 architecture archiconv of convertidor is


2 begin
3 conv: process (bcd)
4 begin
5 case bcd is
6 when "0000" => LED <= "1111110";
7 when "0001" => LED <= "1100000";
8 when "0010" => LED <= "1011011";
9 when "0011" => LED <= "1110011";
10 when "0100" => LED <= "1100101";
11 when "0101" => LED <= "0110111";
12 when "0110" => LED <= "0111111";
13 when "0111" => LED <= "1100010";
14 when "1000" => LED <= "1111111";
15 when "1001" => LED <= "1110111";
16 when others => LED <= "0000000";
17 end case;
18 end process conv;
19 end archiconv;

Este ejemplo no tiene nada de extraño a estas alturas del tutorial, ya que la sentencia case ha aparecido en muchas ocasiones.
Lo único es que hemos puesto un nombre al proceso (conv). Esto es útil para cuando tenemos varios de ellos en el mismo
programa y queremos estructurar la programación para hacerla más legible. Al cerrar un proceso con nombre, hay que
especificarlo, como aparece en la línea 18.

http://det.bp.ehu.es/vhdl/pagina/express/04.htm (5 of 5) [03/04/02 13:46:43]


Práctica 5: Comparador

Un comparador es un dispositivo lógico que recibe dos números a la entrada, A y B, y a la salida indica si el
número A es mayor, menor o igual que el número B. La longitud de las palabras de la entrada es
indiferente, pero iguales para ambos números. Pueden llevar además entradas en cascada, usadas para
utilizar varios comparadores.

Los comparadores van desde el más sencillo hasta el más complejo posible. Se puede ver claramente en
este ejemplo, las mejoras de VHDL frente a los MSI.

Elige en la lista una práctica para empezar, sin más que pinchar en el botón adecuado. Para volver pulsa el
botón que está al lado del título

Comparador de dos bits

Comparador de dos bits

Comparador de cuatro bits con entrada en cascada

Comparador de cuatro bits con entrada en cascada

Entidad 1: Comparador de dos bits


Este comparador de dos bits es realmente uno de los más sencillos de crear, ya que sólo necesitamos dos entradas para los dos
números (de dos bits cada uno) y tres salidas, que se activarán según el resultado de la activación. Como ya dijimos en la práctica del
codificador, usaremos el tipo std_logic_vector, que es el más usado y el que más juego nos da.

http://det.bp.ehu.es/vhdl/pagina/express/05.htm (1 of 5) [03/04/02 13:47:02]


Práctica 5: Comparador

library ieee;
use ieee.std_logic_1164.all;
entity compara is port(
a,b: in std_logic_vector(1 downto 0);
Necesitamos dos entradas de dos bits (a y b) y tres salidas
mayor: out std_logic;
de un bit cada uno (mayor, menor e igual).
menor: out std_logic;
igual: out std_logic
);
end compara;

Arquitectura 1: Comparador de dos bits


Para hacer la comparación de dos números con VHDL podemos usar varias formas o métodos. A continuación describimos algunos
de ellas.

Este primer método es un ejemplo de qué no debemos hacer, no porque esté incorrecto, sino porque no aprovecha la potencia de
VHDL, es complicado de entender y seguir, y por ser un programa demasiado largo para solamente indicar si el número a es mayor,
menor o igual que el b.

1 architecture archicompara of compara is


2 begin
3 process (a,b)
4 begin
5 if (a(1) = b(1)) and (a(0) = b(0)) then mayor <= '0';
6 menor <= '0';
7 igual <= '1';
8 elsif (a(1) = '1') and (b(1) = '0') then mayor <= '1';
9 menor <= '0';
10 igual <= '0';
11 elsif (a(1) = '0') and (b(1) = '1') then mayor <= '0';
12 menor <= '1';
13 igual <= '0';
14 elsif (a(0) = '1') and (b(0) = '0') then mayor <= '1';
15 menor <= '0';
16 igual <= '0';

http://det.bp.ehu.es/vhdl/pagina/express/05.htm (2 of 5) [03/04/02 13:47:02]


Práctica 5: Comparador

17 elsif (a(0) = '0') and (b(0) = '1') then mayor <= '0';
18 menor <= '1';
19 igual <= '0';
20 end if;
21 end process;
22 end archicompara;

El siguiente diseño ya es mucho más aceptable y utiliza toda la potencia de VHDL para dar un resultado preciso. Para esto utiliza la
librería ieee (que la utilizaremos siempre que haya que usar una función especial), la cual contiene al paquete std_arith que nos
permite hacer operaciones tales como comparaciones o sumas, restas, ... Ya que hay que cargar este paquete, escribiremos de nuevo
la entidad con la llamada al mismo.

library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
entity compara is port(
a,b: in std_logic_vector(1 downto 0);
mayor: out std_logic;
menor: out std_logic;
igual: out std_logic
);
end compara;

Y esta sería la arquitectura correspondiente:

1 architecture archicompara of compara is


2 begin
3 process (a,b)
4 begin
5 if a > b then mayor <= '1';
6 menor <= '0';
7 igual <= '0';
8 elsif a < b then mayor <= '0';
9 menor <= '1';
10 igual <= '0';
11 elsif a = b then mayor <= '0';
12 menor <= '0';
13 igual <= '1';
14 end if;
15 end process;
16 end archicompara;

Esta estrucuta es mucho más sencilla de crear y de comprender en un posterior análisis por una persona distinta a la que escribió el
código.

http://det.bp.ehu.es/vhdl/pagina/express/05.htm (3 of 5) [03/04/02 13:47:02]


Práctica 5: Comparador

Entidad 2: Comparador de cuatro bits con entrada en cascada


Este comparador de cuatro bits se corresponde con el 74LS85 de la familia TTL, ya que cuenta con entrada en cascada, que se usa
para comparar números de más de cuatro bits. Esto está anticuado con VHDL ya que cambiando cuatro parámetros en el programa,
un comparador de cuatro se convierte en un comparador de ocho o de 16 bits. Necesitamos dos entradas para los números de cuatro
bits cada una y tres para la cascada de entrada, y tres de salida para la cascada de salida. Usaremos otra vez el paquete std_arith por
lo que la declararemos adecuadamente en la entidad.

library ieee;
use ieee.std_logic_1164.all;
entity compara is port(
a,b: in std_logic_vector(1 downto 0);
antes_mayor: in std_logic; Necesitamos dos entradas de cuatro bits (a y b), tres
antes_menor: in std_logic; entradas de un bit para la entrada en cascada
antes_igual: in std_logic (antes_mayor, antes_menor y antes_igual) y tres salidas
mayor: out std_logic; de un bit cada uno (mayor, menor e igual).
menor: out std_logic;
igual: out std_logic
);
end compara;

Arquitectura 1: Comparador de cuatro bits con entrada en cascada


Ahora para realizar esta arquitectura tendremos que tener en cuenta que debemos dar prioridad a la entrada en cascada, ya que
proviene siempre de un módulo que compara bits de mayor peso, por lo que sólo deberemos comparar realmente cuando la entrada
en cascada antes_igual esté activada.

http://det.bp.ehu.es/vhdl/pagina/express/05.htm (4 of 5) [03/04/02 13:47:02]


Práctica 5: Comparador

1 architecture archicompara of compara is


2 begin
3 process (a,b,antes_igual,antes_mayor,antes_menor)
4 begin
5 if antes_igual = '0' then igual <= antes_igual;
6 mayor <= antes_mayor;
7 menor <= antes_menor;
8 elsif antes_igual = '1' then
9 if a > b then mayor <= '1';
10 menor <= '0';
11 igual <= '0';
12 elsif a < b then mayor <= '0';
13 menor <= '1';
14 igual <= '0';
15 elsif a = b then mayor <= '0';
16 menor <= '0';
17 igual <= '1';
18 end if;
19 end if;
20 end process;
21 end archicompara;

En esta ocasión hemos usado parte del código del ejemplo anterior para comparar cuatro bits en cascada. Esta es otra de las ventajas
de VHDL; su modularidad permite el usar otras aplicaciones ya creadas.

http://det.bp.ehu.es/vhdl/pagina/express/05.htm (5 of 5) [03/04/02 13:47:02]


Práctica 6: Cuádruple Sumador Total

Un CST es un dispositivo lógico cuya operatividad básica conciste en sumar dos numeros de cuatro bits,
recibiendo un posible carry o llevada de una etapa anterior y generando el carry propio de esta.

El CST ha sido un circuito básico en el diseño de ALU's y circuitos ariméticos en general.Poe ello VHDL nos
permite crearlos fácilmente.

Elige en la lista una práctica para empezar, sin más que pinchar en el botón adecuado. Para volver pulsa el
botón que está al lado del título

Cuádruple Sumador Total.

Cuádruple Sumador Total.

Cuádruple Sumador Total con acarreo en paralelo (flujo de


datos).
Cuádruple Sumador Total con acarreo en paralelo (flujo de
datos).

Entidad 1: Cuádruple Sumador Total.


Para el diseño de un cuadruple sumador total, nos hace falta dos entradas de cuantro bits (que serán los números a sumar), una entrada
de un bit (que sera el carry de la etapa anterior) y como salidas una de cuatro bits que sera el resultado de la suma además del carry.

http://det.bp.ehu.es/vhdl/pagina/express/06.htm (1 of 4) [03/04/02 13:47:18]


Práctica 6: Cuádruple Sumador Total

library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all; Los números a sumar son a y b, el carry de entrada es cin, el
entity sumador is port( resultado de la suma es sum y el carry siguente es cout. Para
a,b: in std_logic_vector(3 downto 0); este diseño emplearemos la librería aritmética de VHDL
cin: in std_logic; llamada std_arith, que se carga al incluir la tercera línea de
sum: out std_logic_vector(4 downto 0) este programa.
);
end sumador;

Arquitectura 1: Cuádruple Sumador Total.


Este ejemplo nos servira para poder hacer uso de una de las características más potentes de VHDL, que es la utilización de las librerias
que vienen por defecto con el paquete, que nos permitira sumar restar multiplicar, etc con sencillez. Esto hara que el cuerpo del
programa sea mucho mas legible y menos engorroso, ahorrandonos las dificultades propias de los circuuitos MSI.

1 architecture archisumador of sumador is


2 begin
3 process (a,b,cin)
4 variable aux:std_logic_vector(4 downto 0);
5 begin
6 aux:=('0' & a) + ('0' & b);
7 if cin='1' then aux:=aux+1;
8 elsif cin='0' then null;
9 end if;
10 sum<=aux;
11 end process;
12 end archisumador;

En la línea 5 se suman a y b pero como el resultado puede ser de cinco bits, la señal a la que asignaremos la suma debe ser de esta
anchura. Para que no haya problemas concatenamos a y b con un cero. Una vez sumados a y b, deberemos emplear el carry de entrada
el cual incrementará el resultado en uno si es necesario, o no tocarlo (null) en caso contrario.

http://det.bp.ehu.es/vhdl/pagina/express/06.htm (2 of 4) [03/04/02 13:47:18]


Práctica 6: Cuádruple Sumador Total

Entidad 2: Cuádruple Sumador Total con acarreo en paralelo (flujo de


datos).
Este es un inmejorable ejemplo de lo inútil de usar el estilo de flujo de datos en estado puro, es decir, sin recurrir a los demás. El
programa resultante es, aparte de extenso, totalmente incomprensible y no aprovecha ninguna de las opciones que nos ofrece VHDL
para describir cómodamente un cirucito. Este programa está realizado en mayúsculas para recalcar que VHDL no diferencia entre
mayúsculas y minúsculas.

ENTITY fcadd4 IS
PORT (CI : IN BIT;
A3,A2,A1,A0: IN BIT;
En vez de usar vectores de bits vamos a usar las entradas
B3,B2,B1,B0: IN BIT;
y salidas desglosadas en bits.
SUM3,SUM2,SUM1,SUM0 : OUT BIT;
CO: OUT BIT);
END fcadd4;

Arquitectura 2: Cuádruple Sumador Total con acarreo en paralelo (con


flujo de datos).
Esta es la arquitectura correspondiente al Cuádruple Sumador Total con acarreo en paralelo. Si empleamos circuitos MSI para la
implementación de este circuito, resulta más rápido que el 74LS85, pero si ambos los creamos con VHDL, la velocidad es la misma, ya
que el compilador interno de VHDL nos optimiza directamente el código.

http://det.bp.ehu.es/vhdl/pagina/express/06.htm (3 of 4) [03/04/02 13:47:18]


Práctica 6: Cuádruple Sumador Total

1 ARCHITECTURE archfcadd4 OF fcadd4 IS


2 signal no1_o,no2_o,no3_o,no4_o: bit;
3 signal na1_o,na2_o,na3_o,na4_o: bit;
4 BEGIN
5 no1_o <= not(a0 or b0);
6 na1_o <= not(a0 and b0);
7 no2_o <= not(a1 or b1);
8 na2_o <= not(a1 and b1);
9 no3_o <= not(a2 or b2);
10 na3_o <= not(a2 and b2);
11 no4_o <= not(a3 or b3);
12 na4_o <= not(a3 and b3);
13 co <= not( (no4_o) or
14 (na4_o and no3_o) or
15 (no2_o and na4_o and na3_o) or
16 (no1_o and na4_o and na3_o and na2_o) or
17 ((not ci) and na4_o and na3_o and na2_o and na1_o)
18 ) ;
19 sum3 <= (na4_o and (not no4_o)) xor
20 not((no3_o) or
21 (no2_o and na3_o) or
22 (no1_o and na3_o and na2_o) or
23 (na3_o and na2_o and na1_o and (not ci))
24 );
25 sum2 <= (na3_o and (not no3_o)) xor
26 not ((no2_o) or
27 (no1_o and na2_o) or
28 (na2_o and na1_o and (not ci))
29 );
30 sum1 <= (na2_o and (not no2_o)) xor
31 not ((no1_o) or
32 (na1_o and (not ci))
33 );
34 sum0 <= (na1_o and (not no1_o)) xor ci;
35 END archfcadd4;

Este tipo de descripción, por flujo de datos, nos lleva a la consecución de un código árido de leer que dificulta su comprensión y
posteriores modificaciones.

http://det.bp.ehu.es/vhdl/pagina/express/06.htm (4 of 4) [03/04/02 13:47:18]


Práctica 7: Restador

Un restador es un dispositivo lógico que recibe dos números a la entrada, A y B, y a la salida nos da su
diferencia, admitiendo una posible llevada de una operación anterior y proporcionándonos un na nueva.

Los restadores utilizan el formato de complemento a dos para representar los números negativos.

Elige en la lista una práctica para empezar, sin más que pinchar en el botón adecuado. Para volver pulsa
el botón que está al lado del título

Restador de cuatro bits

Restador de cuatro bits

Restador de cuatro bits (con LPM_PACKAGE)

Restador de cuatro bits (con LPM_PACKAGE)

Entidad 1: Restador de cuatro bits


Para crear un restador de cuatro bits, se suele usar un cuádruple sumador total y cuatro puertas xor, lo que nos obliga a tener
dos circuitos integrados. Con VHDL, reducimos esto a un único CI.

Nuestra entidad sólo necesita los números de entrada (de 4 bits) y el de salida (de 4 bits también). La llevada anterior está
deshabilitada y la de salida se debe ignorar.

http://det.bp.ehu.es/vhdl/pagina/express/07.htm (1 of 4) [03/04/02 13:47:29]


Práctica 7: Restador

1 library ieee;
2 use ieee.std_logic_1164.all;
3 use work.sumador.all;
4 entity resta is port (
5 a,b: in std_logic_vector(3 downto 0);
6 sr: in std_logic;
7 c: out std_logic_vector(3 downto 0)
8 );
9 end resta;

Arquitectura 1: Restador de 4 bits


Para sumar usaremos la librería std_arith, y para restar deberemos sumar al número a el complemento a 2 de b. El indicador
de si sumamos o restamos es la entrada sr.

1 architecture archiresta of resta is


2 signal aux : std_logic_vector(3 downto 0);
3 begin
4 process (a,b,sr,aux)
5 begin
6 if sr='0' then aux<=b;
7 elsif sr='1' then aux<=not(b);
8 end if;
9 end process;
10 c<=a+aux+("000"&sr);
11 end archiresta;

Para complementar un número a dos, deberemos invertirlo y sumarle uno. La sentencia if invierte al número b si es necesario.
Se le suma una unidad más adelante.

Para restar deberemos sumar a, la señal aux y la señal de suma/resta, para acabar de complementar a dos el número b.

http://det.bp.ehu.es/vhdl/pagina/express/07.htm (2 of 4) [03/04/02 13:47:29]


Práctica 7: Restador

Entidad 2: Restador de 4 bits (con LPM_PAKCAGE)


Para crear este restador/sumador de cuatro bits, vamos a usar la librería LPM_PACKAGE. Es una librería de módulos
parametrizables, la cual sirve para cualquier anchura de datos de entrada. Sólamente habra que declararla para poder usarla,
como se muestra en la siguiente entidad:

1 library ieee;
2 use ieee.std_logic_1164.all;
3 use work.lpmpkg.all;
4 entity resta is port (
5 a,b: in std_logic_vector(3 downto 0);
6 cin,sr: in std_logic;
7 c: out std_logic_vector(3 downto 0);
8 cout,ov: out std_logic
9 );
10 end resta;

Arquitectura 2: Restador de 4 bits


La arquitectura es muy sencilla, ya que sólamente requiere conocer cómo funciona el módulo madd_sub que es el usado para
sumar/restar. Ello se consigue usando la documentación que viene incluido con WARP2, y que se puede consultar aquí.

http://det.bp.ehu.es/vhdl/pagina/express/07.htm (3 of 4) [03/04/02 13:47:29]


Práctica 7: Restador

1 architecture archiresta of resta is


2 begin
3 restador: Madd_sub
4 generic map(4,lpm_unsigned,lpm_no_typ,speed)
5 port map(a,b,cin,sr,c,cout,ov);
6 end archiresta;

Para complementar un número a dos, deberemos invertirlo y sumarle uno. La sentencia if invierte al número b si es necesario.
Se le suma una unidad más adelante.

Para restar deberemos sumar a, la señal aux y la señal de suma/resta, para acabar de complementar a dos el número b.

http://det.bp.ehu.es/vhdl/pagina/express/07.htm (4 of 4) [03/04/02 13:47:29]


Práctica 8: Multiplicador

Un flip flop es un circuito electrónico, llamdo también simplemente biestable, que tiene dos estados
estables. El flip flop es un elemento básico de memoria que es capaz de almacenar un número binario
(bit), es decir, que permanece indefinidamente en uno de sus dos estados posibles aunque haya
desaparecido la señal de excitación que provocó su transición al estado actual.

Debido a su amplia utilización, los flip flops se han convertido en un elemento elemental dentro de los
circuitos secuenciales y con el paso del tiempo se han desarrolado varios tipos: RS, JK, D y T.

Elige en la lista una práctica para empezar, sin más que pinchar en el botón adecuado. Para volver pulsa
el botón que está al lado del título

Multiplicador de 3 bits

Multiplicador de 3 bits

Multiplicador de 3 bits (con STD_ARITH)

Multiplicador de 3 bits (con STD_ARITH)

Multiplicador de 3 bits (con LPM_PACKAGE)

Multiplicador de 3 bits (con LPM_PACKAGE)

Entidad 1: Multiplicador de 3 bits


Para conseguir un multiplicador de 3x3 bits necesitaríamos bastantes sumadores totales, lo cual nos llevaría a tener nueve
circuitos integrados si lo implementamos físicamente. El emplear VHDL en la descripción de circuitos lógicos nos facilita las
tareas de diseño y adamás nos puede disminuir el espacio de placa necesario para su implementación y las conexiones
empleadas para ello.

Para crear un multiplicador de 3x3 bits, necesitaremos una única cápsula, gracias a VHDL (y cualquier HDL). Nuestro
circuito va a tener dos entradas de tres bits cada una, y el resultado debe ser de seis bits, ya que en el caso que nos da un
mayor resultado (7x7=49), necesitamos 6 bits para completar el número.

http://det.bp.ehu.es/vhdl/pagina/express/08.htm (1 of 5) [03/04/02 13:47:55]


Práctica 8: Multiplicador

1 library ieee;
2 use ieee.std_logic_1164.all;
3 use work.std_arith.all;

4 entity multiplicador is port(


5 a,b:in std_logic_vector(2 downto 0);
6 c:out std_logic_vector(5 downto 0));
7 end multiplicador;

Arquitectura 1: Multiplicador de 3 bits


Para multiplicar, nos basaremos en el método empleado para multiplicar núeros en formato decimal, es decir, se multiplica un
número por cada uno de los dígitos del otro teniendo en cuenta el peso de cada uno. Al ser en binario, y sólo haber ceros y
unos, el multiplicar se convierte en un desplazamiento si hay un uno y en una omisión si hay un cero. Por eso el código de la
arquitectura tiene el aspecto siguiente.

1 architecture archimulti of multi is


2 signal aux1,aux2,aux3: std_logic_vector(5 downto 0);
3 begin
4 process (a,b)
5 begin
6 if b(0)='1' then aux1 <= ('0', '0', '0', a(2), a(1), a(0));
7 elsif b(0)='0' then aux1<=(others => '0'); end if ;
8 if b(1)='1' then aux2 <= ('0', '0', a(2), a(1), a(0), '0' );
9 elsif b(1)='0' then aux2<=(others => '0'); end if;
10 if b(2)='1' then aux3 <= ('0', a(2), a(1), a(0), '0', '0' );
11 elsif b(2)='0' then aux3<=(others => '0'); end if;
12 end process;
13 c <=aux1 + aux2 + aux3;
14 end archimulti;

Hay que destacar que la suma de las señales aux1, aux2 y aux3 se hace FUERA del proceso, ya que de no ser así, c no se
actualizaría correctamente y adoptaría el valor del producto anterior.

http://det.bp.ehu.es/vhdl/pagina/express/08.htm (2 of 5) [03/04/02 13:47:55]


Práctica 8: Multiplicador

Entidad 2: Multiplicador de 3 bits (con STD_ARITH)


Esta práctica es ideal para comprobar la potencia de VHDL y de sus librerías. En el ejemplo anterior, para multiplicar 3x3
bits, se necesitaba un código muy complejo y nada claro para posteriores revisiones. En cambio, si usamos la librería
std_arith para cargar el operador * que nos permitirá multiplicar dos números de cualquier longitud, debiendo ser la anchura
del resultado la suma de las anchuras de los operandos.

Para la entidad sólo necesitamos declarar los dos números a multiplicar y el producto, pero queremos que además de hacernos
el producto de a y b nos sume un número d (de la misma anchura que el producto). Por lo tanto la entidad debe ser como se
muestra en el ejemplo.

1 library ieee;
2 use ieee.std_logic_1164.all;
3 use work.std_arith.all;

4 entity multiplicador is port(


5 a,b:in std_logic_vector(2 downto 0);
6 d: in std_logic_vector(2 downto 0);
7 c:out std_logic_vector(5 downto 0));
8 end multiplicador;

Arquitectura 2: Multiplicador de 3 bits (con STD_ARITH)


El ejemplo no podía ser más sencillo, ya que en una sóla línea incluimos toda la operatividad que desábamos darle a nuestro
circuito. Esto es posible a que hemos sobrecargado la librería std_arith.

http://det.bp.ehu.es/vhdl/pagina/express/08.htm (3 of 5) [03/04/02 13:47:55]


Práctica 8: Multiplicador

1 architecture archimulti of multiplicador is


2 begin
3 c<=(a*b) + d;
4 end archimulti;

Hay que destacar que un circuito multiplicador no puede ser implementado en una PLD del tipo 22V10, sino en dispositivos
mayores como la C374i. Esto es debido a que cada uno de los elementos que componen al número c necesita mucho
propuctos y sumas lógicas, requiriendo mucho espacio de cápsula.

Entidad 3: Multiplicador de 3 bits (con LPM PACKAGE)


De nuevo vamos a usar otro de los recursos más usuales de VHDL, que es el grupo de librerías LPM Package, que nos
permite usar módulos con entradas y salidas de anchura parametrizable, es decir, una misma entidad y arquitectura sirve para
definir un multiplicador de uno, dos, tres, etc. bits sin más que cambiar una serie de parámetros.

Para usar estas librerías deberemos incluir en la declaración de librerías la línea

use work.lpmpkg.all;

Para la entidad sólo necesitamos declarar los dos números a multiplicar y el producto, pero queremos que además de hacernos
el producto de a y b nos sume un número d (de la misma anchura que el producto). Por lo tanto la entidad debe ser como se
muestra en el ejemplo.

http://det.bp.ehu.es/vhdl/pagina/express/08.htm (4 of 5) [03/04/02 13:47:55]


Práctica 8: Multiplicador

1 library ieee;
2 use ieee.std_logic_1164.all;
3 use work.lpmpkg.all;

4 entity multi is port(


5 dataA : in std_logic_vector(2 downto 0);
6 dataB : in std_logic_vector(2 downto 0);
7 sum : in std_logic_vector(5 downto 0);
8 result : out std_logic_vector(5 downto 0)
9 );
10 end multi;

Arquitectura 3: Multiplicador de 3 bits (con LPM PACKAGE)


Este ejemplo es tan sencillo como el anterior, pero su única diferencia está en que se utilizan módulos, es decir, se usa un
estilo estructural, no de comportamiento como el ejemplo anterior. La operatividad de un circuito descrito con estilo
estructural, viene definido por los módulos que se usen. Si no se indica que el módulo mmult es un multiplicador/sumador,
en una revisión posterior, no qedará nada claro que es lo que hace este circuito, mientras que si lo hemos hecho con estilo de
comportamiento o behavioral, es fácil ver qué resultado obtenemos.

1 use work.lpmpkg.all;
2 architecture archimulti of multi is
3 begin
4 mul: mmult
5 generic map (3,3,6,6)
6 port map(dataA,dataB,sum,result);
7 end archimulti;

Hay que destacar que un circuito multiplicador no puede ser implementado en una PLD del tipo 22V10, sino en dispositivos
mayores como la C374i. Esto es debido a que cada uno de los elementos que componen al número result necesita mucho
propuctos y sumas lógicas, requiriendo mucho espacio de cápsula.

Se debe aclarar que se ha hecho la introducción de datos al módulo mmult por posición.

http://det.bp.ehu.es/vhdl/pagina/express/08.htm (5 of 5) [03/04/02 13:47:55]


Práctica 10: Flip-Flops

Un flip flop es un circuito electrónico, llamdo también simplemente biestable, que tiene dos estados
estables. El flip flop es un elemento básico de memoria que es capaz de almacenar un número binario
(bit), es decir, que permanece indefinidamente en uno de sus dos estados posibles aunque haya
desaparecido la señal de excitación que provocó su transición al estado actual.
Debido a su amplia utilización, los flip flops se han convertido en un elemento fundamental dentro de los
circuitos secuenciales

Elige en la lista una práctica para empezar, sin más que pinchar en el botón adecuado. Para volver pulsa
el botón que está al lado del título

Entidad para un Flip flop RS

Arquitectura para un Flip flop RS

Entidad para un Flip flop D

Arquitectura para un Flip flop D

Entidad para un Flip flop JK

Arquitectura para un Flip flop JK

Entidad para un Flip flop T

Arquitectura para un Flip flop T

Entidad 1: Flip Flop RS


El flip flop RS es la unidad de memoria más simple, y en base a él, se diseñan flip flops más avanzados. El circuito tiene dos
entradas,Set (s) y Reset (r), y dos salidas, llamadas q y notq (que es la negada de la salida q).

clk S R q
ñ L L q
ñ L H L
ñ H L H

http://det.bp.ehu.es/vhdl/pagina/express/10.htm (1 of 7) [03/04/02 13:48:10]


Práctica 10: Flip-Flops

ñ H H X

1 library ieee;
2 use ieee.std_logic_1164.all;
3 entity flipfloRS is port ( Se define como entradas las señales s, r y la señal de
4 r,s,clk: in std_logic; reloj clk, La.senal de salida q, se define como buffer
5 q: buffer std_logic; para poder emplear su valor, y asignarselo a la señal
6 notq: out std_logic de salida notq
7 );
8 end flipfloRS;

Arquitectura 1: Flip Flop RS


Cuando la señal de entrada set (s) esta activa a nivel lógico uno, la señal de salida q pasa a valer uno, si la entrada reset U(r)
es la que esta activa a nivel lógico uno,la salida q pasa a valer uno. Nunca se puede dar el caso de que esten activas
simultaneamente las dos señales de entrada, r y s.

1
architecture archiflipfloRS of flipfloRS is
2
begin
3
process (clk)
4
begin
5
if (clk'event and clk='1') then
6 La asignación del valor de la señal notq
if (r='1')and(s='0') then q <= '0';
7 debe de hacerse a la salida del proceso, para
elsif (r='0')and(s='1')then q <='1';
8 que la señal q, ya haya actualizado su valor.
end if;
9
end if;
10
end process;
11
notq <= not q;
12
end archiflipfloRS;
13

Es reseñable de esta arquitectura la utilización de la sentencia event, que detecta cuando cambia la señal a la que esta

http://det.bp.ehu.es/vhdl/pagina/express/10.htm (2 of 7) [03/04/02 13:48:10]


Práctica 10: Flip-Flops

asociada. En el caso de esta arquitectura, es empleada para detectar un flanco de reloj (clk). La sentencia booleana clk'event
and clk='1' indicará si se ha producido un flanco de subida en la señal de reloj clk. El falnco de bajada se indica con la
sentencia clk'event and clk='0'.

Entidad 2: Flip Flop D


Este circuito tiene como entradas las señales de reloj (clk) y de información (d), siendo activa por flanco de subida. Como
salida se tiene al puerto q.

clk D q
ñ L L
ñ H H

1 library ieee;
2 use ieee.std_logic_1164.all;
3 entity flipflopd is port (
4 d,clk: in std_logic;
5 q : out std_logic
6 );
7 end flipflopd;

Esta entidad es muy sencilla ya que las entradas y la salida son de un único bit de ancho.

http://det.bp.ehu.es/vhdl/pagina/express/10.htm (3 of 7) [03/04/02 13:48:10]


Práctica 10: Flip-Flops

Arquitectura 2: Flip Flop D


El circuito opera de la siguiente forma: cuando hay un flanco de subida en el puerto de entrada clk, y la entrada d vale '1',
entonces la salida q pasa a tomar el valor de d. Cuando clk está a nivel bajo, la entrada d se encuentra desabilitada,
manteniendo q el valor anterior. Esta es la base de su operatividad como memoria.

1 architecture archiflipflopd of lipflopd is


2 begin
3 process (clk) En este diseño, solo se especifica que
4 begin pasa con la salida q cuando hay un flanco
5 if (clk'event and clk='1') then q <= d; de subida, quedando sin especificar que
6 end if; sucede con q si no se da ese flanco.
7 end process;
8 end archiflipflopd;

En la líne 5 tenemos un caso de memoria implícita ya que solamente se especifíca que se debe hacer con la señal de salida q
cuando aparece un flanco de subida en la señal de reloj, por lo que la salida q, mantendra su valor anterior mientras no se de
dicho flanco..

Entidad 3: Flip Flop JK


El flip flop JK se emplea para eliminar la incertidumbre cuando las señales de entrada J=K=1, en el caso del flip flop RS, esta
asignación de los valores de las entradas estaban prohibidas en el caso del RS,sin embargo aquí en el JK, se dará la función
basculamiento,

clk J K q
ñ L L q
ñ L H L

http://det.bp.ehu.es/vhdl/pagina/express/10.htm (4 of 7) [03/04/02 13:48:10]


Práctica 10: Flip-Flops

ñ H L H
ñ H H notq

1 library ieee;
2 use ieee.std_logic_1164.all;
3 use work.rtlpkg.all;
4 entity ffjk is
5 port (
En el flip flop JK, las entradas J K son análogas a las
6 j : in std_logic;
entradas set (s) y reset (r), respectivamente.
7 k : in std_logic;
8 clk : in std_logic;
9 q : out std_logic
10 );
11 end ffjk;

Arquitectura 3: Flip Flop JK

El flip flop JK es el más completo de ,los flip flops que se emplean. Tiene dos entradas J y K, similares a las entradas S y R
de un flip flop RS. La estrada J realiza la función set y la entrada K la función reset . La principal diferencia entre ambos es
que J y K pueden valer uno simultáneamente, a diferencia del flip flop RS, en este caso la salida cambia de estado, pasando a
valer lo contrario de lo que valía antes.Es el basculamiento

1 architecture archffjk of ffjk is


2 signal qx, dx : std_logic;
3 begin
4 dx <= (j and not(qx)) or (not(k) and qx);
5 q <= qx;
6 d1:dff port map(dx,clk,qx);
7 end archffjk;

http://det.bp.ehu.es/vhdl/pagina/express/10.htm (5 of 7) [03/04/02 13:48:10]


Práctica 10: Flip-Flops

En este ejemplo, se ha implementado un flip flop JK, basándonos en la operatividad de un flip flop d, previamente descrito en
la librería rtlpkg.Esto se hace através de la utilización de las señales qx y dx,

Entidad 4: Flip Flop T


El flip flop T, dispone de una única entrada de control t. Activado por flancos de subida, es empleado como un contador de
flancos.La salida q, mantendra su valor anterior hasta la llegada del siguente flanco.

clk T q
ñ L q
ñ H not q

1 library ieee;
2 use ieee.std_logic_1164.all;
3 entity tff is port (
En el flip flop T, las únicas entradas seran la señal de
4 t, clk : in std_logic;
reloj, clk, y la señal t, dandonos por salida q.
5 q : buffer std_logic
6 );
7 end tff;

http://det.bp.ehu.es/vhdl/pagina/express/10.htm (6 of 7) [03/04/02 13:48:10]


Práctica 10: Flip-Flops

Arquitectura 4: Flip Flop T


El flip flop T basa toda su operatividad en el valor lógico de su única entrada de control. Si en t tenemos el nivel lógico uno,
la salida q basculara, cambiando constantemente su valor según le bayan llegando los flancos de subida del reloj. Si la entrada
t esta a nivel lógico cero, el flip flop mantiene su valor anterior a modo de una memoria.

1 architecture architff of tff is


2 begin
3 process (clk) begin
4 if (clk'event and clk = '1') then
Si la entrada de control t esta a nivel
5 if (t = '1') then q <= not(q);
lógico alto el flip flop bascula, si esta a
6 else q <= q;
nivel bajo, mantiene su valor anterior.
7 end if;
8 end if;
9 end process;
10 end architff;

http://det.bp.ehu.es/vhdl/pagina/express/10.htm (7 of 7) [03/04/02 13:48:10]


Práctica 11: Contador

Un contador es un dispositivo lógico sínrono o asíncrono, en cuyas salidas tenemos un número que va
creciendo o decreciendo a intervalos regulares según lo hayamos especificado nosotros. Suelen contar
así mismo con entrada de reset y preset (a partir de que número se cuenta).

Los comparadores pueden contar tanto en binario natural, BCD, octal,... y contar de uno en uno, de
dos en dos,...

Elige en la lista una práctica para empezar, sin más que pinchar en el botón adecuado. Para volver
pulsa el botón que está al lado del título

Contador ascendente

Contador ascendente con carga

Contador ascendente con carga y reset

Contador ascendente / descendente con carga y reset

Contador BCD

Ejercicio 1: Contador ascendente


Este contador es muy simple ya que no tiene ningún tipo de control, ya que cuenta de 0 a 15 una vez tras otra, sin poder
influir sobre ello, más que en la frecuencia, al variar los pulsos de reloj. Necesitaremos por lo tanto la entrada de reloj y la
salida (de cuatro bits).

library ieee; Declaración de librerías para usar el tipo


use ieee.std_logic_1164.all; std_logic y para poder usar el signo + para
use work.std_arith.all; sumar

http://det.bp.ehu.es/vhdl/pagina/express/11.htm (1 of 6) [03/04/02 13:48:24]


Práctica 11: Contador

entity contador is port(


clk: in std_logic;
Declaración de la entrada de reloj (clk), y de
conta: buffer std_logic_vector(3 downto 0) la salida conta.
);
end contador;

architecture archicontador of contador is


begin
process (clk)
begin
En el flanco de subida del reloj, se ejecuta lo
if (clk'event and clk= '1') then que sigue al then: sumar 1 a la señal conta.
conta <= conta + 1;
end if;
end process;
end archicontador;

Lo único a destacar de este ejercicio es que la salida debe ser del tipo buffer, no del tipo out, ya que debemos conocer la
salida que tenemos, para poder sumarla uno. Este ejemplo no merece más comentarios, ya que iremos añadiendo operatividad
a medida que avancemos en esta práctica.

Ejercicio 2: Contador ascendente con carga


Este contador se diferencia del anterior en que le podremos indicar a partir de qué número queremos que empiece a contar,
por lo que deberemos añadirle una entrada para el número en cuestión y otra par indicarle que queremos que lo use.

library ieee; Declaración de librerías para usar el tipo


use ieee.std_logic_1164.all; std_logic y para poder usar el signo + para
use work.std_arith.all; sumar

entity contador is port(


clk, load:in std_logic; Declaración de la entrada de reloj (clk), y de la
data: in std_logic_vector(3 downto 0); salida conta. Ahora le añadimos la entrada
conta:buffer std_logic_vector(3 downto 0) load que indica que si queremos que empiece a
); contar a partir del número data
end contador;

http://det.bp.ehu.es/vhdl/pagina/express/11.htm (2 of 6) [03/04/02 13:48:24]


Práctica 11: Contador

architecture archicontador of contador is


begin
process (clk)
begin
if (clk'event and clk= '1') then Ahora, si hay un flanco de subida en clk,
if load = '1' then primero se comprueba si se pide contar a partir
conta <= data; cierto número (si load está habilitada), y si es
else así, el contador se inicializa con el valor de
conta <= conta + 1; data. Si no lo es, se le suma 1 a la salida
end if;
end if;
end process;
end archicontador;

Lo único a destacar de este ejercicio es que al haber dos sentencias if deberemos cerrar ambas. VHDL, como todos los
lenguajes de programación, cierra primero la última sentencia if en abrirse.

Ejercicio 3: Contador ascendente con carga y reset


A este contador le hemos añadido ahora una señal de reset (asíncrono), que hará que el contador se ponga a cero mientras
dure este pulso. Una vez acabado la inicialización vuelve a cmprobar si se le pide que cuente a partir de load, o si cuenta
normalmente.

library ieee; Declaración de librerías para usar el tipo


use ieee.std_logic_1164.all; std_logic y para poder usar el signo + para
use work.std_arith.all; sumar

entity contador is port(


clk, load, reset:in std_logic;
Declaración de la entrada de reloj (clk) y de la
data: in std_logic_vector(3 downto 0);
carga (load y data). Ahora le añadimos la
conta:buffer std_logic_vector(3 downto 0) señal de reset. Conta es la salida.
);
end contador;

http://det.bp.ehu.es/vhdl/pagina/express/11.htm (3 of 6) [03/04/02 13:48:24]


Práctica 11: Contador

architecture archicontador of contador is


begin
process (clk,reset)
begin Ahora, si hay un flanco de subida en clk, o hay
if reset = '1' then un cambio en la señal reset, primero se
conta <= "0000"; comprueba si esta última ha sido habilitada, lo
elsif (clk'event and clk= '1') then cual hace que conta se ponga a "0000". Si lo
que ha cambiado ha sido la señal clk (reloj), se
if load = '1' then siguen los mismos pasos que antes: se verifica
conta <= data; si se pide contar a partir cierto número (si load
else está habilitada), y si es así, el contador se
conta <= conta + 1; inicializa con el valor de data. Si no lo es, se le
end if; suma 1 a la salida
end if;
end process;
end archicontador;

Si el contador llega a "1111", y le sumamos uno, la salida que obtengamos será "0000", ya que automáticamente VHDL
realiza la operación de despreciar el overflow que se daría, ya que el resultado debiera de ser de cinco bits y no de cuatro, tal y
como hemos declarado la salida.

Ejercicio 4: Contador ascendente/descendente con carga y reset


Ahora deberemos modificar el código del contador anterior par que según le indiquemos con una señal nueva, llamada
arriba, cuente hacia arriba como hacia abajo, según le digamos. Esta señal basta con que sea de un solo bit.

library ieee; Declaración de librerías para usar el tipo


use ieee.std_logic_1164.all; std_logic y para poder usar el signo + para
use work.std_arith.all; sumar

entity contador is port(


clk, load, reset,arriba:in std_logic; Declaración de la entrada de reloj (clk), de la
data: in std_logic_vector(3 downto 0); carga (load y data), la señal de reset y
conta:buffer std_logic_vector(3 downto 0) además la que indica si cuenta hacia arriba
); como hacia abajo. Conta es la salida.
end contador;

http://det.bp.ehu.es/vhdl/pagina/express/11.htm (4 of 6) [03/04/02 13:48:24]


Práctica 11: Contador

architecture archicontador of contador is


begin
process (clk,reset)
begin Ahora, si hay un flanco de subida en clk, o hay
if reset = '1' then un cambio en la señal reset, primero se
conta <= "0000"; comprueba si esta última ha sido habilitada, lo
elsif (clk'event and clk= '1') then cual hace que conta se ponga a "0000". Si lo
que ha cambiado ha sido la señal clk (reloj), se
if load = '1' then
verifica si se pide contar a partir cierto número
conta <= data; (si load está habilitada), y si es así, el contador
elsif arriba = '1' then se inicializa con el valor de data. Si no lo es, se
conta <= conta + 1; analiza si se le pide contar hacia arriba o hacia
else conta <= conta - 1; abajo, sumándole 1 a la salida o restándoselo,
end if; respectivamente.
end if;
end process;
end archicontador;

Deberemos tener en cuidado en este caso, ante la cantidad de if's y de elsif, dentro de cuál de ellos estamos, a la hora de
cerrarlos o de asignar cambios a señales, ya que el resultado puede ser distinto al que queríamos.

Ejercicio 5: Contador BCD


Nuestro objetivo ahora es modificar el contador anterior, para conseguir que cuente de 0 a 9, es decir, que cuente en BCD.

library ieee; Declaración de librerías para usar el tipo


use ieee.std_logic_1164.all; std_logic y para poder usar el signo + para
use work.std_arith.all; sumar

entity contador is port(


clk, load, reset,arriba:in std_logic; Declaración de la entrada de reloj (clk), de la
data: in std_logic_vector(3 downto 0); carga (load y data), la señal de reset y
conta:buffer std_logic_vector(3 downto 0) además la que indica si cuenta hacia arriba
); como hacia abajo. Conta es la salida.
end contador;

http://det.bp.ehu.es/vhdl/pagina/express/11.htm (5 of 6) [03/04/02 13:48:24]


Práctica 11: Contador

architecture archicontador of contador is


begin
process (clk,reset)
begin
if reset = '1' then
Ahora, si hay un flanco de subida en clk, o hay
conta <= "0000"; un cambio en la señal reset, primero se
elsif (clk'event and clk= '1') then comprueba si esta última ha sido habilitada, lo
if load = '1' then cual hace que conta se ponga a "0000". Si lo
conta <= data; que ha cambiado ha sido la señal clk (reloj), se
elsif arriba = '1' then verifica si se pide contar a partir cierto número
if conta = "1001" then (si load está habilitada), y si es así, el contador
se inicializa con el valor de data. Si no lo es, se
conta <= "0000"; analiza si se le pide contar hacia arriba o hacia
else conta <= conta + 1; abajo. Antes de sumarle uno, comprueba si
end if; hemos llegado al límite (9), y si lo hemos
else hecho, se pone conta a "0000", si no es así, le
if conta = "0000" then suma uno. Realiza la misma operación pero
conta <= "1001"; comprobando si hemos llegado al otro límite
(0), y si es así, pone conta a "1001". Si no lo
else conta <= conta - 1; es se resta uno a la salida.
end if;
end if;
end if;
end process;
end archicontador;

Ahora deberemos extremar el cuidado con los if's que hay, por lo que deberemos organizar el testo de tal forma que no nos
lleve a error. Ante tantos if's, deberemos plantearnos si es mejor utilizar la sentencia case.

http://det.bp.ehu.es/vhdl/pagina/express/11.htm (6 of 6) [03/04/02 13:48:24]


Práctica 12: Secuenciador

En los circuitos secuenciales, la salida, a diferencia de los combinacionales, se debe tanto a las
entradas actuales como a los valores anteriores, de esta forma, las salidas toman distintos niveles
lógicos para las mismas entradas de contro. Emplearemos el principio de los circuitos secuensiales para
implementar un circuito cuyas salidas variaran en función del tiempo

Nuestro secuenciador utiliza un contador y un decodificador 2/4 previamente definidos como


componentes en una librería personalizada, invocada desde el fichero de descripción.

Elige en la lista una práctica para empezar, sin más que pinchar en el botón adecuado. Para volver
pulsa el botón que está al lado del título

Decodificador 2/4

Decodificador 2/4

Contador

Contador

Secuenciador

Secuenciador

Entidad 1: Decodificador 2/4


El decodificador 2/4 tiene dos señales de control, que en nuestra entidad, viene dada por la señal de selección . Como salida
un vector de longitud cuatro y dos entradas de habilitación (enable).

http://det.bp.ehu.es/vhdl/pagina/express/12.htm (1 of 7) [03/04/02 13:48:57]


Práctica 12: Secuenciador

1 library ieee;
2 use ieee.std_logic_1164.all;
3 use work.uno.all; Es necesario poner en la cabecera del
4 entity decoder is port ( código, la llamada a la librería "uno", que
5 seleccion:in std_logic_vector(1 downto 0); es donde guardaremos a este
6 enable1,enable2: in bit; decodificador como un componente.
7 salida: out std_logic_vector(3 downto 0));
8 end decoder;

Arquitectura1: Decodificador 2/4


El decodificador basa su operatividad en dos señales de control "seleccion", con las que seleccionamos la salida que queremos
que sea activa a nivel alto. Segun sea el valor que tome dicha señal de "seleccion", se eligira una salida u otra.

1 architecture archidecoder of decoder is


2 begin
3 decodificador:process(seleccion,enable1,enable2)
4 begin
5 if enable2='1' then salida<=(others=>'0');
6 elsif enable2='0' and enable1='0' then salida<=(others El decodificador es activado
7 => '0'); atravez de sus dos señales de
8 elsif(enable1='1') then enable. Enable1 va conectada a
9 case seleccion is la señal de reloj, para que el
10 when "00" => salida <= "0001"; funcionamiento del codificador
11 when "01" => salida <= "0010"; se sincronice a dicha señal.
12 when "10" => salida <= "0100"; Enable2, hará las veces de un
13 when "11" => salida <= "1000"; abilitador normal.
14 when others => salida <="1111";
15 end case;

http://det.bp.ehu.es/vhdl/pagina/express/12.htm (2 of 7) [03/04/02 13:48:57]


Práctica 12: Secuenciador

16 en if;
17 end process decodificador;
18 end archidecoder;

El habilitador de entrada de este decodificador, enable1 y enable2, le confiere a este diseño la particularidad de poder
controlar tanto su estado de funcionamiento así como sincronizarlo con la entrada de reloj, para que funcione a la vez que el
contador al que estará unido.

Entidad 2: Contador
Este circuito tiene como entradas las señales dereloj (clk) y de información (d), siendo activa por flanco de subida. Como
salida se tiene al puerto q.

1 library ieee;
2 use ieeee.std_logic_1164.all;
3 use work.std_arith.all;
4 use work.uno.all;
5 entity count is port (
6 clk,reset:in bit;
7 conya :buffer std_logic_vector(1 downto 0));
8 end count;

Esta entidad es muy sencilla ya que las entradas y la salida son de un único bit de ancho. La entrada reset, se emplea paea
habilitar o sesabilitar al reloj.

http://det.bp.ehu.es/vhdl/pagina/express/12.htm (3 of 7) [03/04/02 13:48:57]


Práctica 12: Secuenciador

Arquitectura 2: Contador
Un contador es un circuito secuencial que repite su estado cada cierto número de pulsos de reloj. El número de estados por los
que pasa antes de volver al mismo estado se llama "modulo".

1 architecture archicount of count is


2 begin
3 contador :process (clk,reset)
4 begin
5 if (reset='1')
6 then conta <= (others => '0') ;
7 elsif clk'event and clk='1'
8 then conta <= conta + 1;
9 end if;
10 end process contador;
11 end archicount;

Estas dos entidades, tanto el contador como el decodificador, estarán incluidas dentro de un paquete o Package para poder
hacer uso de ellos através de la utilización de dichos elementos como componentes. Ambos circuitos serán guardados dentro
de la librería personalizada "uno".A continuación se lista el código de este paquete

A continuación se edita el paquete (package) "uno" donde se guarda como componentes tanto el contador como el
decodificador. Estos elementos serán posteriormente llamados para formar parte del diseño completo del secuenciador que ha
sido diseñado dentro de "total".

1 library ieee;
2 use ieee.std_logic_1164.all;
3 use work.std_arith.all;
4
5 package uno is
6 component
7 count port (
8 clk,reset:in bit;
9 conta :buffer std_logic_vector(1 downto 0));
10 end component;
11 component
12 decoder port (
13 seleccion :in std_logic_vector(1 downto 0);

http://det.bp.ehu.es/vhdl/pagina/express/12.htm (4 of 7) [03/04/02 13:48:57]


Práctica 12: Secuenciador

14 enable1,enable2:in bit;
15 salida :out std_logic_vector(3 downto 0));
16 end component;
17 end package;
18
19 library ieee;
20 use ieee.std_logic_1164.all;
21 use work.std_arith.all;
22 use work.uno.all;
23 entity count is port (
24 clk,reset:in bit;
25 conta:buffer std_logic_vector(1 downto 0));
26 end count;
27
28 architecture archicount of count is
29 begin
30 contador :process (clk,reset)
31 begin
32 if (reset='1') then conta <= (others => '0') ;
33 elsif clk'event and clk='1' then conta <= conta + 1;
34 end if;
35 end process contador;
36 end archicount;
37
38 --descripcion del decodificador 3/8 (74ls138)
39 library ieee;
40 use ieee.std_logic_1164.all;
41 use work.uno.all;
42 entity decoder is port (
43 seleccion :in std_logic_vector(1 downto 0);
44 enable1,enable2:in bit;
45 salida :out std_logic_vector(3 downto 0));
46 end decoder;
47
48 architecture archidecoder of decoder is
49 begin
50 decodificador:process(seleccion,enable1,enable2)
51 begin
52 if enable2='1' then salida<=(others=>'0');
53 elsif enable2='0' and enable1='0' then salida<=(others => '0');
54 elsif(enable1='1') then
55 case seleccion is
56 when "00" => salida <= "0001";
57 when "01" => salida <= "0010";
58 when "10" => salida <= "0100";
59 when "11" => salida <= "1000";
60 when others => salida <="1111";
61 end case;
62 end if;
63 end process decodificador;
64 end archidecoder;

http://det.bp.ehu.es/vhdl/pagina/express/12.htm (5 of 7) [03/04/02 13:48:57]


Práctica 12: Secuenciador

La especificación de un package consta de dos partes claramente diferenciadas, la primera es la cabecera donde se declara
como componente (component), los elementos que van a estar contenidos en dicha librería. A continuación aparece la
declaración de las entidades y arquitecturas de cada uno de los componentes de forma similar a como se declara un circuito
cualquiera, la única aclaración a tener en cuenta sera que habra que incluir necesariamente la sentencia use work.uno.all;
donde se especifíca el nombre de la librería en la que estamos.

Entidad 3: Secuencaidor
En esta practica se parte de la gráfica siguente. Las especificaciones del diseño nos pide que creemos un circuito que se ajuste
al comportamiento de la siguente gráfica.

Tras el análisis de los requerimientos, se diseña el siguente circuito donde se implementara, previamente, los componentes
count y deco, que seran guardados en el package uno. El circuito total se implementara haciendo las llamadas pertinentes a
traves de sentencias estructurales port map a dicho package.

http://det.bp.ehu.es/vhdl/pagina/express/12.htm (6 of 7) [03/04/02 13:48:57]


Práctica 12: Secuenciador

1 library ieee;
2 use ieee.std_logic_1164.all;
3 use work.uno.all;
4 entity total is port(
5 clk,reset:in bit;
6 salida:out std_logic_vector(3 downto 0));
7 end total;

Arquitectura 3: Secuenciador
En esta parte se unen el contador y el decodificador antes descrito, para conseguir el comportamiento del secuenciador
previamente diseñado. Para ello se hace uso de la señal intermedio, que nos sirve para pasar las señales propias del count y
llevarlas a la entrada del decoder.

1 architecture architotal of total is


2 signal intermedio:std_logic_vector(1 downto 0);
3 begin
4 bloque1:count port map(clk,reset,intermedio);
5 bloque2:decoder port map(intermedio,clk,reset,salida);
6 end architotal;

http://det.bp.ehu.es/vhdl/pagina/express/12.htm (7 of 7) [03/04/02 13:48:57]


INDUSTRI INGENIARITZA TEKNIKO ESKOLA

ELEKTRONIKA ETA TELEKOMUNIKAZIO SAILA


INDUSTRI INGENIARITZA TEKNIKORAKO ESKOLA

DEPARTAMENTO DE ELECTRONICA Y
TELECOMUNICACIONES
ESCUELA TECNICA DE INGENIERIA INDUSTRIAL

Castellano Euskara

Euskal-Herriko Unibertsitatea
Elektronika eta Telekomunikazio Saila
La Casilla Plaza, 3, Bilbao (Bizkaia)
Tlf: 94 601 43 04
CiberStats.
Pincha para
estadisticas.

http://det.bp.ehu.es/ [03/04/02 13:50:15]


Departamento de Electrónica y Telecomunicaciones. EUITI Bilbao

Profesores

Proyectos Fin de
Carrera

Asignaturas
Virtuales DEPARTAMENTO DE
ELECTRONICA Y
Asignaturas
Impartidas
TELECOMUNICACIONES

Curriculums de
alumnos

Examenes
ESPECIALIDAD

Programas INGENIERIA TECNICA


ELECTRONICA
Inicio

[Profesores] [Proyectos Fin de Carrera]


[Asignaturas Virtuales]
[Asignaturas Impartidas] [Curriculums de alumnos]
[Inicio]

http://det.bp.ehu.es/castellano/marco.htm [03/04/02 13:50:27]


Elektronika eta Telekomunikazio Saila. IITUE Bilbao

Irakasleak

Ikasketa
bukaerako
Proiektuak

Irakasgai ELEKTRONIKA ETA


Birtualak
TELEKOMUNIKAZIO
Elektronika
SAILA
Irakasgaiak

Ikasleen
Curriculum-ak ESPEZIALITATEA

Azterketak INGENIARITZA
TEKNIKO
Hasiera
ELEKTRONIKOA

[Irakasleak] [Karrera Bukaerako Proiektuak]


[Irakasgai Birtualak]
[Elektronika Irakasgaiak] [Ikasleen Curriculum-ak]
[Hasiera]

http://det.bp.ehu.es/Euskera/marco.htm [03/04/02 13:50:46]


Accesos directos

Links a páginas sobre VHDL


VHDL International (VI):

● VHDL International Users Forum (VIUF)


● VIUF Local Chapter User Groups (LC's)
● Marketing Advisory Committee (mac)
● Technical Advisory Committee (tac)
● Design Constraints Working Group (dcwg)
● Misc submissions (misc)
● VHDL Users' Group (VUG) RBBS-PC Archive (1988-1991)

EIA Electronic Information Group (EIG)

● Advanced Intermediate Representation with Extensibility (AIRE)


● Die Information Exchange (DIE): EIA xxx
● I/O Buffer Information Specification (IBIS): ANSI/EIA-656 (see also IBIS)
● Microwave Design Automation Standards (microwave)
● Rule Augmented Interconnect Layout (RAIL)
● VHDL Commercial Component Model Specification: EIA 567
● Computer Aided Software Engineering (CASE)
● Electronic Data Interchange Format (EDIF)

Other VHDL (Tools, Models, etc.):

● Free VHDL models from Free Model Foundation (fmf)


● VHDL Validation Suite Effort (validation)
● comp.lang.vhdl FAQ and archive (USENET News)
● Misc. submissions (from VUG/VIUF meetings, etc.)
● VHDL models, info, etc. from RASSP E&F
● Free VHDL SAVANT tools from MTL Systems
● Free VHDL tools from Univ of Dortmund EE Dept. (English text)

Other EDA / CADGroups:

● ACM Special Interest Group on Design Automation (SIGDA)


● 3D TCAD Model Interoperability (tcad3d)
● Bay Area MEMS Journal Club (bamjc)
● EDA Companies (EDAC)
● EDA Standards Industry Council (EDA Stds IC)

http://det.bp.ehu.es/vhdl/pagina/links1.htm (1 of 3) [03/04/02 13:50:51]


Accesos directos

● Glossary of Standards at CFI (now SI2)


● IEC TC93- USA TAG Activity
● IEEE Design Automation Technical Committee (DATC)
● ISO TC184: Design Automation:
❍ Std 10303 - Standard Exchange of Product Data STEP (ISO TC184/SC4/WG4)

❍ Std 13584 - Part Libraries STEP Application (ISO TC184/SC4/WG2)

● Int. Society for Hybrid Microcircuits (ISHM)


● The Institute for Interconnecting and Packaging Electronic Circuits (IPC)
● NCSU CAD Benchmarking Library
● Open Verilog International (OVI)

IEEE Design Automation Standards Committee (DASC):

● Chip Hierarchical Design System Technical Data (chdstd) Working Group


● Circuit Delay and Power Calculation (dpc) System Study Group
● High Performance HDL Simulation (hpm-sim) Working Group
● HW/SW Co-design (codesign) Study Group
● Object Oriented VHDL (oovhdl) Study Group
● Open Modeling Forum (omf) Working Group
● System Design & Description Language (sddl) Study Group
● Standard Delay Format (sdf) Study Group (PAR 1497)
● Timing (VHDL Initiative Towards ASIC Libraries: vital) Working Group
● Verilog Working Group (PAR 1364)

● Verilog Synthesis Subset Working Group (PAR 1364.1)


● VHDL Analog Extensions (analog) Working Group (PAR 1076.1)
● VHDL Analysis and Standards Group (VASG) (PAR 1076) Issues Screening and Analysis
Committee (isac)
● VHDL Library - "library ieee;" Working Group
● VHDL Library - Utility (libutil) Working Group (PAR 1076.5)
● VHDL Math Package (math) Working Group (PAR 1076.4)
● VHDL Microwave Extensions (vhdl-mw) Study Group
● VHDL Parallel Simulation (parallel) Working Group
● VHDL Programming Language Interface (vhdlpli) Task Force
● VHDL Shared Variables Working Group (svwg) (PAR 1076; mod a)
● VHDL Synthesis Interoperability (siwg) Working Group (PAR 1076.6)
● VHDL Synthesis Package (vhdlsynth) Working Group (PAR 1076.3)
● VHDL System and Interface based Design (sid) Study Group
● VHDL Test (vhdl_test) Working Group
● Waveform and Vector Exchange [Standard] (WAVES) (Std 1029.1-1991) (joint with
Standards Coordinating Committee 20)

http://det.bp.ehu.es/vhdl/pagina/links1.htm (2 of 3) [03/04/02 13:50:51]


Accesos directos

● MMIC Hardware Description Language (MHDL) (IEEE Standards Coordinating Committee


30)

http://det.bp.ehu.es/vhdl/pagina/links1.htm (3 of 3) [03/04/02 13:50:51]


Página de simulación

Simulación
En esta parte del tutorial, se ofrecen los ficheros fuentes (.vhd) de los diseños
presentados en las prácticas expuestas. Para ello deberemos tener el programa
WARP2 , versión 4.1 o superior o cualquier compilador de VHDL ya que este es un
lenguaje estandar.

Multiplexor
Multiplexor de 3 canales, 4 bits y con enable.

Pulsa aquí para ver el código fuente

http://det.bp.ehu.es/vhdl/pagina/express/simula.htm (1 of 14) [03/04/02 13:52:48]


Página de simulación

Multiplexor de dos canales y un bit con enable, estilo flujo de datos.

Pulsa aquí para ver el código fuente

Multiplexor de dos canales y un bit con enable, estilo estrucural

Pulsa aquí para ver el código fuente

Demultiplexor
http://det.bp.ehu.es/vhdl/pagina/express/simula.htm (2 of 14) [03/04/02 13:52:48]
Página de simulación

Demultiplexor de 3 canales y dos bits con enable

Pulsa aquí para ver el código fuente

Codificador
Codificador binario 4 a 2 sin prioridad, diseño incorrecto.

Pulsa aquí para ver el código fuente

http://det.bp.ehu.es/vhdl/pagina/express/simula.htm (3 of 14) [03/04/02 13:52:48]


Página de simulación

Codificador binario 4 a 2 sin prioridad, diseño correcto.

Pulsa aquí para ver el código fuente

Codificador binario 8 a 3 con prioridad.

dentro fuera EO
HXXXXXXX HHH L
LHXXXXXX HHL L
LLHXXXXX HLH L
LLLHXXXX HLL L
LLLLHXXX LHH L
LLLLLHXX LHL L
LLLLLLHX LLH L
LLLLLLLH LLL L
LLLLLLLL LLL H

Pulsa aquí para ver el código fuente

Codificador binario 16 a 4 con interrupción.

http://det.bp.ehu.es/vhdl/pagina/express/simula.htm (4 of 14) [03/04/02 13:52:48]


Página de simulación

Pulsa aquí para ver el código fuente

Decodificador
Decodificador 3 a 8

Entrada Salida
g1 g2
(2 a 0) (7 a 0)
X H XXX HHHHHHHH
L L XXX HHHHHHHH
H L LLL LHHHHHHH
H L LLH HLHHHHHH
H L LHL HHLHHHHH
H L LHH HHHLHHHH
H L HLL HHHHLHHH
H L HLH HHHHHLHH
H L HHL HHHHHHLH
H L HHH HHHHHHHL

http://det.bp.ehu.es/vhdl/pagina/express/simula.htm (5 of 14) [03/04/02 13:52:48]


Página de simulación

Pulsa aquí para ver el código fuente

Decodificador 74154************************

Pulsa aquí para ver el código fuente

Decodificador de BCD a siete segmentos

Entrada Salida
(BCD) (LED)
LLLL HHHHHHL
LLLH HHLLLLL
LLHL HLHHLHH
LLHH HHHLLHH
LHLL HHLLHLH
LHLH LHHLHHH
LHHL LHHHHHH
LHHH HHLLLHL
HLLL HHHHHHH
HLLH HHHLHHH
LLLL LLLLLLL

Pulsa aquí para ver el código fuente

Comparador

http://det.bp.ehu.es/vhdl/pagina/express/simula.htm (6 of 14) [03/04/02 13:52:48]


Página de simulación

Comparador de dos bits, diseño no recomendado.

Pulsa aquí para ver el código fuente

Comparador de dos bits, diseño recomendado.

Pulsa aquí para ver el código fuente

Comparador de cuatro bits con entrada en cascada.

Pulsa aquí para ver el código fuente

Cuádruple Sumador Total


Cuádruple sumador total

Pulsa aquí para ver el código fuente

http://det.bp.ehu.es/vhdl/pagina/express/simula.htm (7 of 14) [03/04/02 13:52:48]


Página de simulación

Comparador de cuatro bits con entrada en cascada.

Pulsa aquí para ver el código fuente

Restador
Sólo hay que ejecutar el programa de simulación y pedirle que abra el
fichero deseado

Multiplicador
Sólo hay que ejecutar el programa de simulación y pedirle que abra el fichero
deseado

ALU
Sólo hay que ejecutar el programa de simulación y pedirle que abra el
fichero deseado

http://det.bp.ehu.es/vhdl/pagina/express/simula.htm (8 of 14) [03/04/02 13:52:48]


Página de simulación

Flip Flop
Flip Flop RS

Pulsa aquí para ver el código fuente

Flip Flop JK

Pulsa aquí para ver el código fuente

Flip Flop D

http://det.bp.ehu.es/vhdl/pagina/express/simula.htm (9 of 14) [03/04/02 13:52:48]


Página de simulación

Pulsa aquí para ver el código fuente

Flip Flop T

Pulsa aquí para ver el código fuente

Contador
Contador ascendente

Pulsa aquí para ver el código fuente

http://det.bp.ehu.es/vhdl/pagina/express/simula.htm (10 of 14) [03/04/02 13:52:48]


Página de simulación

Contador ascendente con carga

Pulsa aquí para ver el código fuente

Contador ascendente con carga y reset

Pulsa aquí para ver el código fuente

Contador ascendente/descendente con carga y reset

Pulsa aquí para ver el código fuente

Contador BCD ascendente/escendente con carga y reset

Pulsa aquí para ver el código fuente

Secuenciador

http://det.bp.ehu.es/vhdl/pagina/express/simula.htm (11 of 14) [03/04/02 13:52:48]


Página de simulación

Decodificador de 2 a 4

Pulsa aquí para ver el código fuente

Contador

Pulsa aquí para ver el código fuente

Secuenciador

http://det.bp.ehu.es/vhdl/pagina/express/simula.htm (12 of 14) [03/04/02 13:52:48]


Página de simulación

Pulsa aquí para ver el código fuente

Autómatas
Sólo hay que ejecutar el programa de simulación y pedirle que abra el
fichero deseado

http://det.bp.ehu.es/vhdl/pagina/express/simula.htm (13 of 14) [03/04/02 13:52:48]


Página de simulación

http://det.bp.ehu.es/vhdl/pagina/express/simula.htm (14 of 14) [03/04/02 13:52:48]

Das könnte Ihnen auch gefallen