Escrito por Guillermo Acevedo
 
Objetivos:
  • Diseñar e implementar una aceleración para el algoritmos de karplus strong por medio de hardware, realizando un hardware especifico para nuestro sistema controlado por medio del software.
  • Conocer el principio de la aceleración de algoritmos por medio de hardware y su implementación
 
Diseño
 
En esta practica se realiza la implementación hardware del el algoritmo de karplus strong, para tener los sonidos de una guitarra, en la anterior practica se implementó de manera software, en esta se realizara desde el punto de vista software, es decir, haciendo la analogia con una guitarra real, antes teníamos el software como dedos y guitarra, esta vez los dedos serán el software y el hardware en la FPGA sera la guitarra, cuando el software induce la nota y el tiempo, el sonido se creara en la FPGA y saldrá por un pin que emula ser un convertidor digital-analógico, se quiere implementar el siguiente diseño:
 
 
 
El divisor de frecuencia va conectado al dato para tener la frecuencia deseada y al clk del sistema, del NIOS, se selecciona la nota que se enviara, el nois_en elige que datos pasan por el multiplexor, se escogieron 500 registros ya que según la tabla el máximo valor al que se llegara es 469.
 
 
 Qsys
 
Lo primero que se debe hacer es ingresar al Qsys, y colocar nuevos puertos paralelos de entrada y salida, los cuales serán noise, noise_en, sel_nota, noise_pulse como se muestra en la siguiente figura, se conectan el clk al reloj de 50Mhz, se conecta el reset al reset del sistema, s1 se conecta al data master, y la conexión externa se exporta con el nombre deseado y generamos automáticamente las direcciones.
 
 
Se debe generar el HDL verilog, y debe aparecer en la jerarquía los puertos que acabamos de agregar, como se muestra en la siguiente figura:
 
 
Verilog karplus strong
 
Generamos un nuevo archivo de verilog, y creamos el modulo de karplus strong, debemos instanciar allí las entradas y las salidas del sistema, para este tendremos en las entradas un clk, reset, el vector noise [15:0], noise_en, vector sel_nota [9:0], noise_pulse, vector div_freq_in[31:0] y la salida syn_guitar[15:0]
 
Para poder diseñar lo anteriormente descrito se debe crear un registro de tamaño 500 y de 16 bits, y el registro z, el cual es un retenedor de orden 1, es decir retiene el dato anterior por un pulso de reloj. 
Se crean wires para transmitir los datos, en el wire current_value se guarda el dato de salida del valor seleccionado de sel_nota.
En el wire feedback se realiza la suma de los valores current_value y z, es decir, el valor seleccionado en la salida mas el valor anterior divididos en 2, por eso la suma se realiza de 15:1 y no de 15:0, ya que una división en 2 elimina el ultimo bit. 
Se crea también un cable para transmitir la frecuencia de la salida del divisor de frecuencia llamado clk_div_freq.
En la primera figura podemos observar 2 multiplexores, uno decide si pasa ruido, o si pasa el valor de feedback, y el otro decide si pasa el valor de la frecuencia del pulso de ruido o clk_div_freq. Para el primero se asigna directamente a la salida syn_guitar el valor; para el segundo se crea un wire llamado clock, el cual sera la señal de reloj con la cual trabajara nuestro sistema.
Luego de esto se debe instanciar el modulo de division de frecuencia dentro de nuestro modulo de karplus strong para poder utilizarlo, conectamos a la entrada div_freq_in y a la salida de este modulo clk_div_freq.
En el primer always se realiza cada vez que hay un flanco de subida en el wire clock, en el se guarda el valor anterior en z.
Lo anteriormente mencionado se puede observar en la siguiente imagen:
 
 
para inicializar los valores del registro utilizaremos el generate, el cual posee un pre compilador para traducir el código descrito en alto nivel a lenguaje de descripción de hardware, esta vez utilizaremos un for para ello, utilizamos 499 de los 500 registros en esto. Creamos un nuevo always dentro del for, que trabaja con cada flanco de subida del wire clock, y el valor de line_length en en registro actual es igual al valor line_length del registro menor a el.
 
 
Implementación
 
Instanciamos nuestro modulo de karplus strong y lo pegamos en en modulo principal, borramos las señales internas, creamos wires nuevos para interconectar nuestro modulo con el modulo del NIOS,  wire de noise_nios, wire de guita_syn el cual es la salida del modulo kuartus, el cual se conectara mas adelante, wire de sel_nota que transmite cual es la nota seleccionada, wire de noise_en que transmite el enable creado por el NIOS, wire de noise_pulse el cual transporta los pulsos de la salida noise_pulse del NIOS. 
 
 
Se conectan respectivamente con los periféricos de los modulos del NIOS y el de karplus, los cuales, en su gran mayoria, poseen un nombre muy parecido a su respectivo wire, como se observa en la siguiente figura:
 
Instanciamos ahora el modulo dac_nano, el cual emula un convertidor digital-análogo, conectamos a su entrada el wire guita_syn, con su bit mas significativo negado ya que este es el del signo, y su salida la conectamos a un pin de salida del GPIO.
 
