Documentos de Académico
Documentos de Profesional
Documentos de Cultura
CuadernoLabMic PDF
CuadernoLabMic PDF
LABORATORIO DE
MICROELECTRÓNICA
Enero 2010
Laboratorio de Microelectrónica Digital
Tabla de contenidos
Práctica 1. Control del Display de 7 segmentos ..................................................................... 3
1. Objetivo propuesto......................................................................................................... 4
2. Tarjeta S3 de Digilent ..................................................................................................... 4
2.1. Display de 7 segmentos y cuatro dígitos ............................................................ 4
2.2. Señal de reloj ........................................................................................................... 8
2.3. Pulsadores y reset asíncrono................................................................................. 8
3. Realización de la práctica .............................................................................................. 8
3.1. Divisor de frecuencia ........................................................................................... 10
3.2. Contador de 0 a 9 .................................................................................................. 10
3.3. Registro de desplazamiento ................................................................................ 10
3.4. Decodificador de binario a 7 segmentos ........................................................... 11
3.5. Bloque de jerarquía superior ................................................................................... 11
Práctica 2. Control de un monitor VGA ................................................................................ 13
1. Objetivo propuesto....................................................................................................... 14
2. Conexión VGA en la Tarjeta S3 de Digilent.............................................................. 14
3. Monitor VGA en modo 640x480 ................................................................................. 15
4. Realización de la práctica ............................................................................................ 19
4.1. Contador ................................................................................................................ 20
4.2. Comparador .......................................................................................................... 20
4.3. Dibuja ..................................................................................................................... 21
4.4. Gen_color............................................................................................................... 22
4.5. Frec_pixel............................................................................................................... 23
4.6. Nivel de jerarquía superior ................................................................................. 24
Práctica 3. Transmisión por línea serie .................................................................................. 25
1. Objetivo propuesto....................................................................................................... 26
2. Enlace Serie.................................................................................................................... 26
3. Realización de la práctica ............................................................................................ 27
a. Diseño de la memoria ROM utilizando CORE Generator.................................. 28
b. Realización de la práctica ........................................................................................ 35
c. Configuración del Hyperterminal. ........................................................................ 40
Práctica 4. PRÁCTICA DE SISTEMAS EMBEBIDOS USANDO EDK .............................. 42
1. Introducción .................................................................................................................. 43
2. Primera Parte ................................................................................................................ 43
3. Segunda Parte ............................................................................................................... 60
1. Objetivo propuesto
2. Tarjeta S3 de Digilent
Para la realización de esta práctica utilizaremos la tarjeta S3 de Digilent. En este
apartado se explicará cómo funcionan los recursos de la tarjeta que utilizaremos en la
práctica1.
Básicamente, la tarjeta Digilent S3 consiste en una FPGA (Xilinx Spartan-3 con 200K
puertas equivalentes) cuyos puertos están unidos directamente a una serie de
periféricos. En la figura 1 Se muestra el diagrama de bloques básicos de la tarjeta.
1Toda la información de este apartado se ha extraída del documento Spartan-3 Starter Kit Borrad User
Guide disponible en la página de Digilent. Se anima al alumno a utilizar el documento original.
A modo de ejemplo, en la figura 2, se ilustra qué estímulos (en azul) habría que
proporcionar a los displays para conseguir que aparezca un 2 en el primer dígito:
Tabla 2. Conexiones entre la FPGA y los displays de 7 segmentos (activos a nivel bajo)
En este punto podríamos hacernos una pregunta. Si, como hemos comentado
anteriormente, los cuatro displays comparten los 8 bits que encienden cada uno de los
segmentos: ¿cómo podemos utilizar los cuatro displays simultáneamente? La respuesta
podemos encontrarla en la figura 3.
Para introducir el reset asíncrono a nuestro diseño utilizaremos uno de los cuatro
pulsadores de la parte inferior izquierda de la tarjeta. Debajo de los pulsadores
podemos encontrar una etiqueta con un nombre asignado al mismo (BTN3-0), y en la
tabla 3 de especifican los puertos de la FPGA conectados a los mismos. Al pulsar un
botón producimos un nivel lógico ‘1’ en el puerto correspondiente de la FPGA2.
3. Realización de la práctica
En la figura 4 se muestra el esquema general de la práctica. Podemos distinguir los
siguientes bloques a diseñar en VHDL:
2Normalmente, para utilizar los pulsadores en un proyecto será necesario implementar un filtro de glitches
en la FPGA. En la presenta práctica, que utilizaremos el pulsador como reset asíncrono, no es necesario.
DIV_FREC CONT_DIGITO
sat2 sat
clk reset clk reset
CONT_DIGITO
4
cuenta
enable
sat DECODIFICADOR
clk reset
4 binario siete_seg 7 7
A, B, C, D, E, F, G
CONT_DIGITO
cuenta 4
enable
sat
clk reset
‘1’ DP
CONT_DIGITO
cuenta 4
enable
sat
clk reset
REG_DESP 4 4
AN3-0
enable
Display_enable 4
clk reset
clk reset
Figura 4. Diseño a realizar en la práctica 1
3.2. Contador de 0 a 9
CONT_DIGITO
Descripción Contador síncrono con habilitación. Cuando está activa la habilitación se
contará de 0 a 9, volviendo a comenzar de nuevo por 0.
Entidad entity cont_digito is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
enable : in STD_LOGIC;
cuenta : out STD_LOGIC_VECTOR (3 downto 0);
sat : out STD_LOGIC);
end cont_digito;
Descripción de los puertos
clk Reloj
reset Reset asíncrono activo a nivel alto
enable Señal de habilitación activa a nivel alto. Si enable=’1’ el contador avanzará
uno en la cuenta en el flanco positivo de reloj.
cuenta Salida de cuatro bits. Comenzará en “0000” y terminará en “1001”, volviendo
a empezar de nuevo.
sat Si cuenta sea igual a “1001”, sat estará activada (activa a nivel alto).
REG_DESP
Descripción Registro de desplazamiento circular. El valor del registro al producirse un
reset asíncrono será “1110”, por tanto, la secuencia que se producirá será:
“1110” “1101” “1011” “0111” “1110”. (Ver figura 3). Sólo se
producirá un desplazamiento si módulo está habilitado.
El valor de registro se utilizará para controlar las señales de habilitación de
los displays: AN3:0.
Entidad entity reg_desp is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
enable : in STD_LOGIC;
display_enable : out STD_LOGIC_VECTOR (3 downto
0));
end reg_desp;
Descripción de los puertos
clk Reloj
reset Reset asíncrono activo a nivel alto
enable Habilitación activa a nivel alto
display_enable Valor del registro de desplazamiento. Con enable=’1’, se producirá un
desplazamiento cada flanco positivo de reloj:
• Todos los bits de desplazarán una posición a la izquierda (hacia el
BIT más significativo).
• El BIT menos significativo pasa a tener el valor del BIT más
significativo.
DECODIFICADOR
Descripción Bloque combinacional que produce el código correcto para la activación del
display de 7 segmentos a partir del número en binario.
El diseño de este bloque es trivial utilizando la tabla 1 y una sentencia case
Entidad entity decoficador is
Port (binario : in STD_LOGIC_VECTOR (3 downto 0);
siete_seg : out STD_LOGIC_VECTOR (6 downto 0));
end decoficador;
Descripción de los puertos
binario Código binario sin signo
siete_seg Código de 7 segmentos según la tabla 1. Se corresponde, de más a menos
significativo, con las entradas A,B,C,D,E,F y G del display.
Una vez diseñados y simulados los bloques anteriores pararemos a conectarlos tal
como se muestra en la figura 4.
CONTROL_DISPLAY
Descripción Realizará un contador de 4 dígitos en el display de 7 segmentos.
Bloque de mayor jerarquía que llama a todos los anteriores como
componentes.
Entidad entity control_display is
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
A : out STD_LOGIC;
B : out STD_LOGIC;
C : out STD_LOGIC;
D : out STD_LOGIC;
E : out STD_LOGIC;
F : out STD_LOGIC;
G : out STD_LOGIC;
DP : out STD_LOGIC;
AN : out STD_LOGIC_VECTOR (3 downto 0));
end control_display;
Descripción de los puertos
clk Reloj
reset Reset asíncrono activo a nivel alto
A,B,C,D,E,F,G Salidas activas a nivel bajo que encienden los leds correspondientes del
display (ver figura 2)
DP Salida activa a nivel bajo que enciende el punto del display. Siempre estará
desactivada.
AN Habilitación de los diferentes dígitos del display. Se formará una secuencia
como se indica en la figura 3.
1. Objetivo propuesto
R G B Color
0 0 0 Negro
0 0 1 Azul
0 1 0 Verde
0 1 1 Cian
1 0 0 Rojo
1 0 1 Magenta
1 1 0 Amarillo
1 1 1 Blanco
Tabla 4. Representación de 8 colores
En este apartado se explicará cómo deben generarse las señales HS, VS, R, G y B
para representar una imagen en un monitor en modo 60Hz, 640x480 y 8 colores. Es
decir, explicaremos brevemente el protocolo VGA.
Tres cañones de electrones (1) producen tres haces de electrones, uno por cada
color básico (rojo, azul y verde). Estos haces de electrones se focalizan (2), utilizando
una bobina, para conseguir que converjan en un punto de la pantalla. Posteriormente,
mediante un campo magnético generado por un par de bobinas (horizontal y vertical)
se direccionan al punto deseado de la pantalla. En la pantalla de visualización (5), los
rayos son separados (3) por una máscara e inciden en una capa fosforescente con zonas
receptivas para cada color (4).
4El tubo de rayos catódicos está quedando obsoleto, sin embargo los nuevos monitores LCD
mantienen la misma temporización en las señales de entrada VGA.
imagen en el monitor. El estándar VGA admite diferentes resoluciones, para las que
tendríamos que utilizar diferentes frecuencias en HS y VS5.
Todos los datos necesarios para generar correctamente las señales VGA se
proporcionan en la figura 9. En la tabla de la figura 9, el número de periodos (Clocks)
se refiere siempre a la frecuencia de píxel (25MHz) y no al reloj general del sistema
(50MHz).
4. Realización de la práctica
En la figura 10 se representa el diagrama de bloques del diseño a realizar en la
presente práctica. Podemos distinguir:
1. CONTADOR: Contador con reset síncrono y señal de habilitación. El
número de bits del contador será parametrizable utilizando GENERICS.
2. COMPARADOR: Comprador síncrono. Los umbrales de comparación serán
parametrizables mediante GENERICS.
3. FREC_PIXEL: Generador de la frecuencia de píxel. Dividirá la frecuencia de
reloj por dos para obtener una señal de 25MHz. Es un bloque tan sencillo
que puede ser diseñado directamente en el nivel de jerarquía superior.
4. GENCOLOR: Este bloque asegura que el cañón sólo esté activo el tiempo en
que está apuntando a la pantalla. El resto del tiempo, que denominamos en
el apartado anterior retrace time el color presentantazo debe ser negro (R=’0’,
G=’0’ y B=’0’). Es decir, el cañón debe estar apagado el tiempo de retorno. Se
recomienda que este bloque se diseñe directamente en el nivel de jerarquía
superior.
5. DIBUJA: Genera los colores (R, G y B) deseados en función de las
coordenadas de pantalla. Dependiendo cómo se diseñe este bloque se
representará una imagen diferente en pantalla.
4.1. Contador
CONTADOR
Descripción Contador síncrono de Nbit con habilitación y reset síncrono
Entidad entity contador is
Generic (Nbit: INTEGER := 8);
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
enable : in STD_LOGIC;
resets : in STD_LOGIC;
Q : out STD_LOGIC_VECTOR (Nbit-1 downto 0));
end contador;
Descripción de los puertos
clk Reloj
reset Reset asíncrono activo a nivel alto
enable Señal de habilitación activa a nivel alto. Si enable=’1’ el contador
avanzará uno en la cuenta en el flanco positivo de reloj.
resets Reset síncrono activo a nivel alto. Si resets=’1’ el contador pasará a
cero en el siguiente flanco positivo de reloj.
Q Salida de Nbit igual al valor de la cuenta.
4.2. Comparador
COMPARADOR
Descripción Comparado síncrono. Las salidas O1, O2 y O3 cambiarán en los
flancos positivos de reloj7.
Entidad entity comparador is
Generic (Nbit: integer :=8;
End_Of_Screen: integer :=10;
Start_Of_Pulse: integer :=20;
End_Of_Pulse: integer := 30;
End_Of_Line: integer := 40);
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
data : in STD_LOGIC_VECTOR (Nbit-1 downto 0);
O1 : out STD_LOGIC;
O2 : out STD_LOGIC;
O3 : out STD_LOGIC);
end comparador;
Descripción de los puertos
clk Reloj
reset Reset asíncrono activo a nivel alto
data Dato de entrada de Nbit
7 Se realiza el comparador síncrono para filtrar los posibles gitches. Es crítico que los pulsos de
sincronismo (HS y VS) estén limpios de glitches, pudiendo incluso dañar el monitor CRT.
4.3. Dibuja
DIBUJA
Descripción Bloque combinacional que generará, a partir de las coordenadas de
pantalla (eje_x y eje_y), las salidas de color necesarias (R,G y B) para
producir una imagen. Se deja la funcionalidad a la imaginación del
alumno8.
Entidad entity dibuja is
Port ( eje_x : in STD_LOGIC_VECTOR (9 downto 0);
eje_y : in STD_LOGIC_VECTOR (9 downto 0);
R : out STD_LOGIC;
G : out STD_LOGIC;
B : out STD_LOGIC);
end dibuja;
Descripción de los puertos
eje_x Coordenada horizontal del píxel. Sólo estarán dentro de la pantalla los
píxeles con coordenadas comprendidas entre 0 y 639.
eje_y Coordenada vertical del píxel. Sólo estarán dentro de la pantalla los
píxeles con coordenadas comprendidas entre 0 y 479.
R Salida de color rojo para el píxel
G Salida de color verde para el píxel
B Salida de color azul para el píxel
8 Se puede comenzar, por deferencia al profesor Jon Tombs, con el siguiente código:
process(eje_x, eje_y)
begin
G<='1'; B<='1'; R<='1';
if ((eje_x>279 and eje_x<359) or (eje_y>209 and eje_y<269)) then
R<='1';G<='0';B<='0';
end if;
end process;
4.4. Gen_color
DIBUJA
Descripción Bloque combinacional que asegura que el cañón de electrones esté
apagado cuando apunta fuera de la pantalla o está volviendo al
comienzo de otra línea.
Se puede diseñar:
a. Como un bloque independiente, con la entidad especificada a
continuación.
b. Como un process (con una sentencia if ) en el nivel de jerarquía
superior9.
Entidad entity gen_color is
Port ( blank_h : in STD_LOGIC;
(opción a) blank_v : in STD_LOGIC;
R_in : in STD_LOGIC;
G_in : in STD_LOGIC;
B_in : in STD_LOGIC;
R : out STD_LOGIC;
G : out STD_LOGIC;
B : out STD_LOGIC);
end gen_color;
Process gen_color:process(Blank_H, Blank_V, R_in, G_in, B_in)
begin
(opción b) if (Blank_H='1' or Blank_V='1') then
R<='0'; G<='0'; B<='0';
else
R<=R_in; G<=G_in; B<=B_in;
end if;
end process;
Descripción de los puertos
Blank_h Indicador de que está fuera de pantalla del comparador horizontal
Blank_v Indicador de que está fuera de pantalla del comparador vertical
R_in, G_in, Entradas de color procedentes del bloque DIBUJA
B_in
R, G, B Salidas de color del controlador VGA
9 Opción recomentada
4.5. Frec_pixel
FREC_PIXEL
Descripción Divide por dos la frecuencia de reloj, produciendo en su salida una
señal de 25MHz:
Se puede diseñar:
c. Como un bloque independiente, con la entidad especificada.
d. Como un process síncrono en el nivel de jerarquía superior10.
Entidad entity frec_pixel is
Port ( clk : in STD_LOGIC;
(opción a) reset : in STD_LOGIC;
clk_pixel : out STD_LOGIC);
end frec_pixel;
Proceso div_frec:process(clk,reset)
begin
(opción b) if (reset='1') then
clk_pixel<='0';
elsif (clk='1' and clk'event) then
clk_pixel<= not clk_pixel;
end if;
end process;
Descripción de los puertos
clk Reloj de entrada
reset Reset asíncrono activo a nivel alto
Clk_pixel Señal generada de 25MHz
10 Opción recomendada
VGA_DRIVER
Descripción Nivel de jearquía superior mostrado en la figura 10.
1. Objetivo propuesto
Los objetivos didácticos propuestos en la práctica son los siguientes:
2. Enlace Serie
Las principales características del enlace serie a diseñar serán:
3. Realización de la práctica
La práctica consta de tres apartados:
Si bien podemos arrancar CORE Generator de forma independiente, para esta práctica
nos servirá arrancarlo desde ISE. Seleccionamos Project -> New Source, y seleccionamos
la opción IP (Coregen & Architecture Wizard). Ver Figura 3.
12 Realmente muchas de las primitivas se pueden acceder directamente desde código VHDL,
pero su manejo es bastante más complicado (por ejemplo: describir unos registros de forma que
el sintetizador infiera una memoria empotrada)
13 Por esta razón es necesario especificar qué modelo de FPGA concreto estamos utilizando en
nuestro proyecto. Si se realiza a través del Coregen & Architecture Wizard, como se explica en
este apartado, se tomará por defecto la FPGA definida al crear el proyecto.
14 Ante la duda, se pueden consultar los datasheet de los cores, utilizando el botón View Data
Sheet que aparece en la esquina inferior izquierda de las ventanas del Wizard de CORE
Generator
Tras lo que nos aparece una pantalla de resumen de las opciones seleccionadas (Figura
5). Fijémonos en el ‘Source Name’ del fichero que nos va a generar. Si queremos
guardar únicamente los ficheros fuente de un proyecto que use cores, guardaremos,
además de los ficheros .vhd y .ucf, los ficheros .xco (Xilinx Core) correspondientes a los
cores generados y, en su caso, los ficheros de coeficientes .coe.
Figura 5. Resumen de las opciones seleccionadas en el asistente. Tras pulsar Finish se llamará a la
aplicación Coregen con estas opciones.
Figura 6. Primer menú del Core Generator para la generación de una memoria Block Memory. Se
especifica el tipo de memoria.
Figura 7. Segundo menú del Core Generator para la generación de Block Memory. Entre otras opciones
se configura el tamaño de la memoria.
Marcamos la opción Register Port A of Output Memory Primitives, esta opción nos
sintetizará un registro a la salida de la memoria, de forma que cuando se cambie el
valor del bus de direcciones (ADDRA), el nuevo dato (DOUTA) estará disponible al
siguiente ciclo de reloj (en este caso no tenemos señal Enable, la memoria siempre está
habilitada para lectura, ya que seleccionaremos la opción Always Enabled).
El último paso es utilizar un fichero .coe (Coefficients) para dar los valores iniciales a la
memoria (en este caso, tratándose de una ROM, es la única forma que tenemos de
introducir dichos valores en la misma). En la siguiente sección se detalla la sintaxis que
han de seguir los ficheros .coe. Marcamos también la opción Fill Remaining Memory
Locations, con el valor 0, para asegurarnos de que las posiciones de memoria que no
queden descritas por el fichero .coe se inicializen a cero.
Figura 8. Tercer menú del Core Generator para la generación de Block Memory. Se direcciona un
fichero .coe con los datos inciales de la memoria.
Figura 9. Cuarto menú del Core Generator para la generación de Block Memory.
Cuando pulsemos ‘Finish’ nos generará la IP. Es un proceso que tarda un poco, y por la
consola de ISE nos avisará cuando haya terminado, o si detecta algún error.
El fichero .coe es un fichero de texto plano, que contiene un vector con los valores que
se han de introducir en la memoria, y una variable ‘radix’ (que significa ‘base
numérica’ en inglés), que indica en qué base numérica debemos interpretar los datos15.
15Recordemos que, por ejemplo, los dígitos “10”, según se interpreten en binario, decimal,
hexadecimal u octal, significan “dos”, “diez”, “dieciséis” u “ocho” respectivamente
Recordamos que radix 16 sería hexadecimal (base 16), radix 8 octal, radix 10 decimal…
Para poder utilizar la memoria que acabamos de generar, necesitaremos una definición
de componente, igual que para los componentes que tengamos definidos en VHDL.
¿De dónde obtenemos esta definición?
♦ Manage Cores: Nos permite volver a configurar nuestro core, en caso de que nos
hayamos equivocado en algo o simplemente de que queramos cambiar su
configuración.
♦ Regenerate Core: Genera todos los ficheros intermedios del software de Xilinx a
partir del .xco original.
♦ View HDL functional model: Nos muestra el modelo HDL para simulación
funcional de la primitiva generada. Este modelo tiene una sección ENTITY que
podemos copiar para obtener la declaración de componente necesaria para
instanciarlo.
El manejo de la memoria es muy sencillo. Tiene dos entradas (ADDRA y CLK), y una
salida (DOUTA). Ya que no existe señal enable, y hemos puesto un registro a la salida
de la memoria, cuando cambie ADDRA obtendremos un dato nuevo en DOUTA al
siguiente flanco de reloj.
b. Realización de la práctica
El envío de los datos a través del puerto serie se va a controlar mediante una máquina
de estados16. Dicha máquina de estados pedirá el dato que necesita en cada momento a
través del puerto direcc y lo recibirá por el puerto data. Dichos puertos estarán
conectados a los puertos de la memoria en un nivel jerárquico superior.
Por otro lado, para implementar la comunicación síncrona de la Figura 1, Irá contando
el número de ciclos de reloj que hay que esperar para poder transmitir cada bit de
forma correcta respetando el protocolo. Para ello utilizará un contador interno que
deberá estar generado con sendas señales cont y p_cont del tipo std_logic_vector y el
ancho apropiado (dependerá de la tasa de transmisión). Para poder generar la
dirección correcta del dato a transmitir en cada momento también se usará un contador
16En el nivel de abstracción RTL que utiliza normalmente en VHDL una máquina de estado un
un bloque muy potente y versátil. Se recomienda la utilización de máquinas de estado en los
proyectos de los alumnos dentro de lo posible.
interno debidamente descrito con las señales dir y p_dir que se incrementará cada vez
que se transmite un byte completo.
Por último enviamos el bit de stop. La línea de transmisión se vuelve a poner a ‘1’
durante un tiempo de bit. Cuando se cumpla el tiempo de bit se resetea el contador
interno y se incrementa la dirección del siguiente dato a leer. Pasamos al estado inicio
para esperar a que el nuevo dato esté disponible.
FSM
Descripción Circuito de control del proceso de transmisión.
Entidad entity fsm is
Generic (ancho_bus_dir:integer:=4;
VAL_SAT_CONT:integer:=20000;
ANCHO_CONTADOR:integer:=20);
PRACTICA_3
MSG_ROM FSM
DATA[7:0]
MEMORIA MÁQUINA DE TX
ROM ESTADOS
DIRECC[3:0]
CLK
RST
BUTTON
Debe aparecer conectar usando COM1. Aquí presionar el botón ·”Configurar”. Aquí
debe aparecer la configuración de la velocidad del puerto serie:
La Figura 14 muestra la configuración del puerto serie para realizar esta práctica. Una
vez configurado la información que se escriba desde teclado en la consola del
hyperterminal se transfiere automáticamente al puerto serie, y la información recibida
será escrita en la consola. Los caracteres escritos no aparecen en la configuración por
defecto de la consola.
1. Introducción
Esta práctica pretende introducir al alumno en el diseño de sistemas embebidos
utilizando el sistema de desarrollo EDK del fabricante Xilinx.
Para ello se va a utilizar como plataforma hardware la tarjeta XS3 de Digilent que
incluye una FPGA Spartan 3 de Xilinx de 200.000 puertas equivalentes. Esta capacidad
es más que suficiente para implementar tanto un microprocesador softcore como otros
periféricos que requiera el usuario.
En este caso se va a utilizar el sistema EDK (Embeded Design Kit) para implementar el
microprocesador MicroBlaze de Xilinx. Se trata de un microprocesador de 32 bits que
se puede implementar en muchas familias de FPGAs de Xilinx. La descripción del
microprocesador incluida en el EDK es del tipo post síntesis pero previa a la
implementación de forma que no es posible acceder al código VHDL que describe el
comportamiento del microprocesador aunque esto no es necesario para poder
utilizarlo.
Aunque existen diferentes formas de diseñar un sistema embebido con el software de
Xilinx vamos a utilizar las dos más habituales.
En la primera parte de la práctica se va a implementar únicamente el MicroBlaze en la
FPGA por lo que solamente será necesario utilizar el EDK. En esta parte se le añadirán
al micro periféricos hardware de librería para poder utilizar todos los componentes de
la placa. En concreto, se usará el puerto RS232 como entrada y salida estándar del
programa que se esté ejecutando en el MicroBlaze. Este caso consiste en realizar el
¡Hola Mundo! en la FPGA.
En la segunda parte se integrará el MicroBlaze como un componente más en la
estructura jerárquica de un proyecto ISE. En este caso estará implementado en la FPGA
junto con otros periféricos VHDL definidos por el usuario. En esta parte de la práctica
se pretende que el alumno realice un sistema embebido más completo y que sirva de
ejemplo de un sistema real. Partiendo de este sistema básico debería ser posible
fácilmente añadir más periféricos hasta conseguir un sistema que se adapte a los
requerimientos de una aplicación concreta.
2. Primera Parte
Comenzaremos arrancando la aplicación principal del EDK, el Xilinx Platform Studio.
Lo podemos encontrar en el menú del EDK dentro del software de Xilinx.
A continuación nos aparece la ventana de la Figura 1 donde el software nos ofrece tres
alternativas:
• Utilizar el asistente para crear un nuevo proyecto desde cero.
18Es posible almacenar la configuración de un diseño en un archivo con extensión .bsb. Esto
permite configurar rápidamente un diseño partiendo de la configuración de otro previo.
Figura 3 Ventana de selección para crear un nuevo diseño o cargar la configuración de uno
previo.
A continuación nos aparece una nueva ventana en la que poder seleccionar si vamos a
crear un proyecto para una placa conocida19 o para una placa a medida. Configurar las
distintas opciones tal y como aparece detallado en la Figura XXX. En el campo Board
Description puede apreciarse cómo el software ha identificado la placa y nos describe
todos los componentes que incluye.
19 Muchos fabricantes de placas de desarrollo crean los archivos donde se describen las
restricciones de pineado de la FPGA que incluyen y la de los periféricos que incorpora la placa.
Este archivo puede añadirse al EDK para que el Wizard nos configure automáticamente el
proyecto adaptándose a nuestra placa en concreto.
Figura 4 Selección de una tarjeta conocida cuyas características están incluidas en el EDK.
20 Si las aplicaciones de usuario necesitaran más de 64KB, entonces es posible utilizar memorias
externas como memoria del sistema aunque siempre es necesario implementar una memoria
local mínima de 8KB dentro de la FPGA. Si se desea utilizar memoria RAM externa como
memoria principal entonces es posible almacenar en la memoria local de la FPGA un programa
(llamado bootloader) que lee desde una memoria externa no volátil el contenido inicial de la
memoria y lo copia a la memoria RAM externa antes de que empiece ningún procesado.
Después de copiar todo el programa a la RAM salta a la primera instrucción de dicho programa
y comienza la ejecución normal del mismo.
Figura 6 Lista de periféricos hardware de librería incluidos en el diseño por defecto para
poder controlar el hardware que incorpora la placa XS3 de Digilent.
A continuación nos pide que le indiquemos dónde van a ir ubicadas las distintas partes
de cada uno de los programas que nos va a generar automáticamente. Por un lado está
la parte dedicada a las instrucciones que componen el programa, en segundo lugar los
datos y variables, y en tercer lugar la pila (Stack) y la reserva dinámica de memoria
(Heap). Por defecto y para el programa de test de memoria está seleccionada la
memoria interna de la FPGA para las tres partes. Dejamos activa dicha opción ya que
la memoria interna es suficiente para almacenar las tres partes del programa.
Figura 12 El wizard nos propone por defecto ubicar todas las partes del programa de test de
periféricos en la RAM externa.
Por último el software nos muestra un resumen con el rango de direcciones asignado a
cada uno de los periféricos detallando el tipo de bus al que está conectado cada uno.
Hacemos Lclik en generate y nos aparece un resumen de todos los archivos generados y
la opción activada de generar un archivo .bsb con todas las selecciones realizadas en el
Wizard para que pueda ser utilizada en proyectos futuros.
Figura 13 Resumen del rango de direcciones asignado por defecto a todos los periféricos
incluidos en el proyecto.
Pulsamos Finish para terminar con el wizard y nos aparece la ventana normal de
trabajo del EDK que debe tener un aspecto similar al que se ilustra en la Figura 15.
Con las distintas pestañas podemos ver todos los archivos que contiene el proyecto
(Figura 15), el conjunto de aplicaciones que tengamos definidas en ese momento
(Figura 16) o la lista de periféricos de librería disponibles que podemos añadir a
nuestro proyecto (Figura 17).
Figura 16 Aplicaciones generadas por el wizard. Por defecto está activa la del test de
memoria.
Figura 18 Detalle del código fuente del programa que testa la memoria generado
asmáticamente por el EDK.
Una vez llegado este punto podemos hacer varias cosas. Podemos implementar el
hardware que hemos configurado en el menú Hardware con la opción Generate Netlist.
Luego podremos rellenar los bloques internos de memoria de la FPGA con el programa
compilado que queramos. También podemos compilar el código fuente de las
aplicaciones que nos ha generado automáticamente el wizard. Esto puede hacerse con
la opción Build All users applications del menú Software (Figura 19) ó haciendo Rclick en
cada aplicación y luego seleccionando Build Project (Figura 20). También podemos
hacerlo todo directamente seleccionando la opción Update Bitstream del menú Device
Configuration como aparece detallado en la Figura 21. Esto realizará primero la
implementación para esa FPGA de todo el hardware incluyendo el MicroBlaze y todos
los periféricos que hayamos incluido. Luego realizará la compilación del código que se
Figura 19 Opción para compilar todas las aplicaciones de usuario del menú Software.
Figura 20 Opción para compilar una aplicación concreta haciendo Rclick sobre ella.
Figura 21 Opción que actualiza el bitstream con el ejecutable de la aplicación que se haya
especificado para la memoria interna de la FPGA.
FFFFFFFFFFFFFFFFFFFffff
Vamos a crear ahora un nuevo programa para nuestro proyecto. Para crear una nueva
aplicación software seleccionamos la opción Add Software Application Project del menú
Software (Figura 23).
Después de elegir el nombre del programa podemos añadir archivos con el código
fuente a ejecutar (ya sea un archivo nuevo o creado externamente) haciendo Rclik sobre
la sección Sources de nuestro nuevo programa (Figura 25).
Elegimos el nombre del nuevo archivo fuente y una vez creado lo abrimos para escribir
el código a ejecutar. Para crear el “Hola Mundo” basta con el siguiente código.
#include <stdio.h>
Main{
}
Una vez compilado el código podemos actualizar el bitstream (archivo .bit) con dicho
código compilado. Usamos la opción descrita en la Figura 21.
Una vez programada la FPGA debemos observar en el hyperterminal un texto similar
al que aparecen en la XXXXXXXXXXXX. De nuevo el puerto serie del hyperterminal
debe estar configurado de la misma forma que el del periférico hardware (Figura 6).
3. Segunda Parte
En esta segunda parte de la práctica vamos a implementar el MicroBlaze junto con un
contador desde el ISE. Se va a utilizar el hyperterminal de Windows para modificar la
velocidad del contador (el paso de cada cuenta). Para ello vamos a conectar el puerto
RS232 de la placa al MicroBlaze y éste al módulo top descrito en VHDL. El MicroBlaze
va a controlar el puerto serie y mediante un protocolo muy sencillo va a ir
incrementando o decrementando un valor que va a poner en un puerto de salida. Este
puerto de salida se va a leer desde el módulo top y su contenido se va a interpretar
como el paso del contador.
Este ejemplo tan sencillo permite ilustrar cómo es posible integrar un microprocesador
en un desarrollo hardware y utilizarlo
Vamos a iniciar un nuevo proyecto en el ISE como siempre y a la hora de añadir
componentes vamos a elegir un VHDL Module llamado top.vhd. Será el top que
contendrá al microprocesador. Los puertos que debe contener el top aparecen
detallados en la .
Añadimos primero
Añadimos ahora un nuevo archivo fuente del tipo Implementation Constraints File
llamado top.ucf. Será el archivo que contenga las restricciones de pineado.
Una vez configurado el micro pulsamos Generate y el software nos informa de que en el
ISE se podrá consultar un archivo que contiene las restricciones de pines para la placa
seleccionada.
Pulsamos Finish para que el EDK termine de generar el hardware. Creamos una nueva
aplicación software que incluya el código que queremos ejecutar. El código fuente del
programa a ejecutar aparece detallado a continuación.
XXXXXXXXXXXXXXXX Incluir código XXXXXXXXXXXXXXXXXx
#define GPIO_DIR_BASE
#define G_DATA_OUT_R 2
main(int i){
char aux;
int cuenta=0;
unsigned int *ip=0;
while (1){
aux=getc();
if (aux==”+”){
cuenta=2*cuenta;
if (cuenta>=10000) cuenta=10000;
}
else if (aux==”-“){
if (cuenta<=100) cuenta=100;
}
ip[GPIO_DIR_BASE + G_DATA_OUT_R]=cuenta;
}
Return 0;
}
Le damos a salvar proyecto y ya podemos cerrar el EDK para continuar desde el ISE.
De nuevo en el ISE vamos a crear un archivo VHDL Module llamado top que va a
incluir el MicroBlaze como componente. Creamos también un archivo de restricciones
Implementation Constraints File asociado al top. El top va a contener los siguientes
puertos:
XXXXXXXXXXXXXx
Para poder instanciar el MicroBlaze como componente podemos usar una plantilla que
nos genera automáticamente el ISE donde se incluyen todos los periféricos que le
hayamos añadido al micro en el EDK ().
XXXXXXXXXXX Figura de vista del Template XXXXXXXXXXXXXXXx
De esta forma podemos copiar y pegar directamente (tal y como nos indican) el código
de la plantilla en el top para declarar e instanciar el MicroBlaze.
Únicamente nos falta completar el código del módulo top y del ucf. El pineado exacto
de los periféricos que incluye la placa puede encontrarse en la hoja de datos (data
sheet) de la misma aunque también puede consultarse en el archivo ucf generado por
el asistente en el proyecto de la primera parte de la práctica. A continuación aparecen
unos posibles códigos que permiten generar el diseño que se desea conseguir.
XXXXXXXXXXXXX Códigos XXXXXXXXXXXXXXXx
Únicamente nos falta completar la implementación y programar la FPGA. Una vez
hecho esto debemos observar en el hyperterminal un comportamiento parecido al que
aparece reflejado en la ().