Documentos de Académico
Documentos de Profesional
Documentos de Cultura
principiantes
Parte 1 - Introducción
Introducción
Aprender electrónica puede ser un poco desafiante a veces, pero es realmente divertido si tienes un
poco de paciencia para leer, comprender y experimentar. Los FPGA no necesitan ser diferentes.
Vamos a probarlo y ver qué tan rápido y fácil podemos aprender un poco sobre los FPGA y crear un
proyecto de prueba de trabajo simple con este sencillo tutorial de FPGA. Para obtener lo mejor de
esta serie de tutoriales, le recomiendo descargar las herramientas que figuran al final de este
documento e intente seguir cada paso a medida que lo lea.
Hace algún tiempo, quería aprender sobre la programación de FPGA. Comencé a buscar en Google
solo para encontrar que no hay un tutorial de FPGA en la web (ese es el caso cuando este tutorial se
escribió originalmente. ¡Pero debería haber más tutoriales de FPGA disponibles en línea ahora!) Que
pueden ayudarlo a comenzar a aprender un poco HDL y lo llevará a través del diseño, la simulación
y la implementación. Hay muchos tutoriales en línea que lo ayudarán a aprender HDL, algunos
tutoriales le dicen cómo hacer la simulación, algunos pueden informarle sobre la implementación,
pero no hay un tutorial único que lo guíe paso a paso desde lo básico hasta la implementación.
Decidí escribir este tutorial con la esperanza de que pueda ayudar a nuestros lectores a aprender
un poco de Verilog (El HDL que elegí aprender primero debido a su similitud de sintaxis con C),
simular su código e implementarlo en hardware real. Este tutorial espera que tenga conocimientos
básicos en electrónica digital, familiaridad con algún lenguaje de programación (preferiblemente
C). Este tutorial no pretende ser un estudio en profundidad sobre Verilog o FPGAs o cualquier cosa,
sino solo una guía para guiarlo a través de diferentes cosas básicas que necesita saber para diseñar
un circuito digital simple en Verilog, simularlo e implementarlo en hardware.
Usaremos Xilinx ISE para simulación y síntesis. Se prefiere ISE Webpack versión 14.7, que es la
última versión disponible (y la última desde que Xilinx pasó a Vivado). Si se le pregunta durante la
instalación, instale "System Edition" porque también incluirá Xilinx EDK. Tenga en cuenta que las
licencias ISE Webpack y EDK son independientes. Necesitará la licencia ISE instalada para seguir las
siguientes partes de este tutorial. Tenga en cuenta que la licencia de evaluación EDK solo es válida
por 30 días, pero la licencia ISE Webpack es perpetua. El diseño final se programará en una placa de
desarrollo FPGA Elbert - Spartan 3A para asegurarse de que nuestro código también funcione en
hardware real.
También puede seguir una versión alternativa de esta guía utilizando una placa Mimas A7 - Artix 7
FPGA en el siguiente enlace.
¿Qué es la FPGA?
FPGA significa "Field Programmable Gate Array". Como ya sabrás, FPGA es esencialmente una gran
variedad de compuertas que se pueden programar y reconfigurar en cualquier momento en
cualquier lugar. "Gran variedad de compuertas" es una descripción demasiado simplificada de
FPGA. FPGA es de hecho mucho más complejo que una simple matriz de compuertas. Algunos FPGA
tienen bloques duros incorporados, como controladores de memoria, interfaces de comunicación
de alta velocidad, puntos finales PCIe, etc. Pero el punto es que hay muchas compuertas dentro del
FPGA que pueden conectarse arbitrariamente para hacer un circuito de su elección. Más o menos
como conectar circuitos integrados de compuertas lógicas individuales (nuevamente simplificado
en exceso, pero una buena imagen mental, no obstante). Los FPGA son fabricados por compañías
como Xilinx, Altera, Microsemi, etc. Los FPGA son fundamentalmente similares a los CPLD, pero los
CPLD son muy pequeños en tamaño y capacidad en comparación con los FPGA.
• Criptografía
• Creación de prototipos ASIC
• Instrumentos industriales, médicos y científicos.
• Procesamiento y transmisión de audio / video e imagen
• Computación de alto rendimiento, inteligencia artificial y aprendizaje profundo
• Aplicaciones militares y espaciales
• Redes, procesamiento de paquetes y otras comunicaciones.
¿Qué es Verilog?
En los párrafos anteriores, mencioné la palabra "simplificado en exceso" dos veces. La razón es que
los FPGA son mucho más que un simple grupo de compuertas. Si bien es posible construir circuitos
lógicos de cualquier complejidad simplemente organizando y conectando compuertas lógicas,
simplemente no es práctico ni eficiente. Por lo tanto, necesitamos una forma de expresar la lógica
en un formato fácil de usar que eventualmente se pueda convertir en una matriz de compuertas.
Dos formas populares de lograr esto son la entrada esquemática y las HDL (lenguaje de descripción
de hardware). Antes de que las HDL fueran populares, los ingenieros solían diseñar todo con
esquemas. Los esquemas son maravillosamente fáciles para diseños pequeños, pero son
dolorosamente inmanejables para un diseño grande (¡piense en los ingenieros de Intel que dibujan
esquemas para Pentium, que tiene millones de compuertas! Es inaceptablemente complejo). Si tiene
experiencia en electrónica, su tendencia inicial será usar esquemas para realizar su diseño en lugar
de aprender un nuevo idioma (esto me sucedió, sinceramente). Por las razones antes mencionadas,
nos quedaremos con HDL a lo largo de este tutorial.
Verilog es un lenguaje de descripción de hardware (HDL) que se puede utilizar para describir
circuitos digitales de manera textual. Escribiremos nuestro diseño para FPGA usando Verilog (como
si escribiera programas de microcontroladores en C y Ensamblaje). Aprender Verilog no es tan
difícil si tienes experiencia en programación. VHDL es también otro HDL popular utilizado en la
industria ampliamente. Verilog y VHDL comparten más o menos la misma popularidad en el
mercado, pero elegí Verilog porque es fácil de aprender y su similitud sintáctica con el lenguaje C.
Una vez que se sienta cómodo con Verilog, también debería ser fácil aprender VHDL. ¿Quieres leer
más sobre Verilog? Consulte esta página wiki (http://en.wikipedia.org/wiki/Verilog ) o consulte
este tutorial (http://www.asic-world.com/verilog/index.html).
Parte 2 - Módulos
Aprender Verilog en sí no es una tarea difícil, pero crear un buen diseño puede serlo. Pero aquí nos
centramos en diseños simples y haré todo lo posible para explicar las cosas de la manera más simple
posible. Si hubiera estado programando con lenguajes de procedimiento como C, C ++, tendrá que
decidirse a comprender que no todas las cosas suceden secuencialmente en el mundo digital.
Muchas cosas suceden paralelas también. Cuando comencé a aprender Verilog, solía escribir código
secuencialmente como si estuviera escribiendo un programa en C. Los programas C se ejecutan en
microprocesadores, que ejecutan una instrucción a la vez secuencialmente. Por lo tanto, es fácil
escribir un programa de la forma en que desea que las cosas sucedan paso a paso. Y si nos fijamos
bien, este es el punto débil de los microprocesadores / microcontroladores. Solo pueden hacer una
cosa a la vez, una y solo una cosa (¡por supuesto, estoy hablando de dispositivos de un solo núcleo!).
Pero a diferencia de los microprocesadores, los circuitos digitales (FPGA, CPLD y ASIC) pueden
hacer muchas cosas al mismo tiempo. Y necesita aprender a visualizar muchas cosas que suceden
al mismo tiempo en contraste con muchas cosas que suceden en diferentes momentos, una cosa a
la vez, en un lenguaje de procedimiento.
Módulos Verilog
Un módulo Verilog es una unidad de diseño similar a una caja negra, con un propósito específico
diseñado por el diseñador RTL. Tiene entradas, salidas y funciona según su diseño previsto. Un
módulo Verilog más simple podría ser una simple compuerta NOT, como se muestra en la segunda
imagen a continuación, cuyo único trabajo es invertir la señal de entrada entrante. No hay límite
superior en la complejidad de los módulos Verilog, ¡incluso pueden describir núcleos de procesador
completos! Verilog trata con circuitos digitales. En el reino de Verilog, los módulos pueden
considerarse equivalentes a los componentes de un circuito digital, tan simples como una
compuerta o una entidad compleja como ALU, contador, etc. Los módulos son análogos a las clases
en C ++ de forma autónoma y dar un número finito de métodos (puertos) para interactuar con el
mundo externo. Los módulos se pueden instanciar como las clases también se instancian en C ++.
Pero cuidado; Los módulos no son 100% similares a las clases cuando se implementan. Para una
fácil comprensión, un módulo puede representarse simplemente gráficamente como una caja con
varios puertos. Los puertos pueden ser entradas, salidas o bidireccionales. Los puertos pueden
tener un solo bit o varios bits de ancho. La imagen a continuación representa un módulo con algunas
entradas y salidas. El número de entradas y salidas, su ancho y dirección dependerán únicamente
de la funcionalidad del módulo.
Básicamente, Verilog (o la mayoría de las HDL) se trata de crear módulos, interconectarlos y
administrar el tiempo de las interacciones.
Basta de hablar, ni siquiera escribimos un programa "Hola Mundo" todavía. Entonces, ¿cómo nos
ensuciamos las manos con Verilog? Diseñemos una compuerta NOT en Verilog, simulemos y
probémosla en hardware real. Una compuerta NOT (también conocida como un inversor) sería la
más simple de todas. La salida de un inversor es siempre la negación de la entrada. es decir; B =! A,
donde A es la entrada y B es la salida. La siguiente tabla resume el comportamiento de NOT gate
como una tabla de verdad.
La puerta NOT puede considerarse como un módulo con una entrada y una salida con un
comportamiento interno de B =! A. Consulte la representación gráfica del módulo inversor a
continuación.
Veamos cómo representaríamos esto en Verilog.
Muy simple, ¿no es así? repasemos todas y cada una de las líneas e intentemos comprender lo que
sucede en este código.
El nombre del módulo es "myModule" y se declara usando la palabra clave "module". El módulo de
palabras clave en Verilog define nuestro módulo (llamado myModule) y le asigna dos puertos.
Todo lo que entra en este módulo se coloca entre las palabras clave " module " y "endmodule".
"MyModule" tiene dos puertos. El tamaño o la dirección de los puertos aún no se conoce.
En las dos líneas siguientes, el puerto A y el puerto B se declaran como entrada y salida,
respectivamente. ¡Estoy seguro de que tiene curiosidad acerca de lo que la palabra clave "wire"
está haciendo allí! Bueno, en Verilog hay dos tipos de datos fundamentales, “wire” y “reg”. Hay
muchos otros tipos de datos como int, real, etc.… Pero “wire” y “reg” juegan roles muy importantes
en Verilog, que sin aprenderlos no podemos progresar mucho.
Como mencioné antes, conocer un poco de electrónica digital será útil aquí. “wire” es como un
cable físico que usamos para conectar dos cosas diferentes eléctricamente. Si se aplica un
potencial en un extremo del cable de cobre, aparecerá en el otro extremo del cable siempre y
cuando continúe aplicando el potencial. Tan pronto como elimine la entrada, el potencial
desaparecerá. Esto también es cierto para un tipo de datos 'cableados' en Verilog. Un cable tendrá
un estado lógico particular siempre que sea conducido por alguna otra entidad. Si nadie conduce
el cable, estará en un estado desconocido. En Verilog, “wire” puede usarse para conectar cosas
dentro de un módulo o entre dos módulos.
Por otro lado, “reg” puede almacenar un estado lógico y mantenerlo hasta que alguien lo cambie
(piense en un registro en un microcontrolador). Esto es similar a un flip-flop. Si coloca flip-flop en
un estado, permanecerá en ese estado hasta que alguien lo cambie.
Por lo tanto, puede usar el cable como entrada o salida para un módulo y “reg” puede usarse como
la salida de un módulo. Cuando se usa un cable como salida, debe haber un “reg” que impulse el
cable desde el módulo para que el 'cable' tenga información significativa sobre él. Si se usa “reg”
como salida, no se necesita ningún otro mecanismo, ya que puede contener datos por sí mismo.
Entonces, ¿por qué "myModule" tiene entradas y salidas declaradas como cables? Buena pregunta,
la respuesta es, porque el módulo representa una compuerta NOT. Las compuertas nunca
almacenan ningún estado. Las compuertas son puramente combinacionales; es decir, su salida
siempre depende de la entrada actual. Si se aplica algún estado lógico a su entrada, habrá una
salida correspondiente (B =! A en este caso). Si no se aplica ningún estado lógico a la entrada, se
considera un estado desconocido y el estado de salida también será desconocido. Y esto también
implica que, para tener cualquier salida útil de este módulo, alguna otra entidad debería conducir
su entrada desde otro lugar (tenga esto en cuenta, tocaremos este tema más adelante cuando
hablemos sobre el banco de pruebas).
Una cosa más importante sobre el código anterior es la palabra clave " assign". La palabra clave de
asignación se utiliza para crear circuitos combinacionales. Lo que esté escrito en el lado derecho
del signo igual en el enunciado se evaluará y el resultado se asignará a la entidad en el lado
izquierdo y esto sucede de forma asincrónica. Tan pronto como ocurran cambios en el lado
derecho, el resultado se reflejará en el lado izquierdo. Si le resulta difícil entender esto, es posible
que desee leer un poco sobre los circuitos digitales combinacionales.
Ahora que tenemos un fragmento de código, es posible que queramos simular el código para ver si
funciona como se esperaba. La simulación, en un sentido amplio, es el proceso de dar alguna
entrada conocida y generar la salida correspondiente. Se espera que la salida dependa tanto de la
entrada como del comportamiento del módulo bajo prueba. Cuando la salida se verifica contra la
salida esperada, se llama verificación. Hay muchas herramientas disponibles para simulación y
verificación. Aquí usaremos iSim (parte de Xilinx ISE Webpack) para simulación e inspección de
formas de onda.
Parte 3 - Simulación
Ok, tenemos un módulo y herramientas listas ahora, intentemos ejecutar una simulación en el
módulo y ver si funciona como se esperaba. Para simular el módulo, necesitamos dar alguna entrada
al módulo, ¿cómo lo hacemos? La respuesta es que necesitamos crear un test bench (banco de
pruebas). test bench generará las entradas necesarias para el módulo bajo análisis (Aquí
"myModule"). Un test bench no es más que otro módulo Verilog que genera algunas señales y las
alimenta al módulo bajo prueba. Durante la simulación, el test bench debe ser un " top module"
(módulo de nivel superior) sin puertos de I/O. Pero cuando se trata de implementación en FPGA
real, el "módulo superior" puede tener puertos de I/O y los bancos de prueba no serán los módulos
principales allí (hablaremos de esto en detalle más adelante). Así que aquí va el código del banco de
pruebas.
module myModule_tb();
wire out;
reg clock;
always begin
#1 clock =!clock;
end
initial begin
//Initialize clock
clock = 0;
//End simulation
#10
$finish;
end
endmodule
4. Cambie la configuración del proyecto según sea necesario. Puede seleccionar la familia y el
dispositivo FPGA según la placa que utilice. Para la placa de desarrollo Mimas V2 Spartan 6
FPGA , debe configurarse como en la imagen a continuación. Para la placa de desarrollo FPGA
Elbert V2 Spartan 3A , la familia de dispositivos será “Spartan 3A y Spartan 3AN”, el
dispositivo será “XC3S50A”, el paquete será TQ144 y la velocidad será -4. Una vez que se
complete la información, haga clic en Siguiente y luego termine.
5. Hemos creado un proyecto vacío en Xilinx ISE Webpack. Ahora haga clic derecho en el
proyecto y seleccione "Nueva fuente" en el menú emergente.
6. Seleccione "Módulo Verilog" como el tipo de fuente y escriba el nombre del archivo como se
muestra en la imagen a continuación.
7. Reemplace la plantilla del módulo autogenerado (o el contenido del archivo completo) con
el código a continuación.
module myModule_tb();
wire out;
reg clock;
always begin
#1 clock =!clock;
end
initial begin
//Initialize clock
clock = 0;
//End simulation
#10
$finish;
end
9. Inicie la simulación haciendo clic con el botón derecho en el proceso "Sim" en la vista de
proceso y seleccionando "Ejecutar" (El archivo Verilog myModule_sim.v debe seleccionarse
en la Vista de diseño para que esta opción sea visible).
10. Ahora se iniciará el simulador ISim y se le presentará una forma de onda de simulación como
la siguiente (a veces puede que tenga que acercar / alejar un poco para ver la forma de onda
correctamente).
Inspeccione la forma de onda y asegúrese de que nuestro módulo Verilog funcione como se
esperaba. Como puede ver en la imagen de arriba, la salida es la forma invertida del reloj de entrada.
Esto es exactamente lo que esperamos de una compuerta NOT. En la parte 4 de este tutorial,
implementaremos este módulo en hardware real.
Parte 4 – Síntesis
Hasta ahora aprendimos algunas cosas sobre Verilog y cómo crear un módulo en Verilog y ejecutar
una simulación. Si bien la simulación puede decirnos muchas cosas sobre la corrección de nuestro
módulo, no hay nada como ponerlo en un hardware y verlo funcionar. En esta parte del tutorial, lo
guiaremos a través de los pasos para sintetizar el módulo e implementarlo en el hardware de la
placa de desarrollo FPGA Mimas V2 Spartan 6 (o de la placa de desarrollo FPGA Elbert V2 Spartan
3A ).
Como se menciona en la parte 3 de este tutorial, el código del test bench se usa solo para simulación.
Para sintetizar nuestro módulo, tenemos que eliminar el código del banco de pruebas. Para aquellos
que no saben, HDL Synthesis es el paso donde se interpreta el HDL (Verilog / VHDL o cualquier otro
HDL) y se genera una topología de hardware equivalente. Esta topología de hardware será muy
específica para el objetivo FPGA seleccionado. La síntesis es un proceso muy complejo y no
necesitamos conocer las partes internas para poner en funcionamiento nuestro módulo simple.
Utilizaremos la placa de desarrollo FPGA Mimas V2 Spartan 6 para implementar nuestro módulo y
los pasos son muy similares para la placa de desarrollo FPGA Elbert V2 Spartan 3A también. La placa
Mimas V2 tiene una FPGA Xilinx Spartan 6, una SDRAM DDR y algunos otros periféricos a bordo. El
número de pieza de FPGA exacto utilizado en esta placa es XC6SLX9-CSG324. Este es un chip BGA
CSG324 de 324 pines con celdas lógicas de 9K. La imagen a continuación muestra la parte de los
esquemas donde se conectan las I/O FPGA para LED e interruptores de botón. Usaremos un
interruptor de botón y un LED para implementar nuestra lógica.
En el diagrama anterior, un interruptor está conectado a una entrada que se eleva a VCC utilizando
una resistencia. La salida está conectada a un LED. Tomemos un momento para entender cómo se
comportará este circuito. Cuando el interruptor está en posición abierta, habrá un voltaje positivo,
es decir; un 1 lógico en la entrada (A) de la compuerta NOT. Eso significa que la salida (B) estará en
la lógica 0. Por lo tanto, el LED estará apagado. Cuando el interruptor está cerrado, la entrada de la
compuerta NOT se convertirá en lógica 0 y la salida cambiará al estado lógico 1. Y el LED brillará.
Ahora conocemos los requisitos básicos de hardware. Necesitamos lo siguiente en nuestro posible
hardware.
1. Una entrada IO capaz con una resistencia pull-up y un interruptor conectado.
2. Una salida capaz de IO con un LED conectado.
Echemos un vistazo más de cerca a la placa de desarrollo Mimas V2 Spartan 6 FPGA. La siguiente
imagen muestra el LED y el interruptor que planeamos usar en Mimas V2. Elbert V2 también tiene
interruptores integrados y LED que se pueden usar para este propósito. Si está utilizando Elbert V2,
LED8 y Switch SW5 serían buenas opciones (el proyecto adjunto en el tutorial para Elbert V2 usa
SW5 y LED8).
Como vemos en la imagen de arriba, Mimas V2 tiene seis interruptores de botón de propósito
general y ocho LED para la conveniencia del usuario. Ahora podemos echar un vistazo a los
esquemas de Mimas V2 y aprender un poco más sobre dónde están conectados los interruptores y
los LED. Elija nuestro interruptor de botón SW3 y LED8 para nuestro propósito. Mirando en los
esquemas revela que SW3 está conectado a IO M16 y LED8 está conectado a T18 del FPGA
respectivamente (M16 y T18 no son los nombres de IO, sino que son los nombres de las bolas de
BGA a las que están conectados los IO).
Ahora tenemos un módulo Verilog que queremos implementar y hemos seleccionado una
plataforma de hardware y hemos decidido qué IO usar para la implementación. Volvamos a visitar
nuestro módulo. Volveré a publicar el código del módulo aquí.
input wire A;
output wire B;
assign B = !A;
endmodule
Nuestro módulo tiene dos puertos. Puerto A, que es la entrada y Puerto B, que es la salida. Un lector
atento estaría preguntando ahora, ¿cómo vamos a conectar el Puerto A a M16 del hardware y el
Puerto B a T18 del hardware? Haremos esto definiendo las restricciones del usuario. Las
restricciones del usuario le indican al enrutador y a la lógica de ubicación (que es parte del
sintetizador HDL) en qué pines físicos se deben conectar las señales del módulo. Hacemos una lista
de restricciones y la colocamos en un archivo e incluimos ese archivo en el proyecto. Este archivo
se llama un archivo de restricciones de usuario. Para las herramientas Xilinx, es un archivo de texto
con extensión .ucf. Afortunadamente, el archivo de restricciones de usuario para Mimas V2 ya está
disponible para descargar en la página del producto. Este archivo tiene definiciones para todas las
I/O disponibles en Mimas V2. Pero no los necesitamos a todos. Así que eliminaré la parte no utilizada
y publicaré el contenido del archivo requerido aquí.
# Onboard LEDs
NET “LED” LOC = T18;
El contenido de este archivo se explica por sí mismo. En la línea No.4 dice que la Red(NET) del LED
(la red es equivalente al cable / conexión en el circuito físico) está conectado al pin físico T18. Es
posible que haya notado la parte NET "SW" PULLUP. Esto significa que el SW neto se elevará a VCC.
Muchos de los IO de FPGA tienen resistencias pull-up incorporadas disponibles. Estas resistencias
se pueden activar al mencionarlas adecuadamente en el archivo de restricciones del usuario. Eso es
exactamente lo que hace esta línea en particular. La línea No. 11 conecta el SW neto al IO físico M16.
Bueno, esto todavía no responde cómo se van a conectar los puertos de nuestro módulo al
conmutador y al LED. Como he mencionado antes, los puertos de un módulo son equivalentes a los
cables que entran y salen del módulo. Eso, a su vez, es equivalente a una red. Entonces podemos
usar los nombres de puerto como nombres de red en el archivo de restricciones de usuario.
Entonces, si modificamos el código de restricciones de usuario anterior para nuestro módulo de
compuerta NOT, se verá más o menos así.
# Onboard LEDs
NET “B” LOC = T18;
Puede descargar proyectos completos de Xilinx ISE para Mimas V2 y Elbert V2 al final de este
capítulo. Los proyectos contienen archivos .ucf en funcionamiento.
Ahora tenemos casi todo lo que necesitamos para sintetizar el diseño y probarlo. Abra nuestro
proyecto de simulación en Xilinx ISE Webpack y cambie el modo a Implementación y agregue el
archivo de restricciones de usuario en el proyecto como se muestra en la imagen a continuación. No
olvide eliminar el código del banco de pruebas del archivo fuente de Verilog y volver al modo de
"implementación" en la vista de diseño.
Guarde el proyecto y haga clic derecho en el módulo y seleccione "Implementar módulo superior"
en el menú emergente. La síntesis puede tomar de unos segundos a un minuto. Y si todo va bien,
verá muchos círculos verdes con una marca de verificación en la vista Proceso justo debajo de la
vista Jerarquía (consulte la imagen a continuación).
Si algún elemento se vuelve amarillo, significa que hay algún tipo de advertencia. Las advertencias
están bien por el momento. Si algún elemento se vuelve rojo, hay algo que salió mal. Regrese y
verifique todos los pasos.
Hemos sintetizado con éxito el diseño. Ahora es el momento de programar la salida en el hardware.
Nuestra plataforma de hardware Mimas V2 (y Elbert v2) requiere un flujo de bits (el resultado final
del proceso de síntesis) en formato binario sin formato. Pero ISE no genera un archivo de bits
binarios sin formato por defecto. Podemos hacer esto siguiendo los pasos a continuación.
1. Haga clic derecho en la opción "Generar archivo de programación" en la ventana "Procesos".
Pero hay esperanza. Por definición (en términos sueltos), FPGA es un conjunto de elementos lógicos
que se pueden configurar para hacer cualquier circuito lógico. Si eso es cierto, ¿por qué no hacer un
microprocesador a partir de esas celdas lógicas y programas utilizando lenguajes y herramientas
amigables tradicionales de Embedded System? Sí, es posible. Pero hay una pregunta sobre por qué
este método de hacer un microprocesador o microcontrolador con lógica FPGA es mejor en
comparación con los microprocesadores disponibles. Hay muchas razones por las que fabricar un
microprocesador / controlador en un tejido FPGA es mejor (o peor) en comparación con un micro
estándar. La razón más importante es que tiene acceso a la estructura FPGA desde el
microcontrolador (a través de buses y periféricos creados dentro de la estructura, por supuesto) y
puede implementar periféricos desde una amplia gama de IP periféricas disponibles de forma
gratuita de Xilinx o crear su IP (o comprar IP de terceros). Es posible hacer prácticamente cualquier
periférico que desee dentro de la capacidad del FPGA con el que ha elegido trabajar. Sin embargo,
hay algunos inconvenientes importantes en este esquema. El costo total del hardware generalmente
será más alto en comparación con un micro disponible para la misma cantidad de potencia de
procesamiento sin procesar. Si no puede encontrar la IP periférica que está buscando, terminará
teniendo que escribir una usando Verilog o VHDL y volverá al punto de partida (recuerde, lo que
queríamos era no lidiar con el flujo de trabajo HDL o FPGA en absoluto). Es posible comprar IP de
terceros, pero dependiendo de la IP específica, puede ser muy costoso. Además, vale la pena
mencionar que las herramientas necesarias para construir un sistema integrado a partir de un FPGA
podrían retrasarlo en unos pocos cientos de dólares.
Después de cargar Platform Studio GUI, haga clic en Archivo> Nuevo proyecto BSB. En la ventana
del asistente del proyecto que aparece, ingrese una ruta y un nombre para el nuevo proyecto. En la
imagen a continuación, "C: \ embedded \ HelloWorld \ edk" es la ruta y "HelloWorld" es el nombre
del proyecto.
Haga clic en Aceptar para continuar. En la siguiente ventana, seleccione Nuamto Lab Mimas V2 como
la placa de desarrollo. Deje todas las demás configuraciones por defecto. Consulte la imagen a
continuación para ver configuraciones de muestra.
Presione siguiente para continuar. En la siguiente ventana, asegúrese de que solo UART esté
seleccionado como periférico como se muestra en la imagen a continuación. Deje todas las demás
configuraciones por defecto.
Haga clic en "Finalizar" para finalizar el asistente y generar el proyecto. Si todo salió bien, se le
presentará una ventana similar a la imagen a continuación.
Todas las IP que se incluyen en el proyecto son configurables para satisfacer sus necesidades. Pero
el único cambio que necesitamos hacer aquí para que esta demostración funcione es la velocidad de
transmisión UART. Haga clic derecho en la IP de UART y seleccione "Configurar IP" en el menú
emergente. En la ventana de configuración de IP, seleccione 19200 baudios y haga clic en Aceptar.
Las imágenes a continuación muestran estos pasos.
Un cambio más que debemos hacer al proyecto es cambiar el reloj de inicio. Por defecto, XPS
configurará el reloj JTAG como reloj de inicio FPGA. Esto está perfectamente bien cuando usamos
un adaptador JTAG como Xilinx Platform Cable - USB para programar FPGA. Pero para cargar la
configuración FPGA desde la memoria flash SPI, necesitamos configurar el reloj de inicio en Cclk en
lugar de JTAGCLK. Para hacer esto, vaya a la pestaña "Proyecto" justo al lado de la pestaña "Catálogo
IP" en XPS y abra el archivo de Opciones de Bitgen "etc / bitgen.ut". Cambie la línea "-g StartUpClk:
JTAGCLK" a "-g StartUpClk: CCLK". Guarde el archivo y reconstruya el proyecto haciendo clic en el
botón "Generar archivo de bits" en el panel izquierdo. XPS puede tardar unos minutos en construir
el proyecto. Una vez que la compilación se complete con éxito, verá el mensaje "La generación de
Bitstream se ha completado. ¡Hecho!". Si aparecen errores (idealmente no debería), corríjalos y
reconstruya. Hemos terminado con la creación de nuestro hardware de sistema integrado, ¡así de
fácil!
Ahora podemos exportar los archivos de salida y crear un proyecto SDK. SDK es la herramienta que
usaremos para crear una aplicación de compilación que se ejecutará en el microprocesador
Microblaze. Haga clic en el botón "Exportar diseño" en la caja de herramientas del lado izquierdo en
XPS. En la ventana emergente, haga clic en "Exportar solo". XPS exportará todos los archivos
necesarios para crear un proyecto SDK.
Ahora inicie SDK seleccionando "Xilinx Software Development Kit" en el menú de inicio. Seleccione
una carpeta conveniente como espacio de trabajo y haga clic en Aceptar. Para crear un nuevo
proyecto, haga clic en Archivo> Nuevo proyecto> Proyecto de aplicación. Aparecerá la aplicación
Project Wizard y le pedirá que ingrese un nombre de proyecto y un nombre de proyecto.
Llamaremos a este proyecto "HelloWorld". En la misma ventana, en la sección "Hardware de
destino", haga clic en el cuadro combinado "Plataforma de hardware" y seleccione "Crear nuevo". El
asistente "Nuevo proyecto de hardware" que aparece. Complete el nombre del proyecto y haga clic
en el botón "Examinar" y navegue hasta nuestro proyecto XPS y busque la carpeta SDK y seleccione
HelloWorld.xml (la ruta completa es SDK \ SDK_Export \ hw \ HelloWorld.xml). Luego haga clic en
Finalizar. Vea la imagen a continuación para ver un ejemplo.
Una vez que se crea un nuevo proyecto de plataforma de hardware, se lo enviará nuevamente al
asistente de proyectos de la aplicación SDK. La nueva plataforma de hardware creada se
seleccionará automáticamente en el asistente de aplicaciones. Al asistente debería gustarle como en
la imagen a continuación cuando todo esté configurado correctamente.
Haga clic en "siguiente" y seleccione la plantilla de proyecto "Mundo Hellow" y luego haga clic en
"Finalizar". Xilinx SDK creará el proyecto y lo compilará automáticamente. Si todo salió bien, debería
ver el mensaje "Build Finished" en la consola de compilación.
Hay una modificación menor que debemos hacer al código en este momento. La aplicación generada
usando SDK imprimirá "Hello World" una vez y saldrá. Queremos cambiar el código de la aplicación
para que el código siga imprimiendo los datos indefinidamente. Busque la declaración de impresión
en el código (HelloWorld.c) y reemplácela con el siguiente código.
while(1)
{
print("Hello World\n\r");
}
Todo lo que estamos haciendo aquí es rodear la declaración de impresión en un ciclo while para que
la impresión nunca se detenga. Guarda el proyecto y construye.
Paso i
cmd> c:\Xilinx\xx.x\ISE_DS\settings64.bat
Asegúrese de reemplazar xx.x en el primer comando con su versión ISE para formar una ruta
correcta y use los nombres de archivo correctos en el segundo comando (si los nombres de su
proyecto XPS / SDK eran diferentes). Si los comandos se ejecutaron correctamente, debería ver un
nuevo archivo de bits generado en la carpeta (HelloWorld_rp.bit en mi caso).
Paso ii
Ahora necesitamos generar un archivo bin. Ejecute el siguiente comando en la misma ventana de
comandos.
cmd> promgen -w -p bin -u 0x0 HelloWorld_rp.bit -spi -o download_me
Si el comando fue exitoso, verá algunos archivos nuevos generados en la carpeta. Uno de los archivos
será download_me.bin. Utilizaremos este archivo para configurar el módulo Saturn Spartan 6 FPGA.
Ejecute la herramienta de configuración flash Mimas v2, seleccione download_me.bin y haga clic en
el botón "programa" como en la imagen a continuación (asegúrese de configurar el interruptor SW7
adecuadamente para permitir la descarga flash).
Haga doble clic para ejecutar el asistente del generador de interfaz de memoria. En la primera
pantalla, asegúrese de que el dispositivo FPGA seleccionado y otras configuraciones sean correctas.
La configuración debería verse como en la imagen a continuación.
Haga clic en Siguiente para pasar a la siguiente pantalla y escriba el nombre de un componente si es
necesario. Dejar el nombre predeterminado también debería funcionar bien. En aras de la claridad,
llamaremos a nuestro componente "s6_lpddr". Reemplace esto con el nombre del componente que
eligió cuando aparezca "s6_lpddr" más adelante en este tutorial.
Haga clic en Siguiente para ir a la pantalla tres del asistente. Deje todas las opciones sin cambios y
continúe con la pantalla 4. Esta pantalla es donde seleccionamos el tipo de memoria DDR y le
decimos al asistente MIG dónde está conectada. El dispositivo Spartan 6 LX9 tiene dos controladores
de memoria disponibles. En la placa de desarrollo Mimas V2 FPGA, el dispositivo LPDDR está
conectado al Banco 3 del FPGA. Seleccione LPDDR en el cuadro combinado correspondiente al
Banco 3. Deje la configuración del Banco 1 sin cambios. La configuración en esta página debe verse
como en la imagen a continuación.
Haga clic en Siguiente para ir a la siguiente pantalla. Este es el lugar donde seleccionamos el
dispositivo de memoria DDR y su frecuencia de funcionamiento. Mimas V2 tiene memoria LPDDR
integrada que es Micron MT46H32M16 o equivalente. Este dispositivo admite reloj DDR de hasta
166MHz. Seleccione el dispositivo de memoria MT46H32M16 y configure el período de reloj en
10,000. El período de reloj 10,000 corresponde a la frecuencia de reloj DDR de 100MHz. Aunque el
dispositivo DDR admite hasta 166MHz de reloj, usaremos 100MHz para evitar la complicación de
jugar con la configuración PLL más adelante. Mimas V2 tiene una fuente de reloj de 100MHz y al
usar la misma frecuencia para el reloj DDR, podemos dejar la configuración PLL generada por MIG
tal como está. A continuación se muestra la imagen con la parte de memoria correcta y la frecuencia
seleccionada.
Haga clic en Siguiente para pasar a la siguiente pantalla y dejar todos los ajustes a sus valores
predeterminados. Haga clic en Siguiente nuevamente para pasar a la pantalla de configuración del
puerto. Seleccione el Puerto 0 y deje el resto de los puertos sin marcar como se muestra a
continuación.
Haga clic en Siguiente para pasar a la página de configuración de arbitraje. Como estamos usando
un solo puerto, no hay parámetros para cambiar en esta pantalla. Haga clic en Siguiente nuevamente
para pasar a la pantalla Opciones de FPGA. Seleccione N4 como ubicación de pin RZQ y seleccione
Single Ended como entrada de reloj del sistema. Vea la imagen a continuación con la configuración
correcta.
Haga clic en el siguiente botón unas cuantas veces más y termine. Core Generator generará un
montón de archivos. Estos archivos se pueden encontrar en el directorio \ ipcore_dir \ s6_lpddr
(suponiendo que haya utilizado el nombre "s6_lpddr" para el componente generado
automáticamente). Verá tres carpetas aquí, docs, example_design y user_design. La carpeta docs
tiene documentación muy importante que se puede utilizar para obtener más información sobre
Spartan 6 Memory Controller y la IP generada por MIG. Guárdelos para una lectura posterior.
Los cambios anteriores harán que los pines "error" y "calib_done" funcionen con el estándar
LVCMOS33 IO y asignen las redes a T18 y T17 de FPGA donde están conectados el LED1 y el LED2.
Esto hará que el LED1 se encienda cuando se complete la calibración y el LED2 se encienda si la
prueba de memoria falla
3. Cambie las líneas NET “c3_sys_clk” IOSTANDARD = LVCMOS25;
NET “c3_sys_rst_n” IOSTANDARD = LVCMOS18;ToNET “c3_sys_clk” IOSTANDARD =
LVCMOS33;
NET “c3_sys_rst_n” IOSTANDARD = LVCMOS33;
El cambio anterior establecerá los estándares de E / S para la entrada del reloj y restablecerá la
entrada a LVCMOS33. Esto se debe nuevamente a que el banco al que pertenecen estos IO está
alimentado por un riel de 3.3V.
4. Agregue una línea NET “c3_sys_rst_n” PULLDOWN;
Esto permitirá desplegar el pin de reinicio y mantendrá el controlador de memoria sin reinicio sin
tener que usar ningún componente externo. A pesar del nombre "c3_sys_rst_n", MIG parece estar
configurando la entrada de reinicio como alta activa.
5. Cambie las asignaciones de pin "c3_sys_clk" y "c3_sys_rst_n" como se muestra a
continuación.
NET “c3_sys_clk” LOC = “V10”;
NET “c3_sys_rst_n” LOC = “M16”;
Esto asignará los pads IO correctos para la entrada del reloj y asignará el interruptor SW3 como
entrada de reinicio.
Ya hemos terminado con los cambios en el archivo ucf. Esto puede parecer difícil pero lo
suficientemente fácil si se hace con cuidado. Es una buena idea hacer una copia de seguridad de su
archivo ucf original antes de guardar los cambios por si acaso desea volver y reiniciar nuevamente.
Construyendo el código
El siguiente paso es modificar el entorno de compilación para generar un archivo de configuración
binario. Este es un paso muy fácil de hacer. Busque el archivo mem_interface_top.ut y ábralo en un
editor de texto. Busque la línea "-g Binary: no" y cámbiela a "-g Binary: yes" y guárdela.
Ahora estamos listos para construir el proyecto. Antes de compilar el proyecto, asegúrese de
agregar la ruta a las herramientas de compilación Xilinx a la variable de entorno PATH. Por lo
general, la ruta es C:\Xilinx\\ISE_DS\ISE\bin\nt suponiendo que ISE esté instalado en la unidad C:.
Ahora ejecute el archivo por lotes ise_flow.bat haciendo doble clic en el archivo o utilizando el
símbolo del sistema. Si todo salió bien hasta ahora, el archivo por lotes ejecutará las herramientas
necesarias para compilar el proyecto y terminará con un mensaje "Listo" y un montón de archivos
nuevos en la carpeta par. El mensaje debería verse en la imagen a continuación.
Si el proceso de compilación falla, consulte ise_flow_results.txt para obtener más detalles sobre las
causas de la falla. Debería ver el archivo "example_top.bin" en la carpeta par si la compilación se
realizó correctamente. Este es el archivo con el que vamos a programar la placa de desarrollo Mimas
V2 Spartan 6 FPGA.
¿Qué es el microblaze?
Microblaze es un procesador de software suave de 32 bits desarrollado por Xilinx para sus
dispositivos FPGA de gama media y alta. Microblaze es compatible con sus dispositivos Spartan 6,
Virtex y Zynq. Puede encontrar más recursos, incluida la hoja de datos para Microblaze en la página
de Microblaze de Xilinx. Afortunadamente, no necesitamos descargar Microblaze IP por separado,
ya que está incluido con la herramienta Xilinx EDK. El diseño integrado basado en Microblaze puede
usar PLB o AXI como sistema de bus. Dado que Xilinx está planeando eliminar PLB y mantener solo
AXI en el futuro, nos quedaremos con AXI para nuestros diseños. No necesita un conocimiento
profundo de Microblaze o AXI para seguir este artículo y construir un sistema de trabajo con éxito.
¿Qué es el AXI?
AXI significa Interfaz avanzada extensible. AXI es una interconexión de bus basada en la popular
arquitectura de bus AMBA de ARM. En un sistema integrado basado en Microblaze, AXI conecta el
microprocesador a todos los periféricos disponibles. La única excepción es Block RAM, que está
conectado al procesador a través de LMB (bus de memoria local). AXILite está disponible para
conectar periféricos de bajo rendimiento al sistema como UART, GPIO, etc. AXILite utiliza menos
recursos lógicos en FPGA en comparación con AXI. Por lo general, AXI se usa para conectar
periféricos de alto rendimiento como memoria DDR, Ethernet, etc. Una vez más, no se requiere una
comprensión detallada de AXI para seguir este artículo. Pero para los lectores curiosos, la Guía de
referencia de AXI está disponible aquí .
¿Qué es el EDK?
EDK es un conjunto de herramientas de desarrollo proporcionadas por Xilinx para ayudar a crear
un sistema embebido basado en Microblaze y desarrollar software para el sistema. Xilinx EDK tiene
dos componentes principales.
Xilinx Platform Studio (XPS)
Kit de desarrollo de software Xilinx (SDK)
Estas son las dos herramientas de software separadas que utilizaremos para diseñar e implementar
nuestro sistema. XPS es la herramienta utilizada para diseñar y generar el sistema de hardware.
Creará y configurará el procesador Microblaze y los periféricos necesarios utilizando XPS y generará
un archivo de bits a partir del diseño. Este archivo de bits se programará en el FPGA para completar
el diseño del hardware. SDK es la herramienta donde el software está escrito para el procesador
Microblaze. El software se puede escribir usando C o C ++. SDK y XPS juntos generarán todos los
archivos de encabezado necesarios y los scripts de enlazador necesarios para construir con éxito el
software para su sistema. Analizaremos detalladamente estas herramientas a medida que
avancemos. Más detalles sobre estas herramientas se pueden encontrar aquí .
Paso 1
cmd> c: \ Xilinx \ xx.x \ ISE_DS \ settings64.bat
cmd> data2mem -bm ddrdemo_bd.bmm -bd ddrdemoapp.elf -bt ddrdemo.bit
Asegúrese de reemplazar xx.x en el primer comando con su versión ISE para formar una ruta
correcta y use los nombres de archivo correctos en el segundo comando (si los nombres de su
proyecto XPS / SDK eran diferentes). Si los comandos se ejecutaron correctamente, debería ver un
nuevo archivo de bits generado en la carpeta (ddrdemo_rp.bit en mi caso).
Paso 2
Ahora necesitamos generar un archivo bin. Ejecute el siguiente comando en la misma ventana de
comandos.
cmd> promgen -w -p bin -u 0x0 ddrdemo_rp.bit -spi -o download_me
Si el comando fue exitoso, verá algunos archivos nuevos generados en la carpeta. Uno de los archivos
será download_me.bin. Utilizaremos este archivo para configurar Mimas V2. Ejecute la herramienta
de configuración flash Mimas V2 (asegúrese de configurar el interruptor deslizante de Mimas V2 en
el modo de programación, consulte los detalles en el manual del usuario), seleccione
download_me.bin y haga clic en el botón "programa" como en la imagen a continuación.
Una vez que la placa está programada, coloque el interruptor deslizante de Mimas V2 en modo
normal y conéctese al puerto COM correspondiente a la placa utilizando cualquier software de
emulación de terminal en serie como Hyperterminal o TeraTerm. Luego presione el interruptor
SW3 para reiniciar el procesador. Si todo ha ido bien hasta ahora, debería ver los siguientes
resultados de la prueba impresos en el terminal.
Este tutorial muestra lo fácil que es generar y crear aplicaciones de prueba simples para ejercitar la
SDRAM DDR disponible en la placa de desarrollo Mimas V2 FPGA (o cualquier otra placa basada en
Spartan 6 para el caso).