Observamos el RTL del diseño para observar que todo halla quedado bien conectado, el resultado es el siguiente:
podemos observar que todo esta conectado de acuerdo a nuestros requerimientos, observemos a continuación lo que se ve en nuestro modulo de karplus strong en el RTL:
Esto se debe a que tenemos conectados dentro de el con solo el generate 500 flip flops, con los otros elementos se interconectan para producir este resultado.
 
Para terminar este diseño hardware se debe guardar todo y compilar el diseño, podemos ver el diseño hardware en el archivo DE0_NaNO_SOC_practica_nios2.qar que se encuentra en los archivos para descargar; nos dirigimos ahora a realizar nuestro código software
 
Software
abrimos el software de eclipse para NIOS II, creamos una nueva aplicacion and BSP from template
 
abrimos el archivo SOPC generado por el diseño hardware, le colocamos un nombre a nuestro proyecto y seleccionamos en project template a hello world y damos en finish.
 
Creamos nuestro proyecto, ahora vamos a nuestro proyecto, damos click derecho en el proyecto y elegimos en crear una nueva carpeta, la cual llamaremos karplus, en la que guardaremos los archivos .h y .c que vamos a utilizar.
 
en la carpeta que creamos hacemos click derecho y creamos un nuevo header file, luego realizamos lo mismo con un source file, despues de crearlos cambiamos sus nombres por karplus.h y karplus.c respectivamente
 
 
abrimos el archivo karplus.h, en el cual vamos a incluir las librerías necesarias para este trabajo, en el también definimos cada una de las notas de las cuerdas con sus respectivos trastes según la tabla dada al principio y por ultimo definimos las funciones que vamos a utilizar; para ver la tabla completa definida de las notas mira el archivo https://github.com/Adrizcorp/ece10243upb2016/blob/master/Estudiantes/guillermo/solucion_guitarra/software/nios_2/karplus/karplus.h.
 
Teniendo en cuenta las funciones que vamos a utilizar abrimos el karplus.c, y en el vamos a definir cada cada función y describirlos, en el primero, inject_noise se realiza un for para inyectar el ruido a los 500 flip flops, y envía los pulsos de noise_pulse cada vez que envía un dato.
 
 
En la función init_karplus, se inicializan las variables y en la función de set_karplus_frequency se da la velocidad de muestreo de nuestro audio, para este caso sera de 44100Hz, por ultimo, en la función play tone se selecciona la nota, se indica el tiempo en mili-segundos de la duracion de la nota, 
 Por ultimo editamos el archivo hello_world.c, en ella incluimos nuestra libreria #include "./karplus/karplus.h", y en nuestro int main inicializamos con init_karplus y damos la frecuencia de muestreo con se_karplus_frequency, luego de esto en nuestro while infinito escribimos las notas y los tiempos deseados para producir una canción, en este caso tenemos la opción para  probar cada uno de los valores de la tabla, sonar la canción del himno de la alegría, o que suene a canción O Christmas Tree Tannenbaum.
 
Referencias:
 
 
 
 
 
Escrito por: Alix Angarita
 

En esta práctica usaremos el procesador Nios II, implementado en la práctica anterior.  En esta ocasión para generar el sonido de una guitarra al ser tocada gracias al algoritmo de Karplus-Strong.

En la imagen a continuación se pueden ver algunos conceptos importantes a saber antes de seguir el manual.  

 

Algoritmo de Karplus-Strong

El algoritmo consiste en un sistema discreto que para una línea de registros que son leídos y escritos llegan a producir sonidos muy similares a los de una cuerda al ser rasgada.  Es un método de modelado físico, que lleva una corta forma de onda a través de estos registros.

Esta técnica aprovecha la transformada Z para tener el retraso de la señal necesario para realizar el ciclo. Fue inventado por Alexander Strong, y luego analizado por Kevin Karplus. Implementaron el algoritmo juntos llamándolo "Síntesis Digitar" como una contracción de "Digital Guitar".

 

 
Funciona inicialmente con una señal de excitación, la cual es realimentada por las muestras anteriores almacenadas en los registros, dentro del proceso ésta pasa por un filtro pasa-bajas.
Al final se tiene la mezcla simultánea de ambas señales.

Algoritmo implementado en Matlab

Tenemos un código en Matlab con el algoritmo de Karplus-Strong funcionando.  Descárguelo aquí.  Pruébelo, así sonará la guitarra que implementaremos.

 
 
En el programa se declara la línea de registros con 156 elementos, los cuales se leen a una frecuencia de muestreo de 16000 Hz.
Para inicializar los registros se usan valores aleatorios, ya que lo que necesitamos es un cambio o impulso que representaría la perturbación que recibe la cuerda de la guitarra al ser tocada.
El ciclo for realiza el proceso que indica el diagrama de bloques, recorre las muestras almacenadas en la fila de registros y luego se multiplican por el factor de 0.5 tanto la muestra actual como la anterior, se suman y se mandan a la salida como realimentación.
 

Base Hardware

El hardware sobre el que trabajaremos será el mismo que describimos para usar el Nios II, con los módulos del Nios diseñado en el Qsys y un dac_nano como el usado en la práctica del NCO para convertir las frecuencias en una salida de audio.  A la salida final se conectan una resistencia, un capacitor y un parlante o audífono para escuchar el sonido de la guitarra.

