You are on page 1of 162

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 Electrnica Digital y tener nociones de
cualquier lenguaje de programacin ya sea Pascal, C, Basic,...
El lenguaje de descripcin hardware VHDL (Very high speed Hardware
Description Logic) es un lenguaje orientado a la descripcin de hardware pero
con muchos elementos heredados de otros lenguajes como C o Pascal. Una
vez realizado un programa en VHDL (con extensin VHD) y haberlo compilado
con xito, tendremos un fichero con el mismo nombre y extensin JED, con el
cual podremos grabar una PLD (Dispositivo Lgico 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 seales son visibles o accesibles desde el exterior, es decir los
puertos o ports del dispositivo. Es describir las patillas del circuito que sern
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 ms 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 realizarn sobre los datos que
entren por los 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 introduccin deberemos tener en cuenta una serie de detalles
ms de ste lenguaje:
VHDL no distingue las maysculas de las minsculas, 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 smbolos como &, %, $, #, !, etc. Su longitud no est limitada, no pueden
acabar con un carcter de subrayado o tener dos subraryados seguidos.
Para representar un nmero de una sola cifra, deberemos situarlo entre
apstrofes; as: '1'
Para representar un nmero de mas de una cifra, lo representaremos as:
"10011"
Es muy probable que en cada prctica encuentres varias entidades y varias
arquitecturas. Tomando como ejemplo al multiplexor, sabemos que no todos
tienen el mismo nmero de bits o de canales, por eso cada uno tiene una
entidad distinta.

Un multiplexor es un dispositivo lgico que recibe informacin por sus


dos o ms entradas (de uno o mas bits de ancho) y mediante una seal de control
decidimos cual de la entradas aparece reflejada en la salida; esto es, un
convertidor de paralelo a serie. Si tienen una seal de "enable" esta hace que el
multiplexor est habilitado o no

Los multiplexores que


Elige en la lista una prctica
hemos
propuesto
tienen todos seal de
para empezar, sin ms que pinchar en el
enable
menos
el
primero.
Las
botn adecuado. Para volver pulsa el
arquitecturas
estn
realizadas
solo para
botn que est al lado del ttulo
algunas entidades

Multiplexor de un bit y dos canales sin


"enable"

Cmo aadir una seal de "enable"

Como aumentar los bits de cada canal

Cmo aumentar el nmero de canales

Completar la entidad 4 con estilo algortmico


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 ms 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 seal o
variable asociada es de un slo bit. La nomenclatura usada para
designar a los puertos se mantendr hasta el final de la prctica, no
as como el nombre de la entidad, que lo cambiaremos.
entity multiplexor is port(
a,b
: in bit;
control : in bit;
c
: out bit
);
end multiplexor;

En este caso, las entradas son a y


b (por eso son del modo in), la
seal de control es control
(tambin del modo in), y la salida
es c (del modo out). Todas son de
un bit de ancho.

Entidad 2: Qu hacer para que tenga seal de


"enable"
Para que nuestro diseo tenga una seal de enable, y a efectos de la
entidad, solamente debemos incluirla sin ms. Ms adelante, en la
arquitectura ser donde deberemos manejar esta seal para que
realice lo que nosotros queramos.
entity multiplexor is port(
a,b
: in bit;
control : in bit;
enable : in bit;
c
: out bit
);
end multiplexor;

En este caso, las entradas son a y


b, la seal de control es control,
la seal de enable es enable, y la
salida es c. Todas vuelven a ser de
un bit de ancho.

Entidad 3: Qu hacer para que cada canal sea de


mas bits
Si queremos que cada entrada (y la salida, por supuesto), tengan ms
anchura, es decir, ms 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 nmero de mayor
peso seguido de la palabra downto y del nmero de menor peso.

entity multiplexor is port(


a,b:in bit_vector(3 downto 0);
control:in bit;
enable :in bit;
c: out bit_vector(3 downto 0)
);
end multiplexor;

En este caso, las entradas son a y


b, la seal de control es control,
la seal de habilitacin es enable,
y la salida es c. Ahora, las
entradas a y b son de 4 bits de
ancho, pero como slo son dos,
control debe seguir siendo de un
solo bit. La salida debe aumentar
tambin para adaptarse a las
entradas.

Entidad 4: Qu hacer para que tenga ms canales


Al igual que cuando queramos que tuviese seal de enable, si ahora
queremos ms canales, a efectos de la entidad, slo debemos
aadirlos.
entity multiplexor is port(
a,b,c: in bit_vector(3 downto
0);
control:in bit_vector(1 downto
0);
enable: in bit;
d:
out bit_vector(3 downto
0);
);
end multiplexor;

En este caso, las entradas son a,


b, y c, la seal de control es
control, la seal de habilitacin
es enable, y la salida es d. Las
entradas y la salida siguen siendo
de 4 bits de ancho, y al haber mas
de dos, control debe aumentar su
anchura a dos bits.

control

enable

XX

HHHH

LL

LH

HL

HH

HHHH

Arquitectura 1: Estilo algortmico o de


comportamiento usando la entidad 4
El estilo algortmico es una forma de programacin en la cual se usan
los elementos propios de un lenguaje de programacin, 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 sera la siguiente:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

entity multi is port(


a, b, c :in bit_vector(3 downto 0);
enable :in bit;
control :in bit_vector(1 downto
0);
d
:out bit_vector(3 downto 0)
);
end multi;
Cabecera del programa
architecture archmul of multi is
Empieza el programa
begin
Cabecera de un proceso
process (a, b, c, control, enable)
Empieza el proceso
begin
Sentencia if
if enable='1' then d<="1111";
Sentencia elsif
elsif enable='0' then
Sentencia case
case control is
when "00" => d <= a;
when "01" => d <= b;
when "10" => d <= c;
when others => d <= "1111";
Acaba sentencia case
end case;
Acaba sentencia if y elsif
end if;
Acaba el proceso

17

end process;
end archmul;

Finaliza el programa

18
19
20
21
22
Debemos ver lo siguiente en este ejercicio:

Entre las lneas 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 lnea 10 empieza un proceso (process), el cual acaba en


la lnea 21. Si alguna de las variables que estn dentro del
parntesis cambia, el proceso se ejecuta. Una vez ejecutado el
proceso cambian las seales, no durante l.

En la lnea 12 hay una sentencia que acaba en la lnea 20. Si se


cumple la condicin que est despus de la palabra if, se
ejecuta lo que est despus de la palabra then. En caso de que
la condicin no se cumpla, se evala lo que est detrs de la
palabra elsif, y si es verdad se ejecuta lo que est despus del
segundo else. Si se cumple la primera condicin, 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 lnea 14 y acaba en la 29.


Segn 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 tambin 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.

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 lgicas es el siguiente:

1
2
3
4
5
6
7
8
9
10
11

entity multi is port(


a,b
: in bit;
control : in bit;
enable : in bit;
c
: out bit
);
end multi;
architecture archmul of multi is
signal aux1,aux2,aux3: bit;
begin
aux1 <= b and (not(control));
aux2 <= a and control;
aux3 <= aux1 or aux2;
c <= enable and aux3;
end archmul;

12
13

Cabecera del programa


Declaracin de seales
Empieza el programa
Sentencia concurrente
Sentencia concurrente
Sentencia concurrente
Sentencia concurrente
Finaliza el programa

14
15
Recordemos que unas sentencias son concurrentes si se ejecutan
todas a la vez. De este cdigo debemos destacar estas dos
cuestiones:

En la lnea 9 se declaran las seales aux1, aux2 y aux3, que son


seales intermedias que no forman parte de la entrada ni de la
salida y que las utilizamos para hacer ms cmodamente la
estructuracin del programa. Si estas seales, el cdigo sera
ms confuso aunque igualmente vlido, ya que de no usarlas

deberamos haber sustituido las lneas de la 11 a la 14 por la


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

La explicacin de las sentencias que estn en la lnea 11 a la 14


habla por si solas sin ms que mirar el cdigo. Con una simple
inspeccin comprobamos que se corresponde con el grfico
situado sobre el cdigo.

Este tipo de estilo es solo recomendable usarlo en "estado puro" solo


para diseos tan sencillos , siendo de verdadera utilidad al usarlo
como complemento del estilo algortmico y en ocasiones del
estructural. A partir de ahora la nica forma en que la veamos ser
esta: como complemento.

Arquitectura 3: Estilo estructural usando la entidad


2
El estilo estructural es fcilmente reconocible porque la operatividad
del programa no se puede leer del cdigo ya que est formado
ntegramente por componentes y las seales que les unen a otros. Es
decir, est formado por bloques o cajas negras a los cuales metemos
informacin y sacamos las salidas, las cuales podrn o no ir a otros
bloques. Para esto debemos conocer la operatividad de estos bloques,
los cuales suelen estar en libreras. Para usar las puertas que estn en
el paquete gatespkg debemos primero invocar a la librera ieee
(lase "i e cubo") como est expuesto en la primera lnea de la
entidad que debemos usar. Para usar el paquete (o sub-librera)
gatespkg la llamaremos de la forma en que est en la segunda lnea.
Estas libreras vienen incluidas en la versin 3.5 del programa WARP,
de Cypress Semiconductor.

library ieee;

Llamamos a la librera

use work.gatespkg.all;

3
4
5
6
7
8
9
10
11
12
13

entity multi is port(


a,b : in bit;
control : in bit;
enable : in bit;
c : out bit
);
end multi;
architecture archmul of multi is
signal aux0,aux1,aux2,aux3: bit;
begin
puerta0:inv port map(control,aux0);
puerta1:and2 port
map(b,aux0,aux1);
puerta2:and2 port
map(a,control,aux2);
puerta3:or2 port
map(aux1,aux2,aux3);
puerta4:and2 port
map(enable,aux3,c);
end archmul;

14
15
16
17

IEEE
Llamamos a la librera
que tiene las puertas
lgicas

Cabecera del programa


Declaracin de seales
Empieza el programa
Sentencia concurrente
Sentencia concurrente
Sentencia concurrente
Sentencia concurrente
Sentencia concurrente
Finalizamos el programa

18
19
En este ejemplo vemos que debemos hacer para usar las libreras que
vienen predefinidas con el lenguaje VHDL y ms concretamente con
Warp 3.5 de Cypress Semiconductor. Para trabajar con libreras
debemos tener en cuenta estos puntos:

La librera 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 librera. Para ello
nuestras primeras lneas del programa deben hacer referencia a
la librera que necesitemos. En este ejemplo, se usa la librera
ieee. Dentro de la librera est el paquete de puertas lgicas
comunes, que vienen en el fichero gatespkg.vhd. Este
paquete es el que debemos invocar (ya que no vamos a usar la
librera en toda sus extensin, slo una parte). Para esto
debemos conocer el paquete, que utilidades nos puede ofrecer
y cual es el orden correcto de las variables entre parntesis.
Para ello no hay ms remedio que ir llevando una lista con las
libreras que vayamos conociendo y estudiar la estructura de las
libreras por dentro.

Una vez que hemos cargado la librera, la usamos de la forma


expuesta en las lneas de la 13 a la 17, indicando que parte de
la librera usamos (inv, and2, or2,...) seguido de las palabras
claves port map, y entre parntesis las seales que

introducimos en las estructuras de las libreras. En estos casos,


la ltima seal suele ser la que sacamos, aunque no tiene
porque se as. Para ms informacin detn del cursor al lado del
icono de ayuda en la lnea correspondiente.
Si alguien cambiase el contenido de la librera e hiciese que el bloque
and2 dejase de ser una puerta and de dos entradas, nuestro diseo
no sera correcto, ya que no hara lo que nosotros pretendemos en un
principio. Por sto, debemos estar seguros de que funcin realiza una
parte de una librera antes de usarla.
Al igual que el estilo de flujo de datos, este estilo es poco usado en
estado puro, usndose solamente para unir diseos complejos
creados anteriormente.

Estilo flujo de datos usando la entidad 2

-- tiempo de compilacin 17 segundos


-- utilizacin de macroclulas 86%
-- utilizacin de terminos de productos logicos de salida 9%
entity multiplexor is port(
a, b, c : in bit_vector(3 downto 0);
enable : in bit;
control : in bit_vector(1 downto 0);
d
: out bit_vector(3 downto 0)
);
end multiplexor;
architecture archimultiplexor of multiplexor is
begin
process( a , b , c , control , enable )
begin
if enable='1' then d<="1111";
elsif enable='0' then
case control is
when "00"
=> d <= a;
when "01"
=> d <= b;
when "10"
=> d <= c;
when others => d <= "1111";
end case;
end if;
end process;
end archimultiplexor;

Estilo estructural usando la entidad 2


--tiempo de compilacin 20 segundos
--utilizacin de la cpsula 1%
--utilizacin de macroclulas 22%
library ieee;
use ieee.std_logic_1164.all;
use work.gatespkg.all;
entity multi is port(

a,b
: in
control : in
enable : in
c
: out
);
end multi;

bit;
bit;
bit;
bit

architecture archmul of multi is


signal aux0,aux1,aux2,aux3: bit;
begin
puerta0:inv port map(control,aux0);
puerta1:and2 port map(b,aux0,aux1);
puerta2:and2 port map(a,control,aux2);
puerta3:or2 port map(aux1,aux2,aux3);
puerta4:and2 port map(enable,aux3,c);
end archmul;

Un demultiplexor es un dispositivo lgico que como su nombre indica


realiza la operacin inversa al multiplexor; esto es, un convertidor de serie a
paralelo. El demultiplexor recibe informacin por su nica entrada (de uno o mas
bits) y una seal de control decide en cual de las salidas se refleja. Si tienen una
seal de "enable" esta hace que el demultiplexor est habilitado o no

Estos demultiplexores son


Elige en la lista una prctica
los
inversos
a
la mayora de los
para empezar, sin ms que pinchar en el
multiplexores de la prctica anterior. No
botn adecuado. Para volver pulsa el
hemos usado los estilos de flujo de datos
botn que est al lado del ttulo
y estructural por no ser "rentable".

Demultiplexor de un bit y dos canales sin


"enable"

Cmo aadir una seal de "enable"

Como aumentar los bits de cada canal

Cmo auentar el nmero de canales

Completar la entidad 4 con estilo


algortmico

Entidad 1: Demultiplexor de un bit y dos canales sin


"enable"
Al igual que en la prctica anterior, este es el demultiplexor ms
sencillo que podemos imaginar, es decir con menos canales y con
menos bits. Tiene una entrada de datos de un bit y dos salidas,
tambin de un bit. Esto hace que la seal de control tenga la misma
anchura..
entity demultiplexor is port(
entra : in bit;
control : in bit;
a,b
: out bit
);

En este ocasin, la entrada es


entra, la seal de control es
control, y la salidas son a y b.
Todas son de un bit de ancho. La
ltima declaracin no lleva punto

end demultiplexor;

y coma.

Entidad 2: Qu hacer para que tenga seal de


"enable"
Tal y como vimos en la prctica anterior, para aadir la seal de
habilitacin o enable, y al estar tratando de momento las entidades,
solamente hay que aadirla a la lista de entradas y salidas. Ser
cuando construyamos las arquitecturas cuando deberemos modificar
la operatividad del programa para que realice la funcin que
queremos.
entity demultiplexor is port(
entra : in bit;
control : in bit;
enable : in bit;
a,b
: out bit
);
end demultiplexor;

Slamente hemos aadido la seal


de enable, que tiene ese nombre,
y todas vuelven a ser de un bit de
ancho.

Entidad 3: Qu hacer para que cada canal sea de


mas bits
Si queremos que cada entrada (y la salida, por supuesto), tengan ms
anchura, es decir, ms 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);
control, enable :in bit;
a,b: out bit_vector(7 downto
0)
);
end demultiplexor;

Esta entidad se diferencia de la


anterior en que en vez de ser la
entrada y las salidas de un bit, son
de ocho (de siete a cero). Adems
hemso puesto a control y a
enable en la misma lnea por ser
del mismo tipo, separados por una
coma.

Entidad 4: Qu hacer para que tenga ms canales


Al igual que cuando queramos que tuviese seal de enable, si ahora
queremos ms canales, a efectos de la entidad, slo debemos
aadirlos, ser luego, en la arquitectura cuando deberemos hacer que
tenga la operatividad deseada..
entity demultiplexor is port(
entra: in bit_vector(7 downto
0);
control:in bit_vector(1 downto
0);
enable: in bit;
a,b,c,d:out bit_vector(7 downto
0)
);
end demultiplexor;

Slo hemos aadido dos salidas


ms, que deben ser de la misma
anchura que la otras y que la
entrada. La seal de control debe
ser ms ancha porque tiene que
controlar a cuatro salidas (a, b, c
y d)

contr enab
A
ol
le

XX

entr
b
a

LL

LH

entr
a

HL

HH

entr
d
a

entr
a

Arquitectura 1: Estiloalgortmico usando la entidad


4
En esta arquitectura usaremos la entidad anterior, y la hemos
construido de dos formas, para diferenciar una caracterstica muy
importante de VHDL como es la memoria implcita. Para ms ayuda
detn el cursor sobre los iconos azules al lado de la lnea
correspondiente.
1
2

entity demulti is port(


entra: in bit_vector(7 downto 0);

La entidad se llama
demulti

3
4
5
6
7
8
9
10

control: in bit_vector(1 downto 0);


enable: in bit;
a,b,c,d: out bit_vector(7 downto 0)
);
end demulti;
architecture archdemul of demulti is
begin
process (entra, control, enable)
begin
if enable='1' then a<="11111111";
b<="11111111";
c<=(others=>'1');
d<=(others=>'1');
elsif enable='0' then
case control is
when "00" => a <= entra;
when "01" => b <= entra;
when "10" => c <= entra;
when others => d <= entra;
end case;
end if;
end process;
end archdemul;

11
12
13
14
15
16
17
18

y es idmtica a la
entidad
anterior

Cabecera del
programa
Empieza el
programa
Cabecera de un
proceso
Empieza el proceso
Sentencia if

Sentencia elsif
Sentencia case

19
Finaliza el case
Finaliza el if y el
elsif
Finaliza el proceso
Finaliza el programa

20
21
22
23
24
25

Debemos ver lo siguiente en este ejercicio:

Entre la lnea 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 nmero 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 ms adelante control es "01", b toma el valor de
entra, pero a sigue con el valor anterior de entra ya que no
hay ninguna instruccin que modifique su valor. Esta memoria
est implcita 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 lneas de la 17 a la 22 por
lo siguiente:
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, slamente una salida toma el


valor de entra y las otras el valor "00000000", ya que as lo hemos
pedido explcitamente.

Estiloalgortmico usando la entidad 4


-- tiempo de compilacin 1 minuto 8 segundos
-- utilizacin de macroclulas 22%
entity demulti is port(
entra: in bit_vector(7 downto 0);
control:in bit_vector(1 downto 0);

enable: in bit;
a,b,c,d:out bit_vector(7 downto 0)
);
end demulti;
architecture archdemul of demulti is
begin
process (entra, control, enable)
begin
if enable='1' then a<="11111111";
b<="11111111";
c<=(others=>'1');
d<=(others=>'1');
elsif enable='0' then
case control is
when "00" => a <= entra;
when "01" => b <= entra;
when "10" => c <= entra;
when others => d <= entra;
end case;
end if;
end process;
end archdemul;

-- tiempo de compilacin 1 minuto 8 segundos


-- utilizacin de macroclulas 22%
entity demulti is port(
entra: in bit_vector(2 downto 0);
control:in bit_vector(1 downto 0);
enable: in bit;
a,b,c:out bit_vector(2 downto 0)
);
end demulti;
architecture archdemul of demulti is
begin
process (entra, control, enable)
begin
if enable='1' then a<="111";
b<="111";
c<=(others=>'1');
elsif enable='0' then
case control is
when "00" => a <= entra;
b <= "000";
c <= "000";
when "01" => a <= "000";
b <= entra;
c <= "000";
when "10" => a <= "000";
b <= "000";
c <= entra;
when others => a <= "000";
b <= "000";
c <= "000";
end case;
end if;

end process;
end archdemul;

Un codificador es un dispositivo lgico que recibe informacin por su


entrada y la traduce a un cdigo, el cual depende del tipo de codificador. Tienen
una serie de patillas de entrada de las cuales slo una se activa, apareciendo el
nmero de la patilla activada a la salida en el cdigo correspondiente: Aiken,
decimal, BCD, BCD+3,...

A partir de ahora crearemos


Elige en la lista una prctica
las
entidades
y arquitecturas a la vez
para empezar, sin ms que pinchar en el
para
trabajar
de
forma normal
botn adecuado. Para volver pulsa el
prescindiremos
de
la columna de ayuda
botn que est al lado del ttulo
de la derecha.

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 interrupcin

