next up previous
Next: Simulación del cerrojo SR Up: Práctica 3. Simulación del Previous: Práctica 3. Simulación del

Simulación de una puerta NAND con tiempo de establecimiento y de propagación

Se entiende como tiempo de establecimiento el tiempo que debe permanecer constante una entrada para que su valor lógico sea considerado como tal por la puerta lógica y como tiempo de propagación el tiempo que transcurre desde que las entradas están establecidas hasta que la salida actúa en consonancia.

En la simulación de la puerta NAND de la práctica anterior se ha presupuesto un tiempo de establecimiento y de propagación iguales a cero. Ahora, para aproximarnos más a lo que ocurre en la realidad, vamos a dotar al modelo usado para simular la puerta con estos dos tiempos.

En concreto, asignaremos a la puerta NAND un tiempo de establecimiento igual a dos iteraciones de simulación, con lo que cualquiera de las dos entradas de la puerta NAND deberá permanecer constante al menos dos ciclos para que la modelo la considere como tal. Por otra parte, el tiempo de propagación será igual a una iteración de simulación. Como ejemplo, valga la siguiente simulación de una puerta NAND según el modelo propuesto:

 in0 in1 out 
 --- --- ---
   0 255   0 --> No existe historia anterior, iteración no relevante  
 255 255   0
 255 255   0
 255 255   0
   0 255   0 --> in0=0, si conserva un ciclo más su valor hará que out=255
   0 255 255     en la iteración siguiente, tal y como ocurre
   0 255 255
 255   0 255
 255   0 255
 255   0 255
   0   0 255
   0   0 255
   0   0 255
 255   0 255
 255 255 255 --> in0=in1=255, si permanecen constantes dos ciclos, out=0
 255 255   0     tal y como ocurre en la siguiente iteración
   0 255   0
   0 255 255
   0 255 255
 255 255 255
 255 255   0
 255   0   0
   0   0 255
   0   0 255
   0   0 255
 255   0 255
 255   0 255
 255   0 255
   0 255 255
   0 255 255
   0 255 255
 255 255 255
 255 255   0
 255 255   0
   0 255   0
   0   0 255
   0   0 255
 255   0 255
 255   0 255
 255   0 255
   0   0 255
   0   0 255
   0 255 255
 255 255 255
 255 255   0
 255 255   0
   0 255   0
   0 255 255
   0 255 255
 255   0 255
 255   0 255
   0 255 255
   0 255 255
   0   0 255
 255   0 255
 255 255 255 --> Este es un caso límite para comprobar el tiempo de
 255 255   0     establecimiento (2 ciclos)
   0   0   0
   0   0 255
   0 255 255
 255 255 255
 255   0 255
 255   0 255
   0 255 255
   0 255 255
   0   0 255
 255   0 255
 255 255 255
 255 255   0
   0   0   0
   0   0 255
   0 255 255
 255 255 255
 255   0 255
 255   0 255
   0 255 255
   0 255 255
   0   0 255
 255   0 255
 255 255 255
 255 255   0
   0   0   0
   0   0 255
   0 255 255
 255 255 255
 255   0 255
 255   0 255
   0 255 255
   0 255 255
   0   0 255
 255   0 255
 255 255 255
 255 255   0
   0   0   0
   0   0 255
   0 255 255
 255 255 255
 255   0 255
 255   0 255
   0 255 255
   0   0 255
 255 255 255 --> Aquí in1 no respeta un tiempo de establecimiento de al menos
 255   0 255     dos ciclos: la puerta no es capaz de saber que pasa y deja
 255 255 255     su salida como estaba (255)
   0   0 255
   0 255 255
   0   0 255
 255 255 255
 255   0 255
 255 255 255
   0   0 255
   0 255 255
   0   0 255
 255 255 255
 255   0 255
 255 255 255
   0   0 255
   0 255 255
   0   0 255
 255 255 255
 255   0 255
 255 255 255
   0   0 255
   0 255 255
   0   0 255
 255 255 255
 255   0 255
 255 255 255
   0   0 255
   0 255 255
   0   0 255
 255 255 255
 255   0 255
 255 255 255
   0   0 255
   0 255 255
   0   0 255
 255 255 255
 255   0 255
 255 255 255
   0   0 255
   0 255 255
   0   0 255
 255 255 255
 255   0 255
 255 255 255
   0   0 255
   0 255 255
   0   0 255
 255 255 255