Para esto se puede trabajar sobre el proyecto de la práctica anterior de Nios II agregando el dac_nano que se encuentra al final del manual con el resto de los archivos de la práctica.

Se crean las instanciaciones y se copian en el chip principal, a la entrada sw exportada de Nios se conectan los interruptores, a la salida div_freq_export se conecta un cable que llevará la señal hasta el módulo dac_nano en el pin DACin, la salida de audio se asigna al GPIO.

 

Programación del NIOS II

Como vamos a implementar el algoritmo en el Nios II, usando a la FPGA como creador del impulso de la guitarra y como la guitarra misma, el código en Matlab se puede reutilizar para programar el procesador, así, el siguiente paso es pasar el código escrito en Matlab a código en C, usando el IDE Eclipse.

Después de abierto, cree un nuevo proyecto desde una plantilla:

 

En la ventana del nuevo proyecto, abra el archivo de hardware*, la ventana tardará un poco en habilitar el resto de las opciones, la CPU se seleccionará de forma automática, ya que sólo contamos con una, luego nombramos el proyecto en el segundo campo, nos aseguramos que la plantilla del proyecto sea la de Hello World, por último, le damos Finish.

 

* El archivo de hardware tiene formato SOPC y debe asegurarse que esté exactamente en la carpeta del proyecto de quartus que programamos en la FPGA.

 

Dentro del proyecto que se acaba de crear abra el archivo llamado hello_world.c, dentro de él se escribirá el código en C del algoritmo Karplus-Strong.

 

Se incluyen las librerías básicas de C, la librería system.h para poder trabajar con el procesador diseñado y la librería io.h para usar los periféricos.

Se declaran algunas variables tal como se hizo en el código de Matlab, y un vector con las frecuencias de las notas para el primer traste.

 
Se declara un ciclo infinito para escribir el proceso de Karplus-Strong.  Dentro del while se lee el valor actual de entrada y si se detecta el impulso se inicializa el vector sr con valores aleatorios y se generan las muestras y se realizan el resto de las operaciones para generar el sonido propuesto multiplexando las frecuencias para cada nota.
 
download source

Construimos el proyecto y hacemos el debug para probar que el procesador esté funcionando según el algoritmo programado.  Si no recuerda cómo hacer esto revise el manual de NIOS II Software.

Resultados

Para probarlo conecte un plug de salida de audio en el pin del GPIO_0 número 4, y un audífono o parlante para escuchar las diferentes notas generadas por la guitarra digital que acabamos de programar.

En el video a continuación puede ver el funcionamiento de la FPGA como guitarra. Descargar Solución

 

Referencias

 
 
  • https://people.ece.cornell.edu/land/courses/ece5760/FinalProjects/f2009/kr334_ask43/kr334_ask43/kr334_ask43/index.html
  • https://ccrma.stanford.edu/~jos/pasp/Karplus_Strong_Algorithm.html
  • Julius Smith, "Making Virtual Electric Guitars and Associated Effects Using Faust", Encontrado en: https://ccrma.stanford.edu/realsimple/faust_strings/faust_strings.pdf 
  • K. Karplus y A. Strong, "Digital synthesis of plucked string and drum timbres'',  Encontrado en: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.144.5585&rep=rep1&type=pdf

 

Escrito por: Alix Angarita

 
Durante este tutorial aprenderemos a dibujar en la pantalla basados en el proyecto en el que trabajamos para la primer articulo de este manual.  Para dibujar usaremos el algoritmo de Bresenham.
 

Algoritmo de Bresenham

Es un algoritmo que determina los elementos de una matriz que deberían seleccionarse para que juntos formen una línea.  Esto se aplica para la matriz de pixeles que forman una pantalla.
Consiste en una aproximación de puntos tal que al pasar una línea por ellos haya el menor error posible, funciona con suma de enteros, restas y corrimientos, las cuales son operaciones que no requieren de mucho procesamiento y funcionen en cualquier arquitectura.  Tiene la desventaja de ir aumentando su error a medida que se aumenta su complejidad, pero por ser tan sencillo en términos generales es bastante utilizado.
 
La convención que utiliza para hacer el barrido es el siguiente: 
 
El valor del pixel aumenta a la derecha y hacia abajo, siendo la primera coordenada el valor de la columna y la segunda el valor de la fila.  Es importante saber esto, ya que así es posible determinar la línea que se dibujará en función de su pendiente.
Sabiendo la pendiente de la línea que se va a dibujar se obtienen los pixeles que se siguen dibujando para dar forma a la línea basado en la siguiente fórmula:
  
 
Al usar el algoritmo, el resultado sería algo como esto:
 
 
 
 

Pseudocódigo:

 function line(x0, y0, x1, y1)
     real deltax := x1 - x0
     real deltay := y1 - y0
     real error := -1.0
     real deltaerr := abs(deltay / deltax)    // Asumir deltax != 0
     // Es importante tener en cuenta los decimales en la división
     int y := y0
     for x from x0 to x1-1 
         plot(x,y)
         error := error + deltaerr
         if error ≥ 0.0 then
             y := y + 1
             error := error - 1.0
 
