PRÁCTICAS DE COMPUTADORES I

UNDÉCIMA SESIÓN


  1. Redes capacitivas

    En esta sesión vamos a tratar de modelar memoria DRAM con Verilog. La celda elemental de este tipo de memoria es muy sencilla:
    Celda elemental de memoria DRAM

    Su modo de operación es, asimismo, muy sencillo:

    La buena noticia es que Verilog dispone de una declaración especial para tratar este tipo de memoria capacitiva: trireg. De las malas noticias, hablaremos luego.

    trireg es un cable especial que funciona en gran parte como tri. Cuando se vierten señales distintas sobre él, gana aquella de mayor fuerza y, en caso de empate, se queda en X. La diferencia aparece cuando todas las señales que actúan sobre él son del alta impedancia. En ese caso, trireg adquiere el último valor que poseyó.

    Por otro lado, las fuerzas con las que actúan los triregs son especiales y distintas de las fuerzas que hemos visto hasta ahora. Aparecen en la siguiente tabla en su posición relativa:

    triregs   Otros elementos
    supply
    strong
    pull
    large
    weak
    medium
    small
    highz

    Además, se puede especificar para este tipo de elementos de uno a tres valores de retardo, de los cuales nos interesa especialmente el tercero. Si no se actúa sobre el trireg (se deja que todas las señales que vierten en él sean de alta impedancia), el elemento decae a X. Por ejemplo, este trireg decae a X pasadas 50 unidades de tiempo:

      trireg #(0,0,50) celda;
    

    Parece, pues, que tenemos una aproximación bastante razonable de nuestra celda de memoria dinámica con apenas dos líneas:

       module CeldaDram(inout bl, input sel);
         trireg #(0,0,50) celda;
         tranif1 #5 (celda, bl, sel);
       endmodule
    

    La aproximación no sería exacta porque:

    1. La operación de lectura no es destructiva
    2. La operación de lectura se hace colocando BL en alta impedancia
    3. Cuando la celda decae, decae a X y no a 0, como en el caso real

    No son diferencias muy importantes e, incluso, el último punto es interesante porque ayuda a detectar problemas en los diseños.

    Llegó el momento de conocer las malas noticias:

    1. La versión actual de iverilog (0.9.2) no admite triregs
    2. cver pone severas restricciones en los retardos que se pueden especificar en puertas bidireccionales como tranif. Esto se puede solventar separando los caminos de entrada y de salida de datos, pero:
    3. La versión actual de cver (2.12a) tiene un error y no trata adecuadamente a los triregs

    Veamos este último punto con un sencillo ejemplo:

    // ComprobaciOn de trireg
    
    module TestTriReg;
      reg w;
      trireg #(0,0,50) tr;
    
      assign tr=w;
    
      // Bloque de comportamiento
      initial
        begin
          $monitor($time," w=%v, tr=%v", w, tr);
          w=0;
          #10 w='bz;
          #10 w=1;
          #10 w='bz;
          #70 w=1;
          #70 $finish;
        end
    endmodule
    
    

    El comportamiento esperado sería que, en t=20, al escribir el 1, el trireg pasara a valer 1, pero mantiene su valor, aunque luego se descargue a X de un modo correcto. Una vez descargado, sí admite un nuevo valor. Comprobadlo ejecutando el código.

  2. Parámetros

    Se denominan parámetros (parameter) en Verilog a aquellas constantes definidas en el momento de hacer el programa. Suelen usarse para almacenar valores característicos del módulo y que puedan variarse de simulación en simulación. Por ejemplo, para indicar que el tiempo de lectura del módulo es de 50 unidades de tiempo, podemos usar un parámetro:
      parameter t_lectura=50;
    
  3. Síntesis

    Para obtener un producto electrónico que realice las funciones programadas en un módulo de Verilog hay que sintetizarlo. Se puede hacer manualmente o, lo que será preferible, mediante una herramienta automática.

    Para que el código Verilog sea sintetizable de un modo automático es necesario que cumpla una serie de reglas que se escapan al alcance de estas sesiones.

    Cabe preguntarse por qué, aparte de por motivos docentes, puede ser deseable programar código no sintetizable. Y si no sería más razonable que el propio Verilog no permitiera las instrucciones no sintetizables. La razón de por qué sí estriba en que, en ocasiones, se desea sintetizar un módulo, pero antes probarlo en un entorno de otros módulos que no se van a sintetizar. Estos últimos se pueden programar de modo no sintetizable.

    Aprovechando la mala suerte que parece tener trireg con los simuladores de Verilog que tenemos, vamos a programar varias celdas DRAM siguiendo el estilo marcado en el párrafo anterior: no con el objetivo de que vayan a ser sintetizadas así, sino para que simplemente simulen el comportamiento de una celda real.

    Veamos una primera posibilidad (modelando el tiempo):

    
    module CeldaDinAmica (inout tri io, input wire sel);
      reg r, r_out;
      time tw;
      parameter t_exp=100;
      parameter t_r=4;
    
      assign (pull0, pull1) io=r_out;
    
      initial
      begin
        r=0; tw=$time; r_out='bz;
      end
    
      always @(sel)
      begin
        case (sel)
          'b0: r_out='bz;
          'b1: begin
                 case (io)
                   'bz: /* Lectura */
                        begin
                          if ($time-tw>t_exp) r=0;
                          r_out=r;
                          r=#(t_r) 0;
                          r_out=r;
                        end
                   default: /* Escritura */
                        begin
                          tw=$time;
                          r_out='bz;
                          r=io;
                        end
                 endcase
               end
        endcase
      end
    endmodule
    
    

    El funcionamiento del módulo es el siguiente:

    Copiad el módulo y programad un módulo auxiliar para probarlo. ¿Funciona bien en todas las circunstancias?
  4. Operador condición-valor

    Se trata de un operador ternario, también disponible en C. El primer operando es una condición. Si es verdadera, el resultado es el segundo operando. Si es falsa, el resultado es el tercero. Sustituye de un modo resumido algunos bloques ifs sencillos. También es un modo fácil de modelar un multiplexor 2x1. Veamos un ejemplo:
      resultado = a>0 ? 7 : 8;
      // resultado valdrA 7 si a es mayor que cero.
      //           Si no lo es, a valdrA 8.
    

  5. Ejercicio

    Juntad en un nuevo fichero fuente el módulo de prueba del apartado anterior con este nuevo módulo que simula una celda DRAM basándose en la carga del condensador y no directamente en el tiempo:
    module CeldaDinAmica (inout tri io, input wire sel);
      integer carga;
      reg r_out;
      tri sensor0, sensor1;
      parameter q_w=100;
      parameter q_r=25;
    
      bufif1 (pull1,pull0) (io,r_out,sel);
    
      rnmos(sensor0,io,1);
      pulldown(sensor0);
    
      rnmos(sensor1,io,1);
      pullup(sensor1);
    
      initial
      begin
        carga=0; r_out=0;
      end
    
      always
      begin
        #1 case (sel)
             'b0: // Aislado
                  begin
                    carga=carga-1;
                  end
             'b1: // Contacto con el exterior
                  if (sensor0===0 && sensor1===1) // Lectura
                    carga=carga-q_r;
                  else                            // Escritura
                    carga=io*q_w;
        endcase
        if (carga<0) carga=0;
        r_out=carga>0?1:0;
      end
    endmodule
    
    

    Este módulo usa muchos de los elementos vistos en las dos últimas sesiones. Realizad un trabajo de ingeniería inversa para deducir cuáles son las claves de su funcionamiento.

  6. Ejercicio y colofón

    Constrúyase un módulo de Verilog que, con ayuda de módulos del tipo del anterior simule una memoria DRAM con las siguientes características:
    1. Tamaño de la palabra: 1 bit
    2. Tamaño de la memoria: 256 bits
    3. Organización: matriz de 16x16
    4. Direccionamiento: señales RAS y CAS activas por flaco de bajada. Para realizar una operación de lectura/escritura, primero se activa RAS para proporcionar la dirección de fila y luego, sin desactivar RAS, se activa CAS para la dirección de columna
    5. Señales de control: R_W (lectura 1, escritura 0)
    6. Refresco: si se activa CAS sin haber activado RAS, el módulo refresca una fila de la memoria. Tendrá un contador interno para ir refrescando una a una cada fila en secuencia cada vez que se solicite un refresco
    7. Datos: señales DI y DO separadas para escritura del dato y lectura del dato. DO estará en alta impedancia cuando no esté proporcionando un valor
    Los tiempos propios de la memoria se deben dejar como parámetros. Constrúyase un módulo de prueba y dibújense los cronogramas para los ciclos de lectura, escritura y refresco.

    Se debe programar lo máximo posible mediante puertas, con ayuda de módulos del tipo de los vistos en estas sesiones (multiplexores, contadores,...).

    Como todo proyecto complejo, debéis enfrentaros a él de un modo incremental. No programéis todas las funciones al principio. Por ejemplo, podéis dejar el circuito de refresco para el final. Podéis seguir también un esquema de arriba a abajo. Algunos módulos complejos pueden, en versiones iniciales, programarse a más alto nivel, con órdenes de comportamiento y, una vez funcione el diseño, irlos sustituyendo por sus versiones con puertas.

    Ayuda para la realización del ejercicio

  7. FINIS
  8. Órdenes de la shell relacionadas.

    ls
    lista el contenido de un directorio
    cd
    cambia el directorio de trabajo
    rm
    borra un fichero
    man
    muestra la página de manual de una orden
    cat
    muestra el contenido de un fichero


  9. LPEs.


© 2010 Guillermo González Talaván.