Skip to content

CT.3: Pines de Entrada Salida

Juan Gonzalez-Gomez edited this page Apr 6, 2024 · 121 revisions

Descripción

Los pines de la FPGA se pueden configurar como entradas, salidas o entrada/salida. La configuración bidireccional de los pines es muy importante para implementar controladores de buses, como por ejemplo el I2C, 1-wire, LCDs, etc. Aprenderemos cómo configurarlos en Icestudio

Historial

  • 2019-Abril-20: Version inicial del cuaderno técnico
  • 2024-Abril-05:
    • Ejemplos adaptados a la nueva toolchain: apio-0.9.3. Eliminado el error en la verificación. Probados con icestudio 0.11.3wip (futura versión 0.12). Los pantallazos de los ejemplos no se han actualizado todavía
    • Todos los bloques InOut se han actualizado con los de la versión 0.2 de la colección iceIO

Colección y ejemplos

  • iceIO: Todos los bloques relacionados con la entrada/salida están disponibles en la colección iceIO, junto con algunos ejemplos

  • Todos los ejemplos están disponibles en este repositorio

Contenido

Pines

Los chips se comunican con el exterior a través de sus pines. Cuando los datos salen del chip hacia el exterior, se denominan pines de salida. Cuando los datos entran desde el exterior hacia el chip, se denominan pines de entrada

En muchos chips, hay pines que se puede usar tanto para salida como para entrada, comportándose bidireccionalmente. Se denominan pines de Entrada/salida (I/O pins)

Si bien los pines de entrada o salida los conectamos directametne a nuestros circuitos, sin ningún problema, NO podemos hacer lo mismo con los de E/S. Tenemos que configurarlos y gestionar su dirección en cada momento. Necesitamos usar puertas tri-estado

Puertas tri-estado

Todos los circuitos digitales funcionan internamente con bits, que pueden estar en dos estados 0 ó 1. Para interconectar chips entre sí, es muy útil añadir un tercer estado: desconectado. Así, un pin de salida, por ejemplo, podría sacar un 0, un 1 o estar físicamente desconectado

Esa es la misión de la puerta triestado. Tiene 2 entradas y una salida. Los bits sólo pueden fluir de la entrada a la salida cuando la entrada de control, que se denomina habilitación de salida, está activada. Se comporta como un puente levadizo

Cuando la salida NO está habilitada, no hay conexión entre la entrada y salida de la puerta tri-estado y por tanto los bits no pueden salir. Cuando la puerta está en este estado se dice que está en alta impedancia

Al habilitar la salida, el puente levadizo baja y los bits pueden circular en el sentido entrada salida. El estado de la salida será 0 ó 1, según el bit que se esté sacando

Bloques PIO

Las FPGAs tienen unos bloques especializados en entrada/salida que están junto a los pines. En las FPGAs de la familia ice40 de Lattice se denominan PIOs (Programable Input-Outputs). Otros fabricamentes los llaman IOBs (Input-Output blocks)

En cada bloque PIO hay una puerta tri-estado para que los pines sean de entrada/salida. En la familia ice40 sólo hay puertas tri-estado en esos bloques y NO en el interior. Por eso sólo se pueden usar para salir hacia el exterior y no en otras partes de nuestros diseños

Este es un esquema simplificado del interior de un PIO. Hay más cosas, pero nos centraremos sólo en lo relativo a los pines de E/S. Nuestros circuitos sacan los bits a enviar hacia el exterior por dout. Con oe bajamos el puente levadizo. Y por din llegan los datos del exterior

Configuración como pin de entrada

Para que el pin se configure como entrada, hay que desconectar dout (levantar el puente levadizo) poniendo oe a 0. Todos los bits que lleguen por el pin accederán a nuestros circuitos a través de din

Por defecto, cuando hacemos un circuito que accede a las entradas (sólo modo entrada) el sintetizador te configura automáticamente el pin como entrada poniendo oe a 0. En tu circuito no tienes que hacer nada

Configuración como pin de salida

Para que un pin se configure como salida, se conecta dout al pin a través de la puerta tri-estado (bajando el puente levadizo). Se hace poniendo oe a 1. Todos los bits enviados por dout salen al exterior del chip

Cuando en nuestro circuito conectamos un cable a una salida, el sintetizador lo conecta internamente a la señal dout del bloque PIO asociado a ese pin y activa la señal oe. El circuito no tiene que hacer nada con dout ni con oe. Todo lo gestiona el sintetizador

Trabajando con pines de E/S

Para trabajar con pines de E/S es necesario que nuestro circuito, de forma explícita, tome el control de las señales dout, din y oe. Ahora el sintetizador no lo configurará por nosotros, sino que es el propio circuito el que debe decidir cuándo configurar el pin como salida y cuándo como entrada