Se puede ver que se describe la función line, que como es nuestro objetivo dibujaría una línea en la pantalla.  Esta función incluye 4 argumentos, los cuales son dos pixeles de la pantalla, cada uno con sus coordenadas, la línea recta que une a estos dos pixeles sería la que se mostraría en pantalla.
 
Para calcular la pendiente de la recta se halla primero dos deltas, el delta horizontal y vertical, con la división de éstas se tiene:
 
 
Donde el término de la izquierda es deltaerr.  
 
Con esto empezamos a recorrer los pixeles que conforman la línea.  Se tiene para X que se recorre desde X0 hasta X1, de la misma manera para Y.  Usando la relación matemática se encuentra cuál es el error para cada pixel dibujado, que como se puede ver incrementa a cada iteración, esto se corrige variando la coordenada en Y, con esto el error se recalcula.
 
El siguiente paso para entender el algoritmo es implementarlo en software, yo lo implementé en C, pero cualquier lenguaje es útil.
 
El código es el siguiente:
 
               
 
 
En la primera parte está la descripción de la función tal y como en el pseudocódigo, en la segunda parte la declaración de la matriz, etc, lo importante es el uso de la función que dibuja la línea, en la cual se colocaron las coordenadas de la línea que se quería dibujar.
 
Al compilarlo se graficó así en forma de texto para hacerlo más sencillo:
 
 
Se puede concluir que la línea se dibujó con un código muy sencillo, pero se hizo evidente la desventaja del error al inicio de la línea, en este caso sobretodo porque se tenía una matriz muy pequeña, pero es un buen ejemplo para entender mejor cómo funciona el algoritmo.
 
Ahora es momento de implementarlo en hardware, primero en papel definimos que entradas y salidas tendría el chip y que más requeriríamos para su construcción.
El módulo consiste en:
  • Una señal de start para indicar que se debe ejecutar el módulo, esto porque las coordenadas (x0,y0) y (x1,y1) son válidas.
  • Cuatro entradas de 11 bits con las coordenadas correspondientes
  • Una señal de salida plot, la cual indica que las coordenadas ingresadas hacen parte de la línea
  • Dos señales x y y que llevan la información que se irá dibujando en cada pixel
  • Una señal llamada done, para indicar que el proceso se ha terminado
Si se hace un análisis de los tiempos con las señales propuestas se tienen los siguientes comportamientos:
 
Se puede ver claramente el comportamiento de las señales x y y, según las entradas de coordenadas y después de que ha sido activado el pulso start.  De igual manera cómo están sincronizadas la señal plot con la señal start done formando lo que serían 3 estados del proceso.
 

Descripción en Verilog

Este módulo se trabaja en el proyecto de la primera parte del tutorial, por lo que con éste abierto creamos un nuevo archivo de tipo systemverilog.
 
Un archivo systemverilog es una combinación entre un lenguaje de descripción de hardware y un lenguaje de verificación de hardware, funciona de manera muy similar a verilog, con la misma sintaxis. 
 
 
La descripción como la indica la bibliografía es la siguiente:
 
 
 
 
 
 
 
Su comportamiento general es el de una máquina de estados con datapath.
  
                              Para Dx y Dy:                                                                                                                                                            
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Para err:  

   
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Para x y y:
 
 
 


Simulación

Después de describir el módulo, conviene simular que las señales de salida se comporten como las que vimos antes en la teoría.
 
Es importante revisar la sección de simulación en esta página para realizar la simulación de manera exitosa.
 
Para llegar a este punto se seleccionan las señales que se quieren simular, en la imagen se muestran cuales nos ayudarán a llegar a una buena conclusión.
 
 
Se comprueba que el proceso empiece con un flanco de subida de la señal start.
 
Se analiza el comportamiento.  Para las mismas coordenadas analizadas en un diagrama de tiempos al principio de este manual se continuó la simulación después de que start se llevó a bajo y la señal plot se puso en alto, funcionando el algoritmo.  Se observa que cambia de manera líneal y que Y depende de la señal de error.  Err toma los mismos valores que se predijeron en el diagrama de tiempos.

Módulos adicionales:

  • Framebuffer

Un framebuffer es una porción de RAM que contiene un mapa de bits de manera que al ser leída se puede reconstruir un frame.  Allí se almacenan los valores de color para cada pixel. 
Es posible incluir un canal alpha para generar el efecto visto en la parte 1 de este manual.

Éste módulo, tiene entradas de posición que indican dónde se está posicionando en la pantalla y dos señales para habilitar el color y la escritura, en este caso la línea.  A la salida se tienen las señales de sincronización vertical y horizontal.

Para describir el módulo en verilog, después de indicar las entradas y salidas se indican algunos parámetros necesarios para las señales de sincronización a la salida, tal como se hizo con la primera parte.

          

Se usan dos contadores, uno horizontal y otro vertical para el barrido de la imagen, ambos a la velocidad del reloj de 50MHz o interrumpidos por reset si este pulso aparece. 

Las señales end0fLine end0field indican como su nombre lo indica el fin de una línea barrida o de un frame.

