miércoles, 28 de enero de 2015

LA VELA MÁGICA: Proyecto de laboratorio

La fotografía fue tomada en Expociencia Juvenil en Corferias donde se presentó este proyecto por parte del Club de Física del INEM Santiago Perez-Tunal de Bogotá:


Veamos los detalles de los elementos que intervienen  en el desarrollo del proyecto:

Se llama fototransistor a un transistor sensible a la luz. La luz incide sobre la región de base, generando portadores en ella. Esta carga de base lleva el transistor al estado de conducción.

En el mercado se encuentran fototransistores tanto con conexión de base como sin ella y tanto en cápsulas plásticas como metálicas (TO-72, TO-5) provistas de una lente.


El símbolo del fototransistor es el mostrado en la figura: 


Para información sobre fototransistor consultar: http://es.wikipedia.org/wiki/Fototransistor

Veamos un esquema eléctrico de la Vela Electrónica:

Como elemento de memoria biestable se utiliza un flip-flop SET RESET Latch implementado con dos compuertas NOR 74LS02:

Observe además  que la base del fototransistor de tres pines  no está conectada. Se deja al aire.

 En lugar del fototransistor se puede utilizar un fotodiodo o una fotoresistencia, en un divisor de tensión. Consultar http://es.wikipedia.org/wiki/Fotodiodo , o, http://es.wikipedia.org/wiki/Fotorresistencia

“La fotorresistencia, como su nombre lo indica, es un resistencia cuyo valor depende de la energía luminosa incidente en ella, específicamente son resistencias cuyo valor de resistividad disminuye a medida que aumenta la energía luminosa incidente sobre ella y viceversa. Una fotorresistencia se compone de un material semiconductor cuya resistencia varia en función de la iluminación. La fotorresistencia reduce su valor resistivo en presencia de rayos luminosos.

Es por ello por lo que también se le llama resistencias dependientes de luz (LDR: light dependent resistors), fotoconductores o células fotoconductoras”.





miércoles, 26 de noviembre de 2014

Máquina ASM en FPGA con VHDL


Veamos el diagrama ASM:

El control en su forma esquemática debe ser tal como se muestra.

El control se puede obtener como una Máquina de Moore así:

El contador C1 tiene dos detectores D1 y D2:


C2  tiene el detector D3:

Se requiere dividir los 50 Mhz para obtener un reloj de 1 HZ:

Se añadió al control una salida para poder manejar el contador C2 mediante su enable:


Se usaron Flip-flops D, en lugar de J-K:

Los flip-flops F1,F2, y F3, tienen códigos idénticos.

Veamos el de F1:

Veamos por último el código VHDL del circuito final interconectando los bloques componentes  anteriores:

Se implementó en la tarjeta Basys 2 Digilent.

Veamos el archivo UCF de asignación de pines en la FPGA:


Veamos el esquemático RTL del circuito final:

viernes, 24 de octubre de 2014

Letrero con matriz de leds en FPGA

Se trata de obtener por pantallazos en una matriz de leds de 7 filas, 5 columnas los caracteres que se muestran: 
  Las 7 filas de la matriz, se conectan a 7 salidas de la FPGA dispuesta en la tarjeta Digilent en sus puertos de expansión.  Los cátodos de los leds, en las columnas se manejan a través de un contador de anillo de 5 bits, activo por nivel bajo.   Sólo una columna se energiza cada vez, pero al hacer la secuencia del contador de anillo muy rápidamente cada 0,01 segundo, el ojo humano, por la persistencia de la imágen en la retina, ve todas las 5 columnas como si estuvieran todas energizadas, y pareciese que todos los Leds que generan el caracter estuvieran encendidos, pero en realidad sólo se estan encendiendo columnna por columna, de acuerdo al CERO que envía el Contador de Anillo a todos los 7 leds de cada columna y aterrizarlos.  Por medio de la FPGA  se envían los UNOS para que se enciendan los leds requeridos para que vaya formando el caracter. Por ejemplo, para formar la U, inicialmente la memoria debe enviarle a los leds de la primera columna 1111110, luego 0000001 a la segunda columna al tiempo que se energiza esa columna por el contador de anillo, después eso mismo a la tercera y cuarta columna a medida que el contador de anillo se desplaza, y al final a los 0,05 segundos, cuando se energiza la quinta columna, la más a la derecha, la memoria debe enviar nuevamente 1111110,  y esto debe  hacerlo repetitivamente unas 20 veces, para que el caracter, en este caso la U se observe durante 1 segundo ( 0,05 * 20 = 1). Luego se continúa en igual forma con los otros dos caracteres, la A y la N, dejando en blanco durante 1 segundo el display, y luego seguir la secuencia  desplegando el mensaje UAN blanco, UAN blanco,.. indefinidamente.