Codificador binario 16 a 4 con interrupcin

Entidad 1: Codificador binario de 4 a 2 bits sin


prioridad
Este codificador tiene una seal de cuatro bits (numerados del cero al
tres) de entrada, y una de salida de dos. Segn qu bit de los cuatro
de la entrada est seleccionado (esto es a nivel alto), saldr a la
salida un nmero 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.
entity coder is port(
dentro: in bit_vector(3 downto
0);
fuera : out bit_vector(1 downto
0);
error : out bit
);
end coder;

Necesitamos una entrada de 4


bits (dentro), una salida de dos
bits (fuera), y otra de uno
llamada error.

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 slo
podemos tener seleccionado un slo bit de entrada. Para detectar si
hay ms 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
2
3
4
5
6
7
8
9
10
11
12
13

architecture archicoder of coder is


begin
process (dentro)
begin
case dentro is
when "0001" => fuera <= "00";
when "0010" => fuera <= "01";
when "0100" => fuera <= "10";
when "1000" => fuera <= "11";
when others => error <= '1';
end case;
end process;
end archicoder;

Pero debemos darnos cuenta de que este diseo es del todo


incorrecto por la memoria implcita que tiene el lenguaje VHDL, ya
que en el momento en que haya un dos entradas seleccionas a la vez,
la seal error permanecera para siempre a nivel lgico alto, ya que
no hay ninguna instruccin que haga que est a nivel lgico cero.
Para corregir esto deberemos escribir el siguiente cdigo, en el cual,
cada vez que hay una entrada correcta la seal error se pone a cero.
1
2
3
4
5
6
7
8
9
10
11
12
13

architecture archicoder of coder is


begin
process (dentro)
begin
case dentro is
when "0001" => fuera <= "00"; error
when "0010" => fuera <= "01"; error
when "0100" => fuera <= "10"; error
when "1000" => fuera <= "11"; error
when others => error <= '1';
end case;
end process;
end archicoder;

<=
<=
<=
<=

'0';
'0';
'0';
'0';

Entidad 2: Codificador binario de 8 a 3 con prioridad


En esta ocasin, no necesitaremos la seal de error por ser un
codificador con prioridad en el cual se especifica que hacer si hay
mas de un bit habilitado. Le dotaremos adems de una seal de
salida de "enable output" o de codificador habilitado, que la
llamaremos EO. Para conseguir un codificador deberemos cargar la
funcin std_match que sirve para comparar dos vectores si en uno
de ellos hay trminos "poco importa". Esta funcin se encuentra en el
paquete std_arith, que est en la librera ieee. Esta funcin,
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 ms
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
LHXXXXXX
LLHXXXXX
LLLHXXXX
LLLLHXXX
LLLLLHXX
LLLLLLHX
LLLLLLLH

HHH
HHL
HLH
HLL
LHH
LHL
LLH
LLL

L
L
L
L
L
L
L
L

LLLLLLLL

LLL

library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
entity coder is port(
dentro: in std_logic_vector(7 downto
0);
fuera : out std_logic_vector(2 downto
0);
eo : out bit
);
end coder;

La primera lnea llama a la


librera ieee, la cual
contiene el paquete
std_logic_1164, que lo
necesitamos para usar el
tipo std_logic_vector, y
dentro de este paquete est
std_arith, que nos
proporciona la funcin
std_match. Se usan los
tipos bits y std_logic.

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 slo se le hace caso al que hemos determinado que sea el de
ms peso. En este caso el bit de ms peso es dentro(7) y el de menos
peso es dentro(0). La librera que hemos cargado nos permite hacer
comparaciones de elementos de los denominados "poco importa" con
la funcin std_match. Para operar con std_match introducimos dos
vectores (de igual longitud) y nos devuelve le valor true o false
segn sea el resultado de la comparacin. Pulsa aqu para ver la
sentencia if.
1
2
3
4
5

architecture archicoder of coder is


begin
process (dentro)
begin
if std_match(dentro,"1-------") then fuera<="111"; eo<='0';
end if;

6
7
8
9
10
11
12
13
14
15

if std_match(dentro,"01------") then fuera<="110"; eo<='0';


end if;
if std_match(dentro,"001-----") then fuera<="101"; eo<='0';
end if;
if std_match(dentro,"0001----") then fuera<="100"; eo<='0';
end if;
if std_match(dentro,"00001---") then fuera<="011"; eo<='0';
end if;
if std_match(dentro,"000001--") then fuera<="010"; eo<='0';
end if;
if std_match(dentro,"0000001-") then fuera<="001"; eo<='0';
end if;
if std_match(dentro,"00000001") then fuera<="000";
eo<='0'; end if;
if std_match(dentro,"00000000") then fuera<="000";
eo<='1'; end if;
end process;
end coder;

Hacer este ejercicio con el estilo de flujo de datos hubiera sido


impensable, ya que habra que buscar las ecuaciones lgicas 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 continuacin se muestran la
ecuacin lgica para conseguir el bit fuera(0):
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 cdigo.

Entidad 3: Codificador binario 16 a 4 con


interrupcin
Este ejemplo lo emplearemos para poder dar muestra de la
versatilidad de VHDL para el diseo e implementacin de circuitos,

que por sus caractersticas peculiares no existen en el mercado, por lo


que en condiciones normales nos veramos obligados a disearlos e
implementarlos haciendo uso de varios circuitos MSI que aumentaran
la complejidad del "routeado" y aumentara la posibilidad de tener
fenmenos 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 corresponderan con tecnologa
CMOS) y una salida de interrupcin 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 tambin requerir una disposicin 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 diseo del dispositivo lgico debe ser el
siguiente:

De esta forma la entidad nos queda como sigue:


library ieee;
use ieee.std_logic_1164.all;
entity coder is
port(
ent: in std_logic_vector(16 downto 1);
interr: out std_logic;
sal: out std_logic_vector(4 downto 1)
);

Al igual que antes, para


usar el tipo std_logic o
alguno de sus derivados
(como los vectores),
debemos cargar la librera
ieee, y, de sta, el paquete
std_logic_1164. La
palabra all indica que
cargamos TODO el
attribute pin_numbers of coder:entity paquete, no una parte.
is
Para prefijar la dispocicion
"ent(1):3 ent(2):2 ent(3):20 ent(4):19 de las seales en las
ent(5):1 ent(6):23 ent(7):22 ent(8):21
patillas de la cpsula,
ent(9):10 ent(10):11 ent(11):4 ent(12):5 hemos usado la sentencia
ent(13):8 ent(14):9 ent(15):6 ent(16):7 " attribute pin_numbers, en
&
la cual primero se
"sal(1):14 sal(2):15 sal(3):16 sal(4):17
especifica el orden de las
inerr:18 ";
entradas y despues el de
las salidas.

end coder;
Como nota curiosa hay que sealar que el compilador que usamos, el
Galaxy / Warp de Cypress no admite que las lneas de la posicin de
los pines tengan varias lnea, sino slamente una para las entradas y
slamente una para las salidas. Adems entre la ltima asignacin y
las comillas debe existir un espacio.

Arquitectura 3: Codificador binario 16 a 4 con


interrupcin
Para crear la arquitectura de este codificador deberemos conocer con
precisin cuales han de ser sus requerimientos de funcionamiento.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

architecture archicodifi of coder is


begin
code: process (ent)
begin
case ent is
when "1111111111111110" => sal <= "0000";
when "1111111111111101" => sal <= "0001";
when "1111111111111011" => sal <= "0010";
when "1111111111110111" => sal <= "0011";
when "1111111111101111" => sal <= "0100";
when "1111111111011111" => sal <= "0101";
when "1111111110111111" => sal <= "0110";
when "1111111101111111" => sal <= "0111";
when "1111111011111111" => sal <= "1000";
when "1111110111111111" => sal <= "1001";
when "1111101111111111" => sal <= "1010";
when "1111011111111111" => sal <= "1011";
when "1110111111111111" => sal <= "1100";
when "1101111111111111" => sal <= "1101";
when "1011111111111111" => sal <= "1110";
when "0111111111111111" => sal <= "1111";
when others => sal <= "1111"; interr<='0';
end case;
end process code;
end archicodifi;

interr<='1';
interr<='1';
interr<='1';
interr<='1';
interr<='1';
interr<='1';
interr<='1';
interr<='1';
interr<='1';
interr<='1';
interr<='1';
interr<='1';
interr<='1';
interr<='1';
interr<='1';
interr<='1';

Este ejemplo no tiene nada de extrao 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 programacin para hacerla ms legible. Al cerrar un
proceso con nombre, hay que especificarlo, como aparece en la lnea
24.

Codificador binario de 4 a 2 bits sin prioridad


entity coder is port(
dentro: in bit_vector(3 downto 0);
fuera : out bit_vector(1 downto 0);
error : out bit
);
end coder;
architecture archicoder of coder is
begin
process (dentro)
begin
case dentro is
when "0001" => fuera <= "00";
when "0010" => fuera <= "01";
when "0100" => fuera <= "10";
when "1000" => fuera <= "11";
when others => error <= '1';
end case;
end process;
end archicoder;

Codificador binario de 8 a 3 con prioridad


library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
entity coder is port(
dentro: in std_logic_vector(7 downto
fuera : out std_logic_vector(2 downto
eo
: out bit
);
end coder;
architecture archicoder of coder is
begin
process (dentro)
begin
if std_match(dentro,"1-------") then
if std_match(dentro,"01------") then
if std_match(dentro,"001-----") then
if std_match(dentro,"0001----") then
if std_match(dentro,"00001---") then
if std_match(dentro,"000001--") then
if std_match(dentro,"0000001-") then
if std_match(dentro,"00000001") then
if std_match(dentro,"00000000") then
end process;
end archicoder;

0);
0);

fuera<="111";
fuera<="110";
fuera<="101";
fuera<="100";
fuera<="011";
fuera<="010";
fuera<="001";
fuera<="000";
fuera<="000";

eo<='0';
eo<='0';
eo<='0';
eo<='0';
eo<='0';
eo<='0';
eo<='0';
eo<='0';
eo<='1';

end
end
end
end
end
end
end
end
end

if;
if;
if;
if;
if;
if;
if;
if;
if;

Codificador binario 16 a 4 con interrupcin


library ieee;
use ieee.std_logic_1164.all;
entity codifi is
port(
ent: in std_logic_vector(15 downto 0);
interr: out std_logic;
sal: out std_logic_vector(3 downto 0)
);
attribute pin_numbers of coder:entity is
"ent(1):3 ent(2):2
ent(3):20 ent(4):19 ent(5):1 ent(6):23
ent(7):22 ent(8):21 ent(9):10 ent(10):11 ent(11):4 ent(12):5 ent(13):8
ent(14):9 ent(15):6 ent(16):7 " &
"sal(1):14 sal(2):15 sal(3):16 sal(4):17 interr:18 ";
end codifi;
architecture archicodifi of codifi is
begin
deco: process (ent)
begin
case ent is
when "0111111111111111" => sal <= "0000"; interr
when "1011111111111111" => sal <= "0001"; interr
when "1101111111111111" => sal <= "0010"; interr
when "1110111111111111" => sal <= "0011"; interr
when "1111011111111111" => sal <= "0100"; interr
when "1111101111111111" => sal <= "0101"; interr
when "1111110111111111" => sal <= "0110"; interr
when "1111111011111111" => sal <= "0111"; interr
when "1111111101111111" => sal <= "1000"; interr
when "1111111110111111" => sal <= "1001"; interr
when "1111111111011111" => sal <= "1010"; interr
when "1111111111101111" => sal <= "1011"; interr
when "1111111111110111" => sal <= "1100"; interr
when "1111111111111011" => sal <= "1101"; interr
when "1111111111111101" => sal <= "1110"; interr
when "1111111111111110" => sal <= "1111"; interr
when others => sal <= "1111"; interr <='0';
end case;
end process deco;
end archicodifi;

<=
<=
<=
<=
<=
<=
<=
<=
<=
<=
<=
<=
<=
<=
<=
<=

'1';
'1';
'1';
'1';
'1';
'1';
'1';
'1';
'1';
'1';
'1';
'1';
'1';
'1';
'1';
'1';

Un decodificador es un circuito combinacional cuya caracterstica


fundamental es que, para cada combinacin de las entradas, slo una de las
salidas tiene un nivel lgico diferente a las dems. Este circuito realiza la operacin
inversa a la de un codificador de datos y es anloga a la de un demultiplexor, pero
sin entrada de informacin.

Los decodificadores
Elige en la lista una prctica
para empezar, sin ms que pinchar en el expuestos ser una muestra prctica de
la versatilidad de VHDL para la
botn adecuado. Para volver pulsa el
implementacin de este tipo de circuitos
botn que est al lado del ttulo
lgicos.

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 diseo de la entidad necesitamos tener una entrada de tres
bits, dos entradas de control, y una salida de ocho bits que en este
caso sern activas por nivel bajo. El cdigo no requiere mayor
explicacin, ya que la entidad es muy sencilla:
library ieee;
use ieee.std_logic_1164.all;

La entrada de
informacin es entrada,

