martes, 22 de noviembre de 2016

MANEJO DE 7 SEGMENTO CON TECLADO MATRICIAL


La siguiente entrada es sobre la constituciĆ³n de unas de las notas esenciales del curos que estamos en desarrollo para generar insumos que son Ćŗtiles para el proyecto final que hablaremos en otra entrada en el blog. En este taller el objetivo es familiarizarse con el desarrollo de interfaces de entrada y salida en VHDL para la tarjeta Nexys 4.


FUNCIONALIDAD:
El propĆ³sito es conectar un teclado matricial 4 X 4 (TM4)  al puerto PMOD JA de la tarjeta Nexys 4. Cada vez que se presione una tecla, su valor se mostrara en el display de siete segmentos (D7S) numero  0, el ultimo visto desde la derecha del conjunto de display.
A continuaciĆ³n le mostraremos el funcionamiento del teclado matricial 4 X 4 que estĆ” constituido por una matriz de pulsadores dispuestos en filas (A, B, C, D) y columnas (1, 2, 3, 4), con la intensiĆ³n de reducir el nĆŗmero de pines necesarios para su conexiĆ³n.


TECLADO MATRICIAL
Su funcionamiento es muy sencillo, cuando se presione una tecla, se conectan internamente la fila y columna correspondiente; por ejemplo, al presionar la tecla “7” se conectan la fila c y la columna 1, si no hay ninguna tecla presionada, las filas estarĆ”n desconectadas de las columnas. 
 

Cuando se presiona una tecla de corriente puede fluir a travĆ©s del switch y el voltaje de los pines conectados a las filas del teclado (5 V o nivel alto) aparece tambiĆ©n ahora uno de los pines RB0 a RB3 segĆŗn la columna en la que se encuentre la tecla oprimida. La siguiente imagen ilustra lo que sucede al oprimir una tecla: al oprimir el botĆ³n 6 provocamos un cambio en el pin RB2 que ahora recibe un 1 lĆ³gico o estado alto. Sabes entonces que se ha pulsado un botĆ³n en la segunda columna y se muestra como un nivel lĆ³gico alto aparece en los bits menos significativos del puerto B, especĆ­ficamente en RB2. 


Diagrama de flujos del teclado matricial 

 

Display 7 segmentos
Es un componente que se utiliza para la representaciĆ³n de nĆŗmeros o letras en muchos dispositivos electrĆ³nicos. La decodificaciĆ³n que se utiliza para pasar a un nĆŗmero de BCD a 7 segmentos tiene la siguiente combinaciĆ³n que va hacer ilustrada a continuaciĆ³n:

 

A continuaciĆ³n les mostramos el diagrama de bloques que representa la conexiĆ³n del teclado matricial al display de 7 segmentos.

 

Le vamos a dejar la pĆ”gina donde pueden entrar y leer todo sobre la FPGA Nexys  4 Artix  https://sites.google.com/site/logicaprogramable/calculadoras/fpga/nexys-4-artix-7-fpga-board y asĆ­ familiarizarse mĆ”s a fondo sobre este dispositivo.
CODIGO EN VHDL  PARA IMPLEMENTAR EL PROBLEMA PLANTEADO:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL
entity teclado is
    port (
    ledfila, ledcol : out unsigned(3 downto 0);
        clk     : in std_logic;
        reset   : in std_logic;
            fila    : in unsigned(3 downto 0);
            col     : out unsigned(2 downto 0);
            display : out std_logic_vector(7 downto 0);
            seg7    : out std_logic_vector(6 downto 0)
    );
end teclado;

