Documente Academic
Documente Profesional
Documente Cultură
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity compuertas is
Port ( X : in STD_LOGIC;
Y : in STD_LOGIC;
end compuertas;
begin
Z(7)<= not X;
Z(6)<= not Y;
Z(5)<= X and Y;
Z(4)<= X or Y;
Z(3)<= X xor Y;
Z(2)<= X nand Y;
Z(1)<= X nor Y;
Z(0)<= X xnor Y;
end Behavioral;
Reloj de 12hrs en VHDL
Objetivo
Diseñar un reloj de tiempo real, donde cada segundo del reloj sea un segundo real. El reloj debe
ser de 24 horas.
Material
6 Display ánodo común de 12.7mm modelo DA05
6 Resistencia de 220Ω
Batería 9V
1 Oscilador de cristal con salida de señal cuadrada
Fuente de 5V
Circuito integrado 7448
CPLD
Max-Plus II
Procedimiento
El primer paso para lograr nuestro objetivo es la programación en VHDL en Max-Plus II.
Obteniendo los siguientes programas.
Este programa es un divisor de frecuencia el cual de la frecuencia de 4Mhz que se recibe del
oscilador se obtiene una salida de 1 Mhz necesaria para nuestro propósito. El cual puede ser
modificado si el reloj no va en el tiempo adecuado.
------------------------------------------------------------------------------------------------------------
--DIVISOR DE FRECUENCIA
LIBRARY ieee;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_1164.all;
ENTITY clk_seg IS
PORT(
clock : IN BIT;
Segundo : OUT BIT
);
END clk_seg;
ARCHITECTURE a OF clk_seg IS
BEGIN PROCESS (clock)
VARIABLE CONTEO_MAX: INTEGER;
BEGIN
IF (clock = '1' AND clock'event) THEN
CONTEO_MAX := CONTEO_MAX+1;
END IF;
IF (CONTEO_MAX > 39) THEN
segundo<= '1';
ELSE IF(CONTEO_MAX=40) THEN
CONTEO_MAX:=0;
segundo<='1';
ELSE
segundo<='0';
END IF;
END IF;
END PROCESS;
END a;
------------------------------------------------------------------------------------------------------------
Luego se debe de hacer un programa para que cuente de 0 a 9 que es el caso e las unidades
--CONTEO DE UNIDADES
ENTITY MOD_10 IS
PORT(
clock :IN BIT;
CONTEO_MAX,
q0, q1, q2, q3: OUT BIT);
END MOD_10;
ARCHITECTURE a OF MOD_10 IS
BEGIN PROCESS (clock)
VARIABLE count: BIT_VECTOR(3 DOWNTO 0);
VARIABLE x1: BIT;
BEGIN IF (clock = '1' AND clock'event) THEN
CASE count IS
WHEN "0000"=> count:="0001"; x1:='0';
WHEN "0001"=> count:="0010"; x1:='0';
WHEN "0010"=> count:="0011"; x1:='0';
WHEN "0011"=> count:="0100"; x1:='0';
WHEN "0100"=> count:="0101"; x1:='0';
WHEN "0101"=> count:="0110"; x1:='0';
WHEN "0110"=> count:="0111"; x1:='0';
WHEN "0111"=> count:="1000"; x1:='0';
WHEN "1000"=> count:="1001"; x1:='0';
WHEN OTHERS=> count:="0000"; x1:='1';
END CASE;
END IF;
CONTEO_MAX<=x1;
q0 <= count(0);
q1 <= count(1);
q2 <= count(2);
q3 <= count(3);
END PROCESS;
END a;
------------------------------------------------------------------------------------------------------------
Ahora un programa para que cuente las decenas
------------------------------------------------------------------------------------------------------------
--CONTEO DE DECENAS
ENTITY MOD_6 IS
PORT(
clock :IN BIT;
CONTEO_MAX, q0, q1, q2, q3: OUT BIT
);
END MOD_6;
ARCHITECTURE a OF MOD_6 IS
BEGIN PROCESS (clock)
VARIABLE count: BIT_VECTOR(3 DOWNTO 0);
VARIABLE x1: BIT;
BEGIN
IF (clock = '1' AND clock'event) THEN
CASE count IS
WHEN "0000"=> count:="0001"; x1:='0';
WHEN "0001"=> count:="0010"; x1:='0';
WHEN "0010"=> count:="0011"; x1:='0';
WHEN "0011"=> count:="0100"; x1:='0';
WHEN "0100"=> count:="0101"; x1:='0';
WHEN OTHERS=> count:="0000"; x1:='1';
END CASE;
END IF;
CONTEO_MAX<=x1;
q0 <= count(0);
q1 <= count(1);
q2 <= count(2);
q3 <= count(3);
END PROCESS;
END a;
------------------------------------------------------------------------------------------------------------
Al final por cuestiones de espacio colocamos uno doble para el conteo de 24 horas
------------------------------------------------------------------------------------------------------------
ENTITY MOD_12 IS
PORT(
clock :IN BIT;
q0, q1, q2, q3, d0, d1, d2, d3: OUT BIT);
END MOD_12;
ARCHITECTURE a OF MOD_12 IS
BEGIN PROCESS (clock)
VARIABLE count, unit, dec: BIT_VECTOR(3 DOWNTO 0);
VARIABLE x1: BIT;
END PROCESS;
END a;
------------------------------------------------------------------------------------------------------------
Luego se utilizo un multiplexor
------------------------------------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_1164.all;
ENTITY clk_multiplex IS
PORT(
clock, su0,su1,su2,su3
,sd0,sd1,sd2,sd3
,mu0,mu1,mu2,mu3,md0,md1,md2,md3,hu0,hu1,hu2,hu3,hd0,hd
1,hd2,hd3
:IN BIT;
s0, s1, s2, s3 : OUT BIT
);
END clk_multiplex;
ARCHITECTURE a OF clk_multiplex IS
BEGIN PROCESS (clock)
VARIABLE count : BIT_VECTOR(2 DOWNTO 0);
VARIABLE CONTEO_MAX: INTEGER;
VARIABLE result: BIT_VECTOR(3 DOWNTO 0);
BEGIN
IF (clock = '1' AND clock'event) THEN
CONTEO_MAX := CONTEO_MAX+1;
END IF;
IF (CONTEO_MAX = 1) THEN
CONTEO_MAX:= 0;
CASE count IS
WHEN "000" => count:="001";
result:=sd0&sd1&sd2&sd3;
WHEN "001" => count:="010";
result:=mu0&mu1&mu2&mu3;
WHEN "010" => count:="011";
result:=md0&md1&md2&md3;
WHEN "011" => count:="100";
result:=hu0&hu1&hu2&hu3;
WHEN "100" => count:="101";
result:=hd0&hd1&hd2&hd3;
WHEN OTHERS=> count:="000";
result:=su0&su1&su2&su3;
END CASE;
END IF;
s0 <= result(0);
s1 <= result(1);
s2 <= result(2);
s3 <= result(3);
END PROCESS;
END a;
------------------------------------------------------------------------------------------------------------
El cual recibe 4 bit de cada programa dando un total de 25 entradas y los combina para
obtener 4 salidas las cuales se colocaran a un 7448 para obtener 6 salidas una correspondiente
para cada display.
El contador
La entidad del contador se describe en la figura 2, donde se observa que
solamente tiene dos entradas: el reloj de 1 Hz (o 1 segundo) y la señal de reset.
Las salidas corresponden a los cuatro digitos: dos para mostrar la hora y dos para
mostrar los minutos.
Figura 2: Entradas y salidas del contador.
Existen diversas formas para realizar el contador del reloj, todas con ventajas y
desventajas. En esta entrada se optó por usar cuatro contadores independientes
(uno por dígito) para evitar posteriores conversiones de números binarios a BCD.
El listado 1 muestra el código utilizado para crear el contador para nuestro reloj.
1 library IEEE;
2 use IEEE.NUMERIC_STD.ALL;
3 use IEEE.STD_LOGIC_1164.ALL;
4
entity contador_reloj is
5
PORT (
6
clk : IN STD_LOGIC; --Reloj de 1Hz.
7
reset: IN STD_LOGIC; --Señal de reset.
8
H1 : OUT STD_LOGIC_VECTOR(2 DOWNTO 0); --Segundo digito de la hora.
9
H0 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0); --Primer digito de la hora.
10
M1 : OUT STD_LOGIC_VECTOR(2 DOWNTO 0); --Segundo digito de los minutos.
11 M0 : OUT STD_LOGIC_VECTOR(3 DOWNTO 0) --Primer digito de los minutos.
12 );
13 end contador_reloj;
14
35 end if;
if hh0 = 9 then
36
hh1 <= hh1 + 1;
37
hh0 <= "0000";
38
end if;
39
-- Al pasar 23:59, regresar a 00:00.
40 if hh1 = 2 AND hh0 = 3 AND mm1 = 5 AND mm0 = 9 then
41 hh1 <= "000";
43 end if;
end if;
44 end process;
45
46 --Asignación de señales.
H1 <= STD_LOGIC_VECTOR(hh1);
47
H0 <= STD_LOGIC_VECTOR(hh0);
48
M1 <= STD_LOGIC_VECTOR(mm1);
49
M0 <= STD_LOGIC_VECTOR(mm0);
50
end Behavioral;
51
52
53
54
55
56
contador1Hz=50MHz1Hz=50000000
talto=tbajo=500000002=25000000
Y dado que empezamos el conteo desde cero, nuestra nueva constante para el
reloj es 24 999 999.
(Aunque es sólo copiar el módulo del divisor de 200Hz y cambiar unas cuantas
cosas, aquí dejo el código correspondiente al divisor de 1 Hz).
Uniéndolo todo
Ahora que ya tenemos todos los bloques necesarios, sólamente falta enlazarlos.
Esto se realiza mediante un nuevo archivo, denominado reloj.vhd, que contiene
los PORT MAP correspondientes, como se muestra en el listado 3.
1 library IEEE;
2 use IEEE.STD_LOGIC_1164.ALL;
4 entity reloj is
5 PORT(
6 clk : IN STD_LOGIC;
7 reset : IN STD_LOGIC;
);
10
end reloj;
11
12
architecture Behavioral of reloj is
13
COMPONENT clk1Hz IS
14
PORT (
15
entrada: IN STD_LOGIC;
16
reset : IN STD_LOGIC;
17 salida : OUT STD_LOGIC
18 );
19 END COMPONENT;
20
21 COMPONENT contador_reloj IS
22 PORT (
23 clk : IN STD_LOGIC;
24 reset: IN STD_LOGIC;
31 COMPONENT siete_segmentos_completo IS
32 PORT (
33 clk : IN STD_LOGIC;
34 reset : IN STD_LOGIC;
);
41
END COMPONENT;
42
43
signal clk_out : STD_LOGIC := '0';
44
signal HH1, MM1: STD_LOGIC_VECTOR(2 downto 0);
45
signal HH0, MM0: STD_LOGIC_VECTOR(3 downto 0);
46 signal pHH1, pHH0, pMM1, pMM0: STD_LOGIC_VECTOR(5 downto 0);
47 begin
48 --PORT MAPs necesarios para habilitar el reloj.
52
--Padding de las señales del contador para siete segmentos.
53
pHH1 <= "000" & HH1;
54
pHH0 <= "00" & HH0;
55
pMM1 <= "000" & MM1;
56
pMM0 <= "00" & MM0;
57
end Behavioral;
58
59
60
61
Implementación en Basys2
Para probar nuestro gran diseño digital en la tarjeta Basys2 es necesario crear un
archivo deconstraints que enlacen las señales de salida a puertos en el FPGA. El
contenido del archivo se muestra en el listado 4 mientras que en la figura 3 se
muestra el resultado de dicha implementación.
12 # Multiplexor #########################
0
inShare
En este breve artículo se describe un divisor de frecuencia con VHDL, así como
el proceso mediante el cual se obtiene el factor de escalamiento deseado.
Descargar 1.07 KB
Los cálculos
El divisor de frecuencia es un componente simple, cuyo objetivo es reducir la
frecuencia de entrada. Éste se implementa con ayuda del factor de escalamiento y
un contador. Primeramente, el factor de escalamiento es la relación entre la
frecuencia de entrada y la frecuencia de salida deseada:
Escala=fentradafdeseada
Asumiendo que tenemos una frecuencia de 50MHz y deseamos una salida
de 200Hz, tenemos que:
Escala=50MHz200Hz=250000
Por lo tanto, el contador para el divisor de frecuencia tiene como función generar
la señal de salida de 200Hz cada 250000 ciclos.
El código
Sin más preámbulo, el Listado 1 muestra el código fuente para el divisor de
frecuencia.
1 library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
2
3
entity clk200Hz is
4
Port (
5
entrada: in STD_LOGIC;
6
reset : in STD_LOGIC;
7
salida : out STD_LOGIC
8
);
9 end clk200Hz;
10
14 begin
22 else
27
salida <= temporal;
28 end Behavioral;
29
30
31
La simulación
Con ayuda del software de Xilinx ISE (versión 13.1), se genera un test bench o
banco de pruebas cuyo objetivo es demostrar la veracidad de lo que acábo de
decir (una simulación). Por fortuna el software hace la mayoría de la tarea, de
igual forma el código se muestra en el listado 2.
Listado 2: Banco de pruebas del divisor de frecuencia.
LIBRARY ieee;
1
USE ieee.std_logic_1164.ALL;
2
3
ENTITY clk200Hz_tb IS
4
END clk200Hz_tb;
5
9 entrada : IN std_logic;
10 reset : IN std_logic;
12 );
END COMPONENT;
13
14
-- Entradas
15
signal entrada : std_logic := '0';
16
signal reset : std_logic := '0';
17
-- Salidas
18 signal salida : std_logic;
19 constant entrada_t : time := 20 ns;
20 BEGIN
27
-- Definición del reloj.
28 entrada_process :process
29 begin
35 -- Procesamiento de estímulos.
36 estimulos: process
37 begin
44
45
46
47
Para terminar, una imagen de los resultados de la simulación (véase la figura 1).