Se utilizó una matriz miniatura 

En la implementación se utlizan 3 puertos de expansión dispuestas en la tarjeta Digilent Basys 2:
Se pueden observar en el gráfico anterior las resistencias de protección contra corto circuitos a las salidas, lo mismo que Diodos de protección ESD a tierra contra descargas electrostáticas.

Veamos la conexión de pines:

Veamos ahora el programa final en VHDL:

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

entity Letrero_UAN is
    Port ( CLOCK50MHZ : in  STD_LOGIC;
           COL : out  STD_LOGIC_VECTOR (4 downto 0);
           FIL : out  STD_LOGIC_VECTOR (6 downto 0));
end Letrero_UAN;

architecture Behavioral of Letrero_UAN is
signal Xclk: STD_LOGIC;
signal Xclk_letras: STD_LOGIC;
signal Xq  : STD_LOGIC_VECTOR (2 downto 0);
signal Xcol: STD_LOGIC_VECTOR (4 downto 0);
signal XSL : STD_LOGIC_VECTOR (1 downto 0);

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

component Cont 
    Port ( Clk : in  STD_LOGIC;
             Q : out  STD_LOGIC_VECTOR (2 downto 0));
 end component;


component anillo
    Port ( Entrada : in  STD_LOGIC_VECTOR (2 downto 0);
           Salida : out  STD_LOGIC_VECTOR (4 downto 0));
end component;

component Memoria 
      Port ( Selector_letra: in STD_LOGIC_VECTOR (1 downto 0);
       Direccion : in  STD_LOGIC_VECTOR (4 downto 0);
           Datos : out  STD_LOGIC_VECTOR (6 downto 0));
end component;

component Cont_letras 
    Port ( CLK_letras : in  STD_LOGIC;
           Q : out  STD_LOGIC_VECTOR (1 downto 0));
end component;

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

begin
paso1: Divisor port map (CLOCK50MHZ, Xclk);
paso2: Cont    port map (Xclk, Xq); 
paso3: anillo  port map (Xq, Xcol);
paso4: Memoria port map (XSL,Xcol, FIL );
paso5: Reloj_letras port map (CLOCK50MHZ, Xclk_letras);
paso6: Cont_letras port map (Xclk_letras, XSL);

COL <= Xcol;

end Behavioral;

El esquemático RTL es el siguiente:

A continuación  el código VHDL de  cada  componente:

-- DIVISOR 1 KHZ

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;
           CLK1khz   : out STD_LOGIC);
end Divisor;

architecture Behavioral of Divisor 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;

................................................................................................................................................

-- CONTADOR DEL 0 AL 4
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Cont is
    Port ( Clk : in  STD_LOGIC;
             Q : out  STD_LOGIC_VECTOR (2 downto 0));
            
end Cont;

architecture Behavioral of Cont is
signal count: STD_LOGIC_VECTOR (2 downto 0);
begin
process (Clk) 
begin
   if count = "101" then 
      count <= "000";
   elsif Clk ='1' and Clk'event then
             count <=  count + 1;
   end if;

end process;
Q <= count;

end Behavioral;

................................................................................................................................................

-- CONTADOR DE ANILLO
-
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity anillo is
    Port ( Entrada : in  STD_LOGIC_VECTOR (2 downto 0);
           Salida : out  STD_LOGIC_VECTOR (4 downto 0));
end anillo;

architecture Behavioral of anillo is