Se añaden otras señales que tienen la mismas funciones que las descritas en el módulo mi_vga de la primera parte 

En el bloque always a continuación, se indica cuándo el barrido corresponde al área visible.

Al final se asigna el bit menos significativo del conteo al reloj, lo que hace que la señal presente un cambio de estado que resulta en un reloj de la mitad de la frecuencia del conteo, es decir de 25MHz.
 
El dato que se lee en el registro framebuffer en la posición read_adress, se asigna a las salidas R, G y B, para conectar al siguiente módulo.

 

  • Hallway: Generador de línea

En este módulo se describe una máquina de estados que lleva la información de la línea a el módulo bresenham para ejecutar el algoritmo.

Se declara la variable que determinará el estado en el que se encuentra la máquina.

Crea el bloque always donde se describirá la máquina de estados, también el nivel de las señales de salida si se activa el reset.  Define a S_TOP como el estado predeterminado.

Se define el case con el primer estado, en el cual la salida start se activa para una señal de done en alto, y se asigna el comportamiento de x0.

Los siguientes estados se definen a continuación:

 

 

 

 

 

 

 

Define que cuando VGA_VS está en bajo se está fuera de la zona visible de la pantalla.

Resultados

Ya con los módulos necesarios, regresamos al chip principal para hacer las instanciaciones y probar el resultado final.

Se necesitan algunos cables para hacer las conexiones entre los módulos, y asignar a los pines de salida.

 
En el módulo bresenham se conectan las entradas de startdone, las coordenadas de entrada para la línea que se va a dibujar, y las señales y de salida al framebuffer.
 
 
Para el framebuffer se conectan los datos de color que se asignan a la salida para su conexión al cable VGA.
 
 
Lo mismo para el módulo hallway.
 
 
 
Referencias
  • http://www.cs.columbia.edu/~sedwards/classes/2016/4840-spring/
  • https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
  • https://sites.google.com/site/ece10243upb2016/2-simulacion-y-fsm
  • Pong P. Chu, "Embedded SoPC Desing with Nios II Processor and Verilog Examples"
  • Stephen A. Edwards, "Drawing Lines with SystemVerilog"

 

Written by Guillermo Acevedo
 
Diapositivas:
 Procedimiento en base a la practica de ece31289upb2015:
 
 

