Introduccion
Lazos combinacionales
son estructuras lógicas que contienen realimentación sin ningún elemento sincrónico
en el camino. Normalmente los lazos combinacionales provocan inestabilidad y
sistemas pocos confiables, violando los principios de diseño sincrónico al
establecer un lazo de realimentación sin registros.
Porqué? Cómo se genera un lazo combinacional?
Un lazo
combinacional es implementado en hardware cuando en el código VHDL escrito una señal
que está del lado izquierdo de una instrucción de asignación (a la izquierda
del símbolo <=) también aparece en la expresión aritmética/lógica del lado
derecho de la instrucción de asignación (a la derecha de <=); siempre y
cuando se esté describiendo lógica combinacional. Por ejemplo las siguientes
líneas de código generaran un lazo combinacional si se escribe en un proceso
combinacional o directamente como una instrucción de asignación concurrente.
1 acc <= acc + data;
2
3 Z <= Z nand B;
4
5 cnt <= cnt + 1;
2
3 Z <= Z nand B;
4
5 cnt <= cnt + 1;
Sin embargo es importante, muy importante, aclarar que si estas mismas líneas de código son escritas dentro de un proceso controlado por reloj, se generara la respectiva lógica secuencial; debido a que el reloj del proceso almacena el valor correspondiente por un ciclo de reloj, de este modo no existe una realimentación combinacional.
Hardware
La
siguiente figura representa un esquema de un lazo combinacional:
Como se ve
en la figura, la salida de la lógica combinacional se realimenta a si misma sin
ningún tipo de registro en el medio. Este tipo de esquema lógico, normalmente
no se desea, no es lo que se desea implementar, por ello la herramienta de
síntesis genera una advertencia (warning) tal como se detalla en el siguiente
ejemplo.
1 library ieee;
2 use ieee.std_logic_1164.all;
3
4 entity lazo_comb is
5 port(
6 a: in std_logic;
7 z: out std_logic);
8 end lazo_comb;
9
10 architecture beh of lazo_comb is
11
12 signal y: std_logic;
13
14 begin
15 z <= y;
16
17 process(a,y)
18 begin
19 y <= y nand a;
20 end process;
21
22 end beh;
2 use ieee.std_logic_1164.all;
3
4 entity lazo_comb is
5 port(
6 a: in std_logic;
7 z: out std_logic);
8 end lazo_comb;
9
10 architecture beh of lazo_comb is
11
12 signal y: std_logic;
13
14 begin
15 z <= y;
16
17 process(a,y)
18 begin
19 y <= y nand a;
20 end process;
21
22 end beh;
La
herramienta de síntesis, Synplify en este ejemplo, genera el siguiente mensaje de advertencia para este
código:
El mensaje
‘found combinational loop at y’ significa que la señnal ‘y’ es realimentada
combinacionalmente tal como se puede apreciar en el diagrama RTL de la
respectiva implementación del código descrito:
A continuación se puede ver la simulación del sistema descrito arriba.
Esta figura merece un detallado análisis. En primer lugar la primer ventana (de arriba hacia abajo) grafica las formas de ondas de las señales del sistema cuya principal expresión es la de
la línea 24 de la segunda ventana. La tercer ventana, Transcript, detalla un
error de simulación, diciendo que el limite de iteraciones del simulador fue
alcanzado a los 50ns y no se llego a ningún valor estable. Es decir que el
sistema empezó a oscilar y se quedo oscilando. El numero de iteración limite es
programable en ModelSim (Simulate->Runtime Options), y en la mayoría de los
simuladores. Por defecto este valor es de 5000. Viendo mas en detalle la parte
inferior de la ventana donde se grafican las formas de ondas, se puede leer que
el numero de Delta alcanzado es de 5000, que es justamente el numero limite de
iteraciones configurado. Han transcurridos 5000 Deltas y aun el sistema no es
estable.
Otro punto
importante a considerar en este ejemplo es el hecho de lo importante que es
simular un sistema aun cuando sea muy simple. Suponiendo que hubiéramos
directamente configurado el FPGA sin haber realizado la simulación (ya que la
herramienta de síntesis nos da solo un ‘warning’), hubiéramos visto que la
salida del sistema no era estable; y hubiéramos perdido una considerable
cantidad de tiempo tratando de ver porque la salida no es estable
En diseños
con una gran cantidad de código a veces es muy fácil cometer errores como el
del código descrito arriba. Por ello, hay que seguir un cierto orden en la
escritura del código, tratando de mantener un cierto flujo de datos, por ej. de
derecha a izquierda.
En casos en que deliberadamente
se desea implementar cierta lógica con un lazo combinacional tener en cuenta:- Comentar suficientemente el código de modo que se puede fehacientemente conocer la razón de existencia del lazo.
- Realizar todas las simulaciones posibles, primero en PC y luego en hardware para comprobar que aun con la existencia del lazo el sistema sigue funcionando correctamente.
Otro punto
importante a tener en cuenta cuando deliberadamente se implementa un lazo
combinacional, es que la herramientas de análisis de tiempo estático (Static
Taming analysys, STA) normalmente incrementan por un valor (2-8 veces) el
periodo mínimo cuando encuentran un lazo combinacional. Por ello, en estos
casos se debería decirle a la herramienta STA que ‘ignore’ ese camino en
particular. La sintaxis para el caso de Quartus (Altera), es ‘set_false_path’
(recordar que las herramientas de Altera usan constraints con las sintaxis de
Synopsys; para ISE (Xilinx) use TIG con su respectiva sintaxis.