jueves, 23 de junio de 2016

¿ Qué tanto sabemos de microelectrónica, FPGA con VHDL ?

Test de autoevaluación de 20 preguntas de selección multiple

Veamos por el momento las 9 primeras preguntas con sus respuestas explicadas




Para los puntos del 12 al  16 tenga en cuenta el siguiente código correspondiente a un algoritmo del conversor de Binario a BCD de 8 bits:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Conv_Bin_BCD is
    Port ( Bin : in   STD_LOGIC_VECTOR (7 downto 0);
           Cen :    out  STD_LOGIC_VECTOR (3 downto 0);
           Dec :    out  STD_LOGIC_VECTOR (3 downto 0);
Uni :   out  STD_LOGIC_VECTOR (3 downto 0));
end    Conv_Bin_BCD;

architecture Behavioral of Conv_Bin_BCD is
begin
Process(Bin)
variable Z: STD_LOGIC_VECTOR (19 downto 0);
 begin
 for i in 0 to 19 loop
 Z(i) := '0';
 end loop;

 Z(10 downto 3) := Bin;
 
 for i in 0 to 4 loop
                                            if Z(11 downto 8) > 4 then
                             Z(11 downto 8) := Z(11 downto 8) + 3;
 end if;
                             
                             if Z(15 downto 12) > 4 then  Z(15 downto 12) := Z(15 downto 12) + 3;
    end if;
                             
                             Z(17 downto 1) := Z(16 downto 0);
  end  loop;
   
                                Cen <= Z(19 downto 16);
  Dec <= Z(15 downto 12);
                           Uni <= Z(11 downto 8);
end Process; 

end Behavioral;





RESPUESTAS    EXPLICADAS

1.  ( D )          I  es falsa, porque R es la entrada binaria mas significativa y no P.
                      II es falsa, porque con dos bits no se puede obtener en binario el decimal 5.

2.   ( C )        I es verdadera, puesto que el led con ánodo a Vcc enciende con los ceros
                     II es falsa, puesto que Z es una señal interna para interconectar la salida de un Mux21 a la entrada Mux21 del siguiente Mux21, lo cual sólamente puede suceder si R = 0.

3.    ( C )        I  es falsa, porque un.Mux21 tiene 3 entradas, las dos de datos y la de selección.
                      II  es verdadera, puesto que el circuito final tiene como entradas P y R, y una salida;L

4.    ( C )      I  es falsa, porque Z y W no son variables, sino señales internas SIGNAL.
                    II  es verdadera, puesto que el circuito final se requieren tres pasos, para conectar Vcc y Gnd a las entradas de los mux21 iniciales, interconectar los mux21 entre si por medio de las señales             internas, y las entradas R y P, y salida L a cada uno de los multiplexores.

5.    ( C )     Es la única expresión con la sintasis correcta  exigida en programación VHDL.

6.    ( B )    La ecuación  Booleana para el  Mux21 es: Y = S' A  +  S B, que para su esquemático requiere una OR de 2 entradas, dos AND de 2 entradas y un inversor.

7     ( C )    El archiivo UCF permite introducir como entradas P y R de la FPGA a los interruptores de la tarjeta  Basys 2  y la salida L del circuito final a un Led de la FPGA.

8    ( A )   La entrada Clear es asíncrona y prioritaria, activa con nivel bajo.

9    ( A )    Si Clear  y T está en nivel alto, el flip flop cambia de nivel lógico al producirse el flanco de bajada del reloj, según la notación establecida para el esquemático indicado en la figura.

10   ( B )  Q1 hace el togle y pasa a nivel alto porque su entrada T está conectada a Vcc. Si X está a nivel bajo lo mismo que Q1 a la salida de la Xor hay un cero lógico, y al estar T en cero lógico, Q0 sigue en cero

11.  Si Q1 está en nivel alto y T a Vcc en el flanco de reloj Q1 debe pasar a nivel bajo. Si X está en uno lógico y Q1 también a la salida de la Xor hay un cero, y al estar la entrada T en cero, Q0 debe permanecer en nivel alto. En realidad la respuesta sería la D, pero quedó mal redactada; lo correcto sería Q1 pasa a nivel bajo y Q0 sigue en nivel alto.