Pipeline - DE0-NANO-SOC

  • Suponga lo siguiente: su maquina de estados recibe un dato(in) cada start y realiza la siguiente operación matemática a=in*3 y luego a=a+3, para realizar esta operación suponga que su FSM utilizo 4 estados, IDLE, MULT, SUM y READY, ahora suponga que su FSM trabaja a 50MHz y que el start esta en 1'b1 y responda:
    • ¿Cuantas ciclos de reloj necesito para realizar la operación?
      • Se necesitan 4 ciclos de reloj
    • Cuanto tiempo requiere para dar un resultado.
      • Se requieren 80ns
    • ¿Que tendría que hacer para se genere una respuesta cada 20ns?
      • Aumentar la frecuencia de trabajo
  • Entendido el anterior concepto podemos empezar con el concepto de pipeline, para esto comparemos una FSM con un diseño pipeline.
    • Compare la FSM del anterior punto con lo siguiente:
      • Imagine una fabrica que fabrica dulces y tiene solo un trabajador que se llama wilmer el cual se encarga de toda la cadena de producción, y esta cadena de producción tiene 4 etapas.
        • 1 etapa: Recibe el dulce.
        • 2 etapa: le da forma al dulce.
        • 3 etapa: sella el dulce.
        • 4 etapa pone el dulce en una caja listo para la venta.
      • Como en la FSM se requirieron 4 etapas para llevar un dulce de una etapa inicial a una etapa final, hágase la misma pregunta de el primer punto.
      • ¿como aumentaría el numero de dulces por minuto que genera la fabrica?
        • Si usted lo pensó bien, contrataría a 3 personas mas, teniendo así 4 personas en producción.
        • veamos ahora el ciclo
          • La primera persona recibe el dulce, mientras que las otras 3 no hacen nada.
          • La segunda persona le da forma dulce mientras que la primera recibe otro dulce, y las otras 2 no hacen nada.
          • La tercera persona sella el dulce mientras que la segunda le da forma al dulce y la ultima no hace nada.
          • la cuarta persona pone el dulce en la caja listo para la venta, mientras que la tercera sella otro dulce, la segunda le da forma a otro dulce y la primera recibe otro dulce.
          • ahora todas las personas están haciendo algo y cada vez que la primera persona recibe un dulce, sale un dulce listo en una caja.
        • ¿Que diferencia tiene esto con tener una persona(FSM) y tener 4 personas(Pipeline)?
          • Con 4 personas se tendrían mas dulces en un menor tiempo que si tuviéramos una sola persona trabajando
        • ¿Que beneficios trae con respecto a la cantidad de dulces que puede hacer por minuto?
          • Cada dulce que se hace en un dulce una sola persona, se crean 4 con 4 personas, es decir, si en un minuto una persona hace un dulce, 4 personas harían 4 dulces
    • Ahora pensemos en hardware y no en personas, la misma FSM del punto 1...si lo noto bien y para aumentar la cantidad de operaciones se debe aumentar la frecuencia de reloj, lo que traer como consecuencia el aumento de potencia que consume un dispositivo electrónico, ¿no es asi?, osea que si yo necesito que mi FSM genere datos a alta velocidad necesitare aumentar frecuencia y por lo tanto la potencia que disipara la FPGA sera mayor...
    • Ahora imagine utilizar en vez de 4 estados, 4 stage (como las personas) y que cada stage es un registro que almacena lo que viene del anterior(persona) en la cadena de producción.
      • ¿Que beneficios trae esto en cuanto al consumo de potencia y la frecuencia necesaria?
        • Se utilizaría menor potencia ya que la frecuencia de reloj es menor, se necesita menor frecuencia para tener un mismo resultado que con una FSM normal
      • ¿Alguna desventaja?.
        • Se utilizan mas recursos de la FPGA en paralelo
  • Habiendo leído lo anterior usted ya tiene el concepto de pipeline y ahora necesita aplicarlo, para esto va hacer lo siguiente.
    • Diseñe una FSM como la del punto 1.
      • en la siguiente imagen podemos ver la simulación de la FSM del primer punto, el codigo esta puesto en el archivo multi.v, podemos ver que en la primera linea, en el cuadro celeste, se encuentra la entrada, la segunda linea, en el cuadro gris, es la señal de start que siempre esta activado, la tercera linea, en el cuadro rosado, son los pulsos de reloj, la cuarta, en el cuadro rojo, es la salida del idle, la cual indica cuando se encuentra en en el primer estado, la quinta señal, en el cuadro naranja, es el finish, la cual indica cuando se encuentra en el ultimo estado. por ultimo tenemos la señal de salida, en el cuadro verde, la cual da una salida cada 4 pulsos de reloj, cada vez que se activa finish da la salida correspondiente.
    • Lea la documentación siguiente desde la diapositiva #9 a la #15 y desarrolle cada circuito y problema que proponen en el.
  • en la siguiente imagen se puede observar la simulación con Pipeline del ejercicio anterior y podemos ver el archivo en los anexos como pipeline.v
    • en la imagen observamos el reloj en verde,dentro del cuadro rosado, cada flanco de subida es un pulso, en la primera linea, encerrada en el cuadro morado, vemos la entrada del sistema, 3, 5, 7, 9, etc, la linea roja después de estos números es una x de indefinido, la segunda linea son los pulsos de reloj, la tercera linea es la salida del sistema, encerrada en amarillo, podemos observar que a partir del cuarto pulso obtenemos salida en el sistema, antes de este pulso, la salida es indefinida, luego da una salida diferente cada pulso de reloj
    • encerrado con marron estan los diferentes registros de cada estado.
    • la cuarta linea tenemos el valor de la entrada guardado como memoria, llamado idle, después del ultimo dato ingresado en la entrada también es el ultimo dato en idle, luego también su valor es indefinido
    • la quinta linea tenemos el valor guardado de la multiplicación por 3 de cada numero, en el segundo pulso tenemos la primera salida en multi, en la sexta linea tenemos el valor de la suma, el valor de la multiplicación anterior mas 3, su primer valor esta en el tercer pulso de reloj, en la séptima linea tenemos la salida del sistema, este se conecta por medio de un cable a la salida y tienen el mismo valor, su primer valor esta en el cuarto pulso
  • el codigo para pipeline es el siguiente:
    •  
  • se debe crear un flip flop para cada estado, es decir, cada estado ademas es un registro y se deben conectar por medio de cables, estos registros guardan el dato y lo utilizan en el siguiente pulso de reloj para pasar el dato, es como tener registros en serie y al final se obtiene la salida de las operaciones cada flanco de reloj, esto lo podemos ver con mas detalle en la siguiente grafica
  •  
  • la primera salida en ambos se crea en el cuarto pulso, la diferencia es que con la maquina de estados finitos se tiene una salida cada 4 pulsos de reloj, en cambio con pipeline despues de tener la primera salida, se tienen salidas constantemente.
  • en 500MHz el periodo del reloj es de 2ns, es decir, con una FSM da un resultado cada 8ns, sabiendo esto, en un segundo tenemos 125 millones de resultados, con pipeline tenemos un resultado cada flanco de reloj, es decir, podemos tener un reloj de 8ns para obtener el mismo numero de resultados, es decir, un reloj de 125MHz obtendría los mismos resultados que con la FSM.
  • – Pipelines gráficos  se encuentran en la mayoría de las tarjetas graficadoras y consiste en múltiples unidades aritméticas o CPUs completas  que implementan variados escenarios de operaciones típicas, por ejemplo calculos de luz y colores  renderizado proyección de perspectiva entre otros.

  •  En software  consiste en varios  procesos ordenados de tal forma que el flujo de salida de un proceso alimenta la entrada del siguiente proceso. Como por ejemplo, los pipelines de Unix.

  • Lea los siguientes artículos y analice para ver el campo de aplicación:

Pipeline practice ece31289upb 2015