En esta primera parte del cĆ³digo se colocan las variables que son de salida o que son de entrada que son el reloj (CLK), reset, fila, columna (col), display es el que me define que display vamos a usar y  7 segmentos (seg7) es el que dice el nĆŗmero a mostrar.
architecture teclado of teclado is
    type estado is (reposo, inicio, cuenta, rotacion, deteccionFilaCol, deteccionTecla, mostrar);
    signal estadoActual, estadoSiguiente : estado;
    signal scol            : unsigned(2 downto 0);
    signal scol4 : unsigned(3 downto 0);
    signal nfila : unsigned(3 downto 0);
    signal tecla : unsigned(3 downto 0);
    signal multi : unsigned(7 downto 0);
    signal contador : unsigned(21 downto 0);
    constant U0L : unsigned(21 downto 0) := to_unsigned(0,22)
    constant U0 : unsigned(3 downto 0) := to_unsigned(0,4);
    constant U11: unsigned (3 downto 0) := to_unsigned (11,4);
    constant U1 : unsigned(3 downto 0) := to_unsigned(1,4);
    constant U2 : unsigned(3 downto 0) := to_unsigned(2,4);
    constant U3 : unsigned(3 downto 0) := to_unsigned(3,4);
    constant U4 : unsigned(3 downto 0) := to_unsigned(4,4);
    constant U5 : unsigned(3 downto 0) := to_unsigned(5,4);
    constant U6 : unsigned(3 downto 0) := to_unsigned(6,4);
    constant U7 : unsigned(3 downto 0) := to_unsigned(7,4);
    constant U8 : unsigned(3 downto 0) := to_unsigned(8,4);
    constant U9 : unsigned(3 downto 0) := to_unsigned(9,4);
    constant U12: unsigned(3 downto 0) := to_unsigned (12,4);
    constant U10: unsigned (3 downto 0) := to_unsigned (10,4);

En esta parte del programa ya viene la arquitectura, se habla sobre todos los estados que vienen siendo reposo, inicio, cuenta, rotaciĆ³n, decodificaciĆ³n fila-columna, detenciĆ³n tecla y mostrar. TambiĆ©n se encuentran las seƱales como seƱal de estado actual y como seƱal de estado siguientes, donde se indican cada seƱal dependiendo de lo que se quiera realizar, tenga en cuenta que en VHDL siempre se tiene que manejar las variables del mismo tamaƱo.

