Skip to content

Procesador SIMPLEZ F

Juan Gonzalez-Gomez edited this page Jan 22, 2016 · 115 revisions

Simplez F, con su carcasa impresa en 3D :-)

Acceso al repositorio

Resumen

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

VideoBlog

TODO

Introducción

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.

Características de Simplez

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

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)

FPGA y herramientas libres

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.

Materiales

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

Descripción

Los pines

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

Simplez en la icestick

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

Formato de instrucción

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

Repertorio de instrucciones

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

Periféricos

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)

Directivas del ensamblador

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

Ejemplos hola mundo de programación

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)

leds_on.asm: Encender todos los leds

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

sec.asm: Secuencia de 2 estados 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

eco.asm: Sacar por la pantalla todo lo enviado por el teclado

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

Manual de uso

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

Instalación

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. También necesitaremos un terminal de comunicaciones serie, como por ejemplo el gtkterm

Todo el proceso de instalación está descrito en el apartado "instalación" de este capítulo del tutorial de verilog

Una vez instalado, realizar los pasos indicados en el apartado configuración, del mismo tutorial, para configurar la placa icestick

Probando ejemplos en Simplez

Para programar y ejecutar nuestros programas en simplez seguiremos los siguientes pasos:

  1. 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

  2. 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:

  1. 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

  1. Cargar el diseño en la FPGA: usando el comando make prog:
$ make prog

En unos 3 segundos la carga estará completada.

  1. 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

  1. 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:

Simulando ejemplos en el PC con ssim

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

Simplez1.asm: Simulando la suma de dos números

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:

  1. Ensamblar el programa, obteniendo el código máquina en el fichero prog.list:
$ ./ssim.py asm/simplez1.asm
  1. 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

  1. 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)

  1. 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

  1. 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

  1. 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

Simulación paso a paso

Volvemos a cargar el mismo programa del apartado anterior:

  1. Arrancamos el simulador: igual que antes
$ python3 -i ssim.py

prog.list loaded into memory!
>>>
  1. 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

  1. 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)

  1. 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
>>> 

Más ejemplos de programación de simplez

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

Bootloader y Cargador sboot

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

Grabando el bootloader

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

Ejemplo: boot_02_sec1.asm

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

Carga de programas con sboot

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

Más ejemplos

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

sboot en modo test

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!!!

sboot en modo interactivo

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....  :-)

Simulación hardware

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:

  1. 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
  1. 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

Implementación

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

Entidad símplez

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
);

Parámetros:

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

Pines

Son los descritos en el apartado Descripción / pines

Diagrama de bloques

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

Recursos

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

Análisis de tiempo

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

Author

Juan González Gómez (Obijuan)

Créditos

  • 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:

  • Herramientas para la simulación hardware de SIMPLEZ F:

Licencia

Licensed under a Creative Commons Attribution-ShareAlike 4.0 International License

Referencias

[1] Libro: "Curso de ordenadores : conceptos básicos de arquitectura y sistemas operativos". Ed. ETS Ingenieros Telecomunicaciones, UPM. 2005. Madrid. ISBN: 9788474023121

Enlaces