Una simulación así puede conseguirse con el código que presentado a continuación. En primer lugar escribiremos el modelo de la puerta NAND. Llamar al fichero nand.h:

class NAND {
  unsigned char delay;
public:
  void run(unsigned char in0,
           unsigned char in1,
           unsigned char &out) {
    unsigned char tmp = ~(in0 & in1); /* 1 */
    if(delay==tmp) out=tmp;           /* 2 */
    delay=tmp;                        /* 3 */
    if(out<127) out=0; else out=255;  /* 4 */
  }
};

Cómo podemos apreciar, una variable privada del objeto llamada delay se encarga de almacenar el valor de la salida de la puerta en la iteración de simulación anterior. Notar que cada vez que sea creado un objeto de la clase NAND, se emplea 1 byte para almacenar la variable local delay. Esto es necesario tenerlo en cuenta si van a necesitarse simultáneamente millones de puertas NAND.

La primera línea de la función void run() (etiquetada con /* 1 */ en el código fuente) calcula la salida de la puerta en función de las entradas actuales, con el objetivo de realizar la simulación lógica de la puerta. La línea segunda comprueba que la salida coincide con la obtenida en la anterior iteración. Si coincide, la salida actual tiene en cuenta las entradas y si no coincide, la salida no varía. La tercera línea almacena en la variable que contiene la salida en la iteración anterior (delay) la salida actual (tmp). Por último, la cuarta línea ``binariza'' la salida por si su valor no fuera 0 o 255. De esta forma nos aseguramos un funcionamiento más correcto del simulador en el caso de que olvidemos inicializar las variables (que pueden en realidad tomar cualquier valor entre 0 y 255).

Si colocamos un objeto de la clase NAND en el siguiente ``entrenador'', deberíamos obtener la salida presentada anteriormente. Llamarlo test_nand.cc.

#include <iostream.h>
#include <iomanip.h>
#include "clock.h"
#include "nand.h"

void main() {
  int iter=50;
  unsigned char a=0,b=0,c=0;
  NAND gate;
  while(iter--) {
    Clock(iter,3,a);
    Clock(iter,7,b);
    gate.run(a,b,c);
    cout << setw(4) << (int)a
         << setw(4) << (int)b
         << setw(4) << (int)c
         << '\n';
  }
  iter=50;
  while(iter--) {
    Clock(iter,3,a);
    Clock(iter,2,b);
    gate.run(a,b,c);
    cout << setw(4) << (int)a
         << setw(4) << (int)b
         << setw(4) << (int)c
         << '\n';
  }
  iter=50;
  while(iter--) {
    Clock(iter,3,a);
    Clock(iter,1,b);
    gate.run(a,b,c);
    cout << setw(4) << (int)a
         << setw(4) << (int)b
         << setw(4) << (int)c
         << '\n';
  }
}

Notar que se ha usado una función especial llamada void Clock() que se declara en el fichero cabecera clock.h que es presentado a continuación:

/*
 * clock.h -- Generador de onda cuadrada de periodo ajustable.
 * gse. 1999.
 */
void Clock(int iteracion_de_simulacion,
           int duracion_del_semiperiodo,
           unsigned char &senhal_de_reloj);

El respectivo fichero con la implementación de la función void Clock() se debe llamar clock.cc y contiene el código:

#include "clock.h"

void Clock(int iter, int duracion, unsigned char &io) {
  if(io<127) io=0; else io=255;
  if(!(iter%duracion)) io = ~io;
}

Para compilar y ejecutar la simulación de la puerta NAND deberemos escribir las siguiente sentencias en el shell:

c++ -c clock.cc
c++ test_nand.cc clock.o -o test_nand
./test_nand


next up previous
Next: Simulación del cerrojo SR Up: Práctica 3. Simulación del Previous: Práctica 3. Simulación del

1999-10-18