DISEÑO EN VHDL PARA FPGAs - BUCOMSEC

Anuncio
DISEÑO EN VHDL PARA
FPGAs
Raúl Mateos Gil.
Ignacio Fernández Lorenzo.
Pedro Martín Sánchez.
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
ÍNDICE
1. FLUJO DE DISEÑO VHDL SOBRE FPGAs. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.1. INTRODUCCIÓN. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2. STANDARD VITAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.3. CREACIÓN DEL MODELO. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.4. SÍNTESIS DEL MODELO. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.5. IMPLEMENTACIÓN DEL MODELO. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
1
1
2
3
4
2. DESCRIPCIÓN DEL DISEÑO A REALIZAR. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1. CREACIÓN DEL MÓDULO LOGIBLOX. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2. MÓDULO BCD2SEG. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3. MÓDULO CRONO.VHD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3.1. Declaración de librerías. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.3.2. Definición de la entidad. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.3.3. Parte declarativa de la arquitectura. . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.3.4. Instantación de componentes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.3.5. Contador de décadas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.3.6. Registros de lapso. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.3.7. Máquina de estados. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.4. BANCO DE PRUEBAS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.5. FICHERO CONFBEHAVIORAL.VHD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3. SIMULACIÓN FUNCIONAL DEL DISEÑO. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.1. INTRODUCCIÓN. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.1.1. Librerías. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2. MANEJO DEL SIMULADOR. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2.1. Creación del proyecto. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2.2. Creación de nuevas librerías y mapeado de las librerías a reutilizar .
3.2.3. Compilación del código fuente. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2.4. Carga de la unidad de diseño a simular . . . . . . . . . . . . . . . . . . . . . . .
3.2.5. Selección de puntos de prueba. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2.6. Avance y detención de la simulación. . . . . . . . . . . . . . . . . . . . . . . . . .
3.2.7. Introducción de estímulos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2.8. Análisis de resultados. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2.9. Finalizar una sesión de simulación. . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3. PUNTOS DE RUPTURA. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.4. METODOLOGÍA DE TRABAJO. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
20
21
23
24
24
25
26
27
31
33
35
36
36
38
4. SÍNTESIS DEL DISEÑO. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.1. OPERACIÓN INTERNA DEL SINTETIZADOR. . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.1. Generadores de módulos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2. MANEJO DEL SINTETIZADOR. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.1. Inicialización del sintetizador. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.2. Selección de la tecnología destino. . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.3. Selección del método de codificación de las máquinas de estados. . .
4.2.4. Lectura de ficheros del diseño. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.5. Selección del diseño actual. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.6. Configuración de opciones de optimización. . . . . . . . . . . . . . . . . . . .
4.2.7. Optimización del diseño. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.8. Almacenamiento del diseño. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
39
42
43
45
45
45
47
47
48
51
52
-i-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
4.2.9. Exportación de la lista de conexiones. . . . . . . . . . . . . . . . . . . . . . . . . . 52
4.2.10. Uso de ficheros de scripts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
4.3. ANÁLISIS DE RESULTADOS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
5. IMPLEMENTACIÓN DEL DISEÑO. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
5.1. USO DE FICHEROS DE RESTRICCIONES. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
6. SIMULACIÓN A NIVEL DE PUERTAS. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
-ii-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
1. FLUJO DE DISEÑO VHDL SOBRE FPGAs.
1.1. INTRODUCCIÓN.
La figura 1.1 muestra el diagrama de flujo para el diseño en VHDL de sistemas implementados sobre
FPGAs de Xilinx. El proceso de diseño se divide en tres fases: creación del modelo, síntesis e
implementación. Al finalizar cada una de las fases es preciso comprobar la validez del diseño
mediante simulación, utilizandose distintos tipos de simulación en cada una de ellas:
!
Simulación funcional RTL para validar el modelo VHDL creado.
!
Simulación funcional post-síntesis a nivel de puertas para validar el modelo sintetizado.
!
Simulación temporal post-implementación para validar la implementación del modelo
implementado.
El diseño contiene componentes
LogiBLOX instanciados
Editor VHDL
Plantillas de
instantación
Modelo de
simulación del
componente
LogiBLOX.
VHDL
VHI
SIMULADOR
VHDL
Simulación RTL.
Restricciones
de diseño.
Fichero de lista de
conexiones de salida.
SINTETIZADOR
VHDL
XNF
EDIF
LIsta de conexiones
en formato nativo.
UNISIM
VITAL
.NGC
VHDL
Simulación post-sintesis
pre-implementación.
LogiBLOX
SIMULACIÓN FUNCIONAL.
Fichero fuente
RTL VHDL
LogiBLOX
Fichero de
restricciones
de usuario.
Banco de
pruebas VHDL
HERRAMIENTAS DE
IMPLEMENTACIÓN
Ficheros de
informes
BIT
JEDEC
Fichero de programación
del dispositivo.
EDIF
SDF
VHDL
Ficheros de lista de conexiones
para simulación post-implementación
SIMPRIM
VITAL
SIMULACIÓN TEMPORAL.
Comportamiento
Figura 1: Flujo de diseño en VHDL para FPGAs de Xilinx.
El banco de pruebas creado para validar el modelo es único, siendo utilizado en todos los tipos de
simulación mencionados. Las dos últimas son simulaciones a nivel de puertas, ya que el diseño esta
expresado como una descripción estructural VHDL en términos de las celdas de la tecnología destino
para la que se va implementar.
1.2. STANDARD VITAL
Para poder realizar simulaciones temporales mediante un simulador VHDL se necesitan modelos
VHDL con información temporal de los elementos de la librería de la tecnología destino. El standard
VITAL (VHDL Initiative Towards ASIC Library) define las técnicas de generación de estos modelos de
-1-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
simulación mediante dos paquetes denominados VITAL_Timing y VITAL_Primitives. En este caso el
fabricante del ASIC debe proporcionar las librerías VITAL en la que estén descritas las celdas básicas
de la tecnología destino. La retroanotación de los retardos internos (tanto debidos a elementos
activos como a interconexiones) se realiza mediante ficheros SDF. Se pueden utilizar distintos
ficheros SDF a lo largo de las distintas etapas del proceso de diseño. Alguno de estos ficheros pueden
contener datos temporales pre-layout. Otros pueden contener restricciones de caminos críticos de
señales o información temporal post-layout.
Xilinx proporciona varias librerías VITAL para realizar simulaciones VHDL de diseños para FPGAs.
La librería UNISIM es una librería VITAL en la que se han desactivado las comprobaciones de
violaciones de temporización para realizar simulaciones funcionales con retardos unitarios. Al
sintetizar una descripción VHDL RTL para FPGAs de Xilinx las celdas de la tecnología destino que
aparecen en el fichero de salida corresponden a las celdas primitivas definidas en la biblioteca
unificada de Xilinx de las herramientas de captura de esquemas. La librería UNISIM contiene los
modelos VITAL de estas celdas básicas. Además se incluyen los modelos de otras celdas primitivas
que se pueden instanciar como componentes para aprovechar los recursos de la FPGA (por ejemplo,
el oscilador integrado OSC4 de la familia Spartan XL). Sin embargo UNISIM no dispone de modelos
para los componentes de tipo macro que aparecían en la librería unificada de las herramientas de
captura de esquemas. Esto impide realizar simulaciones RTL de diseños en los que se instancien
estas macros como componentes descritos por una lista de conexiones.
La librería XILINXCORELIB se utiliza para realizar simulaciones funcionales de diseños en los que
aparezcan componentes creado con la herramienta COREGEN. Finalmente la librería SIMPRIMS es
una librería VITAL para realizar simulaciones temporales a nivel de puertas. En esta librería se
almacenan los modelos de los componentes físicos que aparecen en el interior de una FPGA (LUTs,
biestables, etc). En este caso las comprobaciones de violaciones de temporización si están activadas.
La retroanotación de los retardos de los elementos activos (LUTs, biestables, buffers triestado, etc)
y de las interconexiones se realizan mediante un fichero SDF.A continuación se describirán en detalle
cada una de las fases del flujo de diseño así como las peculiaridades de la simulación utilizada para
la verificación de los resultados obtenidos.
1.3. CREACIÓN DEL MODELO.
El primer paso consiste en crear un modelo RTL del diseño que se pretende realizar. Para ello se
puede utilizar un editor de texto. El diseño puede contener:
!
Código VHDL genérico que describe lógica independiente de la tecnología donde se va a
implementar.
!
Componentes instanciados propios de la arquitectura del dispositivo en el que se va a
implementar. Un ejemplo de esto sería el uso del oscilador interno OSC4 de la familia
Spartan XL.
!
Componentes instanciados creados mediante COREGEN. Un ejemplo de esto sería el uso
de una memoria, un contador, etc creados mediante COREGEN.
Para el caso de utilización de componentes propios de la arquitectura del dispositivo el sintetizador
obtiene la descripción de dichos componentes de la biblioteca de celdas de la tecnología destino.
El formato de esta biblioteca dependerá de la herramienta de síntesis utilizada. En algunos casos
dicha biblioteca está integrada en la propia herramienta como una biblioteca más del sistema. Tal
es el caso del sintetizador “Leonardo Spectrum”. En otros casos la biblioteca aparece como conjunto
-2-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
de macros expresadas como listas de conexiones en formato XNF. Estos componentes aparecen
como módulos sin definición (cajas negras) en la descripción VHDL donde se instancian.
Si el diseño utiliza componentes COREGEN es preciso crearlos previamente mediante esta
herramienta. Al crear un componente COREGEN, se genera un fichero VHDL con una definición
abstracta del funcionamiento del mismo, que puede ser simulado y sintetizado. También se crea un
archivo de lista de conexiones para la implementación (.EDN). Será posteriormente durante la
implementación del diseño cuando las herramientas de implementación de Xilinx enlacen esta lista
de conexiones con la del diseño principal obtenida tras el proceso de síntesis.
Si bien el componente obtenido es un módulo sin definición aparente, COREGEN puede crear un
fichero VHDL de comportamiento para permitir la verificación del diseño completo mediante
simulación. Este fichero tiene extensión .VHD. También puede generar un fichero de declaración
del componente en VHDL con extensión VHO. Este fichero contiene una plantilla con las
construcciones necesarias para la declaración e instanciación del componente COREGEN en el
fichero VHDL donde se vaya a utilizar, lo que facilita el desarrollo de diseños con este tipo de
componentes.
Antes de proceder a la síntesis del diseño es preciso verificar el modelo creado mediante simulación.
Se trata de una simulación funcional en la que el diseño está descrito con construcciones RTL de alto
nivel. Si el diseño utiliza componentes propios de la tecnología destino es preciso utilizar la librería
de simulación XILINXCORELIB.
Estos componentes COREGEN no son sintetizables por lo que su declaración se intercala entre
directivas de inhabilitación/ habilitación del proceso de síntesis. Estas directivas aparecen como
“comentarios sintéticos” en el fichero fuente. La sintaxis de tales directivas debe ser aceptada por la
herramienta de síntesis en cuestión. Estas directivas son
-- synopsys translate_off
.........
-- synopsys translate_on
las cuales son aceptadas por Leonardo Spectrun.
1.4. SÍNTESIS DEL MODELO.
Una vez validado el modelo creado se procede a la síntesis de éste. El resultado de la síntesis es una
lista de conexiones en formato EDIF o XNF. Si en el proceso de síntesis se fijan restricciones de
diseño (topológicas o temporales) que afectan al proceso de implementación éstas se exportan en
la propia lista de conexiones.
Para comprobar los resultados de la síntesis es preciso realizar una simulación funcional (retardos
unitarios) a nivel de puertas (expresadas como componentes de UNISIM). Para ello se debe disponer
de una herramienta capaz de generar una descripción estructural VHDL equivalente a las listas de
conexiones mencionadas. El procedimiento a seguir es similar a la simulación funcional RTL. Los
modelos de los componentes COREGEN siguen siendo modelos de comportamiento. Si la
herramienta de síntesis no es capaz de proporcionar este fichero VHDL habrá que utilizar las
herramientas de implementación para poder realizar este tipo de simulación.
-3-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
1.5. IMPLEMENTACIÓN DEL MODELO.
Una vez sintetizado el diseño se procede a su implementar. La figura 1.2 muestra el diagrama de
flujo de las herramientas de implementación de Xilinx. En ella aparecen las distintas fases en que se
divide la implementación del diseño y las herramientas utilizadas en cada una de éstas.
FASES
HERRAMIENTAS
Lista de conexiones
de entrada
.XNF o EDIF
NGDBUILD
Diseño jerárquico aplanado
.NGD
MAP
Traducción lógica a física.
Agrupamiento de LUTs y FFs en CLBs
.NCD
.PCF
TRCE
Estimación de retardos estáticos.
PAR
Emplazamiento del diseño físico
Interconexión del diseño físico.
.NCD
TRCE
Estimación de retardos estáticos.
NGDANNO & NGD2VHDL
Retroanotación de retardos.
Generación de ficheros
simulación temporal VHDL .
BITGEN
Obtención del fichero de configuración.
VHDL
SDF
.BIT
Figura 2: Flujo de implementación.
El diseño a implementar puede estar descrito en base a un conjunto de ficheros de listas de
conexiones XNF o EDIF formando una estructura jerárquica. En esta jerarquía pueden aparecer
componentes en uno de los ficheros cuya estructura interna está descrita en otro fichero. Tal es el
caso de aquellos diseños que contienen componentes COREGEN en los que cada uno de ellos está
descrito por una lista de conexiones EDN. En la fase de traducción (traslate), realizada mediante la
herramienta NGDBUILD, se enlazan los ficheros de lista de conexiones creando un único fichero de
salida en el que queda reflejada la jerarquía citada. El formato de este fichero de salida se denomina
-4-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
NGD (Native Generic Design) y contiene componentes lógicos: puertas lógicas, biestables, RAMs,
etc.
Esta herramienta puede generar también un fichero VHDL que contiene una descripción estructural
del diseño en base a componentes contenidos en la librería UNISIM. El cual se puede utilizar para
realizar simulaciones funcionales post-síntesis cuando el sintetizador no es capaz de generar este tipo
de ficheros VHDL. En este caso, los componentes generados mediante COREGEN están descritos
también mediante elementos de la librería UNISIM, por lo que no se ha de emplear los ficheros
VHDL de comportamiento de estos componentes ni la librería XILINXCORELIB.
En la fase de mapeado (map) se mapean mediante la herramienta MAP los componentes lógicos en
los componentes físicos de que dispone la FPGA: tablas LUT, biestables, buffers triestado, etc. A
continuación se encapsulan estos componentes físicos en bloques configurables (CLBs e IOBs),
creando un fichero de salida en formato NCD (Native Circuit Design).
En esta fase se realiza un análisis estático de tiempos mediante la herramienta TRCE. En él se
analizan los caminos críticos de las señales comprobando el cumplimiento de las restricciones
temporales introducidas mediante el fichero PCF (Project Constrains File). Esta evaluación es sólo
preliminar ya que todavía no se dispone de la información de los retardos debidos a las
interconexiones.
Si el diseño cumple las restricciones temporales impuestas se pasa a realizar el emplazamiento e
interconexión de los bloques configurables en la FPGA mediante la herramienta PAR. Esto
corresponde a la fase denominada place & routing. La herramienta PAR genera un fichero de lista
de conexiones en formato NCD. Una vez finalizado este proceso se dispone de toda la información
de retardos internos (elementos activos e interconexiones). Con la herramienta TRCE se puede
realizar de nuevo un análisis estático de tiempos esta vez con todos los datos de retardos internos.
En la siguiente fase se obtienen la información para realizar simulaciones temporales del diseño
completo. En primer lugar la herramienta NGDANNO retroanota la información de retardos internos.
A continuación la herramienta NGD2VHDL crea un fichero VHDL estructural en base a los
componentes físicos de la FPGA y un fichero SDF con los retardos internos de la FPGA. Los modelos
de simulación de estos componentes se encuentran en la librería SIMPRIM. La retroanotación de
retardos se realiza mediante un fichero SDF. Utilizando estos ficheros se puede realizar la verificación
del diseño final mediante una simulación temporal VHDL post-síntesis post-implementación tal y
como muestra la figura 1.1. Finalmente la herramienta BITGEN genera el fichero de configuración
de la FPGA.
2. DESCRIPCIÓN DEL DISEÑO A REALIZAR.
Para ilustrar el proceso de diseño en VHDL para FPGAs se empleará como ejemplo de diseño la
realización de un cronometro digital con precisión de segundos y valor máximo de cuenta de un
minuto. Con este diseño se pretende ilustrar las situaciones más frecuentes que aparecen en los
diseños para FPGAs descritos en VHDL. El diseño se implementará en una FPGA XC2S50ETQ144-6
, utilizando para su desarrollo la placa empleada en el laboratorio. La figura 1.3 muestra el diseño
a realizar.
-5-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
OSCILADOR
FPGA
Vcc
Vcc
R
RST
clk
R
DisplayUnidades
MARCHA
lapso
rst
UPDOWN
P1
DisplayDecenas
Figura 3: Diseño a realizar
La señal de reloj del sistema proviene de un osiclador externo, que proporciona una señal de
frecuencia 10 MHz. El número de segundos transcurridos se visualizará sobre sendos displays de 7
segmentos conectados a la FPGA. El sistema dispone de un pulsador de reset para inicializar la
cuenta del tiempo transcurrido. Además se dispone de otro pulsador para implementar la función
de lapso. Al pulsar este pulsador se congela el tiempo actual de forma que sobre los displays se
muestra dicho instante de tiempo mientras que el cronómetro sigue contando internamente. Al
volver a pulsar el pulsador de lapso se muestra el tiempo transcurrido actualmente. Si bien en la
figura anterior las resistencias conectadas a los pulsadores aparecen como componentes externos,
en el diseño a realizar éstas se implementarán mediante las resistencias de pull-up de los IOBs
correspondientes a estos terminales de la FPGA. La figura 1.4 muestra el diagrama de bloques del
diseño a realizar.
PRESCALER
DIVISOR
1 / 10E10
CONTADOR
0-59
EN1HZ
REGISTROS BCD2SEG
EN
prescaler.vhd
BCD2SEG
clk
EN
bcd2seg.vhd
rst
FSM
lapso
crono.vhd
Figura 4: Diagrama de bloques del diseño.
La descripción VHDL de este diseño está compuesta de varios ficheros. El fichero bcd2seg.vhd
contiene la descripción de un decodificador BCD a 7 segmentos para displays de cátodo común. Este
decodificador se instanciará como sendos componentes en la entidad de mayor jerarquía que se
encuentra almacenada en el fichero crono.vhd. En esta entidad se intancia también el componente
PRESCALER que proporciona la señal de 1 Hz, emplada para contar los segundos. Esta señal se
-6-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
obtiene de dividir la frecuencia de la señal de reloj clk por un factor de 10E10. Este componente se
generará mediante COREGEN.
El tiempo transcurrido viene indicado mediante un contador de décadas de 2 dígitos (unidades y
decenas). Para implementar la función de congelación del tiempo se intercalan sendos registros entre
la salida del contador y los decodificadores BCD a 7 segmentos. Cuando la señal de habilitación de
estos registros está activa la salida de los registros reflejan el valor actual de cuenta. Si por el contrario
la señal de habilitación está desactivada no se actualiza la salida del contador sobre los displays
implementando de esta forma la función de congelación.
La señal de habilitación de estos registros se controla mediante una máquina de estados que recibe
como entrada la señal procedente del pulsador de lapso, y cuyo grafo se muestra en la figura 1.5.
La variable P indica el estado del pulsador: 1 sin pulsar, 0 pulsado.
P=1
P=0
S1
1
P=0
P=1
S4
S2
1
0
P=1
S3
P=0
P=0
0
P=1
Figura 5: Grafo de la máquina de estados.
Inicialmente la máquina parte del estado S1 (la salida está a 1), de forma que la cuenta no está
congelada. Si en este estado se pulsa el pulsador (P=0) se pasa al estado S2, inhabilitandose el
refresco de los registros (la salida pasa a 0). Se permanece en este estado mientras el pulsador se
encuentre activado. Al liberarse (P=1) se pasa al estado S3 (la salida permanece a 0), donde se
espera hasta que se vuelva a activar el pulsador (P=0) momento en el cual se pasa al estado S4 (la
salida pasa a 1), habilitando de nuevo el refresco de los registros. El sistema permanece en S4
mientras el pulsador permanece activado, pasando a S1 al liberarse.
Una vez descrito el comportamiento del diseño se pasará describir el código VHDL a utilizar para
implementarlo. En el archivo codigo.zip se encuentran todos los ficheros VHDL necesarios para
realizar la aplicación antes descrita. Estos archivos se almacenarán en el directorio raíz del diseño.
En este grupo se incluyen todos los ficheros fuente VHDL empleados, tanto los desarrollados por el
diseñador, como los generados automáticamente por las herramientas de síntesis (Leonardo), así
como las de implementación (ISE 4.1): Éstos ultimo serán utilizados, ademas de configurar la FPGA,
para realizar la simulación temporal del diseño. Otros ficheros son los pertenecientes a los
componentes COREGEN utilizados. Por tanto, si el diseño contiene componentes COREGEN (como
es el caso que nos ocupa), el directorio de proyecto de estos componentes deberá ser el directorio
raíz. Finalmente también se almacenará en el directorio raíz el fichero de restricciones de usuario
(.ucf) empleado para asociar las señales externas del diseño a terminales concretos de la FPGA.
En el archivo herramientas.zip se encuentran archivos scrips a utilizar con las herramientas de
simulación y síntesis que permitirán simplificar la fase de diseño. a lo largo de este manual se irán
explicando la funcionalidad de cada uno de ellos.
-7-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
2.1. CREACIÓN DEL MÓDULO COREGEN.
Como se ha comentado el módulo prescaler se va a crear mediante COREGEN. Esta herramienta
permite generar nuevos componentes a partir de un modelo básico predefinido que el usuario
parametriza y ajusta a sus necesidades. Esta herramienta se ejecuta seleccionando:
Inicio º Programas º Xilinx ISE4.1 º Accesorios
Esto arranca la herramienta COREGEN apareciendo la pantalla de Setup mostrada en la figura 1.7,
que nos permite crear un proyecto nuevo o acceder a uno ya creado. Un proyecto se considera
como el subdirectorio donde se almacenan los componentes creados por esta herramienta. Para
nuestra aplicación será el mismo en el que se almacena el código VHDL.
Figura 7: Selección de un proyecto para COREGEN.
Sise ha optado por la opción de crear un proyecto nuevo (Create New Project) aparece la ventana
mostrada en la figura 1.8, en la que se selecciona el formato del archivo de salida. En nuestro caso
se debe seleccionar las opciones VHDL y la herramienta de síntesis utilizada (exemplar, para el caso
de utilizar Leonardo Spectrum). Así mismo, también se selecciona la familia de FPGAs para la que
se va a crear el componente.
-8-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
Figura 8: Ventana de configuración de COREGEN.
En la pestaña Project Directory debe aparecer el path del directorio donde se almacenará el
componente creado con COREGEN. Según lo indicado, para este ejemplo debe ser c:\tutorial. Una
vez creado un proyecto se pueden modificar las anteriores opciones utilizando la herramienta
Project Options del menú Project.
Una vez fijadas las distintas opciones se validan mediante el botón Aceptar mostrandose a
continuación la ventana principal de COREGEN (figura 1.9)
Figura 9: Ventana principal de COREGEN.
En el campo Target Family se muestran el tipo de agrupación de los elementos que se poden crear,
pudíendose cambiar la selección con la pestaña View Catalog. En el campo Contens Of se
representan los componentes que podemos crear. Por su parte, en el campo Generated Modules
se muestran todos los componentes que se encuentra en el proyecto de trabajo, haciendo doble clic
sobre cada uno de ellos se pueden volver a editar y en consecuencia a modificar su funcionalidad.
Una vez seleccionado un componente en la ventana Contens Of, seleccionando
se accede
a un archivo en formato PDF en el que se detalla la funcionalidad de cada uno de los terminales del
-9-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
componente. El prescaler se va a crear a partir de un contador, para ello se selecciona la carpeta
Counters en Basic Elements para entran en el modelado del componente se hace doble clic sobre
el elemento de la ventana Contens Of o se ejecuta
, apareciendo el menú de la figura 1.10 que
permite parametrizar el componente de acuerdo con nuestras necesidades. En este caso debemos
diseñar un contador de 0 a 10E10-1(98967FH ) con señal de reset asíncrono (ACLR) y fin de cuenta
(THRESH0), para acceder a estas opciones se debe seleccionar el botón Next.
Figura 10: Plantilla de los contadores.
Una vez parametrizado el componente se crea actuando sobre Generate, creandose el archivo
VHDL. A su vez se crea un archivo, de extensión vho, que proporciona las lineas de código para
definir y instanciar el componente en un archivo VHDL. El contenido del fichero de plantilla
prescaler.vho es:
-- This file is owned and controlled by Xilinx and must be used
--- solely for design, simulation, implementation and creation of
--- design files limited to Xilinx devices or technologies. Use
--- with non-Xilinx devices or technologies is expressly prohibited --- and immediately terminates your license.
----- Xilinx products are not intended for use in life support
--- appliances, devices, or systems. Use in such applications are
--- expressly prohibited.
----- Copyright (C) 2001, Xilinx, Inc. All Rights Reserved.
------------------------------------------------------------------------ The following code must appear in the VHDL architecture header:
------------- Begin Cut here for COMPONENT Declaration ------ COMP_TAG
component prescaler
port (
Q: OUT std_logic_VECTOR(23 downto 0);
CLK: IN std_logic;
THRESH0: OUT std_logic;
ACLR: IN std_logic);
end component;
-- COMP_TAG_END ------ End COMPONENT Declaration ------------- The following code must appear in the VHDL architecture
-- body. Substitute your own instance name and net names.
------------- Begin Cut here for INSTANTIATION Template ----- INST_TAG
your_instance_name : prescaler
port map (
Q => Q,
CLK => CLK,
THRESH0 => THRESH0,
ACLR => ACLR);
-- INST_TAG_END ------ End INSTANTIATION Template ----------------
You must compile the wrapper file prescaler.vhd when simulating
the core, prescaler. When compiling the wrapper file, be sure to
reference the XilinxCoreLib VHDL simulation library. For detailed
instructions, please refer to the "Coregen Users Guide".
2.2. MÓDULO BCD2SEG.
-10-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
El modelo del decodificador BCD a 7 segmentos se almacena en el fichero bcd2seg.vhd. La
decodificación se realiza mediante una asignación concurrente de señal seleccionada tal y como se
muestra en el siguiente listado. La salida de este módulo es un bus de 7 líneas donde la de menor
peso corresponde al segmento “a” y la de mayor peso al segmento “g”.
library ieee;
use ieee.std_logic_1164.all;
entity BCD2SEG is
port (
BCD:
in
Display:out
end BCD2SEG;
std_logic_vector(3 downto 0); -- input data
std_logic_vector(6 downto 0));
architecture inside of BCD2SEG is
begin
with BCD select
Display <=
"0111111"
"0000110"
"1011011"
"1001111"
"1100110"
"1101101"
"1111101"
"0000111"
"1111111"
"1100111"
"0000000"
end inside;
when
when
when
when
when
when
when
when
when
when
when
"0000",
"0001",
"0010",
"0011",
"0100",
"0101",
"0110",
"0111",
"1000",
"1001",
others;
--0
--1
--2
--3
--4
--5
--6
--7
--8
--9
--0
2.3. MÓDULO CRONO.VHD
Este es el fichero principal del diseño sobre el que se instancian los componentes bcd2seg y
prescaler. El resto de los módulos que aparecen en el diagrama de bloques de la figura 1.4 (contador,
registros, FSM, etc) aparecerán como procesos dentro de la arquitectura del cronometro. El listado
completo de este fichero se muestra a continuación.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity crono is
port (
lapso:
rst:
clk:
in
in
in
std_logic;
std_logic;
std_logic;
DisplayUnidades:
out
std_logic_vector(6 downto 0);
DisplayDecenas:
out
std_logic_vector(6 downto 0));
attribute pull:string;
attribute pull of rst,lapso:signal is "pullup";
end crono ;
architecture rtl of crono is
-- Declaración del decodificador BCD a 7 segmentos.
component BCD2SEG
port(
BCD: in std_logic_vector (3 downto 0);
Display: out std_logic_vector (6 downto 0));
end component;
-- Declaración del prescaler (COREGEN).
component prescaler
port (
Q: OUT std_logic_VECTOR(23 downto 0);
CLK: IN std_logic;
THRESH0: OUT std_logic;
ACLR: IN std_logic);
end component;
signal Unidades:
signal Decenas:
signal CntUnidades:
signal CntDecenas:
signal EN1HZ,rst_n:
std_logic_vector(3 downto 0);
std_logic_vector(3 downto 0);
unsigned(3 downto 0);
unsigned(3 downto 0);
std_logic;
-- Estados de la FSM que controla el sistema.
type stateFSM is (
-11-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
S1,
S2,
S3,
S4);
-----
signal state:
signal actualizar:
RunningWaitingOnPush
RunningWaitingOnRelease
FrozenWaitingOnPush
FrozenWaitingOnRelease
stateFSM;
std_logic;
begin
-- Instantación de los decodificadores BCD a 7 segmentos.
U1 : BCD2SEG
BCD
DISPLAY
port map (
=> Unidades,
=> DisplayUnidades);
U2 : BCD2SEG
BCD
DISPLAY
port map (
=> Decenas,
=> DisplayDecenas);
-- Instantación del prescaler (COREGEN).
U3 : prescaler
port map (
CLK => clk,
THRESH0 => EN1HZ,
ACLR =>rst_n);
rst_n<=
not rst;
-- Proceso contador.
process(clk,rst)
begin
if(rst='0') then
CntUnidades <= (others => '0');
CntDecenas <= (others => '0');
elsif(clk='1' and clk'event) then
if(EN1HZ='1') then
if (CntUnidades = 9) then
CntUnidades <= (others => '0');
if (CntDecenas = 5) then
CntDecenas <= (others => '0');
else
CntDecenas <= CntDecenas + 1;
end if;
else
CntUnidades <= CntUnidades + 1;
end if;
end if;
end if;
end process;
-- Proceso de registros de lapso.
process(clk,rst)
begin
if(rst='0') then
Unidades
<= (others => '0');
Decenas <= (others => '0');
elsif (clk'event and clk='1') then
if (actualizar = '1') then
Unidades
<= std_logic_vector(CntUnidades);
Decenas <= std_logic_vector(CntDecenas);
end if;
end if;
end process;
-- Maquina de estados de control del lapso:
-Control del cambio de estados.
process(clk,rst)
begin
if(rst='0') then
state <= S1;
elsif (clk'event and clk='1') then
case state is
when S1 =>
if (lapso = '1') then
state <= S1;
else
state <= S2;
end if;
when S2 =>
if (lapso = '0') then
state <= S2;
else
state <= S3;
end if;
when S3 =>
if (lapso = '1') then
state <= S3;
else
state <= S4;
end if;
when S4 =>
if (lapso = '0') then
state <= S4;
else
state <= S1;
end if;
end case;
end if;
end process;
-12-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
-- Maquina de estados de control del lapso:
-Control de la salida.
process(state)
begin
case state is
when S2 | S3 =>
actualizar <= '0';
when S1 | S4 =>
actualizar <= '1';
end case;
end process;
end rtl ;
2.3.1. Declaración de librerías.
Este fichero comienza con la declaración de las librerías a emplear. El paquete numeric_std
contiene la declaración de tipos y operadores que permiten realizar operaciones aritméticas con
vectores de bits.
2.3.2. Definición de la entidad.
Respecto a la declaración de la entidad la única cuestión a destacar sobre lo ya expuesto es la
asignación del atributo pull a los puertos correspondientes a los pulsadores. Este atributo es
reconocido automáticamente por el sintetizador como indicador de que debe emplear la resistencia
de pull-up de los IOBs correspondientes a dichos puertos. Esto se verá con más detalle en el apartado
dedicado al sintetizador.
2.3.3. Parte declarativa de la arquitectura.
En esta parte del código se declaran los componentes a instanciar (decodificadores BCD a 7
segmentos y el prescaler creado con COREGEN) así como las señales internas empleadas para
conectar los distintos elementos que aparecen en el diagrama de bloques de la figura 1.4. También
aparece un tipo enumerado empleado en la descripción de la señal de estado de la FSM.
2.3.4. Instanciación de componentes.
Al principio del cuerpo de la arquitectura se realiza la instanciación de los componentes
mencionados. Así el puerto clk se conecta a la entrada de reloj del prescaler, obteniéndose su
salida la señal EN1Hz, utilizada para habilita la cuenta del contador.
2.3.5. Contador de décadas.
Este contador se implementa mediante el proceso cuyo listados se muestra a continuación. Dicho
proceso es sensible a las señales de reset asíncrona (rst) y reloj (clk) . El carácter asíncrono de la
señal de reset se fija mediante la posición de la sentencia if dentro de la estructura de if anidados
que evalúa su estado. El valor de cuenta se almacena sobre las señales CntUnidades y CntDecenas.
Estas señales están declaradas de tipo unsigned. Este es un tipo derivado de std_logic_vector que
permite realizar operaciones aritméticas. El valor de cuenta sólo se modifica si la señal EN1HZ está
a 1. Esta señal se obtiene del módulo prescaler.
-- Proceso contador.
process(clk,rst)
begin
if(rst='0') then
CntUnidades <= (others => '0');
CntDecenas <= (others => '0');
elsif(clk='1' and clk'event) then
if(EN='1') then
if (CntUnidades = 9) then
CntUnidades <= (others => '0');
if (CntDecenas = 5) then
CntDecenas <= (others => '0');
-13-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
else
end if;
else
end if;
end process;
end if;
end if;
CntDecenas <= CntDecenas + 1;
CntUnidades <= CntUnidades + 1;
2.3.6. Registros de la visualización.
Los registros empleados para implementar la función de congelación de la visualización se describen
mediante el siguiente proceso.
process(clk,rst)
begin
if(rst='0') then
Unidades
<= (others => '0');
Decenas <= (others => '0');
elsif (clk'event and clk='1') then
if (actualizar = '1') then
Unidades
<= std_logic_vector(CntUnidades);
Decenas <= std_logic_vector(CntDecenas);
end if;
end if;
end process;
Si la señal actualizar correspondiente a la salida de la FSM está a uno (visualización no congelada)
las señales Unidades y Decenas reflejan el valor de cuenta en cada flanco activo de la señal de
reloj. Las cuales se conectan a las entradas de los decodificadores BCD a 7 segmentos. Hay que
destacar que estas señales son de tipo std_logic_vector mientras que las señales de cuenta
CntUnidades y CntDecenas son de tipo unsigned. Por este motivo es preciso emplear una
conversión “cast” en la asignación.
2.3.7. Máquina de estados.
La figura 1.11 muestra el diagrama de bloques de una máquina de estados. Como se aprecia ésta se
describe mediante sendos procesos: uno para controlar las transiciones entre estados y otro para
generar la salida de la máquina.
Entradas
asíncronas
Proceso síncrono
Entradas
Próximo
estado
Cálculo del
próximo estado
Lógica
combinacional
Reloj
Elementos
de memoria
Lógica
secuencial
Entradas
(sólo para tipo Mealy)
Estado
actual
Cálculo de
las salidas.
Salidas
Lógica
combinacional
Proceso combinacional
Figura 11: Estructura de una máquina de estados.
Para representar el estado de la máquina se ha definido el tipo enumerado stateFSM que puede
tomar los valores correspondientes a dichos estados. El valor del estado actual de la FSM se almacena
en la señal state. La salida de la FSM es la señal actualizar que toma el valor cero cuando la
cuenta está congelada. Para declarar estas señales se emplea el siguiente código:
-14-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
type stateFSM is (
S1,
-- RunningWaitingOnPush
S2,
-- RunningWaitingOnRelease
S3,
-- FrozenWaitingOnPush
S4);
-- FrozenWaitingOnRelease
signal state:
signal actualizar:
stateFSM;
std_logic;
El proceso empleado para modelar las transiciones entre estados es sensible a las señales de control
asíncronas (rst) y reloj (clk). La decodificación del siguiente estado en función del
estado actual y las entradas se realiza mediante una sentencia case. El
código VHDL de este proceso es el siguiente
-- Maquina de estados de control del lapso:
-Control del cambio de estados.
process(clk,rst)
begin
if(rst='0') then
state <= RunningWaitingOnPush;
elsif (clk'event and clk='1') then
case state is
when S1 =>
if (lapso = '1') then
state <= S1;
else
state <= S2;
end if;
when S2 =>
if (lapso = '0') then
state <= S2;
else
state <= S3;
end if;
when S3 =>
if (lapso = '1') then
state <= S3;
else
state <= S4;
end if;
when S4 =>
if (lapso = '0') then
state <= S4;
else
state <= S1;
end if;
end case;
end if;
end process;
El proceso empleado para modelar la lógica combinacional empleada para
generar las salidas es sensible al estado de la FSM. Si se tratará de una
máquina de tipo Mealy en esta lista deberían declararse también las entradas
de la FSM.
-- Maquina de estados de control del lapso:
-Control de la salida.
process(state)
begin
case state is
when S2 | S3 =>
actualizar <= '0';
when S1 | S4 =>
actualizar <= '1';
end case;
end process;
2.4. BANCO DE PRUEBAS.
A continuación se proporciona el listado del fichero VHDL correspondiente al banco de pruebas
empleado para validar el diseño. Se trata de una entidad sin puertos. En la parte declarativa de la
arquitectura se declara el componente a verificar (crono) y un conjunto de señales correspondientes
a cada uno de los puertos de dicho componente. Éstas son fácilmente reconocibles porque tienen
el sufijo _tb.
-15-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
library IEEE;
use ieee.std_logic_1164.all;
entity testbench is
generic (
PUSHTIME:
time := 500 ns;
-- Tiempo de duración de una tecla.
RSTTIME:
time := 10 ns;
-- Tiempo de activación del reset.
Tclk:
time := 100 ns); -- Periodo de la señal de reloj.
end testbench;
architecture simula of testbench is
-- Declaración del componente crono.
component crono
port (
lapso:
in
std_logic;
rst:
in
std_logic;
clk:
in
std_logic;
DisplayUnidades:
out
std_logic_vector(6 downto 0);
DisplayDecenas:
out
std_logic_vector(6 downto 0));
end component;
begin
-- Señales auxiliares para de excitación para el banco de pruebas.
signal lapso_tb:
std_logic;
signal rst_tb:
std_logic:='0';
signal clk_tb:
std_logic:='0';
signal DisplayUnidades_tb:
std_logic_vector(6 downto 0);
signal DisplayDecenas_tb:
std_logic_vector(6 downto 0);
-- Instantación del componente crono.
uut : crono port map (
lapso
=> lapso_tb,
rst
=> rst_tb,
clk
=> clk_tb,
DisplayUnidades
=> DisplayUnidades_tb,
DisplayDecenas
=> DisplayDecenas_tb);
-- Generación de la señal de reset.
rst_tb <=
'1' after RSTTIME;
-- Generación de la señal de reloj.
clk_tb <=
not clk_tb after Tclk/2;
-- Proceso principal control de la excitacion.
process
--------------------------------------------------------- PULSAR: Simula la pulsación del pulsador de lapso
-- Parámetros de entrada:
-No tiene.
--------------------------------------------------------procedure pulsar is
begin
lapso_tb <= '0';
wait for PUSHTIME;
lapso_tb <= '1';
wait for PUSHTIME;
end pulsar;
begin
-- Valor inicial de los estímulos.
lapso_tb <= '1';
-- Secuencia de operación.
wait for 1 ms;
pulsar;
wait for 10 ms;
pulsar;
wait for 10 ms;
pulsar;
-- Termina la simulación.
assert FALSE report "Finalizacion controlada de la simulacion" severity failure;
end process;
end simula;
El control de la introducción de estímulos propiamente dicha se realiza mediante un proceso. En él
se declara un procedimiento para cada una de las acciones a llevar a cabo en la verificación del
diseño. En este ejemplo el procedimiento pulsar reproduce la pulsación de la tecla lapso. En el
cuerpo del proceso se controla el instante en que se realiza cada acción (ejecución del proceso
asociado) mediante sentencias wait for. Notese que este proceso no tiene lista de sensibilidades
por lo que se estaría ejecutando siempre. Para controlar la finalización de la simulación desde el
propio banco de pruebas se emplea la sentencia assert.
2.5. FICHERO
CNF_FUNCIONAL.VHD
-16-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
Co el fín de que el testbench creado pueda ser utilizado tanto para realizar una simulación funcional
como temporal se deben crear sendas configuraciones, que nos permitan seleccionar arquitecturas
diferentes para el componente crono. En el caso de realizar la simulación funciona, para el
componente cronol instanciado en el testbench, se debe se debe seleccionar la arquitectura rtl . El
código del archivo de configuración es el siguiente:
configuration funcional of testbench is
for simula
for dut : crono use entity work.crono(rtl);
end for;
end for;
end funcional ;
Todas las cuestiones anteriores referidas a la configuración de componentes son innecesarias si a la
hora de referenciar el componente crono en el testbench, se utiliza la referencia a componente de
VHDL-93, en la cual se puede referenciar un componente sin ser previamente declarado en la parte
declarativa de la arquitectura y en la cual puede especificarse la entidad y la arquitectura a usar. En
el caso de utilizar esta alternativa será necesario crear dos archivos de testbench, uno para realizar
la simulación funcional y otro para la temporal, si bien el contenido sería el mismo. La única
diferencia estaría en la instanciación del componente, así en el testbench de para la simulación
funcional se pondría:
dut : entity work.crono(rtl) port map (
lapso
=> lapso_tb,
rst
=> rst_tb,
clk
=> clk_tb,
DisplayUnidades
=> DisplayUnidades_tb,
DisplayDecenas
=> DisplayDecenas_tb);
El listado completo del testbench para realizar la simulación temporal utilizando la anterior
declaración de componente se encuentra en el archivo tb_funcional.vhd. También se aporta un
nuevo scrip para la compilación de todo el diseño, caso de utilizar el anterior testbench. Dicho
archivo scrip es compila2.do. Así mismo, se añade el archivo sim_funcional2.do para realizar la
simulación funcional.
3. SIMULACIÓN FUNCIONAL DEL DISEÑO.
3.1. INTRODUCCIÓN.
Para verificar la validez del diseño realizado se realizará una simulación de funcional (también
denominada de comportamiento o RT) empleando para ello el simulador ModelSim de Mentor
Graphics. Para ello arranque el simulador seleccionando
Inicio º Programas
º ModelSim SE EE º ModelSim
En ese momento se muestra la pantalla que aparece en la figura 1.12.
-17-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
Figura 12: Pantalla del simulador VHDL.
Este simulador se puede controlar mediante una interface gráfica de usuario basada en menús y cajas
de diálogo desplegables o bien mediante una línea de comandos. En este tutorial se explicará el uso
del simulador mediante comandos. Esta decisión se basa en el hecho de que el interface de usuario
puede variar de una versión a otra, no ocurriendo esto con los comandos. Concretamente para
realizar este tutorial se ha empleado la versión 5.5c, por lo que algunas de las ventanas mostradas
pueden variar ligeramente.
La secuencia de comandos a emplear para realizar una simulación se pueden almacenar en un
fichero de script. Conceptualmente los ficheros de scripts son similares a los ficheros de proceso por
lotes de un sistema operativo (por ejemplo .bat para DOS). Se les suele asignar la extensión .do. Para
ejecutar un fichero de script se emplea el comando do cuya sintaxis es:
do <nombre_fichero_script>
La posibilidad de almacenar estas secuencias de comandos en ficheros de script permite reutilizarlos
en los distintos tipos de simulación a realizar (funcional, post-implementación y temporal) durante
el flujo de diseño VHDL para FPGAs.
3.1.1. Librerías.
Las librerías son directorios que contienen unidades de diseño compiladas. Estas unidades de diseño
pueden ser primarias o secundarias. Las unidades de diseño primarias (entidades, declaraciones de
paquetes y configuraciones) almacenadas en una librería deben tener un nombre único. Por otro
lado las unidades de diseño secundarias (arquitecturas y cuerpos de paquetes) pueden tener nombres
comunes. Por ejemplo, las arquitecturas de dos entidades distintas pueden tener el mismo nombre.
Este simulador clasifica las librerías en dos tipos: librerías de trabajo y librerías de recursos. Todo
diseño dispone de una única librería de trabajo que por defecto se denomina work, donde se
almacenan una vez que se han compilado las unidades de diseño descritas en los ficheros fuente del
-18-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
diseño. La librería de trabajo debe crearse antes de compilar los ficheros fuente del diseño. Por otro
lado las librerías de recursos contienen unidades de diseño a las que se puede hacer referencia desde
diseño que se está compilando. Estas librerías se declaran mediante las sentencias library y use. Así
para nuestro ejemplo, la entidad y arquitectura del cronómetro se almacena en la librería work
mientras que el componente OSC4 se encuentra almacenado en la librería unisim.
Para crear una librería se utiliza el comando vlib. La sintaxis de este comando es:
vlib <library_name>
donde <library_name> es el nombre de la librería. Este comando crea el directorio asociado a
dicha librería en el directorio de trabajo actual.
Una vez creada la librería se pueden proceder a compilar los ficheros fuente VHDL que contienen
la descripción de las unidades de diseño que se almacenarán en dicha librería. Para ello se emplea
el comando vcom. La sintaxis resumida de este comando es:
vcom [-93] [-work <nombre_librería>] <fichero1>.vhd <fichero2>.vhd ...
El parámetro -93 indica que se emplee el la versión 93 de VHDL frente a la 87. Si no se especifica
este parámetro se emplea la versión especificada mediante la opción Options º Compile... de
la barra de menús. Mediante el parámetro -work se especifica la librería destino en la que se
almacenará el código compilado. Si no se especifica este parámetro por defecto se almacena en la
librería work. Recuerdese que la librería destino debe haber sido creada con anterioridad y en caso
de que no se encuentre en el directorio actual haber sido hecha visible mediante el comando vmap.
Por último se especifican los ficheros VHDL a compilar. Éstos se compilan en el orden de aparición.
El orden en que se especifican los ficheros fuente dependerá de las dependencias existentes entre
las unidades de diseño descritas en ellos. Según esto se debe compilar:
!
!
!
!
!
!
La entidad antes que la arquitectura.
La declaración del paquete antes que el cuerpo de éste.
Las unidades de diseño antes de las referencia a ellas.
Los paquetes antes que las entidades/arquitecturas que los utilicen.
Las entidades/Configuraciones antes de las arquitecturas a que hacen referencia.
Las configuraciones se compilan las últimas.
Puede ocurrir que el directorio donde se almacena una librería no este contenido en el directorio
de trabajo actual. Esta es una situación típica que se da cuando se pretenden utilizar unidades de
diseño compiladas con anterioridad para otro diseño en el diseño actual. Por ejemplo, las librerías
unisim, simprim y xilinxcoregenlib se reutilizarán en cada nuevo diseño para FPGAs de Xilinx.
Para gestionar estas situaciones ModelSim asigna a cada librería un nombre físico y un nombre
lógico. El nombre físico corresponde al path del directorio donde se almacenan las unidades de
diseño compiladas. El nombre lógico es la denominación que recibe la librería cuando se hace
referencia a ella desde el simulador o desde el código fuente VHDL, por ejemplo mediante la
sentencia use. Cuando una librería se encuentra almacenada en el directorio de trabajo actual el
nombre físico coincide con el nombre lógico. En caso contrario es preciso asignar a la librería un
nombre lógico mediante el comando vmap. A este proceso se le denomina mapeado. La sintaxis de
este comando es:
vmap <nombre_logico> <path_del_directory>
-19-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
Otros comandos empleados para la gestión de librerías son vdir y vdel que se emplean
respectivamente para mostrar el contenido de una librería y para borrar elementos de ésta. La sintaxis
de vdir es:
vdir [-lib <nombre_librería>]
Si se emplea el comando sin parámetros se muestra el contenido de la librería work. Por otro lado
la sintaxis del comando vdel es:
vdel [-lib <nombre_librería>]
[-all |<unidad_de_diseño>]
donde <nombre_librería> es la librería de donde se desea borrar la unidad de diseño en cuestión.
Si no se especifica la librería se toma por defecto la librería work. En cuanto a las unidades de diseño
a borrar éstas se pueden especificar individualmente o bien borrar todas ellas utilizando el parámetro
-all. En este último caso se borra incluso el directorio correspondiente a la librería por lo que si se
desean compilar con posterioridad nuevos ficheros fuente sobre ésta será preciso crearla de nuevo
con el comando vlib.
Al igual que ocurre en los compiladores de C, los cuales proporcionan en la librería de soporte del
sistema las funciones definidas por ANSI C, los simuladores VHDL suelen disponer de una serie de
librerías predefinidas que no es necesario compilar cada vez que se realiza un nuevo diseño. En
el caso concreto de ModelSim se encuentran predefinidas las siguientes librerías:
!
!
!
La librería std que contiene los paquetes standard y textio.
La librería IEEE que contiene paquetes aritméticos precompilados de Synopsys e IEEE.
La librería vital empleada para realizar simulaciones temporales.
Estas librerías están optimizadas para la simulación por lo que no es recomendable que el usuario
realice modificaciones de ellas.
Teniendo en cuenta lo expuesto, siguiendo con nuestro ejemplo se procederá a crear las librerías
VHDL de Xilinx (unisim, simprim y XilinxCoreLib) y compilarlas. Para ello cree el directorio donde
se almacenarán estas librerías. Por ejemplo:
c:\VHDL_Xilinx_lib
El código fuente de estas librerías se encuentra en c:\ise41\vhdl\src. Dentro de este directorio
se encuentran tres subdirectorios correspondientes a cada una de las librerías citadas. Para compilar
las librerías cambie el directorio actual del simulador al directorio donde se almacenarán ejecutando
desde la consola de ModelSim el comando:
cd c:/VHDL_Xilinx_lib
Notese que la sintaxis empleada por ModelSim para especificar la jerarquía de un directorio es la
misma que la de Unix, ya que las primeras versiones de este simulador se desarrollaron para dicho
sistema operativo.
Para crear estas librerías se deben ejecutar los siguientes comandos desde la consola de ModelSim:
!
Compilación de la librería unisim.
vlib unisim
vcom -work unisim C:/ise41/vhdl/src/unisims/unisim_VPKG.vhd
-20-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
vcom -work unisim C:/ise41/vhdl/src/unisims/unisim_VCOMP.vhd
vcom -work unisim C:/ise41/vhdl/src/unisims/unisim_VITAL.vhd
vmap unisim c:/VHDL_Xilinx_lib/unisim
!
Compilación de la librería simprim.
vlib
vcom
vcom
vcom
vmap
!
simprim
-work simprim C:/ise41/vhdl/src/simprims/simprim_Vpackage.vhd
-work simprim C:/ise41/vhdl/src/simprims/simprim_Vcomponents.vhd
-work simprim C:/ise41/vhdl/src/simprims/simprim_VITAL.vhd
simprim c:/VHDL_Xilinx_lib/simprim
Compilación de la librería XilinxCoreLib.
vlib XilinxCoreLib
vcom -work XilinxCoreLib C:/ise41/vhdl/src/XilinxCoreLib/mvlutil.vhd
vcom -work XilinxCoreLib C:/ise41/vhdl/src/XilinxCoreLib/mvlarith.vhd
vcom -work XilinxCoreLib C:/ise41/vhdl/src/XilinxCoreLib/XilinxCoreLib.vhd
vmap XilinxCoreLib c:/VHDL_Xilinx_lib/XilinxCoreLib
Para facilitar el trabajo junto con el código fuente del diseño se proporcionan un fichero script
xilinx_lib.tcl que permite realizar las operaciones anteriores de una manera más simple. La ejecución
del script se realiza mediante el comando source.:
source xilinx_lib.tcl
una vez ejecutado aparece la ventana mostrada en la figura 1.13. Se deben seleccionar las opciones
que aparecen en dicha figura, pudiendose variar el subdirectorio destino.
Figura 13: Configuración de las librerías.
La creación de las estas librerías sólo se realiza una vez, es decir, no es preciso compilar estas librerías
para cada nuevo diseño a realizar. Ademas el archivo de inicialización de ModelSim es modificado
de forma que dichas librerías serán siempre visibles para posteriores diseños.
3.2. MANEJO DEL SIMULADOR.
Los pasos a dar para realizar una simulación son los siguientes.
Ø
Ù
Ú
Creación del proyecto.
Creación de nuevas librerías y mapeado de las librerías a reutilizar.
Compilación del código fuente.
-21-
Ingeniería Electrónica.
Û
Ü
Ý
Þ
ß
ô
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
Carga de la unidad de diseño a simular.
Definición de puntos de prueba.
Avance y detención de la simulación.
Introducción de estímulos.
Análisis de resultados.
Finalización de la sesión de simulación.
3.2.1. Creación del proyecto.
Al igual que ocurre con otros entornos de desarrollo ModelSim gestiona la información de cada
diseño mediante un proyecto, facilitando de esta forma su gestión. Un proyecto se compone de:
!
!
!
!
Un directorio de trabajo en el que se almacenan los distintos ficheros generados durante la
compilación y simulación de un diseño.
Los ficheros fuente VHDL del diseño.
Las librerías creadas.
La configuración empleada en el simulador.
Esta información se almacena en un fichero con el mismo nombre que el proyecto y la extensión
.mpf. Las operaciones que se pueden realizar con un proyecto son crearlo, abrirlo, cerrarlo o
borrarlo. Estas se realizan mediante las opciones New, Open, Close y Delete del menú File.
Para crear el proyecto empleado para realizar la simulación funcional del diseño del ejemplo
seleccione la opción File º New º Project de la barra de menús. En ese momento se mostrará
en la pantalla la ventana Create Project. Configure las opciones de estas ventana tal y como se
muestra la figura 1.14. Con esto se creará automáticamente el subdirectorio behavioral dentro del
directorio c:\tutorial. Además crea automáticamente la librería work definiendola como la
librería de trabajo para este nuevo diseño. Por tanto, el path de esta librería será
c:/tutorial/behaviral/work.
Figura 14: Ventana de creación de proyecto.
Si bien el empleo de proyectos no es obligatorio su uso facilita la gestión del diseño. En caso de no
desear emplear esta facilidad habría que ejecutar los siguientes comandos:
cd c:/tutorial
mkdir behavioral
cd behavioral
vlib work
-22-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
3.2.2. Creación de nuevas librerías y mapeado de las librerías a reutilizar
Si se desea compilar alguno de los ficheros fuente sobre alguna librería distinta de work será preciso
crearla previamente con el comando vlib. De igual forma si dentro de nuestro código se hace
referencia a alguna librería creada con anterioridad será preciso mapearla mediante el comando
vmap. Claro está que esto no es aplicable a las librerías predefinidas del simulador. Así, para hacer
visibles las librerías de Xilinx en un diseño se emplearían los siguientes comandos:
vmap unisim c:/VHDL_Xilinx_lib/unisim
vmap simprim c:/VHDL_Xilinx_lib/simprim
vmap XilinCoreLib c:/VHDL_Xilinx_lib/XilinCoreLib
Conviene aclarar que cuando se realiza el mapeado de una librería, el simulador almacena esta
información en el fichero de descripción del proyecto, de forma que se mantenga esta configuración
la próxima vez que se abra el proyecto. El simulador considera esta configuración como un aspecto
general siendo aplicable a todos aquellos proyectos que se creen a partir de ese momento. Para ello
almacena la información de mapeado en el fichero de configuración general denominado
modelsim.ini. Este fichero se encuentra en el directorio donde ha sido instalado ModelSim. En tal
caso, en dicho fichero deben aparecer las siguientes líneas:
simprim = C:/VHDL_Xilinx_lib/simprim
unisim = C:/VHDL_Xilinx_lib/unisim
XilinCoreLib = C:/VHDL_Xilinx_lib/XilinCoreLib
En el caso de este tutorial no es necesario mapear la librerías de Xilinx ya que esa labor se ha
realizado con la ejecución del scrip xilinx_lib.tcl.
Otra forma sencilla de verificar si las librerías son visibles para el proyecto actual es mediante la
opción Design º Browse Libraries de la barra de menús tal y como muestra la figura 1.15.
En caso de que no aparezcan las librerías citadas será preciso realizar el mapeado de éstas.
Figura 15: Ventana de listado de librerías.
3.2.3. Compilación del código fuente.
-23-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
Una vez creado el proyecto se procederá a la compilación de los ficheros VHDL que forman parte
del diseño. Por defecto las unidades de diseño se almacenarán en la librería work. Si un fichero
VHDL proporciona una unidad de diseño que será utilizada en otro fichero el primero de ellos debe
compilarse en primer lugar. Para compilar los ficheros fuente del diseño se han de ejecutar los
siguientes comandos desde la consola de ModelSim:
vcom
vcom
vcom
vcom
vcom
-93
-93
-93
-93
-93
bcd2seg.vhd
prescaler.vhd
crono.vhd
testbench.vhd
cnf_funcional.vhd
El fichero script compila.do recoge estos comandos. Por tanto se debe ejecutar el comando:
do compila.do
Durante la compilación el simulador muestra en la consola información referente a la evolución de
ésta. Si aparecen errores, la descripción de estos se muestra en color rojo. Haciendo doble click
sobre la línea de error se muestra automáticamente la línea del fichero fuente que produjo este error
en la ventana de código fuente. En la figura 1.16 aparece un ejemplo de ésto.
Figura 16: Visualización automática de errores en el código fuente.
3.2.4. Carga de la unidad de diseño a simular
Para poder simular el diseño realizado es preciso cargarlo en el simulador. Para ello se emplea el
comando vsim. El formato resumido de este comando es:
vsim
[-lib <nombre_librería>]
[-t [múltiplo]<unidades_tiempo>]
-24-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
[-sdfmin | -sdftyp | -sdfmax <instancia>=<fichero_sdf>]
<entidad> [<arquitectura>] | <configuración>
Como se puede observar todos los parámetros son opcionales excepto el último de ellos que indica
la unidad de diseño superior. Este último indica la entidad a simular, siendo posible especificar
también la arquitectura concreta a emplear. Esto resulta especialmente útil cuando la entidad
dispone de varias arquitecturas. Por ejemplo si se deseara simular únicamente el decodificador bcd
a 7 segmentos el comando a emplear sería:
vsim work.BCD2SEG inside
o bien simplemente
vsim BCD2SEG
La librería que contiene la unidad de diseño a simular también se puede especificar mediante el
parámetro opcional -lib. Si no se especifica, por defecto se supone que dicha unidad se encuentra
almacenada en la librería de trabajo. El parámetro -t indica la resolución de la simulación. Dicha
resolución se especifica en unidades de tiempo según el formato indicado en la tabla 1.1.
Adicionalmente puede emplearse un factor multiplicador siendo los valores admisibles 1, 10 o 100.
Si no indica la resolución del simulador, por defecto este trabaja con una resolución de 1 ns.
Tabla 1.1: Nomenclatura empleada para especificar unidades de tiempo.
Unidades
Valor
Unidades
Valor
fs
10-15 sg
ms
10-3 sg
ps
10-12 sg
sec
segundos
ns
10-9 sg
min
minutos
us
10-6 sg
hr
horas
Para el caso de una simulación temporal de un diseño para FPGAs teniendo en cuenta que los
retardos internos se expresan con una resolución de 0.1 ns la opción a emplear para fijar la
resolución sería -t 100ps. Notese que no hay espacios en blanco entre el multiplicador y las
unidades. Por último el parámetro -sdfxxx sólo se usa en simulaciones temporales, empleandose
para especificar el fichero sdf que contiene la retroanotación de retardos. Por este motivo su
explicación detallada se pospondrá al apartado destinado a simulaciones temporales.
Según lo expuesto, una vez compilados los ficheros fuente del diseño de nuestro ejemplo se puede
proceder a cargar la unidad de diseño a simular. Para nuestro ejemplo ésta es la configuración
ConfBehavioral, por lo que el comando a emplear será:
vsim cnf_funcional
3.2.5. Selección de puntos de prueba.
La verificación del diseño mediante simulación se basa en observar los
distintos elementos que aparecen en éste. Por analogía con un simulador
digital clásico a los puntos del circuito a observar (señales) los
denominaremos puntos de prueba, si bien en diseños descritos en VHDL la
variedad es más amplia: variables, señales, procesos en ejecución, etc.Tal
-25-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
y como muestra la figura 1.17 el simulador define un total de ocho ventanas
destinadas a representar los distintos tipos de elementos. Estas ventanas
son:
!
!
!
!
!
!
!
structure. Muestra la estructura jerárquica del diseño en forma de
árbol. En nivel seleccionado en esta ventana afectará al contenido de
las ventanas de formas de onda, variables, etc.
source. Muestra la el código fuente del diseño. Se suele emplear para
ejecutar el código paso a paso.
signal. Muestra las señales contenidas en el nivel seleccionado en la
ventana de estructura.
process. Proporciona información del estado de ejecución de los
procesos.
wave. Permite representar los cronogramas de la evolución de las
señales y variables del diseño.
dataflow. La ventana de flujo de datos permite realizar un seguimiento
gráfico de la conexión de procesos mediante las señales del diseño.
list. La ventana de listado permite observar los resultados de la
simulación de forma tabular y reflejando los ciclos delta
Figura 17: Ventanas del simulador.
Para abrir una de estas ventanas se emplea el comando view cuyo formato es:
view <nombre_ventana>
Este comando admite el carácter comodín *. Así el siguiente comando abre
todas las ventanas citadas:
view *
-26-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
La descripción detallada del uso de todas las ventanas queda fuera de los
objetivos de este texto. Por este motivo sólo se expondrá el uso de la
ventana de formas de onda, al ser éste el método más empleado para depurar
sistemas digitales mediante simulación.
Para abrir esta ventana seleccione la opción View º Wave de la barra de
menús, o bien ejecute el comando:
view wave
A continuación es preciso seleccionar las señales a visualizar. Si el número
de señales a visualizar es elevado esta operación puede ser un tanto tediosa.
En ese caso se puede optar por realizar esta operación mediante el interface
gráfico. Para ello es preciso abrir las ventanas de estructura y de señales.
La primera de ellas nos servirá para navegar por la estructura jerárquica del
diseño, mientras que la segunda nos permitirá seleccionar las señales a
añadir a la ventana de formas de onda. Para abrir la ventana de estructura
seleccione la opción View º Structure de la barra de menús, o bien ejecute
el comando:
view structure
De forma similar, para abrir la ventana de señales seleccione la opción View
º Signal de la barra de menús, o bien ejecute el comando:
view signal
Tal y como muestra la figura 1.18 al seleccionar un nivel en la ventana de
estructura, se muestran todas las señales contenidas en dicho nivel sobre la
ventana de formas de onda.
Figura 18: Selección de las señales de un determinado nivel
jerárquico.
Una vez mostradas las señales de interés en la ventana de señales se
procederá a añadirlas a la ventana de formas de onda. Para ello se
seleccionan las señales en cuestión en la ventana de señales y a continuación
se elige la opción View º Wave º Selected Signals de la barra de menús. O
de una forma más simple, se seleccionan y se arrastran hasta la ventana wave.
Una vez finalizado este proceso la ventana de formas de onda presenta el
aspecto mostrado en la figura 1.19.
-27-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
Figura 19:
Ventana wave una vez
seleccionadas
las
señales
a
visualizar.
También es posible representar en la ventana de formas de onda la evolución
de las variables de los procesos. Para ello es preciso que el proceso al que
pertenece la variable a visualizar esté etiquetado. Esta etiqueta sirve como
elemento identificador dentro de la ventana de estructura. El proceso a
seguir es el mismo que el utilizado para seleccionar las señales, pero
utilizando la ventana de variables.
El color de las señales, el formato numérico utilizado en el caso de los
vectores, etc. se puede fijar mediante las distintas opciones del menu
sensible al contexto que aparece al seleccionar una señal determinada y
pulsar a continuación el botón derecho del ratón (o con Format de la barra
de menús).
La configuración utilizada en la ventana de formas de onda puede almacenarse
en un fichero de scripts denominado wave.do para volverla a utilizar en
posteriores sesiones de simulación (por ejemplo cuando se realice la
simulación temporal). Para ello seleccione la opción Fileº Save Format de
la barra de menús. Básicamente, este fichero contiene comandos del tipo add
wave, los cuales se utilizan para añadir señales o variables a la ventana de
formas de onda. Su sintaxis resumida es:
add wave [-<format>] [-<radix>] <nombre_elemento>
El parámetro <nombre_elemento> especifica el nombre de la variable o señal
a visualizar. Si dicho elemento no se encuentra en la entidad superior de la
jerarquía se debe indicar el camino completo dentro de ésta. En el caso de
las variables, se especificará el camino hasta la arquitectura donde reside
el proceso que contiene la variable.
El parámetro opcional radix especifica la base numérica con que se
representan los vectores. Los valores que puede tomar este parámetro son
binary, octal, decimal (o signed), unsigned, hexadecimal, ascii, symbolic o
default. Puesto que estos nombres son suficientemente ilustrativos hay poco
que añadir a este respecto. Tan sólo indicar, que la opción -symbolic se
emplea con tipos enumerados. Si no se indica nada se representa según la base
numérica fijada por defecto (-default) en las opciones del simulador.
El parámetro opcional format indica el formato de representación (numérico
o gráfico) a emplear de los vectores. Los valores que puede tomar son
literal,
logic,
analog-step,
analog-interpolated
y
analog-backstep.
Normalmente esta opción no se suele emplear, dejando que estos los vectores
se representen en formato numérico. Las tres últimas opciones permiten
-28-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
representar la secuencia de valores que toma el vector como las muestras de
una señal analógica digitalizada. Esto es especialmente útil en la
implementación de sistemas de tratamiento digital de señal. La figura 1.20
muestra un ejemplo de esto.
Figura 20: Ejemplo de representación analógica de señales.
Una descripción más detallada de los formatos analógicos, como de los
digitales, se encuentra en el manual del simulador, al que se puede acceder
desde Help de la barra de menús.
En el ejemplo de diseño considerado, para analizar el funcionamiento del
sistema se van a observar los puertos del cronómetro, las señales de cuenta
(clkla y EN1HZ) y el estado de la presentación (señal actualizar). A la hora
de especificar una señal es preciso indicar el camino completo dentro de la
jerarquía. Según esto los comandos a ejecutar serían:
add
add
add
add
add
add
add
add
add
add
wave
wave
wave
wave
wave
wave
wave
wave
wave
wave
/testbench/rst_tb
/testbench/clk_tb
/testbench/dut/en1hz
/testbench/lapso_tb
/testbench/dut/state
/testbench/dut/actualizar
-unsigned /testbench/dut/cntunidades
-unsigned /testbench/dut/cntdecenas
/testbench/displayunidades_tb
/testbench/displaydecenas_tb
Tal y como se ha indicado una forma sencilla de obtener estos comandos es
realizar una selección manual y a continuación generar el fichero de
configuración wave.do, de este último se extraen las variables que queremos
visualiza, y se añaden al archivo scrip para la simulación. Téngase presente
que el formato de los comandos add wave tienen diferente contenido al
mostrado anteriormente, por lo que, si el usuario lo considera pertinente
puede retocarlos, para tener una sintaxis más corta, si bien la semántica
sigue siendo la misma. A continuación se muestran estos comandos tal y como
se encuentran en el archivo wave.do.
-29-
Ingeniería Electrónica.
add
add
add
add
add
add
add
add
add
add
wave
wave
wave
wave
wave
wave
wave
wave
wave
wave
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
-noupdate
-noupdate
-noupdate
-noupdate
-noupdate
-noupdate
-noupdate
-noupdate
-noupdate
-noupdate
-format
-format
-format
-format
-format
-format
-format
-format
-format
-format
Logic /testbench/rst_tb
Logic /testbench/clk_tb
Logic /testbench/dut/en1hz
Logic /testbench/lapso_tb
Literal /testbench/dut/state
Logic /testbench/dut/actualizar
Literal -radix unsigned /testbench/dut/cntunidades
Literal -radix unsigned /testbench/dut/cntdecenas
Literal /testbench/displayunidades_tb
Literal /testbench/displaydecenas_tb
Los comandos utilizados para cargar el diseño a simular y configurar la
ventana de formas de onda
se recogen en el script sim_funcional.do
proporcionado.
3.2.6. Avance y detención de la simulación.
Para provocar un avance de la simulación se emplea el comando run, siendo su
sintaxis:
run[<magnitud>[<unidades_tiempo>]] | <modo>
El tiempo a avanzar en la simulación se puede especificar de varias formas,
de acurdo a una serie de modos predeterminados. Una primera especificación
del tiempo de simulación es:
run[<magnitud>[<unidades_tiempo>]]
En este formato se avanza el tiempo especificado por el parámetro. Este
tiempo se da como un valor numérico seguido de unas unidades de tiempo
empleando para ello el formato descrito en la tabla 1.1. Si no se especifican
las unidades se entiende que el tiempo viene expresado en la resolución del
simulador (por defecto es 1ns). Por ejemplo, el siguiente comando provocaría
un avance en la simulación de 400 ns:
run 400ns
Otra forma de emplear el comando run responde al formato:
run<modo>
donde el parámetro <modo> puede ser uno de los siguientes valores:
!
!
!
!
!
-all Ejecuta la simulación indefinidamente hasta que ésta se detenga
debido a un punto de ruptura o a un error de simulación (sentencia
assert).
-step Avanza la simulación hasta la siguiente sentencia VHDL.
-stepover Es exactamente igual que la anterior salvo que las llamadas
a procedimientos o funciones se tratan como una única sentencia,
ejecutandose de una vez.
-continue
Continua la simulación desde el punto en que se detuvo
debido a un punto de ruptura.
-next Ejecuta la simulación hasta el siguiente evento.
Según esto el comando:
run -all
-30-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
ejecutaría la simulación del ejemplo hasta que se detuviera debido a la línea
del fichero testbench:
assert FALSE
report "Finalizacion controlada de la simulacion"
severity failure;
Para reiniciar la simulación, volviendo el tiempo a 0 ns, e iniciar una nueva
simulación se emplea el comando restart. Al ejecutar este comando aparece la
ventana mostrada en la figura 1.21. En ella se puede seleccionar qué
elementos mantendrán la configuración fijada durante la sesión de simulación
actual.
Figura 21: Ventana Restart.
Si durante la sesión de simulación se descubre un error de diseño que obliga
a modificar el código fuente será preciso finalizar la simulación mediante
el comando quit -sim. A continuación se modifica el código fuente, se compila
y se vuelve a cargandolo de nuevo tal y como se ha descrito.
3.2.7. Introducción de estímulos.
Normalmente los estímulos del diseño se introducen mediante el código del
fichero de banco de pruebas o testbencs. Sin embargo en un diseño típico el
sistema está compuesto por varios módulos más sencillos que se instanciarán
en el diseño final. Antes de obtener el diseño final será preciso validar los
módulos que lo componen. La realización de un banco de pruebas para cada uno
de estos módulos tan sencillos puede resultar una tarea tediosa. Para
solventar esta situación se puede emplear el comando force, que permite
introducir estímulos sobre las señales resueltas del diseño de una forma
sencilla. La sintaxis general de este comando es:
force <nombre_señal> <valor1> <tiempo1>, <valor2> <tiempo2> ...
Con este formato se introducen los estímulos especificados en pares (valor,
instante de tiempo) para la señal en cuestión. Cuando se trata de una señal
interna en el nombre se debe especificar el camino completo en la jerarquía
del diseño. Los valores a asignar a una deben ajustarse al tipo de datos de
misma. Los instantes de tiempo pueden expresarse en formato relativo al
instante actual de simulación o en valor absoluto respecto al origen de
tiempos (t=0). En este último caso se ha de añadir el prefijo @. Por defecto
las unidades en que se expresan los tiempos coincide con la resolución del
simulador (ns).
Existe un conjunto de
parámetros adicionales que permiten introducir
estímulos periódicos. Estos son:
-repeat <periodo>
Repite el comando force con el periodo de tiempo
especificado.
-31-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
-cancel <tiempo>
Cancela el comando force una vez transcurrido el
tiempo especificado.
A continuación se muestran varios ejemplos del uso de este comando.
force clr 0
Fuerza clr a 0 en el instante actual de
simulación.
force bus1 01XZ 100 ns
Fuerza bus1 a 01XZ 100 ns después del instante
actual de simulación.
force bus2 16#4F @200
Fuerza bus2 a 4Fh 200 unidades de tiempo
(especificadas por la resolución de simulación)
desde el inicio de ésta.
force clk 0 0, 1 25 -repeat 50
Genera una señal de periodo 50 ns con un ciclo
de trabajo del 50%
force clk 0 0, 1 20 -repeat 50
-cancel 1000
Fuerza clk a 0 en el instante actual de
simulación, 20 unidades de tiempo después pasa
a 1. Esto se repite cada 50 unidades de tiempo
hasta alcanzar 1000 unidades de tiempo. Por
tanto el siguiente 1 ocurrirá en la unidad de
tiempo 70.
Según lo expuesto para validar de forma individual el módulo prescaler se
emplearía la siguiente secuencia de comandos:
vsim work.prescaler
add
add
add
add
wave
wave
wave
wave
/prescaler/aclr
/prescaler/clk
/prescaler/q
/prescaler/thresh0
force aclr 1 0, 0 20
force clk 0 0,1 10 -repeat 20
Como se ha comentado este comando se emplea para aplicar estímulos a señales
resueltas. En el caso de que se aplique un estímulo a una señal interna del
diseño, la función de resolución determinará el estado que toma esta señal.
Existe un modo de operación de este comando denominado “modo congelado” que
permite imponer un valor a una señal interna. Esto es especialmente útil para
reducir el tiempo de simulación de un diseño.
Así, en el diseño considerado la salida del sistema cambia cada segundo, por
lo que para verificar el diseño se precisaría mucho tiempo de simulación.
Para reducirlo se forzará la salida del prescaler (señal EN1Hz) a 1 mediante
el comando:
force -freeze testbench/dut/EN1HZ 1
En el caso de utilizar la opción freeze con un comando force, para
desactivarla se debe ejecutar en comando noforce. Por ejemplo para el caso
anterior se utilizaría:
noforce
testbench/dut/EN1HZ 1
Resumiendo, para realizar la simulación del diseño se introducirá la
secuencia de comandos que se indica a continuación. Esta secuencia se
encuentra almacenada en el fichero de script sim_funcional.do proporcionado.
-32-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
# scrip de simulacion
destroy .wave
vsim work.cnf_funcional
# Definicion de se¤ales a visualizar.
add
add
add
add
add
add
add
add
add
add
wave
wave
wave
wave
wave
wave
wave
wave
wave
wave
/testbench/rst_tb
/testbench/clk_tb
/testbench/dut/en1hz
/testbench/lapso_tb
/testbench/dut/state
/testbench/dut/actualizar
-unsigned /testbench/dut/cntunidades
-unsigned /testbench/dut/cntdecenas
/testbench/displayunidades_tb
/testbench/displaydecenas_tb
run 400 ns
force -freeze testbench/dut/EN1HZ 1
run 50 us
Para realizar la simulación funcional del diseño, es algo tan sencillo como
ejecutar el comando:
do sim_funcional.do
La figura 1.22 muestra el aspecto de la pantalla de cronogramas obtenida al
ejecutar el comando anterior, donde se puede comprobar el funcionamiento
correcto del diseño.
Figura 22: Resultado de la simulación del cronómetro.
3.2.8. Análisis de resultados.
En este apartado se comentará como navegar por la ventana de cronogramas así
como la realización de mediciones de tiempos.
Para ajustar el zoom de la visualización se emplean las cuatro lupas que
aparecen en la barra de herramientas:
!
Zoom de acercamiento.
!
Zoom de alejamiento.
!
Amplia una zona de los cronogramas.
-33-
Ingeniería Electrónica.
!
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
Muestra la totalidad de los cronogramas.
Para realizar medidas de tiempo se emplean los cursores, un cursor se añade
con el elemento
. La primera vez que se pulsa este botón aparece el
cursor principal, que tal y como muestra la figura 1.23, éste aparece como
una línea azul de trazo grueso. Los cursores se pueden situar de forma manual
pulsando directamente sobre un punto de los cronogramas. En este caso el
cursor se sitúa sobre la transición más próxima al punto seleccionado. Si se
desean desplazar los cursores hasta la siguiente transición de la señal
seleccionada se emplean los botones
. Esto es especialmente útil para
las medidas de tiempos.
Las mediciones de tiempo se realizan utilizando un segundo cursor, para ello
se sitúan el cursor principal y el secundario sobre las dos transiciones, de
la misma u otra señales. Estas transiciones delimitan el tiempo a medir. El
segundo cursor se añade de igual forma que el primero, mostrándose en trazo
discontinuo. El tiempo medido se muestra en la parte inferior de la pantalla.
Finalmente para eliminar estos cursores se emplea el botón
.
Figura 23: Medida de tiempos.
3.2.9. Finalizar la sesión de simulación.
La simulación de un diseño permite comprobar el correcto funcionamiento del
mismo. Desde que se crean un diseño hasta que se van a realizar varias
simulaciones hasta depurar y obtener el código correcto, por lo que será
preciso finalizar la sesión de simulación, modificar el código fuente,
compilar y volver a simular.
Para finalizar la sesión de simulación se emplea el comando quit -sim. Notese
que el finalizar la sesión de simulación no supone cerrar ModelSim.
El uso de este comando tiene su interés cuando el código VHDL hace uso de
ficheros. Una práctica muy habitual es emplear fichero del cual se toma la
secuencia de estímulos (vectores de test) a aplicar al diseño. Por ejemplo
en el caso de sistemas de tratamiento digital de señal implementados en
FPGAs, el bando de pruebas puede obtener los datos a procesar desde un
fichero previamente creado mediante Matlab. De forma similar los resultados
del procesamiento se pueden almacenar en un fichero de salida para su
posterior análisis. En este caso, el simulador abre el ficheros de salida al
cargar la unidad de diseño a simular, manteniendo el control sobre éste por
lo que no se puede acceder a su contenido hasta que no finalice la sesión de
simulación. En ese momento el fichero de salida puede abrirse con otra
herramienta.
-34-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
3.3. PUNTOS DE RUPTURA.
Una de las posibilidades más empleadas en los simuladores son los puntos de
ruptura (breakpoints). ModelSim permite trabajar con dos tipos de puntos de
ruptura. El primero de ellos se fija sobre las líneas de código de la ventana
de código fuente (source). Este tipo de puntos de ruptura se asemeja al
empleado por los depuradores de software. Para activar un punto de ruptura
de este tipo basta con pulsar con el ratón sobre la línea en la que queremos
poner el punto de ruptura. Para desactivarlo basta con una nueva pulsación.
Cuando se ejecuta la línea de código marcada se detiene la simulación.
Esto también se puede realizar mediante el comando bp. El formato empleado
es:
bp <nombre_fichero> <número_de_línea>
El segundo formato, denominado condicional, se asemeja al concepto empleado
por un simulador digital, permitiendo asociarlo a señales., para ello se
utiliza el comando when, cuya sintaxis es:
when [-label <nombre>] {<expresión_condición>} {<acción>}
El parámetro -label asigna el identificador <nombre> al punto de ruptura
definido. El parámetro <expresión_condición> define la condición a evaluar
en el punto de ruptura. Cuando esta expresión es cierta se dispara el punto
de ruptura. La sintaxis de esta expresión responde al siguiente formato:
subexpresión1 operador_lógico subexpresión2 operador_lógico
subexpresión3...
Las subexpresiones vienen dadas por operadores relacionales y atributos de
detección de eventos. Los siguientes ejemplos muestran las situaciones
admitidas.
!
!
!
Igualdad.
Desigualdad
Detección de eventos:
clk = ’1' ó clk==’1'
bus1 /= “0000"
clk’EVENT
Los operadores de igualdad y desigualdad sólo admiten como segundo parámetro
un literal, es decir no se puede comparar el estado de dos señales. Los
operadores lógicos que ligan las subexpresiones pueden ser el operador and
o el operador or. En la expresión condicional se admite el empleo de
paréntesis para establecer la prioridad con que se evalúan las distintas
subexpresiones.
El parámetro <acción> define la secuencia de comandos a del simulador a
ejecutar cuando se dispara el punto de ruptura. Este parámetro es opcional,
si no se indica la acción a realizar consiste en detener la simulación.
Por ejemplo, para simular el prescaler se podría utilizar los siguientes el
siguientes comandos
force aclr 1 0, 0 20
force clk 0 0,1 10 -repeat 20
run 30
when -label pto1 { thresh0'event} {stop}
run -all
-35-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
De forma, la simulación se realizará hasta que se detecte una transición en
la señal thresh0, o lo que es lo mismo cuando thresh0 pase a ‘1'.
Para borrar un punto de ruptura de este tipo se emplea el comando nowhen,
cuya sintaxis es:
nowhen <identificador>
Por ejemplo para borrar el punto de ruptura definido en el ejemplo se emplea
el comando:
nowhen pto1
3.4. METODOLOGÍA DE TRABAJO.
En la descripción realizada a cerca del manejo del simulador se ha hecho
especial incapié en su uso mediante comandos, obviandose el uso del interface
gráfico. Aparentemente el uso de comandos puede parecer más complejo debido
al esfuerzo inicial que supone la creación de estos ficheros. Pero hay que
tener en cuenta que en raras ocasiones se obtiene a la primera un diseño
totalmente correcto. En tal caso la verificación del diseño mediante
simulación se convierte en un proceso iterativo consistente en modificar el
código fuente, compilarlo, simular y observar los resultados. Mediante el uso
de ficheros de scripts esto se reduce a seleccionar mediante el “doskey” de
la consola la secuencia de comandos:
do compila.do
do simula.do
quit -sim
....
do compila.do
A esto hay que añadir que este esfuerzo inicial que supone la creación de los
ficheros de script se ve recompensado por la facilidad de poder
reutilizarlos. Así los scripts creados para la simulación funcional se pueden
reutilizar con leves modificaciones en la simulación temporal. Además en su
formato básico no varían demasiado de un diseño a otro, por lo que también
se suelen reutilizar en este caso.
3.5. UTILIZACIÓN DEL INTERFACE GRÁFICO
Como se comentó con anterioridad, los diferentes comando también se pueden
seleccionar por los iconos o elementos de la barra de herramientas. A
continuación se van a ver algunos de ello.
Permite selecciona el o los
archivo a compilar (comando vcom). Cuando
se activa se accede a la pantalla de la figura 1.24, donde se selecciona el archivó VHDL
a compilar. Haciendo uso de las teclas SHIFT y CTRL se pueden seleccionar más de un archivo,
teniendo en cuenta que se deben seleccionar en orden ascendente de la jerarquía
-36-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
Figura 24: Compilación de archivos VHDL.
Un campo importante de la figura anterior es el de las Default Options (figura 1.25), donde se
selecciona, entre otras cosas , el estándar VHDL utilizado.
Figura 25: Opciones de compilación.
Permite seleccionar la unidad VHD a simular (comando vsim). Cuando se selecciona se
accede a la pantalla de la figura 1.26, donde se selecciona la unidad a simular.
-37-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
Figura 26: Selección de la unidad de diseño a simular.
En la barra de herramientas se encuentran otros iconos que permiten controlar el avance del tiempo
del simulador, a continuación se detallan:
Permite selecciona la cantidad de tiempo que avanza la simulación
cuando se ejecuta el comando run.
run.
run -continue
run -all
Parar la simulación (break).
run - step
run - step over
restart
Merece la pena hacer incapie en la utilización del menú help para acceder a una colección de
archivos en formato pdf que van desde un manual de ModelSim hasta la explicación de la semántica
y sintaxis de todos los comandos.
4. SÍNTESIS DEL DISEÑO.
-38-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
Una vez realizada la simulación funcional del diseño descrito en VHDL se
procederá a sintetizarlo. Para ello se empleará como herramienta de síntesis
VHDL el sintetizador Leonardo Spectrum de Exemplar.
4.1. OPERACIÓN INTERNA DEL SINTETIZADOR.
Antes de proceder a la síntesis del diseño se mostrará el funcionamiento
interno de este sintetizador. Esto facilitará la compresión de su manejo. Tal
y como muestra la figura 1.28 la síntesis RTL se divide en las siguientes
fases:
!
!
!
análisis.
elaboración.
optimización.
Jerarquía
del diseño
Diseño RTL a nivel de puertas.
Análisis de caminos críticos.
Optimización
temporal
.work
.work
Análisis
Diseño VHDL
compilado en
memoria
Elaboración
RTL
(diseño con
puertas genéricas)
OPTIMIZACIÓN
Diseño mapeado en
la tecnología destino
DISEÑO EN MEMORIA
ESCRITURA
LECTURA
VHDL
VHDL
EDIF
XNF
Ficheros de lista de
conexiones de salida.
EDIF
Ficheros fuente.
Diseño en celdas de la tecnología destino.
HERRAMIENTAS
SIMULADOR
DE IMPLEMENTACIÓN
VHDL
Figura 28: Proceso de síntesis.
Durante la fase de análisis se verifica la sintaxis del fichero VHDL, se
comprueban las dependencias y se resuelven los genéricos que pudieran
aparecer en el código fuente. A partir de los ficheros analizados el
sintetizador construye una base de datos interna del diseño. Si alguno de los
ficheros fuente hace referencia a elementos que aperecen en librerías o
paquetes propios del diseñador estos deben ser procesados previamente. Muchas
librerías y paquetes standard están integrados en el propio sintetizador y
no necesitan ser procesados explícitamente.
En la fase de elaboración, se sintetiza el código VHDL en una lista de
conexiones compuesta por funciones lógicas genéricas y cajas negras asociadas
a los operadores. Estas funciones lógicas genéricas son primitivas propias
del sintetizador (no de la FPGA), a partir de las cuales se construye el
diseño sintetizado. Se trata pues, de un formato intermedio previo al mapeado
tecnológico en el que estas primitivas se sustituirán por las celdas propias
de la tecnología destino. Esto permite que una misma herramienta de síntesis
se pueda utilizar con distintas tecnologías destino.
Posteriormente, estas cajas negras asociadas a operadores se sustituirán con
operadores implementados específicamente para la tecnología destino. En
-39-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
muchas ocasiones es el propio fabricante de los dispositivos para los que se
sintetiza el circuito el que proporciona estos operadores en forma de una
librería de macroceldas parametrizables. Este tratamiento diferenciado que
se da a los operadores se debe a que las herramientas de síntesis no son muy
eficientes a la hora de procesar la lógica aritmética y relacional
(denominada normalmente lógica del data path). Esto es especialmente cierto
para las FPGAs, donde cada tecnología destino tiene distintas formas de
optimizar el uso de sus recursos internos.
Un diseño VHDL puede estar formado por uno o varios ficheros fuente VHDL.
Además muchos sintetizadores permiten incorporar partes del diseño como
componentes descritos mediante una lista de conexiones en la que aparecen
celdas de la tecnología para la que se va a sintetizar. Estos componentes se
instanciarán en el código fuente VHDL donde se vayan a utilizar mediante
descripciones estructurales. Los sintetizadores pueden admitir formatos de
listas de conexiones standard como EDIF, o propios de la herramienta de
implementación de la tecnología para la que se va a sintetizar.
Un ejemplo de esto último es el formato XNF de Xilinx. La posibilidad de
describir parte del diseño en este formato permite reutilizar partes de un
diseño anterior realizado mediante esquemas. Para ello sería necesario
generar una lista de conexiones en formato XNF de estos esquemas. Para
facilitar la migración de estos diseños algunos sintetizadores como Express
de Synopsys disponen además de bibliotecas de macros expresadas como listas
de conexiones en formato XNF que corresponden a las macros que aparecen en
las librerías de captura de esquemas.
Internamente los sintetizadores almacenan los datos de un diseño en librerías
cuyo formato depende de la cada herramienta. Así la herramienta “Leonardo
Spectrum” utiliza un formato similar al EDIF. La forma en que las distintas
partes del diseño se almacena es estas librerías internas es la siguiente:
!
Librería de la tecnología destino. Al fijar en el sintetizador la
tecnología destino para la que se va a sintetizar, éste carga
automáticamente una librería que contiene todas las celdas de esa
tecnología. Los componentes contenidos en esta librería pueden ser
instanciados en el código VHDL para sacar partido a las características
de la arquitectura del dispositivo para el que se va a sintetizar. Un
ejemplo de esto sería el uso del oscilador interno de la familia
Spartan XL de Xilinx.
!
Librerías de trabajo. Al cargar una descripción VHDL o una parte del
diseño expresada como una lista de conexiones las entidades contenidas
en éstas quedan almacenadas por defecto en la librería work, si bien
es posible, si se desea, definir otra librería como destino.
!
Librería de primitivas. El sintetizador crea automáticamente una
librería de primitivas que contiene todas las funciones lógicas básicas
o primitivas que emplea el sintetizador cuando compila o elabora el
código VHDL. Mediante diseño estructural se pueden instanciar estos
componentes independientes de la tecnología (aunque dependen del
sintetizador empleado).
Librería de operadores. El sintetizador también crea una librería de
operadores. Esta librería contiene celdas de operadores (sumadores,
multiplicadores, multiplexores, etc). Al compilar una descripción VHDL
estos operadores se generan cuando es preciso.
!
Una vez finalizada la síntesis RT, se procede a realizar la síntesis lógica.
En esta fase, las herramientas de síntesis permiten imponer restricciones
temporales al diseño. Estas restricciones pueden controlar el proceso de
mapeado tecnológico y la optimización. Durante la optimización se persigue
-40-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
la obtención de implementaciones con el menor área posible y el cumplimiento
de restricciones temporales en aquellos caminos críticos en que han sido
fijadas estas restricciones, dando lugar a un sistema rápido y que ocupa los
menos posibles recursos de la FPGA.
También es posible imponer restricciones topológicas que permitan guiar a la
herramienta de implementación durante el proceso de emplazamiento e
interconexionado. Por ejemplo, desde la propia herramienta de síntesis se
puede asignar los pads que infieren los puertos de la entidad de nivel
superior a terminales del dispositivo sobre el que se va a implementar el
diseño.
Finalmente el sintetizador genera una lista de conexiones, es decir, un
modelo estructural que contiene solamente referencias a celdas lógicas de
la tecnología destino. Esta lista de conexiones será utilizada por la
herramienta de implementación para realizar el emplazamiento e interconexión
y de esta forma proceder a la implementación del diseño sobre un dispositivo
físico. No existe un formato standard para esta lista de conexiones, pero el
más extendido es el formato EDIF. Algunas herramientas de síntesis para FPGAs
producen listas de conexiones en un formato propio de la tecnología para la
que se está sintetizando. Tal es el caso del sintetizador Leonardo Spectrum
que puede generar una lista de conexiones en formato .XNF para posteriormente
compilarlo con las herramientas de implementación de Xilinx, aunque éstas
también interpretan el formato EDIF.
Por otra parte, es posible que el sintetizador genere esta lista de
conexiones como una descripción estructural VHDL lo que validar el resultado
de la síntesis con los mismos bancos de prueba utilizados con la descripción
RTL original. Es lo que normalmente se conoce como simulación post-síntesis
pre-implementación.
Ciertos aspectos del proceso de síntesis se pueden controlar mediante
directivas que aparecen en el propio código fuente. Se trata de directivas
que aparecen como comentarios de forma que sólo son reconocidas por el
sintetizador siendo ignoradas por los simuladores. A este tipo de directivas
se les denomina pragma (comentarios sintéticos o metacomentarios). Su formato
depende de cada herramienta de síntesis en particular, por ejemplo:
-- synopsys translate_off
.........
-- synopsys translate_on
En otras ocasiones se emplean atributos para controlar el proceso de
síntesis. Cada sintetizador define sus propios atributos. Al analizar el
código fuente VHDL, el sintetizador reconoce automáticamente dichos atributos
operando según proceda. Por ejemplo, Leonardo Spectrum al detectar el
atributo pull aplicado sobre un puerto de entrada instancia una resistencia
de pull-up o pull-down entre el IPAD y el IBUF asociado a dicho puerto. El
tipo de resistencia a emplear depende del valor del atributo. Por ejemplo,
para fijar una resistencia de pull-up en los puertos de los pulsadores de
nuestro diseño se emplearía el siguiente código:
attribute pull:string;
attribute pull of rst,lapso:signal is "pullup";
4.1.1. Generadores de módulos.
-41-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
Como se ha comentado anteriormente las herramientas de síntesis no son
eficientes a la hora de procesar la lógica aritmética y relacional
aparece en el data path, siendo especialmente problemático en el caso de
FPGAs, donde cada tecnología tiene una forma distinta de optimizar
implementación de estos operadores.
muy
que
las
la
Con el fín de obtener resultados óptimos, el diseñador podría optar por
utilizar
macros
hard (p.e. módulos generados mediante COREGEN) o soft
(ficheros de listas de conexiones) proporcionadas por el fabricante de FPGAs
para implementar este tipo de lógica. Esta macro aparecería como un
componente instanciado en el código fuente. Sin embargo la instanciación de
componentes plantea los siguientes inconvenientes:
!
!
!
La descripción del diseño deja de ser comportamental.
El código VHDL se convierte en dependiente de la tecnología.
La instanciación de componentes no está permitida en la definición de
operadores o funciones.
Normalmente los sintetizadores disponen de generadores de módulos
incorporados que proporcionan al diseñador un mecanismo de sobrecarga de los
operadores del data path, como por ejemplo para las funciones “+”, “-” y
“>”, con implementaciones prediseñadas específicas de una tecnología. Esta
generación se realiza atendiendo al tamaño (número de elementos) de los
operandos. Normalmente los sintetizadores soportan los siguientes operadores:
!
!
!
!
!
!
Multiplicador (operador * ).
Sumador, restador y sumador/restador (operadores + y -).
Incremento, decremento e incremento/ decremento (operadores + y -).
Complemento a dos (operador unario -).
Comparador (operadores relacionales <, <=, >, >=, =, /=, ==, !=).
Multiplexor (estamentos de selección).
Puesto que los algoritmos de generación de módulos son específicos para cada
familia de FPGAs soportada, las prestaciones y el área de estos módulos se
optimizan específicamente para dicha arquitectura, igualando los resultados
obtenidos con las macros proporcionadas por el fabricante. Al mismo tiempo,
permite al diseñador describir la lógica con un estilo de comportamiento
puro.
El hecho de que estos módulos sean generados por el propio sintetizador le
permite optimizar la lógica obtenida junto con la que aparece alrededor del
módulo, con lo que la lógica resultante es menor y más rápida. Esto no es
posible con macros hard ya que dichos componentes aparecen como cajas negras
en el código sintetizado. Además el sintetizador puede aplicar algoritmos de
compartición de recursos, con lo que se puede optimizar aún más el circuito.
La figura 1.29 muestra el flujo de datos general en el entorno de generación
de módulos. Una vez que se ha analizado con éxito el código fuente, se pasa
al motor de inferencia que compara los operadores soportados con las
implementaciones prediseñadas de la librería de generación de módulos. Cada
vez que se encuentra en el código fuente un operador soportado, se consulta
la librería de generación de módulos específicos de la tecnología. Si se
encuentra una implementación, se utiliza en el diseño. En caso contrario, el
sintetizador proporciona la implementación lógica por defecto de ese
operador. Por ejemplo, si no se dispusiera de un módulo del operador suma
para la tecnología destino, se podría generar un sumador con acarreo serie
mediante lógica combinacional.
-42-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
Código
fuente VHDL
Analizador
sintáctico VHDL.
Motor de inferencia
para generación
de módulos.
genéricos
módulo
Librería de
generación
de módulos
Síntesis,
optimización
y mapeado.
Lista de conexiones
para FPGA
Figura 29: Generador de módulos.
4.2. MANEJO DEL SINTETIZADOR.
Una vez descrita la forma en que opera internamente el sintetizador, se
pasará a exponer la forma de utilizar esta herramienta. Para ejecutar el
sintetizador seleccionese la opción:
Inicio
º Programas
º LeonardoSpectrum º LeonardoSpectrum
mostrandose la ventana que muestra la figura 1.30. Esta ventana permite fijar
el nivel de operación del sintetizador. El nivel de operación determina el
control que tendrá el usuario sobre el proceso de síntesis: a mayor nivel
mayor control.
Figura 30: Selección del nivel de
operación.
Seleccione el nivel 3 y pulse el botón OK. Con esto se entra en la ventana
principal del sintetizador cuyo aspecto se muestra en la figura 1.31.
-43-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
Barra de
menús
Barra de
herramientas
Pestañas
de flujo
Ventana de
flujo de diseño
Ventana de
comandos
Línea de estado
Figura 31: Ventana principal del sintetizador.
Los principales elementos que aparecen en esta ventana son:
!
Una barra de menús desde la que es posible seleccionar las distintas
opciones que controlan el funcionamiento del sintetizador.
!
Una barra de herramientas que permite acceder directamente a las
opciones que se emplean con mayor frecuencia.
!
Una línea de estado. Proporciona cierta información como el estado del
sintetizador, directorio de trabajo, etc.
!
Una ventana de flujo de diseño con la que controlan las distintas fases
del proceso de síntesis y se fijan las opciones de éstas. Cada fase
tiene una pestaña asociada. Con esta ventana se realiza la síntesis
mediante un interface gráfico.
!
Ventana de comandos. Otra forma de controlar el proceso de síntesis es
mediante la ejecución de comandos. De hecho ésta es la forma básica de
operación del sintetizador mientras que la ventana de flujo de diseño
es un mero “caparazón” gráfico desde que se invocan los comandos
necesarios. La ventana de comandos se divide en dos partes. La parte
inferior es una consola desde la que se introducen los comandos,
mientras que la información referente a su evolución se muestra en la
parte superior de esta ventana.
Como se ha comentado, el proceso de síntesis se puede controlar mediante una
interface gráfica (ventana de flujo de diseño) o mediante comandos (ventana
de comandos). El uso de uno u otro método depende de las preferencias
personales de cada usuario. En cualquier caso es obvio que el primer método
resulta más intuitivo pero permite un control menos exhaustivo del proceso
de síntesis y resulta tedioso su manejo cuando la complejidad del diseño es
elevada. Algunos diseñadores aducen en contra del empleo de comandos que
resulta complicado aprenderse toda una serie de nuevos comandos. A este
respecto hay que indicar que para un control básico del proceso de síntesis,
el conjunto de comandos a emplear es bastante reducido, siendo posible además
almacenar la secuencia de comandos a emplear en un fichero de scripts y
-44-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
ejecutarlos conjuntamente tal y como se hizo en el simulador. Por estos
motivos se expondrá el manejo del sintetizador mediante comandos,
describiendo los comandos a emplear en cada una de las fases del proceso de
síntesis.
En el caso de que el usuario opte por la ejecución de la síntesis desde el
interface gráfico, a medida que se ejecuta cada herramienta en la ventana de
comandos se van listando los comandos a los que corresponde dicha
herramienta, con lo que con una simple operación de selección y copy-pastes,
se puede obtener de una forma sencilla el scrip para la síntesis.
4.2.1. Inicialización del sintetizador.
Para sintetizar un nuevo diseño en primer lugar es preciso inicializar el
sintetizador, borrando el contenido de las librerías internas y fijando el
directorio de trabajo actual. Esta operación se realiza mediante el comando:
clean_all
El directorio de trabajo actual para nuestro ejemplo será c:/tutorial/.
4.2.2. Selección de la tecnología destino.
En primer lugar es preciso cargar la librería de la tecnología destino
(familia Spartan2 de Xilinx), seleccionando a continuación el dispositivo en
concreto para el que se va a sintetizar (XC2S50TQ144), la velocidad de éste
(-6) y la estimación de retardos debidos a interconexiones (ésta se calcula
en función del número de entradas conectadas a cada salida pudiendose dar
como valor promedio o para el peor caso). Esta información temporal es
empleada durante la optimización del diseño.
Una forma sencilla de realizar estas operaciones es mediante el uso del
interface gráfico. Para ello seleccione la herramienta de síntesis avanzada
pulsando el botón
de la barra de herramientas.
Tal y como se muestra en la figura anterior, mediante la pestaña Technology
se pueden seleccionar las opciones citadas. Con el árbol que aparece a la
izquierda se selecciona la familia en cuestión (familia Spartan2 de Xilinx),
la opción Device se emplea para seleccionar el dispositivo (XC2S50TQ144),
el grado de velocidad se fija con la opción Speed (-6) y finalmente la opción
Wire Load la forma de estimar los retardos debidos a interconexiones. Una vez
realizadas estas operaciones, al pulsar el botón Load Library se desencadena
la ejecución de los comandos necesarios para configurar el sintetizador. Esta
secuencia de comandos se muestra en la ventana de comandos. De entre todos
los comandos mostrados (existen algunos cuyo uso es irrelevante) los que
realizan las operaciones mencionadas son:
load_library xisxl
set part S10xlPC84
set process 4
set wire_table s10xl-4_avg
4.2.3. Selección del método de codificación de las máquinas de estados.
El lenguaje VHDL no define la forma en que se codifican los tipos enumerados.
Si el diseño contiene máquinas de estado es preciso indicar como se
codificará el tipo enumerado que define el estado de la máquina.
Estas cuestiones relacionadas con el funcionamiento interno del sintetizador
se pueden configurar mediante variables o atributos internos de la
-45-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
herramienta. Como es lógico, estas variables y atributos internos dependen
de cada herramienta en cuestión, variando de unas a otras.
Las variables internas se emplean su uso debe afectar a la totalidad del
diseño, fijandose el valor de dichas variables mediante el comando set. Por
otro lado, los atributos internos se emplean cuando su uso debe afectar a un
elemento concreto del diseño (p.e. un tipo enumerado, una señal, un
componente, etc). En este caso el comando a emplear se denomina
set_attribute. La mayoría de los atributos internos del sintetizador (¡no
todos!) se pueden fijar en el propio código fuente. Un ejemplo de esto es el
atributo pull utilizado en el ejemplo para fijar las resistencias de pull-up
de los pulsadores.
Volviendo a la cuestión del tipo de codificación de los tipos enumerados,
este sintetizador soporta los siguientes tipos de codificación:
!
Binario. Genera máquinas de estados con el menor número de biestables
posible.
!
Gray. Con este tipo de codificación sólo conmuta un biestable en las
transiciones de la máquina.
!
Aleatorio (ramdom). Asigna los códigos de estado de forma aleatoria.
Este tipo sólo se debe utilizar si los restantes tipos no proporcionan
los resultados adecuados.
!
One Hot. Con este tipo de codificación se emplea un biestable para cada
estado de la máquina, proporcionando las mejores prestaciones en cuanto
a consumo de recursos y máxima frecuencia de funcionamiento. Si bien
el número de biestables empleado en la codificación one-hot es mayor
que en la binaria, es preferible su uso en dispositivos programables
cuya arquitectura dispone de un gran número de biestables. Tal es el
caso de las FPGAs de Xilinx.
Para fijar de forma global el tipo de codificación se emplea la variable el
comando set encoding cuyo formato es:
set encoding <tipoo
donde tipo puede ser binary, onehot, twohot, gray, random o auto. Por ejemplo
para seleccionar una codificación one hot en nuestro ejemplo se emplea el
comando:
set encoding onehot
Para indicar de forma explícita la codificación utilizada por un determinado
tipo de datos se utiliza el atributo es TYPE_ENCODING. De esta forma es
posible asignar individualmente el código a cada estado de la máquina. Antes
de asignar este atributo al tipo enumerado es preciso declararlo. Así para
nuestro ejemplo, si se desea asignar el código 00 al estado S1, el 01 al S2,
el 11 al S3 y 10 al S4 se emplearía el siguiente código:
-46-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
..
-- Declaración del atributo TYPE_ENCODING:
type exemplar_string_array is array (natural range <>,natural range <>) of character;
attribute TYPE_ENCODING : exemplar_string_array ;
-- Estados de la FSM que
type stateFSM is (
S1,
S2,
S3,
S4);
signal state: stateFSM;
controla el sistema.
-----
RunningWaitingOnPush
RunningWaitingOnRelease
FrozenWaitingOnPush
FrozenWaitingOnRelease
-- Asignación del atributo type-encoding.
attribute TYPE_ENCODING of state:type is ("00","01","11","10") ;
...
4.2.4. Lectura de ficheros del diseño.
Una vez seleccionada la tecnología destino para la que se va a sintetizar,
se han de leer los ficheros VHDL que componen el diseño. El orden en que se
leen estos ficheros dependerá de las dependencias que existen entre ellos.
Así si uno de ellos define una unidad de diseño que es utilizada en otro de
ellos el primero de ellos debe leerse antes que el segundo. Por tanto el
orden de lectura suele coincidir con la posición que ocupan en la jerarquía
del diseño, leyendose en primer lugar el de nivel inferior. Según esto para
el ejemplo considerado el comando a emplear es:
read {../BCD2SEG.vhd ../crono.vhd}
Notese que no se indican ni los ficheros de los módulos COREGEN (son modelos
de simulación), ni los del banco de pruebas y el fichero de configuración
asociado (soló se emplea en simulación para introducir los estímulos al
diseño).
Al realizar la lectura de un fichero el sintetizador analiza el código
fuente. Si aparece algún mensaje
de error este aparece marcado con un
circulo rojo en la parte superior de la ventana de comandos. Haciendo doble
click con el ratón sobre dicho círculo aparece una ventana que muestra el
código fuente que produjo dicho error. La figura 1.32 muestra esto. Esto
mismo es aplicable a los avisos (warnings), salvo que en este caso el círculo
es de color azul.
Figura 32: Búsqueda automática de errores en el código fuente.
Para seleccionar de los archivos, mediante el interface gráfico se utiliza
la pestaña Imput(
), apareciendo la ventana de la figura 1.33
-47-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
Figura 33: Selección de archivos.
Con las pestañas Work Directory y Open files se seleccionan los archivos VHDL
a sintetizar, utilizando para ello un orden creciente en la jerarquía de
diseño. A continuación se selecciona el tipo de codificación para los estados
de las máquinas de estados (Encoding Style). Para finalizar se pulsa la
pestaña read.
4.2.5. Selección del diseño actual.
Los distintos ficheros leídos proporcionan unidades de diseño que el
sintetizador almacena internamente en las librerías de trabajo (por defecto
work). Antes de realizar la síntesis propiamente dicha es preciso indicar el
par entidad-arquitectura de mayor jerarquía del diseño que se va a
sintetizar. La sintaxis empleada es:
nombre_librería.nombre_entidad.nombre_arquitectura.
Según esto para nuestro diseño el comando a emplear será:
present_design .work.cronometro.inside
4.2.6. Configuración de opciones de optimización.
Una vez leídos los ficheros que componen el diseño estos se analizan y
elaboran. El siguiente paso consistiría en realizar la optimización de la
síntesis. Previamente a esta última operación habrá que fijar las
restricciones a aplicar al proceso optimización. Al igual que ocurre con el
tipo de codificación de los tipos enumerados las restricciones se pueden
aplicar de forma global mediante variables internas o de forma particular
mediante atributos internos. Las restricciones impuestas desde el
sintetizador se exportan a las herramientas de implementación mediante un
fichero de restricciones en formato nativo (.ncf) que acompaña a la lista de
conexiones que genera el sintetizador.
Como se ha comentado estas restricciones pueden ser topológicas o temporales.
Un ejemplo del primer caso consistiría en la asignación del IOB asociado a
-48-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
un puerto de la entidad de mayor jerarquía a un terminal concreto de la FPGA.
Para esto se puede emplear el siguiente comando:
set_attribute -port {.work.cronometro.inside.rst} -name PIN_NUMBER -value P28
En cualquier caso, ha de destacarse que este tipo de restricciones también
es posible aplicarlas desde la herramienta de implementación de Xilinx
mediante un fichero de restricciones de usuario (.ucf). La elección del
método dependerá de las preferencias del diseñador.
En cuanto a las restricciones temporales es posible imponer el retardo máximo
admisible entre dos puntos del diseño. Si esta restricción no se cumple el
sintetizador puede elegir otra estrategia de síntesis. Por ejemplo para el
caso de un sumador se puede optar por sintetizarlo con acarreo paralelo
frente a una implementación con acarreo serie.
Al igual que en el caso de las restricciones topológicas, las restricciones
temporales también se pueden fijar durante la implementación. Sin embargo en
este caso es deseable hacerlo durante la síntesis ya que estás pueden
determinar la lógica inferida, de forma que si ésta no es óptima los
esfuerzos realizados por las herramientas de implementación para buscar el
emplazamiento más adecuado de los CLBs pueden resultar vanos.
Las restricciones temporales pueden ser globales o individuales. Las primeras
se aplican a la totalidad del diseño, siendo éstas las más fáciles de
utilizar. Tal y como muestra la figura 1.34 existen cuatro tipos de
restricciones globales. Para fijar estas restricciones Leonardo define cuatro
variables internas. Estas son:
!
!
!
!
input2reg. Indica el máximo retardo admisible entre los puertos de
entrada y el primer registro del diseño. En este tiempo se incluye el
tiempo de set-up de los biestables.
register2register. Indica el máximo retardo admisible entre los dos
registros del diseño. En este tiempo se incluye el tiempo de
propagación de los biestables del registro de salida y el de set-up de
los de entrada.
register2output. Indica el máximo retardo admisible entre los registros
y los puertos de entrada. En este tiempo se incluye el tiempo de
propagación de los biestables del registro de salida.
input2output. Indica el máximo retardo admisible entre los dos puertos
conectados únicamente por lógica combinacional.
-49-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
input2register
Bloque
combinacional
data_in
register2register
D Q
A
Bloque
combinacional
B
register2output
D Q
Bloque
combinacional
data_out
C
FF1
FF2
clk
clk
clock
Bloque
combinacional
D
data_in
data_out
output2output
Figura 34: Uso de restricciones temporales globales.
Para fijar estas restricciones se emplea el comando
set <variable> <valor>
donde <valor> es el tiempo de retardo máximo expresado en ns. Así por ejemplo
para garantizar que nuestro diseño pueda funcionar al menos a una frecuencia
de 10 MHz (T= 100 ns) se emplearían los siguientes comandos:
set
set
set
set
register2register 100
input2register 100
register2output 100
input2output 100
El otro tipo de restricciones permite fijar individualmente a cada uno de los
puertos el máximo retardo admisible. A este tipo de restricciones se les
denomina restricciones de puertos y se suelen emplear para optimizar aquellas
señales de temporización más crítica. El sintetizador impone una serie de
limitaciones a la hora de fijar las restricciones de puertos. Concretamente
en el análisis temporal no se toman en consideración los caminos de señal que
afectan a las señales de inicialización asíncrona (reset y preset) de los
biestables. Tampoco se permite fijar restricciones temporales en diseños con
varios relojes asíncronos. Sin embargo, si es posible el análisis de diseños
con varios relojes síncronos (diseños multifase). Aun así la variedad de
situaciones que se pueden abordar con las restricciones es muy amplia por lo
que nos limitaremos a exponer aquellas que aparecen en diseños síncronos con
una única señal de reloj. La figura 1.35 ilustra el uso de las restricciones
individuales. A continuación se describirán estas restricciones.
-50-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
input_arrival
clock_cycle
DATA_IN
Bloque
combinacional
Circuito externo
virtual
D
Q
D Q
A
Bloque
combinacional
Bloque
combinacional
B
required_time
D Q
Bloque
combinacional
DATA_OUT
C
FF1
FF2
clk
clk
FF
DATA_OUT2
clk
CLK
pulse_cycle
pulse_width
CLK
DATA_IN
input_arrival
required_time
DATA_OUT
Figura 35: Modelado de restricciones individuales.
!
clock_cycle define el periodo máximo (frecuencia mínima ) admisible de
la señal de reloj del bloque. Este periodo vendrá dado por la suma del
retardo de la salida de los biestables, el tiempo de propagación de la
lógica combinacional y el tiempo de set-up de la entrada de los
biestables.
!
pulse_width permite modelar el ciclo de trabajo de la señal de reloj.
!
arrival_time define la demora respecto al flanco de reloj con que
llegan los datos a la entrada del bloque.
!
required_time define la demora máxima admisible desde el flanco de
reloj hasta que los datos aparecen estables en el puerto de salida.
Para fijar estas restricciones se emplean los siguientes comandos:
clock_cycle <periodo_reloj> <puerto_señal_reloj>
pulse_width <ancho_pulso_reloj> <puerto_señal_reloj>
arrival_time <valor_retardo> <lista_puertos_entrada>
required_time <tiempo_necesario> <lista_puertos_salida>
Los primeros parámetros de estos comandos son valores de tiempo expresados
en ns. Las lista de puertos se expresan como una lista de nombres entre
llaves separadas por espacios. Como ejemplo se mostrarán los comandos a
emplear para el circuito de la figura anterior bajo las siguientes
suposiciones:
!
!
!
!
!
Frecuencia mínima de funcionamiento:
10 MHz.
Ciclo de trabajo de la señal de reloj:
25 %
Tiempo de demora máximo de los datos de entrada:
12 ns
Máximo retardo admisible en salidas secuenciales:
5 ns
Máximo retardo admisible en salidas combinacionales: 10 ns
Según esto los comandos a emplear serían:
clock_cycle 100 clk
pulse_width 25 clk
-51-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
arrival_time 12 {DATA_IN}
required_time 5 {DATA_OUT}
En el modelado de una salida puramente combinacional, como es el caso de la
señal DATA_OUT2,
el tiempo necesario será la suma de la demora de las
entradas más el máximo retardo admisible de estas salidas:
required_time 22 {DATA_OUT2}
Para acceder a las opciones de optimización desde el interface gráfico se
utiliza la pestaña
, accediendo a la ventana de restricciones. Para generar las
restricciones de cada uno de los elementos antes comentados se actúa sobre
las pestañas mostrados en la figura 1.36 que se encuentra en la parte
inferior de dicha ventana.
Figura 36: Selección de las restricciones para la síntesis
4.2.7. Optimización del diseño.
La optimización del diseño se realiza mediante el comando optimize, o con la
pestaña
. Su sintaxis es:
optimize
[<design_name>]
[-target <technology_name>]
[-io_target <technology_name>]
[-single_level]
[-effort <effort_type>]
[-chip]|[-macro]
[-area]|[-delay]|[-auto]
[-pass <pass_nums>]|[-nopass <pass_nums>]
[-hierarchy <auto|preserve|flatten>]
El primer parámetro especifica el diseño a optimizar. Si no se especifica,
éste corresponde al diseño actual. Ésta suele ser la situación típica, si
bien para diseños complejos se pueden optimizar por separado cada uno de los
módulos que componen el diseño con objeto de obtener mejores resultados. El
parámetro target indica la tecnología destino para la que se va a sintetizar
(xisxl para nuestro ejemplo). El parámetro chip indica al optimizador que
añada buffers de I/O a los puertos de la entidad de mayor nivel. Los
parámetros area y delay indican el factor sobre el que se va a tratar de
minimizar (consumo de área o retardos) en el diseño. Estos son mutuamente
excluyentes. El parámetro efford fija el tipo de esfuerzo a realizar durante
la optimización. Los valores válidos son:
!
remap Realiza ciertas optimizaciones locales y a continuación el
mapeado tecnológico.
!
quick Realiza la optimización de una sola pasada y a continuación el
mapeado tecnológico. Normalmente esta es la opción empleada en las
primeras fases del diseño.
!
standard (valor por defecto). Realiza varias pasadas durante la
optimización y a continuación el mapeado tecnológico. Para ello se
aplican distintas estrategias de optimización obteniendose mejores
-52-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
resultados que en el modo quick pero se consume más tiempo. Suele
emplearse para afinar los resultados de la síntesis.
El parámetro hierarchy indica si se mantendrá la jerarquía de diseño indicada
en el código fuente (preserve) o bien si se aplanará el diseño (flatten). Por
defecto la optimización de la síntesis se aplica individualmente a cada uno
de los módulos que componen la jerarquía del diseño. Sin embargo los límites
jerárquicos impiden o limitan las optimizaciones a realizar por lo que puede
ser deseable aplanarla. En ciertas ocasiones puede ser deseable preservarla,
por ejemplo, para dar un tratamiento especial a bloques de temporización
crítica. En cualquier caso se establece como regla de oro que los bloques
jerárquicos no tengan tamaños superiores a 50 K puertas.
Según lo expuesto el comando empleado en nuestro diseño para realizar la
optimización es:
optimize -target xisxl -delay -effort quick -chip -hierarchy preserve
4.2.8. Almacenamiento del diseño.
Una vez realizada la optimización, se pueden salvar los resultados de la
síntesis para su uso posterior. Como se ha comentado estos consisten en una
lista de conexiones en la que aparecen elementos de la tecnología destino y
otra información adicional (p.e. restricciones para la herramienta de
implementación). Esta lista de conexiones se puede salvar en distintos
formatos standard (EDIF, VHDL, XNF, etc), si bien lo más idóneo es emplear
el formato propio del sintetizador (XDB). Para salvar el diseño del ejemplo
en el fichero crono.xdb se emplea el comando:
write -format xdb crono.xdb
4.2.9. Exportación de la lista de conexiones.
La última operación a realizar durante la síntesis consiste en exportar los
resultados de ésta para que puedan ser empleados en las siguientes fases del
flujo de diseño. El formato con que se almacene la lista de conexiones
dependerá de la herramienta que la utilice en las siguientes fases del flujo
de diseño. Si esta lista de conexiones se utiliza con las herramientas de
implementación de Xilinx el formato puede ser EDF o XNF. Por ejemplo si se
exporta en formato EDIF el comando a emplear para nuestro ejemplo será:
auto_write -format edif ../crono.edf
Normalmente el comando auto_write suele ir precedido por el comando lo2up que
convierte los nombres de los objetos a mayúsculas. Esto evita problemas de
interpretación del contenido de la lista de conexiones. De igual forma cuando
se utilizan componentes COREGEN se debe ejecutar con anterioridad el comando:
set edif_write_arrays FALSE
Esto evita que la lista de conexiones generada haga uso de la notación
compacta para la definición de buses que emplea formato EDIF. Puesto que las
herramientas de Xilinx no admiten esta posibilidad si se empleará esta
notación aparecería un error durante la implementación al intentar enlazar
ambas listas de conexiones (la generada por el sintetizador y la
correspondiente al componente COREGEN).
-53-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
Si por el contrario se desea exportar la lista de conexiones como un fichero
VHDL
estructural
para
realizar
una
simulación
post-síntesis
preimplementación la secuencia de comandos a emplear será:
set vhdl_write_component_package FALSE
set vhdl_write_use_packages "library IEEE; use IEE.std_logic_1164.all;
library UNISIM; use UNISIM.vcomponents.all;"
write -format vhdl ../post-synthesis/crono.vhd
La desactivación del atributo vhdl_write_component_package evita que los
componentes que aparecen en la lista de conexiones se escriba en un paquete
a parte. Mediante el atributo vhdl_write_use_packages se indican la
declaración a incluir en cada entidad que aparece en el fichero VHDL
generado. Finalmente el comando write salva el fichero VHDL
La versión de Leonardo empleada en el laboratorio no realiza correctamente
la exportación de la lista de conexiones en formato VHDL para FPGAs de la
familia Spartan XL. Para otras familias como Spartan II o Virtex no hay
ningún tipo de problemas.
Para generar el archivo EDIF para la herramientas de implementación se puede
utilizar la ventana de la figura 1.37 .
Figura 37: Selección del archivo EDIF de salida.
4.2.10. Uso de ficheros de scripts.
Toda esta secuencia de comandos se puede almacenar en un fichero de script
para su posterior ejecución permitiendo realizar la síntesis de una sola
pasada. Con este ejemplo se proporciona el fichero sintetiza.tcl para tal
fín. Para ejecutar este fichero ejecute en el comando:
source sintetiza.tcl
4.3. ANÁLISIS DE RESULTADOS.
-54-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
Para analizar los resultados obtenidos se pueden generar informes del área
consumida o de los retardos del diseño. Para generar un fichero con un
informe del área consumida se emplea el comando:
report_area informe1.txt -cell_usage -hierarchy -all_leafs
Parte del contenido de este fichero se muestra en la figura 1.38.
*******************************************************
Cell: CRONO
View: RTL
Library: work
*******************************************************
Number
Number
Number
Number
Cell
Library
BUFGP
FDC
FDCE
FDP
GND
IBUF
LUT1
LUT2
LUT3
LUT4
MUXF5
OBUF
PRESCALER
PULLUP
xis2
xis2
xis2
xis2
xis2
xis2
xis2
xis2
xis2
xis2
xis2
xis2
work
xis2
of
of
of
of
ports :
nets :
instances :
references to this view :
Total accumulated area :
Number of BUFGP :
Number of Dffs or Latches :
Number of Function Generators :
Number of GND :
Number of IBUF :
Number of MUXF5 :
Number of OBUF :
Black Box PRESCALER :
Number of PULLUP :
Number of gates :
References
1
3
16
1
1
2
3
1
5
20
1
14
1
2
x
x
x
x
x
x
x
x
x
x
x
x
x
x
Total Area
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
3
16
1
1
2
3
1
5
20
1
14
1
2
BUFGP
Dffs or Latches
Dffs or Latches
Dffs or Latches
GND
IBUF
Function Generators
Function Generators
Function Generators
Function Generators
MUXF5
OBUF
PRESCALER
PULLUP
17
72
71
0
1
20
29
1
2
1
14
1
2
26
***********************************************
Device Utilization for 2s50tq144
***********************************************
Resource
Used
Avail
Utilization
----------------------------------------------IOs
17
92
18.48%
Function Generators
29
1536
1.89%
CLB Slices
15
768
1.95%
Dffs or Latches
20
2082
0.96%
-----------------------------------------------
Figura 38: Informe de consumo de área (fichero informe1.txt).
De forma similar para generar un informe de las temporizaciones del diseño
se emplea el comando:
report_delay informe2.txt -num_paths 1 -critical_paths -clock_frequency
La figura 1.39 muestra parte del contenido de este fichero.
-55-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
Clock Frequency Report
Clock
: Frequency
-----------------------------------CLK
: 161.3 MHz
Critical Path Report
Critical path #1, (path slack = 10.0):
NAME
GATE
ARRIVAL
LOAD
---------------------------------------------------------------------------------------CLK/
0.00 0.00 up
1.90
CLK_IBUF/O
BUFGP
0.09 0.09 up
3.70
REG_UNIDADES(2)/C
FDCE
0.00 0.09 up
0.00
data arrival time
0.09
data required time (default specified - setup time)
10.09
---------------------------------------------------------------------------------------data required time
10.09
data arrival time
0.09
---------slack
10.00
----------------------------------------------------------------------------------------
Figura 39: Informe de retardos (fichero informe2.txt)
Para acceder a las opciones de generación de archivos de informes desde el
interface gráfico se utiliza la pestaña
, accediendo a la ventana de
informes, en la que se puede seleccionar la generación de un informe de área
y/o velocidad.
Otra forma de analizar los resultados de la síntesis consiste en emplear un
método gráfico que permite visualizar en forma de esquemas los módulos
inferidos durante la síntesis. Para ello seleccione la opción Tools º Design
Browser de la barra de menús, o con el icono
. En ese momento se muestra
la pantalla que aparece en la figura 1.40. En la parte izquierda de esta
ventana se muestra la jerarquía del diseño sintetizado, donde se pueden
distinguir claramente las distintas librerías citadas con anterioridad.
Navegando por este árbol se puede seleccionar el elemento para el cual se
desean mostrar su implementación.
Figura 40: Ventana del navegador de diseños.
Estos esquemas se pueden mostrar a nivel RTL o a nivel de puertas. En el
primer caso los componentes que aparecen son las primitivas genéricas
empleadas por el sintetizador durante la síntesis. En el segundo caso los
componentes empleados son elementos de la tecnología destino para la que se
ha sintetizado. Está claro que los esquemas a nivel de puertas no se pueden
visualizar hasta que no se haya completado la fase de mapeado tecnológico.
-56-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
Como se puede apreciar, en la ventana del navegador del diseño se muestran
dos arquitecturas para la entidad de mayor jerarquía. La primera de ellas
tiene el nombre empleado en el código fuente VHDL. Al seleccionar los
elementos que aparecen en esta arquitectura se muestran los esquemas RTL. La
otra arquitectura tiene el mismo nombre con el sufijo _XRTL correspondiendo
a la arquitectura generada tras el mapeado tecnológico. Al seleccionar los
elementos que aparecen en esta arquitectura se muestran los esquemas a nivel
de puertas. En cualquier caso se puede visualizar uno u otro tipo de esquemas
mediante las opciones Tools º View RTL Schematic y Tools º View Gate Level
Schematic de la barra de menús, icono
.
También es posible visualizar el camino de máximo retardo pulsando sobre el
botón
de la barra de herramientas. En ese momento aparece la pantalla
que se muestra en la figura 1.41.
Figura 41: Ventana de camino crítico.
5. IMPLEMENTACIÓN DEL DISEÑO.
La siguiente fase del proceso de diseño es la implementación de éste
empleando para ello las herramientas de Xilinx. Estas herramientas reciben
la lista de conexiones en formato EDIF generada durante la síntesis.
Para compilar el diseño sintetizado ejecute la herramienta Design Manager
seleccionando Inicio º Programas º XilinxISE41 ºAccesories º
.
A continuación se debe crear un nuevo proyecto seleccionando la opción File
º New Project de la barra de menús (
). En el campo imput design se debe
seleccionar el archivo EDIF creado por la herramienta de síntesis, tal y como
se muestra en la figura 1.42.
-57-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
Figura 42: Creación de un proyecto con el Disign Manager.
Al pulsar la pestaña OK se va a crear un subdirectorio xproj en el que se van
a almacenar los archivos generados durante la implementación y aparece la
ventana de la figura 1.43., que entre otras cosas permite seleccionar el
dispositiva sobre el que se va a realizar la implementación.
Figura 43: Selección del dispositivo.
En un proyecto pueden existir varias versiones y dentro de cada una de ellas,
varias revisiones. Una versión corresponde a la compilación del diseño en el
que se han producido variaciones en el archivo fuente o se ha seleccionado
una nueva familia de dispositivo. Por su parte el término revisión se
corresponde con una compilación del diseño en la que se han variado algunos
parámetros u opciones de la misma, pero no el archivo fuente.
Antes de proceder a la implementación hay que seleccionar las opciones de la
misma, para ello se seleccionando Design º Options de la barra de menús. Con
el icono
, también se puede acceder a las opciones de implementación,
Estas opciones se dividen en tres campos (figura 1.44 ): Implementation que
permite imponer restricciones para la implementación, Simulation que permite
seleccionar el formato del archivo de salida para realizar la simulación
temporal o post-implementación y Configuration que permite seleccionar
opciones concernientes a la fase de configuración del dispositivo. Para el
-58-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
diseño que nos trata sólo se va a retocar el campo de Simulation para indicar
que se genere un archivo un archivo VHDL para ser simulado con ModelSim.
Figura 44: Opciones de implementación.
Con ésto, a parte del fichero de configuración (crono.bit), se generan los
ficheros time_sim.vhd y time_sim.sdf empleados para realizar unas simulación
VHDL post-implementación (también denominada simulación a nivel de puertas).
El fichero time_sim.vhd contiene una descripción estructural de la entidad
de jerarquía superior (crono). En este fichero, las herramientas de Xilinx
asignan siempre el nombre
STRUCTURE a la arquitectura de la entidad de
jerarquía superior. Por su parte, el archivo time_sim.sdf contiene la
información temporal con los retardos que sufren las señales, presentes en
el archivo time_sim.vhd, dentro del dispositivo.
Ha de tenerse en cuenta que para que la compilación del diseño se realice
correctamente el fichero de lista de conexiones asociado al módulo COREGEN
(prescaler.edn) debe encontrarse en el directorio donde ha sido almacenada
la lista de conexiones generada por el sintetizador.
Antes de proceder con la implementación se puede generar un archivo de
restricciones de usuario pueden emplearse para fijar restricciones durante
el proceso de implementación del diseño. Con estas restricciones se puede
asignar las señales correspondientes a los puertos de la entidad de mayor
jerarquía a sus terminales correspondientes, así como otras configuraciones
de entrada/salida (slew-rate, estándar lógico, etc) (restricciones
topológicas) o bien imponer retardos máximos en los caminos de señal. El
fichero de restricciones de usuario (User Constrains File- ucf) se crea con
Tools º Constrains Editor , o con
, accediendo a la ventana de la figura
1.45.
-59-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
Figura 45: Creación de un archivo de restricciones.
Con los elementos
(crear nuevo archivo ucf) ,
(abrir archivo ucf) y
(guardar archivo ucf)se puede seleccionar el contenido del archivo de
restricciones. En la figura 1.46. se muestra el contenido del archivo ucf
utilizado en el diseño del tutorial.
NET
NET
NET
NET
NET
NET
NET
NET
NET
NET
NET
NET
NET
NET
NET
NET
NET
"CLK" LOC = "p55";
"DISPLAYDECENAS(0)" LOC = "p4";
"DISPLAYDECENAS(1)" LOC = "p5";
"DISPLAYDECENAS(2)" LOC = "p6";
"DISPLAYDECENAS(3)" LOC = "p7";
"DISPLAYDECENAS(4)" LOC = "p8";
"DISPLAYDECENAS(5)" LOC = "p10";
"DISPLAYDECENAS(6)" LOC = "p11";
"DISPLAYUNIDADES(0)" LOC = "p12";
"DISPLAYUNIDADES(1)" LOC = "p13";
"DISPLAYUNIDADES(2)" LOC = "p14";
"DISPLAYUNIDADES(3)" LOC = "p15";
"DISPLAYUNIDADES(4)" LOC = "p18";
"DISPLAYUNIDADES(5)" LOC = "p20";
"DISPLAYUNIDADES(6)" LOC = "p21";
"LAPSO" LOC = "p22";
"RST" LOC = "p23";
Figura 46: Fichero de restricciones crono.ucf.
Una vez creado o seleccionado el archivo de restricciones, se procede a la
implementación del diseño, para ello se ejecuta Tools º Flor Engine, o se
actúa sobre el botón
de la barra de herramientas, creandose de forma automática una nueva
versión o revisión según sea el caso. Cuando se ejecuta dicho comando aparece el cuadro de
diálogo de la figura 1.47.
-60-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
Figura 47: Implementación de un diseño.
Los Indicadores de Proceso que posee la ventana de la figura anterior
muestran en qué etapa se encuentra el flujo del diseño en ese preciso
momento. Las flechas entre cada paso se vuelven de color negro después que
el paso previo ha terminado. En la barra de proceso que muestra el estado en
que se encuentra cada proceso, ya sea en ejecución (Running), completado
(Completed), abortado (Aborted) o con algún error en la ejecución (Failed).
Para el caso de trabajar con FPGA’s, los procesos son:
- Translate: Realizar la traducción del diseño.
- Map: Realizar la partición del diseño.
- Place&Rute: Realizar el emplazamiento y ruteado del diseño.
- Timing(Sim). Genera un archivo de retardos paar realizar
simulación temporal
- Configure: Genera el archivo de configuración.
una
El proceso de implementación de un diseño conlleva la ejecución secuencial de una serie de
herramientas, cada una de las cuales genera un archivo ASCII de informes (reporters) en el que
se reflejan todas las acciones realizadas por el mismo, así como los errores o avisos (warnings)
que se producen. En la figura 1.48. se muestra el grupo de archivos de informes generados
durante la implementación de un diseño para una FPGA. Para acceder a la los informes
de la barra de
ejecuta Utilies º Report Browser, o se actúa sobre el botón
herramientas,
Figura 48: Archivos de informes de la implementación
6. SIMULACIÓN A NIVEL DE PUERTAS.
-61-
Ingeniería Electrónica.
Laboratorio de Diseño de Circuitos y Sistemas Electrónicos.
El proceso a seguir para llevar a cabo la simulación post-implementación es
muy similar al descrito para la simulación RTL variando únicamente los
ficheros VHDL a emplear en cada caso. El archivo a compilar es ahora el
time_sim.vhd, el cual contiene una descripción estructural realizad con
componentes de la tecnología destino. Una vez compilado se crea la
arquitectura structure para el componente crono, por lo que habrá que crear
una nueva configuración para seleccionar el uso de dicha arquitectura en el
testbench. El fichero que contiene la configuración para la simulación
temporal es cnf_temporal.vhd. Así la secuencia de comandos a ejecutar será:
vcom -87 time_sim.vhd
vcom -93 testbench.vhd
vcom -93 cnf_temporal.vhd
Los comandos para realizar la compilación de los archivos necesarios para
realizar la simulación temporal se encuentran en el scrip compila_tmp.do.
En una simulación temporal a la hora de cargar el diseño a simular es preciso
indicar la entidad sobre la que se aplicará el fichero .sdf que contiene las
retroanotaciones de retardos. La sintaxis empleada para ello por el comando
vsim es:
vsim
[-sdfmin | -sdftyp | -sdfmax [<instance>=]<sdf_filename>]
[<library_name>.<design_unit>]
Según esto para nuestro caso mediante la opción -sdfmax se empleará el valor
máximo de los retardos retroanotados (simulación del peor caso). Estos se
aplicaran al componente uut que está instanciado en la raíz (“/”) de la
jerarquía. Estos retardos se encuentran almacenados en el fichero
time_sim.sdf. Con esto el comando a emplear sería:
vsim -sdfmax /dut=../time_sim.sdf cnf_temporal
vsim
-sdfmax
dut=C:/tutorial/time_sim.sdf
work.cnf_temporal
-multisource_delay
Desde el interface gráfico, una vez actuado sobre
latest
y seleccionada la
unidad de diseño a simular (cnf_temporal) con la pestaña SDF se selecciona
el archivo que contiene la información temporal haciendo uso de la ventana
de la figura 1.49.
Figura 49: Selección del archivo sdf.
-62-
Diseño en VHDL para FPGAs.
R. Mateos, I. Fernández. P. Martín
En la figura anterior actúando sobre la pestaña add se selecciona el archivo
sdf y el elemento sobre el que se aplica (figura 1.50 ), para ello se indica la
referencia que el componente tiene en el testbenc (dut).
Figura 50: Parámetros del archivo sdf.
El resto de comandos a emplear son exactamente los mismos, salvo por un
pequeño detalle. Durante el proceso de síntesis y su posterior implementación
puede ocurrir que determinadas señales internas desaparezcan debido a
optimizaciones realizadas por estas herramientas. Por tanto es aconsejable
visualizar únicamente los puertos de la entidad del diseño, nunca señales
internas.
Tan sólo en el caso de que por motivos de depuración fuese
necesario visualizar señales internas únicamente es posible visualizar los
puertos de los componentes instanciados en el código VHDL y siempre que se
preserve la jerarquía durante la síntesis.
Con esto los comandos necesarios para seleccionar las señales a visualizar
serán:
# Definicion de se¤ales a visualizar.
add
add
add
add
add
add
add
add
add
add
wave
wave
wave
wave
wave
wave
wave
wave
wave
wave
/testbench/rst_tb
/testbench/clk_tb
/testbench/dut/en1hz
/testbench/lapso_tb
/testbench/dut/state
/testbench/dut/actualizar
-unsigned /testbench/dut/cntunidades
-unsigned /testbench/dut/cntdecenas
/testbench/displayunidades_tb
/testbench/displaydecenas_tb
run 400 ns
force -freeze testbench/dut/EN1HZ 1
run 50 us
Estos comandos están recogidos en el script sim_temporal.do
-63-
Descargar