Written by: Holguer A. Becerra
  • Suponga lo siguiente: su maquina de estados recibe un dato(in) cada start y realiza la siguiente operación matemática a=in*3 y luego a=a+3, para realizar esta operación suponga que su FSM utilizo 4 estados, IDLE, MULT, SUM y READY, ahora suponga que su FSM trabaja a 50MHz y que el start esta en 1'b1 y responda:
    • ¿Cuantas ciclos de reloj necesito para realizar la operación?
    • Cuanto tiempo requiere para dar un resultado.
    • ¿Que tendría que hacer para se genere una respuesta cada 20ns?
  • Entendido el anterior concepto podemos empezar con el concepto de pipeline, para esto comparemos una FSM con un diseño pipeline.
    • Compare la FSM del anterior punto con lo siguiente:
      • Imagine una fabrica que fabrica dulces y tiene solo un trabajador que se llama wilmer el cual se encarga de toda la cadena de producción, y esta cadena de producción tiene 4 etapas.
        • 1 etapa: Recibe el dulce.
        • 2 etapa: le da forma al dulce.
        • 3 etapa: sella el dulce.
        • 4 etapa pone el dulce en una caja listo para la venta.
      • Como en la FSM se requirieron 4 etapas para llevar un dulce de una etapa inicial a una etapa final, hágase la misma pregunta de el primer punto.
      • ¿como aumentaría el numero de dulces por minuto que genera la fabrica?
        • Si usted lo pensó bien, contrataría a 3 personas mas, teniendo así 4 personas en producción.
        • veamos ahora el ciclo
          • La primera persona recibe el dulce, mientras que las otras 3 no hacen nada.
          • La segunda persona le da forma dulce mientras que la primera recibe otro dulce, y las otras 2 no hacen nada.
          • La tercera persona sella el dulce mientras que la segunda le da forma al dulce y la ultima no hace nada.
          • la cuarta persona pone el dulce en la caja listo para la venta, mientras que la tercera sella otro dulce, la segunda le da forma a otro dulce y la primera recibe otro dulce.
          • ahora todas las personas están haciendo algo y cada vez que la primera persona recibe un dulce, sale un dulce listo en una caja.
        • ¿Que diferencia tiene esto con tener una persona(FSM) y tener 4 personas(Pipeline)?
        • ¿Que beneficios trae con respecto a la cantidad de dulces que puede hacer por minuto?
    • Ahora pensemos en hardware y no en personas, la misma FSM del punto 1...si lo noto bien y para aumentar la cantidad de operaciones se debe aumentar la frecuencia de reloj, lo que traer como consecuencia el aumento de potencia que consume un dispositivo electrónico, ¿no es asi?, osea que si yo necesito que mi FSM genere datos a alta velocidad necesitare aumentar frecuencia y por lo tanto la potencia que disipara la FPGA sera mayor...
    • Ahora imagine utilizar en vez de 4 estados, 4 stage (como las personas) y que cada stage es un registro que almacena lo que viene del anterior(persona) en la cadena de producción.
      • ¿Que beneficios trae esto en cuanto al consumo de potencia y la frecuencia necesaria?
      • ¿Alguna desventaja?.
  • Habiendo leído lo anterior usted ya tiene el concepto de pipeline y ahora necesita aplicarlo, para esto va hacer lo siguiente.
    • Diseñe una FSM como la del punto 1.
    • Lea la documentación siguiente desde la diapositiva #9 a la #15 y desarrolle cada circuito y problema que proponen en el.
    • Ahora en base a la documentación diseñe en configuración Pipeline un sistema que haga lo mismo que la FSM del primer punto.
    • Simule los dos circuitos el de FSM y Pipeline.
      • ¿Cuando se produce el primer resultado en la FSM?
      • ¿Cuando se produce el primer resultado en Pipeline?
      • Suponga una frecuencia de reloj de 500MHz para el sistema de FSM
        • ¿Cuantas operaciones es capaz de realizar por segundo?
      • Ahora compare con Pipeline.
        • ¿Que frecuencia de reloj necesitaría el circuito en Pipeline para producir la misma cantidad de operaciones?
  • Haga un cuadro comparativo entre FSM y Pipeline viendo ventajas y desventajas de cada configuración, llegue a sus propias conclusiones.
  • ¿Donde se aplica este concepto en la computación?

 
 

Written by Juan David

 

Introducción 

El proyecto FPGArduino consiste en transformar el uso que normalmente se le da a la FPGA y usarlo como un sistema de micro controladores programables usando Arduino. El sistema consiste en implementar un “SoftCORE” que ejecuta subgrupos de cualquier RISC-V o MIPS grupo de instrucciones.

 

¿Qué es softcore?

Es un microprocesador de núcleo que puede ser implementado en su totalidad mediante la síntesis de la lógica. Se puede implementar a través de diferentes dispositivos semiconductores  que contienen la lógica programable (por ejemplo, FPGA, CPLD), incluyendo tanto de gama alta y las variaciones de las materias primas.

En este caso la SoftCORE que usamos es el F32C

 ¿Cómo funciona?

Una vez configurado, la FPGA se comporta como sistema en un chip de 32 Bit, ejecutando un gestor de arranque que espera una compilación binaria para ser recibida en el puerto serial de la FPGA.