Para leer desde el exterior (pin de entrada) debe desactivarse oe. Lo que entra por el pin le llega a nuestro circuito por din. El caso de salida es ligeramente diferente. Al activar oe, los datos de dout se sacan por el pin, pero también entran por din. Es la lógica del circuito la que debe interpretar correctamente los datos. Cuando está como salida, lo que llegue por din se debe ignorar

En este ejemplo, se activa el pin como salida (oe=1) y se envía primero un 0 y luego un 1 por dout. Estos valores salen por el pin hacia el exterior. Pero también se reciben por din. Normalmente cuando el circuito envía al exterior se ignora lo que llega por din

Entrada/salida en Icestudio

En icestudio tenemos acceso a las señales din, dout y oe a través del bloque InOut

Bloque InOut

El bloque InOut está disponible en la colección Jedi 1.4.0 en el menú Pines/In-out. Es un bloque de color amarillo, diferente al resto porque es especial: Sólo se puede usar si se le conectar un pin físico a su puerto pin. En los bloques típicos de icestudio lo que está a la izquierda es siempre entrada. En el caso de este bloque esa norma no vale. El puerto pin se corresponde con un pin físico real, que puede ser tanto de entrada como de salida

El resto de puertos ya los conocemos: dout para sacar bits, oe para habilitar la salida y din para recibir bits. En realidad InOut representa un bloque PIO, aunque sólo con los puertos necesarios para trabajar con entrada/salida (El bloque PIO real tiene más cosas)

Bloque InOut-right

El bloque InOut-right es exactamente igual que el Inout, pero con el pin en la parte de la derecha. Y es lo mismo que antes: es un pin de entrada/salida aunque esté en la parte de salidas. En nuestros diseños podemos elegir uno u otro según nos convenga el cableado

Ejemplos de entrada

Vamos con los experimentos. Empezamos por lo que ya conocemos: usar un pin como entrada

Ejemplo 1: Pin de entrada. Configuración automática

Usaremos este circuito de ejemplo. La entrada está conectada a un pulsador externo en D13. Al apretarse se captura un '1' en el biestable D y se enciende un LED interno de la placa

(01-pin-entrada-test-1.ice)

Lo que nos interesa en este ejemplo es el la entrada. El sintetizador conecta la señal din del bloque PIO del pin D13 a la entrada de nuestro circuito, y coloca un 0 en oe para configurarlo como entrada. Nuestro circuito no tiene que gestionar nada

Ejemplo 2: Pin de entrada. Configuración manual

El pin D13 lo configuramos manualmente como entrada sin más que añadir el bloque InOut. Conectamos su entrada pin a la entrada D13, oe a 0, din a la entrada de nuestro circuito (en este ejemplo al controlador del pulsador) y dout lo dejamos desconectado

(02-pin-entrada-test-2.ice)

Este circuito es equivalente al ejemplo 1 (consume los mismos recursos), pero lo hemos configurado nosotros. El bloque InOut es especial (por eso es amarillo) y debe estar asociado siempre a un pin real

Si conectamos cualquier otra cosa que no sea un pin real, a su entrada pin, obtendremos el siguiente error:

ERROR: No wire found for port PACKAGE_PIN on destination cell

Imaginemos que en nuestro circuito queremos negar la entrada. Si colocamos la puerta NOT a continuación del bloque entrada... se producirá el error. ¡Es incorrecto! El bloque InOut es un bloque PIO, y está asociado SIEMPRE a un pin físico. Por lo que a su entrada pin debe conectarse bien a un bloque de entrada o de salida

Ejemplos de salida

Vamos a hacer los experimentos para configurar un pin como salida

Ejemplo 3: Pin de salida. Configuración automática

Usaremos el ejemplo clásico de parpadeo de un LED externo. Colocamos un corazón conectado al pin D13, donde se conecta el LED

(03-pin-salida-test-1.ice)

El sintetizador añade automáticamente un bloque PIO configurado como salida, en el que la señal oe se pone a 1 y la salida del corazón la conecta a dout. La señal din se deja sin conectar. Nuestro circuito no ha tenido que gestionar nada

Ejemplo 4: Pin de salida. Configuración manual

El pin D13 lo configuramos manualmente como salida sin más que añadir el bloque InOut-right. Conectamos su entrada pin al bloque salida D13, oe a 1 y conectamos el corazón a dout. La señal din la dejamos desconectada

(04-pin-salida-test-2.ice)

Este circuito es equivalente al ejemplo 3 (consume los mismos recursos), pero lo hemos configurado nosotros. El bloque InOut-right es especial (por eso es amarillo) y debe estar asociado siempre a un pin real. Si lo conectamos a otro bloque, nos saldrá el error mostrado en el ejemplo 2