12.  ( A )  I y II son verdaderas, son pasos fundamentales en el algoritmo.

13.  ( B )   Se desplaza el binario 3 bits a la izquierda. Los bits 0,1 y 2 del binario, ahora serán 3,4 y 5 en la variable Z.

14.  ( B )  Un loop del 0 al 4  se ejecuta 5 veces.

15. ( A )  Sumar a un binario 3 cuando es mayor de 4 y desplazarlo a la izquierda equivale a sumarle 6 si es mayor de 9, lo cual es lo requerido para convertir el binario a BCD cuando es mayor de 9.

16.  ( B )  I es verdadero y II es falso.Si todos los bits se desplazan a la izquierda, necesariamente los bits de las decenas y unidades deben cambiar.

17.  ( A )  I y II son verdaderas. Para proteger la tarjeta Basys 2 al manejar AC en una salida se recomienda optoacoplamiento y fuente de voltaje DC externo.

18. ( B )  I es verdadero y II es falso. La FPGA no tiene problemas para trabajar a la frecuencia de 50 Mhz, pero el ojo humano a esa frecuencia no percibe parpadeo en un led,por lo que se requiere bajar la frecuencia a 1 hz por medio de un divisor.

19.  ( D )   El full adder requiere los 2 bits a sumar, Cin, S y Cout.

20.  ( B)   11 + 14 = 25 = 16 +  9. Si omitimos el bit mas significativo queda sólo 9 = (1001) en binario.

viernes, 10 de junio de 2016

Conversor binario BCD de 8 bits en VHDL

El objetivo es implementar en la FPGA disponible en la  tarjeta Basys 2, Digilent,  y utilizando el software Xilinx ISE, un conversor de Binario a BCD, que al introducir en binario un Byte, por medio de los 8 interruptores disponibles en la tarjeta de desarrollo, se pueda visualizar en tres displays de 7 segmentos de la tarjeta, el respectivo número decimal que corresponda al número binario introducido de 8 bits. Los decimales visualizados en los displays estan comprendidos desde el 000 hasta el 255. 

Se tiene en cuenta el siguiente diagrama esquematico:


Elaboramos el código en VHDL del conversor de Binario a BCD de acuerdo al algoritmo de sumar 3 y desplazar cada 4 bits, para lo cual hacemos uso de una VARIABLE de 20 bits, que llamamos la variable Z, y que debe contener los 8 bits del binario a convertir, y los 12 bits del BCD: 4 bits de las centenas, 4 bits de las decenas y los 4 bits de las unidades.  Cada vez que en BCD se detecte un número mayor de 4 se le suma 3 y se desplaza, lo cual equivale a sumar 6, lo cual es lo requerido para efectuar la conversión de binario a BCD para cada 4 bits.  Inicialmente la variable Z se pone en ceros, y luego desplaza los tres primeros bits, antes de averiguar si el número es mayor de 4, para sumarle tres y desplazarlo en caso que lo sea.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity Conv_Bin_BCD is
    Port ( Bin : in   STD_LOGIC_VECTOR (7 downto 0);
           Cen : out  STD_LOGIC_VECTOR (3 downto 0);
           Dec : out  STD_LOGIC_VECTOR (3 downto 0);
           Uni : out  STD_LOGIC_VECTOR (3 downto 0));
end Conv_Bin_BCD;

architecture Behavioral of Conv_Bin_BCD is

begin

Process(Bin)
variable Z: STD_LOGIC_VECTOR (19 downto 0);
begin

 for i in 0 to 19 loop
 Z(i) := '0';
 end loop;

 Z(10 downto 3) := Bin;


 for i in 0 to 4 loop

    if Z(11 downto 8) > 4 then
Z(11 downto 8) := Z(11 downto 8) + 3;
end if;

if Z(15 downto 12) > 4 then
Z(15 downto 12) := Z(15 downto 12) + 3;
    end if;

Z(17 downto 1) := Z(16 downto 0);
  end  loop;
   

 
  Cen <= Z(19 downto 16);
  Dec <= Z(15 downto 12);
  Uni <= Z(11 downto 8);
end Process;
end Behavioral;

