-
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:
Su modo de operación es, asimismo, muy sencillo:
- N, al igual que ocurría con la celda estática,
sirve para aislar la celda cuando no queremos acceder a ella.
SEL es la línea de control que regula el acceso
- El corazón de la celda lo constituye un condensador.
Cuando el condensador está cargado, la celda almacena un
1. Almacena un 0 en el caso contrario
- Para escribir, se pone el valor deseado en BL y se activa SEL.
Esto carga o descarga el condensador de un modo acorde
- Leer es un poco más complicado. Se establece una tensión
intermedia en BL y se abre SEL. Se producirá un pulso de corriente
dependiendo de la carga del condensador que lo detectará un
circuito especial. Al leer, se actúa por consiguiente
sobre la carga del condensador, por lo que la operación de
lectura es destructiva
- El condensador dista de ser ideal por lo que presenta fugas. Esto hace
que, aun sin estar seleccionada la celda, con el pasar del tiempo,
acaba por descargarse y perder su valor. Estas celdas necesitan
refrescarse (cada cierto tiempo leer su valor para
volver a escribirlo a continuación)
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
trireg
s 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:
- La operación de lectura no es destructiva
- La operación de lectura se hace colocando BL en
alta impedancia
- 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:
- La versión actual de
iverilog
(0.9.2) no
admite trireg
s
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:
- La versión actual de
cver
(2.12a) tiene un error y no
trata adecuadamente a los trireg
s
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.
-
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;
-
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:
- El registro
r_out
se encarga de verter la salida
de la celda sobre la línea de entrada/salida io
- Se hace un seguimiento del valor de la línea
sel
- Si
sel
vale 1 e io
no está en
alta impedancia, se trata de una escritura y se alacena el valor
en el registro r
- Si
sel
vale 1 e io
está en alta
impedancia, tenemos una lectura y se saca el valor de r
por r_out
- Para modelar la descarga del condensador, se toma nota de cuándo
se realizó la última escritura en la variable
tw
. Si al realizar una lectura ha pasado demasiado
tiempo (más de t_exp
), se lee un cero
Copiad el módulo y programad un módulo auxiliar para probarlo.
¿Funciona bien en todas las circunstancias?
-
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 if
s 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.
-
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.
-
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:
- Tamaño de la palabra: 1 bit
- Tamaño de la memoria: 256 bits
- Organización: matriz de 16x16
- 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
- Señales de control: R_W (lectura 1, escritura 0)
- 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
- 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
- Consulta, estudia y comprende la solución
al ejercicio de la sesión anterior relativa a una memoria
SRAM
- Establece las semejanzas y diferencias entre ambos problemas:
líneas separadas de entrada y salida de datos (este) frente
a bus de datos de entrada/salida (el otro), tamaño de la
palabra de un bit (este) y cuatro bits (el otro), organización
matricial con líneas de RAS y CAS (este) frente a
organización lineal (el otro), refresco (este) frente a
sin refresco (el otro),...
- Trazar un plan de trabajo similar en objetivos parciales al del
ejercicio anterior. Una vez se desarrolla un objetivo, se prueba
y se depura completamente antes de pasar al siguiente. El resto
de puntos de esta lista os ofrece un bosquejo de dicho plan
- Primera etapa: Celda elemental
- Elegid un código de celda elemental de los dos propuestos.
Yo os recomiendo el código segundo, pues es más
fiel al comportamiento real de la celda
- Haced un diagrama de la configuración de la celda a
partir de su código Verilog. Es justo el proceso
contrario al que habéis seguido hasta ahora al hacer
un ejercicio: primero, diagrama, luego, código
- Variad el diagrama para que la celda admita de modo separado
una linea de entrada y una de salida. El prototipo del
módulo debe ser:
module MiCelda(output reg r_out, input wire in, input wire SEL);
Esto simplifica mucho las cosas, como enseguida os vais a dar cuenta.
Entre otras cosas, los sensores no van a ser necesarios, aunque
sí se necesitarán dos búferes o xmos
para que
cuando se seleccione la celda exista conexión de entrada
y de salida
- Segunda etapa: memoria de 1 bit
Hay que adaptar la intefaz de la memoria a las señales externas
que nos van a proporcionar:
- En la operación de lectura, la celda se selecciona al estar
activos RAS y CAS. R_W vale 1 y sirve para abrir, junto con SEL,
el búfer de salida
- En la operación de escritura, la celda se selecciona al
estar activos RAS y CAS. R_W vale 0 y sirve para abrir, junto con
SEL, el búfer de entrada
- Tercera etapa: fila de celdas
Construimos una fila de celdas con 16 celdas de un modo parecido a como
se hizo con la memoria SRAM. Aunque hay diferencias importantes
- En el ejercicio de la SRAM se trataba de aumentar el ancho de
palabra, por lo que cada celda de la fila tenía su propia
línea en el bus de datos. En este caso, todas las celdas
comparten la misma DI para entrada y la misma DO para salida
- La señal R_W se pasa tal cual a las celdas de modo
compartido
- A la fila le debe entrar una línea independiente para
seleccionar una celda concreta de la fila
- También debe haber una línea SEL para seleccionar
la fila
- Una celda estará seleccionada si la SEL de su fila está
seleccionada Y su línea independiente también lo está
- Para probar este módulo, dejad la línea SEL de la fila
a 1. Mediante un decodificador 4x16, activáis la línea
independiente de cada celda de la fila en función de lo que
haya en el bus de direcciones
- Cuarta etapa: matriz de celdas
En la etapa anterior, debemos haber sido capaces de leer una celda concreta
dentro de la única fila de 16 celdas que teníamos. En esta
etapa, completamos el diseño de la memoria, poniendo 16 filas
de 16 celdas.
- El el módulo SRAM final, declaramos las 16 filas
- Las lIneas DI y DO de las filas están unidas entre sí
y a las líneas DI y DO del chip SRAM respectivamente
- Las selecciones de celda de las filas están también unidas
entre sí y al decodificador, como en la etapa anterior
- Lo nuevo son las líneas de selección de fila.
El problema viene porque el bus de direcciones está
multiplexado, esto es, por las mismas líneas de direcciones
se nos da primero la fila (cuando baja RAS) y luego la columna
(cuando, mantenida baja RAS, baja CAS). De algún modo hay
que mantener guardado el número de fila cuando aparece.
Lo logramos mediante biestables de tipo D que alacenen el valor
del bus de direcciones cuando baja RAS.
- La salida de estos biestables irá a un decodificador 4x16
cuyas salidas irán a las líneas de selección de
las filas
- De este modo, para leer o escribir, ponemos la línea
R_W de modo acorde, ponemos la fila en el bus de direcciones,
bajamos RAS, esto hace que el número de fila quede
atrapado en los biestables D, ponemos la columna en el bus
de direcciones, bajamos CAS. En ese momento, solamente la
celda implicada estará seleccionada y haremos la
lectura o la escritura
- Quinta etapa: refresco (para aprobar la práctica
no es necesario tener hecha esta parte. Eso sí, la nota baja
a quienes no la hagan)
En esta etapa tenéis más libertad para construir
el mecanismo de refresco. En líneas generales:
- Debéis detectar la condición de refresco
(baja CAS y RAS está alto)
- El contador de la fila que se debe refescar se incrementa
- Esa fila se selecciona y se le indica que debe refrescarse
- Lo más fácil es que incluyáis el mecanismo
de refresco en la celda y lo activéis mediante alguna
línea de control adicional
FINIS
-
Ó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
-
LPEs.