Xburst-FPGA communication example/es

From Qi-Hardware
Jump to: navigation, search

NOTE, SAKC has been renamed SIE. So, some places SIE is referred to as SAKC.


Contents

[edit] Ejemplo de comunicación entre Xburst y la FPGA

En este ejemplo implementaremos una memoria RAM en la FPGA, con el fín de probar la correcta conexión entre los buses de: datos (D0-D7), dirección (A0-A12) y control (WE0_N, CS2_N, RDWR_N). Este código puede ser utilizado como base para futuras implementaciones y hace parte de las rutinas de prueba de la plataforma en la fase de producción.

[edit] Estructura del Código

Debido a que este ejemplo utiliza la FPGA, es necesario separar el código fuente en dos partes, la primera (logic) describe la arquitectura que se implementará en un PLD, las tareas definidas en este código reciben el nombre de componente hardware . La segunda src implementa el código de la aplicacación que se ejecutará en espacio de usuario y recibe el nombre de componente software.

[edit] Componente Hardware

Aquí puede descargar el código fuente del componente Hardware, en este directorio tenemos 3 archivos:

  • Makefile Script que crea automáticamente el archivo de configuración sram_bus.bit. Para su utilización, es necesario contar con las herramientas de diseño de Xilinx, las que se pueden descargar de forma gratuita aquí. Se debe incluir en la variable PATH el directorio Xilinx/bin/lin/.
  • sram_bus.ucf Archivo de restricciones en el que se hace la asignación de pines.
  • sram_bus.v Código en verilog que implementa la funcionalidad de la siguiente figura.
Diagrama de bloques de la implementación de una RAM en una FPGA.

En la figura anterior se muestra el diagrama de bloques de la implementación de una memoria RAM en la FPGA de SIE (Esta arquitectura es explicada aca). En este ejemplo el periférico está conformado por 4 bloques de memoria RAMB16_Sn (memoria RAM de 2 bits). Adicionalmente, en esta figura se muestra el código en verilog para cada uno de los bloques.

[edit] Componente Software

En esta dirección pueden obtener el código fuente de dos ejemplos, uno que implementa un blink en un GPIO y otro que se comunica con la memoria RAM implementada en la FPGA.

[edit] GPIO TEST

Este ejemplo cambia el estado lógico del GPIO C17 (conectado al led D6) periódicamente y está compuesto por los archivos: jz_test_gpio.c, jz47xx_gpio.h, jz47xx_mmap.h, jz47xx_mmap.c

La función main está definida en el archivo jz_test_gpio.c


  1. 	#define TEST_PORT JZ_GPIO_PORT_C
  2. 	#define TEST_PIN  17
  3.  
  4. 	int
  5. 	main ()
  6. 	{
  7. 	  JZ_PIO *pio = jz_gpio_map (TEST_PORT);
  8.  
  9. 	  if (!pio)
  10. 	    return -1;
  11.  
  12. 	  jz_gpio_as_output (pio, TEST_PIN);
  13.  
  14. 	  int tg = 1;
  15.  
  16. 	  while (1)
  17. 	    {
  18. 	      jz_gpio_out (pio, TEST_PIN, tg);
  19. 	      printf ("[%d]", jz_gpio_get_pin (pio, TEST_PIN));
  20. 	      fflush (stdout);
  21. 	      usleep (500 * 1000);
  22. 	      tg = !tg;
  23. 	    }
  24. 	  return 0;
  25. 	}

Es necesario acceder a los registros del procesador para cambiar la configuración del pin GPC17, el cual debe ser un pin de salida, para esto, es necesario realizar un mapeo de la dirección física del registro de configuración a una dirección de memoria virtual que pueda ser utilizado por nuestra aplicación.