begin
ledfila <= fila;
ledcol <= '1' & scol;
    display <= "11110110";
    col <= scol;
    multi <= U3*nfila;
    -- camino de datos (datapath)
    process(clk, estadoActual,tecla,scol,fila)
      begin
       if (clk'event and clk = '1') then
         case estadoActual is
             when reposo =>
                      scol <= "111"
  contador <= U0L;
             when inicio =>
                      scol <= "011";
             when cuenta =>
                  contador <= contador+1;
             when rotacion =>
                  scol <= scol(1 downto 0) & scol(2);
                  contador <= U0L;
                 when deteccionFilaCol =>
                  case fila is        
                      when "0111" => nfila <= U0;
                                      when "1011" => nfila <= U1;
                      when "1101" => nfila <= U2;
                      when "1110" => nfila <= U3;
                     when others => nfila <= U10;
                  end case;
                  case scol is        
                      when "011" => scol4 <= U0;
                              when "101" => scol4 <= U1;
                      when "110" => scol4 <= U2;
                      when others => scol4 <= U0;
                  end case;

                 when deteccionTecla =>
                  if fila(3)='0' then
                     tecla <= U0;
                  else
                     tecla <= scol4 + U1 + multi(3 downto 0);
                  end if;
             when mostrar =>
                  case tecla is        
                      when U11 => seg7 <= "1111001";  -- 1 working
                      when U8 => seg7 <= "0011001";  -- 4 working
                      when U5 => seg7 <= "0111000";  -- 7 working
                      when U12 => seg7 <= "0110000";  -- 3
                      when U7 => seg7 <= "0010010";  -- 5 working
                      when U4 => seg7 <= "0000000";  -- 8 working
                      When U10 => seg7 <= "0100100";  -- 2 working
                      --When U3 => seg7 <= "1110000"; -- no se
                      when U9 => seg7 <= "0000010";  -- 6 working
                      when U6 => seg7 <= "0011000";  -- 9 working
                      when others => seg7 <= "1000000";  -- *, #
                  end case;
           end case;
         end if;
    end process;

Seguimos con los caminos de datos que es lo que se va a realizar dentro de un estado, es decir que si en el estado de rotaciĆ³n se rota algĆŗn nĆŗmero eso es lo que se va a operar en el estado.
    -- registro de estado
    process(clk, reset)
    begin
        if (reset = '1') then
            estadoActual <= reposo;
        elsif (clk'event and clk = '1') then
            estadoActual <= estadoSiguiente;
        end if;
    end process;

    process (estadoActual,fila,contador) is
    begin

Continuamos con el registro de estado, en este estado lo que hace es guardar la variable y dƔndole funcionalidad al reloj, es decir que de un esta actual cambia al siguiente y que si se hace un reset vuelva a reposo
      case estadoActual is      
        when reposo => estadoSiguiente <= inicio;
        when inicio => estadoSiguiente <= cuenta;
        when cuenta =>
           if contador = "1111111111111111111111" then
               estadoSiguiente <= rotacion;
           else
           estadoSiguiente <= cuenta;
           end if;
        when rotacion =>
           if (fila = "1111") then
              estadoSiguiente <= cuenta;
           else
              estadoSiguiente <= deteccionFilaCol;
           end if;
        when deteccionFilaCol =>
              estadoSiguiente <= deteccionTecla;
        when deteccionTecla =>
              estadoSiguiente <= mostrar;
        when mostrar =>
              estadoSiguiente <= inicio;
     end case;
   end process;
end teclado;

Por Ćŗltimo se encuentra el diagrama de estados donde se encuentra un process, donde son los procesos que estĆ”n dentro de procesos que influirĆ”n sobre el mismo programa a realizar 


CONSTRAINT
set_property LOC E3 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]
# Mapear RESET a BTND
set_property LOC V10 [get_ports reset]
set_property IOSTANDARD LVCMOS33 [get_ports reset]
set_property PACKAGE_PIN B13 [get_ports {col[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {col[0]}]
set_property PACKAGE_PIN F14 [get_ports {col[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {col[1]}]
set_property PACKAGE_PIN D17 [get_ports {col[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {col[2]}]
set_property PACKAGE_PIN G13 [get_ports {fila[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {fila[0]}]
set_property PACKAGE_PIN C17 [get_ports {fila[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {fila[1]}]
set_property PACKAGE_PIN D18 [get_ports {fila[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {fila[2]}]
set_property PACKAGE_PIN E18 [get_ports {fila[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {fila[3]}]
set_property PACKAGE_PIN L3 [get_ports {seg7[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg7[0]}]
set_property PACKAGE_PIN N1 [get_ports {seg7[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg7[1]}]
set_property PACKAGE_PIN L5 [get_ports {seg7[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg7[2]}]
#set_property SEVERITY {warning} [get_drc_checks NSTD-1]
#set_property SEVERITY {warning} [get_drc_checks UCIO-1]
set_property PACKAGE_PIN L4 [get_ports {seg7[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg7[3]}]
set_property PACKAGE_PIN K3 [get_ports {seg7[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg7[4]}]
set_property PACKAGE_PIN M2 [get_ports {seg7[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg7[5]}]
set_property PACKAGE_PIN L6 [get_ports {seg7[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {seg7[6]}]
set_property PACKAGE_PIN N6 [get_ports {display[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display[0]}]
set_property PACKAGE_PIN M6 [get_ports {display[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display[1]}]
set_property PACKAGE_PIN M3 [get_ports {display[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display[2]}]
set_property PACKAGE_PIN N5 [get_ports {display[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display[3]}]
set_property PACKAGE_PIN N2 [get_ports {display[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display[4]}]
set_property PACKAGE_PIN N4 [get_ports {display[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display[5]}]
set_property PACKAGE_PIN L1 [get_ports {display[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display[6]}]
set_property PACKAGE_PIN M1 [get_ports {display[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {display[7]}]
set_property PACKAGE_PIN T8 [get_ports {ledcol[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ledcol[0]}]
set_property PACKAGE_PIN V9 [get_ports {ledcol[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ledcol[1]}]
set_property PACKAGE_PIN R8 [get_ports {ledcol[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ledcol[2]}]
set_property PACKAGE_PIN T6 [get_ports {ledcol[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ledcol[3]}]
set_property PACKAGE_PIN P2 [get_ports {ledfila[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ledfila[0]}]
set_property PACKAGE_PIN R2 [get_ports {ledfila[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ledfila[1]}]
set_property PACKAGE_PIN U1 [get_ports {ledfila[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ledfila[2]}]
set_property PACKAGE_PIN P5 [get_ports {ledfila[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {ledfila[3]}]

En el constraint es la asignaciĆ³n de puerto de la FPGA, asignamos el puerto pmog que por donde nosotros conectamos el teclado matricial.
A continuaciĆ³n le ilustraremos la entidad del problema  y tambiĆ©n el diagrama de estados: 

 



1 comentario:

  1. disculpa una pregunta cuando declaras " display : out std_logic_vector(7 downto 0) " , que quieres decir con eso? que salidas seran?

    ResponderEliminar