Ejemplos de Entrada/Salida

Veremos ejemplos de configuración de un pin bidireccional, comportándose bien como entrada o como salida. Usaremos el pin D13, un pulsador externo de entrada y un LED externo para la salida

Ejemplo 5: Entrada/salida independiente

Partimos de un ejemplo usando dos circuitos en paralelo, cada uno con su propio pin. Un circuito que hace parpadear el LED conectado a D13 (Salida) y otro que emite un pulso en el LED7 al apretar el pulsador conectado a D12 (entrada)

(05-inout-test-01.ice)

Nos sirve como reparso para ver las dos formas de configuración. El pin D13 se configura manualmente como salida, usando el bloque inout-right. El pin D12 se ha configurado automáticamete como entrada (lo hace el sintetizador). El escenario que usaremos es el siguiente:

Cargamos el circuito y lo probamos. Los dos circuitos funcionan en paralelo, sin ningún problema. El LED parpadea a 1Hz y al apretar el pulsador se emite un pulso en LED7. Cada uno con su propio pin.

Click to see the youtube video

Ejemplo 6: Entrada/salida. Pulsador y LED

Ahora reconvertimos el ejemplo anterior para usar un único pin como entrada o salida. Usaremos un interruptor externo para establecer el sentido del pin: entrada o salida. El proceso lo haremos manualmente, cambiando el cable de D13 para conectar al LED o al pulsador:

El circuito es el siguiente. Cuando el switch externo está a 0, el pin está configurado como entrada. Al apretarse el pulsador se emite un pulso por LED7. Si switch está a 1, el pin está configurado como salida y se hace parpadear el LED externo a 1Hz

(05-inout-test-02.ice)

Lo cargamos y lo probamos. Inicialmente D13 está configurado como entrada. Apretamos el pulsador para probarlo, y vemos que el LED7 luce. D13 es una entrada. Ahora lo conectamos al LED externo y cambiamos el switch para configurarlo como salida. Vemos cómo el LED parpadea a 1 Hz. D13 es una salida

Click to see the youtube video

Observamos que cuando está configurado como salida, se encienden los dos LEDs: el externo y el LED7 interno. Es es porque al configurarse como salida, dout se saca por el pin, pero también entra por din. Es resposabilidad de nuestro circuito gestionar esto

Ejemplo 7: Entrada/salida. Pulsador y LED. Versión 2

El circuito lo podemos mejorar añadiendo una puerta AND y una NOT para deshabilitar din cuando el pin está configura de salida. En ese caso, din será siempre 0. Pero si está configura como entrada, por din llegará lo que entre por D13: 1 si el pulsador está apretado y 0 no lo está

(06-inout-test-03.ice)

Lo cargamos y lo probamos. Funciona igual que antes, pero ahora, al configurarlo como salida, sólo parpadea el LED externo. El LED7 se enciende sólo cuando está configurado como entrada y apretamos el pulsador

Click to see the youtube video

Ejemplo 8: Pin bidireccional entre dos circuitos

Comunicaremos dos circuitos muy simples, en ambas direcciones, usando un único cable externo. Cada circuito saca por un LED lo que recibe por su pin, cuando está configurado como entrada, y envía una señal periódica cuando está configurado como salida. Mediante un interruptor externo configuramos el sentido de la comunicación

Al poner el interruptor a 1, el sentido de la comunicación cambia: El circuito 2 envía al circuito 1. Para ello se cambian de estado las señales oe de sus pines

Los circuitos podrían estar situados físicamente en FPGAs diferente, pero por comodidad se meten en la misma. El circuito 1 envía una señal de 10Hz, y el circuito 2 de 4Hz. Cuando están configurados como entrada muestran lo recibido por los LEDs 7 y 0 respectivamente

(07-inout-dos-circuitos.ice)

El interruptor externo se conecta a las señales oe de los pines, pero usando una puerta not para que estén siempre en estado diferentes: si uno es de entrada, el otro es de salida y vice-versa

Este es el escenario de pruebas. El cable violeta es el que une el circuito 1 con el 2, a través de los pines D13 y D0

Lo cargamos y lo probamos. En este vídeo se muestra su funcionamiento. Inicialmente el circuito 1 envía al 2 una señal de 4Hz, por lo que el LED7 parpadea a esta frecuencia. Al cambiar el sentido, es el circuito 2 el que envía al 1 una señal de 10Hz, que se muestra por el LED0. Si quietamos el cable de conexión, el LED deja de parpadear: no hay comunicación entre ambos circuitos

Click to see the youtube video

Autor

Licencia

Créditos y agradecimientos

  • El bloque InOut está basado en el realizado por Salvador Tropea. ¡Muchas gracias!

Enlaces

(TODO)

Clone this wiki locally