Hasta ahora hemos visto qué es una FPGA y qué piezas tiene por dentro (LUTs y Flip-Flops). Ahora nos toca abordar la parte que suele asustar a los recién llegados: El Toolchain (o flujo de trabajo).
En el mundo de programacion, estamos acostumbrados a un botón de “Compilar y Subir”. Detrás de escena, un compilador (avr-gcc) traduce C++ a código máquina.
En el mundo de las FPGAs, el proceso es radicalmente distinto. No estamos generando instrucciones para una CPU, estamos diseñando un chip físico. Esto requiere una serie de pasos complejos que transforman nuestra descripción abstracta en una configuración eléctrica real.
A este proceso lo llamamos FPGA Implementation Flow y entenderlo es importante para saber qué está pasando cuando tu ordenador se queda “pensando” durante minutos (o horas en diseños grandes).
Entrada de diseño (design entry)
Todo empieza con nosotros escribiendo código. Como vimos, usamos un HDL (Hardware Description Language) como Verilog o VHDL.
También es posible usar herramientas de diseño gráfico (Schema Entry) uniendo bloques con el ratón, pero en el mundo profesional y en este curso, nos centraremos en el código, que es mucho más potente y mantenible.
// Nuestra descripción abstracta
module blinky(input clk, output led);
// ... lógica del contador ...
endmoduleSíntesis (synthesis)
El primer paso “pesado” es la Síntesis.
Aquí, la herramienta toma nuestro código Verilog (que es legible por humanos) y lo traduce a una lista de componentes lógicos básicos. Es equivalente a cuando un compilador de C pasa a ensamblador, pero en lugar de instrucciones, genera puertas lógicas y registros.
El sintetizador realiza tres tareas clave:
Chequeo de Sintaxis: Busca errores en el código.
Inferencia: Detecta qué queremos hacer. Si ve un +, infiere un sumador. Si ve un if, infiere un multiplexor.
Mapeo Tecnológico: Traduce esos elementos genéricos a los recursos reales de nuestra FPGA específica.
El resultado de la síntesis es un Netlist.
Imagina el Netlist como un esquema eléctrico gigante en texto que dice: “La salida de la LUT A se conecta a la entrada del Flip-Flop B”.
Place and route (implementación)
Esta es una de las partes más delicadas del flujo, y donde el software suda la gota gorda. Tenemos un Netlist (una lista de conexiones lógicas), pero ahora tenemos que colocarlo físicamente en el chip.
Este paso se divide en dos fases que suelen ir de la mano:
La herramienta decide qué recurso físico exacto de la FPGA va a realizar cada función.
- “La función lógica del contador la pondremos en la LUT de la fila 3, columna 12”.
- “El buffer de entrada estará en el Pin 45”.
Es como jugar a un Tetris gigante con millones de piezas, intentando que las piezas que se conectan entre sí queden cerca para reducir los retardos.
Una vez que las piezas tienen un sitio fijo, hay que conectarlas. La herramienta busca caminos a través de la Matriz de Interconexión (esos “cables” y switches que vimos en el artículo anterior).
El enrutador debe encontrar caminos libres para miles de señales sin que se crucen incorrectamente y, lo más importante, cumpliendo los tiempos.
El Place & Route es un problema matemático NP-Completo. Por eso, en FPGAs muy grandes, este paso puede tardar horas. Afortunadamente, en las FPGAs pequeñas que usaremos (como la iCE40), tarda solo unos segundos.
Análisis de tiempos (timing analysis)
Este no es un paso que genere un archivo, sino un reporte crítico. En un circuito digital, las señales tardan un tiempo físico en viajar de un Flip-Flop a otro (atravesando cables y LUTs). Si la señal tarda demasiado, no llegará a tiempo para el siguiente ciclo de reloj y el sistema fallará.
El analizador de timing verifica si, con la colocación y enrutado actuales, nuestro diseño puede funcionar a la velocidad que le hemos pedido (por ejemplo, 100 MHz).
- Si cumple, tenemos Timing Closure.
- Si no cumple, la herramienta nos avisará de que hay caminos críticos que violan las restricciones.
Generación del bitstream
Si todo ha ido bien, el último paso es generar el archivo final. Dependiendo de la marca, tendrá extensión .bit, .bin, .sof, etc.
Este archivo Bitstream no es un ejecutable. Es una trama de bits que define el estado de todos los interruptores de configuración de la FPGA.
Es literalmente el mapa que dice:
- “Switch 1024: ON”
- “Contenido de la LUT 50: 10110010”
- “Estándar de voltaje del Pin 3: 3.3V”
Configuración y carga
Finalmente, enviamos el Bitstream al chip. Aquí hay una distinción importante respecto a los microcontroladores.
La mayoría de FPGAs (como las de Xilinx o la familia iCE40) están basadas en SRAM. Esto significa que son volátiles.
- Al encender la placa, la FPGA está “vacía” y tonta.
- La FPGA lee el bitstream desde una memoria Flash externa (o se lo enviamos nosotros por USB).
- Se configura y empieza a funcionar.
Si quitas la energía, la FPGA pierde su configuración. Por eso, cuando “programamos” nuestra placa, en realidad solemos estar grabando la memoria Flash externa que acompaña a la FPGA.
El flujo completo
Para que nos quede claro el mapa mental:
Código (Verilog/VHDL): Lo que escribimos nosotros.
Síntesis: Traducción lógica a primitivas (Netlist).
Place & Route: Colocación física y cableado en el chip.
Bitstream: Archivo binario de configuración.
Carga: Enviar a la FPGA/Flash.