Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Ap6 Ejemplos VHDL
Ap6 Ejemplos VHDL
A6 Apndice al captulo 23
Ejemplos de diseo con V H D L
Este apndice ofrece una serie de ejemplos de diseo de circuitos de control descritos
en VHDL. Los seis primeros se refieren a pequeos sistemas, basados en la utilizacin de
contadores, a saber:
- temporizacin de la luz de una escalera,
- control de anchura de pulsos de entrada,
- supervisin de velocidad de un motor,
- comparacin de anchura de pulsos sucesivos,
- generacin de n pulsos, siendo n la medida del pulso de entrada,
- y pulsos de anchura progresivamente creciente/decreciente.
En estos ejemplos, como referencia para el texto VHDL y, tambin, como ejercicio
de diseo modular, se incluye y se comenta el correspondiente diagrama de bloques.
Otros tres diseos se refieren a mquinas algortmicas descritas en el captulo 24:
- producto de dos nmeros de 64 dgitos binarios (apartado 24.3.),
- raz cuadrada de un nmero de 64 dgitos (ejemplo 24.4.2.),
y, por ltimo, se desarrollan dos diseos ms amplios, relativos a un cronmetro
controlado mediante dos pulsadores (ejemplo 24.4.5. del captulo 24) y al control de una
encimera de cocina vitrocermica con cuatro fuegos.
[Los diez diseos de este apndice han sido comprobados, mediante compilacin y
simulacin del texto VHDL con la herramienta MAX+plus II de ALTERA.]
Electrnica Digital
use ieee.std_logic_1164.all;
entity ESCALERA is
port ( CK, RS, P
conmutador
luces
end ESCALERA;
use ieee.std_logic_unsigned.all;
: in std_logic;
: in std_logic_vector(3 downto 0);
: out std_logic);
-- el contador cont_1 divide por 10: pasa del reloj de 1" a 10"
-- cont_2 cuenta intervalos de 10" (cuando cont_1 est en 9)
begin
-- si cont_2 < conmutador BCD, luz fija; cuando son iguales, luz intermitente
-- la intermitencia se hace con cont_1(0): semiperodo 1"
luces <= '1' when (cont_2 < conmutador) or ((cont_2 = conmutador) and (cont_1(0) = '1'))
else '0';
TEMPORIZACION: process
begin
wait until CK = '1';
conmutador BCD
-- contaje mdulo 10 para cont_1 y hasta cont_2 > conmutador BCD para ambos
>
= comparador
<
encendido
lmparas
q3
q2
16
P
q1
B
q0
mx
q3
q2
10
q1
q0
B
CK 1Hz 1"
249
Un circuito posee una nica lnea de entrada que recibe pulsos de diferente duracin
y presenta una sola lnea de salida que debe situarse a 1 si la anchura del ltimo pulso
recibido es mayor que 25 s y menor de 60 s, con una precisin de 0,5 s: la salida se
actualiza cuando finaliza cada pulso (flanco de bajada).
Se requiere un reloj de 2 MHz para que la precisin sea de 0,5 s y con dicho reloj:
0
q
A>B
0
B
Y <= yy;
RELOJ: process
begin
wait until CK = '1';
detector(1) <= P;
detector(2) <= detector(1);
detecta 60
q
detector de flancos
q
D
pulsos
CK 2 MHz
Un contador mide la anchura del pulso de entrada con el reloj de 2 MHz (0,5 s) y
la compara con 25 s (comparador) y con 60 s (puerta Nand); cuando llega a 60 el
contador se detiene para que no se d la vuelta (vuelva a 0) e inicie un nuevo contaje.
La comparacin se ejecuta (sobre el biestable de salida) al finalizar el pulso de entrada
(deteccin del flanco de bajada) y, a la vez, se borra el contador para la medida del
siguiente pulso.
use ieee.std_logic_1164.all;
entity ANCHURA is
end ANCHURA;
: in
use ieee.std_logic_unsigned.all;
std_logic; Y
: out std_logic);
begin
CK
library ieee;
:std_logic;
25 s
Comparador
Electrnica Digital
signal yy
250
yy <= '1';
yy <= '0';
end if;
<8
>9
< comparador
detector de flancos
E
q3
CK
q2
16
q1
B
q0
mx
q3
10"
mx
q2
q1
10
104
q0
pulsos
del
sensor
CK 1KHz 1ms
251
El contaje de pulsos se hace en BCD y se compara con 80 y con 90; cuando llega a
90 se detiene para evitar que el contador se d la vuelta. El intervalo de medida (10")
se obtiene dividiendo por 104 la frecuencia de reloj (1 KHz); al final de dicho intervalo se
ejecutan las comparaciones (biestable de salida) y se borra el contador para iniciar una
nueva medida.
library ieee;
use ieee.std_logic_1164.all;
entity MOTOR is
end MOTOR;
: in
std_logic;
: out std_logic);
-- divisin de frecuencia por 10; se utiliza 4 veces (por ello se define como funcin)
function mod10 (e :std_logic; qq :std_logic_vector(3 downto 0)) return std_logic_vector is
variable cont:std_logic_vector(3 downto 0);
begin
if e = '1' then
if qq = "1001" then cont := "0000"; else cont := qq + 1; end if;
else cont := qq; end if;
return cont; end;
Pueden conseguirse tiempos mnimos midiendo el perodo de los pulsos del sensor;
es decir, contando el tiempo entre dos pulsos sucesivos, en lugar de contar pulsos en una
unidad de tiempo:
1/480 r.p.m. = 60 /480 = 125 ms = 1111101
1/540 r.p.m. = 60 /540 = 111,1 ms ; 112 ms = 1101111.
En este caso, para mejorar la resolucin, se utiliza un reloj de 1 MHz.
1
:std_logic;
<112
D
E
begin
Y <= yy;
end if;
La solucin anterior tiene un tiempo de respuesta de 10 segundos (lo cual puede ser
adecuado para un operador humano); en caso de que la informacin respecto a la
velocidad del motor fuera comunicada a un microprocesador de control, es posible que
interesase un tiempo de medida menor.
signal detector
signal flanco
Electrnica Digital
RELOJ: process
begin
wait until CK = '1';
detector(1) <= S;
detector(2) <= detector(1);
use ieee.std_logic_unsigned.all;
signal cont1,cont2
252
A<B
>125
0
B
A
Comparador
CK
E2
E1
1 ms
mx
103
B
detector de flancos
CK 1MHz 1s
q
pulsos
del
sensor
CK 1MHz 1s
253
Ahora lo que se cuentan son milisegundos (se mide el perodo) y dicho contaje se
hace directamente en binario y se compara con 125 y con 111; cuando se alcanza el 125
se detiene el contador para evitar que se d la vuelta. Las comparaciones se ejecutan al
finalizar cada vuelta (flanco de bajada de los pulsos del sensor) y, a la vez, se borra el
contador para un nuevo contaje.
library ieee;
use ieee.std_logic_1164.all;
entity MOTOR2 is
end MOTOR2;
: in
Electrnica Digital
yy <= '1';
yy <= '0';
std_logic;
: out std_logic);
Registro
CK
signal detector
signal flanco
CK
signal yy
:std_logic;
A=B
D
BE
B
A
Comparador
detecta 50
CK 4 MHz 0,25 s
begin
Y <= yy;
end if;
use ieee.std_logic_unsigned.all;
signal contador
254
detector de flancos
pulsos
CK 4 MHz
-- contaje de milisegundos
if (( RS = '1' ) or (flanco = '1')) then
elsif (miliseg = '1') and (contador < "1111101") then
end if;
q
D
use ieee.std_logic_1164.all;
entity COMPARACION is
port ( CK, RS, P : in std_logic; Y
end COMPARACION ;
use ieee.std_logic_unsigned.all;
: out std_logic);
255
256
Electrnica Digital
5. Generacin de n pulsos
-- contador y registro son de 8 bits (para abarcar los 50 s, medidos con 4 MHz)
signal detector
signal flanco
CK 1 MHz 1 s
Contador mdulo 64
E
B
:std_logic;
-- yy es el biestable de salida
Comparador
B<A
begin
Y <= yy;
RELOJ: process
begin
wait until CK = '1';
detector(1) <= P;
detector(2) <= detector(1);
Contador mdulo 32
end if;
-- paso de la medida del pulso al registro para la comparacin con el siguiente pulso
registro <= contador;
q
D
D
CK
q
detector de flancos
E
B
pulsos
de
entrada
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity PULSOS is
port ( CK, RS,P
end PULSOS;
: in
std_logic; Y
: out std_logic);
257
258
Electrnica Digital
CK 1 MHz 1 s
mx
q3
q
begin
Y <= cont2(0);
mx
10
q2
q1
q0
q3
mx
10
q2
q1
q0
<
<
A
= comparador=
>
>
<
A
< comparador=
>
q3
10
q2
q1
q0
CK
RELOJ: process
begin
wait until CK = '1';
detector(1) <= P;
detector (2) <= detector(1);
if (RS = '1') or (flanco = '1') then
cont1 <= "00000";
q3
q2
q1
10
q0
q3
mx
q2
q1
q0
10
J
K
CK 1 MHz 1 s
-- contaje del primer contador: medida de la anchura del pulso de entrada (mximo 25)
elsif detector(2) = '1' then
if (cont1 < "11001") then
library ieee;
cont1 <= cont1 + 1;
end if;
entity PWM is
end PWM;
use ieee.std_logic_1164.all;
port ( CK, RS
: in
use ieee.std_logic_unsigned.all;
std_logic; Y
: out std_logic);
-- contaje mdulo 10, que puede ser bidireccional: hay 5 contadores dcada en el diseo
-- rs acta como inicializacin, dir como control arriba/abajo y e como habilitacin
function mod10 (rs, dir, e :std_logic; qq :std_logic_vector(3 downto 0))
return std_logic_vector is
variable contador :std_logic_vector(3 downto 0);
begin
if rs = '1' then contador := "0000";
elsif e = '1' then
if dir = '1' then if qq = "1001" then contador := "0000";
else contador := qq + 1;
end if;
else
if qq = "0000" then contador := "1001";
else contador := qq - 1;
end if;
else contador := qq; end if;
return contador; end;
signal cont1, cont2, cont3, cont4, cont5
signal max1, max2, ciclo, m_m4
end if;
Con reloj de 1 MHz har falta otro contador dcada para la temporizacin en 10 s.
El contador del ciclo PWM ser habilitado por esta seal de 10 s y de mdulo 100 para
que el ciclo sea de 1 ms (100 x 10 s); el contador que genera la referencia se habilitar
con la salida de mximo del anterior (que determina el final de cada ciclo).
signal dir, yy
signal uno
:std_logic;
:std_logic;
259
260
Electrnica Digital
begin
Y <= yy;
library ieee;
entity MULTIPLICADOR is
port (
CK, RS, Init
P, Q
Dis
R
end MULTIPLICADOR;
use ieee.std_logic_unsigned.all;
: in std_logic;
: in std_logic_vector(63 downto 0);
: out std_logic;
: out std_logic_vector(127 downto 0));
use ieee.std_logic_1164.all;
yy <= '1';
yy <= '0';
constant reposo
constant inicio
constant intermedio
constant sumar
constant desplazar
signal estado : mis_estados;
signal pp,qq
: mis_estados :="0000";
: mis_estados :="0001";
: mis_estados :="0010";
: mis_estados :="0100";
: mis_estados :="1000";
261
end if;
pp <= P;
qq <= Q;
end if;
end process;
end ALGORITMICA ;
use ieee.std_logic_1164.all;
entity RAIZ is
port (
CK, RS, Init
P
Dis
R
end RAIZ ;
use ieee.std_logic_unsigned.all;
: in std_logic;
: in std_logic_vector(63 downto 0);
: out std_logic;
: out std_logic_vector(31 downto 0));
else
Electrnica Digital
CONTROL: process
begin
wait until CK = '1';
if ( RS = '1' ) then
else case estado is
when reposo =>
262
end if;
-- declaracin de estados
type mis_estados is ( reposo, inicio, desplazar1,desplazar2,
intermedio, restar, desplazar);
signal estado
:mis_estados;
signal pp
end if;
R <= rr;
263
end if;
end if;
end if;
264
Electrnica Digital
end if;
borrado
parado
visualizacin
fija
Q.P
en marcha
Q.P
P
P
contaje
detener
la visualizacin
detencin
Q.P
Registro
1h
E
CONTADOR
1 DCADA
Registro
1m
mx
E
hab
1s
mx
CONTADOR
MOD 6x10
Clr
Registro
mx
Clr
CONTADOR
1 DCADA
CONTADOR
MOD 6x10
Clr
Clr
Eregistro
Econtador
T 0,1s
onda de
temporizacin
CK
Clr
Como reloj se utilizar un oscilador de precisin con cristal de cuarzo de 1 MHz; por
divisin de esa frecuencia (mediante 5 dcadas) se obtendr la onda de temporizacin de
0,1 segundo (100 Hz) que es la unidad de tiempo para el contador de la figura anterior.
Asimismo, se obtendr la seal de temporizacin para el barrido de los visualizadores
(vase la figura de la pgina siguiente) que ser de 100 Hz.
T 0,1s
SCAN
1ms
E
CONTADOR
1 DCADA
CONTADOR
1 DCADA
mx
CONTADOR
1 DCADA
mx
CONTADOR
1 DCADA
mx
CONTADOR
1 DCADA
1 MHz
1 s
OSCILADOR
265
A fin de reducir lneas de conexin (6 cifras BCD requieren 24 lneas, que pasan a
ser 42 despus de los conversores a 7 segmentos), la representacin sobre el visualizador
ser de tipo dinmico, segn el esquema de multiplexado que sigue:
fuera del circuito integrado
horas
decenas minutos
BCD
minutos
7
seg.
decenas segundos
266
library ieee;
Electrnica Digital
use ieee.std_logic_1164.all;
entity CRONOMETRO is
port (
CK, RS
P, Q
BCD
E
end CRONOMETRO;
use ieee.std_logic_unsigned.all;
: in std_logic;
: in std_logic;
: out std_logic_vector(3 downto 0);
: out std_logic_vector(6 downto 1));
segundos
-- contaje mdulo 10
decimas
Vcc
decodificador
contador
mdulo 6
E
CK
- salidas: 4 comunes para las cifras BCD y 6 para el barrido de los 6 visualizadores.
BCD(3)
BCD(2)
CK: 1 M Hz
RS
BCD(1)
BCD(0)
-- contaje mdulo 6
function mod6 (e2 :std_logic; q2:std_logic_vector) return std_logic_vector is
variable contador2 :std_logic_vector(6 downto 4);
begin
if e2 = '1' then
if q2 = "101" then contador2 := "000";
else contador2 := q2 + 1;
end if;
else contador2 := q2;
end if;
return contador2; end;
signal seg, min
signal dec, hor
signal max1, max2, max3, max4,max5
E1
E2
E3
E4
E5
E6
267
end if;
if (P = '0') then
end if;
if (P = '1') then
elsif (Q = '1') then
end if;
if (Q = '0') then
end if;
if (P = '1') then
elsif (Q = '1') then
end if;
if (P = '0') then
end if;
end process;
Electrnica Digital
268
end if;
SEALES: process
begin
Clr <= '0';
Econtador <= '0';
Eregistro <= '0';
-- valor por defecto
case estado is
when borrado =>
Clr <= '1';
Eregistro <= '1';
when en_marcha =>
Econtador <= '1';
Eregistro <= '1';
when contaje =>
Econtador <= '1';
Eregistro <= '1';
when detencion =>
when parado =>
when detener_vis =>
Econtador <= '1';
when vis_detenida =>
Econtador <= '1';
when others =>
end case;
end process;
269
270
Electrnica Digital
begin
contscan <= (others => '0');
contscan <= mod6(scan, contscan);
-- multiplexado
MULTIPLEXADO: process(contscan) begin
case contscan is
when "000" =>
BCD <= regdec;
when "001" =>
BCD <= regseg(3 downto 0);
when "010" =>
BCD <= '0' & regseg(6 downto 4);
when "011" =>
BCD <= regmin(3 downto 0);
when "100" =>
BCD <= '0' & regmin(6 downto 4);
when "101" =>
BCD <= reghor;
when others =>
BCD <= "0000";
end case;
end process;
end PULSADORES;
E
E
E
E
E
E
E
<= "000001";
<= "000010";
<= "000100";
<= "001000";
<= "010000";
<= "100000";
<= "000000";
t on
T = 30 segundos
onda de temporizacin
1 segundo
50 ciclos
C<B
COMPARADOR
seal de Red
B
CODIFICADOR
A3
A 2 A1
0-9
A 0 : consigna de potencia
271
Los niveles de potencia de los cuatro fuegos, fijados en los mandos rotativos (en
codigo Gray) sern ledos dinmicamente, a travs de 4 lneas comunes; tales niveles
sern representados (en decimal, de 0 a 9) en cuatro visualizadores de siete segmentos,
tambin en forma dinmica, a travs de 4 lneas BCD:
E1
mando
GRAY
E2
mando
GRAY
E3
mando
GRAY
E4
E1
E2
E3
E4
mando
GRAY
G
R
A
Y
B
C
D
BCD
a
7 seg.
decodificador
PASO
1s
1 u. de t.
50 ciclos/seg
50
De manera que el circuito integrado completo tendr los siguientes terminales (se
aprovecha como reloj la propia seal de la red elctrica: 50 Hz, 10 ms):
visualizador(3)
visualizador(2)
CK: 50 Hz
RS
visualizador(1)
visualizador(0)
mando(3)
E1
mando(2)
E2
mando(1)
E3
mando(0)
E4
on/off 1
on/off 2
on/off 3
on/off 4
272
Electrnica Digital
in std_logic;
in std_logic_vector( 3 downto 0);
out std_logic_vector( 3 downto 0);
out std_logic );
273
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
=>
274
Electrnica Digital
EEEE <=
use ieee.std_logic_unsigned.all;
entity COMUN is
port ( CK,RS
mando
BCD1,BCD2,BCD3,BCD4
visualizador
E1,E2,E3,E4
PASO
CONSIGNA
end COMUN;
: in std_logic;
: in std_logic_vector(3 downto 0);
: in std_logic_vector(3 downto 0);
: out std_logic_vector(3 downto 0);
: out std_logic;
: out std_logic;
: out std_logic_vector(3 downto 0));
visualizador <=
end ON_OFF;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
=>
CONSIGNA <= "0000";
=>
CONSIGNA <= "0001";
=>
CONSIGNA <= "0010";
=>
CONSIGNA <= "0011";
=>
CONSIGNA <= "0100";
=>
CONSIGNA <= "0101";
=>
CONSIGNA <= "0110";
=>
CONSIGNA <= "0111";
=>
CONSIGNA <= "1000";
=>
CONSIGNA <= "1001";
=>
CONSIGNA <= "0000";
end OPERATIVA;
end if;
275
276
component CONTROL
port ( CK,RS,HAB,PASO
CONSIGNA
ONOFF
BCD
end component;
Electrnica Digital
: in
: in
: out
: out
std_logic;
std_logic_vector (3 downto 0);
std_logic;
std_logic_vector (3 downto 0));
begin
E1 <= E1interior; E2 <= E2interior;
E3 <= E3interior;
E4 <= E4interior;
: in std_logic;
: in std_logic_vector (3 downto 0);
: in std_logic_vector (3 downto 0);
: out std_logic;
: out std_logic_vector (3 downto 0);
: out std_logic_vector(3 downto 0));
U1 : COMUN
port map ( CK=>CK, RS => RS, PASO => PASO, CONSIGNA => CONSIGNA,
BCD1 => BCD1, BCD2 => BCD2, BCD3 => BCD3, BCD4 => BCD4,
E1 => E1interior, E2 => E2interior, E3 => E3interior, E4 => E4interior,
mando => mando, visualizador => visualizador );
U2 : CONTROL
port map ( CK => CK, RS => RS, CONSIGNA => CONSIGNA, PASO=>PASO,
HAB => E1interior, BCD => BCD1, ONOFF => ON_OFF1 );
U3 : CONTROL
port map ( CK => CK, RS => RS, CONSIGNA => CONSIGNA, PASO => PASO,
HAB => E2interior, BCD => BCD2, ONOFF => ON_OFF2 );
U4 : CONTROL
port map ( CK => CK, RS => RS, CONSIGNA => CONSIGNA, PASO => PASO,
HAB => E3interior, BCD => BCD3, ONOFF => ON_OFF3 );
U5 : CONTROL
port map ( CK => CK, RS => RS, CONSIGNA => CONSIGNA, PASO => PASO,
HAB => E4interior, BCD => BCD4, ONOFF => ON_OFF4 );
end CONEXIONES;