viernes, 18 de noviembre de 2011
Google Plus es el Reader social.
Google+ me parece un éxito a pesar de lo que se esperaba de la herramienta. No es el nuevo facebook en absoluto, no creo que tenga nada que ver. Por suerte, todo el ruido de Facebook se quedará en Facebook.
Para mí, Google+ es una red mucho más calmada, producto de una esperada mejora social de Google Reader. Creo que las publicaciones en esta red son un "esto quizá te interese" más que el "esto es lo que me interesa a mí" de Facebook o "esto es lo que estoy pensando" de Twitter.
En mi caso, los círculos que tengo en G+ son una proyección perfecta de los contactos a los que quiero enviarles un enlace, una opinión o un álbum de fotos. Antes, en Reader, solía compartir un enlace si a alguno de mis seguidores le podía interesar, enviando ruido al resto. Ahora puedo separar lo relativo a programación e informática, de lo referente a Arduino, DIY y electrónica, de lo de comida y cocina o del poco contenido personal que pongo en G+.
Es evidente que en Facebook se puede hacer también, pero no está tan bien implementado y sus usuarios como mucho utilizan los grupos para separar amigos de familia y así limitar las fotos etiquetadas que ven sus padres. Google obliga a sus usuarios a ser más organizados.
Lo que echo en falta es la forma de tratar los +1s (por lo visto pronunciados "masunos", "plusones" o "plasguans"). Me gustaría que G+ copiara la forma en la que Facebook te dice que a un contacto le gusta algo. "A Fulanito le gusta tal artículo y 5 más". Por ahora la única forma de verlos es en el perfil de cada uno, algo tipo los favoritos de Twitter, que ya podían llamarse "pendiente de leer".
Por otro lado, sigo muchas más empresas o "Pages" en G+ que en Facebook porque puedo gestionarlas con los círculos. Así, si tengo poco tiempo veo los círculos más interesantes y si tengo más veo los de empresas. En Facebook tienes dos opciones: leer sus actualizaciones o ignorarlas completamente.
Si se amplia el concepto de círculos, Google Plus podría reemplazar a Reader en el futuro.
miércoles, 2 de noviembre de 2011
Cinco pasos para mejorar la velocidad de un PC
Escucho con asombro las historias de compañeros de trabajo y familiares
sobre lo lento que funcionan sus ordenadores. Les suelo recomendar estas
tareas:
1. Cambia tu disco duro principal cada dos años (50€)
En mi caso, el disco duro principal (el de los sistemas operativos) lo paso a almacenamiento (fotos, música y vídeos) y el más viejo de almacenamiento lo dejo para backup y lo retiro de su actividad. Utiliza programas como HD Clone (hay versión gratuita) para copiar discos duros enteros, aunque sean de distinta capacidad. Si tienes un portátil, necesitarás un adaptador SATA-USB o un puerto eSATA para conectar dos discos duros al ordenador. En cualquier caso es mejor hacerlo con uno de sobremesa. Los discos duros mueren antes o después y siempre va a perjudicarte. Éste es el único método de evitarlo y un disco duro nuevo se nota en velocidad de arranque y ruido.
2. Amplia tu RAM (20€)
Si sueles tener muchas pestañas abiertas en tu navegador o muchos programas a la vez, los precios de la RAM son de risa y es muy fácil ampliar. Tienes que tener en cuenta:
3. No utilices antivirus
Si usas Windows, asegúrate de que las actualizaciones te llegan todos los días y tómate en serio su instalación. Lo mismo con tu navegador web. Utiliza el sentido común y no abras archivos ejecutables o extraños. Si necesitas bajar un fichero y es de dudosa procedencia, analízalo con Virustotal (gratis) antes de ejecutarlo. Si no tienes plena confianza en ti, usa Microsoft Security Essentials, que no es demasiado pesado y es gratis.
4. Borra las aplicaciones que no utilices
Especialmente las que te venían instaladas con el PC. Aunque no se usen, muchas aplicaciones ralentizan el inicio del sistema operativo para arrancar ellas más rápido. Si la aplicación es mala, seguramente lo sea también su desinstalador. Pásale a tu Windows limpiadores como CCleaner.
5. Cambia de sistema operativo
Si no quieres pagar por Windows, pásate a un sistema operativo libre y gratis, como Ubuntu (Linux). Que el código sea abierto garantiza que las aplicaciones vayan cada vez a mejor. Chrome y Firefox funcionan igual o mejor que en Windows y seguramente sea lo que vayas a usar el 99% del tiempo. Para hacer documentos y presentaciones pásate a Google Docs o, si te da miedo el salto a la Nube, a OpenOffice. Si trabajas con otro tipo de software como AutoCAD o Photoshop, compra una licencia de Windows. Mac es una opción si no te importa pagar desproporcionadamente ni aceptar limitaciones sobre lo que puedes y no puedes hacer con tu ordenador.
1. Cambia tu disco duro principal cada dos años (50€)
En mi caso, el disco duro principal (el de los sistemas operativos) lo paso a almacenamiento (fotos, música y vídeos) y el más viejo de almacenamiento lo dejo para backup y lo retiro de su actividad. Utiliza programas como HD Clone (hay versión gratuita) para copiar discos duros enteros, aunque sean de distinta capacidad. Si tienes un portátil, necesitarás un adaptador SATA-USB o un puerto eSATA para conectar dos discos duros al ordenador. En cualquier caso es mejor hacerlo con uno de sobremesa. Los discos duros mueren antes o después y siempre va a perjudicarte. Éste es el único método de evitarlo y un disco duro nuevo se nota en velocidad de arranque y ruido.
2. Amplia tu RAM (20€)
Si sueles tener muchas pestañas abiertas en tu navegador o muchos programas a la vez, los precios de la RAM son de risa y es muy fácil ampliar. Tienes que tener en cuenta:
- Tipo de ram (DDR2, DDR3 etc.).
- Si es para sobremesa (DIMM) o portatil (SO-DIMM).
- Cantidad máxima de memoria que admite tu placa base.
- Velocidad del bus (1333 MHz, 1666 MHz...).
3. No utilices antivirus
Si usas Windows, asegúrate de que las actualizaciones te llegan todos los días y tómate en serio su instalación. Lo mismo con tu navegador web. Utiliza el sentido común y no abras archivos ejecutables o extraños. Si necesitas bajar un fichero y es de dudosa procedencia, analízalo con Virustotal (gratis) antes de ejecutarlo. Si no tienes plena confianza en ti, usa Microsoft Security Essentials, que no es demasiado pesado y es gratis.
4. Borra las aplicaciones que no utilices
Especialmente las que te venían instaladas con el PC. Aunque no se usen, muchas aplicaciones ralentizan el inicio del sistema operativo para arrancar ellas más rápido. Si la aplicación es mala, seguramente lo sea también su desinstalador. Pásale a tu Windows limpiadores como CCleaner.
5. Cambia de sistema operativo
Si no quieres pagar por Windows, pásate a un sistema operativo libre y gratis, como Ubuntu (Linux). Que el código sea abierto garantiza que las aplicaciones vayan cada vez a mejor. Chrome y Firefox funcionan igual o mejor que en Windows y seguramente sea lo que vayas a usar el 99% del tiempo. Para hacer documentos y presentaciones pásate a Google Docs o, si te da miedo el salto a la Nube, a OpenOffice. Si trabajas con otro tipo de software como AutoCAD o Photoshop, compra una licencia de Windows. Mac es una opción si no te importa pagar desproporcionadamente ni aceptar limitaciones sobre lo que puedes y no puedes hacer con tu ordenador.
viernes, 16 de septiembre de 2011
Tutorial emulación/simulación de Arduino en FPGA - Índice y Conclusiones
Este tutorial se ha creado como complemento a la charla titulada Codiseño y cosimulación basado en FPGAs para plataforma Arduino del Open Source Hardware Convention 2011.
Tiene seis partes:
- Parte I - Introducción
- Parte II - Emulación del modelo RTL de Arduino
- Parte III - Simulación con ModelSIM (si se usa una versión de pago)
- Parte IV - Simulación con ISim (integrado en Xilinx ISE)
- Parte V - Compilar programas Arduino para simulación
- Parte VI - Acelerar, personalizar y optimizar Arduino
Conclusiones*:
- Emular el microcontrolador de Arduino o cualquier otro en una FPGA permite personalizar ancho de buses, número y tipo de salidas y entradas, frecuencias de reloj, tamaño de memoria o puertos de comunicación e inhabilitar los recursos que no sean utilizados para optimizar y adaptar el hardware al proyecto (y no viceversa).
- Simular el proyecto completo, hardware y software, a nivel de señal desde un PC sin necesidad de programación en una FPGA es una ventaja tremenda hasta para proyectos básicos de Arduino.
- Existen otras ventajas de utilizar hardware reconfigurable como son la capacidad de procesado o la protección de obsolescencia pero no son tan importantes en el ámbito DIY/Hardware Libre.
Trabajos futuros:
- Crear una herramienta open-source que permita configurar un sistema completo, añadir módulos con funcionalidades, comunicaciones, co-procesamiento, etc. El prototipo se llama Oruga y está escrito en Javascript: http://oruga.tk
- Crear módulos en HDL (VHDL, Verilog...) administrados desde Arduino, independientes de ellas o conectados a otros módulos como, por ejemplo:
- Salida PWM con frecuencia configurable.
- Entrada RC-PPM de varios canales desde una misma señal.
- Salida VGA.
- Memoria externa.
- Generadores de ondas.
- Entrada analógica.
- Comunicación genérica de protocolos serie como I2C o SPI.
- Generación y mezcla de sonido y otras funciones DSP.
- Módulos de coprocesamiento.
jueves, 15 de septiembre de 2011
Tutorial emulación/simulación de Arduino en FPGA - Parte VI
Acelerar, personalizar y optimizar Arduino
Hasta ahora no hay ninguna razón por la que utilizar una FPGA para ejecutar código Arduino: es mejor y más barato programar una Arduino convencional. En este capítulo se van a discutir y explicar varias razones para emular Arduino -o cualquier microcontrolador- en una FPGA:
1. Aceleración
Una FPGA puede realizar operaciones complejas en uno o pocos ciclos de reloj. Un microcontrolador está especializado en hacer un gran número de operaciones sencillas por segundo. En algunos casos es muy beneficioso resolver un problema con lógica reprogramable. Los ámbitos interesantes son: criptología, tratamiento de imágenes, reconocimiento de voz, radioastronomía...
Es una ventaja interesante especialmente para la investigación. Hay pocos usos en los que una FPGA sea más rápido que un microprocesador moderno o una GPU. En el ámbito Arduino (bajo coste), no importa demasiado.
2. Obsolescencia
Este problema se presenta especialmente en la industria: un microcontrolador utilizado hace años en un proyecto aún en producción, se deja de fabricar. Normalmente el código programado para microcontroladores están especialmente concebidos para un modelo concreto e incluso con una frecuencia de reloj concreta.
Este problema no existe si se emula el microcontrolador en una FPGA. Aunque la FPGA se deje de fabricar, se puede emular el mismo código, con el mismo comportamiento, en cualquier modelo parecido de chip reprogramable.
En el ámbito de Arduino este problema no se suele dar: es más fácil cambiar el código.
3. Paralelismo
Esta es la primera ventaja que sí es interesante en el mundo hazlo-tú-mismo/Arduino.
Ejemplo I: es necesario encender 8 LEDS exactamente a la vez, sin un retraso mayor de un ciclo de reloj entre la primera y la última. Además, hay que encender sólo algunos, dependiendo de una entrada.
Ejemplo II: se está generando una señal con la Arduino que se transmite por radio. Una modulación PWM cuya distorsión debe ser mínima. Además, hay que generar 5 con distintas frecuencias. Además, hay que usar el micro para leer del puerto serie y otros trabajos que utilizan el microcontrolador por períodos indeterminados de tiempo.
Ejemplo III: en un sistema que controla un robot se están utilizando 4 timers, 30 LEDS, 8 entradas analógicas y varios sensores que piden interrupciones para dar su dato.
En estos tres ejemplos una Arduino convencional estaría saturada o no sería capaz de cumplir requisitos. Un número importante de interrupciones puede saturar el microcontrolador y, sobre todo, convertir el desarrollo del proyecto en un auténtico infierno.
Una solución podría ser la siguiente: un microcontrolador para cada sensor, uno para cada salida PWM, uno para cada LED, uno para cada servo y cada motor y una Arduino para gobernarlos a todos.
Con una FPGA es posible llegar a un término medio y es una de sus aplicaciones más comunes: un microcontrolador gobierna un sistema de módulos independientes con un sistema de comunicación entre ellos eficiente y simple.
Entonces, en el ejemplo I se programaría en VHDL un módulo que gestione 8 salidas digitales a la vez, en el mismo ciclo de reloj, en el momento que le llegue la orden del microcontrolador.
En el ejemplo II se programaría un módulo VHDL que genera una señal PWM. Para ello utilizaría un contador, parecido al timer del microcontrolador pero sin interferir con él. Para generar 5 señales sólo hay que instanciar este módulo 5 veces y conectarlos con las salidas correspondientes. Cualquier pin físico sería válido.
En el ejemplo III se generaría un módulo en VHDL para cada timer, módulos de gestión de cada sensor, etc. El microcontrolador sólo tendría que atender las entradas de usuario y enviar los mensajes correspondientes a cada módulo. Todo a máxima velocidad y mínima saturación del micro.
La comunicación entre módulos se hace utilizando las direcciones de ram externa que no están siendo utilizadas en el proyecto AVR8. Se definen tantos registros como sea necesario para cada módulo.
4. Personalización
Tener el código del microcontrolador a utilizar tiene sus ventajas. Es posible, por ejemplo, aumentar el número de salidas digitales o analógicas (y hacerlo de forma más eficiente gracias al punto anterior).
En el siguiente ejemplo se crea una Arduino emulada y se modifica para tener 48 salidas pseudo-analógicas PWM.
Junto con el fichero Oruga.pde, que contiene lo siguiente:
Hasta ahora no hay ninguna razón por la que utilizar una FPGA para ejecutar código Arduino: es mejor y más barato programar una Arduino convencional. En este capítulo se van a discutir y explicar varias razones para emular Arduino -o cualquier microcontrolador- en una FPGA:
1. Aceleración
Una FPGA puede realizar operaciones complejas en uno o pocos ciclos de reloj. Un microcontrolador está especializado en hacer un gran número de operaciones sencillas por segundo. En algunos casos es muy beneficioso resolver un problema con lógica reprogramable. Los ámbitos interesantes son: criptología, tratamiento de imágenes, reconocimiento de voz, radioastronomía...
Es una ventaja interesante especialmente para la investigación. Hay pocos usos en los que una FPGA sea más rápido que un microprocesador moderno o una GPU. En el ámbito Arduino (bajo coste), no importa demasiado.
2. Obsolescencia
Este problema se presenta especialmente en la industria: un microcontrolador utilizado hace años en un proyecto aún en producción, se deja de fabricar. Normalmente el código programado para microcontroladores están especialmente concebidos para un modelo concreto e incluso con una frecuencia de reloj concreta.
Este problema no existe si se emula el microcontrolador en una FPGA. Aunque la FPGA se deje de fabricar, se puede emular el mismo código, con el mismo comportamiento, en cualquier modelo parecido de chip reprogramable.
En el ámbito de Arduino este problema no se suele dar: es más fácil cambiar el código.
3. Paralelismo
Esta es la primera ventaja que sí es interesante en el mundo hazlo-tú-mismo/Arduino.
Ejemplo I: es necesario encender 8 LEDS exactamente a la vez, sin un retraso mayor de un ciclo de reloj entre la primera y la última. Además, hay que encender sólo algunos, dependiendo de una entrada.
Ejemplo II: se está generando una señal con la Arduino que se transmite por radio. Una modulación PWM cuya distorsión debe ser mínima. Además, hay que generar 5 con distintas frecuencias. Además, hay que usar el micro para leer del puerto serie y otros trabajos que utilizan el microcontrolador por períodos indeterminados de tiempo.
Ejemplo III: en un sistema que controla un robot se están utilizando 4 timers, 30 LEDS, 8 entradas analógicas y varios sensores que piden interrupciones para dar su dato.
En estos tres ejemplos una Arduino convencional estaría saturada o no sería capaz de cumplir requisitos. Un número importante de interrupciones puede saturar el microcontrolador y, sobre todo, convertir el desarrollo del proyecto en un auténtico infierno.
Una solución podría ser la siguiente: un microcontrolador para cada sensor, uno para cada salida PWM, uno para cada LED, uno para cada servo y cada motor y una Arduino para gobernarlos a todos.
Con una FPGA es posible llegar a un término medio y es una de sus aplicaciones más comunes: un microcontrolador gobierna un sistema de módulos independientes con un sistema de comunicación entre ellos eficiente y simple.
Entonces, en el ejemplo I se programaría en VHDL un módulo que gestione 8 salidas digitales a la vez, en el mismo ciclo de reloj, en el momento que le llegue la orden del microcontrolador.
En el ejemplo II se programaría un módulo VHDL que genera una señal PWM. Para ello utilizaría un contador, parecido al timer del microcontrolador pero sin interferir con él. Para generar 5 señales sólo hay que instanciar este módulo 5 veces y conectarlos con las salidas correspondientes. Cualquier pin físico sería válido.
En el ejemplo III se generaría un módulo en VHDL para cada timer, módulos de gestión de cada sensor, etc. El microcontrolador sólo tendría que atender las entradas de usuario y enviar los mensajes correspondientes a cada módulo. Todo a máxima velocidad y mínima saturación del micro.
La comunicación entre módulos se hace utilizando las direcciones de ram externa que no están siendo utilizadas en el proyecto AVR8. Se definen tantos registros como sea necesario para cada módulo.
4. Personalización
Tener el código del microcontrolador a utilizar tiene sus ventajas. Es posible, por ejemplo, aumentar el número de salidas digitales o analógicas (y hacerlo de forma más eficiente gracias al punto anterior).
En el siguiente ejemplo se crea una Arduino emulada y se modifica para tener 48 salidas pseudo-analógicas PWM.
- 48 módulos independientes con un temporizador de una resolución de 8 bits.
- Cada módulo se conecta a un pin de la Papilio.
- 48 direcciones de memoria externa reservadas para la comunicación entre Arduino y los módulos.
- Si el valor en cada registro es mayor que el contador, a la salida del módulo se pone un uno. Si no, un cero.
Herramienta Oruga
Además, se baja el módulo PWMout.vhd que está preparado para ser utilizado con un proyecto Oruga. Es un módulo que recoge un valor de 8 bits de un registro de memoria (cuya dirección es definida en el momento de instanciarlo) y lo utiliza para generar una señal PWM con un ciclo de trabajo proporcional al valor que le llegue.
En el siguiente código (auto-generado por Oruga) se instancia el módulo que se configura con la dirección de memoria E/S 0x0FE0 y se conecta con el pin físico 0 del puerto A. Además, se configura ese pin para ser de salida en la última línea.
OrugaA_0:component Oruga_PWMout
GENERIC MAP(
io_base_address_generic => x"0fe0")
PORT MAP(
nReset => nrst,
clk => clk16M,
adr => core_adr,
dbus_in => core_dbusout,
iore => core_iore,
iowe => core_iowe,
output_sig => porta(0)
);
DDRAReg(0)<='0';
GENERIC MAP(
io_base_address_generic => x"0fe0")
PORT MAP(
nReset => nrst,
clk => clk16M,
adr => core_adr,
dbus_in => core_dbusout,
iore => core_iore,
iowe => core_iowe,
output_sig => porta(0)
);
DDRAReg(0)<='0';
Se genera un proyecto con 48 pines conectados a instancias de módulos PWMout. Por defecto se reservan dos direcciones de memoria para cada módulo. El primer módulo tendrá las direcciones 0xFE0 y 0xFE1, el segundo 0xFE2 y 0xFE3 y así hasta el último módulo: 0x103e y 0x103f. Esto es así para poder utilizar un byte de escritura y otro de lectura, pero en este caso sólo es necesario enviar datos al módulo PWM (sólo se usan las direcciones pares).
El esquema con los 48 módulos es peculiar:
El código Arduino inicial va a ser:
void setup()
{
for (int i = 0; i<48; i++){
writePWM(i, 256*i/48);
}
}
void loop()
{
}
{
for (int i = 0; i<48; i++){
writePWM(i, 256*i/48);
}
}
void loop()
{
}
#define io_start_address 0x0FE0
byte writePWM(int pin, byte value){
_SFR_IO8(io_start_address+pin*2) = value;
}
byte writePWM(int pin, byte value){
_SFR_IO8(io_start_address+pin*2) = value;
}
Este sketch va a configurar el estado inicial de cada módulo PWM con código Arduino, por lo que la configuración va a hacerla el microcontrolador, módulo a módulo.
Se puede observar que en 800 microsegundos (menos de un milisegundo) se han configurado los 48 canales, cada uno con un valor distinto de ciclo de trabajo, con 3 líneas de Arduino y ni una sola de VHDL, gracias a la herramienta Oruga. Además, la función loop() de Arduino está vacía, por lo que el microcontrolador está totalmente libre para otros trabajos.
miércoles, 14 de septiembre de 2011
Tutorial emulación/simulación de Arduino en FPGA - Parte V
Compilar programas Arduino para simulación
En capítulos anteriores se ha simulado un programa Arduino previamente cargado. Para programar la FPGA con un sketch personalizado conviene diferenciar dos métodos:
Para proyectos complejos es necesario simular y para ello el código del sketch debe ir previamente escrito en el proyecto (en VHDL).
El código inicial se guarda en bloques de memoria que lleva la FPGA, (de tipo BRAM). En el core se instancian bloques de tipo RAMB16_S18, que es un componente que proporciona Xilinx. En la hoja de características de la FPGA hay más explicaciones sobre los diferentes tipos de memoria que se pueden instanciar.
En el código suministrado se instancia el componente de memoria 8 veces: RAM_Word0 a RAM_Word7. En el código de inicialización de la instancia (ver fichero sources/Memory/XPM8Kx16.vhd) es posible dar los datos iniciales de cada bit, son los registros INIT_00 a INIT_3F.
RAM_Word0:component RAMB16_S18
generic map (
INIT => X"00000", -- Value of output RAM registers at startup
SRVAL => X"00000", -- Ouput value upon SSR assertion
WRITE_MODE => "WRITE_FIRST", -- WRITE_FIRST, READ_FIRST or NO_CHANGE
-- The following INIT_xx declarations specify the intial contents of the RAM
-- Address 0 to 255
INIT_00 => PM_Inst_RAM_Word0_INIT_00,
INIT_01 => PM_Inst_RAM_Word0_INIT_01,
INIT_02 => PM_Inst_RAM_Word0_INIT_02,
...
En cada registro se pueden almacenar 64 dígitos hexadecimales, es decir 4x64 = 256 bits. En cada bloque hay 64 (3F) registros, por lo que hay 16.384 bits en cada bloque. Juntando los 8 bloques inicialmente instanciados, se pueden utilizar 16KBytes de memoria para programas Arduino.
PM_Inst_RAM_Word0_INIT_XX son constantes, que están definidas en el fichero sources/Memory/prog_mem_init.vhd:
constant PM_Inst_RAM_Word0_INIT_00 : bit_vector(0 to 255) := x"0053940C0053940C0053940C0053940C0053940C0053940C0053940C0030940C"; constant PM_Inst_RAM_Word0_INIT_01 : bit_vector(0 to 255) := x"0053940C0053940C0053940C0053940C0053940C0053940C0053940C0053940C";
...
Los caracteres hexadecimales son el sketch compilado para ser utilizado en ATmega.
En el fichero hardware\tools\butterfly_platform\Makefile del Arduino IDE modificado, se modifica la siguiente línea y se cambia por la ruta correcta:
PAPILIO_SIM_PATH = "C:/Arduino-Soft-Core/sources/Memory/prog_mem_init.vhd"
Si alguna de las carpetas tiene un espacio, es importante añadirle el carácter \ antes.
Ahora se selecciona la Gadget Factory Papilio Custom Board del menú Tools y al pulsar "Upload" se generará el nuevo fichero prog_mem_init.vhd.

Sólo queda repetir los pasos de los capítulos anteriores del tutorial para simular el sketch.
En el siguiente capítulo se modificará el diseño del proyecto para crear módulos de aceleración.
Parte I - Introducción
Parte II - Emulación del modelo RTL de Arduino
Parte III - Simulación con ModelSIM (si se usa una versión de pago)
Parte IV - Simulación con ISim (integrado en Xilinx ISE)
Parte V - Compilar programas Arduino para simulación
Parte VI - Acelerar, personalizar y optimizar Arduino
En capítulos anteriores se ha simulado un programa Arduino previamente cargado. Para programar la FPGA con un sketch personalizado conviene diferenciar dos métodos:
- Modificar los bits directamente de la memoria en la FPGA y reemplazar el sketch cargado.
- Modificar el código inicial con el que se sintetiza el diseño del microcontrolador.
Para proyectos complejos es necesario simular y para ello el código del sketch debe ir previamente escrito en el proyecto (en VHDL).
El código inicial se guarda en bloques de memoria que lleva la FPGA, (de tipo BRAM). En el core se instancian bloques de tipo RAMB16_S18, que es un componente que proporciona Xilinx. En la hoja de características de la FPGA hay más explicaciones sobre los diferentes tipos de memoria que se pueden instanciar.
En el código suministrado se instancia el componente de memoria 8 veces: RAM_Word0 a RAM_Word7. En el código de inicialización de la instancia (ver fichero sources/Memory/XPM8Kx16.vhd) es posible dar los datos iniciales de cada bit, son los registros INIT_00 a INIT_3F.
RAM_Word0:component RAMB16_S18
generic map (
INIT => X"00000", -- Value of output RAM registers at startup
SRVAL => X"00000", -- Ouput value upon SSR assertion
WRITE_MODE => "WRITE_FIRST", -- WRITE_FIRST, READ_FIRST or NO_CHANGE
-- The following INIT_xx declarations specify the intial contents of the RAM
-- Address 0 to 255
INIT_00 => PM_Inst_RAM_Word0_INIT_00,
INIT_01 => PM_Inst_RAM_Word0_INIT_01,
INIT_02 => PM_Inst_RAM_Word0_INIT_02,
...
En cada registro se pueden almacenar 64 dígitos hexadecimales, es decir 4x64 = 256 bits. En cada bloque hay 64 (3F) registros, por lo que hay 16.384 bits en cada bloque. Juntando los 8 bloques inicialmente instanciados, se pueden utilizar 16KBytes de memoria para programas Arduino.
PM_Inst_RAM_Word0_INIT_XX son constantes, que están definidas en el fichero sources/Memory/prog_mem_init.vhd:
constant PM_Inst_RAM_Word0_INIT_00 : bit_vector(0 to 255) := x"0053940C0053940C0053940C0053940C0053940C0053940C0053940C0030940C"; constant PM_Inst_RAM_Word0_INIT_01 : bit_vector(0 to 255) := x"0053940C0053940C0053940C0053940C0053940C0053940C0053940C0053940C";
...
Los caracteres hexadecimales son el sketch compilado para ser utilizado en ATmega.
En el fichero hardware\tools\butterfly_platform\Makefile del Arduino IDE modificado, se modifica la siguiente línea y se cambia por la ruta correcta:
PAPILIO_SIM_PATH = "C:/Arduino-Soft-Core/sources/Memory/prog_mem_init.vhd"
Si alguna de las carpetas tiene un espacio, es importante añadirle el carácter \ antes.
Ahora se selecciona la Gadget Factory Papilio Custom Board del menú Tools y al pulsar "Upload" se generará el nuevo fichero prog_mem_init.vhd.

Sólo queda repetir los pasos de los capítulos anteriores del tutorial para simular el sketch.
En el siguiente capítulo se modificará el diseño del proyecto para crear módulos de aceleración.
Parte I - Introducción
Parte II - Emulación del modelo RTL de Arduino
Parte III - Simulación con ModelSIM (si se usa una versión de pago)
Parte IV - Simulación con ISim (integrado en Xilinx ISE)
Parte V - Compilar programas Arduino para simulación
Parte VI - Acelerar, personalizar y optimizar Arduino
miércoles, 31 de agosto de 2011
Tutorial emulación/simulación de Arduino en FPGA - Parte IV
En este capítulo se va a simular el proyecto con ISim, por si no se cuenta con una versión de pago de ModelSIM.
El procedimiento es mucho más sencillo que con ModelSIM. Hay que asegurarse de haber seleccionado ISim como simulador a la hora de crear el proyecto.
Para poder estimular a la Arduino se necesitan, por lo menos, dos cosas: un reloj y una señal de reset. Esto se hace desde un banco de trabajo o testbench. En el código de Gadget Factory se facilita uno, en scripts\XilinxISE\testbench.vhd. En el menú Project se selecciona "Add copy of source" y se busca este fichero.
Antes de simular se deben hacer algunos cambios, abriendo el testbench con doble click:
Cambiar
constant clk_period : time := 1us;
por
constant clk_period : time := 31.25 ns;
Para que el reloj sea de 32Mhz.
Además hay que comentar estas dos líneas:
portb <= "11111111";
portd <= "10101010";
Que deben quedar de esta forma:
--portb <= "11111111";
--portd <= "10101010";
El programa de Arduino que vamos a grabar para la prueba es el siguiente:
int ledPin = 13; void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
digitalWrite(ledPin, HIGH); // set the LED on
digitalWrite(ledPin, LOW); // set the LED off
}
Que simplemente hace parpadear el pin 13 constantemente.

En la ventana Files de ISE se edita prog_mem_init.vhd y se reemplazan las siguientes líneas:
constant PM_Inst_RAM_Word0_INIT_00 : bit_vector(0 to 255) := x"00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C008E940C"; constant PM_Inst_RAM_Word0_INIT_01 : bit_vector(0 to 255) := x"00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C"; constant PM_Inst_RAM_Word0_INIT_02 : bit_vector(0 to 255) := x"00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C013B940C"; constant PM_Inst_RAM_Word0_INIT_03 : bit_vector(0 to 255) := x"0039000000270023003200350038003B000000280022003100340037003A0000"; constant PM_Inst_RAM_Word0_INIT_04 : bit_vector(0 to 255) := x"0303030303030202020202020202010101010101010100200021003000330036"; constant PM_Inst_RAM_Word0_INIT_05 : bit_vector(0 to 255) := x"2010080402010606060606060606050505050505050504040404040404040303"; constant PM_Inst_RAM_Word0_INIT_06 : bit_vector(0 to 255) := x"2010080402018040201008040201804020100804020180402010080402018040"; constant PM_Inst_RAM_Word0_INIT_07 : bit_vector(0 to 255) := x"0000000000000500000100000000000000000000000080402010080402018040"; constant PM_Inst_RAM_Word0_INIT_08 : bit_vector(0 to 255) := x"BE1F241100000000000000000000000000000000000000000000000000000000"; constant PM_Inst_RAM_Word0_INIT_09 : bit_vector(0 to 255) := x"9631920D95D8C004BF0B9503EF0FE0F3E3E8E0B0E6A0E010BFCDBFDEE0DFEFCF"; constant PM_Inst_RAM_Word0_INIT_0A : bit_vector(0 to 255) := x"940C0134940EF7E107B136AB921DC001E0B0E6A2E010BE1BF7C907B136A2F3C8"; constant PM_Inst_RAM_Word0_INIT_0B : bit_vector(0 to 255) := x"00609180950800EC940EE0600060918000EC940EE061006091800000940C019A"; constant PM_Inst_RAM_Word0_INIT_0C : bit_vector(0 to 255) := x"4F3F57262D9095C82FF92FE84F9F54862F932F82E0302F28950800C4940EE061"; constant PM_Inst_RAM_Word0_INIT_0D : bit_vector(0 to 255) := x"95C896312DA095C84FFF5AE01FFF0FEEE0F02FE8F0A923882D8095C82FF32FE2"; constant PM_Inst_RAM_Word0_INIT_0E : bit_vector(0 to 255) := x"2F952F84E0502F489508938C2B89918C9508938C23899590918CF42923662DB0"; constant PM_Inst_RAM_Word0_INIT_0F : bit_vector(0 to 255) := x"4F5F57462D9095C82FF92FE84F9F54862F952F842D2095C82FF92FE84F9F5186"; constant PM_Inst_RAM_Word0_INIT_10 : bit_vector(0 to 255) := x"B58FF4213024C004778FB58FF4193023F0B12322F16923332D3095C82FF52FE4"; constant PM_Inst_RAM_Word0_INIT_11 : bit_vector(0 to 255) := x"E0F02FE3BD857D8FB585F4193025C005BF837D8FB783F4213021C00BBD8F7D8F"; constant PM_Inst_RAM_Word0_INIT_12 : bit_vector(0 to 255) := x"9508938C23899590918CF42923662DB095C896312DA095C84FFF59E21FFF0FEE"; constant PM_Inst_RAM_Word0_INIT_13 : bit_vector(0 to 255) := x"2411920FB60F920F921FCFFD00B3940E00BE940E0183940E9508938C2B89918C"; constant PM_Inst_RAM_Word0_INIT_14 : bit_vector(0 to 255) := x"006A9130006991B0006891A0006791900066918093BF93AF939F938F933F932F"; constant PM_Inst_RAM_Word0_INIT_15 : bit_vector(0 to 255) := x"939000669380006A93201DB11DA19601572DF020372D5F2D2F231DB11DA19601"; constant PM_Inst_RAM_Word0_INIT_16 : bit_vector(0 to 255) := x"1DB11DA19601006591B0006491A00063919000629180006993B0006893A00067"; constant PM_Inst_RAM_Word0_INIT_17 : bit_vector(0 to 255) := x"BE0F900F912F913F918F919F91AF91BF006593B0006493A00063939000629380"; constant PM_Inst_RAM_Word0_INIT_18 : bit_vector(0 to 255) := x"BD8E6081B58EBD8E6082B58EBF876081B787BF836084B78394789518901F900F"; constant PM_Inst_RAM_Word0_INIT_19 : bit_vector(0 to 255) := x"000000000000000DCFFF94F89508BD856081B585BD856082B585BD8F6081B58F"; constant PM_Inst_RAM_Word0_INIT_1A : bit_vector(0 to 255) := x"0000000000000000000000000000000000000000000000000000000000000000"; constant PM_Inst_RAM_Word0_INIT_1B : bit_vector(0 to 255) := x"0000000000000000000000000000000000000000000000000000000000000000";
El programa sólo ocupa estas líneas, desde INIT_00 hasta INIT_19. El resto de líneas se rellenan con ceros. La explicación de compilar programas Arduino y convertirlos en este formato se hará más adelante.
Una vez guardado el fichero, se vuelve a la ventana Design y se selecciona la vista Simulation. Al seleccionar testbench, se habilita el proceso Simulate Behavioral Model. Al hacer doble click sobre él se abre ISim.


En la barra de herramientas

se escribe 300us y se pincha en el tercer icono, "Run for the time specified on the toolbar".
En el visor de señales se comprueba perfectamente que el pin 13 (pin 5 del puerto B) parpadea tal y como estaba previsto.

Se puede comprobar que digitalWrite es una función muy lenta ya que tarda 15 microsegundos en cambiar de estado.

Parte V - Compilar programas Arduino para simulación
Índice del tutorial
El procedimiento es mucho más sencillo que con ModelSIM. Hay que asegurarse de haber seleccionado ISim como simulador a la hora de crear el proyecto.
Para poder estimular a la Arduino se necesitan, por lo menos, dos cosas: un reloj y una señal de reset. Esto se hace desde un banco de trabajo o testbench. En el código de Gadget Factory se facilita uno, en scripts\XilinxISE\testbench.vhd. En el menú Project se selecciona "Add copy of source" y se busca este fichero.
Antes de simular se deben hacer algunos cambios, abriendo el testbench con doble click:
Cambiar
constant clk_period : time := 1us;
por
constant clk_period : time := 31.25 ns;
Para que el reloj sea de 32Mhz.
Además hay que comentar estas dos líneas:
portb <= "11111111";
portd <= "10101010";
Que deben quedar de esta forma:
--portb <= "11111111";
--portd <= "10101010";
El programa de Arduino que vamos a grabar para la prueba es el siguiente:
int ledPin = 13; void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
digitalWrite(ledPin, HIGH); // set the LED on
digitalWrite(ledPin, LOW); // set the LED off
}
Que simplemente hace parpadear el pin 13 constantemente.
En la ventana Files de ISE se edita prog_mem_init.vhd y se reemplazan las siguientes líneas:
constant PM_Inst_RAM_Word0_INIT_00 : bit_vector(0 to 255) := x"00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C008E940C"; constant PM_Inst_RAM_Word0_INIT_01 : bit_vector(0 to 255) := x"00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C"; constant PM_Inst_RAM_Word0_INIT_02 : bit_vector(0 to 255) := x"00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C013B940C"; constant PM_Inst_RAM_Word0_INIT_03 : bit_vector(0 to 255) := x"0039000000270023003200350038003B000000280022003100340037003A0000"; constant PM_Inst_RAM_Word0_INIT_04 : bit_vector(0 to 255) := x"0303030303030202020202020202010101010101010100200021003000330036"; constant PM_Inst_RAM_Word0_INIT_05 : bit_vector(0 to 255) := x"2010080402010606060606060606050505050505050504040404040404040303"; constant PM_Inst_RAM_Word0_INIT_06 : bit_vector(0 to 255) := x"2010080402018040201008040201804020100804020180402010080402018040"; constant PM_Inst_RAM_Word0_INIT_07 : bit_vector(0 to 255) := x"0000000000000500000100000000000000000000000080402010080402018040"; constant PM_Inst_RAM_Word0_INIT_08 : bit_vector(0 to 255) := x"BE1F241100000000000000000000000000000000000000000000000000000000"; constant PM_Inst_RAM_Word0_INIT_09 : bit_vector(0 to 255) := x"9631920D95D8C004BF0B9503EF0FE0F3E3E8E0B0E6A0E010BFCDBFDEE0DFEFCF"; constant PM_Inst_RAM_Word0_INIT_0A : bit_vector(0 to 255) := x"940C0134940EF7E107B136AB921DC001E0B0E6A2E010BE1BF7C907B136A2F3C8"; constant PM_Inst_RAM_Word0_INIT_0B : bit_vector(0 to 255) := x"00609180950800EC940EE0600060918000EC940EE061006091800000940C019A"; constant PM_Inst_RAM_Word0_INIT_0C : bit_vector(0 to 255) := x"4F3F57262D9095C82FF92FE84F9F54862F932F82E0302F28950800C4940EE061"; constant PM_Inst_RAM_Word0_INIT_0D : bit_vector(0 to 255) := x"95C896312DA095C84FFF5AE01FFF0FEEE0F02FE8F0A923882D8095C82FF32FE2"; constant PM_Inst_RAM_Word0_INIT_0E : bit_vector(0 to 255) := x"2F952F84E0502F489508938C2B89918C9508938C23899590918CF42923662DB0"; constant PM_Inst_RAM_Word0_INIT_0F : bit_vector(0 to 255) := x"4F5F57462D9095C82FF92FE84F9F54862F952F842D2095C82FF92FE84F9F5186"; constant PM_Inst_RAM_Word0_INIT_10 : bit_vector(0 to 255) := x"B58FF4213024C004778FB58FF4193023F0B12322F16923332D3095C82FF52FE4"; constant PM_Inst_RAM_Word0_INIT_11 : bit_vector(0 to 255) := x"E0F02FE3BD857D8FB585F4193025C005BF837D8FB783F4213021C00BBD8F7D8F"; constant PM_Inst_RAM_Word0_INIT_12 : bit_vector(0 to 255) := x"9508938C23899590918CF42923662DB095C896312DA095C84FFF59E21FFF0FEE"; constant PM_Inst_RAM_Word0_INIT_13 : bit_vector(0 to 255) := x"2411920FB60F920F921FCFFD00B3940E00BE940E0183940E9508938C2B89918C"; constant PM_Inst_RAM_Word0_INIT_14 : bit_vector(0 to 255) := x"006A9130006991B0006891A0006791900066918093BF93AF939F938F933F932F"; constant PM_Inst_RAM_Word0_INIT_15 : bit_vector(0 to 255) := x"939000669380006A93201DB11DA19601572DF020372D5F2D2F231DB11DA19601"; constant PM_Inst_RAM_Word0_INIT_16 : bit_vector(0 to 255) := x"1DB11DA19601006591B0006491A00063919000629180006993B0006893A00067"; constant PM_Inst_RAM_Word0_INIT_17 : bit_vector(0 to 255) := x"BE0F900F912F913F918F919F91AF91BF006593B0006493A00063939000629380"; constant PM_Inst_RAM_Word0_INIT_18 : bit_vector(0 to 255) := x"BD8E6081B58EBD8E6082B58EBF876081B787BF836084B78394789518901F900F"; constant PM_Inst_RAM_Word0_INIT_19 : bit_vector(0 to 255) := x"000000000000000DCFFF94F89508BD856081B585BD856082B585BD8F6081B58F"; constant PM_Inst_RAM_Word0_INIT_1A : bit_vector(0 to 255) := x"0000000000000000000000000000000000000000000000000000000000000000"; constant PM_Inst_RAM_Word0_INIT_1B : bit_vector(0 to 255) := x"0000000000000000000000000000000000000000000000000000000000000000";
El programa sólo ocupa estas líneas, desde INIT_00 hasta INIT_19. El resto de líneas se rellenan con ceros. La explicación de compilar programas Arduino y convertirlos en este formato se hará más adelante.
Una vez guardado el fichero, se vuelve a la ventana Design y se selecciona la vista Simulation. Al seleccionar testbench, se habilita el proceso Simulate Behavioral Model. Al hacer doble click sobre él se abre ISim.
En la barra de herramientas
se escribe 300us y se pincha en el tercer icono, "Run for the time specified on the toolbar".
En el visor de señales se comprueba perfectamente que el pin 13 (pin 5 del puerto B) parpadea tal y como estaba previsto.
Se puede comprobar que digitalWrite es una función muy lenta ya que tarda 15 microsegundos en cambiar de estado.
Parte V - Compilar programas Arduino para simulación
Índice del tutorial
martes, 30 de agosto de 2011
Tutorial emulación/simulación de Arduino en FPGA - Parte III
En esta parte del tutorial se va a utilizar ModelSIM PE o SE. Lamentablemente el Student Edition (gratuito) está limitado a 10.000 líneas de código y sólo el proyecto AVR8 tiene 16.000. Es posible simular unos cuantos ciclos con él pero es muy muy lento.
Antes de abrir ModelSIM, en ISE es necesario seleccionar el nodo xc3s500e-4vq100 del árbol en la ventana de diseño. La ventana de procesos muestra una serie de acciones y seleccionar "Compile HDL Libraries". Esto va a tardar unos minutos.
Ya en ModelSIM, al iniciar un nuevo proyecto hay que seleccionar la configuración generada por ISE. En el mismo fichero del proyecto ISE hay un fichero llamado modelsim.ini, que dice a ModelSIM dónde encontrar las librerías que se han compilado previamente.
Una vez completado el resto del formulario, se añaden ficheros al proyecto. Se seleccionan directamente del directorio del proyecto ISE, excepto FrqDiv.vhd, que no se utiliza.
Aparecerá una lista de ficheros en la ventana Project. En cualquiera de ellos, seleccionar, con el botón derecho, Compile - Compile Order.
Hacer click en Auto Generate. Debería decir "46 compiles, 0 failed with no errors".
Ahora es necesario añadir un testbench. Es un fichero que estimula el proyecto y sin el cual no haría nada. Gestiona la simulación de entradas y salidas físicas y señales como el reset y el reloj. En la carpeta scripts\XilinxISE del AVR8 hay un testbench.vhd, que hay que añadir al proyecto.
Antes de simular se deben hacer algunos cambios, abriendo el testbench con doble click:
Cambiar
constant clk_period : time := 1us;
por
constant clk_period : time := 31.25 ns;
Para que el reloj sea de 32Mhz.
Además hay que comentar estas dos líneas:
portb <= "11111111";
portd <= "10101010";
Que deben quedar de esta forma:
--portb <= "11111111";
--portd <= "10101010";
El programa de Arduino que vamos a grabar para la prueba es el siguiente:
int ledPin = 13; void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
digitalWrite(ledPin, HIGH); // set the LED on
digitalWrite(ledPin, LOW); // set the LED off
}
Que simplemente hace parpadear el pin 13 constantemente.
Se edita prog_mem_init.vhd y se reemplazan las siguientes líneas:
constant PM_Inst_RAM_Word0_INIT_00 : bit_vector(0 to 255) := x"00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C008E940C"; constant PM_Inst_RAM_Word0_INIT_01 : bit_vector(0 to 255) := x"00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C"; constant PM_Inst_RAM_Word0_INIT_02 : bit_vector(0 to 255) := x"00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C013B940C"; constant PM_Inst_RAM_Word0_INIT_03 : bit_vector(0 to 255) := x"0039000000270023003200350038003B000000280022003100340037003A0000"; constant PM_Inst_RAM_Word0_INIT_04 : bit_vector(0 to 255) := x"0303030303030202020202020202010101010101010100200021003000330036"; constant PM_Inst_RAM_Word0_INIT_05 : bit_vector(0 to 255) := x"2010080402010606060606060606050505050505050504040404040404040303"; constant PM_Inst_RAM_Word0_INIT_06 : bit_vector(0 to 255) := x"2010080402018040201008040201804020100804020180402010080402018040"; constant PM_Inst_RAM_Word0_INIT_07 : bit_vector(0 to 255) := x"0000000000000500000100000000000000000000000080402010080402018040"; constant PM_Inst_RAM_Word0_INIT_08 : bit_vector(0 to 255) := x"BE1F241100000000000000000000000000000000000000000000000000000000"; constant PM_Inst_RAM_Word0_INIT_09 : bit_vector(0 to 255) := x"9631920D95D8C004BF0B9503EF0FE0F3E3E8E0B0E6A0E010BFCDBFDEE0DFEFCF"; constant PM_Inst_RAM_Word0_INIT_0A : bit_vector(0 to 255) := x"940C0134940EF7E107B136AB921DC001E0B0E6A2E010BE1BF7C907B136A2F3C8"; constant PM_Inst_RAM_Word0_INIT_0B : bit_vector(0 to 255) := x"00609180950800EC940EE0600060918000EC940EE061006091800000940C019A"; constant PM_Inst_RAM_Word0_INIT_0C : bit_vector(0 to 255) := x"4F3F57262D9095C82FF92FE84F9F54862F932F82E0302F28950800C4940EE061"; constant PM_Inst_RAM_Word0_INIT_0D : bit_vector(0 to 255) := x"95C896312DA095C84FFF5AE01FFF0FEEE0F02FE8F0A923882D8095C82FF32FE2"; constant PM_Inst_RAM_Word0_INIT_0E : bit_vector(0 to 255) := x"2F952F84E0502F489508938C2B89918C9508938C23899590918CF42923662DB0"; constant PM_Inst_RAM_Word0_INIT_0F : bit_vector(0 to 255) := x"4F5F57462D9095C82FF92FE84F9F54862F952F842D2095C82FF92FE84F9F5186"; constant PM_Inst_RAM_Word0_INIT_10 : bit_vector(0 to 255) := x"B58FF4213024C004778FB58FF4193023F0B12322F16923332D3095C82FF52FE4"; constant PM_Inst_RAM_Word0_INIT_11 : bit_vector(0 to 255) := x"E0F02FE3BD857D8FB585F4193025C005BF837D8FB783F4213021C00BBD8F7D8F"; constant PM_Inst_RAM_Word0_INIT_12 : bit_vector(0 to 255) := x"9508938C23899590918CF42923662DB095C896312DA095C84FFF59E21FFF0FEE"; constant PM_Inst_RAM_Word0_INIT_13 : bit_vector(0 to 255) := x"2411920FB60F920F921FCFFD00B3940E00BE940E0183940E9508938C2B89918C"; constant PM_Inst_RAM_Word0_INIT_14 : bit_vector(0 to 255) := x"006A9130006991B0006891A0006791900066918093BF93AF939F938F933F932F"; constant PM_Inst_RAM_Word0_INIT_15 : bit_vector(0 to 255) := x"939000669380006A93201DB11DA19601572DF020372D5F2D2F231DB11DA19601"; constant PM_Inst_RAM_Word0_INIT_16 : bit_vector(0 to 255) := x"1DB11DA19601006591B0006491A00063919000629180006993B0006893A00067"; constant PM_Inst_RAM_Word0_INIT_17 : bit_vector(0 to 255) := x"BE0F900F912F913F918F919F91AF91BF006593B0006493A00063939000629380"; constant PM_Inst_RAM_Word0_INIT_18 : bit_vector(0 to 255) := x"BD8E6081B58EBD8E6082B58EBF876081B787BF836084B78394789518901F900F"; constant PM_Inst_RAM_Word0_INIT_19 : bit_vector(0 to 255) := x"000000000000000DCFFF94F89508BD856081B585BD856082B585BD8F6081B58F"; constant PM_Inst_RAM_Word0_INIT_1A : bit_vector(0 to 255) := x"0000000000000000000000000000000000000000000000000000000000000000"; constant PM_Inst_RAM_Word0_INIT_1B : bit_vector(0 to 255) := x"0000000000000000000000000000000000000000000000000000000000000000";
El programa sólo ocupa estas líneas, desde INIT_00 hasta INIT_19. El resto de líneas se rellenan con ceros. La explicación de compilar programas Arduino y convertirlos en este formato se hará más adelante.
Botón derecho en cualquier fichero de la pestaña Project - Compile All. Mientras no se está familiarizado con un diseño es recomendable compilar todos los ficheros siempre. Cuando hay más confianza, es más rápido utilizar "Compile out-of-date".
En el menú Simulate, seleccionar "Start Simulation". Se elige work.testbench y se dejan todas las opciones como están.
Se añaden unas cuantas señales al visor de ondas tal y como se indica en la siguiente figura, haciendo click derecho en testbench, Add, To Wave, All items in region.
Si no sale la ventana Wave, seleccionarla desde el menú View. La simulación debería hacer parpadear el pin 13 (pin 5 del puerto B).
(Pendiente de publicar el resultado de la simulación.)
Parte V - Compilar programas Arduino para simulación
Índice del tutorial
Antes de abrir ModelSIM, en ISE es necesario seleccionar el nodo xc3s500e-4vq100 del árbol en la ventana de diseño. La ventana de procesos muestra una serie de acciones y seleccionar "Compile HDL Libraries". Esto va a tardar unos minutos.
Ya en ModelSIM, al iniciar un nuevo proyecto hay que seleccionar la configuración generada por ISE. En el mismo fichero del proyecto ISE hay un fichero llamado modelsim.ini, que dice a ModelSIM dónde encontrar las librerías que se han compilado previamente.
Una vez completado el resto del formulario, se añaden ficheros al proyecto. Se seleccionan directamente del directorio del proyecto ISE, excepto FrqDiv.vhd, que no se utiliza.
Aparecerá una lista de ficheros en la ventana Project. En cualquiera de ellos, seleccionar, con el botón derecho, Compile - Compile Order.
Hacer click en Auto Generate. Debería decir "46 compiles, 0 failed with no errors".
Ahora es necesario añadir un testbench. Es un fichero que estimula el proyecto y sin el cual no haría nada. Gestiona la simulación de entradas y salidas físicas y señales como el reset y el reloj. En la carpeta scripts\XilinxISE del AVR8 hay un testbench.vhd, que hay que añadir al proyecto.
Antes de simular se deben hacer algunos cambios, abriendo el testbench con doble click:
Cambiar
constant clk_period : time := 1us;
por
constant clk_period : time := 31.25 ns;
Para que el reloj sea de 32Mhz.
Además hay que comentar estas dos líneas:
portb <= "11111111";
portd <= "10101010";
Que deben quedar de esta forma:
--portb <= "11111111";
--portd <= "10101010";
El programa de Arduino que vamos a grabar para la prueba es el siguiente:
int ledPin = 13; void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
digitalWrite(ledPin, HIGH); // set the LED on
digitalWrite(ledPin, LOW); // set the LED off
}
Que simplemente hace parpadear el pin 13 constantemente.
Se edita prog_mem_init.vhd y se reemplazan las siguientes líneas:
constant PM_Inst_RAM_Word0_INIT_00 : bit_vector(0 to 255) := x"00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C008E940C"; constant PM_Inst_RAM_Word0_INIT_01 : bit_vector(0 to 255) := x"00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C"; constant PM_Inst_RAM_Word0_INIT_02 : bit_vector(0 to 255) := x"00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C00B1940C013B940C"; constant PM_Inst_RAM_Word0_INIT_03 : bit_vector(0 to 255) := x"0039000000270023003200350038003B000000280022003100340037003A0000"; constant PM_Inst_RAM_Word0_INIT_04 : bit_vector(0 to 255) := x"0303030303030202020202020202010101010101010100200021003000330036"; constant PM_Inst_RAM_Word0_INIT_05 : bit_vector(0 to 255) := x"2010080402010606060606060606050505050505050504040404040404040303"; constant PM_Inst_RAM_Word0_INIT_06 : bit_vector(0 to 255) := x"2010080402018040201008040201804020100804020180402010080402018040"; constant PM_Inst_RAM_Word0_INIT_07 : bit_vector(0 to 255) := x"0000000000000500000100000000000000000000000080402010080402018040"; constant PM_Inst_RAM_Word0_INIT_08 : bit_vector(0 to 255) := x"BE1F241100000000000000000000000000000000000000000000000000000000"; constant PM_Inst_RAM_Word0_INIT_09 : bit_vector(0 to 255) := x"9631920D95D8C004BF0B9503EF0FE0F3E3E8E0B0E6A0E010BFCDBFDEE0DFEFCF"; constant PM_Inst_RAM_Word0_INIT_0A : bit_vector(0 to 255) := x"940C0134940EF7E107B136AB921DC001E0B0E6A2E010BE1BF7C907B136A2F3C8"; constant PM_Inst_RAM_Word0_INIT_0B : bit_vector(0 to 255) := x"00609180950800EC940EE0600060918000EC940EE061006091800000940C019A"; constant PM_Inst_RAM_Word0_INIT_0C : bit_vector(0 to 255) := x"4F3F57262D9095C82FF92FE84F9F54862F932F82E0302F28950800C4940EE061"; constant PM_Inst_RAM_Word0_INIT_0D : bit_vector(0 to 255) := x"95C896312DA095C84FFF5AE01FFF0FEEE0F02FE8F0A923882D8095C82FF32FE2"; constant PM_Inst_RAM_Word0_INIT_0E : bit_vector(0 to 255) := x"2F952F84E0502F489508938C2B89918C9508938C23899590918CF42923662DB0"; constant PM_Inst_RAM_Word0_INIT_0F : bit_vector(0 to 255) := x"4F5F57462D9095C82FF92FE84F9F54862F952F842D2095C82FF92FE84F9F5186"; constant PM_Inst_RAM_Word0_INIT_10 : bit_vector(0 to 255) := x"B58FF4213024C004778FB58FF4193023F0B12322F16923332D3095C82FF52FE4"; constant PM_Inst_RAM_Word0_INIT_11 : bit_vector(0 to 255) := x"E0F02FE3BD857D8FB585F4193025C005BF837D8FB783F4213021C00BBD8F7D8F"; constant PM_Inst_RAM_Word0_INIT_12 : bit_vector(0 to 255) := x"9508938C23899590918CF42923662DB095C896312DA095C84FFF59E21FFF0FEE"; constant PM_Inst_RAM_Word0_INIT_13 : bit_vector(0 to 255) := x"2411920FB60F920F921FCFFD00B3940E00BE940E0183940E9508938C2B89918C"; constant PM_Inst_RAM_Word0_INIT_14 : bit_vector(0 to 255) := x"006A9130006991B0006891A0006791900066918093BF93AF939F938F933F932F"; constant PM_Inst_RAM_Word0_INIT_15 : bit_vector(0 to 255) := x"939000669380006A93201DB11DA19601572DF020372D5F2D2F231DB11DA19601"; constant PM_Inst_RAM_Word0_INIT_16 : bit_vector(0 to 255) := x"1DB11DA19601006591B0006491A00063919000629180006993B0006893A00067"; constant PM_Inst_RAM_Word0_INIT_17 : bit_vector(0 to 255) := x"BE0F900F912F913F918F919F91AF91BF006593B0006493A00063939000629380"; constant PM_Inst_RAM_Word0_INIT_18 : bit_vector(0 to 255) := x"BD8E6081B58EBD8E6082B58EBF876081B787BF836084B78394789518901F900F"; constant PM_Inst_RAM_Word0_INIT_19 : bit_vector(0 to 255) := x"000000000000000DCFFF94F89508BD856081B585BD856082B585BD8F6081B58F"; constant PM_Inst_RAM_Word0_INIT_1A : bit_vector(0 to 255) := x"0000000000000000000000000000000000000000000000000000000000000000"; constant PM_Inst_RAM_Word0_INIT_1B : bit_vector(0 to 255) := x"0000000000000000000000000000000000000000000000000000000000000000";
El programa sólo ocupa estas líneas, desde INIT_00 hasta INIT_19. El resto de líneas se rellenan con ceros. La explicación de compilar programas Arduino y convertirlos en este formato se hará más adelante.
Botón derecho en cualquier fichero de la pestaña Project - Compile All. Mientras no se está familiarizado con un diseño es recomendable compilar todos los ficheros siempre. Cuando hay más confianza, es más rápido utilizar "Compile out-of-date".
En el menú Simulate, seleccionar "Start Simulation". Se elige work.testbench y se dejan todas las opciones como están.
Se añaden unas cuantas señales al visor de ondas tal y como se indica en la siguiente figura, haciendo click derecho en testbench, Add, To Wave, All items in region.
Si no sale la ventana Wave, seleccionarla desde el menú View. La simulación debería hacer parpadear el pin 13 (pin 5 del puerto B).
(Pendiente de publicar el resultado de la simulación.)
Parte V - Compilar programas Arduino para simulación
Índice del tutorial
Suscribirse a:
Entradas (Atom)