Luego seguimos con un Multiplexor de 3 entradas/ 1 salida , y como selector la salida de un contador ascendente binario del 0 al 2, cuyo reloj tiene una frecuencia de 1 khz, para poder lograr la visualización dinámica para el manejo de los displays de 7 segmentos:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Mux_31 is
    Port ( C : in  STD_LOGIC_VECTOR (3 downto 0);
           D : in  STD_LOGIC_VECTOR (3 downto 0);
           U : in  STD_LOGIC_VECTOR (3 downto 0);
           Selectores : in  STD_LOGIC_VECTOR (1 downto 0);
           Salidas : out  STD_LOGIC_VECTOR (3 downto 0));
end Mux_31;

architecture Behavioral of Mux_31 is

begin
process (Selectores,C,D,U)
begin
   case Selectores is
      when "00" => Salidas <= C;
      when "01" => Salidas <= D;
      when "10" => Salidas <= U;
      when others => Salidas <= "0000";
   end case;
end process;

end Behavioral;

De acuerdo al esquemático que nos sirve de guía seguimos con el decodificador de BCD a 7 segmentos:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Dec7seg is
port(  BCD: in  STD_LOGIC_VECTOR (3 downto 0);
       led: out STD_LOGIC_VECTOR(6 downto 0) ); 
 end Dec7seg;
 
architecture comportamiento of Dec7seg is
begin
 process (BCD)
begin
case BCD is
  when "0000" => LED <=  "0000001"; --0
  when "0001" => LED <=  "1001111"; --1
  when "0010" => LED <=  "0010010"; --2
  when "0011" => LED <=  "0000110"; --3
  when "0100" => LED <=  "1001100"; --4 
  when "0101" => LED <=  "0100100"; --5
  when "0110" => LED <=  "0100000"; --6
  when "0111" => LED <=  "0001111"; --7
  when "1000" => LED <=  "0000000"; --8
  when "1001" => LED <=  "0001100"; --9
  when others => LED <=  "0001100"; --9
end case;
end process ;
end comportamiento;

Continuamos ahora con el Divisor de frecuencia del clock de 50 Mhz a 1 Khz:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity RELOJ1KHZ is
    Port ( CLK50MHZ : in  STD_LOGIC;
           CLK1KHZ : out  STD_LOGIC);
end RELOJ1KHZ;

architecture Behavioral of RELOJ1KHZ is
signal pulso: STD_LOGIC := '0';
signal contador: integer range 0 to 24999 := 0;

