3. RESEARCH DESIGN AND MEASUREMENT of VARIABLES
4.3 Regression Analysis
4.3.4 Additional analysis
Este subapartado tiene como finalidad explicar el problema de elaboración encontrado al declarar y utilizar los parámetros genéricos de una entidad, así como el estudio de sus posibles soluciones para que sean tomadas como referencia en futuras modificaciones del elaborador.
La sintaxis de la declaración de los parámetros genéricos se explica en el apartado 4.1.1.”Declaración de puertos y constantes genéricas.”-[43].
La asociación de puertos y parámetros genéricos permite conectar unidades de diseño con componentes mediante la instanciación. Esta asociación es estudiada y analizada con detalle en el apartado 7.2.2.”Asociación de parámetros genéricos y puertos.”- [127]. De forma resumida, la solución que permite asociar los puertos entre una unidad y la instancia se basa en la asignación de las señales que constituyen esos puertos. Si, por ejemplo, se tiene el siguiente fragmento que muestra una declaración de entidad y una instanciación de esa unidad:
-- Entidad de puerta and de dos entradas
ENTITY And2 IS
GENERIC (retardo : time := 3ns);
PORT ( e0:IN std_logic := '1'; e1:IN std_logic; s: OUT std_logic); END And2; -- Arquitectura asociada
ARCHITECTURE And2_arq OF And2 IS BEGIN
s <= e0 and e1 AFTER retardo;
END And2;
-- Arquitectura de Test de la unidad And2
ARCHITECTURE TestFlujo OF And2_tb IS
...
SIGNAL entrada0,entrada1: std_logic := '0';
SIGNAL sal:std_logic_vector (1 downto 0);
BEGIN
instancia0: And2
GENERIC MAP (retardo => 15 ns)
[94]
...
END testFlujo;
Fragmento de código 6.1. Ejemplo de instanciación de la unidad And2.
la asociación entre la instancia y la entidad declarada And2 al ser elaborada produce las siguientes sentencias concurrentes de asignación de señales:
e0 <= entrada0; e1 <= entrada1; sal(0) <= s;
De esta forma la elaboración de la entidad y la arquitectura correspondiente a And2 es independiente a todas las posibles instanciaciones que puedan realizarse con ellas, ya que la comunicación con el resto del diseño se realizará a través de asignaciones de señales, sin que se vean afectadas ni tengan que modificarse sus estructuras internas. Por tanto, esta solución permite almacenar las unidades que han sido elaboradas de una forma estática, sin que vayan a sufrir ningún tipo de cambio.
Esta idea y su consiguiente implementación es válida y correcta para la instanciación de los puertos. Pero qué sucede con la instanciación de genéricos.
Un parámetro genérico representa un valor constante de un tipo definido. Como su nombre indica, se utiliza para poder modelar unidades genéricas, es decir, las unidades tienen una funcionalidad específica, pero pueden ser generalizadas para más de un caso en particular. Para ello, el valor del parámetro puede ser sobrescrito al instanciar la unidad. En el Fragmento de código 6.1 se diseña una puerta and de dos entradas, con un tiempo de retardo genérico. Esto permite en su instanciación definir cuál es el tiempo de retardo que tendrá esa instancia de la puerta and en concreto.
Para mantener la misma solución que la encontrada para el caso de los puertos, era necesario que la asociación entre los parámetros genéricos fuese tratada de la misma forma: durante la instanciación se crearían unas sentencias de asignación que propagasen el valor dado en la asociación de genéricos a cada uno de los parámetros de la unidad.
De esta forma, la elaboración de la instancia del ejemplo del Fragmento de código 6.1 tendría también la sentencia de asignación:
[95]
retardo <= 15 ns;
que resulta de asignar el valor dado en la instanciación al parámetro genérico de la unidad And2.
Con esta solución, se propaga el nuevo valor del genérico por la unidad sin tener que realizar ninguna modificación sobre ella, y por tanto, las unidades siguen siendo estáticas tal y como han sido diseñadas. Se asume que durante la simulación del modelo elaborado los valores dados a los genéricos en la unidad más alta en la jerarquía serán propagados hacia el resto de unidades más bajas.
Entonces, por qué esta solución no es correcta: Se está utilizando el parámetro genérico como una señal, y no como una constante, lo que provoca problemas en el resultado de la elaboración, y problemas durante la propia elaboración de una unidad. El problema generado en el resultado de la elaboración es el que provoca una declaración de un elemento cuando ésta depende de un parámetro genérico. Por ejemplo:
ENTITY mux IS
GENERIC (N: natural)
...
END mux;
ARCHITECTURE mux_arq OF mux IS
señal_aux : std_logic_vector (1 TO N); …
END mux_arq;
La declaración de señal_aux es de tipo vector con un tamaño de 1 a N, siendo N genérico. Al declarar el parámetro genérico como una señal, el resultado de la elaboración es incorrecto ya que el tamaño del vector depende de algo que no es constante, por lo que se produce un error de compilación.
El otro problema generado por esa solución incorrecta se produce durante la elaboración de las sentencias concurrentes Generate que dependen de los parámetros genéricos. Utilizando el ejemplo anterior, se tiene la siguiente sentencia en el cuerpo de la arquitectura:
FOR i IN 1 to N GENERATE
[96]
END GENERATE;
El elaborador debe deshacer esta sentencia duplicando N veces su contenido. Pero qué valor tiene N, siendo éste un parámetro genérico.
Estos dos problemas convergen hacia un origen común, el cual representa el grave problema del actual elaborador: las unidades son elaboradas de una forma estática. Aunque la elaboración comienza con el elemento más alto en la jerarquía y finaliza con los elementos situados en lo más bajo de la jerarquía (véase 3.4.”Necesidad de un análisis recursivo y su diseño.”-[28].), una unidad es elaborada en un determinado momento de una forma independiente, sin tener en cuenta la instancia que la utiliza. De esta manera, la unidad elaborada puede almacenarse y reutilizarse en otras instancias sin necesidad de ser reelaborada.
...
instancia0: And2
GENERIC MAP (retardo => 15 ns)
PORT MAP (e0=> entrada0, e1 => entrada1, s=> sal(0)); instancia1: And2
GENERIC MAP (retardo => 45 ns)
PORT MAP (e0=> entrada2, e1 => entrada3, s=> sal(1)); ...
Fragmento de código 6.2. Instanciación múltiple de un componente.
En el ejemplo, se muestran dos instanciaciones para un mismo componente. Estas sentencias de instanciación utilizan la unidad ya elaborada And2 sin tener que modificarla, aunque los parámetros genéricos tengan valores distintos. Este tratamiento estático de la unidad al ser elaborada es la raíz del problema.
De alguna forma se debe modificar la implementación del elaborador para hacer que una unidad sea dependiente de la instancia que la utilice. La elaboración actual de una unidad se realiza cuando es analizada una declaración de especificación o una especificación de configuración, como por ejemplo:
FOR ALL: And2 USE ENTITY work.And2(And2Flujo);
Es en este momento cuando se elabora la unidad And2 y And2flujo obteniéndose el componente And2. La solución al problema comienza en esta sentencia. Durante la
[97]
elaboración de las unidades And2 y And2flujo debe dejarse sin elaborar aquellos elementos que dependen de los parámetros genéricos. Estos elementos “no elaborados” serán almacenados de tal forma que durante la instanciación del componente puedan ser recuperados y elaborados de manera dependiente a los valores con que hayan sido declarados los genéricos en esa instancia.
Esta solución puede ser complicada de implementar. Hay que tener en cuenta que un parámetro genérico puede ser utilizado tanto en las declaraciones como en sentencias de instanciación o sentencias concurrentes Generate. Todos estos elementos dependientes serán almacenados sin elaborarse hasta que sea definido el valor del parámetro genérico en una instanciación de componente, momento en el que serán recuperados y tratados dependiendo de esos valores tomados. Por tanto, con esta reelaboración del componente instanciado se eliminan los dos problemas encontrados en el presente elaborador.
Otra solución a tener en cuenta es no pre-elaborar ninguna nueva unidad hasta que no sea instanciada, no necesitando de esta forma una biblioteca de unidades instanciadas. Mediante esta posible solución, la elaboración de las unidades no se realizaría en la sentencia de especificación de configuración, como pasa ahora, sino que se llevaría a cabo en la sentencia de instanciación de componentes, momento en el cual se conocen los valores que toman los parámetros genéricos para una instancia concreta de una especificación. De esta forma, el valor de éstos se conoce durante toda la elaboración tanto de las declaraciones como sentencias de una instancia, con lo que los dos problemas serían solucionados. La idea de esta solución se amplía en el apartado 6.2.7.”Sentencia concurrente GENERATE.”-[116].