entity decoder is
port(
entrada: in std_logic_vector(2 downto
0);
las de control son g1 y
g1, g2: in std_logic;
g2 y la salida es salida.
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.

g1 g2

Entrad
a
(2 a 0)

Salida
(7 a 0)

XXX

HHHHHHHH

XXX

HHHHHHHH

LLL

LHHHHHHH

LLH

HLHHHHHH

LHL

HHLHHHHH

LHH

HHHLHHHH

HLL

HHHHLHHH

HLH

HHHHHLHH

HHL

HHHHHHLH

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

HHH

HHHHHHHL

architecture archidecoder of decoder is


begin
decoder: process (entrada,g1,g2)
begin
if g2='1' then salida<=(others=>'1');
elsif g2='0' and g1='0' then salida<=(others=>'1');
elsif g2='0' and g1='1' then
salida <= "01111111" when entrada="000" else
"10111111" when entrada="001" else
"11011111" when entrada="010" else
"11101111" when entrada="011" else
"11110111" when entrada="100" else
"11111011" when entrada="101" else
"11111101" when entrada="110" else
"11111110" when entrada="111" else
"11111111";
end archidecoder;

En este ejemplo introducimos una nueva sentencia, la sentencia


when-else que viene a ser como una scesin de sentencias if
anidadas. No debemos olvidar al final la sentencia others en la que
se contemplan todos los dems 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 ms 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 tpico de decodificador, en el cual tenemos 4
bits de entrada por los cuales nos llega un nmero en BCD natural y a
la salida tenemos 7 bits de salida los cuales contienen decodificado el
nmero de la entrada para que sea entendido por un display de 7

segmentos. La entidad correspondiente no tiene ningna


complicacin, si exceptuamos que usamos el tipo std_logic, para lo
cual hay que cargar un paquete de la librera ieee.
library ieee;
use ieee.std_logic_1164.all;
entity convertidor is
port(
bcd: in bit_vector(3 downto 0);
led: out bit_vector(6 downto 0)
);
end convertidor;

Al igual que antes, para usar


el tipo std_logic o alguno de
sus derivados (como los
vectores), debemos cargar la
librera ieee, y, de sta, el
paquete std_logic_1164. La
palabra all indica que
cargamos TODO el paquete,
no una parte.

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
cdigo, comprobamos la similitud entre ambos. La tabla la siguiente:
Entrada
(BCD)

Salida
(LED)

LLLL

HHHHHHL

LLLH

HHLLLLL

LLHL

HLHHLHH

LLHH

HHHLLHH

LHLL

HHLLHLH

LHLH

LHHLHHH

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

LHHL

LHHHHHH

LHHH

HHLLLHL

HLLL

HHHHHHH

HLLH

HHHLHHH

LLLL

LLLLLLL

architecture archiconv of convertidor is


begin
conv: process (bcd)
begin
case bcd is
when "0000" => LED <= "1111110";
when "0001" => LED <= "1100000";
when "0010" => LED <= "1011011";
when "0011" => LED <= "1110011";
when "0100" => LED <= "1100101";
when "0101" => LED <= "0110111";
when "0110" => LED <= "0111111";
when "0111" => LED <= "1100010";
when "1000" => LED <= "1111111";
when "1001" => LED <= "1110111";
when others => LED <= "0000000";
end case;
end process conv;
end archiconv;

Este ejemplo no tiene nada de extrao 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 programacin para hacerla ms legible. Al cerrar un
proceso con nombre, hay que especificarlo, como aparece en la lnea
18.

Arquitectura 1: Decodficador de 3 a 8
library ieee;
use ieee.std_logic_1164.all;
entity decoder is
port(
entrada: in std_logic_vector(2 downto 0);
g1, g2: in bit;
salida: out std_logic_vector(7 downto 0)
);
end decoder;
architecture archidecoder of decoder is
begin
salida <= (others=>'1') when g2='1'

else (others=>'1') when g2='0' and g1='0'


else
"01111111" when entrada="000" else
"10111111" when entrada="001" else
"11011111" when entrada="010" else
"11101111" when entrada="011" else
"11110111" when entrada="100" else
"11111011" when entrada="101" else
"11111101" when entrada="110" else
"11111110" when entrada="111" else
"11111111";
end archidecoder;

Decodificador de BCD a 7 segmentos


library ieee;
use ieee.std_logic_1164.all;
entity convertidor is
port(
bcd: in bit_vector(3 downto 0);
led: out bit_vector(6 downto 0)
);
end convertidor;
architecture archiconv of convertidor is
begin
conv: process (bcd)
begin
case bcd is
when "0000" => LED <= "1111110";
when "0001" => LED <= "1100000";
when "0010" => LED <= "1011011";
when "0011" => LED <= "1110011";
when "0100" => LED <= "1100101";
when "0101" => LED <= "0110111";
when "0110" => LED <= "0111111";
when "0111" => LED <= "1100010";
when "1000" => LED <= "1111111";
when "1001" => LED <= "1110111";
when others => LED <= "0000000"; -- si no se introduce BCD no se
enciende ningn led
end case;
end process conv;
end archiconv;

Un comparador es un dispositivo lgico que recibe dos nmeros a la


entrada, A y B, y a la salida indica si el nmero A es mayor, menor o igual que el
nmero B. La longitud de las palabras de la entrada es indiferente, pero iguales
para ambos nmeros. Pueden llevar adems entradas en cascada, usadas para
utilizar varios comparadores.

Los comparadores van


Elige en la lista una prctica
desde
el
ms
sencillo hasta el ms
para empezar, sin ms que pinchar en el
complejo
posible.
Se puede ver
botn adecuado. Para volver pulsa el
claramente
en
este
ejemplo, las mejoras
botn que est al lado del ttulo
de VHDL frente a los MSI.

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 ms sencillos de


crear, ya que slo necesitamos dos entradas para los dos nmeros
(de dos bits cada uno) y tres salidas, que se activarn segn el
resultado de la activacin. Como ya dijimos en la prctica del
codificador, usaremos el tipo std_logic_vector, que es el ms usado
y el que ms juego nos da.
library ieee;
use ieee.std_logic_1164.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;

Necesitamos dos entradas de


dos bits (a y b) y tres salidas
de un bit cada uno (mayor,
menor e igual).

Arquitectura 1: Comparador de dos bits


Para hacer la comparacin de dos nmeros con VHDL podemos usar
varias formas o mtodos. A continuacin describimos algunos de
ellas.
Este primer mtodo 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 nmero a es mayor,
menor o igual que el b.
1
2

architecture archicompara of compara is


begin

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

process (a,b)
begin
if (a(1) = b(1)) and (a(0) = b(0)) then mayor <= '0';
menor <= '0';
igual <= '1';
elsif (a(1) = '1') and (b(1) = '0') then mayor <= '1';
menor <= '0';
igual <= '0';
elsif (a(1) = '0') and (b(1) = '1') then mayor <= '0';
menor <= '1';
igual <= '0';
elsif (a(0) = '1') and (b(0) = '0') then mayor <= '1';
menor <= '0';
igual <= '0';
elsif (a(0) = '0') and (b(0) = '1') then mayor <= '0';
menor <= '1';
igual <= '0';
end if;
end process;
end archicompara;

18
19
20
21
22

El siguiente diseo ya es mucho ms aceptable y utiliza toda la


potencia de VHDL para dar un resultado preciso. Para esto utiliza la
librera ieee (que la utilizaremos siempre que haya que usar una
funcin 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 sera la arquitectura correspondiente:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

architecture archicompara of compara is


begin
process (a,b)
begin
if a > b then mayor <= '1';
menor <= '0';
igual <= '0';
elsif a < b then mayor <= '0';
menor <= '1';
igual <= '0';
elsif a = b then mayor <= '0';
menor <= '0';
igual <= '1';
end if;
end process;
end archicompara;

Esta estrucuta es mucho ms sencilla de crear y de comprender en un


posterior anlisis por una persona distinta a la que escribi el cdigo.

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 nmeros de ms de cuatro bits. Esto est anticuado con
VHDL ya que cambiando cuatro parmetros en el programa, un
comparador de cuatro se convierte en un comparador de ocho o de
16 bits. Necesitamos dos entradas para los nmeros 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(

Necesitamos dos entradas de


cuatro bits (a y b), tres
entradas de un bit para la

a,b: in std_logic_vector(1 downto


0);
antes_mayor: in std_logic;
antes_menor: in std_logic;
antes_igual: in std_logic
mayor: out std_logic;
menor: out std_logic;
igual: out std_logic
);
end compara;

entrada en cascada
(antes_mayor, antes_menor
y antes_igual) y tres salidas
de un bit cada uno (mayor,
menor e igual).

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 mdulo que compara bits de mayor peso, por lo que
slo deberemos comparar realmente cuando la entrada en cascada
antes_igual est activada.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

architecture archicompara of compara is


begin
process (a,b,antes_igual,antes_mayor,antes_menor)
begin
if antes_igual = '0' then igual <= antes_igual;
mayor <= antes_mayor;
menor <= antes_menor;
elsif antes_igual = '1' then
if a > b then mayor <= '1';
menor <= '0';
igual <= '0';
elsif a < b then mayor <= '0';
menor <= '1';
igual <= '0';
elsif a = b then mayor <= '0';
menor <= '0';
igual <= '1';
end if;

16
17
18

end if;
end process;
end archicompara;

19
20
21
En esta ocasin hemos usado parte del cdigo 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.

Comparador de dos bits


library ieee;
use ieee.std_logic_1164.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;
architecture archicompara of compara is
begin
process (a,b)
begin
if (a(1) = b(1)) and (a(0) = b(0)) then mayor <= '0';
menor <= '0';
igual <= '1';
elsif (a(1) = '1') and (b(1) = '0') then mayor <= '1';
menor <= '0';
igual <= '0';
elsif (a(1) = '0') and (b(1) = '1') then mayor <= '0';
menor <= '1';
igual <= '0';
elsif (a(0) = '1') and (b(0) = '0') then mayor <= '1';
menor <= '0';
igual <= '0';
elsif (a(0) = '0') and (b(0) = '1') then mayor <= '0';
menor <= '1';
igual <= '0';
end if;
end process;
end archicompara;

otro

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;
architecture archicompara of compara is
begin
process (a,b)
begin
if a > b then mayor <= '1';
menor <= '0';
igual <= '0';
elsif a < b then mayor <= '0';
menor <= '1';
igual <= '0';
elsif a = b then mayor <= '0';
menor <= '0';
igual <= '1';
end if;
end process;
end archicompara;

Comparador de cuatro bits con entrada en cascada


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;
antes_menor: in std_logic;
antes_igual: in std_logic;
mayor: out std_logic;
menor: out std_logic;
igual: out std_logic
);
end compara;
architecture archicompara of compara is
begin
process (a,b,antes_igual,antes_mayor,antes_menor)
begin
if antes_igual = '0' then igual <= antes_igual;
mayor <= antes_mayor;
menor <= antes_menor;
elsif antes_igual = '1' then
if a > b then mayor <= '1';
menor <= '0';
igual <= '0';
elsif a < b then mayor <= '0';
menor <= '1';
igual <= '0';
elsif a = b then mayor <= '0';
menor <= '0';
igual <= '1';
end if;
end if;

end process;
end archicompara;

Un CST es un dispositivo lgico cuya operatividad bsica 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.

Elige en la lista una prctica


El CST ha sido un circuito
para empezar, sin ms que pinchar en el bsico en el diseo de ALU's y circuitos
botn adecuado. Para volver pulsa el
arimticos en general.Poe ello VHDL nos
botn que est al lado del ttulo
permite crearlos fcilmente.

Cudruple Sumador Total.

Cudruple Sumador Total.

Cudruple Sumador Total con acarreo en


paralelo (flujo de datos).
Cudruple Sumador Total con acarreo en
paralelo (flujo de datos).

Entidad 1: Cudruple Sumador Total.


Para el diseo de un cuadruple sumador total, nos hace falta dos
entradas de cuantro bits (que sern los nmeros 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 adems
del carry.
library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
entity sumador is port(
a,b: in std_logic_vector(3 downto 0);
cin: in std_logic;
sum: out std_logic_vector(4 downto
0)
);
end sumador;

Los nmeros a sumar son a y


b, el carry de entrada es cin, el
resultado de la suma es sum y
el carry siguente es cout. Para
este diseo emplearemos la
librera aritmtica de VHDL
llamada std_arith, que se carga
al incluir la tercera lnea de
este programa.

Arquitectura 1: Cudruple Sumador Total.


Este ejemplo nos servira para poder hacer uso de una de las
caractersticas ms potentes de VHDL, que es la utilizacin 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
2
3
4
5
6
7
8
9
10
11
12

architecture archisumador of sumador is


begin
process (a,b,cin)
variable aux:std_logic_vector(4 downto 0);
begin
aux:=('0' & a) + ('0' & b);
if cin='1' then aux:=aux+1;
elsif cin='0' then null;
end if;
sum<=aux;
end process;
end archisumador;

En la lnea 5 se suman a y b pero como el resultado puede ser de


cinco bits, la seal 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.

Entidad 2: Cudruple Sumador Total con acarreo en


paralelo (flujo de datos).
Este es un inmejorable ejemplo de lo intil de usar el estilo de flujo de
datos en estado puro, es decir, sin recurrir a los dems. El programa
resultante es, aparte de extenso, totalmente incomprensible y no
aprovecha ninguna de las opciones que nos ofrece VHDL para
describir cmodamente un cirucito. Este programa est realizado en
maysculas para recalcar que VHDL no diferencia entre maysculas y
minsculas.
ENTITY fcadd4 IS
PORT (CI : IN BIT;

En vez de usar vectores


de bits vamos a usar las

A3,A2,A1,A0: IN BIT;
B3,B2,B1,B0: IN BIT;
SUM3,SUM2,SUM1,SUM0 : OUT BIT;
CO: OUT BIT);
END fcadd4;

entradas y salidas
desglosadas en bits.

Arquitectura 2: Cudruple Sumador Total con


acarreo en paralelo (con flujo de datos).
Esta es la arquitectura correspondiente al Cudruple Sumador Total
con acarreo en paralelo. Si empleamos circuitos MSI para la
implementacin de este circuito, resulta ms rpido 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
cdigo.
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 descripcin, por flujo de datos, nos lleva a la consecucin
de un cdigo rido de leer que dificulta su comprensin y posteriores
modificaciones.

Cudruple Sumador Total.


library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
entity sumador is port(
a,b: in std_logic_vector(3 downto 0);
cin: in std_logic;
sum: out std_logic_vector(4 downto 0)
);
end sumador;
architecture archisumador of sumador is
begin
process (a,b,cin)
variable aux:std_logic_vector(4 downto 0);
begin
aux:=('0' & a) + ('0' & b);
if cin='1' then aux:=aux+1;
elsif cin='0' then null; end if;
sum<=aux;
end process;
end archisumador;

Cudruple Sumador Total con acarreo en paralelo (con


flujo de datos).
ENTITY fcadd4 IS

PORT (CI : IN BIT;


A3,A2,A1,A0: IN BIT;
B3,B2,B1,B0: IN BIT;
SUM3,SUM2,SUM1,SUM0 : OUT BIT;
CO: OUT BIT);
END fcadd4;
ARCHITECTURE archfcadd4 OF fcadd4 IS
signal no1_o,no2_o,no3_o,no4_o: bit;
signal na1_o,na2_o,na3_o,na4_o: bit;
BEGIN
no1_o <= not(a0 or b0);
na1_o <= not(a0 and b0);
no2_o <= not(a1 or b1);
na2_o <= not(a1 and b1);
no3_o <= not(a2 or b2);
na3_o <= not(a2 and b2);
no4_o <= not(a3 or b3);
na4_o <= not(a3 and b3);
co <= not( (no4_o) or
(na4_o and no3_o) or
(no2_o and na4_o and na3_o) or
(no1_o and na4_o and na3_o and na2_o) or
((not ci) and na4_o and na3_o and na2_o and na1_o)
) ;
sum3 <= (na4_o and (not no4_o)) xor
not((no3_o) or
(no2_o and na3_o) or
(no1_o and na3_o and na2_o) or
(na3_o and na2_o and na1_o and (not ci))
);
sum2 <= (na3_o and (not no3_o)) xor
not ((no2_o) or
(no1_o and na2_o) or
(na2_o and na1_o and (not ci))
);
sum1 <= (na2_o and (not no2_o)) xor
not ((no1_o) or
(na1_o and (not ci))
);
sum0 <= (na1_o and (not no1_o)) xor ci;
END archfcadd4;

Un restador es un dispositivo lgico que recibe dos nmeros a la


entrada, A y B, y a la salida nos da su diferencia, admitiendo una posible llevada

de una operacin anterior y proporcionndonos un na nueva.

Elige en la lista una prctica


Los restadores utilizan el
para empezar, sin ms que pinchar en el
formato
de
complemento
a dos para
botn adecuado. Para volver pulsa el
representar
los
nmeros
negativos.
botn que est al lado del ttulo

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 cudruple
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 slo necesita los nmeros de entrada (de 4 bits) y el
de salida (de 4 bits tambin). La llevada anterior est deshabilitada y
la de salida se debe ignorar.
1

library ieee;

2
3
4
5
6
7
8
9

use ieee.std_logic_1164.all;
use work.sumador.all;
entity resta is port (
a,b: in std_logic_vector(3 downto 0);
sr: in std_logic;
c: out std_logic_vector(3 downto 0)
);
end resta;

Arquitectura 1: Restador de 4 bits


Para sumar usaremos la librera std_arith, y para restar deberemos
sumar al nmero a el complemento a 2 de b. El indicador de si
sumamos o restamos es la entrada sr.
1
2
3
4
5
6
7
8
9
10
11

architecture archiresta of resta is


signal aux : std_logic_vector(3 downto 0);
begin
process (a,b,sr,aux)
begin
if sr='0' then aux<=b;
elsif sr='1' then aux<=not(b);
end if;
end process;
c<=a+aux+("000"&sr);
end archiresta;

Para complementar un nmero a dos, deberemos invertirlo y sumarle


uno. La sentencia if invierte al nmero b si es necesario. Se le suma
una unidad ms adelante.
Para restar deberemos sumar a, la seal aux y la seal de
suma/resta, para acabar de complementar a dos el nmero b.

Entidad 2: Restador de 4 bits (con LPM_PAKCAGE)


Para crear este restador/sumador de cuatro bits, vamos a usar la
librera LPM_PACKAGE. Es una librera de mdulos parametrizables, la
cual sirve para cualquier anchura de datos de entrada. Slamente
habra que declararla para poder usarla, como se muestra en la
siguiente entidad:
1
2
3
4
5
6
7
8
9
10

library ieee;
use ieee.std_logic_1164.all;
use work.lpmpkg.all;
entity resta is port (
a,b:
in std_logic_vector(3 downto 0);
cin,sr: in std_logic;
c:
out std_logic_vector(3 downto 0);
cout,ov: out std_logic
);
end resta;

Arquitectura 2: Restador de 4 bits


La arquitectura es muy sencilla, ya que slamente requiere conocer
cmo funciona el mdulo madd_sub que es el usado para

sumar/restar. Ello se consigue usando la documentacin que viene


incluido con WARP2, y que se puede consultar aqu.
1
2
3
4
5
6

architecture archiresta of resta is


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

Para complementar un nmero a dos, deberemos invertirlo y sumarle


uno. La sentencia if invierte al nmero b si es necesario. Se le suma
una unidad ms adelante.
Para restar deberemos sumar a, la seal aux y la seal de
suma/resta, para acabar de complementar a dos el nmero b.

Restador de 4 bits
library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
entity resta is port (
a,b: in std_logic_vector(3 downto 0);
sr: in std_logic;
c:
out std_logic_vector(3 downto 0)
);
end resta;
architecture archiresta of resta is
signal aux : std_logic_vector(3 downto 0);
begin
process (a,b,sr,aux)
begin
if sr='0' then aux<=b;
elsif sr='1' then aux<=not(b);
end if;
end process;
c<=a+aux+("000"&sr);
end archiresta;

Restador de 4 bits
library ieee;
use ieee.std_logic_1164.all;
use work.lpmpkg.all;
entity resta is port (
a,b:
in std_logic_vector(3 downto 0);
cin,sr: in std_logic;
c:
out std_logic_vector(3 downto 0);
cout,ov: out std_logic
);
end resta;
architecture archiresta of resta is

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

Un flip flop es un circuito electrnico, llamdo tambin simplemente


biestable, que tiene dos estados estables. El flip flop es un elemento bsico de
memoria que es capaz de almacenar un nmero binario (bit), es decir, que
permanece indefinidamente en uno de sus dos estados posibles aunque haya
desaparecido la seal de excitacin que provoc su transicin al estado actual.

Elige en la lista una prctica


para empezar, sin ms que pinchar en el
botn adecuado. Para volver pulsa el
botn que est al lado del ttulo

Debido a su amplia
utilizacin, 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.

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 necesitaramos bastantes
sumadores totales, lo cual nos llevara a tener nueve circuitos
integrados si lo implementamos fsicamente. El emplear VHDL en la
descripcin de circuitos lgicos nos facilita las tareas de diseo y
adams nos puede disminuir el espacio de placa necesario para su
implementacin y las conexiones empleadas para ello.
Para crear un multiplicador de 3x3 bits, necesitaremos una nica
cpsula, 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 nmero.
1
2
3

library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;

4
5
6
7

entity multiplicador is port(


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

Arquitectura 1: Multiplicador de 3 bits


Para multiplicar, nos basaremos en el mtodo empleado para
multiplicar neros en formato decimal, es decir, se multiplica un
nmero por cada uno de los dgitos del otro teniendo en cuenta el
peso de cada uno. Al ser en binario, y slo haber ceros y unos, el
multiplicar se convierte en un desplazamiento si hay un uno y en una
omisin si hay un cero. Por eso el cdigo de la arquitectura tiene el
aspecto siguiente.
1
2
3
4
5
6
7
8
9
10
11
12
13
14

architecture archimulti of multi is


signal aux1,aux2,aux3: std_logic_vector(5 downto 0);
begin
process (a,b)
begin
if b(0)='1' then aux1 <= ('0', '0', '0', a(2), a(1), a(0));
elsif b(0)='0' then aux1<=(others => '0'); end if ;
if b(1)='1' then aux2 <= ('0', '0', a(2), a(1), a(0), '0' );
elsif b(1)='0' then aux2<=(others => '0'); end if;
if b(2)='1' then aux3 <= ('0', a(2), a(1), a(0), '0', '0' );
elsif b(2)='0' then aux3<=(others => '0'); end if;
end process;
c <=aux1 + aux2 + aux3;
end archimulti;

Hay que destacar que la suma de las seales aux1, aux2 y aux3 se
hace FUERA del proceso, ya que de no ser as, c no se actualizara
correctamente y adoptara el valor del producto anterior.

Entidad 2: Multiplicador de 3 bits (con STD_ARITH)

Esta prctica es ideal para comprobar la potencia de VHDL y de sus


libreras. En el ejemplo anterior, para multiplicar 3x3 bits, se
necesitaba un cdigo muy complejo y nada claro para posteriores
revisiones. En cambio, si usamos la librera std_arith para cargar el
operador * que nos permitir multiplicar dos nmeros de cualquier
longitud, debiendo ser la anchura del resultado la suma de las
anchuras de los operandos.
Para la entidad slo necesitamos declarar los dos nmeros a
multiplicar y el producto, pero queremos que adems de hacernos el
producto de a y b nos sume un nmero d (de la misma anchura que
el producto). Por lo tanto la entidad debe ser como se muestra en el
ejemplo.
1
2
3
4
5
6
7

library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
entity multiplicador is port(
a,b:in std_logic_vector(2 downto 0);
d: in std_logic_vector(2 downto 0);
c:out std_logic_vector(5 downto 0));
end multiplicador;

Arquitectura 2: Multiplicador de 3 bits (con


STD_ARITH)
El ejemplo no poda ser ms sencillo, ya que en una sla lnea
incluimos toda la operatividad que desbamos darle a nuestro
circuito. Esto es posible a que hemos sobrecargado la librera
std_arith.
1
2
3

architecture archimulti of multiplicador


is
begin

c<=(a*b) + d;
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 nmero c necesita mucho propuctos y
sumas lgicas, requiriendo mucho espacio de cpsula.

Entidad 3: Multiplicador de 3 bits (con LPM


PACKAGE)
De nuevo vamos a usar otro de los recursos ms usuales de VHDL,
que es el grupo de libreras LPM Package, que nos permite usar
mdulos 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 ms que cambiar una serie de
parmetros.
Para usar estas libreras deberemos incluir en la declaracin de
libreras la lnea
use work.lpmpkg.all;
Para la entidad slo necesitamos declarar los dos nmeros a
multiplicar y el producto, pero queremos que adems de hacernos el
producto de a y b nos sume un nmero d (de la misma anchura que

el producto). Por lo tanto la entidad debe ser como se muestra en el


ejemplo.

1
2
3
4
5
6
7
8
9
10

library ieee;
use ieee.std_logic_1164.all;
use work.lpmpkg.all;
entity multi is port(
dataA : in std_logic_vector(2 downto
0);
dataB : in std_logic_vector(2 downto
0);
sum : in std_logic_vector(5 downto
0);
result : out std_logic_vector(5 downto
0)
);
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 mdulos, 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
mdulos que se usen. Si no se indica que el mdulo mmult es un
multiplicador/sumador, en una revisin 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 fcil ver qu
resultado obtenemos.
1
2
3
4
5
6
7

use work.lpmpkg.all;
architecture archimulti of multi is
begin
mul: mmult
generic map (3,3,6,6)
port map(dataA,dataB,sum,result);
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 nmero result necesita mucho
propuctos y sumas lgicas, requiriendo mucho espacio de cpsula.
Se debe aclarar que se ha hecho la introduccin de datos al mdulo
mmult por posicin.

Multiplicador de 3 bits
library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
entity multi is port(
a,b: in
std_logic_vector(2 downto 0);
c : buffer std_logic_vector(5 downto 0)
);
end multi;
architecture archimulti of multi is
signal aux1,aux2,aux3: std_logic_vector(5 downto 0);
begin
process (a,b)
begin
if b(0)='1' then aux1 <= ('0', '0', '0', a(2), a(1), a(0));
elsif b(0)='0' then aux1<=(others => '0'); end if ;
if b(1)='1' then aux2 <= ('0', '0', a(2), a(1), a(0), '0' );
elsif b(1)='0' then aux2<=(others => '0'); end if;
if b(2)='1' then aux3 <= ('0', a(2), a(1), a(0), '0', '0' );
elsif b(2)='0' then aux3<=(others => '0'); end if;
end process;
c
<=aux1 + aux2 + aux3;
end archimulti;

Multiplicador de 3 bits (con STD_ARITH)

Un flip flop es un circuito electrnico, llamdo tambin simplemente

biestable, que tiene dos estados estables. El flip flop es un elemento bsico de
memoria que es capaz de almacenar un nmero binario (bit), es decir, que
permanece indefinidamente en uno de sus dos estados posibles aunque haya
desaparecido la seal de excitacin que provoc su transicin al estado actual.

Elige en la lista una prctica


Debido a su amplia
para empezar, sin ms que pinchar en el utilizacin, los flip flops se han
botn adecuado. Para volver pulsa el
convertido en un elemento fundamental
botn que est al lado del ttulo
dentro de los circuitos secuenciales

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 ms simple, y en base a l, se
disean flip flops ms 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).

1
2
3
4
5
6
7
8

clk

library ieee;
use ieee.std_logic_1164.all;
entity flipfloRS is port (
r,s,clk: in std_logic;
q:
buffer std_logic;
notq:
out std_logic
);
end flipfloRS;

Se define como entradas las


seales s, r y la seal de reloj
clk, La.senal de salida q, se
define como buffer para
poder emplear su valor, y
asignarselo a la seal de
salida notq

Arquitectura 1: Flip Flop RS


Cuando la seal de entrada set (s) esta activa a nivel lgico uno, la
seal de salida q pasa a valer uno, si la entrada reset U(r) es la que
esta activa a nivel lgico uno,la salida q pasa a valer uno. Nunca se
puede dar el caso de que esten activas simultaneamente las dos
seales de entrada, r y s.
1
2
3
4
5
6
7
8
9
10
11
12
13

architecture archiflipfloRS of flipfloRS


is
begin
process (clk)
begin
if (clk'event and clk='1') then
if (r='1')and(s='0') then q <= '0';
elsif (r='0')and(s='1')then q <='1';
end if;
end if;
end process;
notq <= not q;
end archiflipfloRS;

La asignacin del valor


de la seal notq debe
de hacerse a la salida
del proceso, para que la
seal q, ya haya
actualizado su valor.

Es reseable de esta arquitectura la utilizacin de la sentencia event,


que detecta cuando cambia la seal a la que esta 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 seal 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 seales de reloj (clk) y de


informacin (d), siendo activa por flanco de subida. Como salida se
tiene al puerto q.

1
2
3
4
5
6
7

clk

library ieee;
use ieee.std_logic_1164.all;
entity flipflopd is port (
d,clk: in std_logic;
q : out std_logic
);
end flipflopd;

Esta entidad es muy sencilla ya que las entradas y la salida son de un


nico bit de ancho.

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
2
3
4
5
6
7
8

architecture archiflipflopd of lipflopd is


begin
process (clk)
begin
if (clk'event and clk='1') then q <= d;
end if;
end process;
end archiflipflopd;

En este diseo, solo se


especifica que pasa
con la salida q cuando
hay un flanco de
subida, quedando sin
especificar que sucede
con q si no se da ese
flanco.

En la lne 5 tenemos un caso de memoria implcita ya que solamente


se especifca que se debe hacer con la seal de salida q cuando
aparece un flanco de subida en la seal 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
seales de entrada J=K=1, en el caso del flip flop RS, esta asignacin
de los valores de las entradas estaban prohibidas en el caso del
RS,sin embargo aqu en el JK, se dar la funcin basculamiento,

clk

1
2
3
4
5
6
7
8
9
10
11

notq

library ieee;
use ieee.std_logic_1164.all;
use work.rtlpkg.all;
entity ffjk is
port (
j : in std_logic;
k : in std_logic;
clk : in std_logic;
q : out std_logic
);
end ffjk;

En el flip flop JK, las entradas


J K son anlogas a las
entradas set (s) y reset (r),
respectivamente.

Arquitectura 3: Flip Flop JK

El flip flop JK es el ms 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 funcin set y la entrada K la funcin reset .
La principal diferencia entre ambos es que J y K pueden valer uno

simultneamente, a diferencia del flip flop RS, en este caso la salida


cambia de estado, pasando a valer lo contrario de lo que vala
antes.Es el basculamiento

1
2
3
4
5
6
7

architecture archffjk of ffjk is


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

En este ejemplo, se ha implementado un flip flop JK, basndonos en la


operatividad de un flip flop d, previamente descrito en la librera
rtlpkg.Esto se hace atravs de la utilizacin de las seales 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

1
2
3
4
5
6
7

library ieee;
use ieee.std_logic_1164.all;
entity tff is port (
t, clk : in std_logic;
q
: buffer std_logic
);
end tff;

not q

En el flip flop T, las nicas


entradas seran la seal de
reloj, clk, y la seal t,
dandonos por salida q.

Arquitectura 4: Flip Flop T


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

1
2
3
4
5
6

architecture architff of tff is


begin
process (clk) begin
if (clk'event and clk = '1') then
if (t = '1') then q <= not(q);

Si la entrada de
control t esta a
nivel lgico alto el
flip flop bascula, si
esta a nivel bajo,
mantiene su valor

7
8
9
10

else q <= q;
end if;
end if;
end process;
end architff;

Flip Flop RS
library ieee;
use ieee.std_logic_1164.all;
entity flipfloRS is port (
r,s, clk: in std_logic;
q: buffer std_logic;
notq: out std_logic
);
end flipfloRS;
architecture archiflipfloRS of flipfloRS is
begin
process (clk)
begin
if (clk'event and clk='1') then
if (r='1')and(s='0') then q <= '0';
elsif (r='0')and(s='1')then q <='1';
end if;
end if;
end process;
notq <= not q;
end archiflipfloRS;

Flip Flop D
--flip-flop tipo d
library ieee;
use ieee.std_logic_1164.all;
entity flipflopd is port (
d, clk: in std_logic;
q: out std_logic
);
end flipflopd;
architecture archiflipflopd of flipflopd is
begin
process (clk)
begin
if (clk'event and clk='1') then q <= d;
end if;
end process;
end archiflipflopd;

Flip Flop JK

anterior.

--Declaracin de un flip flop JK


library ieee;
use ieee.std_logic_1164.all;
USE WORK.rtlpkg.ALL;
ENTITY ffjk IS
PORT (
j
: IN std_logic;
k
: IN std_logic;
clk
: IN std_logic;
q
: OUT std_logic
);
END ffjk;
ARCHITECTURE archffjk OF ffjk IS
SIGNAL qx, dx : std_logic;
BEGIN
dx <= (j and not(qx)) or (not(k)
q
<= qx;
d1:dff port map(dx,clk,qx);
END archffjk;

-----

J input to J-K register.


K input to J-K register.
Positive edge Clock.
Qutput from register.

and qx);

Flip Flop T
--flip flop t
library ieee;
use ieee.std_logic_1164.all;
entity tff_logic is port (
t, clk : in std_logic;
q
: buffer std_logic
);
end tff_logic;
architecture t_example of tff_logic is
begin
process (clk)
begin
if (clk'event and clk = '1') then
if (t = '1') then
q <= not(q);
else
q <= q;
end if;
end if;
end process;
end t_example;

Un contador es un dispositivo lgico snrono o asncrono, en cuyas


salidas tenemos un nmero que va creciendo o decreciendo a intervalos regulares
segn lo hayamos especificado nosotros. Suelen contar as mismo con entrada de
reset y preset (a partir de que nmero se cuenta).

Elige en la lista una prctica


Los comparadores pueden
para empezar, sin ms que pinchar en el contar tanto en binario natural, BCD,
botn adecuado. Para volver pulsa el
octal,... y contar de uno en uno, de dos
botn que est al lado del ttulo
en dos,...

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 ningn tipo de control,
ya que cuenta de 0 a 15 una vez tras otra, sin poder influir sobre ello,
ms 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;
use ieee.std_logic_1164.all;
use work.std_arith.all;

Declaracin de libreras para usar


el tipo std_logic y para poder
usar el signo + para sumar

entity contador is port(


clk:
in std_logic;
conta: buffer std_logic_vector(3
downto 0)
);
end contador;

Declaracin de la entrada de reloj


(clk), y de la salida conta.

architecture archicontador of contador


is
begin
process (clk)
En el flanco de subida del reloj, se
begin
ejecuta lo que sigue al then:
if (clk'event and clk= '1') then
sumar 1 a la seal 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 ms
comentarios, ya que iremos aadiendo operatividad a medida que
avancemos en esta prctica.

Ejercicio 2: Contador ascendente con carga


Este contador se diferencia del anterior en que le podremos indicar
a partir de qu nmero queremos que empiece a contar, por lo que
deberemos aadirle una entrada para el nmero en cuestin y otra
par indicarle que queremos que lo use.
library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;

Declaracin de libreras para usar


el tipo std_logic y para poder
usar el signo + para sumar

entity contador is port(


clk, load:in std_logic;
data: in std_logic_vector(3 downto
0);
conta:buffer std_logic_vector(3
downto 0)
);
end contador;

Declaracin de la entrada de reloj


(clk), y de la salida conta. Ahora
le aadimos la entrada load que
indica que si queremos que
empiece a contar a partir del
nmero data

architecture archicontador of contador


is
begin
process (clk)
Ahora, si hay un flanco de subida
begin
en clk, primero se comprueba si
if (clk'event and clk= '1') then
se pide contar a partir cierto
if load = '1' then
nmero (si load est habilitada), y
conta <= data;
si es as, el contador se inicializa
else
con el valor de data. Si no lo es,
conta <= conta + 1;
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
programacin, cierra primero la ltima sentencia if en abrirse.

Ejercicio 3: Contador ascendente con carga y reset


A este contador le hemos aadido ahora una seal de reset
(asncrono), que har que el contador se ponga a cero mientras dure
este pulso. Una vez acabado la inicializacin vuelve a cmprobar si se
le pide que cuente a partir de load, o si cuenta normalmente.
library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;

Declaracin de libreras para usar


el tipo std_logic y para poder
usar el signo + para sumar

entity contador is port(


clk, load, reset:in std_logic;
data: in std_logic_vector(3 downto
0);
conta:buffer std_logic_vector(3
downto 0)
);
end contador;

Declaracin de la entrada de reloj


(clk) y de la carga (load y data).
Ahora le aadimos la seal de
reset. Conta es la salida.

architecture archicontador of contador


is
Ahora, si hay un flanco de subida
begin
en clk, o hay un cambio en la
process (clk,reset)
seal reset, primero se
begin
comprueba si esta ltima ha sido
if reset = '1' then
habilitada, lo cual hace que conta
conta <= "0000";
se ponga a "0000". Si lo que ha
elsif (clk'event and clk= '1') then
cambiado ha sido la seal clk
(reloj), se siguen los mismos
if load = '1' then
pasos que antes: se verifica si se
conta <= data;
pide contar a partir cierto nmero
else
(si load est habilitada), y si es
conta <= conta + 1;
as, el contador se inicializa con el
end if;
valor de data. Si no lo es, se le
end if;
suma 1 a la salida
end process;
end archicontador;
Si el contador llega a "1111", y le sumamos uno, la salida que
obtengamos ser "0000", ya que automticamente VHDL realiza la
operacin de despreciar el overflow que se dara, 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 cdigo del contador anterior par que
segn le indiquemos con una seal nueva, llamada arriba, cuente
hacia arriba como hacia abajo, segn le digamos. Esta seal basta
con que sea de un solo bit.

library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;

Declaracin de libreras para usar


el tipo std_logic y para poder
usar el signo + para sumar

entity contador is port(


clk, load, reset,arriba:in std_logic;
data: in std_logic_vector(3 downto
0);
conta:buffer std_logic_vector(3
downto 0)
);
end contador;

Declaracin de la entrada de reloj


(clk), de la carga (load y data),
la seal de reset y adems la que
indica si cuenta hacia arriba como
hacia abajo. Conta es la salida.

architecture archicontador of contador


is
Ahora, si hay un flanco de subida
begin
en clk, o hay un cambio en la
process (clk,reset)
seal reset, primero se
begin
comprueba si esta ltima ha sido
habilitada, lo cual hace que conta
if reset = '1' then
se ponga a "0000". Si lo que ha
conta <= "0000";
cambiado ha sido la seal clk
elsif (clk'event and clk= '1') then
(reloj), se verifica si se pide contar
if load = '1' then
a partir cierto nmero (si load
conta <= data;
est habilitada), y si es as, el
elsif arriba = '1' then
contador se inicializa con el valor
conta <= conta + 1;
de data. Si no lo es, se analiza si
se le pide contar hacia arriba o
else conta <= conta - 1;
hacia abajo, sumndole 1 a la
end if;
salida o restndoselo,
end if;
respectivamente.
end process;
end archicontador;
Deberemos tener en cuidado en este caso, ante la cantidad de if's
y de elsif, dentro de cul de ellos estamos, a la hora de cerrarlos o de
asignar cambios a seales, ya que el resultado puede ser distinto al
que queramos.

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;
use ieee.std_logic_1164.all;
use work.std_arith.all;

Declaracin de libreras para usar


el tipo std_logic y para poder
usar el signo + para sumar

entity contador is port(


clk, load, reset,arriba:in std_logic;
data: in std_logic_vector(3 downto
0);
conta:buffer std_logic_vector(3
downto 0)
);
end contador;

Declaracin de la entrada de reloj


(clk), de la carga (load y data),
la seal de reset y adems la que
indica si cuenta hacia arriba como
hacia abajo. Conta es la salida.

architecture archicontador of contador


is
begin
Ahora, si hay un flanco de subida
process (clk,reset)
en clk, o hay un cambio en la
begin
seal reset, primero se
comprueba si esta ltima ha sido
if reset = '1' then
habilitada, lo cual hace que conta
conta <= "0000";
se ponga a "0000". Si lo que ha
elsif (clk'event and clk= '1') then
cambiado ha sido la seal clk
if load = '1' then
(reloj), se verifica si se pide contar
conta <= data;
a partir cierto nmero (si load
elsif arriba = '1' then
est habilitada), y si es as, el
if conta = "1001" then
contador se inicializa con el valor
de data. Si no lo es, se analiza si
conta <= "0000";
se le pide contar hacia arriba o
else conta <= conta + 1;
hacia abajo. Antes de sumarle
end if;
uno, comprueba si hemos llegado
else
al lmite (9), y si lo hemos hecho,
if conta = "0000" then
se pone conta a "0000", si no es
conta <= "1001";
as, le suma uno. Realiza la misma
else conta <= conta - 1;
operacin pero comprobando si
hemos llegado al otro lmite (0), y
end if;
si es as, pone conta a "1001". Si
end if;
no lo es se resta uno a la salida.
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.

Contador ascendente
library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
entity contador is port(
clk:
in std_logic;
conta: buffer std_logic_vector(3 downto 0)
);
end contador;
architecture archicontador of contador is
begin
process (clk)
begin
if (clk'event and clk= '1') then
conta <= conta + 1;
end if;
end process;
end archicontador;

Contador ascendente con carga


library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
entity contador is port(
clk, load:in std_logic;
data:
in std_logic_vector(3 downto 0);
conta:buffer std_logic_vector(3 downto 0)
);
end contador;
architecture archicontador of contador is
begin
process (clk)
begin
if (clk'event and clk= '1') then
if load = '1' then
conta <= data;
else
conta <= conta + 1;
end if;
end if;
end process;
end archicontador;

Contador ascendente con carga y reset


library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
entity contador is port(
clk, load, reset:in std_logic;

data:
in std_logic_vector(3 downto 0);
conta:buffer std_logic_vector(3 downto 0)
);
end contador;
architecture archicontador of contador is
begin
process (clk,reset)
begin
if reset = '1' then
conta <= "0000";
elsif (clk'event and clk= '1') then
if load = '1' then
conta <= data;
else
conta <= conta + 1;
end if;
end if;
end process;
end archicontador;

Contador ascendente/descendente con carga y reset


library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
entity contador is port(
clk, load, reset,arriba:in std_logic;
data:
in std_logic_vector(3 downto 0);
conta:buffer std_logic_vector(3 downto 0)
);
end contador;
architecture archicontador of contador is
begin
process (clk,reset)
begin
if reset = '1' then
conta <= "0000";
elsif (clk'event and clk= '1') then
if load = '1' then
conta <= data;
elsif arriba = '1' then
conta <= conta + 1;
else conta <= conta - 1;
end if;
end if;
end process;
end archicontador;

Contador BCD
library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
entity contador is port(

clk, load, reset,arriba:in std_logic;


data:
in std_logic_vector(3 downto 0);
conta:buffer std_logic_vector(3 downto 0)
);
end contador;
architecture archicontador of contador is
begin
process (clk,reset)
begin
if reset = '1' then
conta <= "0000";
elsif (clk'event and clk= '1') then
if load = '1' then
conta <= data;
elsif arriba = '1' then
if conta = "1001" then
conta <= "0000";
else conta <= conta + 1;
end if;
else
if conta = "0000" then
conta <= "1001";
else conta <= conta - 1;
end if;
end if;
end if;
end process;
end archicontador;

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 lgicos para las
mismas entradas de contro. Emplearemos el principio de los circuitos secuensiales
para implementar un circuito cuyas salidas variaran en funcin del tiempo

Elige en la lista una prctica


Nuestro secuenciador utiliza
para empezar, sin ms que pinchar en el
un
contador
y
un decodificador 2/4
botn adecuado. Para volver pulsa el
previamente
definidos
como
botn que est al lado del ttulo

componentes en una librera


personalizada, invocada desde el fichero
de descripcin.

Decodificador 2/4

Decodificador 2/4

Contador

Contador

Secuenciador

Secuenciador

Entidad 1: Decodificador 2/4


El decodificador 2/4 tiene dos seales de control, que en nuestra
entidad, viene dada por la seal de seleccin . Como salida un vector
de longitud cuatro y dos entradas de habilitacin (enable).

1
2
3
4
5
6
7
8

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;

Es necesario poner en
la cabecera del cdigo,
la llamada a la librera
"uno", que es donde
guardaremos a este
decodificador como un
componente.

Arquitectura1: Decodificador 2/4


El decodificador basa su operatividad en dos seales de control
"seleccion", con las que seleccionamos la salida que queremos que
sea activa a nivel alto. Segun sea el valor que tome dicha seal de
"seleccion", se eligira una salida u otra.
1
2
3
4
5
6
7
8
9

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');
elsif(enable1='1') then
case seleccion is
when "00" => salida <= "0001";
when "01" => salida <= "0010";

El
decodificad
or es
activado
atravez de
sus dos
seales de
enable.
Enable1 va
conectada
a la seal

10
11
12
13
14
15
16
17
18

when "10" => salida <= "0100";


when "11" => salida <= "1000";
when others => salida <="1111";
end case;
en if;
end process decodificador;
end archidecoder;

de reloj,
para que el
funcionami
ento del
codificador
se
sincronice a
dicha seal.
Enable2,
har las
veces de un
abilitador
normal.

El habilitador de entrada de este decodificador, enable1 y enable2, le


confiere a este diseo 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 seales dereloj (clk) y de
informacin (d), siendo activa por flanco de subida. Como salida se
tiene al puerto q.

1
2
3

library ieee;
use ieeee.std_logic_1164.all;
use work.std_arith.all;

4
5
6
7
8

use work.uno.all;
entity count is port (
clk,reset:in bit;
conya :buffer std_logic_vector(1 downto
0));
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.

Arquitectura 2: Contador
Un contador es un circuito secuencial que repite su estado cada cierto
nmero de pulsos de reloj. El nmero de estados por los que pasa
antes de volver al mismo estado se llama "modulo".

1
2
3
4
5
6
7
8
9
10
11

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;

Estas dos entidades, tanto el contador como el decodificador, estarn


incluidas dentro de un paquete o Package para poder hacer uso de
ellos atravs de la utilizacin de dichos elementos como
componentes. Ambos circuitos sern guardados dentro de la librera
personalizada "uno".A continuacin se lista el cdigo de este paquete

A continuacin se edita el paquete (package) "uno" donde se guarda


como componentes tanto el contador como el decodificador. Estos
elementos sern posteriormente llamados para formar parte del
diseo completo del secuenciador que ha sido diseado dentro de
"total".

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
package uno is
component
count port (
clk,reset:in bit;
conta :buffer std_logic_vector(1 downto 0));
end component;
component
decoder port (
seleccion
:in std_logic_vector(1 downto 0);
enable1,enable2:in bit;
salida
:out std_logic_vector(3 downto 0));
end component;
end package;
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;
--descripcion del decodificador 3/8 (74ls138)
library ieee;
use ieee.std_logic_1164.all;
use work.uno.all;

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

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;
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');
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;

La especificacin 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 librera. A continuacin aparece la declaracin de las
entidades y arquitecturas de cada uno de los componentes de forma
similar a como se declara un circuito cualquiera, la nica aclaracin a
tener en cuenta sera que habra que incluir necesariamente la
sentencia use work.uno.all; donde se especifca el nombre de la
librera en la que estamos.

Entidad 3: Secuencaidor
En esta practica se parte de la grfica siguente. Las especificaciones
del diseo nos pide que creemos un circuito que se ajuste al
comportamiento de la siguente grfica.

Tras el anlisis de los requerimientos, se disea 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.

1
2
3
4
5
6
7

library ieee;
use ieee.std_logic_1164.all;
use work.uno.all;
entity total is port(
clk,reset:in bit;
salida:out std_logic_vector(3 downto
0));
end total;

Arquitectura 3: Secuenciador

En esta parte se unen el contador y el decodificador antes descrito,


para conseguir el comportamiento del secuenciador previamente
diseado. Para ello se hace uso de la seal intermedio, que nos sirve
para pasar las seales propias del count y llevarlas a la entrada del
decoder.
1
2
3
4
5
6

architecture architotal of total is


signal intermedio:std_logic_vector(1 downto 0);
begin
bloque1:count port map(clk,reset,intermedio);
bloque2:decoder port map(intermedio,clk,reset,salida);
end architotal;

Decodificador 2/4
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;
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
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;

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

=> '0');

architecture archicuad of cuad 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 archicuad;

Secuenciador
--EN ESTE FICHERO SE LLAMA A LAS LIBRERIAS DECLARADAS EN EL FICHERO
UNO
library IEEE;
use ieee.std_logic_1164.all;
use work.uno.all;
entity total IS PORT (
clk,reset:in bit;
salida:out std_logic_vector(3 downto 0));
end total;
architecture architotal of total is
SIGNAL intermedio:std_logic_vector(1 downto 0);
BEGIN
bloque1:octal port map(clk,reset,intermedio);
bloque2:decoder port map(intermedio,clk,reset,salida);
end architotal;

Unidades Bsicas de Diseo


Como se declara una Entidad 12 Como se declara una
Arquitectura
Paquetes 34 Librera LPM (Library of
parametrized
modules)

Como se declara una Entidad

En la declaracin de entidades, se definen las entradas, salidas y


tamao de un circuito, explicitando cuales son, de qu tamao (de 0 a
n bits), modo (entrada, salida, ...) y tipo (integer, bit,...) . Las

entidades pueden definir bien las entradas y salidas de un diseo ms


grande o las entradas y salidas de un chip directamente. La
declaracin de entidades es anloga al smbolo esquemtico 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 declaracin
de entidades tiene la siguiente forma:
entity circuito_a is
port(
-----

puertos
puertos
puertos
puertos

de
de
de
de

entradas
salidas
I/O
buffers

);
end circuito_a;

Cabecera del programa


Se indica que a continuacin viene los
puertos (o grupos seales) de entrada y/o
salida
Aqu se declaran las entradas y/o salidas con
la sintaxis que se ver a continuacin. Las
lneas empezadas por dos guiones son
ignoradas por el compilador. As mismo,
recordamos que el compilador no distingue
las maysculas de las minsculas
Se indica que se ha acabado la declaracin de
puertos de entrada y/o salida, y que se ha
acabado la entidad

Como hemos dicho, cada seal en una declaracin de entidad est


referida a un puerto (o grupo de seales), el cual es anlogo a un(os)
pin(es) del smbolo esquemtico. Un puerto es un objeto de
informacin, el cual, puede ser usado en expresiones y al cual se le
pueden asignar valores. A cada puerto se le debe asignar un nombre
vlido. A continuacin se exponen algunos ejemplos:
nombre_variable: modo tipo;

Forma genrica de designar un puerto

puertoa: in bit;

El primer puerto es un bit de entrada, y


su nombre es "puertoa"

puertob: in bit_vector(0 to 7);


puertoc: out bit_vector(3 downto
0);

El segundo puerto es un vector de 8


bits de entrada siendo el MSB el
puertob(0) y el LSB el puertob(7)
El tercer puerto es un vector de 4 bits
de salida siendo el MSB el puertoc(3) y
el LSB el puertoc(0)

puertod: buffer bit;

El cuarto puerto es un buffer de un solo


bit, cuyo nombre es "puertod"

puertoe: inout std_logic;

El quinto puerto es una entrada/salida


del tipo estndar 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 direccin en la cual la
informacin es transmitida a travs 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 informacin


correspondiente al mismo, entra a la entidad y se suele usar para
relojes, entradas de control (como las tpicas load, reset y enable), y
para datos de entrada unidireccionales.
Modo out: Un puerto es de modo out si la informacin fluye hacia
fuera de la entidad. Este modo no permite realimentacin ya que al
declarar un puerto como out estamos indicando al compilador que el
estado lgico en el que se encuentra no es leble. Esto le da una
cierta desventaja pero a cambio consume menos recursos de
nuestros dispositivos lgicos programables.
Modo buffer: Es usado para una realimentacin interna ,es decir,
para usar este puerto como un driver dentro de la entidad. Este modo
es similar al modo out, pero adems, permite la realimentacin y no
es bidireccional, y solo puede ser conectado directamente a una seal
interna, o a un puerto de modo buffer de otra entidad. Una aplicacin
muy comn 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 seales bidireccionales, es decir, si
necesitamos que por el mismo puerto fluya informacin tanto hacia
dentro como hacia afuera de la entidad. Este modo permite la
realimentacin interna y puede reemplazar a cualquiera de los modos
anteriores, pudindose usar este modo para todos los puertos, pero
reduciremos la lectura posterior del cdigo por otra persona, y
reduciendo los recursos disponibles de la dispositivo.
Como se ha comentado ms arriba, el lenguaje slo admite cuatro
modos para los puertos, pero puede haber tantos tipos de seales
como queramos, ya que los podemos crear nosotros mismos. VHDL
incorpora varios tipos de forma estndar (por haber sido creado as),
pudiendo usar otros definidos en libreras 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 tpico es la salida de un comparador que da
verdadero si los nmeros comparados son iguales y falso si no lo son:
equal:out boolean;

Slo puede tomar dos valores: verdadero o falso,


y es de salida (darle mas operatividad a la salida
de un comparador sera superfluo)

Tipo bit: Puede tomar dos valores: 0 1 ( o tambin "low" o "high",


segn se prefiera). Es el tipo ms 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 segn pongamos la
palabra reservada downto o to estaremos diciendo que el bit ms
significativo es el nmero ms alto o el ms bajo del vector,
respectivamente..
numero : bit_vector (0 to 7);

En este caso el MSB es numero(0) y


numero(7) el LSB

numero : bit_vector (7 downto En este caso el MSB es numero(7) y


numero(0) el LSB
0);
Tipo integer: Para manejar nmeros enteros. Hay que advertir que
el uso de enteros consume muchos recursos del dipositivo de lgica
programable, siempre y cuando sea sintetizable, debido a que est
prcticamente creado para la simulacin.
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 lgico estndar, que es el ms usado en la actualidad, as como
en la mayora de ejemplos de este libro.
Como ejemplo, a continuacin se incluye la declaracin de una
entidad correspondiente a un multiplexor de 2x1 de cuatro bits, con
entrada de habilitacin o enable. El multiplexor necesita las entradas
de informacin, la seal de seleccin, la de enable y las salidas de
informacin.
entity multi is port (

enable: in bit;
selec: in bit;
in1: in bit_vector(3 downto
0);
in2: in bit_vector(3 downto
0);
out1:out bit_vector(3
downto 0)

);
end multi;

Cabecera ya estudiada arriba, en la que


multi es el nombre de la entidad

enable es un bit de entrada


(suficiente para habilitar o no)

selec es otro bit de entrada, que


selecciona la entrada in1 o in2,
ambas de 4 bits

out1 es de salida, que lgicamente,


debe ser de la misma longitud que in1
e in2

Notes que el ltimo puerto no lleva punto


y coma al final de la lnea. Si lo llevase
estara incorrecto

A continuacin se muestra otro ejemplo correspondiente a la


entidad para un comparador:

entity compa is port (


a,b: in bit_vector(3 downto
0);
igual: out bit;
);
end compa;

Cabecera de la entidad, cuyo nombre es


compa

a y b son las entradas de cuatro bits

igual es la salida de un slo bit

Se finaliza la entidad con la palabra clave


end y el nombre de la misma (compa).

Debemos recordar dos puntos ms a la hora de dar el nombre a


algn puerto, que se tratarn ms adelante en el aprtado de objetos:
VHDL no distingue las letras maysculas de las minsculas, 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 prctica
donde se demuestra esto.
El primer carcter de un puerto slo puede ser una letra, nunca un
nmero. 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 caracterstica ms del
lenguaje.

Como se declara una Arquitectura

La arquitectura indica el tipo de procesado que se realiza con la


informacin correspondiente a las seales de entrada, (declarados
previamente en la entidad) para llegar a tener los puertos de salida
(tambin declarados en la entidad). En la declaracin 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 declaracin de arquitecturas debe constar de las siguientes
partes como mnimo, aunque suelen ser ms:

architecture archpro of
programa is
-- declaracin de seales y otros
accesorios
begin
-- ncleo del programa
end archpro;

Cabecera de la arquitectura. En sta,


archpro es un nombre cualquiera (suele
empezar por "arch", aunque no es
necesario) y programa es el nombre de
una entidad existente en el mismo
fichero
Declaraciones de apoyo, que se vern en
la pgina siguiente
Se da comienzo al programa
Conjunto de sentencias, bucles,
procesos, funciones,... que dan
operatividad al programa.
Fin del programa

Como podemos apreciar, es una estructura muy sencilla, y que


guarda alguna relacin 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 electrnico como cualquier otro que trate sobre VHDL. A
continuacin, se muestra el cdigo fuente de un programa en VHDL
de un multiplexor (esta es una de las mltiples formas de
implementar un multiplexor en VHDL), el cual debe ir unido a la
entidad expuesta en el apartado de la declaracin de entidades, ya
que una parte sin la otra carecen de sentido.

architecture archimulti of multi


is
-- seales
begin
process(enable,in1,in2)
begin
if enable='0' then
out1<="1111";
elsif enable='1' then
if(selec = '0') then out1<=in1;
elsif(selec = '1') then
out1<=in2;
end if;
end if;
end process;
end archimulti;

Cabecera de la arquitectura. En esta


ocasin el nombre de la arquitectura es
archimulti, y el de la entidad es multi,
la cual est definida anteriormente.
En este programa no se necesitan
seales
Comienza al programa

Sentencias que hacen que la entidad


definida como multiplexor realice la
funcin propia de su nombre. Solo hay
que entender la estructura de las
arquitecturas en estos momentos, por lo
que este cdigo no debe ser objeto de
preocupacin.

Fin del programa

Para describir una arquitectura podremos usar cuatro estilos,


teniendo cada uno, su propio nivel de abstraccin. Los estilos son:
Estilo behavioral o comportamiento: Este estilo se caracteriza
por incluir las sentencias y rdenes tpicas de un lenguaje de

programacin (if, then, case,...), sin importarnos como quedar la


distribucin de puertas lgicas dentro de la PLD. Es necesario un
proceso al ser una estructura secuencial. El siguiente fragmento de
cdigo 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
Como se puede apreciar en este ejemplo
comp: process (a, b)
se utilizan los clsicos if then else de
begin
cualquier lenguaje de programacin, y
if a= b then
adems las asignaciones son
igual<='1';
secuenciales. Esto es lo que hace esta
else
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 cmo la informacin
ser transferida de seal a seal 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
begin
igual<='1' when (a=b) else '0';
end dataflow1;
architecture dataflow2 of compa
is
begin
igual<= not(a(0) xor b(0))
and not(a(1) xor b(1))
and not(a(2) xor b(2))
and not(a(3) xor b(3));
end dataflow2;

Esta arquitectura es del estilo dataflow


porque se especifica como la
informacin pasar a la salida sin usar
sentencias secuenciales

Aqu de nuevo las asignaciones son


concurrentes, no secuenciales.

Estilo structural o estructural: En l se describe un "netlist" de


VHDL, en los cuales los componentes son conectados y evaluados
instantneamente mediante seales. No se suele usar este estilo
nicamente en una arquitectura ya que resulta muy lioso y difcil de
modificar, siendo de verdadera utilidad cuando debemos crear una
estructura grande y deseamos descomponerla en partes para
manejarla mejor, y para hacer la simulacin de cada parte ms

sencilla. Se suele requerir el uso de seales auxiliares, y adems


paquetes y libreras 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
u0: xnor2 port map (a(0),b(0),x(0));
u1: xnor2 port map (a(1),b(1),x(1));
u2: xnor2 port map (a(2),b(2),x(2));
u3: xnor2 port map (a(3),b(3),x(3));
u4: and4 port map
(x(0),x(1),x(2),x(3),igual);
end struct;

Aqu solo se interconexionan


salidas con entradas de
componentes. La salida
viene dada por la
operatividad de los
componentes, la cual no se
puede saber si no
conocemos el paquete del
cual ha sido leda.

Estilo mixto: Es el estilo que est compuesto en mayor o menor


medida de dos o ms de los estilos descritos anteriormente.
Deberemos tener en cuenta que el cdigo VHDL que escribamos no
siempre va a describir una funcin de forma ptima, la cual no
siempre va a poder ser reducida por la herramienta de compilacin.
Esto se traduce en un peor aprovechamiento de los recursos de las
PLD's. Por lo tanto, diferentes diseos producen diferentes, aunque
equivalentes, ecuaciones de diseo, pudindose dar, sin embargo,
disposiciones diferentes de los recursos.
Es habitual el usar el estilo estructural para descomponer un
diseo en unidades manejables,siendo cada unidad diseada por
equipos de trabajo distintos. El estilo estructural se usa adems para
tener un grado de control alto sobre la sntesis.
Para concluir el apartado dedicado a las arquitecturas slo 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 compilacin.

Paquetes

Un diseador de Hardware que utilice frecuentemente la misma


tecnologa de diseo ha de hacerse, con el paso del tiempo, con una
resea 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 diseo de diferentes circuitos sin ser repetidas en la declaracin de
cada uno.
La estructura bsica en la declaracin de un paquete est dividida
en dos partes claramente diferenciadas:
La declaracin del paquete, package: donde obtenemos una visin
externa y simplificada del componente. La declaracin del paquete va
precedida por la palabra reservada package y finaliza con end. En el
cuerpo de la declaracin nos encontramos con procedures, funciones,
componentes, etc. tal y como apareceran en la parte de la
declaracin de una entidad.
package nombre_del_package
is
-- declaracin de procedures
-- declaracin de funciones
-- declaracin de tipos, etc...

Esta parte es a una entidad, lo mismo que


un paquete es a un programa normal en
VHDL.

end nombre_del_package;

La declaracin del cuerpo del paquete, package body: especifica


el funcionamiento de procedures, funciones, tipos, etc. que nos
permite su implementacin, de forma similar a la arquitectura. Debe
llevar las palabras reservadas package body.
package body
nombre_del_package is
-- definicin de procedures
-- definicin de funciones
-- definicin de tipos, etc.

Esta parte se corresponde con una


arquitectura.

end nombre_del_package;
Todo esto hace posible que una vez declarados los subprogramas
dentro de un package, podamos utilizarlos haciendo nicamente uso
de una llamada al proceso, asignndole un nombre y la lista de
parmetros necesarios.
Para poder usar o llamar a un package que ha sido descrito
anteriormente, debemos incluir la clusula 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 librera 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, haramos uso de la palabra all de la siguiente
forma:
use work.nombre del package.all;
Como ejemplo se muestra a continuacin la declaracin de un
package que contiene a dos componente, un contador y un
decodificador.
--Primero se declaran las libreras que se van a emplear
library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;
--Empieza la declaracin 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 (
seleccion
:in std_logic_vector(1 downto 0);
enable1,enable2:in bit;
salida
:out std_logic_vector(3 downto 0));
end component;
end package;
--Declaracin 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;
--Declaracin 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;
--Descripcin 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');
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;

Librera LPM (Library of parametrized


modules)
La LPM fue propuesto en 1990 como una extensin del estndar
Electronic Design Interface Format (EDIF) para permitir al diseador
crear un circuito completo con independencia de la arquitectura,
separando las partes fsicas y lgicas del diseo
Cada componente en la librera esta definido por unos parmetros,
que le permiten al diseador de hardware representar una amplia
variedad de variables lgicas, evitando la repeticin del trabajo.
Un diseo basado en la utilizacin de la librera LPM (library of
parametrized modules) combina simultneamente, los aspectos
propios de un diseo en alto nivel, con las mejoras propias de la
sntesis en bajo nivel. Debido a que los componentes descritos en
esta librera son aceptados por lo fabricantes, su consumo de los
recurso internos viene previamente optimizado.
La librera LPM System Library, en la cual se nos ofrecen mltiples
mdulos, ya creados, puede facilitarnos enormemente nuestro
trabajo, ya que incluye desde el generador de constantes ms sencillo
hasta contadores y multiplicadores con todas las caractersticas
opcionales posibles. La lista de componentes incluida en esta es la
siguiente:
Nombre del paquete Nombre del componente
MCCSTNT Mdulo de constantes
MINV Mdulo de inversores
MAND Mdulo de AND's
MOR Mdulo de OR's
MXOR Mdulo de XOR's

MBUSTRI Mdulo de bus triestado


MMUX Mdulo de multiplexores
MDECODE Mdulo de decodificador
MADD_SUB

Mdulo de
sumadores/restadores

MCOMPARE Mdulo de comparadores


MMULT Mdulo de multiplicadores
MCOUNTER Mdulo de contadores
MLATCH Mdulo de latches
MFF Mdulo de flip-flops
MSHFTREG Mdulo de registros

Para usar cualquiera de stos mdulos, slamente deberemos


incluir en nuestro fichero de cdigo la siguiente lnea, encima de la
declaracin 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
adems sumarle otro nmero de ocho bits (s) al resultado. Para ello
deberemos invocar previamente a la librera lpmpkg tal y como
habamos dicho:
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 0);
s: in std_logic_vector(7 downto 0);
p: out std_logic_vector(7 downto 0)
);
end multi_lpm;
use work.lpmpkg.all;
architecture archimulti of multi_lpm
is
begin
a0: mmult generic map(4,4,8,8)
port map(a,b,s,p);
end archimulti;

Llamamos a lpmpkg
Vamos a multiplicar a y b
Y vamos a sumar s
El resultado es p

Llamamos a lpmpkg

Usamos el mdulo mmult

En este ejemplo hemos hecho uso del mdulo mmult, el cual nos
exige no slo introducirle las seales con las cuales operar (con la

sentencia port map) sino tambin su dimensin (sentencia generic


map). Pulsa aqu para ir al ejemplo del multiplicador.
Como cada mdulo tiene unas especificaciones de entradas, salida
y dimensiones distintas, tendremos que consultar el manual de la
librera lpmpkg para conocer que entradas y salidas necesita cada
mdulo. Podemos acceder a esta documentacin siguiendo estos
pasos:
Conseguir el programa WARP2 Release 4.2, disponible online en la
pgina de Cypress Semiconductor Inc. No es neceasrio si ya est
instalado en el subdirectorio c:\WARP en el ordenador donde ests
leyendo estas lneas. Si no lo tienes, isntalal en esa direccin.
Descargar el programa gratuito Acrobat Reader 3.01 y sus plug-ins.
Puedes acceder a l en Internet o en el CD-ROM de donde ha sido
instalado ste libro electrnico. No es necesario si ya lo tienes
instalado.
Una vez realizado estos pasos, aparecer debajo de estas lneas la
documentacin sobre la librera lpmpkg, en el captulo 5 del
documento. Si no te aparece pulsa c:\warp\doc\refmanl.pdf

Objetos, tipos de datos y


operaciones
Objetos
Palabras reservadas
Tipos de datos
Atributos de los vectores

12 Identificadores
34 Smbolos especiales
56 Expresiones y operadores
7

Objetos

En un lenguaje de descripcin de software (SDL) una variable


contiene un valor y puede aceptar un nuevo valor a travs de una
asignacin secuencial. Por otro lado, las constantes tienen valores
prefijados a lo largo de toda la ejecucin del programa. Sin embargo,

en VHDL se hace necesaria la utilizacin de un nuevo tipo de objeto


que puede emular las asignaciones concurrentes propias de los
circuitos elctricos reales; este nuevo tipo de objeto son las seales.
Un objeto en VHDL es un elemento que tiene asignado un valor de
un tipo determinado. Segn sea el tipo de dato, el objeto poseer un
conjunto de operaciones que se le podrn aplicar. En general, no ser
posible realizar operaciones entre dos objetos de distinto tipo, a
menos que definamos previamente un programa de conversin 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
comprensin del cdigo.
Las reglas a tener en cuenta a la hora de elegir un identificador
son:
Los identificadores deben empezar con un carcter alfabtico, no
pudiendo terminar con un carcter subrayado, ni tener dos o ms de
estos caracteres subrayados seguidos.
VHDL identifica indistintamente tanto las maysculas como las
minculas, pudindose emplear por igual el identificador "sumador" o
"SUMADOR". Pulsa aqu para ir a la prctica del sumador, donde se
demuestra la indiferencia de maysculas y minsculas.
El tamao o extensin del identificador no est fijado por VHDL,
siendo recomendable que el usuario elija un tamao que confiera
sentido y significado al identificador, sin llegar a alcanzar longitudes
excesivamente largas.
Los identificadores pueden contener caracteres numricos 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 especfico en VHDL. Estas palabras son
empleadas dentro del lenguaje a la hora de realizar un diseo. Por
esta razn 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
access
after
alias
all
and
architecture
array
asser
attribute
begin
block
body
buffer
bus
case
component
configuration
constant
disconnect
downto

else
elsif
end
entity
exit
file
for
function
generate
generic
guarded
if
in
inout
is
label
library
linkage
loop
map
mod

nand
new
next
nor
not
null
of
on
open
or
others
out
package
port
procedure
process
range
record
register
rem
report

return
select
severity
signal
subtype
then
to
transoprt
type
units
until
use
variable
wait
when
while
with
xor

Smbolos especiales

Adems de las palabras reservadas empleadas como


identificadores predefinidos, VHDL utiliza algunos smbolos especiales
con funciones diferentes y especficas, tales como el smbolo "+" se
utiliza para representar la operacin suma y, en este caso, es un
operador. El smbolo "- -" es empleado para los comentarios
realizados por el usuario, de tal forma que el programa al encontrar
una instruccin precedida por "- -" la saltar ignorando su contenido.
De esta forma, el programador puede hacer ms comprensible el
cdigo del programa.
Los smbolos especiales en VHDL son:
+ - / ( ) . , : ; & ' < > = | # <= => := -Para finalizar, recordar que el smbolo ms empleado por un
programador es el " ; ", smbolo que debe finalizar todas y cada una
de las lneas del cdigo dando por terminada dicha sentencia en el
programa.

Tipos de datos

El tipo de datos es un elemento bsico 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 declaracin de un tipo de datos es la sentencia VHDL utilizada
para introducir un nuevo tipo. Esta declaracin est formada por un
identidificador que nos permitir usar el nuevo tipo al llamarlo y la
descripcin del conjunto de valores que forman el tipo de datos. Para
ello usamos la palabra reservada type. La declaracin 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 dems, aunque estn
declarados de la misma forma, por lo cual no podemos asignar a una
seal de un tipo otra de otro tipo distinto, a menos que definamos
una funcin de transformacin.
Los tipos pueden ser clasificados segn las caractersticas de lo
que van a determinar:
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 parntesis 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 ningn valor inicial, el objeto se inicializa con
el valor ms a la izquierda de los especificados en la declaracin 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 ningn valor inicial, el objeto se inicializa con
el valor ms a la izquierda de los especificados en la declaracin 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 numrico, la magnitud fsica 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 ningn valor inicial, el objeto se inicializa con
el valor ms a la izquierda de los especificados en la declaracin 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 metodologa de programacin de un componente, basada en la


descripcin por comportamiento (behavioral), puede emplear en su
diseo la mayora de operadores que se encuentran habitualmente
tiles en los SDL's ( software design languages)
En el cuadro adjunto se puede ver una relacin de los operadores
predefinidos ms empleados en VHDL, as mismo se aprecia que su
clasificacin atiende al tipo de dato que vaya a manejar:

OPERADORES LGICOS

NOT, AND, OR,


NAND, NOR, XOR

OPERADORES RELACIONALES

= / < <= > >=

Tipo de operador: boolean


Tipo de resultado: boolean

Tipo de operador: cualquier tipo


Tipo de resultado: boolean

OPERADORES ARITMTICOS
OPERADOR CONCADENACIN

+ - * / **
MOD, REM, ABS
&

Tipo de operador: integer, real, signal


tipo de resultado: integer, real,signal
Tipo de operador: array
tipo de resultado: array

Los operadores lgicos, pueden ser empleados con los tipos


predefinidos, BIT y BOOLEAN, dndonos 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 continuacin lo ilustramos con la
ayuda del diseo de un sumador de cuatro bits mas el carry de la
etapa anterior. Pulsa aqu para ir a la prctica del Cudruple Sumador
Total.
En este ejemplo se aprecia
una concatenacion del
lemento "a" (que
architecture archisumador of sumador
previamente debe de haber
is
sido definido como un
begin
std_logic_vector), con un
process (a,b,cin)
"0", dandonos como
variable aux:std_logic_vector(4 downto
resulytado un array en el
0);
que la primera poscicion la
begin
ocupa el "0" y despues va el
aux:=('0' & a) + ('0' & b);
elemento "a"
if cin='1' then aux:=aux+1;
Este mismo ejemplo nos
elsif cin='0' then null;
servira para graficar la
end if;
utilizacin del operador
sum<=aux;
suma "+", que lo
end process;
empleamos para
end archisumador;
incrementar a la variable
aux, en caso de que cin
valga uno.
Los operadores relacionales tambin 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 combinacin " /= ".
Los operandos de tipo aritmticos estn en la obligacin 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 aade uno,(como se aprecia en el anterior
ejemplo).
El operador concadenacon es empleado para concadenar arrays
de bits, como muestra se grafca 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.

Atributos de los vectores

Un atributo nos proporciona informacin sobre ciertos elementos


como las entidades, arquitecturas, tipos y seales. Hay varios
atributos de para seales que son muy tiles en sntesis, y
especialmente en el VHDL simulable (no sintetizable). Ai ae trabaja
con VHDL sintetizable slo se pueden utilizar algunos atributos como:
Atributo 'left: se usa para manejar al elemento ms a la izquierda
de un vector.
if entrada'left='0' then ...

Si el elemento ms a la izquierda de
entrada es '0', entonces se ejecuta lo que
sigue al then

Atributo 'right: se usa para manejar al elemento ms a la derecha


de un vector.
if entrada'right='1' then ...

Si el elemento ms a la derecha de
entrada es '1', entonces se ejecuta lo que
sigue al then

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


if entrada'lenght=5 then ...

Si la longitud de entrada (se supone,


lgicamente, que es un array o vector) es 5,
entonces se ejecuta lo que sigue al then.

Atributo 'event: se usa para conocer si una variable ha cambiado o


no, solindose usar como variable booleana:
if entrada'event=5 then ...

Si hay un cambio en el nivel lgico de la


seal entrada, entonces se ejecuta lo que
sigue al then.

Gramtica del lenguaje I


Sentencias secuenciales 12 Asignacin a una seal
Asignacin a variable 34 Sentencia if
Sentencia case 56 Sentencia loop
Sentencia exit 78 Sentencia next
Sentencia null 910 Sentencia wait
Sentencia wait until 11

Sentencias secuenciales

En la mayora de los lenguajes de descripcin de software, todas


las sentencias de asignamiento son de naturaleza secuencial. Esto
significa que la ejecucin 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
disposicin de las mismas dentro del cdigo fuente.
VHDL lleva a cabo las asignaciones a seales 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 compilacin. Esto hace que cuando utilicemos modelos
secuenciales en VHDL, estos se comporten de forma parecida a
cualquier otro lenguaje de programacin como Pascal, C, etc.

Asignacin a una seal

Podremos asignar un cierto valor a una seal siempre que sta


haya sido declarada en la entidad en el apartado de declaracin de
puertos, o bien porque la hayamos creado especficamente dentro de
un process.

La asignacin a una seal dentro de un proceso es siempre


secuencial, es decir, la seal 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 asignacin est siempre activa, y se
actualiza instanteneamente. Para hacer una asignacin a una seal
deberemos usar el operador <=, estando la seal a asignar a la
izquierda y el valor que debe tomar a la derecha.
signal <= signal1 + signal2;
Las seales son el objeto ms usado dentro de la sntesis de
diseos, teniendo la particularidad de que los cambios en una seal
son programados, no son inmediatos. Esto resulta extrao, 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;
b <= a;
wait on a,b;
end process;

La seal a tendr el valor b


La seal b tendr el valor a
Se acualizan los cambios AQU

En este ejemplo, las dos seales intercambian sus valores, ya que


cuando se ejecuta la segunda (b<=a), el valor de la seal a no ha
cambiado todava aunque est la sentencia a<=b, ya que ninguna
seal 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.

Asignacin a variable

La asignacin a una variable viene totalmente influenciada por su


propia naturaleza, la cual hace que slo tengan su campo de accin
en un proceso o un subprograma (areas secuenciales). Una variable
no retiene sus valores dentro de un subprograma despus 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 seal, y operar con la
seal fuera. Para hacer el asignamiento a una variable deberemos
usar el operador := , como se muestra en los ejemplos siguientes.

A diferencia de las seales, 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 asigacin, de forma
que las sentencias que vengan a continuacin, la variable recien
asignada, tendr el nuevo valor. De esta forma, el ejemplo expuesto
para seales, al ser usado para variables, no conseguimos el mismo
resultado:
a := b;
b := a;

a toma el valor b
b toma el NUEVO valor de a (el de
b)

En esta ocasin, no se intercambiarn los valores de ambas


seales, sino que acabarn 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 := a;
a := b;
b := temp;

temp toma el valor de a


a toma el valor de b
b toma el valor de temp (que era
a)

Deberemos tener en cuenta que una variable se reinicializa


siempre al hacer una nueva llamda a un subprograma.

Sentencia if

La construccin if-then-else es usada para seleccionar un


conjunto de sentencias para ser ejecutadas segn la evaluacin de
una condicin o conjunto de condiciones, cuyo resultado debe ser o
true o false. Su estructura es la siguiente:
if (condicin) then
haz una cosa;
else
haz otra cosa diferente;
end if;
Si la condicin entre parntesis es verdadera, la(s) sentencia(s)
secuencial(es) seguidas a la palabra then son ejecutadas. Si la
condicin entre parntesis es falsa, la(s) sentencia(s) secuencial(es)

seguidas a la palabra else son ejecutadas. La construccin 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 condicin si
no se ha cumplido la primera (la cual tiene prioridad). Su estructura
es la siguiente:
if (condicin) then
haz una cosa;
elsif (otra condicin) then
haz otra cosa diferente;
else
haz otra totalmente diferente;
end if;
Si se da la situacin en la cual la primera condicin es verdad
ejecuta las sentencias que van despus del primer then. Si no es
verdadera la primera condicin, se pasa a evaluar la segunda, y de
ser esta verdad, ejecuta las sentencias que estn a continuacin del
segundo then. Si ninguna de las dos es verdadera, se ejecuta lo que
est detrs de la palabra else. Ntese que para que se ejecute las
sentencias con el nombre "otra cosas diferente", no solo debe ser la
segunda condicin verdadera, sino que adems la primera condicin
debe ser falsa. Un ejemplo de esta sentencia se puede ver a
continuacin:
entity multi is port(
a, b, c :in bit_vector(3 downto
entidad del multiplexor
0);
puertos del multiplexor
enable :in bit;
control :in bit_vector(1 downto
0);
d
:out bit_vector(3 downto 0)
);
finaliza la entidad
end multi;
architecture archmul of multi is
begin
process (a, b, c, control, enable)
begin
if enable='1' then d<="1111";
elsif enable='0' then
case control is
when "00" => d <= a;
when "01" => d <= b;
when "10" => d <= c;
when "11" => d <= "1111";
end case;

arquitectura del multiplexor

si enable es 1 entonces
d="1111"
si enable no es 1 y es 0
entonces
sentencia case dentro del if

end if;
end process;
end archmul;

se cierra la sentencia case


se cierra la sentencia if con end
finaliza la arquitectura

Deberemos tener cuidado al usar una sentencia if-then-else ya


que podemos caer en el error de la memoria implcita. Si no incluimos
la palabra else, y si no se cumple la primera condicin, las seales de
salida no cambian, reteniendo el valor previo a la sentencia if. Esto
puede ayudarnos (flip-flops) o bien hacer que un diseo sea
totalmente errneo. Analicmoslo con un ejemplo:
if (clk'event and clk='1') then
q <= d;
end if;

Si hay un flanco de subida en la seal


clk, entonces q toma el valor de d.

En este caso se dice que debe ejecutarse si hay un flanco de


subida en la seal 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
implcita, y VHDL hace que la seal q siga con el valor que tena antes
de ejecutarse la sentencia if. Esto hace que este cdigo y el que se
lista a continuacin sean equivalentes:
if (clk'event and clk='1') then
q <= d;
else
q <= q;
end if;

Si hay un flanco de subisda en la


seal clk, entonces q toma el valor de
d, si no es as, q sigue manteniendo
su valor.

Esto hace que se recomiende siempre el especificar con else que


debe pasar con las seales si no se cumpla la condicin indicada con
el if. En la parte prctica hay varios ejemplso con la sentencia if,
pulsa aqu para ir a la parte prctica.
Para evitar la inclusin de memoria implcitas se recomienda
especificar siempre el comportamiento 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


segn el valor dado de una seal de seleccin. 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 (seal 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 seal a evaluar (situada despus 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 slo
estudiamos la parte correspondiente a la sentencia case:
entity multi is port(
entidad del multiplexor
a, b, c :in bit_vector(3 downto
puertos del multiplexor
0);
enable :in bit;
control :in bit_vector(1 downto
0);
d
:out bit_vector(3 downto 0) finaliza la entidad
);
end multi;
arquitectura del multiplexor
architecture archmul of multi is
begin
process (a, b, c, control, enable)
begin
if enable='1' then d<="1111";
elsif enable='0' then
case control is
when "00" => d <= a;
when "01" => d <= b;
when "10" => d <= c;
when "11" => d <= "1111";
end case;
end if;
end process;
end archmul;

sentencia if que contiene al case


se evala la seal control
si control vale "00" entonces
d<=a
si control vale "01" entonces
d<=b
si control vale "10" entonces
d<=c
si control vale "11" d valdr
"1111"
se cierra la sentencia case con
end
se cierra la sentencia if

finaliza la arquitectura
Esta sentencia es muy tpica de los lenguajes de programacin y
cuenta adems con una variante, muy importante en VHDL, como es
dar un valor especificado a la cierta seal si no se contemplan todos
los casos posibles de la seal a evaluar. Para ello se usa la palabra
reservada others, que aparece en el siguiente fragmento de cdigo:
case control is
when "00" => d <= a;
when "01" => d <= b;
when "10" => d <= c;
when others => d <=
"1111";
end case;

se evala la seal control


si control vale "00" entonces d<=a
si control vale "01" entonces d<=b
si control vale "10" entonces d<=c
si control no toma ningn valor de los
especificados antes, toma el valor
"1111"
finaliza la arquitectura

Al igual que era recomendable especificar un else dentro de cada


if, se recomienda, con ms razn 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 ms valores aparte
del nivel uno y cero lgico, como el estado Z o de alta impedancia.
Pulsa aqu para ir a la prctica del multiplexor.
La sentencia case tambin nos permite especificar un rango de
valores posibles de la seal de seleccin, para los cuales hacer una
asignacin, mediante la palabra reservada to. Como ejemplo veamos
dos fragmentos de cdigo que son equivalentes:
case control is
when "000" => d <= a;
when "001" => d <= a;
when "010" => d <= a;
when "011" => d <= b;
when "100" => d <= b;
when "101" => d <= b;
when "110" => d <= b;
when "111" => d <= c;
when others => d <= null;
end case;

Sentencia loop

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

La sentencia loop (ciclo en castellano) se usa para ejecutar un


grupo de sentencias un nmero determinado de veces, y consiste
tanto en un ciclo for como en un ciclo while. La sentencia for se
ejecuta un nmero especfico de iteraciones basado en el valor de
una variable. La sentencia while continuar ejcutndo una operacin
mientra una condicin de control local sea cierta. Estas sentencias
son muy tpicas de los lenguajes ms usuales de programacin,
usndose habitualmente para ello la variable i. A continuacin se
listan sendos ejemplos para cada caso:
process (a)
begin
ciclo1: for i in 7 downto 0 loop
Cabecera del ciclo
entrada(i) <= ( others => '0' )
Instrucciones a ejecutar 8 veces
end loop;
Finalizacin del ciclo
end process;
Este fragmento de cdigo hace que uno por uno los 8 ltimos bits
de la seal entrada tengan el valor lgico cero. Que se indique que
deben hacerse cero 8 bits, no quiere decir que la seal entrada est
formada por ms 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 atomticamente, 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 ms
posibilidades de organizacin al programador.
process (a)
variable i: integer := 0;
begin
ciclo2: while i < 7 loop
entrada(i) <= (others => '0');
i := i + 1;
end loop;
end process;

Mientras i sea menor que 7 =>


ciclo
Finaliza el ciclo

En esta ocasin 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 lneas entre
loop y end loop mientras la variable i sea menor que siete. Es lgico
que esta variable cambie dentro del ciclo, ya que de no ser as, se
ejecutara 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 ms
trabajo.

Sentencia exit

Usada siempre dentro de un loop, la sentencia exit nos permite


salir del mismo si se alcanza una condicin fijada por nosotros. Su
verdadera utilidad la encontramos si diseamos controladores de
memoria. A continuacin 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.

Sentencia next

La sentencia next tambin debe estar dentro de un ciclo loop, y


nos sirve para saltarnos una o ms 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;
end loop;
Finaliza el ciclo
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 iteracin si la varaibale i vale cuatro.

Sentencia null

La sentencia null se utiliza, al igual que en otros lenguajes de


programacin, para que dada una condicin especial no pase nada ,
es decir, que ninguna seal o variable cambie, y que el programa siga
su curso habitual. Su comportamiento dentro de un loop es similar al
de la sentencia next.

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 cdigos siguientes son equivalentes.
process (a,b,c)
begin
x <= a and b and c;
end process;

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

Ambos procesos se ejecutarn cuando haya un cambio en la seal


a, b o c se muestra en este caso la equivalencia de una lista sensitiva
y una sentencia wait explcita.

Sentencia wait until

No debemos confundir la sentencia wait until con la sentencia


wait vista en el apartado anterior. En esta ocasin, tampoco se puede
usar una lsita sensitiva con el proceso, ya que sta queda definida
con la misma sentencia. Para las descripciones la frmula wait until
debe estar al prncipio del proceso, por lo que la lgica descrita de
esta menera no puede ser reseteada asncronamente. 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 condicin siguiente a wait
until es verdadera. Una vez que es verdad, y las asignaciones de
seal se han realizado, el proceso vuelve a esperar hasta que la seal
clk vuelve a valer de nuevo 1, es decir, un flanco de subida. Pulsa
aqu para ir a la prctica del Flip Flop D.

Gramtica del lenguaje II


Sentencias concurrentes 12 Sentencia Process
Asignacin concurrente a seal4 Asignacin concurrente
3condicional
Asignacin concurrente con6 Llamada concurrente a
seleccin 5subprograma
Sentencias estructurales 78 Subprogramas
Funciones 910 Procedimientos

Sentencias concurrentes

La naturaleza propia de los circuitos elctricos obliga a VHDL a


soportar un nuevo tipo de asignacin de seales, que nos permita
implementar este tipo de operatividad. En ella todas las asignaciones
se llevan a cabo en paralelo (al mismo tiempo). En una asignacin
concurrente la seal que est a la izquierda de la asignacin es
evaluada siempre que alguna de las seales de la derecha modifique
su valor. Como ejemplo tenemos las siguientes sentencias de
asignacin:

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

Si las seales de entrada (situadas a la derecha), a o b, cambian su


valor, las seales 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 tpicas de VHDL


usadas para agrupar algoritmos. Esta sentencia se inicia (de forma
opcional) con una etiqueta seguida de dos puntos ( : ), despus la
palabra reservada process y una lista de variables sensibles. La lista
sensible, indica que seales harn 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 despus de otra, y los
posibles cambios que deba haber en las seales alteradas se
producen despus de evaluar todo el ciclo al completo. Esta
caracterstica 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 parntesis, se

sentencias secuenciales
end process etiqueta;

ejecuta el proceso.

Siempre que queramos utilizar sentencias secuenciales se deber


usar un proceso. Como ejemplo del uso de un proceso se muestra el
siguiente fragmento de cdigo correspondiente a un flip-flop d.
contador: process (clock)
Si hay un cambio en la seal clock
begin
(reloj), se ejecuta el process que
if (clock'event and clk='1') then contiene una sentencia if. Una vez
acabado de evaluar todas las
q <= d;
sentencias del proceso, se cambian
end if,
todas las seales 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 seales y las variables. La primera es que las
variables toman instantneamente el valor especificado y que slo
tienen sentido de existencia dentro de un proceso. La segunda es que
las seales 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 despus e haber
incrementado la seal b, sta vale "0001", c deber valer '1', si no es
as deber valer '0'.
Si hay un cambio en la seal de entrada

architecture no_funciona of uno is a, entonces se ejecuta el proceso:


begin
process (a)
b se incrementa cuando se
begin
acabe de ejecutar el proceso
(manteniendo el valor actual
if a = "0000" then b <= b + 1;
hasta el end del mismo) si a
end if;
vale "1111"
if b = "0001" then c <= '1';
else c <='0';
c vale '1' si b tiene el valor
end process;
"0001"
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 evaluacin del
proceso, por lo que b no valdr "0001" hasta entonces, por lo que c
no valdr '1', que no era lo que desebamos.
architecture funciona of uno is
begin
process (a)

Si hay un cambio en la seal de entrada


a, entonces se ejecuta el proceso:

variable v: bit_vector(3 downto


0);
begin
v:=b;
if a = "0000" then v := v + '1';
end if;
if v = "0001" then c <= '1';
else c <='0';
b <= v;
end process;
end funciona;

v toma instantaneamente el
valor de b

v se incrementa
instantaneamente si a vale
"1111"

c vale '1' si v tiene el valor


"0001"

b toma el valor de v

El segundo ejemplo si que funciona como habamos especificado


para cualquier valor de b. Si a cambia y toma el valor "0000", la
variable v toma instantneamente el valor inicial de b (esto es
"0000"), y se incrementar en una unidad instantneamente por lo
que valdr "0001". Entonces c tomar el nivel lgico alto, y seguido a
esto, b tomar el valor incrementado de v. Los nuevos valores de b y
c aparecern a la salida al acabar la evaluacin completa del proceso.

Asignacin concurrente a seal

En un apartado anterior vimos como era la asignacin secuencial a


una seal. Pero las asignaciones a seales tambin pueden ser
concurrentes. La principal forma de sta asignacin es que no se
encuentra en los procesos o subprogramas, sino en las arquitecturas.
La sintaxis de asignacin tiene la misma forma que si fuese
secuencial, es decir, usando el operador <=.

Asignacin concurrente condicional

Esta asignacin es equivalente a la sentencia if, con la salvedad


que es concurrente. La sintaxis a seguir es la siguiente:

seal_uno <= seal_dos when condicion else


seal_tres;
En este caso, a seal_uno se le asigna el valor de seal_dos si se
cumple lo especificado en condicin, y en caso de no cumplirse, se
le asigna el valor de seal_tres. Un ejemplo muy tpico para el
asignamiento concurrente condicional es el de un multiplexor. Los dos
listados siguientes tienen la misma operatividad:

salida <= entrada1 when


control='1'
else entrada2;

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

La ltima asignacin tambin puede llevar condicin (slo a partir


de la norma de 1993).

Asignacin concurrente con seleccin

Es la forma compacta y concurrente de la sentencia case, la cual


tiene la siguiente sintaxis:
with expresion select
seal1 <= seal2 when
valor_expresin_1,
seal3 when valor_expresin_2;
Es muy importante notar que no se incluye el punto y coma (;)
habitual ms que al final de la sentencia, ya que de otra forma sera
incorrecto. La sentencia asigna a seal1 el valor de seal2 si se da
que expresion toma el valor valor_expresin_1, toma el valor
seal3 si expresion toma el valor valor_expresin_2,...
pudiendose ampliar esta cadena de condiciones tanto como
queramos.
Como ejemplo veamos los siguientes fragmentos de cdigo, ambos
equivalentes, que modelan a una simple Unidad Lgica:

with operacion select


resul <= a and b when "00",
a or b when "01",
a xor b when "10",
not (a and b) "11";

process(a, b, operacion)
begin
case operacin is
when "00" => resul <=
when "01" => resul <=
when "10" => resul <=
when "11" => resul <=
b);
end case;
end process;

a and b;
a or b;
a xor b;
not(a and

En ambos fragmentos de cdigo se realiza la operacin and a las


seales a y b siendo el resultado asignado a resul si operacion vale
"00", se realiza la operacin or si operacin 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

La llamada a una funcin 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 parmetros de
entrada cambia. Debemos tener en cuenta que las funciones que
vayamos a usar deben ser visibles para el compilador, es decir, que la
librera que las contenga debe estar declarada correctamente. La
sintaxis general es la siguiente:
nombre_de_la_funcin (entradas, salidas);
Al subprograma llamado nombre_de_la_funcin 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 instantacin), son una forma


ms 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 descripcin que se est realizando; slo
habr que hacer una llamda a dicho componente para usarlo con las
especificaciones propias del diseo actual. Se aprecia que su
operatividad es muy similar a la de una librera. El lenguaje nos
proporciona una serie de sentencias dedicadas a la descripcin 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 funcin port map (mapa de puertos).
Componentes: Para realizar la descripcin 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 fcilmente reconocible porque la
operatividad del programa no se puede leer del cdigo ya que est
formado ntegramente por componentes y las seales que les unen a
otros. Es decir, est formado por bloques o cajas negras a los cuales
metemos informacin y sacamos las salidas, las cuales podrn o no ir
a otros bloques. Para esto debemos conocer la operatividad de estos
bloques, los cuales suelen estar en libreras. Para usar las puertas que
estn en el paquete gatespkg debemos primero invocar a la librera
ieee (lase "i e cubo") como est expuesto en la primera lnea de la
entidad que debemos usar. Para usar el paquete (o sub-librera)
gatespkg la llamaremos de la forma en que est en la segunda lnea.
Estas libreras vienen incluidas en la versin 3.5 del programa WARP,
de Cypress Semiconductor. Como ejemplo se lista el cdigo de un
multiplexor implementado por descripcin estructural.

library ieee;
use work.gatespkg.all;

Llamamos a la librera IEEE


Llamamos a la librera que
tiene las puertas lgicas

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;
Declaracin de seales
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 cdigo se basa en los
elementos "inv", "and2" y "or2", que se encuentran en la librera
gatespkg, que listamos a continuacin:
package gatespkg is
component and2
port (
a,b : in bit;
q : out bit
);
end component;
component or2
port (
a,b : in bit;
q : out bit
);
end component;

Incluimos el nombre del paquete


Empezamos el componente and2

Empezamos el componente or2

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

Empezamos el componente inv

use work.cypress.all;
entity and2 is
port (
a,b : in bit;
q : out bit
);
end and2;
architecture archand2 of and2 is
begin
q <= (a and b);
end archand2;

Empezamos la entidad and2

use work.cypress.all;
entity or2 is
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;
qn : out bit
);
end inv;
architecture archinv of inv is
begin
qn <= not (a);
end archinv;

Empezamos la entidad or2

Empezamos la entidad inv

Subprogramas

Los subprogramas se usan para describir algoritmos de cualquier


tipo que son ms 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 definicin del
subprograma y la definicin del cuerpo del subprograma. En la
primera se define el nombre del mismo y los parmetros 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 estn destinadas a realizar clculos, siendo una


nueva forma de definir nuevos operadores que pueden aparecer en
una expresin. A las funciones se le pueden introducir todos los
valores que se necesiten, pero slo devuelven un nico valor, siendo
las variables internas a ella imposibles de recuperar para otras
operaciones.
Una funcin est formada por:
Parte declarativa: En ella indicamos cuales son los parmetros
que introducimos en la funcin, la cual entender que son constantes,
y de modo in (por defecto). Podemos definir, adems, todas las
estructuras de datos que necesitemos (tipos, constantes,
variables,...), pero slo existirn cuando la funcin haya sido llamada
y se crean e inicializan cada vez que esto ocurra. Esta es la razn de
no poder incluir seales en la parte declarativa.
Parte de sentencias: En ella se transforman los objetos que
introducimos en la funcin para obtener la salida. En esta parte

podremos usar el valor de seales y variables externas, pero no


podremos modificarlas. Tampoco podremos usar la sentencia wait.
Como ejemplo crearemos una funcin que realiza una operacin
tan sencilla como asignar a la salida de la funcin, suma, la suma de
dos nmeros, a y b.
La parte declarativa sera:
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 funcin y entre parntesis los objetos de entrada con su tipo
correspondiente. Despus va la palabra return y el tipo del resultado
de la funcin. Tiene el mismo sentido que las entidades.
La parte de sentencias sera:
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 lneas de la parte de sentencias coinciden con la parte
declarativa, slo que la primera lleva al final la palabra is, tal y como
se aprecia en el ejemplo. Seguido viene la declaracin de tipos,
subtipos y variables, etc. en la cual debe incluirse la variable que va a
ser devuelta por la funcin, 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 funcin,
ya que de no hacerlo sta se quedara sin resultado.
Para llamar a esta funcin deberemos escribir un cdigo parecido a
este en nuestro programa, teniendo en cuenta que la llamada a una
funcin 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;
En esta ocasin hemos hecho la asignacin de las entradas por
posicin: al ejecutarse la funcin, el compilador usa el valor de
numero1 como a, ya que numero1 es el primer valor que se
introduce en la funcin y a es el primero incluido en la declaracin de
la funcin. Lo mismo ocurre con numero2 y con b. Tambin podamos
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 seales a la entrada
del subprograma, stas deben coincidir en el tipo, es decir, en el
ejemplo no podamos haber introducido en la funcin numero1 y
numero2 si stos hubieran sido del tipo entero o bit. De la misma
forma la variable o la seal a la cual asignamos el valor de la funcin
debe coincidir con el tipo del objeto que hemos especificado para la
salida en la funcin. Es decir, no podemos asignar a salida el valor de
la funcin que hemos creado si es del tipo integer (por ejemplo), ya
que la salida de la funcin es suma que es del tipo std_logic_vector.

Procedimientos

Los procedimientos estn 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
ms 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 parmetros
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 seal 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 podrn 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 adems

modificarlo. Al igual que en las funciones podremos declarar todos los


tipos, constantes, variables, etc. pero slo existirn cuando se haga
un llamamiento a la procedure y se reinicializarn cada vez que se
vuelva a llamar.
Parte de sentencias: En ella se modifican seales y variables
tanto internas como externas al procedure, pudiendo adems 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 parntesis 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 cul de las seales es de entrada y/o salida.
La parte de declaraciones sera como sigue:
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 funcin, los tipos de los objetos de entrada y


salida a una funcin 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 funcin.
En este caso hemos hecho la asignacin por posicin, ya que al no
indicar nada, el compilador supone que queremos asignar el primer
objeto que hemos introducido en la funcin al primer objeto que
habamos 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 continuacin:
sumar ( numero1=>a, numero2=>b, salida =>suma );
sumar ( salida=> suma, numero2=>b, numero1=>a );
Ambas formas de llamar al procedimiento son vlidas y
equivalentes.

Interface, compilador e
implementacin fsica
VHDL sintetizable 12 Galaxy de Cypress
4 Grabacin de nuestros
Nova de Cypress 3
diseos

VHDL sintetizable

En un principo VHDL, al igual que los dems HDL'S, nacieron con el


proposito de facilitar la labor de los diseadores de circuitos
electrnicos, agilizando su diseo y haciendo ms flexible su posterior
depuracin y mantenimiento. Por este motivo se dot a VHDL con
abundantes instrucciones ms orientadas a la simulacin que a la
implementacin fsica del diseo. Ello trajo consigo la diferenciacion
del VHDL sintetizable del simulable, siendo este ltimo el ms

extendido y el que cuenta con ms herramientas en los programas. Si


trabajamos con VHDL sintetizable, slo podremos hacer uso de un
conjunto de instrucciones vlidas.
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 lgica programable (PLD), ya que ciertas instrucciones no tienen
equivalente fsico.
Como conclusin, se puede decir que todo el cdigo de un
programa en VHDL es simulable, pero no siempre ser sintetizable.

Galaxy de Cypress

Dado que el VHDL es el lenguaje estndar, todas las empresas


fabricantes de PLDs y FPGAs (Cypress, Xilinx, Altera, Actel, etc.) han
desarrollado su propio compilador cada uno con sus propias funciones
y caractersticas especiales. Este turorial ha sido realizado basndose
en el programa Warp2, del cual se muestran varias ventanas cortesa
de la compaa Cypress Semiconductor.
A pesar de ser un producto no muy pensado de cara al usuario, la
herramienta de Cypress es tan potente como las dems, contando
adems con un gran soporte tcnico va e-mail. El nombre de la
herramienta se llama WARP 2, que actualmente va por su versin 4.3.
Este conjunto de programas est orientado a la creacin 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 electrnico en la pgina web de Cypress.
El programa Galaxy es el ncleo de la suite WARP2, ya que nos
gestiona los programas creados, nos permite editarlos y elegir
distintas opciones de compilacin. Su pantalla principal es la
siguiente:

Con este programa podremos describir un circuito en VHDL,


compilarlo y simularlo, sin ms que usar el men adecuado.
Al arrancar por primera vez el programa, nos aparecer una
pantalla que nos gestionar el control de un proyecto, entendindose
por proyecto la creacin de una serie de PLDs concernientes al
mismo trabajo o tema. Deberemos introducir en este cuadro de
dilogo, la ruta y nombre del proyecto, segn nuestras preferencias, y
aadirle la extensin wpr:

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 botn llamado


selected o el botn llamdo new, en la parte de edit, segn querramos
modificar un fichero ya creado o bien hacer uno nuevo,
respectivamente. Entonces se nos abrir una ventana similar a la
siguiente:

En esta ventana crearemos o modificaremos el cdigo fuente de


VHDL segn lo que queramos realizar. Este editor tiene una serie de
guas para ayudarnos a programar, por si se nos olvida la sintaxis.
Una vez escrito todo el cdigo del programa, lo deberemos guardar,
con extensin vhd, en el mismo subdirectorio en el cual hemos creado
el fichero de extensin wpr (en este caso es c:\warp\proyecto) para
que pueda ser compilado sin ningn problema por el programa.
Si queremos crear una librera nueva para este proyecto,
deberemos especificarla despus de haber creado el fichero de
extensin wpr. Para ello deberemos ir al comando files/libraries y
crear una nueva si as lo deseamos.
Una vez creada la librera, 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 compilarn el programa
creado, deberemos seleccionar qu tipo de PLD vamos a usar, el tipo
de optimizacin, etc. Eta tarea la realizamos con los botones de la
parte inferior del programa: file, set top, generic y device.
El botn file nos servir para decirle al programa que queremos
usar la librera por defecto (es lo ms habitual) o si queremos usar un
creada. Su aspecto es el siguiente:

El botn set top sirve para indicar cual de los ficheros a compilar
es el principal, del cual cuelgan los dems ficheros. El botn generic
nos lleva al men que nos permitir elegir ciertas opciones como si
deseamos optimizar la velocidad o el rea usada del dispositivo de
lgica programable. El aspecto del men es el siguiente:

El botn device nos permitir elegir el tipo de PLD que usaremos


para grabar nuestro diseo, que hacer con las salidas no usadas, que
tipo de FlipFlops queremos usar, etc. El aspecto del men es el
siguiente:

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 ms ficheros de VHDL simultneamente.
Una vez pulsado cualquiera de los botones de compilacin, nos
aparecer una pantalla con las incidencias de la misma, incluyendo
las libreras usadas, fecha, hora, errores, etc.
Desde esta pantalla podremos acceder a las lneas del cdigo
errneas 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 cdigo original en un fichero que nos permitir
grabarlo en una PLD. Dicha pantalla tiene el aspecto siguiente:

Si en la barra de estados de la ventana de compilacin aparece la


leyenda "Compilation successful" (como aparece en la figura), querr
decir que la compilacin ha tenido xito y que el fichero de vectores

JEDEC, de extensin jed, necesario para la grabacin de las PLDs ha


sido creado correctamente.
Una vez compilado el programa, llamaremos al programa simulador
de ficheros de VHDL compilados (de extensin jed), llamado Nova,
pulsando en el men "Tools/Nova", tal y como se aprecia en al
siguiente figura:

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 lgico, 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:

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 lgico alto o bajo, que sea un reloj, que tenga un
pulso,...) segn lo que deseemos, sin ms 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 hubiramos obtenido de haber grabado la PLD con
este fichero. Haciendo doble clic en la pare inferior de la ventana nos
aparecer una lnea de gua para poder seguir mejor el resultado de
la simulacin.
Tambin 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 cmo es til la creacin de un bus se muestra en las
siguientes imgenes, 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 simulacin 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".

Si hemos creado un bus, como en la siguiente imagen. El resultado


de los bits de salida los va marcando el programa sin ms que
desplazar la gua 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 seales queremos que formen parte del bus.

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

Grabacin de nuestros diseos

Para poder implementar las descripciones realizadas en VHDL en


un dispositivo de lgica programable, se necesita un programador de
PLD's y el software de que nos grabar el cirucito usando el fichero
compilado por Warp (de extensin jed). Como ejemplo usaremos el
software y la mquina de Advantech Lab Tool, del cual se muestra a
continuacin la pantalla principal.

Para comenzar, se debe indicar al grabador el tipo de dispositivo en


el cual vamos a programar nuestro diseo. Esto se lleva a cabo
pulsando el botn select de la barra de herramientas del Lab Tool.
Una vez hecho esto, aparecer un cuadro de dilogo 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.

Una vez seleccionado el dispositivo es conveniente comprobar que


el mismo est en blanco (sin usar), pulsando el botn blank . En el
caso de que el PLD no estuviera vaco, deberemos borrarlo (si se nos
permite) usando el botn 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 estndar de Windows el fichero
deseado, como se aprecia a continuacin.

Cuando se haya elegido el encapsulado y el fichero a programar,


con tan slo pulsar el botn prog se grabar la PLD de forma
automtica, y habremos concluido el proceso, yaque el mismo
programa, despus de grabar el dispositivo, lo verifica.

ELECTRONICO-ETN
Base, Colector, Emisor electronica la Mejor.

FAC. INGENIERIA

PUBLICACIONES

PROYECTOS

Buscar en el B GO

entrega 2: ejemplos de Vhdl


Publicado el jueves, 13 de mayo de 2010 a las 10:36 p. m. 0
El dia de hoy les traigo mas ejemplos de vhdl... espero que ya se esten dando cuenta como se
hace esto de vhdl.....
Ejemplo 6:
Disear en VHDL, un codificador de 4:2 con prioridad
-------------------------------------------------- electronico-etn.blogspot.com
-- ejemplos practiicos
-- Codificador de prioridad
------------------------------------------------library ieee;
use ieee.std_logic_1164.all;
entity codificador is

port

(w:in std_logic_vector (3 downto 0);


y: out std_logic_vector (1 downto 0);
z: out std_logic);
end codificador;
architecture behaivor of codificador is
begin
with w select
y<= "00" when "0001",
"01" when "0010",
"01" when "0011",
"10" when "0100",
"10" when "0101",
"10" when "0110",
"10" when "0111",
"11" when others;
with w select
z<= '0' when "0000",
'1' when others;
end behaivor;

Ejemplo 7:
Disear en VHDL, un codificador 4:2 (como el ejemplo anterior), sin tanto codigo. realizarlo mas
eficientemente
Solucion:
--------------------------------------------------- electronico-etn.blogspot.com
-- ejemplos practiicos
-- Codificador de prioridad + eficiente
-------------------------------------------------library ieee;
use ieee.std_logic_1164.all;
entity codeficiente is
port (w:in std_logic_vector (3 downto 0);
y: out std_logic_vector (1 downto 0);
z: out std_logic);
end codeficiente;
architecture behaivor of codificador is
begin
with w select
y<= "11" when w(3) H '1' else
"10" when w(2) H '1' else
"01" when w(1) H '1' else
"00";
z<= '0' when w = "0000", else '1';
end codeficiente;

Ejemplo 8:

Disear en VHDL, un comparador de 4 bits , que a la salida te de informacion de A mayor que


B, A menor que B y A Igual que B.
Solucion:
-------------------------------------------- electronico-etn.blogspot.com
-- APLICACION DE MULTIPLEXORES
-- COMPARACION
------------------------------------------LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY comparador IS
PORT
(BCD1, BCD2: IN std_logic_vector(3 DOWNTO 0);
Igual, Mayor, Menor: OUT std_logic);
END comparador;
ARCHITECTURE RTL OF comparador IS
BEGIN
Compara:PROCESS(BCD1, BCD2)
BEGIN
--Comparacin de Igualdad.
IF (BCD1 = BCD2)
THEN Igual <= '1';
ELSE Igual <= '0';
END IF;
--Comparacin de Mayor (svE1>svE2).
IF (BCD1 > BCD2)
THEN Mayor <= '1';
ELSE Mayor <= '0';
END IF;
--Comparacin de Menor (svE1
IF (BCD1 < BCD2)
THEN Menor <= '1';
ELSE Menor <= '0';
END IF;
END PROCESS Compara;
END RTL;

Ejemplo 9:
Disear en VHDL, un comparador de 4 bits, que a la salida te de informacion de A mayor que
B, A menor que B y A Igual que B. METODO 2 (ojo: hay varios mas)
----------------------------------------- electronico-etn.blogspot.com
-- ejemplos practiicos
---------------------------------------LIBRARY ieee;
USE ieee.std_logic_1l64.all;
USE ieee.std_logic_unsigned.all ;
ENTITY ejemplo09 IS
PORT ( A,B: IN STD_LOGIC_VECTOR(3 DOWNTO 0);

igual,mayor,menor: OUT STD_LOGIC);


END ejemplo09;
ARCHITECTURE rtl OF ejemplo09 IS
BEGIN
igual <= 'l' WHEN A = B ELSE '0';
mayor <= '1' WHEN A > B ELSE '0';
menor <='l' WHEN A < B ELSE'0';
END rtl;

Ejemplo 10:
Disear en VHDL, un comparador de 4 bits CON SIGNO, que a la salida te de informacion de A
mayor que B, A menor que B y A Igual que B
Solucion:
---------------------------------- electronico-etn.blogspot.com
-- ejemplos practiicos
--------------------------------LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
-- aqui en la libreria arith radica la
-- diferencia, a comparacion del
-- anterior circuito
ENTITY ejemplo10 IS
PORT ( A,B: IN signed(3 DOWNTO 0);
igual,mayor,menor: OUT STD_LOGIC);
END ejemplo10;
ARCHITECTURE behavior OF ejemplo10 IS
BEGIN
igual <= 'l' WHEN A = B ELSE '0';
mayor <= '1' WHEN A > B ELSE '0';
menor <='l' WHEN A < B ELSE'0';
END behavior;

Ejemplo 11:
Disear en VHDL, un multiplexor de 16 a 1 con 4 variables de seleccion. USANDO
multiplexores de 4 a 1

Solucion:
----------------------------------------------- electronico-etn.blogspot.com
-- ejemplos practiicos
---------------------------------------------LIBRARY ieee;
USE ieee.std_logic_1l64.all;

LIBRARY work;
USE work.mux4to1_package.all;
ENTITY ejemplo11 IS
PORT(w :IN STD_LOGIC_VECTOR(0 TO 15);
s :IN STD_LOGTC_VECTOR(3 DOWNTO 0);
f :OUT STD_LOGIC );
END ejemplo11;
ARCHITECTURE Structure OF ejemplo1l IS
SIGNAL m:STD_LOGIC_VECTOR(O TO 3) ;
BEGIN
Mux1: mux4ro1 PORT MAP
(w(0),w(1),w(2),w(3),s(1 DOWNTO 0),m(0));
Mux2: mux4to1 PORT MAP
(w(4),w(5),w(6),w(7),s(1 DOWNTO 0),m(1));
Mux3: mux4to1 PORT MAP
(w(8),w(9),w(10),w(11),s(l DOWNTO 0),m(2));
Mux4: mux4to1 PORT MAP
(w(12),w(13),w(14),w(15),s(l DOWNTO 0),m(3));
Mux5: mux4to1 PORT MAP
(m(0),m(l),m(2),m(3),s(3 DOWNTO 2),f );
END Structure;

Proximamente mas ejemplos sobre transcodificadores, y ejemplos de laboratorios de digitales 1

Articulos Relacionados

ping-pong 2 Jugadores

Multiplicador de Frecuencias en VHD...

VIDEOJUEGO PONG EN VHDL

Monitor VGA y VHDL (parte-2)

ELECTRONICO-ETN
Base, Colector, Emisor electronica la Mejor.

FAC. INGENIERIA

PUBLICACIONES

PROYECTOS

Buscar en el B GO

Ejemplos vhdl (parte 7) penultima


Publicado el viernes, 25 de marzo de 2011 a las 11:57 a. m. 1
Buen dia... espero que les valla super... bueno esta es nuestra penultima entrega de ejemplos
basicos en VHDL
faltaria solamente realizar secuenciales, maquinas de mealy y moore... en la ultima entrega
mostraremos estos ejemplos..que son relativamente sencillos, solo es ubicarse bien con el
clock evento (rising edge)...

Ejemplo 22:
Disear en VHDL, un contador de 4 bits ascendente, con reloj de 1Hz.
Solucion:
ejemplo publicado en http://www.todopic.com.ar
------------------------------------------------------------------------------------- Contador ascendente 4 bit con 1 Hz de reloj
-- Autor: Americo Alvarez S.
-- Fecha: 05 de marzo de 2011
-- Nombre de modulo: counter_4b_1hz
-- Descripcion:
-Una vez visto el gran inconveniente por el reloj que
-presentaban los contadores al momento de implementarlos
-en la tarjeta fpga. Se vio la necesidad de implementar
-un contador con f=1Hz de frecuencia.
-La salida se la observara en binario, en leds.
-- Abstract:
--

-- Vercion: vercion 0
-----------------------------------------------------------------------------------library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY counter_4b_1hz is
Port (clock_50Mhz : in STD_LOGIC; reset: in bit;
F: OUT INTEGER RANGE 0 TO 15);
END counter_4b_1Hz;
ARCHITECTURE rtl OF counter_4b_1hz IS
SIGNAL clkout: std_logic;
CONSTANT max: INTEGER := 50000000;
CONSTANT half: INTEGER := max/2;
SIGNAL count: INTEGER RANGE 0 TO max;
BEGIN
-- generando seal clock de 1Hz de frecuencia
PROCESS
BEGIN
WAIT UNTIL clock_50Mhz'EVENT and clock_50Mhz = '1';
IF count < max THEN count <= count + 1;
ELSE count <= 0;
END IF;
IF count < half THEN clkout <= '0';
ELSE clkout <= '1';
END IF;
END PROCESS;
--contador 4 bits ascendente
PROCESS(clkout,reset)
VARIABLE cuenta: INTEGER RANGE 0 TO 15;
BEGIN
IF (reset='1') THEN
cuenta:=0;
ELSIF (clkout'EVENT AND clkout='0') THEN
cuenta:=cuenta+1;
END IF;
F <= cuenta;
END PROCESS;
END rtl;

Ejemplo 23:
Disear en VHDL, un contador de 4 bits ascendente, con reloj de 1Hz, y que muestre su salida
en numero hexadecimal en display de 7 segmentos
Solucion:
------------------------------------------------------------------------------------------- Contador ascendente 4 bit con 1 Hz de reloj,
-- con salida hexadecimal en display de 7 segmentos

-- Autor: Americo Alvarez S.


-- Fecha: 25 de marzo de 2011
-- Nombre de modulo: counter_4b_7seg
-- Descripcion:
-Una vez visto el gran inconveniente por el reloj que
-presentaban los contadores al momento de implementarlos
-en la tarjeta fpga. Se vio la necesidad de implementar
-un contador con f=1Hz de frecuencia.
-La salida se la observara en hexadecimal en display de 7seg.
-- Abstract:
--- Vercion: vercion 0.1
-----------------------------------------------------------------------------------------library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY counter_4b_7seg is
Port (clock_50Mhz : in STD_LOGIC; reset: in bit;
7SEG: OUT STD_LOGIC_VECTOR (7 downto 0);
END counter_4b_7seg;
ARCHITECTURE rtl OF counter_4b_1hz IS
SIGNAL clkout: std_logic;
CONSTANT max: INTEGER := 50000000;
CONSTANT half: INTEGER := max/2;
SIGNAL count: INTEGER RANGE 0 TO max;
SIGNAL F: INTEGER RANGE 0 to 15
BEGIN
-- generando seal clock de 1Hz de frecuencia
PROCESS
BEGIN
WAIT UNTIL clock_50Mhz'EVENT and clock_50Mhz = '1';
IF count < max THEN count <= count + 1;
ELSE count <= 0;
END IF;
IF count < half THEN clkout <= '0';
ELSE clkout <= '1';
END IF;
END PROCESS;
--contador 4 bits ascendente
PROCESS(clkout,reset)
VARIABLE cuenta: INTEGER RANGE 0 TO 15;
BEGIN
IF (reset='1') THEN
cuenta:=0;
ELSIF (clkout'EVENT AND clkout='0') THEN
cuenta:=cuenta+1;
END IF;
F <= cuenta;
BEGIN
case F is
when 0 => 7SEG :="10000001";
when 1 => 7SEG :="11001111";
when 2 => 7SEG :="10010010";

when 3 => 7SEG :="10000110";


when 4 => 7SEG :="11001100";
when 5 => 7SEG :="10100100";
when 6 => 7SEG :="11100000";
when 7 => 7SEG :="10001111";
when 8 => 7SEG :="10000000";
when 9 => 7SEG :="10000100";
when 10 => 7SEG :="11100010";
when 11 => 7SEG :="11100000";
when 12 => 7SEG :="11110010";
when 13 => 7SEG :="11000010";
when 14 => 7SEG :="10110000";
when 15 => 7SEG :="10111000";
when others => null;
end case
END PROCESS;
END rtl;

Bueno esperaba poderles mostrar el reloj digital y el cronometro, pero no sera posible
hasta terminar el semestre ya que no tengo tiempo... una sugerencia muy util, si no
pueden disear en leguaje vhdl la manera mas sencilla de presentar los trabajos en
laboratorios de simulacion es realizar la captura esquematica utilizando el quartus2 o el
webpack ise xilinx ya que los simuladores en captura esquematica tienen todos los
componentes basicos para realizar cualquier trabajo de digi y solamente es agarrar el
componente y conectar con cables como el multisim o proteus

Articulos Relacionados

Monitor VGA y VHDL (parte-2)

Monitor VGA y VHDL (parte-1)

DESIGN USING VHDL

ping-pong 2 Jugadores

ELECTRONICO-ETN
Base, Colector, Emisor electronica la Mejor.

FAC. INGENIERIA

PUBLICACIONES

PROYECTOS

Buscar en el B GO

entrega 3 :ejemplos VHDL


Publicado el sbado, 29 de mayo de 2010 a las 9:50 a. m. 0
Ejemplo 12:
Disear en VHDL, un transcodificador,del codigo 84-2-1 al jhonson de 5bits
-------------------------------------------------- electronico-etn.blogspot.com
-- ejemplos practiicos
-- transcodificador de del codigo 84-2-1 al
-- jhonson de 5 bits
------------------------------------------------library ieee;
use ieee.std_logic_1164.all;
entity transcodificador is
port
(cod: in std_logic_vector (3 downto 0);
Jhonson5bits: out std_logic_vector (4 downto 0));
end transcodificador;
architecture rtl of transcodificador is
begin
PROCESS(cod)
BEGIN
CASE cod IS
WHEN "0000" => Jhonson5bits <= "00000";

WHEN "0111" => Jhonson5bits <= "00001";


WHEN "0110" => Jhonson5bits <= "00011";
WHEN "0101" => Jhonson5bits <= "00111";
WHEN "0100" => Jhonson5bits <= "01111";
WHEN "1011" => Jhonson5bits <= "11111";
WHEN "1010" => Jhonson5bits <= "11110";
WHEN "1001" => Jhonson5bits <= "11100";
WHEN "1000" => Jhonson5bits <= "11000";
WHEN "1111" => Jhonson5bits <= "10000";
WHEN OTHERS => Jhonson5bits <= "00000";
END CASE;
END PROCESS;
END rtl;

Ejemplo 13:
Disear en VHDL, generador de bits para la coreccion de errores de un Bcd aiken
Solucion:
--------------------------------------------------- electronico-etn.blogspot.com
-- ejemplos practiicos
-- deteccion y correccion de errores
-------------------------------------------------library ieee;
use ieee.std_logic_1164.all;
entity DyCdeError is
port
(I: in std_logic_vector (3 downto 0);
bits: out std_logic_vector (7 downto 1));
end DyCdeError;
architecture rtl of DyCdeError is
begin
PROCESS(I)
BEGIN
CASE I IS
WHEN "0000" => bits <= "0000000";
WHEN "0001" => bits <= "0000111";
WHEN "0010" => bits <= "0011001";
WHEN "0011" => bits <= "0011110";
WHEN "0100" => bits <= "0101010";
WHEN "1011" => bits <= "1010101";
WHEN "1100" => bits <= "1100001";
WHEN "1101" => bits <= "1100110";
WHEN "1110" => bits <= "1111000";
WHEN "1111" => bits <= "1111111";
WHEN OTHERS => bits <= "0000000";
END CASE;
END PROCESS;
END rtl;

Ejemplo 14:

Disear en VHDL, disee un sumador simple, sin acarreo


Solucion:
-------------------------------------------- electronico-etn.blogspot.com
-- APLICACION DE MULTIPLEXORES
-- suumador
------------------------------------------LIBRARY ieee ;
USE ieee.std_logic_1164.ALL ;
USE ieee.std_logic_arith.ALL ; --define 1:signed 2:unsigned 3:integer
ENTITY sumsen IS
PORT
(A,B: IN signed (4 downto 0) ;
S: out signed (4 downto 0) );
END sumsen ;
ARCHITECTURE rtl OF sumsen IS
BEGIN
S <= A + B ;
END rtl ;

Ejemplo 15:
Disear en VHDL, disee un sumador simple, con acarreo
----------------------------------------- electronico-etn.blogspot.com
-- ejemplos practiicos
---------------------------------------LIBRARY ieee ;
USE ieee.std_logic_1164.ALL ;
USE ieee.std_logic_unsigned.ALL ;
ENTITY sumaca IS
PORT
(A,B: IN std_logic_vector (3 downto 0);
ci: in std_logic;
S: out std_logic_vector (3 downto 0);
co: out std_logic);
END sumaca ;
ARCHITECTURE entera OF sumaca IS
signal suma: std_logic_vector(4 downto 0);
BEGIN
suma <= ('0'& A) + B + ci ;
S <= suma(3 downto 0);
co <= suma(4);
END entera ;

Ejemplo 16:
Disear en VHDL, un sumdor de 8 bits con signo
Solucion:

---------------------------------- electronico-etn.blogspot.com
-- ejemplos practiicos
--------------------------------LIBRARY ieee ;
USE ieee.std_logic_1164.ALL ;
USE ieee.std_logic_arith.ALL ;
ENTITY sumador8bits IS
PORT
(A,B: IN unsigned (7 downto 0) ;
C: IN signed (7 downto 0) ;
D: in std_logic_vector (7 downto 0) ;
S: out unsigned (8 downto 0) ;
T: out signed (8 downto 0) ;
U: out signed (7 downto 0) ;
v: out std_logic_vector (8 downto 0) );
END sumador8bits ;
ARCHITECTURE rtl OF sumador8bits IS
BEGIN
S <= ('0' & A) + ('0' & B) ;
T <= A + C ;
U <= C + SIGNED(D) ;
V <= C - UNSIGNED(D) ;
END rtl ;

muy pronto mas ejemplos.....

Articulos Relacionados

ping-pong 2 Jugadores

Multiplicador de Frecuencias en VHD...

VIDEOJUEGO PONG EN VHDL

Monitor VGA y VHDL (parte-2)

ELECTRONICO-ETN
Base, Colector, Emisor electronica la Mejor.

FAC. INGENIERIA

PUBLICACIONES

PROYECTOS

Buscar en el B GO

entrega 2: ejemplos de Vhdl


Publicado el jueves, 13 de mayo de 2010 a las 10:36 p. m. 0
El dia de hoy les traigo mas ejemplos de vhdl... espero que ya se esten dando cuenta como se
hace esto de vhdl.....
Ejemplo 6:
Disear en VHDL, un codificador de 4:2 con prioridad
-------------------------------------------------- electronico-etn.blogspot.com
-- ejemplos practiicos
-- Codificador de prioridad
------------------------------------------------library ieee;
use ieee.std_logic_1164.all;
entity codificador is
port (w:in std_logic_vector (3 downto 0);
y: out std_logic_vector (1 downto 0);

z: out std_logic);
end codificador;
architecture behaivor of codificador is
begin
with w select
y<= "00" when "0001",
"01" when "0010",
"01" when "0011",
"10" when "0100",
"10" when "0101",
"10" when "0110",
"10" when "0111",
"11" when others;
with w select
z<= '0' when "0000",
'1' when others;
end behaivor;

Ejemplo 7:
Disear en VHDL, un codificador 4:2 (como el ejemplo anterior), sin tanto codigo. realizarlo mas
eficientemente
Solucion:
--------------------------------------------------- electronico-etn.blogspot.com
-- ejemplos practiicos
-- Codificador de prioridad + eficiente
-------------------------------------------------library ieee;
use ieee.std_logic_1164.all;
entity codeficiente is
port (w:in std_logic_vector (3 downto 0);
y: out std_logic_vector (1 downto 0);
z: out std_logic);
end codeficiente;
architecture behaivor of codificador is
begin
with w select
y<= "11" when w(3) H '1' else
"10" when w(2) H '1' else
"01" when w(1) H '1' else
"00";
z<= '0' when w = "0000", else '1';
end codeficiente;

Ejemplo 8:
Disear en VHDL, un comparador de 4 bits , que a la salida te de informacion de A mayor que

B, A menor que B y A Igual que B.


Solucion:
-------------------------------------------- electronico-etn.blogspot.com
-- APLICACION DE MULTIPLEXORES
-- COMPARACION
------------------------------------------LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY comparador IS
PORT
(BCD1, BCD2: IN std_logic_vector(3 DOWNTO 0);
Igual, Mayor, Menor: OUT std_logic);
END comparador;
ARCHITECTURE RTL OF comparador IS
BEGIN
Compara:PROCESS(BCD1, BCD2)
BEGIN
--Comparacin de Igualdad.
IF (BCD1 = BCD2)
THEN Igual <= '1';
ELSE Igual <= '0';
END IF;
--Comparacin de Mayor (svE1>svE2).
IF (BCD1 > BCD2)
THEN Mayor <= '1';
ELSE Mayor <= '0';
END IF;
--Comparacin de Menor (svE1
IF (BCD1 < BCD2)
THEN Menor <= '1';
ELSE Menor <= '0';
END IF;
END PROCESS Compara;
END RTL;

Ejemplo 9:
Disear en VHDL, un comparador de 4 bits, que a la salida te de informacion de A mayor que
B, A menor que B y A Igual que B. METODO 2 (ojo: hay varios mas)
----------------------------------------- electronico-etn.blogspot.com
-- ejemplos practiicos
---------------------------------------LIBRARY ieee;
USE ieee.std_logic_1l64.all;
USE ieee.std_logic_unsigned.all ;
ENTITY ejemplo09 IS
PORT ( A,B: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
igual,mayor,menor: OUT STD_LOGIC);
END ejemplo09;

ARCHITECTURE rtl OF ejemplo09 IS


BEGIN
igual <= 'l' WHEN A = B ELSE '0';
mayor <= '1' WHEN A > B ELSE '0';
menor <='l' WHEN A < B ELSE'0';
END rtl;

Ejemplo 10:
Disear en VHDL, un comparador de 4 bits CON SIGNO, que a la salida te de informacion de A
mayor que B, A menor que B y A Igual que B
Solucion:
---------------------------------- electronico-etn.blogspot.com
-- ejemplos practiicos
--------------------------------LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
-- aqui en la libreria arith radica la
-- diferencia, a comparacion del
-- anterior circuito
ENTITY ejemplo10 IS
PORT ( A,B: IN signed(3 DOWNTO 0);
igual,mayor,menor: OUT STD_LOGIC);
END ejemplo10;
ARCHITECTURE behavior OF ejemplo10 IS
BEGIN
igual <= 'l' WHEN A = B ELSE '0';
mayor <= '1' WHEN A > B ELSE '0';
menor <='l' WHEN A < B ELSE'0';
END behavior;

Ejemplo 11:
Disear en VHDL, un multiplexor de 16 a 1 con 4 variables de seleccion. USANDO
multiplexores de 4 a 1

Solucion:
----------------------------------------------- electronico-etn.blogspot.com
-- ejemplos practiicos
---------------------------------------------LIBRARY ieee;
USE ieee.std_logic_1l64.all;
LIBRARY work;
USE work.mux4to1_package.all;

ENTITY ejemplo11 IS
PORT(w :IN STD_LOGIC_VECTOR(0 TO 15);
s :IN STD_LOGTC_VECTOR(3 DOWNTO 0);
f :OUT STD_LOGIC );
END ejemplo11;
ARCHITECTURE Structure OF ejemplo1l IS
SIGNAL m:STD_LOGIC_VECTOR(O TO 3) ;
BEGIN
Mux1: mux4ro1 PORT MAP
(w(0),w(1),w(2),w(3),s(1 DOWNTO 0),m(0));
Mux2: mux4to1 PORT MAP
(w(4),w(5),w(6),w(7),s(1 DOWNTO 0),m(1));
Mux3: mux4to1 PORT MAP
(w(8),w(9),w(10),w(11),s(l DOWNTO 0),m(2));
Mux4: mux4to1 PORT MAP
(w(12),w(13),w(14),w(15),s(l DOWNTO 0),m(3));
Mux5: mux4to1 PORT MAP
(m(0),m(l),m(2),m(3),s(3 DOWNTO 2),f );
END Structure;