begin
process (CLK50Mhz)
begin
if (CLK50Mhz'event and CLK50Mhz = '1') then 
if (contador = 24999) then
                pulso <= NOT(pulso);
                contador <= 0;
            else
                contador <= contador+1;
            end if;
    end if;
  end process;
 CLK1KHZ <=  pulso;

end Behavioral;


El esquemático nos muestra ahora que seguimos con el contador del 0 al 2:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Cont_0al2 is
    Port ( Clk : in   STD_LOGIC;
           Q : inout  STD_LOGIC_VECTOR (1 downto 0));
end Cont_0al2;

architecture Behavioral of Cont_0al2 is

begin
process (Clk) 
begin
   if Clk ='1' and Clk'event then
if Q = "11" then Q <= "00";
    else
Q <= Q + 1;
   end if;
  end if;
end process;

end Behavioral;

Finalmente requerimos manejar los ánodos de los displays de 7 segmentos, ánodo común, para lograr el efecto de persistencia de la imágen en la retina requerido para la visualización dinámica:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Anodos_displays is
    Port ( Input : in  STD_LOGIC_VECTOR(1 downto 0);
           Anodos : out  STD_LOGIC_VECTOR (3 downto 0));
end Anodos_displays;

architecture Behavioral of Anodos_displays is

begin
process(Input)
begin
         case Input is
            when "00" => Anodos <= "0111";
            when "01" => Anodos <= "1011";
            when "10" => Anodos <= "1101";
            when others => Anodos <= "1111";
         end case;
Anodos(0) <= '1';
end process;
   
end Behavioral;

Luego procedemos a elaborar el código del circuito final que utilice los seis componentes descritos anteriormente y que cumpla con las conexiones, señales internas, entradas y salidas, descritas en el esquemático que nos ha servido de guía en el diseño:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity Final is
    Port ( Binario : in  STD_LOGIC_VECTOR (7 downto 0);
           Reloj50mhz : in  STD_LOGIC;
           Catodos : out  STD_LOGIC_VECTOR (6 downto 0);
           Anodos : out  STD_LOGIC_VECTOR (3 downto 0));
end Final;

architecture Behavioral of Final is
Signal XCen, XDec, XUni, XBCD: STD_LOGIC_VECTOR (3 downto 0);
Signal X1khz : STD_LOGIC;
Signal XQ: STD_LOGIC_VECTOR (1 downto 0);

Component Conv_Bin_BCD 
    Port ( Bin : in  STD_LOGIC_VECTOR (7 downto 0);
           Cen : out  STD_LOGIC_VECTOR (3 downto 0);
           Dec : out  STD_LOGIC_VECTOR (3 downto 0);
           Uni : out  STD_LOGIC_VECTOR (3 downto 0));
end Component;

Component Mux_31 
    Port ( C : in  STD_LOGIC_VECTOR (3 downto 0);
           D : in  STD_LOGIC_VECTOR (3 downto 0);
           U : in  STD_LOGIC_VECTOR (3 downto 0);
           Selectores : in  STD_LOGIC_VECTOR (1 downto 0);
           Salidas : out  STD_LOGIC_VECTOR (3 downto 0));
end Component;

Component Dec7seg 
port(  BCD: in  STD_LOGIC_VECTOR (3 downto 0);
       led: out STD_LOGIC_VECTOR(6 downto 0) ); 
end Component;

Component RELOJ1KHZ 
    Port ( CLK50MHZ : in  STD_LOGIC;
           CLK1KHZ : out  STD_LOGIC);
end Component;

Component Cont_0al2 
    Port ( Clk : in   STD_LOGIC;
           Q : inout  STD_LOGIC_VECTOR (1 downto 0));
end Component;

Component Anodos_displays
    Port ( Input : in  STD_LOGIC_VECTOR(1 downto 0);
           Anodos : out  STD_LOGIC_VECTOR (3 downto 0));
end Component;

begin

paso1: Conv_Bin_BCD PORT MAP (Binario, XCen, XDec, XUni);
paso2: Mux_31       PORT MAP (XCen, XDec, XUni, XQ, XBCD );
paso3: Dec7seg      PORT MAP (XBCD, Catodos);
paso4: RELOJ1KHZ    PORT MAP (Reloj50mhz, X1khz);
paso5: Cont_0al2    PORT MAP (X1khz,XQ);
paso6: Anodos_displays PORT MAP (XQ, Anodos);

end Behavioral;


Tenemos que tener el archivo UCF que describa los pines de la FPGA que voy a utilizar como entradas  y salidas:

#PACE: Start of Constraints generated by PACE

#PACE: Start of PACE I/O Pin Assignments
NET "Anodos<0>"   LOC = "F12"  ;
NET "Anodos<1>"   LOC = "J12"  ;
NET "Anodos<2>"   LOC = "M13"  ;
NET "Anodos<3>"   LOC = "K14"  ;
NET "catodos<0>"  LOC = "M12"  ;
NET "catodos<1>"  LOC = "L13"  ;
NET "catodos<2>"  LOC = "P12"  ;
NET "catodos<3>"  LOC = "N11"  ;
NET "catodos<4>"  LOC = "N14"  ;
NET "catodos<5>"  LOC = "H12"  ;
NET "catodos<6>"  LOC = "L14"  ;
NET "Reloj50mhz"  LOC = "B8"   ;
NET "Binario<7>"  LOC = "N3"   ;
NET "Binario<6>"  LOC = "E2"   ;
NET "Binario<5>"  LOC = "F3"   ;
NET "Binario<4>"  LOC = "G3"   ;
NET "Binario<3>"  LOC = "B4"   ;
NET "Binario<2>"  LOC = "K3"   ;
NET "Binario<1>"  LOC = "L3"   ;
NET "Binario<0>"  LOC = "P11"  ;

#PACE: Start of PACE Area Constraints

#PACE: Start of PACE Prohibit Constraints

#PACE: End of Constraints generated by PAC

sábado, 21 de mayo de 2016

Visualización de Fecha en displays de 7 segmentos: año,mes,dia.

Ejercicio para subir nota, para presentar en clase el miercoles 25 de mayo:

 Elaborar un programa en VHDL  que permita visualizar en los 4 displays de 7 segmentos, disponibles en la tarjeta Basys 2 Digilent,  el año, el mes y el dia. Si un boton pulsador no se acciona debe aparecer el año: 2016, y se acciona el pulsador debe visualizarse  en los dos primeros displays  el mes: 05, y en los dos ultimos displays el dia:25.


Ayudas:

1. Se sugiere analizar el siguiente esquemático:


2. Sintetizar el código para cada uno de los seis componentes.
3. Elaborar el programa final utilizando los componentes y señales indicados.

martes, 17 de mayo de 2016

Contador del 0 al 99 con VHDL en FPGA de la tarjeta Basys 2

Comenzamos el diseño en nuestro proyecto que hemos llamado contador_BCD, creando una nueva fuente  Contador  con el codigo en VHDL de un contador BCD de 2 dígitos: decenas y unidades, el cual dispone de una entrada de reloj de 1 Hz, y de entradas adicionales sincrónicas  de Clear y Enable, para poderlo reiniciar e inhabilitar cuando se requiera.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Contador is
    Port ( clock : in  STD_LOGIC;
           Clear, Enable : in  STD_LOGIC;
           Dec,Uni : inout  STD_LOGIC_VECTOR (3 DOWNTO 0));
end Contador;

architecture Behavioral of Contador is
begin
  PROCESS(clock)
  begin
   if clock'event and clock = '1' then
  if Clear = '1' then
   Dec <= "0000"; Uni <= "0000";
elsif Enable = '1' then
   if Uni = "1001" then 
      Uni <= "0000";
if Dec = "1001" then
   Dec <= "0000";
else
                Dec <= Dec + '1';
             end if;
else
          Uni <= Uni + '1';
end if;  
end if;
     end if;
  end PROCESS;  
 end  Behavioral;

Las decenas y unidades en BCD del contador  se declaran en la entidad como inout (entrada/salida) y son vectores de 4 bits.

En el proceso se considera que en el flanco de subida del reloj, si la entrada Clear es de nivel alto, las decenas y unidades del contador se hacen igual a cero.  

Luego se observa en el código que para que el contador trabaje se requiere que la entrada de habilitación Enable esté en nivel alto, estando la entrada Clear en nivel bajo.

Para comprender la esencia del código es importante analizar el siguiente diagrama de flujo:

Al llegar el flanco de subida del reloj de 1 Hz, si el Clear = 0, y el Enable = 1,  las unidades del contador se incrementan cada segundo, y al llegar al 9, (1001) en binario, las unidades se resetean y las decenas se incrementan. Esta situación hace que el contador pase del 09 al 10, y así sucesivamente, luego pase del 19 al 20, etc. Al llegar al 99 pasará al 00. 

Este código debe salvarse y sintetizarse para ser utilizado luego como componente del programa final que busca visualizar en dos de los  displays de 7 segmentos disponibles en la tarjeta Basys 2 el conteo de decenas y unidades desde el 00 al 99.

Requerimos además adicionar una fuente con el código del divisor que convierte el reloj de cristal  de 50 Mhz disponible en la tarjeta Basys 2 a la frecuencia de 1 Hz requerido para que el conteo de las unidades se haga cada segundo:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Divisor is
    Port ( CLK50Mhz : in  STD_LOGIC;
           CLK1hz   : out STD_LOGIC);
end Divisor;

architecture Behavioral of Divisor is
signal pulso: STD_LOGIC := '0';
signal contador: integer range 0 to 24999999 := 0;

begin
process (CLK50Mhz)
begin
if (CLK50Mhz'event and CLK50Mhz = '1') then 
if (contador = 24999999) then
                pulso <= NOT(pulso);
                contador <= 0;
            else
                contador <= contador+1;
            end if;
    end if;
  end process;
 CLK1hz <=  pulso;
end Behavioral;

Este código deberá guardarse y sintetizarse, asignandole módulo de nivel superior Set as Top Module para poderlo hacer.

Como ya se ha estudiado anteriormente en este código se produce un pulso de 1 segundo de periodo de reloj,  por cada cincuenta millones de pulsos del cristal de 50 Mhz. 

Se requiere ahora como un tercer componente utilizar un multiplexor de 2 a 1, que permita seleccionar las decenas o las unidades para enviarlas a sus displays respectivos:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Mux21 is
    Port ( Decenas  : in  STD_LOGIC_VECTOR (3 downto 0);
           Unidades : in  STD_LOGIC_VECTOR (3 downto 0);
   Selector : in  STD_LOGIC;
           Salidas  : out  STD_LOGIC_VECTOR (3 downto 0));
end Mux21;

architecture Behavioral of Mux21 is

begin

 Salidas <= Decenas WHEN Selector = '0' ELSE 
           Unidades ; 

end Behavioral;

Este código que debe haberse guardado y sintetizado, permite con el Selector = 0,  que las Decenas del contador pasen a las Salidas, y con Selector = 1 lo hagan las unidades.

Se requiere ahora como cuarto componente sintetizar el decodificador que convierta el binario disponible en las decenas y unidades a lo exigido en los leds del display de 7 segmentos, ánodo común, para visualizar los dígitos desde el 0 hasta el 9.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Dec7segm_hex is
port(  BINARIO: in  STD_LOGIC_VECTOR (3 downto 0);
       led: out STD_LOGIC_VECTOR(6 downto 0) ); 
 end Dec7segm_hex;

architecture comportamiento of Dec7segm_hex is
begin
 process (BINARIO)
begin
case BINARIO is
  when "0000" => LED <=  "0000001"; --0
  when "0001" => LED <=  "1001111"; --1
  when "0010" => LED <=  "0010010"; --2
  when "0011" => LED <=  "0000110"; --3
  when "0100" => LED <=  "1001100"; --4 
  when "0101" => LED <=  "0100100"; --5
  when "0110" => LED <=  "0100000"; --6
  when "0111" => LED <=  "0001111"; --7
  when "1000" => LED <=  "0000000"; --8
  when "1001" => LED <=  "0001100"; --9
  when "1010" => LED <=  "0001000"; --A
  when "1011" => LED <=  "1100000"; --b  
  when "1100" => LED <=  "0110001"; --C   
  when "1101" => LED <=  "1000010"; --d    
  when "1110" => LED <=  "0110000"; --E 
  when others => LED <=  "0111000"; --F
end case;
end process ;
end comportamiento;

Aunque sólo se requiere visualizar los números del 0 al 9, adicionamos una fuente que ya se tenía, con el código dea un decodificador de 7 segmentos para el hexadecimal.

Un quinto componente indispensable para lograr la visualización dinámica que permita ver encendido los dos displays mostrando las decenas y unidades del contador es un RELOJ de 1 KHZ, que produce un periodo de 1 milisegundo. Como la persistencia de la imágen en la retina del ojo humano es de una décima de segundo, este tiempo que es cien veces mas pequeño, nos hará ver encendido el display que en la realidad está apagado.

Este periodo de 1 ms será entonces el Selector del Multiplexor de 2 a 1. 

Se utiliza como reloj de 1 Khz  un código análogo al del Divisor, sólo que en lugar de dividir por 50 millones, lo hace ahora por 50 mil.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity RELOJ1KHZ is
    Port ( CLK50MHZ : in  STD_LOGIC;
           CLK1KHZ : out  STD_LOGIC);
end RELOJ1KHZ;

architecture Behavioral of RELOJ1KHZ is
signal pulso: STD_LOGIC := '0';
signal contador: integer range 0 to 24999 := 0;

begin
process (CLK50Mhz)
begin
if (CLK50Mhz'event and CLK50Mhz = '1') then 
if (contador = 24999) then
                pulso <= NOT(pulso);
                contador <= 0;
            else
                contador <= contador+1;
            end if;
    end if;
  end process;

Al igual que el Multiplexor 2 a 1 debe trabajar a una frecuencia de 1 KHZ, así mismo lo deben  hacer los ánodos que son los que habilitan a traves de transistores PNP a los displays de 7 segmentos.

Esto hace que se requiera un sexto componente,  los Anodos de los displays, para que sincronizadamente con el multiplexor tambien esten cambiando cada milésima de segundo.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity Anodos_displays is
port( input: in std_logic;
      anodo: out std_logic_vector(3 downto 0));
end Anodos_displays;

architecture Behavioral of Anodos_displays is

begin
process(input)
begin
          case input is
            when '0' => anodo <= "0111";
            when others => anodo <= "1011";
           
         end case;
   
end process;

end Behavioral;

Recuerde que para que el transistor PNP se sature y por consiguiente permita que le llegue la alimentación de 3.3 voltios al ánodo de led del display debe existir un cero lógico entre base y colector del transistor. Con el 1 lógico, el display está desactivado, al estar desconectado el ánodo del display al voltaje de alimentación.

Procedemos despues de haber sintetizado los seis componentes a elaborar el código del circuito Final que obedezca el siguiente esquemático:


En este circuito final en la entidad se deben declarar como entradas el Reloj de 50 Mhz, el Clear y el Enable, y como salidas los cátodos de los displays de 7 segmentos, y los Änodos de los mismos.

Así mismo se utilizan como señales internas para interconectar los seis componentes:  X1hz, XDec, XUni, X1khz, y  XBin.

El código Final es el siguiente:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity final is
    Port ( Reloj50mhz, Clear,Enable : in  STD_LOGIC;
           Anodos : out  STD_LOGIC_VECTOR (3 downto 0);
           catodos : out  STD_LOGIC_VECTOR (6 downto 0));
end final;

architecture Behavioral of final is
signal X1hz,X1khz: std_logic;
signal XDec: STD_LOGIC_VECTOR (3 downto 0);
signal XUni: STD_LOGIC_VECTOR (3 downto 0);
signal XBin: STD_LOGIC_VECTOR (3 downto 0);

component Divisor 
    Port ( CLK50Mhz : in  STD_LOGIC;
           CLK1hz   : out STD_LOGIC);
end component;

component Contador 
    Port ( clock : in  STD_LOGIC;
           Clear, Enable : in  STD_LOGIC;
           Dec,Uni : inout  STD_LOGIC_VECTOR (3 DOWNTO 0));
end component;

component Mux21 
    Port ( Decenas  : in  STD_LOGIC_VECTOR (3 downto 0);
           Unidades : in  STD_LOGIC_VECTOR (3 downto 0);
 Selector : in  STD_LOGIC;
           Salidas  : out  STD_LOGIC_VECTOR (3 downto 0));
end component;

component Dec7segm_hex 
port(  BINARIO: in  STD_LOGIC_VECTOR (3 downto 0);
       led: out STD_LOGIC_VECTOR(6 downto 0) ); 
end component;

component RELOJ1KHZ 
    Port ( CLK50MHZ : in  STD_LOGIC;
           CLK1KHZ : out  STD_LOGIC);
end component;

component Anodos_displays 
port( input: in std_logic;
      anodo: out std_logic_vector(3 downto 0));
end component;

begin
paso1: Divisor         PORT MAP (Reloj50mhz, X1hz);
paso2: Contador        PORT MAP (X1hz,Clear,Enable,XDec,XUni);
paso3: Mux21           PORT MAP (XDec,XUni,X1khz,XBin);
paso4: Dec7segm_hex    PORT MAP (XBin,catodos);
paso5: RELOJ1KHZ       PORT MAP (Reloj50mhz, X1khz);
paso6: Anodos_displays PORT MAP (X1khz,Anodos);
end Behavioral;

Al salvar y sintetizar este código, se observa que este programa fin integra los seis componentes en seis pasos:


Para crear el archivo final.ucf hay que asignar pines como User Constrains (Restricciones de Usuario)

Al editar como texto este archivo de asignacion de pines se obtiene:


Lo que sigue es implementar el diseño, generar el archivo de programación, y una vez encendida la tarjeta Basys 2 configurarla debidamente:

Al efectuar la implementación del diseño aparece una advertencia respecto a lo demasiado angosto del pulso de 1 Hz, lo cual no es inconveniente para nuestro caso.

Luego se llama al ADEPT para la programación de la FPGA con el archivo final.bit.

Se debe verificar el excelente desempeño de la tarjeta al visualizarse en los displays el conteo desde el 00 al 99. 

martes, 10 de mayo de 2016

Contador binario ascendente síncrono con flip-flops T en esquemático

En el contador síncrono todas las entradas de reloj de los flip flops T se encuentran unidas entre sí. De esta forma se evita que  por retardos en cascada  de los flip-flops que el contador cuente en forma errada como lo hace el contador asíncrono.

Mediante tabla de estados y de excitación del flip flop T  se llega al siguiente esquemático utilizando el flip flop T con clear,  FTC, disponible en el Xilinx ISE:



Se sintetiza este archivo.sch  y se crea su símbolo esquemático.

Se crea nueva fuente en modulo VHD y se sintetiza el divisor que convierte los 50 Mhz a 1 Hz:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Divisor is
    Port ( CLK50Mhz : in  STD_LOGIC;
           CLK1hz   : BUFFER STD_LOGIC);
end Divisor;

architecture Behavioral of Divisor is
signal pulso: STD_LOGIC := '0';
signal contador: integer range 0 to 24999999 := 0;

begin
process (CLK50Mhz)
begin
if (CLK50Mhz'event and CLK50Mhz = '1') then 
if (contador = 24999999) then
                pulso <= NOT(pulso);
                contador <= 0;
            else
                contador <= contador+1;
            end if;
    end if;
  end process;
 CLK1hz <=  pulso;
end Behavioral;

Este archivo se sintetiza y luego se crea su símbolo esquemático.

Luego se crea un nuevo archivo esquemático, adicionando al contador el divisor:
Queda listo para implementarlo asignando pines y hacerlo trabajar con la FPGA en la Basys 2.

viernes, 29 de abril de 2016

Esquemático general: Ayuda para implementar el Contador ascendente del 0 al 15 con visualización en dos displays


Estacionarias dobles con optoacoplador en FPGA de Basys 2

Con el navegador de proyectos de Xilinx ISE 10.1  creamos como nuevo proyecto: LedParpadeo, y como nueva fuente en Módulo VHDL: clk1Hz. 

Copiamos y pegamos el programa ya visto, salvamos y chequeamos sintaxis

Para este caso no es necesario efectuar la simulación.

Procedemos a elaborar la síntesis y la asignación de pines. El pin del  Clock de 50 MHZ  es B8.

Procedemos ahora a estudiar la salida optoacoplada con el chip de 4 pines PC817, el cual se muestra en la figura siguiente: 


El chip PC817 dispone internamente de un diodo infrarojo y un fototransistor tal como se muestra en el siguiente diagrama



En muchas ocasiones se hace indispensable, para evitar ruidos que pueden incidir en un mal funcionamiento de un circuito secuencial, el uso de un optoacoplador que aisle la carga del circuito secuencial. Para este situación es muy util implementar una salida optoacoplada con el PC817, tal como se muestra en el siguiente esquema para manejar a traves de un relé de 5 voltios  una bombilla azul y otra roja, a 120 voltios AC.


Si la Entrada es 0 el relé está desenergizado y se activa la bombilla roja, y si la entrada es 1 se energiza el relé y se activa la bombilla roja.  Como el motor funciona al crearse un campo electromagnético en el,  si no existiera el aislamiento eléctrico causará ruido y molestaría en el circuito lógico que lo está activando, y por la alta corriente exigida dañaría la salida de la FPGA.

 El  Optoacoplamiento, quiere decir que el acoplamiento de las bombillas con el circuito lógico que lo activa, se hace en forma óptica, a través del diodo infrarojo y el fototransistor que existen en el interior del chip de 4 pines PC817. Con el 0 lógico el led infrarojo no emite luz, y el fototransistor está abierto, en cambio, si se tiene un 1 lógico a la entrada, el led emite luz. y el fototransistor conduce.


Observe además que se están utilizando  tanto los contactos normalmente abiertos como los normalmente cerrados, o sea los 5 pines de que dispone el relé de 5 voltios.El diodo de conmutacion dispuesto inversamente y en paralelo con la bobina del relevo actúa como supresor de picos de corriente cotrarrestando la Ley de Lenz (  VL = - L di / dt), y evitando que el voltaje autoinducido negativo que se genera en la bobina del relevo queme el transistor 2N2222A que se está utilizando como interface entre la salida del optoacoplador y la bobina o entrada del relevo.

Mas información sobre este interesante tema del optoacoplamiento se puede obtener en http://es.wikipedia.org/wiki/Optoacoplador