begin
process(Entrada)
begin

            case Entrada is
            when "000" => Salida <= "01111";
            when "001" => Salida <= "10111";
            when "010" => Salida <= "11011";
            when "011" => Salida <= "11101";
            when "100" => Salida <= "11110";
when others => Salida <= "00000";
         end case;

end process;


end Behavioral;

................................................................................................................................................

-- DIVISOR DE 1 HZ 

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

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

architecture Behavioral of Reloj_letras 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;

................................................................................................................................................

-- CONTADOR PARA  DESPLEGAR LAS LETRAS UAN

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


entity Cont_letras is
    Port ( CLK_letras : in  STD_LOGIC;
           Q : out  STD_LOGIC_VECTOR (1 downto 0));
end Cont_letras;

architecture Behavioral of Cont_letras is
signal count: STD_LOGIC_VECTOR (1 downto 0);
begin
process (CLK_letras) 
begin
   if (CLK_letras = '1' and CLK_letras'event) then
      count <= count + 1;
   end if;
end process;

 Q <= count;


end Behavioral;
................................................................................................................................................

-- MEMORIA CON LAS LETRAS A DESPLEGAR

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


entity Memoria is
    Port ( Selector_letra: in STD_LOGIC_VECTOR (1 downto 0);
       Direccion : in  STD_LOGIC_VECTOR (4 downto 0);
           Datos : out  STD_LOGIC_VECTOR (6 downto 0));
end Memoria;


architecture Behavioral of Memoria is
begin

process (Selector_letra,Direccion)
begin
if Selector_letra = "00"  then


         case Direccion is   -- Letra U
            when "01111" => Datos <= "1111110";
            when "10111" => Datos <= "0000001";
            when "11011" => Datos <= "0000001";
            when "11101" => Datos <= "0000001";
when "11110" => Datos <= "1111110";
            when others => Datos <=  "0000000";
         end case;

elsif Selector_letra = "01"  then


          case Direccion is    -- Letra A
            when "01111" => Datos <= "0111111";
            when "10111" => Datos <= "1001000";
            when "11011" => Datos <= "1001000";
            when "11101" => Datos <= "1001000";
when "11110" => Datos <= "0111111";
            when others => Datos <=  "0000000";
         end case;


elsif Selector_letra = "10"  then


  case Direccion is    -- Letra N
            when "01111" => Datos <= "0111111";
            when "10111" => Datos <= "1000000";
            when "11011" => Datos <= "1000000";
            when "11101" => Datos <= "1000000";
when "11110" => Datos <= "0111111";
            when others => Datos <=  "0000000";
         end case;
-- end process ;

else 
   

  case Direccion is  -- Espacio en Blanco
            when "01111" => Datos <= "0000000";
            when "10111" => Datos <= "0000000";
            when "11011" => Datos <= "0000000";
            when "11101" => Datos <= "0000000";
when "11110" => Datos <= "0000000";
            when others => Datos <=  "0000000";
         end case;


End if;

end process ;


end Behavioral;

.....................................................................................................................................................

Fotografía: 




viernes, 22 de noviembre de 2013

Evaluación lúdica sobre Máquinas de Estado Algorítmicas

Para todos  los puntos tenga en cuenta la siguiente información, y marque la respuesta correcta en el test.

El siguiente diagrama ASM  corresponde a un sistema digital donde en el procesador de datos hay un motor DC que se maneja a través de un flip-flop J-K de salida M y un contador de década Ascendente/Descendente: C.    S es un pulsador de inicio (Start) y D1,D2 son detectores para el contador.


Solución:
Respuestas al Test de Selección Múltiple con única respuesta:
1. C     2.C     3.B     4.A     5.D     6.B     7.C     8.A     9.B     10.D     11.C     12.B     13.C     14.B
15.A     16.A     17.B     18.D

Mensaje desencriptado:

miércoles, 20 de noviembre de 2013

Contador de "UNOS" de un registro de 8 bits con VHDL

Se trata de implementar un contador que detecte el número de bits en nivel alto presentes en un registro, para implementar con la FPGA de la tarjeta Digilent Basys 2.

Se hace uso del método de Máquina de Estado Algorítmico ASM.

El ejercicio se plantea y resuelve en el libro Fundamentos de Lógica Digital con diseño VHDL de Stephen Brown y Zvonko Vranesic.

Una máquina ASM dispone de una Unidad de Control y de un procesador de datos.

En el procesador de datos se dispone de un registro A que carga en paralelo los 8 bits Data y además puede desplazar los bits de izquierda a derecha (del más al menos significativo). Con la compuerta NOR de 8 entradas se detecta si A = 0, haciendo Z = 1 cuando ello ocurra. Si el bit menos significativo de A (A0 = 1), un contador B que inicia reseteado al cargar sus 8 bits en cero incrementa. Si Z = 1, quiere decir que A =0, y B indicará el número de "Unos" presentes en el registro A. Un led denominado "Done" indicará que ha finalizado el conteo de bits en nivel alto presentes en A.
El registro A  esquemáticamente es similar a la siguiente figura
 Si L = 1, se carga en los flip-flops los datos R, paralelamente, sin importar el enable E.
Si L = 0, y, E=1, hay corrimiento en este caso desde la entrada serial W a Q0, de Q0 a Q1, de Q1 a Q2, etc.
Si L=0, E=0, las salidas Q de los flip-flops no cambian
aunque se presente el flanco de subida del reloj.

La carta o diagrama ASM es tal como se muestra
S responde a un pulso de inicio (start) para que se inicie el proceso de conteo de los bits en nivel alto presentes en el registro A. Mientras S no sea 1 no comienza el conteo de bits.

La unidad de control sigue un diagrama similar a la carta ASM anterior
Si los enables EA y EB estan en nivel alto A desplaza y B incrementa, siempre y cuando las entradas de carga LA y LB esten en nivel bajo. Z=1 si el registro A tiene sus 8 bits en cero, y la bandera "Done" avisa que el conteo de "unos" ha finalizado.

El libro de Brown muestra el código VHDL para el contador de bits y la siguiente simulación realizada en Altera
Para que Xilinx sintetize el código VHDL del contador de bits completo hay que sintetizar previamente el registro A de desplazamiento a la derecha el cual debe ser empaquetado en la librería de Work para que el código de contador de bits lo pueda llamar y ejecutar.
Veamos el código VHDL del registro llamado reg_derecha  con su empaquetamiento:

--Registro de desplazamiento a la derecha,con carga ---paralela y enable (habilitación)

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL;

entity reg_derecha is
    Port ( R : in  STD_LOGIC_VECTOR (7 downto 0);
           L,E,W : in  STD_LOGIC;
           Clock : in  STD_LOGIC;
               Q : buffer  STD_LOGIC_VECTOR (7 downto 0));
end reg_derecha;

architecture Behavioral of reg_derecha is

begin
  Process
  Begin
   wait until Clock'event and Clock = '1';
   If E = '1' then 
     If L = '1' then Q <= R;
     else
      For i IN 0 to 6 LOOP
      Q(i) <= Q(i+1);
      END LOOP;
      Q(7) <= W;
     END if;
   END if;
 END Process;
end Behavioral;

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL;

PACKAGE reg_derecha_PACKAGE IS
 Component reg_derecha
   Port ( R : in  STD_LOGIC_VECTOR (7 downto 0);
           L,E,W : in  STD_LOGIC;
           Clock : in  STD_LOGIC;
               Q : buffer  STD_LOGIC_VECTOR (7 downto 0));
 END component;
END  reg_derecha_PACKAGE;

Chequeamos sintaxis y sintetizamos, y luego procedemos a elaborar el código VHDL del contador de bits completo así:

--Contador de UNOS para registro de 8 bits
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use work.reg_derecha_PACKAGE.all;

entity bitcount is
    Port ( Clock, Resetn : in  STD_LOGIC;
           LA, S : in  STD_LOGIC;
           Data :  in  STD_LOGIC_VECTOR (7 downto 0);
           B    :  BUFFER   INTEGER RANGE 0 TO 8;
           Done :  out  STD_LOGIC);
end bitcount;

architecture Behavioral of bitcount is
TYPE estado IS (S1,S2,S3);
SIGNAL y: estado;
SIGNAL A: STD_LOGIC_VECTOR (7 downto 0);
SIGNAL  Z,EA,LB,EB,LOW: STD_LOGIC;
begin

CONTROL: PROCESS(Clock, Resetn)
  BEGIN
    IF Resetn = '1' THEN y <= S1;
elsif (Clock'EVENT and Clock = '1') THEN
 CASE y is
  WHEN S1 =>
 if S = '0' then y <= S1; else y <= S2;
                  end if;
WHEN S2 =>
 if Z = '0' then y <= S2; else y <= S3; 
                  end if;
WHEN S3 =>
 if S = '1' then y <= S3; else y <= S1;
                  end if;  
End CASE;
  End if;
End Process;

SALIDAS: PROCESS(y,A(0))
begin
EA <= '0'; LB <= '0'; EB <= '0'; Done <= '0';
CASE y IS
  WHEN S1 => 
   LB <= '1'; 
WHEN S2 => 
   EA <= '1'; 
IF A(0) ='1' THEN EB <= '1'; else EB <= '0'; END IF;
WHEN S3 => 
   Done <= '1'; 
 END CASE;
END PROCESS;

upcount: PROCESS(Resetn, Clock)
begin
 if Resetn = '1' THEN
   B <= 0;
 ELSIF (Clock'EVENT and Clock = '1') THEN
   IF LB = '1' THEN B <= 0;
   ELSIF EB = '1' then B <= B + 1;
   END IF;
 END IF;
END PROCESS;

 LOW <= '0';
 SHIFTA:reg_derecha  
PORT MAP(Data,LA,EA,LOW,Clock,A);
 Z <= '1' when A ="00000000" else '0';

end Behavioral;

El código VHDL completo se sintetiza satisfactoriamente

Desde luego hay que adicionar el divisor de frecuencia de 50 Mhz a 1 hz para poder visualizar en la tarjeta Basys2.

viernes, 8 de noviembre de 2013

Multiplicador binario en VHDL con FPGA de Basys 2

Invito al lector a consultar el interesante artículo de Gerardo Muñoz, ingeniero electrónico egresado de la UAN y actualmente docente investigador de la Universidad Distrital,  : donde se muestra como diseñar un multiplicador binario por máquina de estado algoritmico con VHDL:

Un método simple para pasar de un algoritmo a un modelo VHDL

jueves, 26 de septiembre de 2013

¿ Que tanto sabemos ? Contadores asíncronos y síncronos



Solución:
a) La entrada CLR, activa con nivel ALTO, permite resetear el circuito secuencial, que es un contador binario asíncrono descendente de 3 bits.
b) El bloque Clk1Hz  es un divisor de frecuencia que tiene como entrada el reloj a cristal de 50 Mhz disponible en la tarjeta Basys 2 y como salida 1 Hz. Es imposible crearlo esquemáticamente. Sólo puede realizarse a través de un lenguaje HDL, como VHDL o Verilog.
c) Las ondas deben indicar un contador descendente, que con CLR =1, inicia en 0, y si CLR = 0, cada pulso de subida de reloj cambian en decimal a  6, 5,4,3,2,1,0, 7,6,5,4,3,2,1,0,7,6,5,4,3,2,1,0,...
d) La secuencia que se presenta al ojo humano aparenta un conteo tal como se indicó anteriormente. Sin embargo, debido a los retardos en cascada en los flip-flops, sucede un conteo incorrecto, el cual se evidencia al cambiar los 3 bits, por ejemplo, cuando cambia del 0 al 7, o del 4 al 3.
Veamos el cambio del contador del 0 al 7, cuando comienza a descender:

2. a)

b) Mapas de Karnaugh y  Ecuaciones de entrada de los Flip-flops:
    
  
D ( Q2) =  Q1 Q0 + Q2 Q0' 

D(Q1) = Q2' Q1' Q0 + Q1 Q0' 


D(Q0) = Q0' 


c) Circuito lógico:


Ejercicios prácticos con la terjeta Basys2:
Implementar en esquemático cada uno de los dos contadores y verificar su comportamiento.Es indispensable el divisor de frecuencia que a partir del cristal de 50 Mhz genere la frecuencia de 1 Hz.