lunes, 31 de enero de 2011

PRACTICAS EN XILINX

Aqui estan algunos còdigos de los que hemos desarrollado en clase
Este por ejemplo hace un barrido, eta compuesto por 3 módulos:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;-- PARA TRABAJAR KN COMPUERTAS IF OR...ETC

entity cronometro is
    Port ( clk : in  STD_LOGIC;
           go,clr : in  STD_LOGIC;
           d2,d1,d0 : out  STD_LOGIC_VECTOR (3 downto 0));
end cronometro;

architecture Behavioral of cronometro is

        constant DVSR: integer:=5000000;
        signal ms_reg, ms_next: unsigned(22 downto 0);
        signal d2_reg, d1_reg, d0_reg : unsigned (3 downto 0);
        signal d2_next, d1_next, d0_next: unsigned (3 downto 0);
        signal ms_tick: STD_LOGIC;

begin

--    REGISTRO
  process (clk)
  begin
        if(clk'event and clk='1') then
            ms_reg <= ms_next;
            d2_reg <= d2_next;
            d1_reg <= d1_next;
            d0_reg <= d0_next;
        end if;
              
    end process;  
   
    --hacemos el siguiente estado logico para producir la señal de 0.1 segundos
   
    ms_next<=(others=> '0') when clr='1' or (ms_reg= DVSR and go='1') else
                ms_reg+1 when go='1' else
                ms_reg;
        ms_tick<= '1' when ms_reg = DVSR else '0';
      
        --incrementar de 3 digitos
      
        process (d0_reg, d1_reg, d2_reg, ms_tick, clr)
        begin
                --valores  x defecto
                d0_next<=d0_reg;
                d1_next<=d1_reg;
                d2_next<=d2_reg;
                
            if clr='1' then
              d0_next<= "0000";
                d1_next<="0000";
                d2_next<="0000";
            elsif ms_tick='1' then
                    if(d0_reg /= 9) then --  /= diferente
                        d0_next<=d0_reg+ 1;
                    else --ya alcanzo XX9
                        d0_next<="0000";
                        if(d1_reg /= 9) then --  /= diferente
                            d1_next<=d1_reg+ 1;
                        else --ya alcanzo el estado X99
                            d1_next<="0000";
                                if(d2_reg /= 9) then --  /= diferente
                                d2_next<=d2_reg+ 1;
                                else --ya alcanzo el estado 999
                                d2_next<="0000";
                                end if;
                        end if;
                    end if;
            end if;
    end process;
            -- LA SALIDA LOGICA
                    d0<=STD_LOGIC_VECTOR (d0_reg);
                    d1<=STD_LOGIC_VECTOR (d1_reg);
                    d2<=STD_LOGIC_VECTOR (d2_reg);
              
end Behavioral;



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


entity disp_mux is
    Port ( clk, reset : in  STD_LOGIC;
           bcd0, bcd1, bcd2, bcd3 : in  STD_LOGIC_VECTOR (3 downto 0);
           dp_in : in  STD_LOGIC_VECTOR (3 downto 0);
           sseg : out  STD_LOGIC_VECTOR (7 downto 0);
           comun : out  STD_LOGIC_VECTOR (3 downto 0));
end disp_mux;

architecture Behavioral of disp_mux is

constant N: integer:=18;--tamaño de bits para bajar de frecuencia
signal q_reg, q_next: unsigned ((N-1) downto 0);
signal sel:STD_LOGIC_VECTOR (1 downto 0);
signal bcd:STD_LOGIC_VECTOR (3 downto 0);
signal dp:STD_LOGIC;

begin

-- REGISTRO:
process (clk, reset)
begin
    if reset = '1' then
        q_reg<=(others =>'0');
    elsif (clk'event and clk='1') then
        q_reg<=q_next;
    end if;
end process;

--    PROXIMO ESTADO LOGICO DEL CONTADOR
q_next<= q_reg + 1;

--utilizamos los 2 bits mas signidficativos de las señales
--del registro para hacer el control de la multiplexaion
sel<=std_LOGIC_VECTOR (q_reg(N-1 downto N-2));
process(sel, bcd0,bcd1,bcd2, bcd3)
begin
        case sel is
            when "00"=>
            comun <="1110";
            bcd<=bcd0;
            dp<=dp_in(0);
            when "01"=>
            comun <="1101";
            bcd<=bcd1;
            dp<=dp_in(1);
            when "10"=>
            comun <="1011";
            bcd<=bcd2;
            dp<=dp_in(2);       
            when others =>
            comun <="0111";
            bcd<=bcd3;
            dp<=dp_in(3);
        end case;

end process;

-- DECODIFICADOR DE BCD A 7 SEGMENTOS
        with bcd select
        sseg(6 downto 0) <=       
    --para catodo comun          --gfdecba
                    "0111111"when "0000",--0
                    "0000110"when "0001",--1
                    "1011011"when "0010",
                    "1001111"when "0011",
                    "1100110"when "0100",
                    "1101101"when "0101",
                    "1111101"when "0110",
                    "0000111"when "0111",
                    "1111111"when "1000",
                    "1101111"when "1001",
                    "0000000"when others  ;
                sseg(7)<=dp;          

end Behavioral;




Este es el módulo principal:


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


entity cronostop is
    Port ( clk : in  STD_LOGIC;
           b : in  STD_LOGIC_VECTOR (3 downto 0);
           comun : out  STD_LOGIC_VECTOR (3 downto 0);
           sseg : out  STD_LOGIC_VECTOR (7 downto 0));
end cronostop;

architecture Behavioral of cronostop is

signal d2, d1 , d0: STD_LOGIC_VECTOR (3 downto 0);

begin
    disp_uit: entity work.disp_mux
    port map(
            clk=>clk, reset=>'1',
            bcd3=>"0000",bcd2=>d2, --- para catodo creo 1111
            bcd1=>d1,bcd0=>d0,
            dp_in => "0010", comun=>comun,sseg=>sseg ); -- anodo 1101
   
   
    crono_unit: entity work.cronometro
    port map (
            clk => clk, go=>b(1), clr=> b(0),
            d2=>d2, d1=>d1, d0=>d0    );
   

end Behavioral;

sábado, 29 de enero de 2011

Diseño, construcción y descripción en VHDL de un carro seguidor de líneas y evasor de obstáculos con una FPGA SPARTAN 3E



El proyecto está basado en dos funciones básicas del carro, seguir líneas y evadir obstáculos, dichas funciones se describen mediante dos módulos en VHDL para la implementación en hardware dispusimos de 6 sensores, tres infrarrojos, y tres de fin de carrera. Además de un puente H para el control de los servos.
 
Para conectar el puente H, hacemos lo siguiente: conectamos los pines 1, 8, 9, 16 a alimentación. Los pines 4, 5, 12, 13 van conectados a tierra. Los pines 2, 7, 10, 15 son las entradas uno, dos, tres, y cuatro respectivamente.  Los pines 3, 6, 11, 14 son las salidas uno, dos, tres, y cuatro respectivamente.
En nuestro caso debíamos controlar solo dos servomotores por lo que un puente H era suficiente y su conexión seria  así:

Las salidas de los sensores de fin de carrera van conectados como si fuesen switchs y van a la SPARTAN, en esta se procesan y  sus salidas van conectadas a las entradas del puente H para mover los servos. En esto básicamente se basaría el hardware del evasor de obstáculos.

Una vez controlado la parte del evasor de obstáculos, seguimos con el seguidor de líneas, lo más idóneo fue subdividirlo en secciones, diseñadas dependiendo de las posibles combinaciones realizables de encendido de los tres led’s (mostrando un cero apagado, cuando cualquier sensor está sobre la línea negra, o un uno –encendido, cuando se desvía), al ser tres sensores se crearon las ocho combinaciones siguientes:

Sensores Infrarrojos
Descripción
Izquierdo
Central
Derecho
0
0
0
En medio de un cruce de líneas
0
0
1
En medio de un cruce de líneas
0
1
0
En medio de un cruce de líneas
0
1
1
A la derecha de las líneas
1
0
0
En medio de un cruce de líneas
1
0
1
Sobre la línea
1
1
0
A la izquierda de la línea
1
1
1
Totalmente fuera de las líneas
 
Cuando el carro se encuentre sobre la línea, se mantiene el curso hacia el frente. Cuando el carro se encuentre a la derecha de la línea, se direccionaba hacia la izquierda. Cuando el robot se encontraba a la izquierda de la línea, se direccionaba hacia la derecha. Para el resto de las combinaciones se continuaba con la orden de control anterior.

DISEÑO   O--O

Se comenzó a desarrollar por funciones:
  • Seguir líneas
  • Evadir obstáculos.

La placa que se incorporo al carro se puede visualizar en la siguiente imagen:
 CÓDIGO:
--------------------------------------------
      -- Carrito Seguidor de Lìneas----
----------Evasor de obstáculos-------------
--------------------------------------------

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

entity compl is
    Port ( s_fcc, s_fcd, s_fci, reset, ss, c, i, d : in  STD_LOGIC;
     clk: inout STD_LOGIC;
           e1, e2, e3, e4 : out  STD_LOGIC);
end compl;

architecture Behavioral of compl is

constant N : integer := 28; -- tamaño de bits para bajar de frecuencia
signal a: std_logic;
signal q_reg, q_reg1, q_reg2, q_next, q_next1, q_next2 : unsigned (N-1 downto 0);
signal sel : std_logic_vector (1 downto 0);

begin

process (s_fcc, s_fcd, s_fci,c,d,i,clk,ss,reset)

begin

if (reset = '0') then
---- GIRA ADELANTE

    e1<= '0';
    e2<= '1';
    e3<= '0';
    e4<= '1';

    if (ss= '1') then
   if (s_fcc = '1' ) then
    a<= '1';
         if(clk'event and clk = '1' ) then       
            q_reg  <= q_next;
        end if;
    q_next <= q_reg + 1;
    sel <= std_logic_vector(q_reg(N-1 downto N-2));
   
    case sel is
            when "00"=>
            ---- retrocede
            e1<= '1';
            e2<= '0';
           
            e3<= '1';
            e4<= '0';
           
            when "01" =>
            --- gira derecha
            e1<= '0';
            e2<= '1';
           
            e3<= '1';
            e4<= '0';
           
            when others =>
            ---- GIRA ADELANTE
            e1<= '0';
            e2<= '1';
           
            e3<= '0';
            e4<= '1';
               
    end case;
   
end if;

    if (s_fcd = '1') then
        a<= '1';    
         if(clk'event and clk = '1' ) then
           
            q_reg1  <= q_next1;
           
        end if;
   
    q_next1 <= q_reg1 + 1;

   
    sel <= std_logic_vector(q_reg1(N-1 downto N-2));
    case sel is
            when "00"=>
            ---- retrocede
            e1<= '1';
            e2<= '0';
           
            e3<= '1';
            e4<= '0';
           
            when "01" =>
            --- gira izquierda
            e1<= '0';
            e2<= '1';
           
            e3<= '1';
            e4<= '0';
   

            when "10" =>
            ---- GIRA ADELANTE
            e1<= '0';
            e2<= '1';
           
            e3<= '0';
            e4<= '1';

            q_next1 <= q_reg1;

       
            when others =>

            e1<= '0';
            e2<= '1';
           
            e3<= '0';
            e4<= '1';           
          sel <="00";
            a <='0';
   
end case;
end if;

    if (s_fci = '1') then
    a<= '1';
   
         if(clk'event and clk = '1' and a = '1') then
           
            q_reg2  <= q_next2;
           
        end if;
   
    q_next2 <= q_reg2 + 1;

   
    sel <= std_logic_vector(q_reg2(N-1 downto N-2));
    case sel is
            when "00"=>
            ---- retrocede
            e1<= '1';
            e2<= '0';
           
            e3<= '1';
            e4<= '0';
           
            when "01" =>
            --- gira izquierda
            e1<= '1';
            e2<= '0';
           
            e3<= '0';
            e4<= '1';
   

            when "10" =>
            ---- GIRA ADELANTE
            e1<= '0';
            e2<= '1';
           
            e3<= '0';
            e4<= '1';

            q_next2 <= q_reg2;

       
            when others =>

            e1<= '0';
            e2<= '1';
           
            e3<= '0';
            e4<= '1';           
          sel <="00";
            a <='0';
           
end case;
end if;

else
    if (c = '1' and d = '0' and i= '0') then

    ---- Seguir ADELANTE
            e1<= '0';
            e2<= '1';
           
            e3<= '0';
            e4<= '1';

    end if;

    if (c = '1' and d = '1' and i= '0') then

    --- GIRAR DERECHA
            e1<= '1';
            e2<= '0';
           
            e3<= '0';
            e4<= '1';

    end if;



    if (c = '0' and d = '1' and i= '0') then
        --- GIRAR DERECHA

            e1<= '1';
            e2<= '0';
           
            e3<= '0';
            e4<= '1';

    end if;

    if (c = '0' and d = '0' and i= '1') then
            --- gira izquierda
            e1<= '0';
            e2<= '1';
           
            e3<= '1';
            e4<= '0';

    end if;   

    if (c = '1' and d = '0' and i= '1') then
            --- gira izquierda
            e1<= '0';
            e2<= '1';
           
            e3<= '1';
            e4<= '0';
    end if;
end if;

elsif (reset = '1') then
e1<= '1';
e2<= '1';

e3<= '1';
e4<= '1';
end if;

end process;
end Behavioral;

 
  Conclusiones
·         VHDL es un lenguaje muy poderoso que nos permite describir de manera muy sencilla funciones básicas para el manejo del carro.
·         A los sensores de fin de carrera se los puede ver como switchs para recibir la señal desde la FPGA y luego enviarla a los servomotores.
·         Para la implementación de los circuitos, se debe alimentar con una fuente externa ya que la SPARTAN no proporciona mucha corriente para el movimiento de los servomotores.
·         Es necesario probar cada función por separado y luego unir todo en una sola unidad para poder depurar el programa en caso de errores.