La función jz_gpio_map (definida en jz47xx_gpio.c y listada a continuación) mapea inicialmente la dirección física base de los registros del controlador de GPIOs (JZ_GPIO_BASE) y le asigna esta dirección virtual al puntero pio de tipo JZ_PIO(La estructura JZ_PIO contiene todos los registros que controlan el GPIO.

  1. JZ_PIO * jz_gpio_map (int port)
  2. {
  3.   JZ_PIO *pio;
  4.  
  5.   pio = (JZ_PIO *) jz_mmap (JZ_GPIO_BASE);
  6.   pio = (JZ_PIO *) ((unsigned int) pio + port * 0x100);
  7.  
  8.   return pio;
  9. }


Cada grupo de registros está separado por 0x100 bytes (0x10010000, 0x10010100, 0x10010200, 0x10010300), la línea 6 hace que el puntero de la memoria virtual se desplace al inicio del banco donde se encuentra el GPIO que será configurado (puerto C en este caso).

En la línea 12 de la función main se hace un llamado a la función jz_gpio_as_output, la que, como su nombre lo indica configura el pin TEST_PIN (GPC17) como salida, esta función está definida en jz47xx_gpio.c

jz_gpio_as_output (JZ_PIO * pio, unsigned int o)
{
  pio->PXFUNC = (1 << (o));
  pio->PXSELC = (1 << (o));
  pio->PXDIRS = (1 << (o));
}

Colocando un '1' lógico en el bit correspondiente al pin en el registro PXFUNC se fija el registro PXFUN en 0 (Asignando un '1' al bit correspondiente al pin en el reistro PXFUNS se fija PXFUN en '1'), con lo que el pin puede ser usado como GPIO o como entrada de interrupción. Cuando PXSEL de este pin es igual a cero el pin se utilizará como GPIO, y cuando PXDIR es igual a 1 (PXDIRS = 1) el pin se es un GPIO de salida.

La función jz_gpio_out fija el pin TEST_PIN al valor tg, esta función esta definida en jz47xx_gpio.c

void
jz_gpio_out (JZ_PIO * pio, unsigned int o, unsigned int val)
{
  if (val == 0)
    pio->PXDATC = (1 << (o));
  else
    pio->PXDATS = (1 << (o));
}

[edit] SRAM

Este ejemplo hace un mapeo de la dirección asociada al CS2 y realiza la escritura y lectura de 256 datos, si los datos leídos son iguales a los que se escribieron la interfaz funciona correctamente. Para poder utilizar este periférico implementado en la FPGA es necesario:

  1. int main ()
  2. {
  3.   int i,j;
  4.   JZ_PIO *pio;
  5.   JZ_REG *virt_addr;
  6.  
  7.   pio = jz_gpio_map (CS2_PORT);
  8.   jz_gpio_as_func (pio, CS2_PIN, 0);
  9.  
  10.   virt_addr = (JZ_REG *) jz_mmap (0x13010000) + 0x18;
  11.  
  12.   if (*virt_addr != 0xFFF7700)
  13.     {                          // 0 WS, 8 bits
  14.       *virt_addr = 0xFFF7700;
  15.       printf ("Configuring CS2 8 bits\n");
  16.     }
  17.   else
  18.     printf ("CS3, already configured\n");
  19.  
  20.   virt_addr = (JZ_REG *) jz_mmap (0x15000000);
  21.  
  22.   for (i = 0; i < 255; i++)
  23.     {
  24.       virt_addr[i] = i; 
  25.     }
  26.  
  27.   printf ("Reading Memory..\n");
  28.   for (i = 0; i < 255; i++)
  29.     {
  30.       j = virt_addr[i];
  31.       printf ("%X = %X\n", i, j);
  32.     }
  33.  
  34.   return 0;
  35. }
  • Configurar el pin GPB26 para que sea utilizado como CS2 -- Líneas 7 y 8.
  • Configurar el Controlador de Memoria Externa (EMC). Esto se hace escribiendo el valor 0xFFF7700 al registro SMCR2 (dirección 0x13010018), con lo que se configura el banco 2 del EMC para que trabaje como una interfaz de memoria estática de 8 bits en modo normal, 31 ciclos de tiempo de espera, 7 ciclos de tiempo de setup y 7 ciclos para hold -- Líneas 10 a 18
Descripción del registro SMCR2
  • Hacer un mapeo de la dirección asociada a CS2 (Entre 0x14000000 y 0x17FFFFFF) --Línea 20.
  • En la línea 24 se esscriben 256 posiciones de memoria.
  • En las líneas 30 y 31 se leen y se imprimen estas posiciones.
Personal tools
Namespaces
Variants
Actions
Navigation
interactive
Toolbox
Print/export