-
Notifications
You must be signed in to change notification settings - Fork 16
Procesador SIMPLEZ F
Implementación del procesador simplez en Verilog, y sintetizado en la FPGA de la tarjeta Icestick de Lattice. Además se ha creado un ensamblador (SASM), para traducir los ficheros en ensamblador de simplez a su código máquina, un simulador en consola (SSIM), que permite comprobar si un programa ha funcionado correctamente y un cargador (SBOOT), para subir programas a Simplez desde el PC
Todas las herramientas son libres y multiplataforma, por lo que se podría usar desde cualquier sistema operativo. Sin embargo la documentación está hecha para el sistema operativo GNU/Linux Ubuntu 15.10, que es el que tiene instalado el autor
Pulsa en la imagen para acceder al vídeo en youtube. Es el videoblog del 24-Enero-2016
Este vídeo se corresponde con la versión 1.2 de este proyecto. Las instrucciones de la wiki contienen información más actual (y lo que se comenta en el vídeo está desactualizado)
Simplez es un ordenador ficticio creado por el profesor Gregorio Fernández para explicar los principios básicos de la arquitectura de los ordenadores [1]. Se trata de un ordenador mínimo que sirve de punto de partida, al que ir incorporando complejidad. Su objetivo es la docencia.
Simplez F es su implementación en una FPGA, de manera que Simplez pasa de ser un procesador ficticio a uno que podemos tocar físicamente. Como si lo hubiésemos comprado en una tienda. Está listo para programarlo.
Muchos estudiantes de ingeniería tienen ese gen maker que les hace aprender construyendo. Necesitan construir para llegar a comprender en su totalidad los conceptos. O dicho de otra manera, si no pueden construir cosas con los conceptos que se les enseñan, entonces pierden el interés.
Ese era mi caso. Y aunque la asignatura de Fundamentos de computadores, donde aprendí Simplez, me enamoró, siempre se me quedó la espina clavada de no poder construir un Símplez real, para usarlo en proyectos reales, añadirle periféricos, ampliarlo, evolulcionarlo...
Por eso ha nacido Simplez F, una implementación de Simplez en FPGA, usando además herramientas libres.
Simplez es un procesador educacional mínimo, que tiene las siguientes caracterísiticas:
Descripción | |
---|---|
Tipo de arquitectura | CISC |
Instrucciones | Sólo 8: ST, LD, ADD, BR, BZ, CLR, DEC, HALT |
Memoria RAM | 512 palabras de 12 bits |
Registros | Sólo uno de 12 bits: Registro A |
Modos de direccionamiento | Sólo uno: direccionamiento directo |
Periféricos: | Teclado y pantalla, cada uno con dos registros (estado y datos), mapeados en memoria |
Simplez-F es su implementación en FPGA y tiene algunas cosas que difieren del simplez original:
- Microcontrolador: En vez de una cpu aislada, Simplez-F es un microcontrolador que incorpora una cpu de simplez, la memoria y los periféricos todo dentro del mismo chip (que es la FPGA). Hacia el exterior NO salen buses de datos ni direcciones, ya que todo está dentro (SoC)
- Compatibilidad: 100% compatible hacia atrás con Simplez: Todos los programas escritos para simplez funcionan en simplez-F sin hacer modificaciones
- Instrucciones: Todas las de simplez más una nueva: WAIT, que realiza una pausa de 200ms (aunque es un parámetro que se puede modificar al sintetizar).
- Periféricos: Los mismos que simplez más un puerto de 4 bits conectado a 4 leds. Esto permite que los programan envíen notificaciones por los leds. La programación se hace más amena con leds :-)
- Modo depuración: Se configura en la síntesis. Permite conectar el registro A directamente al puerto de los leds, de forma que los 4 bits menos significativos se muestren en los leds. Muy útil para depurar
- Velocidad de comunicación configurable: La comunicación la pantalla y teclado se hace a la velocidad de 115200 baudios, pero es configurable mediante un parámetro en la síntesis
- Pines: El chip tiene los siguietes pines: clk, rstn, rx, tx, leds(4 bits), stop
- Frecuencia: Nominal: 12Mhz (reloj en la icestick). Es la velocidad de funcionamiento normal
- Frecuencia máxima: 56Mhz (calculado con la herramienta icetime)
Simplez-F está descrito en lenguaje Verilog y se sintetiza en la FPGA modelo iCE40HX1K de Lattice, usando sólo herramientas libres: icestorm, yosys y arachne-pnr. Con ellas se genera el fichero de configuración simplez.bin y se carga en la FPGA para que se "convierta" en el procesador Simplez.
Para la simulación del hardware también se usan exclusivamente herramientas libres: icarus verilog y gtkwave
Al ser herramientas libres, pertenecen al patrinomio tecnológico de la humanidad. Son de todos nosotros. El conocimiento de cómo están creadas está disponible para que cualquiera de nosotros las pueda usar, estudiar, modificar, mejorar. Nos hace independientes de los caprichos de los fabricantes. Nos permiten hacer cosas con las FPGAs que no habían sido previstas por los fabricantes. Y lo más importante, nos permiten que su desarrollo se haga dentro de la comunidad, evolucionándolo entre todos.
Simplez es un procesador educativo, cuya finalidad es transmitir conocimientos de arquitectura de ordenadores. Este conocimiento es universal, y tiene todo el sentido del mundo transmitirlo usando herramientas de nuestro patrimonio tecnológico, que también nos pertenecen a todos.
Los componentes para materializar simplez-F son:
Componente | Descripción |
---|---|
Tarjeta Icestick | Tiene la FPGA ICE40HX1K de lattice, 4 leds rojos, 1 verde y conversor USB-serie |
Cable extensor de USB | (opcional) Para conectar la icestick más fácilmente al ordenador |
Parte inferior carcasa | (opcional) Impresa en 3D. Modelo 3D |
Parte superior carcasa | (opcional) Impresa en 3D. Modelo 3D |
El componente principal es la tarjeta icestick, que además de la FPGA ICE40HX1K de lattice incluye 4 leds rojos, 1 verde y la conversión USB serie
Valdría también cualquier tarjeta que incluya esta FPGA o el modelo superior: ICE40HX8K
Los pines que conectan el "chip" simplez F con el exterior se muestran en la siguiente figura:
Se resumen en la siguiente tabla:
Nombre Pin | Tipo | bits | Descripción |
---|---|---|---|
clk | Entrada | 1 | Reloj |
rstn | Entrada | 1 | Reset (activo a nivel bajo) |
rx | Entrada | 1 | Recepción de datos serie (Teclado) |
tx | Salida | 1 | Envío de datos serie (Pantalla) |
stop | Salida | 1 | Indica que Simplez ha ejecutado la instrucción HALT |
leds | Salida | 4 | Puerto de salida de 4 bits |
El chip simplez-F se sintetiza en la FPGA de la tarjeta icestick:
En ella se encuentran el resto de componentes usados:
- Reloj de 12Mhz, que se introduce por el pin de clk de Simplez-F
- led verde conectado al pin de stop
- Los 4 leds rojos conectados a los pines de salida leds
- Un conversor USB-serie del que se conecta la señal DTR al pin de reset. Esto permite realizar el reset de simplez desde el ordenador externo. También se conectan los pines tx y tx para realizar la comunicación con el PC
La icestick se conecta al ordenador externo por el usb, a través del cable extensor de usb. Esto nos permite utilizar el teclado para enviar datos a simplez y la pantalla para recibirlos
En simplez, cada instrucción se almacena en una única posición de memoria. Por ello, las instrucciones son de 12 bits, el mismo tamaño que las palabras de memoria
El formato es el siguiente:
Cada instrucción tiene 2 campos:
- CO: Código de operación. Es un valor de 3 bits que indica el tipo de instrucción
- CD: Campo de dirección. Valor de 9 bits para acceder a cualquiera de las 512 posiciones de la memoria
Código (CO) | Nemónico | Usa CD | Descripción |
---|---|---|---|
0 | ST | si | Almacenar el registro A en la posicion de memoria indicada en el campo CD |
1 | LD | si | Cargar en el registro A el dato de la posición de memoria indicada en el campo CD |
2 | ADD | si | Sumar al registro A el dato de la posición de memoria indicada en el campo CD |
3 | BR | si | Bifurcación incondicional. La siguiente instrucción a ejecutar será la que se encuentre en la direccion cD |
4 | BZ | si | Bifurcación condicional. Si la última operación realizada ha dado como resultado 0, la siguiente instrucción a ejecutar será la que se encuentre en la dirección CD. En caso contrario se ejecuta la que esté a continuación |
5 | CLR | no | Poner a 0 el registro A |
6 | DEC | no | Decrementar el registro A en una unidad |
7 | --- | --- | Se trata de una Instrucción extendida: consultar la tabla de instrucciones extendidas |
Si los 3 bits de CO están a 1, significa que se trata de una instrucción extendida. En ese caso, se tiene también en cuenta el siguiente bit, de forma que se tiene un código de operación extendida (COE) de 4 bits
COE | Nemónico | Descripción |
---|---|---|
0xE | HALT | Parar la ejecución de instrucciones |
0xF | WAIT | Realizar una pausa de 200ms |
Los periféricos se encuentra mapeados en las últimas posiciones de la memoria. El acceso a ellos es exactamente igual que el acceso a las posiciones de memoria. Con LD se hace una lectura y con ST una escritura
Dirección | Tipo | Periférico | Descripción |
---|---|---|---|
507 | Salida | Leds rojos | Puerto de salida de 4 bits (los 4 menos significativos), conectados a los 4 leds rojos de la tarjeta icestick. Permite que nuestros programas puedan encenderlos y apagarlos |
508 | Entrada | Estado Pantalla | Registro de estado de la pantalla. Si vale 1, significa que está lista para recibir datos |
509 | Salida | Datos pantalla | Registro de la pantalla. Una escritura en este puerto envía el dato a la pantalla (sólo los 8 bits menos significativos del registro A) |
510 | Entrada | Estado teclado | Registro de estado del teclado. Si vale 1, significa que hay un carácter esperando a ser leido |
511 | Entrada | Datos teclado | Registro de datos del teclado. Se lee el dato recibido (sólo 8 bits) |
Las directivas del ensamblador que están implementadas en el SASM (Simplez Assembler), desarrollado en este proyecto son:
Directiva | Descripción |
---|---|
ORG dir | Establecer la dirección donde situar el siguiente dato / instrucción. El parámetro dir es un número de entre 0 y 511 (9 bits) |
DATA val | Situar un dato de valor val en la posición actual de memoria. El parámetro val es un número entre 0 y 4095 (12 bits) |
RES num | Reservar el numero de palabras de memoria indicadas |
etiq EQU val | Definir una etiqueta con nombre etiq y cuyo valor es val |
En la carpeta verilog/asm del proyecto se encuentra más ejemplos. Aquí se muestran algunos muy sencillos para hacerse una idea. Estos ejemplos se han hecho para cargarse a partir de la dirección 0, al inicio. En una mejora posterior, se ha añadido un bootloader a Simplez de forma que se pueden cargar los programas muy fácilmente usando la herramienta sboot (ver apartado Bootloader y Cargador sboot). En estos casos los programas deben comenzar en la dirección h'40 (org h'40)
Es el programa "hola mundo" es el más sencillo: encender todos los leds. Para ello se escribe el valor hexadecimal H'0F en la dirección 507, donde están mapeados los leds, y se ejecuta la instrucción HALT para terminar (esto hace que se encienda el led verde, indicando que el procesador está parado)
;-- Programas de ejemplo para Simplez
;-- leds_on.asm: Encender todos los leds
LD /val ; Cargar en A valor a enviar al puerto de los leds
ST /LEDS ; Escribir valor en el puerto de leds
HALT ; Terminar
;-- Datos
val DATA H'0F ;-- Valor a sacar por los leds
;------ PERIFERICO: puerto de leds ------------------
ORG 507
LEDS DATA 0 ;-- Todo lo escrito aqui se saca por los leds
Este ejemplo envía 2 valores diferentes al puerto de los leds. Cada valor hace que se enciendan 2 leds. Los valores se van alternando uno a continuación del otro. Se usa la instrucción WAIT para hacer una pausa de 200ms
;-- Programas de ejemplo para Simplez
;-- sec.asm: Sacar una secuencia de 2 estados por los leds
loop
LD /val1 ;-- Sacar valor 1 por los leds
ST /LEDS
WAIT ; Pausa
LD /val2 ;-- Sacar valor 2 por los leds
ST /LEDS
WAIT
BR /loop ;-- Repetir
;-- Datos
val1 DATA H'03 ;-- Valor 1 de la secuencia
val2 DATA H'0C ;-- Valor 2 de la secuencia
;------ PERIFERICO: puerto de leds ------------------
ORG 507
LEDS DATA 0 ;-- Todo lo escrito aqui se saca por los leds
Este es un programa más largo, que lee todo lo recibido por el teclado y lo saca por la pantalla. Además, todo lo recibido se saca también por los leds
Se usa la instrucción WAIT al principio para emitir una ráfaga para indicar que el programa ha comenzado
;-- Programas de ejemplo para Simplez
;-- eco.asm: Se hace eco de lo recibido por el puerto serie y ademas se saca por los leds
;-- Lanzar una rafaga por los leds, para indicar que arranca el programa
LD /cval1
ST /LEDS
WAIT
CLR
ST /LEDS
;-- Bucle principal: Incrementar contador cada vez que se recibe un caracter
main
;-- Esperar a que llegue un caracter
LD /RXSTATUS
BZ /main
;-- Leer caracter
LD /RXDATA
;-- Sacarlo por los leds
ST /LEDS
;-- Alcacenar caracter recibido
ST /car
;-- Enviarlo de vuelta
txloop ;-- Esperar a que pantalla lista
LD /TXSTATUS
BZ /txloop
;-- Sacarlo por pantalla
LD /car
ST /TXDATA
BR /main
;-- Variables y constantes
cval1 DATA H'0F ;-- Valor constante
car DATA 0 ;-- Caracter recibido
;------ PERIFERICOS ------------------
ORG 507
;-- LEDS
LEDS DATA 0 ;-- 507: Escritura en leds
;--- PANTALLA
TXSTATUS DATA 0 ;-- 508: Registro de estado
TXDATA DATA 0 ;-- 509: Registro de datos
;-- Direcciones de acceso al teclado
RXSTATUS DATA 0 ;-- 510: Registro de estado
RXDATA DATA 0 ;-- 511: Registro de datos
En esta sección se muestran los pasos necesarios para poder crear nuestros programas en Simplez y ejecutarlos en la máquina física real
Las instrucciones de instalación se han probado en una máquina Ubuntu/Linux 15.10
-
Instalar las herramientas de síntesis en FPGA. Simplez F está descrito en lenguaje Verilog. Para sintetizarlo necesitamos tener instaladas las herramientas libres: icestorm, Yosys, arachne-pnr, y para simularlo: gtkwave, icarus verilog. Todo el proceso de instalación está descrito en el apartado "instalación" de este capítulo del tutorial de verilog
-
Configurar la placa Icestick: Una vez instalado, realizar los pasos indicados en el apartado configuración, del mismo tutorial, para configurar la placa icestick
-
Instalar scons*. Es la herramienta usada para la gestión de la síntesis. En la versión 1.2 se usaba make, pero se ha sustituido por scons que es más moderna
$ sudo apt-get install scons
-
Instalar el ensamblador de simplez, junto al resto de utilidades:
$ pip3 install toolchain-simplez
También es posible instalarso **sin privilegios de root**. En ese caso hay que ejecutar:
$ pip3 install --user toolchain-simplez
```
-
Clonar el respositorio Simplez-FPGA* (o hacer un fork y clonarlo): Ahí es donde están todas las fuentes y todos los programas de ejemplo usados
$ git clone https://github.com/Obijuan/simplez-fpga ```
-
Entrar en el directorio raiz del proyecto:
$ cd simplez-fpga ```
Para programar y ejecutar nuestros programas en simplez seguiremos los siguientes pasos:
-
Editar/crear el programa en ensamblador: Usamos cualquier editor de texto para crear el archivo con el programa de simplez en lenguaje ensamblador. En estos pasos usaremos el programa de ejemplo leds_on.asm, presentado en los apartados anteriores
-
Ensamblar el programa: Abrimos un terminal en el directorio simplez-fpga/verilog y ejecutamos el ensamblador sasm.py. Se nos genera el fichero prog.list con el código máquina (y el código ensamblador en los comentarios). Este fichero está en formato de memoria de verilog, de forma que en la síntesis se lee y se usa para inicializar la memoria:
$ ./sasm.py asm/leds_on.asm
Assembler for the SIMPLEZ microprocessor (Version: v1.2)
Released under the GPL license
OK! Machine code for SIMPLEZ generated
File: prog.list
Size: 4 words
Code: 3 words
data: 1 words
Podemos visualizar el fichero prog.list para comprobar que se ha generado el código máquina:
$ cat prog.list
203 //-- [000] LD /VAL ;-- VAL = H'003
1FB //-- [001] ST /LEDS ;-- LEDS = H'1FB
E00 //-- [002] HALT
00F //-- [003][VAL] DATA H'00F
@1FB //-- ORG 0x1FB
000 //-- [1FB][LEDS] DATA H'000
El ensamblador también nos informa del tamaño del programa en palabras, y cuales son código y cuales datos
Aquí se muestra un pantallazo en el terminal de mi máquina:
- Realizar la síntesis: Se genera un bitstream con simplez con la memoria inicializada con el programa prog.list. Para ello hay que ejecutar el comando:
$ make sint
Se genera el fichero simplez.bin, que será el que cargaremos en la tarjeta icestick
- Cargar el diseño en la FPGA: usando el comando make prog:
$ make prog
En unos 3 segundos la carga estará completada.
- Arrancar el terminal de comunicaciones (gtkterm). Dejarlo configurado para abrir el puerto serie donde está la icestick (/dev/ttyUSB1 por defecto), a la velocidad de 115200 baudios. Lo siguiente es desactivar la señal DTR, que es la que usamos para hacer el reset de simplez. Desde gtkterm lo hacemos dándole a la tecla F7
- Ejecución del programa. Al desactivar el reset, empieza a funcionar simplez, ejecutando las instrucciones que están a partir de la dirección 0. En este ejemplo, se encenderán los 4 leds rojos y luego el verde, indicando que el programa ha terminado:
El simulador ssim es una clase python que nos permite cargar un programa en código máquina, ejecutarlo y observar el resultado. También es posible ejecutar las instrucciones paso a paso. Todo se hace en la línea de comandos, usando el intérprete de python en modo interactivo. Toda la simulación se hace en el ordenador. Nos permite detectar errores en nuestros programas en simplez, o verificar si funcionan correctamente
Es el primer ejemplo de programación de simplez que se encuentra en el libro [1], en el apartado 2.2 del capítulo 2:
ld /num1
add /num2
st /suma
HALT
num1 DATA H'7
num2 DATA H'8
suma DATA 0
Simularemos el programa y comprobaremos que efectivamente se obtiene el resultado 15 y se almacena en la variable suma.
Seguimos los siguientes pasos:
- Ensamblar el programa, obteniendo el código máquina en el fichero prog.list:
$ ./sasm.py asm/simplez1.asm
- Arrancar el simulador. Usamos el intérprete de python en modo interactivo (o el intérprete avanzado, ipython3):
$ python3 -i ssim.py
prog.list loaded into memory!
>>>
Se carga el programa prog.list en memoria y nos aparece el prompt de python para introducir comandos
- Ver el programa cargado. Ejecutamos el siguiente comando para comprobar las primeras posiciones de memoria:
>>> s.list()
[000] LD /H'004; [004]=007
[001] ADD /H'005; [005]=008
[002] ST /H'006; [006]=000
[003] HALT
[004] ST /H'007; [007]=000
[005] ST /H'008; [008]=000
[006] ST /H'000; [000]=204
[007] ST /H'000; [000]=204
[008] ST /H'000; [000]=204
[009] ST /H'000; [000]=204
>>>
En la izquierda, entre corchetes aparecen las direcciones de memoria. En la siguiente columna la instrucción en ensamblador correspondiente al código encontrado (interpretándolo como instrucción, aunque puede ser un dato). Como comentarios aparece el contenido de las posicones de memoria a las que se hace referencia en la instrucción. Así, por ejemplo, en la primera instrucción se carga en el contenido de la dirección 4 en el registro A. En la dirección 4 está almacenado el valor 7 (Se indica como [004]=007)
- Ver las variables en memoria. Después de la instrucción HALT se encuentran definidas las variables, cuyas posiciones son 4, 5 y 6. Podemos comprar sus valores iniciales con el comando s.mem(1) (Siendo 1 el número de bloques de 16 palabras a motrar):
>>> s.mem(1)
0 1 2 3 4 5 6 7 8 9 A B C D E F
[000] 204 405 006 E00 007 008 000 000 000 000 000 000 000 000 000 000
>>>
Vemos que los valores iniciales de estas variables, efectivamente son 7, 8 y 0
- Ejecutar el programa. Tecleamos el comando s.run() para ejecutar el programa hasta que termine:
>>> s.run()
Initial state:
PC = H'000
A = H'000
Z = 0
Next: [000] LD /H'004; [004]=007
Executing: [000] LD /H'004; [004]=007
Executing: [001] ADD /H'005; [005]=008
Executing: [002] ST /H'006; [006]=000
Executing: [003] HALT
HALT. xopcode: 14
PC = H'004
A = H'00F
Z = 0
Micro stopped! Halt executed
>>>
Al final se muestra el valor de los registros al terminar. El registro A contiene la suma de los dos (15), y el contador de programa (PC) apunta a la dirección 4
- Comprobar las variables. Por último comprobamos las variables otra vez, para ver si se ha almacenado el resultado correctamente:
>>> s.mem(1)
0 1 2 3 4 5 6 7 8 9 A B C D E F
[000] 204 405 006 E00 007 008 00F 000 000 000 000 000 000 000 000 000
>>>
En la dirección 6 se ha guardado correctamente la suma
Salimos del intérprete de python pulsando ctrl-d
Volvemos a cargar el mismo programa del apartado anterior:
- Arrancamos el simulador: igual que antes
$ python3 -i ssim.py
prog.list loaded into memory!
>>>
- Ejecutando la primera instrucción. Con el comando s.step() se ejecuta sólo la primera instrucción y se vuelve a la línea de comandos
>>> s.step()
Initial state:
PC = H'000
A = H'000
Z = 0
Next: [000] LD /H'004; [004]=007
Executing: [000] LD /H'004; [004]=007
PC = H'001
A = H'007
Z = 0
Next: [001] ADD /H'005; [005]=008
>>>
Vemos el estado inicial de los registros y la instrucción que se va a ejecutar. Luego se ejecuta y se muestra el estado final de los registros. El contador de programa vale 1 (apuntando a la siguiente instrucción). En el registro A se ha cargado el valor 7, que es el que se ha leido de la posición 4
- Ejecución de la siguiente instrucción. Repetimos:
>>> s.step()
Executing: [001] ADD /H'005; [005]=008
PC = H'002
A = H'00F
Z = 0
Next: [002] ST /H'006; [006]=000
Se ejecuta la instrucción de la línea 1, que suma el valor de la posición 5 (que es 8) al registro A, por lo que pasa a valer 15 (0xF)
- Ejecución del resto de instrucciones. Podemos seguir ejecutando paso a paso o podemos directamente ejecutar s.run() para que se ejecuten las instrucción desde la actual hasta el final:
>>> s.run()
Executing: [002] ST /H'006; [006]=000
Executing: [003] HALT
HALT. xopcode: 14
PC = H'004
A = H'00F
Z = 0
Micro stopped! Halt executed
>>>
Los 5 ejemplos de programación de simplez presentados en el capítulo 2 del libro de referencia [1] se han implementado y probado en Simplez-F. Se encuentran en el directorio verilog/asm:
Fichero | Descripción |
---|---|
simplez1.asm | Ejemplo 1: Suma de dos números |
simplez2.asm | Ejemplo 2: Suma de los diez primeros terminos de la sucesion de Fibonacci |
simplez3.asm | Ejemplo 3: Suma de cien números almacenados en la memoria (desde la 100 a la 149) |
simplez4.asm | Ejemplo 4: Intercambio de dos zonas de memoria: (Bloque 100-150 con bloque 200-250) |
simplez5.asm | Ejemplo 5: Subrutina. Resta de dos numeros |
Para facilitar la carga de programas en simplez, y sobre todo, para comprender mejor cómo funcionan los microcontroladores reales, se ha creado un Bootloader en simplez. Está programado en ensamblador de simplez y se almacena a partir de la dirección 0. Ocupa 60 palabras de memoria
Una vez cargado, al arrancar simplez se ejecuta este bootloader, que envía un dato al PC por el puerto serie para indicar que está listo. Desde el PC, con el programa sboot, se envía el programa en código máquina que se quiere cargar en simplez. Es muy importante que este programa empiece a partir de la dirección h'40 (porque antes se encuentra el propio bootloader). El bootloader recibe las palabras del programa y las almacena en memoria. Al terminar le pasa el control al nuevo programa cargado.
Este proceso es muy rápido, lo que nos permite cargar y ejecutar programas en simplez, todas las veces que queramos
Para utilizarlo, el primer paso es cargarlo en la FPGA de la manera que ya conocemos:
- Ensamblar el bootloader:
$ ./sasm.py asm/boot.asm
Assembler for the SIMPLEZ microprocessor (Version: v1.2)
Released under the GPL license
OK! Machine code for SIMPLEZ generated
File: prog.list
Size: 60 words
Code: 50 words
data: 10 words
-
Sintetizar: $ make sint
-
Cargar en la FPGA: $ make prog
El sistema se queda listo para cargar programas a través de sboot
Este es un ejemplo de programa que se puede cargar con sboot. ¡¡Importante!! el programa debe comenzar a partir de la dirección h'40. El programa reproduce una secuencia de 2 estados en los leds:
;-- Acceso a los perifericos
leds EQU 507
;-- Comienzo del programa:
;-- Direccion h'40: para cargarlo con el bootloader
org h'40
loop LD /val1 ;-- Valor secuencia 1
ST /leds
Wait
ld /val2 ;-- Valor secuencia 2
st /leds
wait
BR /loop
val1 DATA h'9
val2 DATA h'6
END
Se ensambla normalmente. En vez de grabarlo en el fichero prog.list lo haremos en sec1.list:
$ ./sasm.py asm/boot_02_sec1.asm -o sec1.list
Assembler for the SIMPLEZ microprocessor (Version: v1.2)
Released under the GPL license
OK! Machine code for SIMPLEZ generated
File: sec1.list
Size: 9 words
Code: 7 words
data: 2 words
Para cargar el ejemplo anterior en simplez ejecutamos:
(NOTA: Tenemos que tener instalada la biblioteca python3-serial)
$ ./sboot.py sec1.list
File: sec1.list
Size: 9 words
Initial address: H'040
Bootloader ready!!!!
EXECUTING!!!
En menos de 1 segundo tenemos el programa cargado y veremos cómo parpadean los leds
Si no hubiésemos grabado el bootloader, obtendríamos el siguiente mensaje de error:
$ ./sboot.py sec1.list
File: sec1.list
Size: 9 words
Initial address: H'040
ERROR: NO bootloader
En el directorio asm hay más ejemplos. Comienzan por el prefijo boot_ Además, en el directorio list hay ya programas de ejemplo compilados que podemos cargar directamente, para hacer pruebas. Probar:
- Secuencia 1:
$ ./sboot.py list/sec1.list
- Secuencia 2:
$ ./sboot.py list/sec2.list
- Contador binario:
$ ./sboot.py list/count.list
El programa sboot tiene un modo de test, en el que se carga un programa que hace rotar una luz por los leds, sin cargarlo de ningun fichero y sin necesidad de tener que ensamblar
Para probarlo hay que poner:
$ ./sboot.py -t 1
Test!
Bootloader ready!!!!
EXECUTING!!!
Para probar programas en simplez que se comunican con el PC (que usan el teclado y la pantalla de simplez), utilizamos el modo interactivo de sboot. En este modo, sboot carga el programa en la RAM de simplez y se convierte en un terminal: todo lo que escribamos se enviará a simplez y todo lo recibido de simplez se mostrará en pantalla
Como ejemplo probaremos el programa de eco. Primero lo ensamblamos:
$ ./sasm.py asm/boot_06_echo.asm -o eco.list
Assembler for the SIMPLEZ microprocessor (Version: v1.2)
Released under the GPL license
OK! Machine code for SIMPLEZ generated
File: eco.list
Size: 17 words
Code: 15 words
data: 2 words
y ahora lo cargamos en modo interactivo. Usamos la opción -i:
$ ./sboot.py -i eco.list
File: eco.list
Size: 17 words
Initial address: H'040
Bootloader ready!!!!
EXECUTING!!!
Entering the interactive mode...
Press CTRL-D to exit
hola como estas.... :-)
La simulación hardware de simplez nos sirve para ver su funcionamiento interno, y comprobar si todas las señales digitales se están generando correctamente. Tiene interés si se están haciendo modificaciones a simplez, como por ejemplo añadiendo nuevos periféricos
Seguimos los siguientes pasos:
- Ensamblamos el programa a simular. Pero en este caso no haremos una simulación funcional, sino ver qué señales se generan en el interior de simplez al ejecutar ese programa. Usaremos el ejemplo leds_on.asm.
$ python3 sasm.py asm/leds_on.asm
Assembler for the SIMPLEZ microprocessor
Released under the GPL license
OK! Machine code for SIMPLEZ generated: prog.list
- Lanzamos la simulación: Ejecutando el siguiente comando:
$ make sim
Se nos lanza la simulación y aparece el resultado en el programa gtkwave:
En la simulación hardware se pueden añadir/quitar señales, para dejar sólo las que nos interesen. En este ejemplo vemos cómo el contador de programa toma los valores 0, 1 y 2, ejecutando las 3 instrucciones el programa. También podemos ver cómo en la señal leds aparece el valor F (que es el que se ha escrito) y cómo stop se pone 1 al final, para indicar que el micro ha ejecutado la instrucción halt
Aunque simplez-F es 100% compatible con el simplez original, su implementación es muy distinta a las mostradas en el libro de texto [1]. Las principales diferencias son:
- Simplez-F es un microcontrolador: toda la memoria y los periféricos están dentro del chip
- Memoria RAM: Tiene una entrada para datos y otra salida diferente. Por tanto el bus de datos está separado
- Registro Ai no existe en Simplez-F: no es necesario
- Acceso de datos a la alu a través de un multiplexor: dependiendo de donde provengan: memoria o periféricos
- Los nombres de las microórdenes son diferentes
- NO se usan puertas triestado
La entidad simplez se declara de la siguiente forma en verilog:
module simplez #(
parameter BAUD = `B115200, //-- Velocidad de comunicacion de la pantalla / Teclado
parameter WAIT_DELAY = `T_200ms, //-- Tiempo de espera para la instruccion WAIT (Debug)
parameter | = "prog.list", //-- Fichero con el contenido de la RAM a cargar
parameter DEBUG_LEDS = 0 //-- Uso de los leds para depuracion
)(
input wire clk, //-- Reloj del sistema
input wire rstn_ini, //-- Reset
output wire [3:0] leds, //-- leds
output wire stop, //-- Indicador de stop
output wire tx, //-- Salida serie para la pantalla
input wire rx //-- Entrada serie del teclado
);
Los parámetros que tiene son:
Parámetro | Valor por defecto | Descripción |
---|---|---|
BAUD | 115200 baudios | Velocidad para la comunicación serie con el teclado / pantalla |
WAIT_DELAY | 200ms | Tiempo de espera para la instrucción WAIT |
ROMFILE | prog.list | Nombre del fichero con el código máquina para iniciar la memoria RAM |
DEBUG_LEDS | 0 | Usar los leds como un puerto de salida normal (0) o bien conectarlos directamente al registro A |
Son los descritos en el apartado Descripción / pines
El diagrama de bloques del circuito se muestra a continuación:
Es una transcripción tal cual del código en verilog. Siempre es más intuitivo el esquema que el código
Los recursos usados de la FPGA ICE40HX1K al sintetizar simplez-F se muestran en la siguiente tabla:
Recurso | ocupación |
---|---|
PIOs | 12 / 96 |
PLBs | 91 / 160 |
BRAMs | 2 / 16 |
La **frecuencia máxima de funcionamiento **de simplez de puede calcular con la herramienta icetime (que forma parte de las icetools). Para calcular la frecuecia máxima ejecutamos:
$ make time
[...]
icetime -mtr simplez.rpt simplez.asc
// Reading input .asc file..
// Reading 1k chipdb file..
// Creating timing netlist..
// Timing estimate: 17.84 ns (56.06 MHz)
Se genera el fichero simplez.rpt con el informe de tiempos y caminos críticos. Para esta implementación de simplez se obtiene una frecuencia máxima de 56MHZ
En la versión 1.2 de simplez, se ha incluido soporte para la síntesis / simulación usando SCONS. Es muy alfa todavía. Scons es una herramienta similar a make, pero más moderna
Scons se instala con el siguiente comando:
$ sudo apt-get install scons
- Para sintetizar, ejecutamos:
$ scons
- Para simular:
$ scons sim
- Para obtener el análisis de tiempos:
$ scons time
- Para hacer limpieza (equivalente a make clean):
$ scons -c
Las reglas de construcción se encuentran en el fichero Sconstruc
Juan González Gómez (Obijuan)
-
Gregorio Fernández Fernández es el creador del procesador Simplez, publicado en su libro [1]
-
Creadores de las herramientas libres usadas para sintetizar a Simplez F:
- Proyecto icestorm, por Clifford Wolf and Mathias Lasser
- Arachne-pnr, por Cotton Seed
-
Herramientas para la simulación hardware de SIMPLEZ F:
- Simulador de Verilog: ícarus Verilog
- Visualizador de señales: Gtkwave
Licensed under a Creative Commons Attribution-ShareAlike 4.0 International License
[1] Libro: "Curso de ordenadores : conceptos básicos de arquitectura y sistemas operativos". Ed. ETS Ingenieros Telecomunicaciones, UPM. 2005. Madrid. ISBN: 9788474023121
- Tutorial Verilog: Diseño Digital para FPGAs, con herramientas libres. Aprende a hacer diseños digitales en verilog y sintetizarlos en FPGA usando herramientas libres
- FPGA-WARS: explorando el lado libre: Grupo / lista de correo para conocer las últimas noticias, preguntar, compartir y colaborar en el desarrollo de hardware libre reconfigurable
- Tarjeta icestick. Tarjeta entrenadora con FPGA, que funciona con las herramientas libres
- Simulador simplez/Algoritmez. Simulador enn JAVA
- Materiales didácticos. Página del DIT, ETSIT, UPM Madrid.
- Micro simplez en VHDL. Implementación de micro-simplez en lenguaje VHDL
- Descripción de Simplez. Universidad de Vigo