La descripción para la CPLD ya está terminada. Uffff! ¡¡por poco no cabe!! He usado todos los pines de la CPLD, y más del 80% de sus recursos.
He pedido una simulación del comportamiento de la CPLD para un posible caso de escritura de un valor en la SD. Para entender el cronograma que viene a continuación, hay que saber la asignación que he escogido para activar las diferentes funciones de esta interfaz, que es la siguiente:
Todas las operaciones son de lectura, ya que el slot ROM sólo se activa con lecturas, así que hay que simular escrituras con lecturas (ahora veremos cómo). Las posiciones "reservadas" hacen que no se active la EPROM.
La interfaz tiene un reloj programable, de forma que se puede establecer la velocidad con la que se accede a la tarjeta SD/MMC. La programación consiste en un valor de 8 bits, en el rango 00 a F9 inclusive. Este valor establece la longitud de un semiperíodo de la señal de reloj SPI (la usada por la tarjeta SD/MMC) en unidades de reloj del sistema (en el prototipo, 40MHz).
Leyendo la posición de memoria $FFFE se obtiene el último valor asignado al divisor de reloj. Para establecer un nuevo valor, hay que leer cualquier posición de memoria en el rango $FF00 a $FFF9 . El nuevo valor del divisor de reloj será el byte menos significativo de la dirección escogida (esto es, un valor entre $00 y $F9). Por supuesto, el valor leído no tiene sentido y se debe ignorar.
Tiene además un registro de estado de 3 bits. El bit 0 indica si la tarjeta está presente o no, el bit 1 indica si está activa la protección contra escritura (sólo disponible en zócalos SD/MMC adecuados), y el bit 2 indica si hay en curso una operación de lectura o escritura en la SD. Leyendo la posición de memoria $FFFD se obtienen los valores de estos 3 bits. El resto del byte leído debe ignorarse.
Para activar la tarjeta SD, se lee de la posición de memoria $FFFA. Esto hace que se encienda el LED que indica que una operación está activa. Leyendo de la posición $FFFB se desactiva la tarjeta SD y se apaga el LED. Al igual que antes, el valor leído en la operación no sirve para nada.
Para enviar un valor a la tarjeta SD se debe leer una posición de memoria comprendida entre $FE00 y $FEFF. El valor entregado a la tarjeta SD será el byte menos significativo de la dirección escogida.
Para leer el último dato entregado por la tarjeta SD, se lee la posición $FFFC.
Este esquema en el que se comparte el espacio de direcciones para la EPROM y el manejo de la interfaz hace que el firmware que vaya en dicha EPROM no pueda disponer de los últimos 512 bytes. El tamaño máximo del firmware es de $3E00 (15872) bytes, desde la posición $C000 hasta la $FDFF inclusive.
En resumen:
Código: Seleccionar todo
FExx : envía el dato xx de 8 bits a la SD
FF00-FFF9 : envia el valor 00 a F9 al divisor de reloj. El valor es el número de cuentas de un semiperíodo de SCLK, medido en unidades del reloj maestro (40MHz en el prototipo)
FFFA : activa la SD
FFFB : desactiva la SD
FFFC : último dato leído de la SD
FFFD : bits de busy, protección de escritura y tarjeta presente
FFFE : valor actual del divisor de reloj
Este es el resultado.
Y se interpreta así. Cada acceso a la interfaz, sea para leer la EPROM o para leer los registros de acceso a la tarjeta SD, están señalizados en los momentos en los que la señal ROMOEH pasa de 1 a 0 (flanco de bajada).
Hay un acceso a la posición $C000, que es una posición perteneciente a la EPROM de la interfaz, y no es una dirección reservada para registros, así que la señal de habilitación de la EPROM se activa (eprom_o).
Casi a la vez, se quita la tarjeta SD, con lo que la señal card_det pasa a 0.
Se lee la posición $FFFD, que devuelve $01 (tarjeta quitada)
Se inserta una tarjeta, y la señal card_det pasa a 1
Se lee de nuevo la posición $FFFD, que devuelve $00 (tarjeta puesta)
Se establece $03 como valor del divisor de frecuencia para el reloj SPI. Para ello se lee la posición $FF03. Se ignora el resultado.
Se activa la tarjeta SD y se enciende el LED, leyendo la posición $FFFA. la señal SS pasa a 0. Se ignora el resultado.
Se envía el byte $AA a la tarjeta SD. Para ello se lee la posición de memoria $FEAA. Se ignora el resultado.
En el cronograma se observan 8 ciclos de reloj en SCLK. En MOSI se tiene el valor binario $AA (10101010), emitido un bit cada vez. Una vez enviado el dato, hay que esperar a que termine el envío. Para ello se lee continuamente el bit de busy (bit 3 de la posición $FFFD).
Se lee la posición $FFFD, que devuelve $04 (tarjeta ocupada)
Se lee de nuevo la posición $FFFD, que devuelve $04 (tarjeta ocupada)
Se lee de nuevo la posición $FFFD, que devuelve $00 (tarjeta NO ocupada)
Se desactiva la tarjeta (y se apaga el LED) leyendo la posición $FFFB. La señal SS pasa a 1. Se descarta el resultado.
(sólo por comprobación). Se lee el valor actual del divisor de frecuencia desde la posición $FFFE. El valor devuelto es $03, que por supuesto coincide con el valor que escribimos casi al principio de la simulación.