Generador de Funciones para Sensores Basados en

Anuncio
Generador de Funciones para Sensores Basados en
Óxidos Metálicos
AUTOR: Marcial Rosado Farré .
DIRECTORES: Nicolau Cañellas, Xavier Vilanova .
FECHA: Febrero/ 2002.
Bibliografía
Bibliografía Recomendada
Para aprender a utilizar el lenguaje de programación VHDL se recomienda
consultar el libro:
Título: VHDL Lenguaje Estándar de Diseño Electrónico
Editorial: Mc Graw Hill
Para obtener información sobre el funcionamiento y estructuras de las FPGA
se puede consultar el libro:
Título: The Programable Lógic Data Book
Autor: XILINX
El funcionamiento de la placa de uso genérico de Xilinx se describe en:
Título: FPGA Design Demonstration Board Hardware User Guide
Autor: XILINX
También se puede encontrar diversa información en la dirección de internet
siguiente:
http://www.xilinx.com
Índice
1.
MEMORIA DESCRIPTIVA ............................................................................. 5
1.1
INTRODUCCIÓN ............................................................................................. 5
1.2
DESCRIPCIÓN GENERAL ................................................................................ 8
1.2.1
Sensores de Semiconductor óxido......................................................... 8
1.2.2
Introducción al VHDL .......................................................................... 9
1.2.3
Introducción a la FPGA ..................................................................... 13
1.2.4
Descripción del Diseño ...................................................................... 15
1.2.5
Descripción Detallada........................................................................ 17
1.2.6
Convertidor DA .................................................................................. 43
1.2.8
Placa de Pruebas................................................................................ 44
1.2.9
Programación de la FPGA ................................................................. 47
2
MEMORIA DE CÁLCULO ............................................................................ 49
2.1
2.2
2.3
2.4
2.6
3
CÁLCULO DE LA FRECUENCIA DEL RELOJ EXTERNO ................................... 49
FRECUENCIA DEL RELOJ EXTERNO PARA LA VERIFICACIÓN DEL DISEÑO .... 49
CÁLCULO DE LOS VALORES DE LA ROM..................................................... 50
CÁLCULO DE COMPONENTES PARA EL CONVERTIDOR DA .......................... 52
CONVERTIDOR DA EN LA PLACA DE PRUEBAS ............................................ 52
MEMORIA DE PLANOS................................................................................ 53
3.1
PLACA DE PRUEBAS..................................................................................... 53
3.1.1
Situación de Componentes.................................................................. 53
3.1.2
Esquema Eléctrico de ORCAD. .......................................................... 54
3.1.3
Listado de Componentes..................................................................... 55
3.2
FPGA DESIGN DEMONSTRATION BOARD.................................................... 56
3.2.1
Situación de Componentes.................................................................. 56
3.2.2
Esquema Eléctrico.............................................................................. 57
3.3
DIAGRAMA DE CONEXIÓN GENERAL ........................................................... 58
4
ANEXOS ........................................................................................................... 59
4.1
CÓDIGO VHDL Y SIMULACIÓN CON VERIBEST ........................................ 59
4.1.1
clk ....................................................................................................... 59
4.1.2
Divisor por 8 ...................................................................................... 60
4.1.3
Divisor de frecuencia.......................................................................... 61
4.1.4
Contador i_d_desp ............................................................................. 62
4.1.5
Diente de sierra .................................................................................. 73
4.1.6
Rectangular ........................................................................................ 74
4.1.7
Triangular .......................................................................................... 75
4.1.8
Senoidal .............................................................................................. 76
4.1.9
ROM ................................................................................................... 77
4.1.10 Inversor .............................................................................................. 79
4.1.11 Conjunto ............................................................................................. 80
4.1.12 Multiplexor ......................................................................................... 84
3
Índice
4.1.13 Amplificador_ofsset ............................................................................ 85
4.1.14 Generador de funciones...................................................................... 94
4.1.15 Diferencias entre el generador simulado y el sintetizado .................. 97
4.2
SINTETIZACIÓN DEL CÓDIGO VHDL ........................................................... 98
4
Memoria Descriptiva
1.
1.1
Memoria Descriptiva
Introducción
El objetivo del proyecto es realizar un generador de funciones. Este generador
proporcionará cuatro tipo de señales: diente de sierra, rectangular, triangular y
senoidal, y podrán ser reguladas en frecuencia, amplitud y offset.
Aunque el generador podría utilizarse en multitud de aplicaciones, el proyecto
se centrará en el uso de sensores de gases, concretamente sensores de semiconductor
óxido. Estos sensores están conectados a unas resistencias donde se debe aplicar
intensidad con diferentes formas de onda para provocar variaciones de la temperatura
en función del tiempo.
Para conseguir el objetivo se ha decidido diseñar el generador mediante un
lenguaje de descripción de hardware. El código generado se sintetizará y grabará en
un dispositivo programable FPGA. Este dispositivo generará una salida digital que
será convertida a analógica con un convertidor digital-analógico con salida de
corriente. Después esta corriente se amplificará con un amplificador para adecuar la
potencia que necesitan las resistencias.
El lenguaje de programación elegido para la implementación del generador
digital ha sido el VHDL (lenguaje de descripción del hardware) debido al amplio
abanico de posibilidades que ofrece, así como su sencillez para hacer modificaciones
del diseño final, permitiendo ampliar los bits de entrada o de salida modificando
únicamente unas lineas de código.
Para simular el código VHDL se utilizará el paquete informático VERIBEST.
Posteriormente, para sintetizar el código y programarlo en la FPGA se utilizará el
paquete informático FOUNDATION, debido a que se trabajará con dispositivos del
fabricante XILINX.
A continuación se puede observar un esquema de las partes principales de este
diseño:
Figura 1. Esquema
En la FPGA se implementará un generador con las siguientes características:
5
Memoria Descriptiva
Figura 2. Generador de funciones
La señal de reloj clk será introducida externamente mediante un circuito
oscilador.
-
periodo: Controla el periodo, y por tanto la frecuencia de la señal. Por
especificaciones del diseño se deben generar periodos comprendidos entre
0.1 y 10 s. Se ha de ajustar el diseño para conseguir un periodo mínimo de
0.1s y a partir de aquí poderlo ampliar. Con 8 bits se podrán generar
periodos desde 0.1 s hasta 255·0.1 = 25.5 s, ya que Tseñal = periodo·0,1.
Cuando periodo sea cero no se obtendrá señal.
-
desplazamiento: La señal a generar debe permitir intervalos de reposo para
permitir el enfriamiento de las resistencias. Este intervalo estará
comprendido entre 0.05 s y 255·0.05 = 12.75 s, ya que
tdesplazamiento=desplazamiento·0.05.
-
amplificación: controlará la amplitud de la señal, la cual debe permitir
amplitudes máximas de 150 mA. Con 8 bits por tanto se podrá conseguir
una amplitud mínima de ∆ = 150 mA/2n bits. La amplitud de la señal se
calcula con la expresión amplitud = amplificación· ∆
-
offset: Controlará el offset a aplicar en la señal. Esta tendrá una amplitud
máxima de 150 mA, por tanto con 8 bits se podrá introducir un offset
mínimo de ∆ = 150 mA/2n bits. El offset de la señal se calcula con la
expresión offsetseñal = offset·∆.
También se contará con una variable externa de 2 bits que controlará que tipo
de señal se quiere seleccionar selec:
-
“00” Diente de sierra
-
“01” Rectangular
6
Memoria Descriptiva
-
“10” Triangular
-
“11” Senoidal
La parte más importante del diseño consistirá en crear la señal triangular, a
partir de la cual se podrá generar el resto de señales.
El proyecto se centrará en la generación de la señal digital y su posterior
conversión a analógica. Para verificar el funcionamiento del diseño se trabajará con la
placa de XILINX FPGA Design Demonstration Board. Se diseñará una placa con el
convertidor digital analógico y con los interruptores necesarios para implementar las
entradas del generador.
7
Memoria Descriptiva
1.2
Descripción General
1.2.1 Sensores de semiconductor óxido
Estos sensores están compuestos de las siguientes partes:
Figura 3. Sensor de semiconductor óxido
En la resistencia Heater se inyecta una corriente con una forma de onda
determinada. Esta corriente provoca una variación de la temperatura en función del
tiempo que se mide en el termistor, donde R = Ro·(1+α∆T). Midiendo la resistencia
se puede determinar la temperatura.
Este tipo de sensor de gases basado en óxido metálico responde en presencia
de gases reductores/oxidantes variando la ρ del óxido, fenómeno motivado por la
reacción de reducción/oxidación que tiene lugar entre el gas y el óxido. El problema
que se plantea es que cuando se observa una variación de resistencia no se puede
saber a priori cual ha sido el gas responsable del cambio (baja selectividad). Una
manera de afrontar el problema es utilizar el hecho que las reacciones químicas antes
mencionadas tienen una temperatura óptima, en principio diferente para cada gas. Por
tanto, si se varía de forma controlada la temperatura del sensor y se procesa de forma
adecuada su respuesta, se puede llegar a identificar los gases responsables de tal
respuesta, ya sean gases simples o mezclas gaseosas.
En presencia de gases la variación de la temperatura provoca una variación de
conductancia en el sensor de SnO2. La variación de la conductancia implica una
variación de la resistencia del sensor, ya que Rsensor = ρ·L/s. Se hace que la superficie
sea grande, ya que la conductancia tiene un valor elevado, y de esta forma se
consiguen resistencias que se pueden medir, con valores comprendidos entre 100 kΩ
y 1 MΩ aproximadamente. Midiendo esta resistencia se puede analizar la respuesta
dinámica de ρ en función de la temperatura. Con un análisis exhaustivo de la
respuesta mediante redes neuronales se puede realizar una discriminación del tipo de
gas y de su concentración.
8
Memoria Descriptiva
El objetivo del proyecto es suministrar corriente a la resistencia Heater cuyo
valor es de 200 Ω .Esta corriente podrá tener forma triangular, rectangular, de diente
de sierra o senoidal con amplitudes de hasta 150 mA, y frecuencias desde 0,1 Hz
hasta 10 Hz.
La frecuencia debe ser baja debido a que las fluctuaciones de temperatura son
lentas.
1.2.2 Introducción al VHDL
En esta sección se pretende hacer una pequeña aproximación al VHDL
(lenguaje de programación del hardware).
Los lenguajes HDL se asemejan bastante a un lenguaje de programación
convencional, salvo por algunas diferencia:
-
Los HDLs describen sistemas concurrentes, en cambio los lenguajes de
programación especifican habitualmente sistemas secuenciales.
-
Los HDLs han
comportamiento.
-
Los HDLs han de permitir la especificación de características y
restricciones temporales del sistema.
de
permitir
descripciones
estructurales
y
de
1.2.2.1 Partes Fundamentales
En general la descripción de un sistema mediante el lenguaje VHDL se puede
considerar constituida por dos partes fundamentales: la declaración del sistema (entity
body) y la definición de la arquitectura del sistema (architecture body).
La declaración del sistema consiste básicamente en la definición de la
interconexión del sistema con otros módulos (puertos de comunicación) y en la
declaración de los bloques básicos que componen su estructura.
Una vez definida la declaración del sistema, es posible especificar una o
diversas implementaciones del mismo mediante la definición de architecture bodies.
Es posible definir diversos architecture bodies para un mismo entity bodie, cada uno
de los cuales puede reflejar un tipo diferente de descripción del sistema.
Un ejemplo de bloque modular descrito por un par entidad/arquitecura podría
ser un sumador:
entity sumador_1bit is
Port(
a: in bit;
b:in bit;
carry_entrada: in bit;
suma:out bit;
carry_out: out bit
);
9
Memoria Descriptiva
architecture dataflow of sumador is
begin
suma<=a xor b xor carry_entrada;
carry_sortida<=a and b or ((a or b) or carry_entrada);
end dataflow;
La definición estructural de la arquitectura de un sistema se lleva a término
mediante dos primitivas básicas: señales(signals) y componentes (component).
1.2.2.2 Componentes
Un componente es un elemento funcional básico, que puede estar contenido y
descrito en una librería de diseño específica (o, por ejemplo, puede corresponder a un
sistema definido previamente mediante las correspondientes definiciones entity y
architecture). Un componente se puede declarar de la siguiente manera:
component nand3
port(a,b,c:in logic_level; y:out lgic_level);
end component;
1.2.2.3 Procesos
Dentro de una arquitectura podemos encontrar
secuenciales:
-
procesos y procesos
Procesos: Son una serie de sentencias secuenciales que se ejecutan en un
orden concreto y son similares a los lenguajes de programación. Se
ejecutan de forma concurrente y repetitiva.
Process sensitivity list
declaration
begin
stament part
part
(Lista de señales que activan el proceso)
(Declaraciones locales del proceso)
(Órdenes secuenciales a ejecutar cada vez
que se activa el proceso)
end process;
La lista de sensibilidad es equivalente a una sentencia wait al final del proceso.
No todas las sentencias secuenciales son sintetizables.
-
Procesos combinacionales: Modelan lógica combinacional y son
sensibles a las señales leídas en el proceso. El proceso se reejecuta cada
10
Memoria Descriptiva
vez que hay cambios en alguna entrada. Si no es sensible a todas las
entradas no es sintetizable.
1.2.2.4 Señales
Posibilitan la comunicación entre procesos. El simulador alterna entre
actualización de señales y la ejecución de procesos activados por cambios de señales
de su lista de sensibilidad.
El valor de las señales se mantiene constante durante la ejecución de un
proceso.
-
Una asignación en un proceso genera un ‘event’ que se pone en la cola de
eventos de la señal correspondiente.
-
El simulador no procesa la cola de eventos hasta que todos los procesos se
han parado.
-
Las asignaciones llevan asociadas un retardo.
1.2.2.5 Primitivas de Control Secuencial
-
Primitiva wait:
wait [until condición;]
[on nom_senyal1, nom_senyal2, ...;]
[for expresión_temporal;]
-
Primitiva if:
If [condición] then [acciones] elsif [acciones] ... end if;
-
Primitiva case:
case [expresión] is
when [selección] =>[acciones];
end case;
11
Memoria Descriptiva
1.2.2.6
Ciclo de Diseño con VHDLs
A grandes rasgos el ciclo de diseño en este proyecto será el siguiente:
Es pecificación VHDL
Simulador
No
¿ Funciona bien?
Si
Sintetizador
Si
¿ Hay
errores ?
No
Place & Rout
FPGA
Gravar FPGA
Placa de pruebas
No
¿ Funciona bien?
Si
FINAL
12
Memoria Descriptiva
1.2.3 Introducción a la FPGA
En este apartado se hará una breve descripción de que es y como está
estructurada una FPGA.
1.2.3.1 ¿Qué es una FPGA?
FPGA (Field Programable Gate Array) es el nombre genérico que se da a los
dispositivos lógicos programables por el usuario que presentan vías de interconexión
para conectar bloques internos. Se trata entonces de pequeños bloques funcionales
que se interconectan entre ellos a través de una red de interconexiones llamada switch
matrix. Los bloques funcionales no tienen relación directa con los pins y se puede
conectar cualquier bloque con cualquier pin u otros bloques a través de las vías de
conexión.
1.2.3.2 ¿Para qué puede servir?
Las FPGA disponen de la posibilidad de hacer funciones lógicas y combinar
los resultados con registros con no mucho más límite que el número de recursos libres
que queden. Estos resultados se pueden utilizar para hacer otras funciones que se
pueden encadenar mientras queden recursos. A diferencia de algunas PALs o PLDs,
donde se pueden realizar cierto número limitado de funciones lógicas, ya que a
menudo hay un número limitado de suma de productos para cada función y los
registros de que disponen están muy ligados a los pins de salida, las FPGA disponen
de más flexibilidad y gran capacidad. Por tanto en una FPGA no trataremos de poner
cierta parte de nuestro circuito digital, sino que se mirará de poner diseños digitales
completos.
Las FPGA pueden utilizarse en diseños donde el hardware cambie
dinámicamente, o donde se debe adaptar a diferentes aplicaciones del usuario. El
hecho de ser programables permite hacer un cambio en su función de manera rápida
sin necesidad de cambiar el hardware. Permiten el método de prueba y error, tiempos
pequeños para hacer prototipos. No precisan tiempo de espera elevados como puede
ser el caso de los ASICs y el coste del software es también mucho más reducido que
el diseño con ASICs.
1.2.3.3 ¿Cómo funcionan?
A continuación se hará una descripción de los bloques internos de que dispone
la familia de FPGA utilizadas. Las FPGA que fabrica XILINX se clasifican en
familias, cada familia tiene unos bloques internos comunes, y entre los diferentes
integrados de la misma familia sólo varía el número de bloques que tiene cada
integrado o la velocidad de este, pero el bloque básico, a nivel funcional, es común
para todos los integrados de una misma familia.
IOBs: (Input/output Bloc) Son los bloques que sirven de interficie entre los
pins del integrado y las CLBs. Estos bloques controlan si el pin es de entrada o salida
o si es bidireccional. Permite poner el pin en alta impedancia, hacer un Pullup o
13
Memoria Descriptiva
Pulldown o incluso determinar el Slew Rate que se quiere dar al pin. También
incluye registros con tal de reducir el número de registros que se utilizan en las CLBs,
por si se quiere realizar un latch de los datos del pin.
CLBs: (Configurable Logic Bloc) Este es el bloque que permite realizar las
funciones lógicas y actuar sobre los registros. Es por tanto aquí donde estará la mayor
parte del diseño. En la familia que se utiliza en este proyecto (XC4000) la
configuración interna de cada CLB está formada por:
-
Dos generadores de funciones de cuatro variables. Cada función puede
hacer cualquier función lógica de las cuatro variables de entrada. Por tanto
es una pequeña PLA. Estas funciones se llaman F y G.
-
Un generador de funciones de tres variables que permite combinar los
resultados de los generadores F y G con otra variable. De esta manera, con
una CLB
podemos hacer cualquier función de cinco variables
combinando las dos de cuatro más la de tres. Pero podemos hacer también
algunas funciones de hasta nueve variables (4+4+1). El generador que
combina las funciones F y G con la tercera variable se llama función H.
-
Dos registros, donde podemos guardar el valor de las funciones o
conectarlos con otros registros. Estos registros permiten la carga por
flanco ascendente o descendente (es programable), tienen una señal de
reloj común y también un clock enable común. Además tienen una señal
asíncrona que les permite hacer un Set o un Reset al activar esta señal. Los
registros son de tipo D y no disponen de salida negada. Estos registros se
llaman X i Y.
-
Generadores de FCL (Fast Carry Logic), esta es una circuitería dedicada
que permite hacer la generación de señales de acarreo en operaciones
aritméticas de mucha velocidad.
-
Dos Buffers de alta impedancia, que permiten dejar nodos en alta
impedancia y también realizar determinadas funciones, como
multiplexores combinando diversos buffers. (Estructuras Wired And).
Las CLBs se encuentran dispuestas en forma de matriz (normalmente
cuadrada). En la FPGA utilizada la matriz es de 10 x 10.
Interconexiones: Estos son los recursos que nos permiten interconectar las
CLBs entre ellas y con los IOBs. Básicamente hay de tres tipos. Las cercanas que
permiten conectar dos bloques vecinos, las medianas que permiten conectar dos
bloques saltándose uno. Finalmente las largas que atraviesan toda la matriz de CLBs
y que permiten dividir en dos mitades si se quiere.
14
Memoria Descriptiva
1.2.4 Descripción del Diseño
La señal generada (triangular en este caso) tendrá las siguientes características:
Figura 4. Señal
La amplitud, offset, periodo y desplazamiento serán controladas externamente
mediante entradas de 8 bits cada una por especificaciones del diseño. La salida será
un valor de 8 bits.
Desplazamiento es una característica particular de este generador, y es el
tiempo que la señal debe mantenerse en reposo por requerimientos del diseño.
Se puede observar que generar esta señal (triangular en este caso) digitalmente
equivale a una cuenta ascendente y descendente, por tanto el sistema será secuencial y
síncrono donde cada pulso de reloj provocará un incremento o decremento de este
contador. Es decir el contador adquirirá valores de 0 a 255 (28 bits) y de 255 a 0:
Figura 5. Señal digital
Para variar el periodo de la señal existen dos posibles soluciones:
15
Memoria Descriptiva
Para hacer la señal más rápida sin variar el periodo del reloj sería necesario
hacer el incremento de la cuenta más rápido, es decir, contar de dos en dos, cuatro en
cuatro (siempre múltiplos de 2). Es decir pasaríamos por ejemplo del valor
“00000000” al “00000010”, “00000100” y así sucesivamente. Contra más rápida sea
la cuenta más deformada quedará la señal.
La otra solución consiste en generar otro reloj mediante software a partir de la
señal de reloj que nos sirve de base de tiempo, en el cual se pueda controlar el periodo
de los pulsos. De esta manera se aseguraría siempre una cuenta de 0 a 255. La
deformación de la señal se producirá en el eje temporal. Con este sistema se consigue
hacer la señal más lenta (periodos más grandes).
Se ha optado por la segunda solución.
La señal triangular será la señal base y a partir de aquí se obtendrán el resto de
señales, rectangular, diente de sierra y senoidal.
Los cuatro tipos de señales se generan a la vez, añadiéndose un sistema de
multiplexación para seleccionar la señal.
Para variar la amplitud de la señal se implementará un multiplicador secuencial
de valores de 8 bits, para aplicar a la señal un factor de ganancia entre 0 y 1. La
multiplicación de 2 números de 8 bits requiere de 8 ciclos de reloj.
Una vez regulada la amplitud se deberá aplicar un offset a la señal.
El diseño contendrá los siguientes bloques:
-
Un contador programable (cont/i/d/desp), que permita mantener a cero
durante un tiempo la señal (lo que se ha denominado desplazamiento).
Este bloque generará directamente la señal triangular, pero como será el
contador principal del generador a partir del cual se generarán todas las
señales se le ha denominado de otra forma. Este contador variará su valor
a cada flanco ascendente de clk512.
-
Un bloque divisor por 8, que generará una señal de reloj clk8 a partir de la
señal de reloj externa clk. Este bloque permitirá que se produzcan un
mínimo de 8 ciclos de clk antes de que se produzca un flanco de clk512,
para que durante este tiempo se calcule la multiplicación.
-
Un divisor de frecuencia que nos permitirá variar la amplitud a voluntad
de los pulsos de clk512 generado a partir de clk8.
A partir del bloque contador incremental decremental (onda triangular) se
generan los cuatro tipos de señal: diente de sierra, rectangular, triangular y senoidal.
Además de los bloques mencionados necesitaremos:
-
Un multiplexor para seleccionar un tipo de señal.
-
Un bloque amplificador y que permita introducir offset a la señal.
El esquema de bloques es el siguiente:
16
Memoria Descriptiva
Figura 6. Bloques del generador
1.2.5 Descripción Detallada
La entidad en VHDL que engloba todo el esquema es:
entity generador is port (
clk,reset:in std_logic;
periodo:in std_logic_vector(7 downto 0);
amplificacion:in std_logic_vector(7 downto 0);
selec:in std_logic_vector(1 downto 0);
desplazamiento: in std_logic_vector(7 downto 0);
offset:in std_logic_vector(7 downto 0);
salidagen:out std_logic_vector(7 downto 0)
);
end generador;
Código 1: Generador
Nota: Todos las entidades síncronas estarán conectadas a la entrada de reset
externa, que permitirá dar un valor inicial a los registros para que el sistema
arranque adecuadamente.
A continuación se explica detalladamente el funcionamiento de cada uno de
los bloques anteriores.
17
Memoria Descriptiva
1.2.5.1 Bloque Divisor por 8
Este bloque genera un segundo reloj clk8 a partir de la señal de reloj externa
clk. Consiste en un contador de 3 bits con el bit de más peso conectado a la salida.
Cada flanco de clk se incrementa en 1 el valor del registro que actúa como contador.
Durante 4 ciclos de clk el bit permanece a cero por tanto clk8 = ‘0’. Durante los 4
restantes el bit permanece a uno clk8 = ‘1’. Es decir dividimos por 8 la frecuencia de
clk (multiplicamos por 8 su periodo):
Tclk8 = 8·Tclk
(1)
Figura 7. Divisor por 8
Figura 8. Clk8
En el código VHDL corresponderá a la siguiente entidad:
entity divisor8 is port (
reset:in std_logic;
clk:in std_logic;
clk8:out std_logic
);
end divisor8;
Código 2: Divisor8
1.2.5.2 Bloque Divisor de Frecuencia
A partir de clk8 se genera un tercer reloj clk512, donde se controlará la anchura
de sus pulsos mediante la entrada periodo.
18
Memoria Descriptiva
Figura 9. Divisor de frecuencia
El registro de 8 bits es un contador que se va incrementando hasta que alcanza
el valor de la entrada periodo. Cuando esto ocurre clk512 varía su valor.
Cuando se produce un flanco ascendente de clk8 si el valor del registro es igual
al de la entrada periodo se produce un cambio de estado en clk512, pasa de ‘0’ a ‘1’ o
viceversa y el registro se carga al valor “00000001”. En caso que sean diferentes se
incrementa el contador y clk512 no cambia.
Se puede comprobar que si periodo vale “00000001” se producen dos ciclos de
clk8 y uno de clk512. Si periodo vale “00000010” se producen cuatro ciclos de clk8 por
dos de clk512. Y así sucesivamente.
Periodo = “00000001”
Figura 10. Clk512
Podemos comprobar entonces que:
Tclk512 = 2·periodo·Tclk8
(2)
Es decir, Tclk512 podrá variar su valor desde 2·Tclk hasta 512·Tclk.
En el código VHDL corresponderá a la siguiente entidad:
entity divis_frec is port (
reset:in std_logic;
clk8:in std_logic;
clk512:out std_logic;
periodo:in std_logic_vector(7 downto 0)
); end divis_frec;
Código 3: Divisor512
19
Memoria Descriptiva
1.2.5.3 Contador i/d/desp
Este es el bloque principal del generador a partir del cual se generan todas las
señales. Genera a la salida de 8 bits una cuenta ascendente (0 a 255) y descendente
(255 a 0) y permanece a cero según el tiempo establecido por la entrada
desplazamiento. Además generará una salida creciente que indicará en que estado de
la cuenta se encuentra (ascendente, descendente o a cero).
El esquema del bloque es el siguiente:
Figura 11. contador i/d/desp
Su entidad en VHDL será:
entity contador is port(
reset:in std_logic;
clk512:in std_logic;
desplazamiento:in std_logic_vector(7 downto 0);
conta0:out std_logic_vector(7 downto 0);
creciente:out std_logic_vector(1 downto 0)
);
end contador;
Código 4: Contador
En el bloque generador de estado se produce la siguiente secuencia:
20
Memoria Descriptiva
Figura 12. Generador de estado
Cuando e1 está a nivel alto ‘1’ indica que se está produciendo una cuenta
ascendente. Si es e2 la que está a nivel alto se está produciendo una cuenta
descendente, y si en cambio es e3 se está produciendo el periodo en el que la señal
está a cero (se está produciendo lo que hemos denominado el desplazamiento de la
señal). Cuando se activa f1 indica que ha finalizado la cuenta ascendente y habilita la
descendente, cuando acaba la descendente empieza el desplazamiento y cuando este
termina repetimos el ciclo.
La entidad VHDL es:
entity bloque_estado is port(
clk512:in std_logic;
f1,f2,f3:in std_logic;
reset:in std_logic;
e1,e2,e3:out std_logic
);
end bloque_estado;
Código 5:Bloque_estado
En el bloque Contador up/dwn como el nombre indica se genera una cuenta
ascendente descendente de la siguiente manera:
Figura 13. Contador up/dwn
21
Memoria Descriptiva
Podemos ver que se trata de un registro de 8 bits que se incrementa o
decrementa en ‘1’ según el estado de e1. Con la puerta xor habilitamos una de las
cuentas ascendente o descendente cuando uno de los dos bits e1 o e2 está a uno. Las
salidas f1 y f2 indican si se ha llegado al final de cuenta ascendente o descendente
respectivamente.
La entidad VHDL es:
entity cont_up_dwn is port(
clk512:in std_logic;
reset:in std_logic;
e1,e2:in std_logic;
f1,f2:out std_logic;
contupdwn:out std_logic_vector(7 downto 0)
);
end cont_up_dwn;
Código 6: cont_up_dwn
En el bloque cont desp se mantiene la señal del contador i/d/desp a cero hasta
que la cuenta alcanza el valor de la entrada exterior desplazamiento:
Figura 14. Contador desp.
Cuando este bloque está activo se produce una cuenta ascendente hasta que
el valor del registro Reg8 es igual al de la entrada de 8 bits desplazamiento, en este
momento se activa f3 y se pone a cero el registro a través de la entrada rs. Durante el
periodo de tiempo que este bloque está activo la salida del contador i/d/desp estará
conectada a Reg8”0” que es un registro donde todos los bits están a cero.
La entidad VHDL es:
22
Memoria Descriptiva
entity cont_desp is port(
clk512:in std_logic;
e3,reset:in std_logic;
desplazamiento:in std_logic_vector(7 downto 0);
reg_cero:out std_logic_vector(7 downto 0);
f3:out std_logic
);
end cont_desp;
Código 7: cont_desp
El Multiplexor selecciona a la salida del bloque up/dwn o cont desp según el
valor de e3.
La entidad VHDL es:
entity multiplex2canales is port(
e3:in std_logic;
canal1,canal2:in std_logic_vector(7 downto 0);
salmux:out std_logic_vector(7 downto 0)
);
end multiplex2canales;
Código 8: multiplex2canales
El codificador genera a su salida un registro de dos bits que valdrá “01” si se
está produciendo una cuenta ascendente, “10” si es descendente, y “11” cuando se
está produciendo el desplazamiento (la señal se mantiene a cero). Este registro será
necesario como veremos más adelante para generar todos los tipos de señales.
entity codificador is port(
e1,e2,e3:in std_logic;
creciente:out std_logic_vector(1 downto 0)
);
end codificador;
Código 9: codificador
La señal obtenida en el contador i/d/desp es la siguiente:
23
Memoria Descriptiva
Figura 15. Salida del bloque i/d/desp.
Teniendo en cuenta que no será así exactamente ya que cada valor digital se
mantiene un ciclo de clk512.
Con este procedimiento se consigue que el periodo de la señal sea:
Tseñal = 512·clk512
(3)
El tiempo durante el cual se produce el tiempo de desplazamiento será:
Tdesp = desplazamiento·clk512
(4)
1.2.5.4 Diente de Sierra
Para generar la señal de diente de sierra y que esta tenga el mismo periodo que
la señal triangular es necesario que se produzca una cuenta ascendente en un ciclo de
subida y bajada de la señal triangular, e inmediatamente pasar a cero, tal y como
indica la figura:
24
Memoria Descriptiva
Figura 16. Señal diente de sierra
Es decir, la señal debe realizar una cuenta ascendente de 0 a 255 en 512 ciclos
de reloj, por tanto se debe incrementar el valor una vez cada dos ciclos de reloj.
Es posible generar la señal directamente de los valores de la triangular sin
necesidad de crear un segundo contador. El contador de la señal triangular va desde
“00000000” hasta “11111111” como se ha comentado anteriormente. Si se desplaza
el valor un bit a la derecha la cuenta irá de “00000000” a “01111111” (de 0 a 127), y
como se anula el bit de menos peso la cuenta solamente variará cada dos cambios del
valor del contador de la triangular.
Durante el ciclo de subida de la señal triangular el valor que se ha conseguido
desplazando un bit será el valor adecuado para la señal diente de sierra.
Durante el ciclo de bajada para contar de 127 a 255 (“01111111” a
“11111111”) a partir del valor del contador de la señal triangular restaremos a
“11111111” el valor obtenido cuando desplazamos un bit, es decir restaremos primero
127 a 255, obteniendo 128 (“10000000”), después 126 a 255 obteniendo 129
(“10000001”), y así sucesivamente hasta llegar a “11111111”.
Utilizaremos el siguiente bloque:
25
Memoria Descriptiva
Figura 17. Bloque diente de sierra
Su entidad en VHDL es:
entity diente_sierra is port (
creciente:in std_logic_vector(1 downto 0);
conta0:in std_logic_vector(7 downto 0);
conta1:out std_logic_vector(7 downto 0)
);
end diente_sierra;
Código 10: diente_sierra
El bloque funciona de la siguiente manera:
Mientras conta0 es creciente (creciente = “01”) asignaremos a la salida los 7
bits de más peso consiguiendo así una cuenta ascendente desde “00000000” hasta
“01111111”. Ignorando el bit de menos peso de conta0 hacemos que conta1 se
incremente cada dos tics de clk512.
Cuando conta0 es decreciente (creciente = “10”) para conseguir que conta1
siga ascendiendo desde “011111111” hasta “11111111” restaremos a “11111111” el
valor de los 7 bits de más peso de conta0.
Durante el desplazamiento, creciente = “11”, la señal permanece a cero.
1.2.5.5 Rectangular
Generar la señal rectangular es muy sencillo, basta con alternar valores entre el
máximo y el mínimo, es decir “11111111” y “00000000”. En este diseño se ha
decidido que la señal permanecerá al valor máximo mientras la señal triangular
realiza un ciclo de subida y bajada, y que permanecerá a cero cuando la señal
triangular esté en reposo. Sólo se tendrá que controlar en que estado se encuentra la
26
Memoria Descriptiva
señal triangular (si está subiendo o bajando o en reposo) y asignar a la salida el valor
“11111111” o “00000000” según el caso.
El esquema del bloque será:
Figura 18. Bloque rectangular
En este bloque generamos una señal rectangular a partir del estado de conta0.
Si conta0 es creciente o decreciente la salida estará a “11111111” y si se produce el
desplazamiento la salida será “00000000”. De esta manera conseguimos controlar con
la entrada desplazamiento el tiempo que está a nivel bajo.
La entidad VHDL es:
entity rectangular is port (
creciente:in std_logic_vector(1 downto 0);
conta2:out std_logic_vector(7 downto 0)
);
end rectangular;
Código 11: rectangular
La señal obtenida será la siguiente:
27
Memoria Descriptiva
Figura 19. Salida del bloque rectangular
1.2.5.6 Triangular
Como se puede intuir fácilmente la señal triangular no es más que el contador
i/d/desp en sí. Por tanto lo único que debemos hacer es una asignación de conta0 a
conta3.
Figura 20. Bloque triangular
La entidad es:
entity triangular is port (
conta0:in std_logic_vector(7 downto 0);
conta3:out std_logic_vector(7 downto 0)
);
end triangular;
Código 12: triangular
1.2.5.7 Senoide
Generar la señal senoidal es un proceso más complejo que los anteriores. Si se
pretende que la señal senoidal tenga el mismo periodo que la triangular y esté
28
Memoria Descriptiva
comprendida entre “00000000” y “11111111” tendrá que tener las siguientes
características:
Figura 21. Señal senoidal
El proceso más adecuado para generar una señal senoidal es crear una tabla
de valores donde cada valor de la tabla tenga almacenado el correspondiente valor de
la senoide. Esto se consigue utilizando una memoria ROM que se direccionará con un
contador.
En nuestro caso lo ideal sería tener una ROM de 256 valores comprendidos
entre "00000000” y “11111111” (8 bits) para generar la mitad de la senoide en un
ciclo de subida de la señal triangular y la otra mitad en un ciclo de bajada.
Posteriormente sólo se debería realizar una inversión del segundo semiperiodo para
que la señal fuera la adecuada.
El problema está en que una ROM de 256 valores consumiría mucho espacio
al ser implementada en una FPGA. La solución consiste en almacenar solamente un
cuarto de la señal senoidal, así en lugar de 256 valores deberíamos almacenar sólo
128. Pero para optimizar todavía más los recursos se utilizará una ROM de 64 valores
(26 bits) comprendidos entre “00000000” y “11111111”.
Para direccionar la memoria se debe generar a partir del contador de la señal
triangular un contador de las siguientes características:
29
Memoria Descriptiva
Figura 22. Direccionamiento de la ROM
Durante 128 cuentas de la señal triangular la dirección debe realizar una
cuenta de 64 valores, de “000000” a “111111”. En el primer cuarto es sencillo, se
deben asignar a la dirección 6 bits del contador de la triangular, del 6 al 1. No
asignando el bit de menos peso (0) se conseguirá que el incremento de la dirección se
produzca cada dos cuentas del contador. En el segundo cuarto la señal triangular
cuenta desde “1000000” a “11111111”, por tanto los seis bits seleccionados
anteriormente repiten la cuenta de “000000” a “111111”. Pero ahora necesitamos que
la ROM se direccione en sentido inverso, por tanto si restamos a 127 (“111111”) la
cuenta de 0 (“000000”) a 63 (“111111”) obtendremos valores desde “11111” a
“000000”.
En el tercer y cuarto cuadrante hemos de repetir el procedimiento, pero
teniendo en cuenta que el valor de la triangular va ahora desde “11111111” a
“00000000”. Por tanto en el tercer cuadrante realizaremos la misma resta descrita
anteriormente y en el cuarto asignaremos a la dirección directamente los mismos 6
bits del contador de la triangular.
Con el procedimiento descrito conseguiremos la siguiente señal:
30
Memoria Descriptiva
Figura 23. Contenido de la ROM
Sólo quedará ahora invertir el segundo semiperiodo para que la señal tenga la
forma deseada. Esto es sencillo, sólo hemos de restar a “11111111” el contenido de la
ROM.
Se utiliza el siguiente bloque:
Figura 24. Bloque Senoide
El bloque senoide no tiene equivalencia en VHDL, ya que a la hora de
programar se han implementado los tres bloques por separado.
Para generar la señal senoidal utilizaremos una memoria ROM de 64 bytes,
donde guardaremos 64 valores de salida que corresponderán a un cuarto de periodo de
la señal. Estas 64 posiciones de memoria se direccionarán con 6 bits.
Para obtener el semiperiodo positivo deberemos direccionar la ROM una vez
ascendentemente y otra descendentemente. Direccionaremos la memoria a partir de
la cuenta generada por el bloque contador (conta0).
31
Memoria Descriptiva
Para obtener el semiperiodo negativo deberemos invertir los valores obtenidos
de la ROM.
En el bloque senoidal se generan los 6 bits que direccionarán la ROM. En el
tiempo que conta0 realiza un ciclo de subida (creciente = “01”) dirección habrá
realizado una cuenta ascendente y otra descendente. Cuando conta0 es decreciente
(creciente = “10”) dirección repite el ciclo. Para conseguir que la señal senoidal tenga
el mismo periodo que la triangular se ha de tener en cuenta que para producir un
cuarto de señal senoidal se direccionan 64 valores, en cambio conta0 en un cuarto de
señal triangular realiza 128 cuentas. La solución consiste en realizar un
direccionamiento cada dos cuentas de conta0, y esto se consigue ignorando el bit de
menos peso de conta0. El procedimiento seguido es el siguiente:
Si conta0 es menor de 128, es decir, el bit de más peso es cero y creciente =
“01”, o si es mayor de 128 (el bit de más peso es 1) y creciente = “10” (primero y
tercer cuarto de la señal senoidal) los 6 bits de menos peso de conta0 (ignorando el
último como se ha comentado antes) tienen el valor requerido, por tanto los
asignamos a la salida (dirección). Si no se cumplen los casos anteriores restaremos a
“111111” el valor de los seis bits de menos peso de conta0. Se puede comprobar que
de esta manera direccion realiza una cuenta de “000000” a “111111” y de “111111”
a “000000” cuando conta0 es creciente y otro ciclo igual cuando es decreciente.
Como en los casos anteriores cuando creciente = “11” la salida permanecerá a cero
(“000000”), ya que la asignamos directamente a la entrada conta0. Con este proceso
conseguiremos que la señal senoidal tenga el mismo periodo que la triangular.
Figura 25. Bloque Senoidal
32
Memoria Descriptiva
La entidad VHDL es:
entity senoidal is port (
creciente:in std_logic_vector(1 downto 0);
conta0:in std_logic_vector(7 downto 0);
direccion:out std_logic_vector(5 downto 0)
);
end senoidal;
Código 13: senoidal
La salida de este bloque será entonces:
Figura 26. Salida del bloque Senoidal
A cada valor de dirección el bloque ROM genera a la salida el correspondiente
valor de 8 bits de la memoria.
Figura 27. ROM
33
Memoria Descriptiva
La entidad VHDL es:
entity ROM is port (
direccion:in std_logic_vector(5 downto 0);
contenido:out std_logic_vector(7 downto 0)
);
end ROM;
Código 14: ROM
A la salida de la ROM obtendremos por tanto la siguiente señal:
Figura 28. Salida del bloque ROM
El bloque inversor funciona de la siguiente manera:
En el primer semiperiodo la salida de la ROM es la necesaria. En cambio,
cuando el bloque anterior genera el segundo semiperiodo (creciente = “10”) debemos
invertirlo para conseguir el semiperiodo negativo de la señal senoidal. Para ello
hemos de restar al valor máximo de la señal (“11111111”) la salida generada por la
ROM, como muestra el esquema :
34
Memoria Descriptiva
Figura 29. Inversor
La entidad VHDL es:
entity inversor is port (
creciente:in std_logic_vector(1 downto 0);
contenido:in std_logic_vector(7 downto 0);
conta4:out std_logic_vector(7 downto 0)
);
end inversor;
Código 15: Inversor
La salida de este bloque será:
Figura 30. Salida del bloque Inversor
35
Memoria Descriptiva
1.2.5.8 Multiplexor
Este componente seleccionará una los cuatro tipos de señales según el valor de
la entrada selec:
-
“00” Diente de sierra
-
“01” Rectangular
-
“10” Triangular
-
“11” Senoidal
Figura 31. Multiplexor
Su entidad VHDL es:
entity multiplexor is port(
A:in std_logic_vector(7 downto 0);
B:in std_logic_vector(7 downto 0);
C:in std_logic_vector(7 downto 0);
D:in std_logic_vector(7 downto 0);
selec:in std_logic_vector(1 downto 0);
salida_mult:out std_logic_vector(7 downto 0)
);
end multiplexor;
Código 16: Multiplexor
1.2.5.9 Amplificador-offset
Para aplicar un factor de ganancia se realiza una multiplicación secuencial del
valor de la señal por un factor externo amplificación.
Una multiplicación de dos valores de 8 bits produce a su salida, como máximo,
un valor de 16 bits y necesita 8 ciclos de reloj para realizar las sucesivas sumas que
requiere.
36
Memoria Descriptiva
El margen de trabajo del factor de ganancia está comprendido entre 0 y 1, es
decir, el generador proporcionará un valor máximo de salida que podremos atenuar.
Volviendo a las especificaciones del diseño, necesitamos 150 mA de amplitud
máxima. Los 16 bits del resultado de la multiplicación podrían proporcionar
intensidades comprendidas entre 2.28·10-3 mA y 65536·2.28·10-3 mA = 150 mA. No
interesa una resolución tan alta de la señal, por tanto cogeremos sólo los 8 bits de más
peso del resultado de la multiplicación.
Este bloque está dividido en otros cuatro como se muestra en la figura 20. El
amplificador se encarga de realizar la multiplicación digital iniciada por el bloque
inicio. El sumador añade el offset al resultado de la multiplicación. El limitador evita
que se exceda el valor máximo de salida al sumar el offset, recortando la señal cuando
sea necesario.
Figura 32. Amplificador_offset
La entidad VHDL será:
entity amplif_offset is port (
reset:in std_logic;
clk,clk512:in std_logic;
offset:in std_logic_vector(7 downto 0);
amplificacion:in std_logic_vector(7 downto 0);
multiplicando:in std_logic_vector(7 downto 0);
sal_amp_off:out std_logic_vector(7 downto 0)
);
end amplif_offset;
Código 17: amplif_offset
La multiplicación es un proceso que requerirá 8 flancos de reloj, por tanto el
bloque amplificador debe trabajar con un reloj más rápido (clk) de manera que cuando
se produzca un flanco del reloj principal del sistema (clk512) se hayan producido un
mínimo de 8 flancos de clk para poder realizar la multiplicación.
Como el nombre indica el bloque inicio se encarga de iniciar la multiplicación.
37
Memoria Descriptiva
Cada vez que se produce un flanco de subida de clk512 se genera un ‘1’ en start
indicando al bloque amplificador que puede iniciar la multiplicación. En cuanto se
produce el primer flanco de clk la señal start vuelve a cero para evitar que se reinicie
de nuevo el sistema.
Como vemos en la figura está compuesto por dos biestables y una puerta xor:
Figura 33. Inicio
Este bloque no tiene entidad VHDL, puesto que está integrado dentro del
bloque amplificador.
El bloque amplificador realiza una multiplicación de dos valores de 8 bits. Al
multiplicar dos valores de 8 bits pueden generar un valor de 16 bits, por tanto lo
lógico sería utilizar registros de 16 bits. Para economizar recursos se utilizan registros
de 10 bits, puesto que al final sólo interesarán los 8 bits de más peso. El registro de
salida es el acumulador que sumará o no el valor de la entrada amplificación según el
valor del bit de la entrada sal_mux.
Cuando start se activa los valores a multiplicar se cargan en los registros.
Amplificacion se carga en un registro rotatorio de 10 bits donde a cada flanco de clk el
valor se desplaza un bit a la derecha. La salida del multiplexor se carga en un registro
rotatorio de 8 bits. Este último registro se desplaza un bit a la izquierda a cada flanco
de clk.
Al registro acumulador de salida se le suma, o no, el valor del registro rotatorio
de 10 bits, según el valor del bit de más peso del registro de 8 bits sea ‘1’ o ‘0’.
38
Memoria Descriptiva
Figura 34. Amplificador
La entidad VHDL es:
entity amplificador is port(
reset:in std_logic;
clk:in std_logic;
clk512:in std_logic;
amplificacion:in std_logic_vector(7 downto 0);
multiplicando:in std_logic_vector(7 downto 0);
resultado:out std_logic_vector(9 downto 0)
);
end amplificador;
Código 18: amplificador
Nota: La entrada multiplicando se corresponde con la entrada sal_mux del
esquema. La salida resultado se corresponde con la salida1 del esquema. La entrada
start no aparece en la entidad puesto que, como se ha comentado anteriormente, en el
código VHDL se ha integrado el bloque inicio en el bloque amplificador.
Obsérvese que la multiplicación se realiza en orden inverso, es decir, del valor
más significativo al menos significativo. De esta forma se consigue no introducir error
al utilizar registros de 10 bits en lugar de 16, puesto que como se ha comentado
anteriormente sólo interesan los 8 bits de más peso del resultado.
39
Memoria Descriptiva
En el bloque sumador se trunca el resultado de la multiplicación de 10 a 8 bits
para posteriormente sumarle el offset (tal y como se ha explicado anteriormente sólo
nos interesan los 8 bits de más peso). Trabajaremos con registros de 9 bits ya que la
suma de dos valores de 8 bits puede generar un valor de 9.
Figura 35. Sumador
Este bloque se implementa en dos entidades, una para hacer la adquisición de
datos y otra para realizar la suma:
entity adquisicion is port(
offset:in std_logic_vector(7 downto 0);
sal_amp:in std_logic_vector(9 downto 0);
operandoA:out unsigned(8 downto 0);
operandoB:out unsigned(8 downto 0)
);
end adquisicion;
Código 19: adquisición
entity sumador9bits is port(
sumandoA:in unsigned(8 downto 0);
sumandoB:in unsigned(8 downto 0);
salida2:out std_logic_vector(8 downto 0)
);
end sumador9bits;
Código 20: sumador9bits
40
Memoria Descriptiva
En el bloque limitador cuando el bit de más peso de la entrada es ‘1’ indica
que al sumar el offset hemos sobrepasado el valor máximo de salida, por tanto se
recorta la señal manteniéndola al valor máximo posible (“11111111”).
Figura 36. Limitador
La entidad VHDL es:
entity limitador is port(
entrada:in std_logic_vector(8 downto 0);
salida3:out std_logic_vector(7 downto 0)
);
end limitador;
Código 21: Limitador
El funcionamiento del bloque amplificador offset quedará más claro en los
siguientes ejemplos:
Ejemplo1:
Supongamos que introducimos un valor de amplificación de “11111111”, es
decir no queremos atenuar la señal y queremos que sus valores varíen entre
“00000000” y “11111111” y añadimos un offset de “00000100”. En este caso la señal
resultará:
Figura 37. Señal recortada
41
Memoria Descriptiva
Ejemplo2:
Supongamos que introducimos un valor de amplificación “11100111”, es
decir queremos atenuar la señal y queremos que sus valores varíen entre “00000000”
y “11100111” y añadimos un offset de “00000100”. En este caso la señal resultará:
Figura 38. Señal atenuada
42
Memoria Descriptiva
1.2.6 Convertidor DA
Para convertir el valor de 8 bits de salida del generador digital se utilizará un
convertidor DA con las siguientes características:
Figura 39. Convertidor DA
La salida proporcionará una corriente de Iref·n/256, donde n será un valor
entre 0 y 255 proporcionado por la salida de la FPGA.
Cuando la entrada digital sea “11111111” Io proporcionará el valor máximo de
corriente (Iref).
El convertidor elegido ha sido un DAC08Q, debido a su reducido coste y a sus
características que se adecuan a las especificaciones del diseño. Proporciona
velocidades de conversión de hasta 1 µs. Teniendo en cuenta los periodos con los que
trabajamos, esta velocidad de conversión será más que suficiente.
A la salida del convertidor DA sería necesaria una etapa de potencia que
amplificara la intensidad Iref hasta los 150 mA requeridos.
43
Memoria Descriptiva
1.2.7 Placa de Pruebas
Para verificar el correcto funcionamiento del generador de funciones se ha
diseñado una placa que, conectada a la placa de XILINX(FPGA demonstration
board), permite introducir entradas a la FPGA y recibir la salida digital para su
conversión a analógica Vo que podrá ser visualizada en el osciloscopio.
Figura 40. Amplificador de corriente
El banco de interruptores S1 corresponde a la entrada del generador
amplificacion. LO y HI indica la posición en que el interruptor proporciona un ‘0’ o
un ‘1’ lógico respectivamente (+5V o 0V), en este caso cuando el interruptor está
cerrado proporciona un ‘0’ y cuando está abierto proporciona un ‘1’. El interruptor
marcado con un 1 corresponde al bit de más peso de la entrada. De izquierda a
derecha obtenemos desde amplificación(7) hasta amplificacion(0).
S2 corresponde a la entrada periodo. El primer interruptor por la izquierda
corresponde también al bit de más peso. Cuando el interruptor está abierto
proporciona un ‘0’ y cuando está cerrado un ‘1’.
S3 es la entrada desplazamiento. Igual que en las entradas anteriores el
primer interruptor de la izquierda corresponde al bit de más peso.
En S4 el primer interruptor de la izquierda corresponde a la entrada de reset
del generador, y los dos siguientes a la entrada de selección de señal, selec(1) y
selec(0) respectivamente.
Nota: La entrada de offset la proporcionará el banco de interruptores SW-3
de la placa de XILINX. El primer interruptor empezando por arriba corresponde al
bit de más peso offset(7). Para localizar SW-3 remitirse al plano de situación de
componentes de la placa FPGA demonstration board.
44
Memoria Descriptiva
JP1,JP2, y JP3 son conectores de 22 pins que permiten la conexión mediante
cable de bus con la placa de XILINX (FPGA design demonstration board).
Vcc es la alimentación de 5 V que permite introducir ‘1’ y ‘0’ lógicos.
Vref son los 10 V que necesita el convertidor DA para proporcionar una
intensidad de referencia de 2 mA.
V+ y V- corresponden a la alimentación del convertidor DA, +15 y –15
respectivamente.
Vo es la salida que proporciona el convertidor. Será una tensión con la forma
de onda seleccionada y comprendida entre 0 y –10 V.
1.2.7.1 Conexión del Convertidor DA
Como se ha comentado anteriormente, este proyecto se centra en la generación
de la señal digital y su posterior conversión a analógica, por tanto en la placa de
pruebas se conecta el convertidor DA de la siguiente manera:
Figura 41. Conexión del Convertidor DA
Utilizando la resistencia adecuada se podrá visualizar la señal en el
osciloscopio y verificar que el generador de funciones se comporta de la forma
esperada. La tensión generada a la salida será negativa, puesto que la corriente es
entrante al convertidor.
45
Memoria Descriptiva
1.2.7.2 Conexión de los Interruptores
Los interruptores de S1 y S4 están conectados a pins de la FPGA que por
defecto tienen la siguiente configuración en la placa de XILINX:
Figura 42. Pin conectado a LED
Cuando el pin se utiliza como salida, según si proporciona un “0” o un “1”
(5 V o 0V) el diodo LED se enciende o no.
Cuando se utiliza como entrada, como es el caso el pin permanece en alta
impedancia, por tanto se produce un divisor de tensión entre la resistencia de 560 Ω y
una resistencia de valor muy elevado, quedando a la entrada del pin aproximadamente
5 v. Es decir, por defecto el pin tiene asignado un “1” lógico. Por tanto si conectamos
el interruptor de la siguiente manera:
Figura 43. Conexión de S1
se consigue que cuando el interruptor está cerrado hay una conexión directa a masa.
Es decir, cuando el interruptor está abierto hay un “1” lógico y cuando está cerrado un
“0”.
Los interruptores de S2 y S3 en cambio, están conectados a pins que no
tienen por defecto asignados ningún valor de tensión. Cuando se utilizan como
entrada, estos pins permanecen en alta impedancia. Para poder introducir “1” y “0”
lógicos se deben utilizar resistencias de Pull Up conectadas a los interruptores, tal y
como muestra la figura :
46
Memoria Descriptiva
Figura 44. Conexión de S2
Cuando el interruptor esté cerrado proporcionará un “1” lógico (5V) y
cuando esté abierto un “0”.
1.2.7.3 Correspondencia de Pins entre la Placa de XILINX y la Placa de Pruebas
El pin 13 de la FPGA se utiliza como entrada externa de reloj.
Los pins 19,20,23,24,25,26,27,28 están conectados al banco de interruptores
SW-3 en la placa de XILINX.
1.2.8 Programación de la FPGA
La placa de XILINX (FPGA design demonstration board) contiene dos FPGA,
la XC3020A y la XC4003E. Estas pueden programarse de 4 formas diferentes:
-
Con el Xchecker/Parallel cable III: Este cable se conecta al ordenador y
permite descargar en la FPGA el archivo con extensión .BIT generado al
sintetizar el código VHDL.
47
Memoria Descriptiva
-
Con una PROM serie (programa único): El programa se carga en la FPGA
desde una PROM que ha sido gravada previamente.
-
Con una PROM serie (programa múltiple): Este modo de programación
permite tener gravados varios programas diferentes en la PROM y poder
cargar en la FPGA cualquiera de ellos, permitiendo de esta manera
alternar a la FPGA entre varias funciones diferentes.
-
En daisy chain: Permite utlizar ambas FPGA a la vez conectadas entre
ellas en modo daisy chain.
Para verificar el diseño sólo se necesita una FPGA, por tanto utilizaremos la
XC4003E. La programación se realiza a través del cable Xchecker.
1.2.8.1 Configuración de la XC4003E a través del Xchecker/Parallel cable III
Para gravar la FPGA a través del cable paralelo es necesario situar los pins de
los interruptores SW1 y SW2 de la siguiente manera:
Interruptor Nombre
Posición
Interruptor Nombre
Posición
SW1-1
INP
X
SW2-1
PWR
X
SW1-2
MPE
X
SW2-2
MPE
OFF
SW1-3
SPE
X
SW2-3
SPE
OFF
SW1-4
MO
X
SW2-4
MO
ON
SW1-5
M1
X
SW2-5
M1
ON
SW1-6
M2
X
SW2-6
M2
ON
SW1-7
MCLK
OFF
SW2-7
RST
X
SW1-8
DOUT
OFF
SW2-8
INIT
OFF
La X indica que no importa la posición.
Nota: Para una información precisa del funcionamiento de la placa de demostración
remitirse a la Hardware User Guide of the FPGA Design Demonstraton Board de la
compañía XILINX.
48
Memoria de Cálculo
2
Memoria de Cálculo
2.1
Cálculo de la Frecuencia del Reloj Externo
En el apartado 1.2.4.1 se ha obtenido la expresión (1) Tclk8 = 8·Tclk y en el
apartado 1.2.4.2 la expresión (2) Tclk512 = 2·periodo·Tclk8. A partir de estas
expresiones se puede comprobar que:
Tclk512 = 16·periodo· Tclk8
(5)
En el apartado 1.2.4.4 se han obtenido las expresiones (3) Tseñal=512·Tclk512
y (4) Tdesp = desplazamiento·Tclk512. A partir de la expresión (5) se obtiene que:
Tseñal = 512·16·periodo·Tclk
(6)
Tdesp = desplazamiento ·16·periodo·Tclk512 (7)
El diseño requiere un periodo mínimo de señal de 0.1 s, que será cuando la
entrada externa periodo valga “00000001”. En este caso:
0,1 = 512·16·1·Tclk
Tclk = 12.2 µs
Es decir, necesitamos un reloj externo de frecuencia 81,92 kHz.
La entrada externa periodo es un valor comprendido entre 0 y 255, por tanto
con este reloj conseguiremos periodos de señal de:
Tseñal = 0,1·periodo (8)
Es decir valores comprendidos entre 0,1 s y 25.5 s. Ajustándose a las
especificaciones del diseño.
El tiempo durante el cual la señal permanece en reposo (Tdesp) comprenderá
valores entre 0.05 s y 12.75 s.
2.2
Frecuencia del Reloj Externo para la Verificación del Diseño
Con los periodos obtenidos en el apartado anterior no sería posible visualizar
la señal en el osciloscopio, por tanto para realizar la comprobación del correcto
funcionamiento del generador de funciones se utiliza una señal de reloj externa de
10 Mhz, es decir 10µ
µs de periodo. A partir de la expresión (6) comprobamos que:
Tseñal = 512·16·periodo·6·10-6
(9)
Obteniendo periodos comprendidos entre 49,15 µs y 12.53 ms. O lo que es lo
mismo frecuencias comprendidas entre 20,346 kHz y 79,8 Hz. Frecuencias que
pueden visualizarse sin problemas en el osciloscopio.
49
Memoria de Cálculo
2.3
Cálculo de los Valores de la ROM
Para conseguir los 64 valores de la onda senoidal comprendidos entre
“00000000” y “11111111” (0 y 255 en decimal) calcularemos con Excel una tabla
con 64 puntos significativos de una función senoidal, obteniendo los siguientes
resultados:
Senoide
300
250
200
150
Senoide
100
50
0
1
7 13 19 25 31 37 43 49 55 61
Figura 45. Gráfica de la senoide
50
Memoria de Cálculo
0
127
27
205
54
250
1
130
28
207
55
250
2
133
29
209
56
251
3
136
30
212
57
252
4
139
31
214
58
252
5
142
32
216
59
253
6
145
33
218
60
253
7
148
34
221
61
253
8
151
35
223
62
253
9
154
36
225
63
253
10
157
37
227
11
160
38
229
12
163
39
230
13
166
40
232
14
169
41
234
15
172
42
235
16
175
43
237
17
178
44
239
18
181
45
240
19
184
46
241
20
186
47
243
21
189
48
244
22
192
49
245
23
194
50
246
24
197
51
247
25
200
52
248
26
202
53
249
Tabla1. Valores de la ROM
51
Memoria de Cálculo
2.4
Cálculo de Componentes para el Convertidor DA
En el diseño se utiliza un DAC08. Este convertidor necesita una intensidad de
referencia de 2 mA que se suministra de la siguiente manera:
Figura 46. Iref del cDA
La tensión de referencia Vref es de 10 V, por tanto:
Rref = 10 V /2 mA = 5 kΩ
Ω
La intensidad de salida variará por tanto entre 0 y 2 mA. Posteriormente sólo
se necesitaría una etapa de potencia de ganancia 75 para proporcionar los 150 mA
requeridos por el diseño.
2.5
Convertidor DA en la Placa de Pruebas
Figura 47. Vo del cDA
Sabiendo que Io varía entre 0 y 2 mA, utilizando una RL de 5 kΩ
Ω , podremos
visualizar en el osciloscopio valores de tensión comprendidos entre 0 y –10 V.
52
Memoria de Planos
3
Memoria de Planos
3.1
Placa de Pruebas
3.1.1 Situación de Componentes
53
Memoria de Planos
3.1.2 Esquema Eléctrico de ORCAD.
54
Memoria de Planos
3.1.3 Listado de Componentes
Item
Cantidad
Referencia
Parte
1
1
DAC
DAC08EQ
2
3
JP1,JP2,JP3
HEADER 11x2
3
2
RN1,RN2
ARRAYS 4K7
4
1
C1
0.01 u
5
2
C2,C3
0.1 u
6
4
S1,S2,S3,S4
SW DIP-8
7
3
RG1,RG2,RG3
REGLETAS-x2
Todas las resistencias son de carbono ¼ W y 10% de tolerancia.
Condensadores C1,C2,C3 de poliester.
Conectores JP1 y JP2 Headers de pins machos para PCB.
DAC08EQ convertidor digital analógico estándar con salida de corriente.
RN1,RN2 arrays de 9 pins y 8 resistencias con masa común.
RG1,RG2,RG3, regletas comunes de 2 conexiones.
55
Memoria de Planos
3.2
FPGA Design Demonstration Board
3.2.1 Situación de Componentes
56
Memoria de Planos
3.2.2 Esquema Eléctrico
57
Memoria de Planos
3.3
Diagrama de Conexión General
Este diagrama está con la finalidad de facilitar la interpretación de cómo hay
que unir la placa de pruebas con la placa de XILINX (FPGA demonstration board). Es
necesario fijarse en la posición de los buses y los conectores que los unen. Los pins
marcados en negro son los pins que nos se utilizan y que pueden servir de referencia
para el conector del bus.
58
Anexos
4
Anexos
4.1
Código VHDL y simulación con VERIBEST
La simulación del generador se realiza con el paquete de software VERIBEST.
El VHDL tiene estructura jerárquica, es decir, una entidad no puede contener
un componente que no haya sido declarado previamente. Siempre hay una entidad
principal que engloba y relaciona el resto de entidades. En este caso se trata de la
entidad generador:
Cada una de estas entidades contiene a su vez otras como se irá viendo.
A continuación se mostrará el código de cada entidad y de su correspondiente
arquitectura junto con su simulación.
Nota: Todas las entidades utilizan las librerías estándar del IEEE:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
4.1.1 clk
Para realizar la simulación es necesario simular una señal de reloj. En este caso
se ha optado por una de 1µs, para que la simulación sea más rápida.
--- Declaración del reloj --entity reloj is port (
clk:out std_logic
);
end reloj;
--- Temporizacion del reloj --architecture tiempo of reloj is
59
Anexos
begin
clock_driver:process
begin
clk<='0','1' after 0.5 us;
wait for 1 us;
end process clock_driver;
end tiempo;
4.1.2 Divisor por 8
--- divisor por 8 --entity divisor8 is port (
reset:in std_logic;
clk:in std_logic;
clk8:out std_logic
);
end divisor8;
architecture clock8 of divisor8 is
signal contador:unsigned(2 downto 0);
begin
process (clk,reset)
begin
if (reset='1') then
contador<="000";
clk8<='0';
elsif (clk' event and clk ='1') then
contador<=contador + 1;
clk8<=std_logic(contador(2));
60
Anexos
end if;
end process;
end clock8;
La simulación de esta entidad es:
4.1.3 Divisor de frecuencia
--- Declaración del divisor de frecuencia --entity divis_frec is port (
reset:in std_logic;
clk8:in std_logic;
clk512:out std_logic;
periodo:in std_logic_vector(7 downto 0)
);
end divis_frec;
--- divisor de frecuencia --architecture clock512 of divis_frec is
signal periodo_aux: unsigned (7 downto 0);
signal clk512aux:std_logic;
begin
process (clk8,reset)
begin
if (reset ='1') then
periodo_aux<="00000001";
61
Anexos
clk512aux<='0';
elsif (clk8' event and clk8 ='1') then
if (periodo="00000000") then
clk512aux<=clk512aux;
periodo_aux<="00000001";
elsif ((periodo_aux)=unsigned(periodo)) then
clk512aux<=not(clk512aux);
periodo_aux<="00000001";
else
clk512aux<=clk512aux;
periodo_aux<=periodo_aux+1;
end if;
end if;
end process;
clk512<=clk512aux;
end clock512;
La simulación de esta entidad con una entrada de periodo “00000001” es:
4.1.4 Contador i_d_desp
Esta entidad está compuesta por otras 5:
---- conjunto (contador incremental_decremental con desplazamiento de señal
entity contador is port(
reset:in std_logic;
62
Anexos
clk512:in std_logic;
desplazamiento:in std_logic_vector(7 downto 0);
conta0:out std_logic_vector(7 downto 0);
creciente:out std_logic_vector(1 downto 0)
);
end contador;
architecture secuencia_principal of contador is
signal e1,e2,e3:std_logic;
signal f1,f2,f3:std_logic;
signal canal1,canal2:std_logic_vector(7 downto 0);
component bloque_estado port(
clk512:in std_logic;
f1,f2,f3:in std_logic;
reset:in std_logic;
e1,e2,e3:out std_logic
);
end component;
component cont_up_dwn port(
clk512:in std_logic;
reset:in std_logic;
e1,e2:in std_logic;
f1,f2:out std_logic;
contupdwn:out std_logic_vector(7 downto 0)
);
end component;
component cont_desp port(
clk512:in std_logic;
e3,reset:in std_logic;
desplazamiento:in std_logic_vector(7 downto 0);
reg_cero:out std_logic_vector(7 downto 0);
f3:out std_logic
63
Anexos
);
end component;
component multiplex2canales port(
e3:in std_logic;
canal1,canal2:in std_logic_vector(7 downto 0);
salmux:out std_logic_vector(7 downto 0)
);
end component;
component codificador port(
e1,e2,e3:in std_logic;
creciente:out std_logic_vector(1 downto 0)
);
end component;
begin
be:bloque_estado
port map(clk512=>clk512,reset=>reset,f1=>f1,
f2=>f2,f3=>f3,e1=>e1,e2=>e2,e3=>e3);
cud:cont_up_dwn
portmap(clk512=>clk512,reset=>reset,e1=>e1,e2=>e2,f1=>f1,f2=>f2,
contupdwn=>canal1);
cd:cont_desp
port map(reset=>reset,clk512=>clk512,e3=>e3,
f3=>f3,desplazamiento=>desplazamiento,reg_cero=>canal2);
m2c:multiplex2canales
port map(e3=>e3,canal1=>canal1,canal2=>canal2,salmux=>conta0);
codif:codificador
port map(e1=>e1,e2=>e2,e3=>e3,creciente=>creciente);
end secuencia_principal;
64
Anexos
La simulación de esta entidad con una entrada de desplazamiento
“00000000” es:
Se puede observar el momento en que el contador llega al valor máximo y
comienza a decrecer.
4.1.4.1 Generador de estado
---- generador de estado ----library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity bloque_estado is port(
clk512:in std_logic;
f1,f2,f3:in std_logic;
reset:in std_logic;
e1,e2,e3:out std_logic
);
end bloque_estado;
architecture gen_estado of bloque_estado is
begin
process (reset,clk512)
begin
if (reset='1') then
e1<='1';
e2<='0';
e3<='0';
else
65
Anexos
if (clk512' event and clk512='1') then
if (f1='1') then
e1<='0';
e2<='1';
e3<='0';
else
if (f2='1') then
e1<='0';
e2<='0';
e3<='1';
else
if (f3='1') then
e1<='1';
e2<='0';
e3<='0';
end if;
end if;
end if;
end if;
end if;
end process;
end gen_estado;
En la simulación de esta entidad se puede observar la transición del contador
de creciente a decreciente:
66
Anexos
4.1.4.2 Contador up/dwn
---- contador incremental_decremental ----entity cont_up_dwn is port(
clk512:in std_logic;
reset:in std_logic;
e1,e2:in std_logic;
f1,f2:out std_logic;
contupdwn:out std_logic_vector(7 downto 0)
);
end cont_up_dwn;
architecture arc_cont_up_dwn of cont_up_dwn is
signal contaux: unsigned(7 downto 0);
signal maximo: unsigned(7 downto 0);
signal minimo: unsigned(7 downto 0);
begin
maximo<="11111101";
minimo<="00000010";
process (clk512,reset)
begin
if (reset='1') then
67
Anexos
contaux<="00000000";
f1<='0';
f2<='0';
maximo<="11111101";
minimo<="00000010";
else
if (clk512' event and clk512='1') then
if ((e1 xor e2)='1') then
case e1 is
when '1' => contaux<=contaux + 1;
when others => contaux<=contaux - 1;
end case;
if (contaux=maximo and (e1='1')) then
f1<='1';
else
f1<='0';
end if;
if (contaux=minimo and (e2='1')) then
f2<='1';
else
f2<='0';
end if;
end if;
end if;
end if;
end process;
contupdwn<=std_logic_vector(contaux);
end arc_cont_up_dwn;
68
Anexos
Se puede observar un ciclo de transición del contador.
4.1.4.3 Contador de desplazamiento
---- contador de desplazamiento ---entity cont_desp is port(
clk512:in std_logic;
e3,reset:in std_logic;
desplazamiento:in std_logic_vector(7 downto 0);
reg_cero:out std_logic_vector(7 downto 0);
f3:out std_logic
);
end cont_desp;
architecture arc_cont_desp of cont_desp is
signal contadesp:unsigned(7 downto 0);
begin
reg_cero<="00000000";
process(clk512,reset)
begin
if (reset = '1') then
contadesp<="00000000";
f3<='0';
69
Anexos
else
if (clk512' event and clk512='1') then
if (e3='1') then
if (contadesp=unsigned(desplazamiento)) then
contadesp<="00000000";
f3<='1';
else
contadesp<= contadesp + 1;
f3<='0';
end if;
else
contadesp<=contadesp;
f3<='0';
end if;
end if;
end if;
end process;
end arc_cont_desp;
La simulación de esta entidad cuando la entrada desplazamiento es
“00000001” es la siguiente :
70
Anexos
4.1.4.4 Multiplexor de dos canales
entity multiplex2canales is port(
e3:in std_logic;
canal1,canal2:in std_logic_vector(7 downto 0);
salmux:out std_logic_vector(7 downto 0)
);
end multiplex2canales;
architecture arc_multiplex2canales of multiplex2canales is
begin
process (e3,canal1,canal2)
begin
case e3 is
when '0' => salmux<=canal1;
when others => salmux<=canal2;
end case;
end process;
end arc_multiplex2canales;
Esta entidad simplemente selecciona la salida del cont up/dwn o del contador
desplazamiento.
71
Anexos
4.1.4.5 Codificador
---- codificacion del estado ----entity codificador is port(
e1,e2,e3:in std_logic;
creciente:out std_logic_vector(1 downto 0)
);
end codificador;
architecture arc_codificador of codificador is
begin
process (e1,e2,e3)
begin
if e1='1' then
creciente <="01";
else
if e2='1' then
creciente <= "10";
else
creciente <= "11";
end if;
end if;
end process;
end arc_codificador;
72
Anexos
Podemos observar la transición entre creciente = “01”, el contador está en un
ciclo de subida, y creciente = “10”, el contador está en un ciclo de bajada.
4.1.5 Diente de sierra
--- diente de sierra --entity diente_sierra is port (
creciente:in std_logic_vector(1 downto 0);
conta0:in std_logic_vector(7 downto 0);
conta1:out std_logic_vector(7 downto 0)
);
end diente_sierra;
architecture secuencia1 of diente_sierra is
signal contaux:unsigned(7 downto 0);
begin
process (conta0,creciente)
begin
case creciente is
when "01" => contaux<="00000000"+unsigned(conta0(7 downto 1));
when "10" => contaux<="11111111"-unsigned(conta0(7 downto 1));
when others => contaux<=unsigned(conta0);
end case;
end process;
conta1<=std_logic_vector(contaux);
end secuencia1;
73
Anexos
Se puede comprobar como conta1 evoluciona cada 2 ciclos de conta0.
4.1.6 Rectangular
---- Rectangular -----entity rectangular is port (
creciente:in std_logic_vector(1 downto 0);
conta2:out std_logic_vector(7 downto 0)
);
end rectangular;
architecture secuencia2 of rectangular is
begin
process(creciente)
begin
if (creciente="11") then
conta2<="00000000";
else
conta2<="11111111";
end if;
end process;
end secuencia2;
74
Anexos
Se puede observar como conta2 permanece a “11111111” cuando creciente es
“01” o “00”, y a “00000000” cuando creciente es “11”.
4.1.7 Triangular
---- Triangular -----entity triangular is port (
conta0:in std_logic_vector(7 downto 0);
conta3:out std_logic_vector(7 downto 0)
);
end triangular;
architecture secuencia4 of triangular is
begin
process(conta0)
begin
conta3<=conta0;
end process;
end secuencia4;
El valor de conta3 es el mismo que el de conta0, tal y como se había explicado
anteriormente.
75
Anexos
4.1.8 Senoidal
---- Senoidal -----entity senoidal is port (
creciente:in std_logic_vector(1 downto 0);
conta0:in std_logic_vector(7 downto 0);
direccion:out std_logic_vector(5 downto 0)
);
end senoidal;
architecture secuencia5 of senoidal is
signal contaux:unsigned(5 downto 0);
begin
process (conta0,creciente)
begin
case creciente is
when "01" =>
if (conta0(7)='0') then
contaux<=unsigned(conta0(6 downto 1));
else
contaux<="111111"-unsigned(conta0(6 downto 1));
end if;
when "10" =>
if (conta0(7)='1') then
contaux<="111111"-unsigned(conta0(6 downto 1));
else
contaux<=unsigned(conta0(6 downto 1));
end if;
when others => contaux<=unsigned(conta0(6 downto 1));
end case;
76
Anexos
end process;
direccion<=std_logic_vector(contaux);
end secuencia5;
En la gráfica se puede ver como evoluciona direccion en función de conta0.
4.1.9 ROM
---- ROM -----entity ROM is port (
direccion:in std_logic_vector(5 downto 0);
contenido:out std_logic_vector(7 downto 0)
);
end ROM;
architecture acceso of ROM is
begin
process(direccion)
begin
case direccion is
when
when
when
when
when
when
when
"000000"
"000001"
"000010"
"000011"
"000100"
"000101"
"000110"
=>
=>
=>
=>
=>
=>
=>
77
contenido<="01111111";
contenido<="10000010";
contenido<="10000101";
contenido<="10001000";
contenido<="10001011";
contenido<="10001110";
contenido<="10010001";
Anexos
when "000111" => contenido<="10010100";
when "001000" => contenido<="10010111";
when "001001" => contenido<="10011010";
when "001010" => contenido<="10011101";
when "001011" => contenido<="10100000";
when "001100" => contenido<="10100011";
when "001101" => contenido<="10100110";
when "001110" => contenido<="10101001";
when "001111" => contenido<="10101100";
when "010000" => contenido<="10101111";
when "010001" => contenido<="10110010";
when "010010" => contenido<="10110101";
when "010011" => contenido<="10111000";
when "010100" => contenido<="10111010";
when "010101" => contenido<="10111101";
when "010110" => contenido<="11000000";
when "010111" => contenido<="11000010";
when "011000" => contenido<="11000101";
when "011001" => contenido<="11001000";
when "011010" => contenido<="11001010";
when "011011" => contenido<="11001101";
when "011100" => contenido<="11001111";
when "011101" => contenido<="11010001";
when "011110" => contenido<="11010100";
when "011111" => contenido<="11010110";
when "100000" => contenido<="11011000";
when "100001" => contenido<="11011010";
when "100010" => contenido<="11011101";
when "100011" => contenido<="11011111";
when "100100" => contenido<="11100001";
when "100101" => contenido<="11100011";
when "100110" => contenido<="11100101";
when "100111" => contenido<="11100110";
when "101000" => contenido<="11101000";
when "101001" => contenido<="11101010";
when "101010" => contenido<="11101011";
when "101011" => contenido<="11101101";
when "101100" => contenido<="11101111";
when "101101" => contenido<="11110000";
when "101110" => contenido<="11110001";
when "101111" => contenido<="11110011";
when "110000" => contenido<="11110100";
when "110001" => contenido<="11110101";
when "110010" => contenido<="11110110";
78
Anexos
when "110011" => contenido<="11110111";
when "110100" => contenido<="11111000";
when "110101" => contenido<="11111001";
when "110110" => contenido<="11111010";
when "110111" => contenido<="11111010";
when "111000" => contenido<="11111011";
when "111001" => contenido<="11111100";
when "111010" => contenido<="11111100";
when "111011" => contenido<="11111101";
when "111100" => contenido<="11111101";
when "111101" => contenido<="11111101";
when "111110" => contenido<="11111101";
when "111111" => contenido<="11111101";
when others => contenido<="00000000";
end case;
end process;
end acceso;
Se puede comprobar como a cada valor de direccion la ROM proporciona un
valor (contenido).
4.1.10 Inversor
---- Inversor de los datos de la ROM -----entity inversor is port (
creciente:in std_logic_vector(1 downto 0);
contenido:in std_logic_vector(7 downto 0);
conta4:out std_logic_vector(7 downto 0)
);
end inversor;
architecture tratamiento of inversor is
signal auxiliar:unsigned(7 downto 0);
79
Anexos
begin
process(contenido,creciente)
begin
if (creciente="10") then
auxiliar<="11111111" - unsigned(contenido);
else
auxiliar<=unsigned(contenido);
end if;
end process;
conta4<=std_logic_vector(auxiliar);
end tratamiento;
Cuando creciente = “10” conta4 invierte el contenido de la ROM.
4.1.11 Conjunto
Este bloque no tiene representación en la memoria descriptiva. Se incluye
simplemente para combinar la generación de los cuatro tipos de señales en una sóla
entidad de manera que luego sea más sencilla su multiplexación.
80
Anexos
---conjunto--library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
entity conjunto is port(
reset:in std_logic;
clk512:in std_logic;
periodo:in std_logic_vector(7 downto 0);
desplazamiento:in std_logic_vector(7 downto 0);
A:out std_logic_vector(7 downto 0);
B:out std_logic_vector(7 downto 0);
C:out std_logic_vector(7 downto 0);
D:out std_logic_vector(7 downto 0)
);
end conjunto;
architecture arq_conjunto of conjunto is
signal
signal
signal
signal
creciente:std_logic_vector(1 downto 0);
conta0:std_logic_vector(7 downto 0);
direccion:std_logic_vector(5 downto 0);
contenido:std_logic_vector(7 downto 0);
component contador port (
reset:in std_logic;
clk512:in std_logic;
desplazamiento:in std_logic_vector(7 downto 0);
conta0:out std_logic_vector(7 downto 0);
creciente:out std_logic_vector(1 downto 0)
);
end component;
component diente_sierra port (
creciente:in std_logic_vector(1 downto 0);
conta0:in std_logic_vector(7 downto 0);
81
Anexos
conta1:out std_logic_vector(7 downto 0)
);
end component;
component rectangular port (
creciente:in std_logic_vector(1 downto 0);
conta2:out std_logic_vector(7 downto 0)
);
end component;
component triangular is port (
conta0:in std_logic_vector(7 downto 0);
conta3:out std_logic_vector(7 downto 0)
);
end component;
component senoidal is port (
creciente:in std_logic_vector(1 downto 0);
conta0:in std_logic_vector(7 downto 0);
direccion:out std_logic_vector(5 downto 0)
);
end component;
component ROM is port (
direccion:in std_logic_vector(5 downto 0);
contenido:out std_logic_vector(7 downto 0)
);
end component;
component inversor is port (
creciente:in std_logic_vector(1 downto 0);
contenido:in std_logic_vector(7 downto 0);
conta4:out std_logic_vector(7 downto 0)
);
end component;
82
Anexos
begin
ct:contador
port
map(reset=>reset,clk512=>clk512,desplazamiento=>desplazamiento,
creciente=>creciente,conta0=>conta0);
sierra:diente_sierra
port map(creciente=>creciente,conta0=>conta0,conta1=>A);
rect:rectangular
port map(creciente=>creciente,conta2=>B);
triang:triangular
port map(conta0=>conta0,conta3=>C);
sen:senoidal
port map(creciente=>creciente,conta0=>conta0,
direccion=>direccion);
memoria:ROM
port map(direccion=>direccion,contenido=>contenido);
tractament:inversor
port map(creciente=>creciente,contenido=>contenido,conta4=>D);
end arq_conjunto;
En este gráfico se puede ver la evolución simultánea de los cuatro tipos de
señales.
83
Anexos
4.1.12 Multiplexor
---multiplexor--entity multiplexor is port(
A:in std_logic_vector(7 downto 0);
B:in std_logic_vector(7 downto 0);
C:in std_logic_vector(7 downto 0);
D:in std_logic_vector(7 downto 0);
selec:in std_logic_vector(1 downto 0);
salida_mult:out std_logic_vector(7 downto 0)
);
end multiplexor;
architecture seleccion of multiplexor is
begin
process(selec,A,B,C,D)
begin
case selec is
when
when
when
when
"00" => salida_mult<=A;
"01" => salida_mult<=B;
"10" => salida_mult<=C;
others => salida_mult<=D;
end case;
end process;
end seleccion;
84
Anexos
Se puede comprobar que cuando selec = “10” a la salida del multiplexor se
obtiene la señal triangular. Si fuera “00” se obtendría la de diente de sierra y así
sucesivamente.
4.1.13 Amplificador_ofsset
Esta entidad tiene cuatro componentes como se observa a continuación:
--- Bloque amplificador offset ----entity amplif_offset is port (
reset:in std_logic;
clk,clk512:in std_logic;
offset:in std_logic_vector(7 downto 0);
amplificacion:in std_logic_vector(7 downto 0);
multiplicando:in std_logic_vector(7 downto 0);
sal_amp_off:out std_logic_vector(7 downto 0)
);
end amplif_offset;
85
Anexos
architecture arc_amplif_offset of amplif_offset is
signal
signal
signal
signal
sal_amp:std_logic_vector(9 downto 0);
operandoA:unsigned(8 downto 0);
operandoB:unsigned(8 downto 0);
salida2:std_logic_vector(8 downto 0);
component amplificador port(
reset:in std_logic;
clk:in std_logic;
clk512:in std_logic;
amplificacion:in std_logic_vector(7 downto 0);
multiplicando:in std_logic_vector(7 downto 0);
resultado:out std_logic_vector(9 downto 0)
);
end component;
component adquisicion port(
offset:in std_logic_vector(7 downto 0);
sal_amp:in std_logic_vector(9 downto 0);
operandoA:out unsigned(8 downto 0);
operandoB:out unsigned(8 downto 0)
);
end component;
component sumador9bits port(
sumandoA:in unsigned(8 downto 0);
sumandoB:in unsigned(8 downto 0);
salida2:out std_logic_vector(8 downto 0)
);
end component;
component limitador port(
entrada:in std_logic_vector(8 downto 0);
salida3:out std_logic_vector(7 downto 0)
);
end component;
begin
amp:amplificador
port map(reset=>reset,clk=>clk,clk512=>clk512,
amplificacion=>amplificacion,multiplicando=>multiplicando,
resultado=>sal_amp);
86
Anexos
adq:adquisicion
port map(offset=>offset,sal_amp=>sal_amp,
operandoA=>operandoA,operandoB=>operandoB);
sum:sumador9bits
port
map(sumandoA=>operandoA,
sumandoB=>operandoB,salida2=>salida2);
lim:limitador
port map(entrada=>salida2,salida3=>sal_amp_off);
end arc_amplif_offset;
A cada flanco de clk512 se le aplica un factor de atenuación a la entrada
multiplicando. Se puede comprobar que el proceso requiere de varios flancos de clk.
4.1.13.1 Amplificador
El amplificador necesita para funcionar una puerta XOR que se muestra a
continuación:
---- Puerta XOR ---entity puerta_xor is port(
s1:in std_logic;
s2:in std_logic;
start:out std_logic
);
end puerta_xor;
87
Anexos
architecture set_multiplic of puerta_xor is
begin
process (s1,s2)
begin
start<=s1 xor s2;
end process;
end set_multiplic;
---- Amplificacion ------entity amplificador is port(
reset:in std_logic;
clk:in std_logic;
clk512:in std_logic;
amplificacion:in std_logic_vector(7 downto 0);
multiplicando:in std_logic_vector(7 downto 0);
resultado:out std_logic_vector(9 downto 0)
);
end amplificador;
architecture arc_amplificador of amplificador is
component puerta_xor is port(
s1:in std_logic;
s2:in std_logic;
start:out std_logic
);
end component;
signal
signal
signal
signal
signal
signal
s1:std_logic;
s2:std_logic;
start:std_logic;
registro:unsigned(9 downto 0);
amplif_aux:unsigned(9 downto 0);
multiplicando_aux:unsigned(7 downto 0);
88
Anexos
begin
p_xor:puerta_xor
port map(s1=>s1,s2=>s2,start=>start);
process (clk512,reset)
begin
if (reset='1') then
s1<='0';
elsif (clk512' event and clk512='1') then
s1<=not(s1);
end if;
end process;
process (clk,reset)
begin
if (reset='1') then
s2<='0';
registro<="0000000000";
amplif_aux<="0000000000";
multiplicando_aux<="00000000";
elsif (clk' event and clk='1') then
if (start='1') then
multiplicando_aux<=unsigned(multiplicando);
amplif_aux(8 downto 1)<=unsigned(amplificacion);
amplif_aux(9)<='0';
amplif_aux(0)<='0';
registro<="0000000000";
s2<=not(s2);
else
s2<=s2amplif_aux(8 downto 0)<=amplif_aux (9 downto 1);
89
Anexos
amplif_aux(9)<='0';
if (multiplicando_aux(7)='1') then
registro<=registro + amplif_aux;
else
registro<=registro;
end if;
multiplicando_aux(7 downto 1)<=multiplicando_aux(6 downto 0);
multiplicando_aux(0)<='0';
end if;
end if;
end process;
resultado<=std_logic_vector(registro);
end arc_amplificador;
En el gráfico se puede observar como a cada flanco de clk512 se activa la señal
start, iniciándose una multiplicación secuencial entre amplificación y multiplicando,
generando un valor de 10 bits.
90
Anexos
4.1.13.2 Sumador
El sumador consta de dos entidades. Una que realiza la adquisición de valores
y la otra que realiza la suma:
---- Adquisición ------entity adquisicion is port(
offset:in std_logic_vector(7 downto 0);
sal_amp:in std_logic_vector(9 downto 0);
operandoA:out unsigned(8 downto 0);
operandoB:out unsigned(8 downto 0)
);
end adquisicion;
architecture arc_adquisicion of adquisicion is
begin
process(offset,sal_amp)
begin
operandoA(7 downto 0)<=unsigned(sal_amp(9 downto 2));
operandoA(8)<='0';
operandoB(7 downto 0)<=unsigned(offset);
operandoB(8)<='0';
end process;
end arc_adquisicion;
---- Sumador de dos entradas de 9 bits -------
entity sumador9bits is port(
sumandoA:in unsigned(8 downto 0);
sumandoB:in unsigned(8 downto 0);
salida2:out std_logic_vector(8 downto 0)
);
end sumador9bits;
91
Anexos
architecture arc_sumador9bits of sumador9bits is
signal salida2_aux:unsigned(8 downto 0);
begin
process(sumandoA,sumandoB)
begin
salida2_aux<= sumandoA + sumandoB;
end process;
salida2<=std_logic_vector(salida2_aux);
end arc_sumador9bits;
Se puede comprobar como se convierte la salida del amplificador a un valor de
9 bits (sumandoA) y se le suma el offset, tal y como se había explicado en la memoria
descriptiva.
4.1.13.3 Limitador
---- Control de desbordamiento ------entity limitador is port(
entrada:in std_logic_vector(8 downto 0);
salida3:out std_logic_vector(7 downto 0)
);
end limitador;
92
Anexos
architecture arc_limitador of limitador is
begin
process(entrada)
begin
if (entrada(8)='1') then
salida3<="11111111";
else
salida3<=entrada(7 downto 0);
end
if;
end process;
end arc_limitador;
Mientras entrada supera el valor “0FF”, es decir “011111111”, salida3 se
mantiene a “FF”, es decir “11111111”.
93
Anexos
4.1.14 Generador de funciones
Como se ha comentado anteriormente esta es la entidad principal que engloba
todas las entidades vistas hasta ahora.
--- generador de funciones ----entity generador is port (
reset:in std_logic;
periodo:in std_logic_vector(7 downto 0);
amplificacion:in std_logic_vector(7 downto 0);
selec:in std_logic_vector(1 downto 0);
desplazamiento: in std_logic_vector(7 downto 0);
offset:in std_logic_vector(7 downto 0);
salidagen:out std_logic_vector(7 downto 0)
);
end generador;
architecture final of generador is
signal
signal
signal
signal
clk,clk8,clk512:std_logic;
multiplicando:std_logic_vector(7 downto 0);
sal_amp_off: std_logic_vector(7 downto 0);
A,B,C,D:std_logic_vector(7 downto 0);
component reloj port (
clk:out std_logic
);
end component;
component divisor8 port (
reset:in std_logic;
clk:in std_logic;
clk8:out std_logic
);
end component;
component divis_frec port (
reset:in std_logic;
clk8:in std_logic;
clk512:out std_logic;
periodo:in std_logic_vector(7 downto 0)
);
end component;
94
Anexos
component conjunto port(
reset:in std_logic;
clk512:in std_logic;
periodo:in std_logic_vector(7 downto 0);
desplazamiento:in std_logic_vector(7 downto 0);
A:out std_logic_vector(7 downto 0);
B:out std_logic_vector(7 downto 0);
C:out std_logic_vector(7 downto 0);
D:out std_logic_vector(7 downto 0)
);
end component;
component multiplexor port(
A:in std_logic_vector(7 downto 0);
B:in std_logic_vector(7 downto 0);
C:in std_logic_vector(7 downto 0);
D:in std_logic_vector(7 downto 0);
selec:in std_logic_vector(1 downto 0);
salida_mult:out std_logic_vector(7 downto 0)
);
end component;
component amplif_offset port(
reset:in std_logic;
clk,clk512:in std_logic;
offset:in std_logic_vector(7 downto 0);
amplificacion:in std_logic_vector(7 downto 0);
multiplicando:in std_logic_vector(7 downto 0);
sal_amp_off:out std_logic_vector(7 downto 0)
);
end component;
begin
temp:reloj
port map(clk=>clk);
divisor:divisor8
port map(reset=>reset,clk=>clk,clk8=>clk8);
95
Anexos
frecuencia:divis_frec
port map(reset=>reset,clk8=>clk8,
clk512=>clk512,periodo=>periodo);
conjunt:conjunto
port map(reset=>reset,clk512=>clk512,
periodo=>periodo,desplazamiento=>desplazamiento,
A=>A,B=>B,C=>C,D=>D);
mux:multiplexor
port map(A=>A,B=>B,C=>C,D=>D,selec=>selec,
salida_mult=>multiplicando);
amplif:amplif_offset
port map(reset=>reset,clk=>clk,clk512=>clk512,
offset=>offset,amplificacion=>amplificacion,
multiplicando=>multiplicando,sal_amp_off=>sal_amp_off);
process (clk512,reset)
begin
if (reset='1') then
salidagen<="00000000";
elsif (clk512' event and clk512='1') then
salidagen<=sal_amp_off;
end if;
end process;
end final;
La salida de este bloque no es necesario simularla, puesto que coincide con la
salida del componente amplificador_offset visto anteriormente.
96
Anexos
4.1.15 Diferencias entre el generador simulado y el sintetizado en la FPGA
Es necesario remarcar que para simular el sistema se ha simulado internamente
una señal de reloj. En el diseño final ésta será introducida externamente, por tanto la
arquitectura del generador no contendrá el componente reloj. Se define en la entidad
una entrada externa clk:
--- generador de funciones ----entity generador is port (
clk,reset:in std_logic;
periodo:in std_logic_vector(7 downto 0);
amplificacion:in std_logic_vector(7 downto 0);
selec:in std_logic_vector(1 downto 0);
desplazamiento: in std_logic_vector(7 downto 0);
offset:in std_logic_vector(7 downto 0);
salidagen:out std_logic_vector(7 downto 0)
);
end generador;
architecture final of generador is
signal
signal
signal
signal
clk8,clk512:std_logic;
multiplicando:std_logic_vector(7 downto 0);
sal_amp_off: std_logic_vector(7 downto 0);
A,B,C,D:std_logic_vector(7 downto 0);
component divisor8 port (
reset:in std_logic;
clk:in std_logic;
clk8:out std_logic
);
end component;
El resto del código permanece igual.
97
Anexos
4.2
Sintetización del Código VHDL
Una vez simulado el código se sintetiza con el paquete de softtware
FOUNDATION de XILINX. Se genera un archivo con extensión .BIT que será
cargado en la FPGA.
Al sintetizar se genera un archivo PLACE&ROUT.PAR que indica el
porcentaje de ocupación de la FPGA.
El código se ha optimizado al máximo hasta conseguir una ocupación del 58%
de CLBS.
Release 4.1i - Par E.30
Copyright (c) 1995-2001 Xilinx, Inc. All rights reserved.
Sun Jan 27 11:18:02 2002
par -w -ol 2 -d 0 map.ncd gen1.ncd gen1.pcf
Constraints file: gen1.pcf
Loading design for application par from file map.ncd.
"generador" is an NCD, version 2.36, device xc4005e, package pc84, speed -1
Loading device for application par from file '4005e.nph' in environment
C:/Xilinx.
Device speed data version: x1_0.96 PRELIMINARY.
Resolved that IOB <amplificacion<0>> must be placed at site P57.
Resolved that IOB <amplificacion<1>> must be placed at site P58.
Resolved that IOB <amplificacion<2>> must be placed at site P59.
Resolved that IOB <amplificacion<3>> must be placed at site P60.
Resolved that IOB <amplificacion<4>> must be placed at site P61.
98
Anexos
Resolved that IOB <amplificacion<5>> must be placed at site P62.
Resolved that IOB <amplificacion<6>> must be placed at site P65.
Resolved that IOB <amplificacion<7>> must be placed at site P66.
Resolved that CLKIOB <clk> must be placed at site P13.
Resolved that IOB <desplazamiento<0>> must be placed at site P84.
Resolved that IOB <desplazamiento<1>> must be placed at site P83.
Resolved that IOB <desplazamiento<2>> must be placed at site P82.
Resolved that IOB <desplazamiento<3>> must be placed at site P81.
Resolved that IOB <desplazamiento<4>> must be placed at site P80.
Resolved that IOB <desplazamiento<5>> must be placed at site P79.
Resolved that IOB <desplazamiento<6>> must be placed at site P78.
Resolved that IOB <desplazamiento<7>> must be placed at site P77.
Resolved that IOB <offset<0>> must be placed at site P28.
Resolved that IOB <offset<1>> must be placed at site P27.
Resolved that IOB <offset<2>> must be placed at site P26.
Resolved that IOB <offset<3>> must be placed at site P25.
Resolved that IOB <offset<4>> must be placed at site P24.
Resolved that IOB <offset<5>> must be placed at site P23.
Resolved that IOB <offset<6>> must be placed at site P20.
Resolved that IOB <offset<7>> must be placed at site P19.
Resolved that IOB <periodo<0>> must be placed at site P10.
Resolved that IOB <periodo<1>> must be placed at site P9.
Resolved that IOB <periodo<2>> must be placed at site P8.
Resolved that IOB <periodo<3>> must be placed at site P7.
Resolved that IOB <periodo<4>> must be placed at site P6.
Resolved that IOB <periodo<5>> must be placed at site P5.
Resolved that IOB <periodo<6>> must be placed at site P4.
Resolved that IOB <periodo<7>> must be placed at site P3.
Resolved that IOB <reset> must be placed at site P38.
Resolved that IOB <salidagen<0>> must be placed at site P37.
Resolved that IOB <salidagen<1>> must be placed at site P39.
99
Anexos
Resolved that IOB <salidagen<2>> must be placed at site P41.
Resolved that IOB <salidagen<3>> must be placed at site P35.
Resolved that IOB <salidagen<4>> must be placed at site P45.
Resolved that IOB <salidagen<5>> must be placed at site P47.
Resolved that IOB <salidagen<6>> must be placed at site P49.
Resolved that IOB <salidagen<7>> must be placed at site P51.
Resolved that IOB <selec<0>> must be placed at site P40.
Resolved that IOB <selec<1>> must be placed at site P44.
Resolved that PRI-CLK <C961> must be placed at site BUFGP_TL.
Device utilization summary:
Number of External IOBs
Flops:
Latches:
44 out of 112
72%
8
0
Number of IOBs driving Global Buffers 1 out of 8
Number of CLBs
114 out of 196
Total CLB Flops:
64 out of 392
4 input LUTs:
209 out of 392
3 input LUTs:
36 out of 196
58%
16%
53%
18%
Number of PRI-CLKs
1 out of 4
25%
Number of SEC-CLKs
2 out of 4
50%
Number of STARTUPs
1 out of 1
100%
Overall effort level (-ol): 2 (set by user)
Placer effort level (-pl):
2 (set by user)
100
12%
Anexos
Placer cost table entry (-t): 1
Router effort level (-rl):
2 (set by user)
Extra effort level (-xe):
0 (default)
Starting initial Placement phase. REAL time: 0 secs
Finished initial Placement phase. REAL time: 0 secs
Starting Constructive Placer. REAL time: 0 secs
Placer score = 127064
Placer score = 92408
Placer score = 87174
Placer score = 78780
Placer score = 73838
Placer score = 69036
Placer score = 64474
Placer score = 62400
Placer score = 60578
Placer score = 59316
Placer score = 57876
Placer score = 55584
Placer score = 54490
Placer score = 53884
Placer score = 53758
Placer score = 53098
Placer score = 53054
Placer score = 52992
Placer score = 52978
Placer score = 52922
Finished Constructive Placer. REAL time: 4 secs
Dumping design to file gen1.ncd.
101
Anexos
Starting Optimizing Placer. REAL time: 4 secs
Optimizing
Swapped 16 comps.
Xilinx Placer [1] 52198 REAL time: 5 secs
Finished Optimizing Placer. REAL time: 5 secs
Dumping design to file gen1.ncd.
Total REAL time to Placer completion: 5 secs
Total CPU time to Placer completion: 5 secs
0 connection(s) routed; 759 unrouted active, 24 unrouted PWR/GND.
Starting router resource preassignment
Completed router resource preassignment. REAL time: 5 secs
Starting iterative routing.
Routing active signals.
End of iteration 1
759 successful; 0 unrouted active,
24 unrouted PWR/GND; (0) REAL time: 6 secs
Routing PWR/GND nets.
Power and ground nets completely routed.
Dumping design to file gen1.ncd.
Starting cleanup
Improving routing.
End of cleanup iteration 1
783 successful; 0 unrouted; (0) REAL time: 9 secs
Dumping design to file gen1.ncd.
Total REAL time: 9 secs
Total CPU time: 9 secs
102
Anexos
End of route. 783 routed (100.00%); 0 unrouted.
No errors found.
Completely routed.
This design was run without timing constraints. It is likely that much better
circuit performance can be obtained by trying either or both of the following:
- Enabling the Delay Based Cleanup router pass, if not already enabled
- Supplying timing constraints in the input design
Total REAL time to Router completion: 9 secs
Total CPU time to Router completion: 9 secs
Generating PAR statistics.
The Delay Summary Report
The Score for this design is: 452
The Number of signals not completely routed for this design is: 0
The Average Connection Delay for this design is:
2.863 ns
The Maximum Pin Delay is:
11.534 ns
The Average Connection Delay on the 10 Worst Nets is: 8.301 ns
Listing Pin Delays by value: (ns)
d < 2.00 < d < 4.00 < d < 6.00 < d < 8.00 < d < 12.00 d >= 12.00
--------- --------- --------- --------- --------- ---------
103
Anexos
417
162
114
41
49
Dumping design to file gen1.ncd.
All signals are completely routed.
Total REAL time to PAR completion: 9 secs
Total CPU time to PAR completion: 9 secs
Placement: Completed - No errors found.
Routing: Completed - No errors found.
PAR done.
Release 3.3.06i – Par D 25
Tue Dec 11 09:57:24 2001
Xilinx PAD Specification File
************************
Input file:
map.ncd
Output file
generador.ncd
Part Type:
Xc4005e
Speed grade
-1
Package:
pc84
104
0
Anexos
Tambien se genera un archivo con extensión .PAD que indica la asignación
de cada un delos pins de la FPGA:
Release 4.1i - Par E.30
Copyright (c) 1995-2001 Xilinx, Inc. All rights reserved.
Sun Jan 27 11:18:11 2002
Xilinx PAD Specification File
*****************************
Input file:
map.ncd
Output file:
gen1.ncd
Part type:
xc4005e
Speed grade:
Package:
-1
pc84
Pinout by Signal Name:
-------------------------------|----------------------|--------|-----------|
Signal Name
|
Pin Name
|
| Pin
| Direction |
| Number |
|
-------------------------------|----------------------|--------|-----------|
amplificacion<0>
|
| P57
| INPUT
|
amplificacion<1>
|
| P58
| INPUT
|
amplificacion<2>
|
| P59
| INPUT
|
amplificacion<3>
|
| P60
| INPUT
|
amplificacion<4>
|
| P61
| INPUT
|
amplificacion<5>
|
| P62
| INPUT
|
amplificacion<6>
|
| P65
| INPUT
|
amplificacion<7>
|
| P66
| INPUT
|
clk
|
| P13
| INPUT
|
desplazamiento<0>
|
| P84
| INPUT
|
105
Anexos
desplazamiento<1>
|
| P83
| INPUT
|
desplazamiento<2>
|
| P82
| INPUT
|
desplazamiento<3>
|
| P81
| INPUT
|
desplazamiento<4>
|
| P80
| INPUT
|
desplazamiento<5>
|
| P79
| INPUT
|
desplazamiento<6>
|
| P78
| INPUT
|
desplazamiento<7>
|
| P77
| INPUT
|
offset<0>
|
| P28
| INPUT
|
offset<1>
|
| P27
| INPUT
|
offset<2>
|
| P26
| INPUT
|
offset<3>
|
| P25
| INPUT
|
offset<4>
|
| P24
| INPUT
|
offset<5>
|
| P23
| INPUT
|
offset<6>
|
| P20
| INPUT
|
offset<7>
|
| P19
| INPUT
|
periodo<0>
|
| P10
| INPUT
|
periodo<1>
|
| P9
| INPUT
|
periodo<2>
|
| P8
| INPUT
|
periodo<3>
|
| P7
| INPUT
|
periodo<4>
|
| P6
| INPUT
|
periodo<5>
|
| P5
| INPUT
|
periodo<6>
|
| P4
| INPUT
|
periodo<7>
|
| P3
| INPUT
|
reset
|
| P38
| INPUT
salidagen<0>
|
| P37
| OUTPUT
|
salidagen<1>
|
| P39
| OUTPUT
|
salidagen<2>
|
| P41
| OUTPUT
|
salidagen<3>
|
| P35
| OUTPUT
|
salidagen<4>
|
| P45
| OUTPUT
|
salidagen<5>
|
| P47
| OUTPUT
|
salidagen<6>
|
| P49
| OUTPUT
|
106
|
Anexos
salidagen<7>
|
| P51
| OUTPUT
|
selec<0>
|
| P40
| INPUT
|
selec<1>
|
| P44
| INPUT
|
-------------------------------|----------------------|--------|-----------|
Pinout by Pin Number:
--------|-------------------------------|----------------------|-----------|
Pin
|
Signal Name
Number |
|
Pin Name
|
|
| Direction |
|
--------|-------------------------------|----------------------|-----------|
P1
|
| GND
|
|
P2
|
| VCC
|
|
P3
| periodo<7>
|
| INPUT
|
P4
| periodo<6>
|
| INPUT
|
P5
| periodo<5>
|
| INPUT
|
P6
| periodo<4>
|
| INPUT
|
P7
| periodo<3>
|
| INPUT
|
P8
| periodo<2>
|
| INPUT
|
P9
| periodo<1>
|
| INPUT
|
P10
| periodo<0>
|
| INPUT
|
P11
|
| VCC
|
|
P12
|
| GND
|
|
P13
| clk
|
| INPUT
P14
|
|
| UNUSED
|
|
|
P15 |
| TDI
P16
|
| TCK
|
|
P17
|
| TMS
|
|
P18
|
|
| UNUSED
P19
| offset<7>
|
| INPUT
|
P20
| offset<6>
|
| INPUT
|
P21
|
| GND
|
|
107
|
|
Anexos
P22
|
| VCC
|
P23
| offset<5>
|
| INPUT
|
P24
| offset<4>
|
| INPUT
|
P25
| offset<3>
|
| INPUT
|
P26
| offset<2>
|
| INPUT
|
P27
| offset<1>
|
| INPUT
|
P28
| offset<0>
|
| INPUT
|
P29
|
|
| UNUSED
P30
|
| M1
P31
|
| GND
P32
|
| M0
P33
|
| VCC
P34
|
| M2
P35
| salidagen<3>
|
| OUTPUT
|
P36
|
|
| UNUSED
|
P37
| salidagen<0>
|
| OUTPUT
|
P38
| reset
|
| INPUT
P39
| salidagen<1>
|
| OUTPUT
P40
| selec<0>
|
| INPUT
P41
| salidagen<2>
|
| OUTPUT
P42
|
| VCC
|
|
P43
|
| GND
|
|
P44
| selec<1>
|
| INPUT
|
P45
| salidagen<4>
|
| OUTPUT
|
P46
|
|
| UNUSED
|
P47
| salidagen<5>
|
| OUTPUT
|
P48
|
|
| UNUSED
|
P49
| salidagen<6>
|
| OUTPUT
|
P50
|
|
| UNUSED
|
P51
| salidagen<7>
|
| OUTPUT
|
P52
|
| GND
|
|
|
|
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
Anexos
P53
|
| DONE
|
P54
|
| VCC
P55
|
| /PROG
P56
|
|
| UNUSED
P57
| amplificacion<0>
|
| INPUT
|
P58
| amplificacion<1>
|
| INPUT
|
P59
| amplificacion<2>
|
| INPUT
|
P60
| amplificacion<3>
|
| INPUT
|
P61
| amplificacion<4>
|
| INPUT
|
P62
| amplificacion<5>
|
| INPUT
|
P63
|
| VCC
|
|
P64
|
| GND
|
|
P65
| amplificacion<6>
|
| INPUT
|
P66
| amplificacion<7>
|
| INPUT
|
P67
|
|
| UNUSED
|
P68
|
|
| UNUSED
|
P69
|
|
| UNUSED
|
P70
|
|
| UNUSED
|
P71
|
|
| UNUSED
|
P72
|
|
| UNUSED
|
P73
|
| CCLK
P74
|
| VCC
|
|
P75 |
| TDO
|
|
P76
|
| GND
|
|
P77
| desplazamiento<7>
|
| INPUT
|
P78
| desplazamiento<6>
|
| INPUT
|
P79
| desplazamiento<5>
|
| INPUT
|
P80
| desplazamiento<4>
|
| INPUT
|
P81
| desplazamiento<3>
|
| INPUT
|
P82
| desplazamiento<2>
|
| INPUT
|
P83
| desplazamiento<1>
|
| INPUT
|
|
|
|
|
|
|
109
|
|
Anexos
P84
| desplazamiento<0>
|
| INPUT
|
--------|-------------------------------|----------------------|-----------|
* Default value.
** This default Pullup/Pulldown value can be overridden in Bitgen.
*** The default IOB Delay is determined by how the IOB is used.
#
# To preserve the pinout above for future design iterations,
# simply invoke PIN2UCF from the command line or issue this command in the GUI.
# For Foundation ISE/Project Navigator - Run the process "Implement Design" ->
"Place-and-Route" -> "Back-annotate Pin Locations"
# For Design Manager - In the Design menu select "Lock Pins...
# The location constraints above will be written into your specified UCF file. (The
constraints
# listed below are in PCF format and cannot be directly used in the UCF file).
#
COMP "amplificacion<0>" LOCATE = SITE "P57" ;
COMP "amplificacion<1>" LOCATE = SITE "P58" ;
COMP "amplificacion<2>" LOCATE = SITE "P59" ;
COMP "amplificacion<3>" LOCATE = SITE "P60" ;
COMP "amplificacion<4>" LOCATE = SITE "P61" ;
COMP "amplificacion<5>" LOCATE = SITE "P62" ;
COMP "amplificacion<6>" LOCATE = SITE "P65" ;
COMP "amplificacion<7>" LOCATE = SITE "P66" ;
COMP "clk" LOCATE = SITE "P13" ;
COMP "desplazamiento<0>" LOCATE = SITE "P84" ;
COMP "desplazamiento<1>" LOCATE = SITE "P83" ;
COMP "desplazamiento<2>" LOCATE = SITE "P82" ;
COMP "desplazamiento<3>" LOCATE = SITE "P81" ;
COMP "desplazamiento<4>" LOCATE = SITE "P80" ;
110
Anexos
COMP "desplazamiento<5>" LOCATE = SITE "P79" ;
COMP "desplazamiento<6>" LOCATE = SITE "P78" ;
COMP "desplazamiento<7>" LOCATE = SITE "P77" ;
COMP "offset<0>" LOCATE = SITE "P28" ;
COMP "offset<1>" LOCATE = SITE "P27" ;
COMP "offset<2>" LOCATE = SITE "P26" ;
COMP "offset<3>" LOCATE = SITE "P25" ;
COMP "offset<4>" LOCATE = SITE "P24" ;
COMP "offset<5>" LOCATE = SITE "P23" ;
COMP "offset<6>" LOCATE = SITE "P20" ;
COMP "offset<7>" LOCATE = SITE "P19" ;
COMP "periodo<0>" LOCATE = SITE "P10" ;
COMP "periodo<1>" LOCATE = SITE "P9" ;
COMP "periodo<2>" LOCATE = SITE "P8" ;
COMP "periodo<3>" LOCATE = SITE "P7" ;
COMP "periodo<4>" LOCATE = SITE "P6" ;
COMP "periodo<5>" LOCATE = SITE "P5" ;
COMP "periodo<6>" LOCATE = SITE "P4" ;
COMP "periodo<7>" LOCATE = SITE "P3" ;
COMP "reset" LOCATE = SITE "P38" ;
COMP "salidagen<0>" LOCATE = SITE "P37" ;
COMP "salidagen<1>" LOCATE = SITE "P39" ;
COMP "salidagen<2>" LOCATE = SITE "P41" ;
COMP "salidagen<3>" LOCATE = SITE "P35" ;
COMP "salidagen<4>" LOCATE = SITE "P45" ;
COMP "salidagen<5>" LOCATE = SITE "P47" ;
COMP "salidagen<6>" LOCATE = SITE "P49" ;
COMP "salidagen<7>" LOCATE = SITE "P51" ;
COMP "selec<0>" LOCATE = SITE "P40" ;
COMP "selec<1>" LOCATE = SITE "P44" ;
#
111
Descargar