Compilar y subir el programa (sketch) es fácil para todas las plataformas. 

 

Procedimiento para usar un ARDUINO con la FPGA

Lo primero que se debe hacer es abrir el código en QUARTUS que se encuentra al final de la pagina llamado DE0_NANO_SOC_arduino.qar

El montaje para conectar la FPGA con el Conversor Serial USB consiste en conectar el Transmisor (Tx) de la FPGA con el Receptor (Rx) del Conversor Serial USB, además conectar el Receptor de la FPGA con el transmisor del Conversor Serial USB y también conectar las tierras de ambos dispositivos.

                       
                    

Como se observa en el código la FPGA maneja unas entradas que son la del reloj, unos switch, dos botones y un receptor, y tiene unas salidas que son los Led y el transmisor.

 

Luego de programar la FPGA se puede observar la conexión en RTL de forma detallada de cómo está construido.

                     

En las imágenes se observa que hay un conjunto de memorias y una etapa de pipeline.

 

Luego, se procede a conectar el Conversor Serial USB  y se abre el archivo Blinked.ino (se encuentra al final de la pagina).

Al abrir el archivo se abre un código en ARDUINO UNO, para  ejecutarlo primero debe asegurarse de que las siguientes configuraciones estén aplicadas:

  1. En la ventana de ARDUINO IDE abrimos el menú archivo y selecciona preferencias
 
 

Luego de haber seleccionado aparecerá una ventana como la siguiente y en esta debe buscar la opción que dice “Gestor de URLs adicionales de tarjetas” y en este espacio agregue la siguiente dirección: http://www.nxlab.fer.hr/fpgarduino/package_f32c_core_index.json

 
 
    2.    Ahora seleccione el menú herramientas y busque la opción que diga “placa”, luego seleccione “gestor de tarjetas”
 
 
 

Luego de seleccionar esta opción busque en la ventana a la que lo dirige la opción que dice “FPGArduino by FER+RIZ+RADIONA” e instalela.

 
 
 
    3.    Ahora para poder empezar a dar uso al programa que usara con la FPGA y el Conversor Serial USB debe seleccionar las siguientes opciones:

                a.    En el menú de herramientas se debe asegurar de que en la opción de placa este seleccionado “Terasic DEO NANO”

 
 
 
                b.     En el menú herramientas en la opción de CPU Architecture seleccionar “MIPS”
 
 
 
 
                    c.        En el menú herramientas en la opción de RAM size seleccionar “32 KB BRAM Internal”
 
 
 
                d.        En el menú herramientas en la opción “programador” seleccionar “ujprog (FPGArduino)”
 
 
 
                e.        En el menú de herramientas en la opción de “puerto” seleccionamos “COM4”
 
 

        Una vez hecha la conexión de la FPGA y el Conversor Serial USB (que se muestra en la figura)

 
            Al ejecutarlo lo que se muestra en la pantalla es lo siguiente
 
 
 
        En el siguiente vídeo podrá observar el funcionamiento en la FPGA
 

Vídeo de YouTube

 

Vídeo de YouTube

   
EJERCICIO - Cajita musical
 
Con el siguiente diseño, genere una secuencia musical
 
 
El procedimiento es el siguiente: 
 
  1. Descargue DE0_NANO_SOC_arduino_2.qar
  2. Abra el archivo en quartus, y abra el archivo Rom_Musical
    Lo que tiene que hacer en la Rom_Musical es añadir las notas que se utilizaran en la secuencia musical que desea hacer añadiendo el numero correspondiente a la frecuencia de cada nota. El numero lo halla con la siguiente formula: En este caso la frecuencia que maneja el reloj es de 50Mhz y la frecuencia de salida es la frecuencia de la nota. Lo único que debe cambiar de la Rom_musical es en el "case" donde dependiendo de la cantidad de notas que va a manejar la secuencia musical es la cantidad de temporales que va a utilizar.

    Una vez haya cambiado las frecuencias de las notas que utilizara, ya se tiene la Rom_Musical, el Div_Freq que se usa en el diseño, y solo falta diseñar el software que mandara la señal a la Rom_Musical mostrando cual es la secuencia musical que debe seguir y la Rom enviara la frecuencia al divisor para que luego se reproduzca en el altavoz.
  3. Ahora para diseñar el software descargue Secuencia_Musical, copielo y peguelo en el archivo "Blinked.ino" que se trabajo anteriormente.
  • Esta parte del código consiste en definir al nombre de las letras que definimos en la Rom_Musical y asignarles un valor. 
  • La siguiente parte del código consiste en un switch el cual se encarga de identificar la nota que sigue en la secuencia y envía una señal a la Rom_Musical para que está pueda enviar la nota al divisor.  En cada "case" se lee la nota dependiendo del valor que le asigno y usd debe formar el numero en binario con varias funciones digitalWrite siendo la 8 bit menos significativo y el 12 el mas significativo.
  • La parte final del código consiste en hacer la secuencia musical deseada en la que pondrá en orden todas las notas que ya asigno con sus respectivos tiempos de duración en el "delay" que se expresa en mili segundos.
.
En el siguiente video puede observar la secuencia musical desarrollada.
 

Vídeo de YouTube