-
Notifications
You must be signed in to change notification settings - Fork 13
CT.11: Señales del sistema. Medición con el LEDOscopio
Estudiaremos los fundamentos de las señales del sistema: las que funcionan con el reloj del sistema y que son muy rápidas. Aprenderemos a generarlas, retrasarlas, combinarlas mediante las operaciones básicas y a visualizarlas en los LEDs con el LEDOscopio. Los conceptos mostrados serán de gran ayuda para comprender los cuadernos técnicos más avanzados
- 2022-Julio-24: Version inicial del cuaderno técnico
- 2024-Mayo-18: Ejemplos adaptados a la nueva toolchain: apio-0.9.4. Eliminado el error en la verificación. Probados con icestudio 0.12. Los pantallazos de los ejemplos no se han actualizado todavía
Todos los ejemplos se han probado con Icestudio 0.12. Usa esta versión o superior
- CT11: Colección con TODOS los ejemplos de este cuaderno técnico
- iceSignals: Colección para este cuaderno técnica. Descargar e instalar. Usa esta versión o superior
- LEDOscopio: Bloques para medir las señales del sistema
Todos los ejemplos de este cuaderno técnico están accesibles desde el menú Archivo/Ejemplos/CT11 de Icestudio, una vez instalada y selecciona la colección CT11
- Introducción
- Arranque del circuito: Ciclo 0
- LEDOscopio
- Start: Señales de arranque
- Retrasando señales
- Generando una señal patrón
- Operaciones con señales
- Bloque Sys-Delay: Retrasando una señal N ciclos
- Generando un pulso
- Trabajando en ns
- Detección de flancos
- Generando señales periódicas
- Conclusiones
- Autor
- Licencia
- Créditos y agradecimientos
- Enlaces
Las señales del sistema son aquellas que tienen frecuencias cercanas a la del reloj del sistema y que usamos para gobernar a otros circuitos. La unidad del tiempo es el ciclo. Son señales muy rápidas, y por tanto difíciles de visualizar y depurar
Hay una señal del sistema que hemos usado muchísimo: el tic. Es el pulso mínimo, que tiene una anchura de 1 ciclo. Lo usamos para representar un evento, como por ejemplo la pulsación de un botón, la llegada de un byte por el puerto serie, la orden de escritura en una memoria...
En esta figura vemos el estado de dos señales durante 5 ciclos de reloj, desde el ciclo i
hasta el ciclo i+4
. La señal 1 es un pulso que dura 2 ciclos, mientras que la señal 2 dura 1 ciclo (es por tanto un tic)
No podemos medir nada menor a un ciclo (es nuestra resolución temporal). Trabajar en ciclos tiene la ventaja de que nos da igual la velocidad real. Por ejemplo, el circuito para generar un pulso de una anchura determinada (en ciclos) será el mismo para cualquier placa, con independencia de la frecuencia de su reloj (12Mhz, 16Mhz, 50Mhz, 100Mhz...)
En el caso de la placa Alhambra II, el reloj es de 12Mhz, por lo que cada ciclo dura 1/12Mhz = 83.3ns
Todo empieza en el ciclo 0. Una vez que la FPGA se ha configurado, arranca el ciclo 0 y nuestro circuito empieza a funcionar. Los biestables tendrán sus valores de inicialización listos a partir de este ciclo
En esta figura vemos lo que ocurre con dos señales en los primeros cuatro ciclos de reloj. Las señales están inicializadas desde el ciclo 0, y van cambiando sus valores. El primer flanco de subida llega al finalizar el ciclo 0 y comenzar el 1
La señal superior es una señal para inicializar circuitos (señal de reset). En el ciclo 0 está activa (1) y luego se pone a 0 en el resto de ciclos
La señal inferior emite un tic
en el ciclo 2 para arrancar otro circuito
En este Cuaderno técnico aprenderemos a generar señales como estas, que se usan para inicializar y arrancar otros circuitos. La clave para trabajar con señales del sistema desde el ciclo 0 es medirlas y visualizarlas
Las FPGAs nos permiten diseñar cualquier circuito digital. Dado que el hardware funciona en paralelo, podemos crear circuitos para realizar mediciones y añadirlos a nuestros diseños. El LEDOscopio es un analizador lógico extremadamente simple, que nos permite observar unos pocos ciclos de una señal en los LEDs
Se encuentra en la colección iceLedoscope. Y hay de varios tipos
Empezaremos por el LEDOscopio más simple: Uno que muestra los primeros 4 ciclos de la señal, en 4 LEDs
Vamos a hacer un experimento para aprender a usar el LEDOscopio. En esta imagen se muestran las dos señales (de mayor y menos peso) de un contador de 2 bits que se incrementa en cada ciclo de reloj (un contador del sistema de 2 bits)
En este circuito de ejemplo se ha conectado el bit de menor peso (bit 0) del contador a un LEDOscopio de 4-bits. Al cargarlo en la placa vemos en los LEDs del 0 al 3 el estado en los ciclos del 0 al 3
Un LED endendido se corresponde con la señal a 1 en ese ciclo, y un LED apagado es la señal a 0
Observamos que hay una correspondencia 1-1 entre los LEDs y los ciclos de la señal. ¡Vemos la señal!
Esta es la maravilla del LEDOscopio, que nos permite observar señales MUY RÁPIDAS (La señal es de 6 MHz), sin necesidad de utilizar equipos externos. Es una herramienta tremendamente útil para comprobar el funcionamiento de muchos de nuestros circuitos, y garantizar su funcionamiento
Y además nos permite ver lo que ocurre desde el ciclo 0, justo al arrancar nuestros circuitos
Comenzamos con el estudio de diferentes señales básico, y cómo las podemos generar utilizando componentes fundamentales
Las señales más básicas que podemos generar son las constantes: 0 y 1. Son señales que toman un valor inicial (0 ó 1) y lo mantienen durante toda la vida del circuito. Son señales que No cambian
Por ejemplo, en esta gráfica se muestran las señales a y b, que tienen los valores constantes 1 y 0 respectivamente
En el dibujo sólo se muestran sus valores durante los 4 primeros ciclos, pero permanecen con esos valores durante todo el tiempo, hasta que se quite la alimentación del circuito
Estas señales se generan con los bloques constantes 0 y 1. Podemos utilizar dos LEDoscopios de 4 bits para comprobar sus valores en los 4 primeros ciclos de reloj. Este es el circuito de pruebas:
Al cargar el circuito y probarlo en la Alhambra II observamos cómo los LEDs 0-3 se encienden (señal a) y los LEDs 4-7 están apagados (señal b)
La señal no constante más básica que se puede generar la denominamos señal de start. Tiene una pinta como la mostrada en esta gráfica. Está a nivel 1 durante el primero ciclo de reloj, y el resto del tiempo está a 0 (hasta que el circuito se apague)
Se denomina señal de start porque nos sirve para inicializar o arrancar otros circuitos. Es una señal muy básico pero MUY IMPORTANTE
¿Cómo podemos generar una señal así?. Utilizando los elementos fundamentales de los circuitos digitales: un biestable D y un bit constante. Los biestables D tienen la propiedad de mantener el valor durante un ciclo de reloj y luego captura el nuevo valor que llegue por su entrada. Esta operación la repiten en cada ciclo de reloj del sistema
Cargamos el circuito en la placa. Vemos la señal de start en los LEDs. El LED 0 está encendido y los LEDS 1-3 apagados. Esto significa que hay un tic activo en el ciclo 0, y luego se pone a 0 en el resto de ciclos: es justo una señal de start
Esta señal de start la podemos usar directamente a partir del bloque start: Genera un tic inicial en el primer ciclo reloj, y luego permanece a 0
Su implementación es como ya la conocemos:
Una operación básica que hacemos con las señales es retrasarlas: se obtiene la misma señal, con su misma forma, pero que empieza un ciclo más tarde
La operación de traso se implementa con los Biestables D. Cada Biestable D retrasa la señal un ciclo. De hecho, se llaman biestables D por esta propiedad: D es de Delay (Retraso)
En esta figura se muestran dos señales de start. La primera comienza en el ciclo 0 (Señal a), y la segunda (señal b) se ha retrasado un ciclo
La señal a se obtiene directamente del bloque start. Su salida se introduce por el Biestable D obteniéndose la señal b, que se lee a través del LEDOscopio para ver su forma
En este dibujo vemos la salida del LEDOscopio, y cómo la señal b tiene la forma esperada: Es la señal de start retrasada un ciclo, por eso sólo se enciende el LED1 (Ciclo 1)
Si queremos realizar retrasos mayores, basta con conectar en serie los biestables D. Una cadena de N biestables en serie provoca un retraso de N ciclos. En este dibujo se muestran dos biestables D encadenados, que provocan un retraso de 2 ciclos
En este diagrama vemos las señales a, b y c. La primera es una señal de start. La segunda está retrasada 1 ciclo, y la tercera 2 ciclos
Para comprobarlo usamos este circuito de ejemplo. La señal c está conectada al LEDOscopio para observar el retraso
En esta figura se muestra el resultado. Ahora sólo se enciende el LED 2 (Ciclo 2)
La conexión en serie de Biestables D nos permite establecer los valores que se quiere tener en cada ciclo, y así podemos generar cualquier patrón. En esta figura se muestra una señal con el patrón 0101. La señal toma un valor diferente en cada ciclo. A partir del quinto ciclo su valor se fija a 0. En esta tabla se muestra el patrón a generar:
Ciclo: | Ciclo 0 | Ciclo 1 | Ciclo 2 | Ciclo 3 | Ciclos > 3 |
---|---|---|---|---|---|
Valor: | 0 | 1 | 0 | 1 | 0 |
Para su generación usamos 4 biestables D conectados en Serie. El situado más a la derecha es el que contiene el bit mostrado en el ciclo 0. El biestable conectado a su izquierda contiene el bit que se mostrará en el ciclo 1 (con un ciclo de retraso). El de su izquierda el bit que saldrá en el ciclo 2 (dos ciclos de retraso)... y así sucesivamente
La señal s se visualiza con el LEDOscopio. Se comprueba que efectivamente aparece el patrón 0101
en los LEDs
Otra manera de construir señales es partir de señales básicas y aplicar operaciones entre ellas: Inversiones (NOT), uniones (OR), intersecciones (AND) y diferencias (XOR)
La operación de "diferencia" es una XOR que en realidad no es la típica operación de diferencia (a - b), sino que muestra los ciclos que son diferentes entre las dos señales. Lo que está a 0 significa que es igual en ambas señales
En las siguientes secciones veremos ejemplos de todas estas operaciones, mostrándolas en un LEDOscopio de 8 LEDs
La operación de inversión es unaria, y se realiza con la puerta lógica NOT. En este ejemplo se invierne una señal de start y se muestra en un LEDosciloscopio de 8 LEDs
Este es el resultado. Los LEDs del 1 al 7 están endendidos. El LED0 está apagado
La operación de unión se realiza con dos señales y la puerta OR. Como ejemplo vamos a generar un pulso de 2 ciclos de anchura que se pone a uno en el ciclo 1
Esta señal se podría generar perfectamente como un patrón (Como vimos en el apartado anterior), colocando tres biestables D en serie inicializados con los valores 0, 1, 1 y conectando un 0 en la entrada del de la izquierda. Pero en este ejemplo lo vamos a generar utilizando la operación de Unión y retrasos
Las operaciones concretas para generar esta señal se muestran en este dibujo
Partimos de una señal de arranque, que llamamos a. La retrasamos un ciclo para generar la señal b. Esto de representamos con la operación b=r(a)
, donde r() es una función que retrasa un ciclo. Ahora obtenemos la suma de las dos funciones: a+b
para combinarlas. Y finalmente la retrasamos un ciclo para obtener la función s.
De manera algebraica, la expresión de la señal s en función de a es la siguiente:
s = r(a + r(a))
Este es el circuito para generar la señal s a partir de las operaciones anteriores
Al cargarlo en la placa vemos la señal s
en el LEDoscopio de 8 LEDs. Efectivamente, sólo los LEDs 1 y 2 están encendidos
La operación de intersección se realiza con dos señales y la puerta AND. Como ejemplo vamos a realizar la intersección de un pulso inicial de 2 ciclos con el mismo pulso pero retrasado un ciclo. Las operaciones y señales intermedias se muestran en esta figura:
Partimos de una seña inicial (a
), que es un pulso de 2 ciclos de anchura. En este caso lo generamos como señal patrón, utilizando 2 biestables en serie. Pero en vez de utilizarlos de manera discreta, se ha usado un Registro de desplazamiento a la derecha, que en su interior contiene estos dos biestables en serie
Utilizando un biestable del sistema (Sys-DFF) retrasamos este pulso para obtener la señal b
, que es r(a)
Ahora realizamos la intersección de ambas señales, a
y b
, por lo que obtenemos la señal final: s = a.b = a.r(a)
El circuito de ejemplo que realiza esta operación es el siguiente:
Al cargarlo en la placa vemos la señal s
en el LEDoscopio de 8 LEDs. Sólo el LEDs 1 está encendido
La operación de diferencia (XOR) se realiza con dos señales y la puerta XOR. Como ejemplo vamos a realizar la operación XOR entre las mismas señales de apartado anterior: un pulso inicial de 2 ciclos con el mismo pulso pero retrasado un ciclo. Las operaciones y señales intermedias se muestran en esta figura:
Partimos de una seña inicial (a
), que es un pulso de 2 ciclos de anchura. En este caso lo generamos como señal patrón, utilizando 2 biestables en serie. Pero en vez de utilizarlos de manera discreta, se ha usado un Registro de desplazamiento a la derecha, que en su interior contiene estos dos biestables en serie
Utilizando un biestable del sistema (Sys-DFF) retrasamos este pulso para obtener la señal b
, que es r(a)
Ahora realizamos la operación XOR entre ambas señales, a
y b
, por lo que obtenemos la señal final: s = a xor b = a xor r(a)
El circuito de ejemplo que realiza esta operación es el siguiente:
Al cargarlo en la placa vemos la señal s
en el LEDoscopio de 8 LEDs. Sólo los LEDs 0 y 2 está encendidos
Hay una operación fundamental: Retrasar una señal un número determinado de ciclos (N). Ya sabemos cómo hacerlo: basta con colocar N biestables D del sistema encadenados. Así, si queremos retrasar una señal 32 ciclos, hay que encadenar 32 biestables D. O lo que es equivalente, un registro de desplazamiento de 32 bits
Sin embargo, en muchas aplicaciones la señal a retrasar es un tic
, y no una señal con una forma más compleja. En estos casos se puede implementar de manera más compacta, gastando menos recursos. Es el bloque Sys-Delay. Existen diferentes variaciones de este bloque:
Los bloques más óptimos son los que implementan un retraso fijo, que es potencia de dos: 2, 4, 8, 16, 32... Luego están los que implementan un retraso variable, a los que se les pasa la cantidad de ciclos a retrasar por su entrada N. O bien este valor N también se puede pasar como parámetro. Los circuitos de retraso variables son más complejos y consumen más recursos
Todos los bloques de retraso tienen una interfaz común, que no sólo es propia de ellos sino que la tienen todos los circuitos que llamamos Máquinas simples (y que analizaremos en otros cuadernos técnicos). Estas señales son:
-
Señales de entrada:
-
start
: Es el tic (pulso de 1-ciclo) que arranca el circuito. Por aquí se introduce el pulso que queremos retrasar
-
-
Señales de salida:
-
busy
: Señal de ocupado. Indica si el bloque de retraso está funcionando, o está inactivo -
done
: Señal de terminado. Es el pulso de salida (tic) que se genera cuando se ha cumplido el retraso indicado -
n
: Ciclo actual. Según el bloque de delay, empieza en el ciclo 0 y termina en N-1, o bien empieza en el 1 y termina en el N, donde N es el número de ciclos a retrasar. Es una señal auxiliar que se permite a otros circuitos conocer el tiempo actual en ciclos, y realizar las operaciones necesarias
-
En esta figura se muestran las señales de interfaz del bloque ejemplo Sys-Delay-x08, que sirve para retrasar 8 ciclos el tic de entrada. Pero son las mismas para el resto de bloques Sys-Delay
En este cronograma se muestra un ejemplo de las señales de interfaz, para un temporiador genéricos que retrasa N ciclos el pulso de entrada
La señal n, que indica el ciclo actual, NO SE HA DIBUJADO, porque su semántica depende del tipo de bloque. En algunos empieza contando desde 0, pero en otros desde 1
Estos bloques de retardo son los más optimizados. Nos permiten realizar un retraso cuyo valor es una potencia de 2: 2, 4, 8, 16, 32... Los valores de la señal n de salida, que indica el ciclo actual van desde 0 hasta N-1, donde N es la potencia de dos. Así, para un bloque de 4 ciclos de retraso, los valores de n
serán 0,1,2 y 3
En esta figura se muestran algunos de estos bloques de retardo fijo
Vamos a Analizar algunos de ellos, para entender su funcionamiento
El retardo de un ciclo se puede hacer con un biestable D del sistema, sin embargo el bloque Sys-delay-x01 tiene las señales de interfaz estándar y permite intercambiar unos bloques de delay por otros, sin tener que recablear
El cronograma se muestra en esta figura:
Las señales busy
, done
y n
, todas de un bit, son iguales
En este ejemplo se realiza la medición con el LEDOscopio, de la señal done
Este es el resultado al analizarlo con el LEDoscopio:
Las etiquetas n
y busy
están disponibles para medirlas también con el LEDOscopio. Como son iguales a done, no haremos la medición (se deja como un ejercicio para el lector)
La implementación de este bloque es muy sencilla. Se usa un biestable D del sistema (Sys-DFF) cuya salida se usa como salida done
, busy
y n
El retraso de 2 ciclos se realiza muy fácilmente colocando 2 biestables D del sistema en serie, o bien un registro de desplazamiento de 2 bits. Sin embargo, en el bloque Sys-Delay-x02 se implementa una solución general que consume menos recursos, aunque sólo sirve para retrasar señales de tipo tic
. En la parte de implementación analizaremos todas las posibilidades de implementación
El cronograma se muestra en esta figura:
La señal done
está retrasada 2 ciclos con respecto a start
, según lo esperado. Ahora la señal de busy es diferente: es un pulso de 2 ciclos de anchura, ya que el componente tarda 2 ciclos en terminar. La señal n
es de un bit, y coincide con done
. Indica el ciclo de espera en el que se encuentra, comenzando por 0. Los dos ciclos de espera son n=0 y n=1
En este ejemplo se retrasa un tic inicial dos ciclos. Se está midiendo la señal done
, pero están las etiquetas busy
y n
disponibles para conectar al LEDOscopio para realizar su medición
En este dibujo se muestran los resultados de las mediciones de las señales de busy
y done
Realizaremos diferentes implementaciones, para comprender el funcionamiento, conocer los recursos empleados y entender mejor la solución definitiva
La primera implementación es la más sencilla. Se usa un registro de desplazamiento de dos bits para retrasar un tic inicial 2 ciclos. Sólo tiene la señal de salida (done), que se mide con el LEDOscopio
Esta implementación (medida sin el LEDOscopio) consume 5 bloques lógicos
Recurso | Cantidad |
---|---|
LC | 5 |
La ventaja de esta implementación es que sirve para retrasar cualquier señal, y no sólo los tics
Queremos que el bloque sys-delay disponga de las salidas de busy
y n
. La implementación se logra añadiendo un biestable RS que arranca con start
y que se resetea al final, transcurridos los dos ciclos. Esto lo hacemos con la señal de salida del registro de desplazamiento
Cuando llega la señal start
, por un lado entra en el registro de desplazamiento para generar el retraso de los 2 ciclos, y por otro activa el Biestable RS para indicar que el circuito está ocpado funcionando. La señal de salida done
se lleva al reset del biestable para desactivarlo, y que busy
se ponga a cero
Esta implementación consume un poco más que la anterior: 6 bloques lógicos
Recurso | Cantidad |
---|---|
LC | 6 |
La implementación 2 es muy fácil de entender, pero no escala bien. Si ahora queremos, por ejemplo, hacer un retraso de 32 ciclos, habría que usar un registro de desplazamiento de 32 bits (32 biestables). Utilizando un contador conseguimos el mismo resultado pero consumiendo menos biestables
Para realizar el delay de 2 ciclos usamos un contador de 1 bit, que se implementa con un biestable T:
La señal de start
activa el Biestable RS para indicar que el circuito está funcionando. Cuando el biestable está activo, el contador tiene un '1' en su entrada de cuenta, y en cada ciclo de reloj del sistema se incrementa. Como el retraso es de sólo 2 bits, cuando se incrementa el contador pasa de 0 a 1, y se desactiva el Biestable RS
Esta es una solución que escala muy bien, y consume poco registros: 5 bloques lógicos (lo mismo que la implemantación 1)
Recurso | Cantidad |
---|---|
LC | 5 |
Aunque sólo sirve para retrasar el tic
de entrada (y no una señal genérica)
El bloque Sys-delay-x04 retarda 4 ciclos de reloj el tic recibido por su entrada
El cronograma de su funcionamiento se muestra en esta figura:
En este ejemplo se retrasa un tic inicial cuatro ciclos. Se está midiendo la señal done
, pero está la etiquetas busy
disponible para conectar al LEDOscopio para realizar su medición
En este dibujo se muestran los resultados de las mediciones de las señales de busy
y done
Este bloque ya está implementado de la forma final: Un biestable RS para almacenar el estado del circuito (ON/OFF) y un contador de 2-bits para llevar la cuenta de los 4 ciclos. La salida max del contador, que se pone a uno cuando el contador alcanza el valor máximo (3), se usa como señal done
. Esta señal es la que se usa también para resetear el biestable RS, y apagar el circuito
Esta implementación (medida sin el LEDOscopio) consume 7 bloques lógicos
Recurso | Cantidad |
---|---|
LC | 7 |
El bloque para hacer un retardo de 8 ciclos es similar al de 4, y se pone aquí como último ejemplo para entender cómo funcionan los bloques de retardo fijo. El resto de bloques Sys-delay de retardo fijo son similares, pero cambiando el número de bits
El cronograma de su funcionamiento se muestra en esta figura:
En este ejemplo se retrasa un tic inicial ocho ciclos. Se está midiendo la señal done
, pero está la etiquetas busy
disponible para conectar al LEDOscopio para realizar su medición. Se utiliza un LEDOscopio de 16 bits, pero como la Alhambra-II sólo tiene 8 LEDs, se visualizan en 2 ventanas de 8 bits
Inicialmente se ve la ventana 0, en la que todos los LEDs están a 0, porque el tic inicial del ciclo 0, al retrasarlo 8 ciclos, se vería en el ciclo 9, que no está visible en la ventana 0. Al apretar el pulsador SW1 se cambia a la ventana 1 y se comprueba que el primer LED efectivamente está encendido
En este dibujo se muestran los resultados de las mediciones de la señal de Done
, en ambas ventanas:
Y en este otro se muestra la señal de busy
:
La implementación del bloque sys-delay-x08 es la misma que para el resto de bloques de esta familia: Un biestable RS y un contador de 3 bits. En general, para un retraso R (potencia de 2), se necesita un biestable RS y un contador de N bits, donde 2**N es R
Al arrancar el circuito, con la señal start, se activa el biestable RS. Cuando se alcanza el valor máximo del contador, este biestable se vuelve a poner a 0
Esta implementación (medida sin el LEDOscopio) consume 8 bloques lógicos
Recurso | Cantidad |
---|---|
LC | 8 |
Esta familia de bloques nos permiten realizar un retardo de N tics, donde ahora N NO tiene porqué ser una potencia de 2, sino cualquier valor mayor a 1. El tamaño de estos bloques depende el número de bits utilizamos para representar el retardo máximo. Por ejemplo, para un bloque de 3 bits, el retardo máximo será de 7 ciclos. El retardo que podemos usar, N, estará comprendido entre 2 (retardo mínimo) y 7 (retardo máximo)
Estos bloques consumen más recursos que los de retardo fijo, por lo que si vamos a utilizar un retardo que es potencia de dos, es mejor usar los de retardo fijo
El retardo N a utilizar se puede introducir de dos maneras: mediante una entrada de bus, o bien mediante un parámetro. Por ello tenemos dos tipos de bloques: sys-delay-xN y sys-delay-xN-K
La salida de bus n
indica el ciclo actual, PERO es ligeramente diferente a la salida n
de los bloques de retardo fijo. Su valor comienza en 1 y llega hasta el número total de ciclos de retraso: N. Así, si queremos especificar un retardo de 5 ciclos, los valores que salen por n son 1, 2, 3, 4 y 5
La semántica del número de retrasos, N, es el número total de ciclos, y NO su valor máximo. Se ha hecho así para que no haya confusión. De esta forma, si queremos un retardo de 7 ciclos, hacemos que N=7
Hay que tener cuidado con los valores máximos introducidor por N. Ya que si, por ejemplo, queremos un retardo de 8 ciclos (N=8), necesitamos 4 bits para representar ese valor (Ya que 8 en binario es 1000). En los de retardo fijo, como están optimizados, un retardo de 8 ciclos lo conseguimos con 3 bits
El valor N de retraso tiene que ser siempre >=2. Es decir, que el retardo mínimo es 2. Si queremos utilizar un retardo de 1, debemos utilizar bien un biestable D del sistema o el bloque Sys-Delay-x01
Estos bloques tienen una entrada de bus, N[]
, por donde se indica el retardo a realizar. Este valor está comprendido entre 0 (Sin retardo) y N (el retardo que queremos)
Note Es importante indicar que el valor N introducido debe permanecer constante durante el funcionamiento del circuito: Debe tener un valor estable mientras la señal busy está a uno. Cuando está a 0, se puede cambiar
Todos los bloques de este tipo son iguales. La única diferencia está en el número de bits usados, lo que nos determina el valor máximo (N) de retardo que queremos. Así por ejemplo, en el componente mostrado en este ejemplo el tamaño es de 3 bits. Esto nos permite espeficiar retardos entre 2 y 7 ciclos.
Si necesitamos hacer retardos mayores, hay que incluir un componente con más bits (y que ocupará más recursos)
En este cronograma se muestran los valores de las señales cuando se realiza un retardo de 5 ciclos, usando el componente Sys-Delay-xN de 3 bits:
En este ejemplo se retrasa un tic inicial 3 ciclos. Dado que el retraso es de 3 ciclos, necesitamos usar al menos un bloque Sys-Delay-xN de 2 ó más bits. El que consumiría menos recursos es el de 2 bits, pero el resultado sería el mismo si se usa otro de más bits
(18-sys-delay-xN-3-ciclos.ice)
El retraso se lo estamos introduciendo por la entrada N, usando una constante de 2 bits. Pero, por supuesto, este valor podría venir de cualquier otro circuito y NO sólo de una constante
El cronograma se muestra en esta figura
En este dibujo se muestran los resultados de las mediciones de las señales de busy
y done
En este ejemplo se retrasa un tic inicial 5 ciclos. Necesitamos usar al menos un bloque Sys-Delay-xN de 3 ó más bits
(19-sys-delay-xN-5-ciclos.ice)
En este dibujo se muestran los resultados de las mediciones de las señales de busy
y done
Los bloques Sys-delay-xN están implementados utilizando un biestable RS para almacenar el estado del circuito, y un contador módulo M con reset, cuyo valor inicial es 1
Este circuito, muy simplificado, funciona perfectamente, aunque sólo es válido cuando la entrada N es estrictamente mayor a 1. Para N=0 ó N=1 el circuito no es válido
Estos bloques son similares a los anteriores (Sys-Delay-xN) PERO el retraso se introduce como un parámetro en vez de como una entrada (es por tanto un valor constante, que no puede cambiar durante la vida del circuito).
Por el parámetro N se introduce el retraso en ciclos. Este valor tiene que ser estrictamente superior a 1. Los valores N=0 y N=1 NO SON VÁLIDOS
Este circuito realiza un retraso de 5 ciclos, igual que el ejemplo 19, pero usando el bloque sys-Delay-xN-K de 3 bits
(20-sys-delay-xN-K.5-ciclos.ice)
Los resultados son exactamente iguales que en el ejemplo anterior
La implementación es directa a partir de una constante y un bloque Sys-delay-xN
Los pulsos son señales que inicialmente están en reposo (0), luego se activan (1) durante un cierto número de ciclos y finalmente vuelven a la situación inicial de reposo. El pulso más corto que se puede generar ya lo conocemos: el tic. Es un pulso que dura sólo 1 ciclo de reloj
Los pulsos se utilizan muchísimo. Son las señales que nos indican que ha sucedido un evento, como por ejemplo la existencia de datos disponibles, o la señal E de los displays de cristal líquito (LCD). Se usa para que el LCD capture los datos de entrada. Los pulsos también sirven para mantener encendido un periférico, como por ejemplo un LED, durante un tiempo
Se necesitan dos evento para definir un pulso: un evento inicial, que marca el inicio del pulso (transición de 0 a 1) y un evento final, que indica su fin (transición de 1 a 0). Ambos eventos están separados N ciclos de reloj
Los pulsos se generan usando un Biestable RS. Por su entrada de set se introduce la señal que arranca el pulso (evento de inicio) mientras que por la entrada de reset la señal para terminarlo (evento de fin)
El evento final es el mismo que el inicial, pero separados N ciclos en el tiempo. Eso se consigue con un circuito de retraso, como los que ya los conocemos. El evento inicial es un simple tic. Por ello, el esquema básico de un generador de pulsos es el que se muestra en esta figura:
Como ejemplo usaremos este esquema básico para obtener un pulso de 2 ciclos de retraso. El pulso se genera al recibirse un tic inicial. Usamos dos biestables D del sistema para generar el retardo, y el biestable RS para obtener el pulso
El cronograma de este circuito se muestra en esta figura
Lo comprobamos con el LEDOscopio, y vemos que efectivamente este circuito produce un pulso de 2 ciclos de anchura
El bloque Sys-Delay-xN tiene un Biestable RS interno para generar la señal de Busy. Pues bien, esta señal es exactamente el pulso de N ciclos de anchura. Así que para generar un pulso de N ciclos basta con usar un bloque Sys-Delay-xN
En este ejemplo se genera un pulso de 6 ciclos de anchura, y se mide con el LEDOscopio
Este es el resultado:
El tiempo se mide en ciclos, que son unidades indivisibles. Hablamos de 1,2,3 ó N ciclos, pero no podemos medir 1.5 ciclos, por ejemplo. Dependiendo de la frecuencia del reloj del sistema, cada ciclo se corresponde un tiempo,que es igual al periodo del reloj (T)
En la tarjeta Alhambra II y muchas otras, el reloj del sistema tiene una frecuencia de 12Mhz, cuyo periodo es T = 1 / 12Mhz = 83.3ns. Así, un ciclo de reloj se corresponde con 83.3 ns
No es posible realizar retrasos de cualquier cantidad, sino sólo en múltiplos del periodo de reloj. En esta tabla se muestra la equivalencia entre ciclos y el tiempo en ns
Se calcula utilizando la siguiente fórmula:
Tiempo (ns) = (1 / 12) * 1000 * Ciclos
Ciclos | Tiempo (ns) | Ciclos | Tiempo (ns) |
---|---|---|---|
1 | 83.3 | 11 | 916.6 |
2 | 166.6 | 12 | 1000 |
3 | 250 | 13 | 1083.3 |
4 | 333.3 | 14 | 1166.6 |
5 | 416.6 | 15 | 1250 |
6 | 500 | 16 | 1333.3 |
7 | 583.3 | 17 | 1416.6 |
8 | 666.6 | 18 | 1500 |
9 | 750 | 19 | 1583.3 |
10 | 833.3 | 20 | 1666.6 |
Observa que para los ciclos múltiplos de 3, se obtienen tiempos exactos en ns. Por ejemplo, 12 ciclos equivalen a un tiempo de 1000 ns (1ms)
Los circuitos de retraso funcionan en ciclos. Pero en muchas aplicaciones nos resulta más sencillo expresarlo en ns. Necesitamos realizar la conversión de nano segundos a ciclos. Esto lo hacemos aplicando la siguiente fórmula:
Ciclos = Ceil(0.012 * tiempo)
Donde tiempo es el tiempo en nano-segundos y Ceil() es la función de redondeo al alza
Este es el código en python para realizar ese cálculo:
import sys
import math
if (len(sys.argv) <= 1):
print("Retardo no especificado")
sys.exit(0);
#-- El primer argumetno es el retardo en ns
R = float(sys.argv[1])
#-- Convertir a Ciclos
Ciclos = math.ceil(0.012 * R)
#-- Clacular el retardo real
R_real = Ciclos / 0.012
#-- Calcular el error
error = abs(R_real - R)
print(f"* Retardo objetivo: {R} ns")
print(f"* Ciclos: {Ciclos}")
print(f"* Retardo real: {R_real:.1f} ns")
print(f"* Error: {error:.1f} ns")
Este es un ejemplo de uso: Convertir de 800ns a ciclos
obijuan@Hoth:~$ python3 ns2c.py 800
* Retardo objetivo: 800.0 ns
* Ciclos: 10
* Retardo real: 833.3 ns
* Error: 33.3 ns
Como 800ns no es múltiplo de un periodo, son necesarios 10 ciclos, pero el retardo real entonces es de 833.3ns
, y el error es de 33.3ns
El bloque ns realiza la conversión de nanosegundos a ciclos. Funciona como una constante, que sirve para introducirla en los bloques que tienen entrada de ciclos, como los de delay
En esta figura se muestra el bloque ns de 2-bits. Cómo máximo la salida puede ser 3, que se corresponde a 250ns. Si el número de ns introducidos es mayor que su máximo, el valor de ciclos obtenido será incorrecto
En este ejemplo se muestra un circuito que genera un pulso de 500ns de anchura
Un retraso de 500ns se corresponde con 6 ciclos, a la frecuencia de 12Mhz, por eso en las mediciones en el LEDOscopio es lo que se ve:
Si lo medimos con un osciloscopio externo, comprobamos que efectivamnete el pulso es de 500ns
El pulso medido es de 500ns porque esta cantidad se corresponde exactamente con 6 ciclos de reloj. Sin embargo, si se introduce otra cantidad no exacta habrá un error, y el pulso tendrá una anchura diferente a la especificada en el bloque ns
Las señales binarias de nuestros circuitos sólo pueden estar en dos estados: 0 ó 1. Las transiciones de un valor a otro se denominan flancos y tenemos dos tipos:
- Flancos de subida: Transición de 0 a 1. Ocurre un flanco de subida cuando el valor de la señal en un ciclo es 0 y pasa a valer 1 en el ciclo siguiente
- Flancos de bajada: Transición de 1 a 0. El flanco de bajada ocurre cuando la señal vale 1 en un ciclo, y pasa a 0 en el ciclo siguiente
Así, si observamos un pulso de una anchura de N ciclos, vemos que está formado por dos flancos, uno de subida y otro de bajada. Entre ambos la señal permanece a 1, sin cambios
Los flancos los detectamos con unos circuitos que se llaman detectores de flancos. Nos indican cuándo ha ocurrido un cambio en la señal. Tenemos de tres tipos: Detectores de flancos de subida, de flancos de bajada, o detectores de ambos flancos:
Todos estos bloques emiten por su salida un pulso de 1 ciclo de anchura (tic) cuando detectan el flanco correspondiente
El bloque para detectar flancos de subida se llama Rising-Edge. La señal llega por su entrada, y por la salida se genera un tic
cuando se detecta un flanco de subida
En este Cronograma se detalla su funcionamiento. Por la entrada se introdcuen dos pulsos, y por su salida se obtienen 2 tics, cada uno correspondiente a su flanco de subida
En este ejemplo se detectan los flancos de subida de una señal como la mostrada en el cronograma anterior: está formada por un pulso de 3 ciclos de anchura, seguido de un de 2 ciclos de anchura. Ambos están separados 1 ciclo, y el primero comienza en el ciclo 1
Este es el circuito:
La señal generada se pasa por el detector de Flancos de subida y se introduce en el LEDOscopio para medirla. El resultado se muestra en esta figura. Se ha incluido también la medición de la señal original, para compararla con el cronograma del apartado anterior
El detector de flancos de subida tiene un retraso de 0 ciclos. Esto significa que si introducimos un tic
por su entrada, en la salida obtenemos el mismo tic
, sin retrasar. En esta figura vemos el cronograma:
En el ejemplo 25 lo comprobamos experimentalmente. Por un lado medimos un pulso inicial (tic) y por otro lado, lo pasamos por el detector de flancos de subida y lo medimos
En esta figura se muestra el resultado de las mediciones. Ambas señales son iguales
El detector de flancos de subida utiliza un biestable D del sistema para almacenar el valor de la señal en el ciclo anterior, y este valor se compara con el que tiene en el ciclo actual. Si el ciclo anterior era 0 y resulta que ahora la señal vale 1, significa que ha llegado un flanco de subida. Esta comparación se hace con una puerta AND
El bloque para detectar flancos de bajada se llama Falling-Edge. La señal llega por su entrada, y por la salida se genera un tic
cuando se detecta un flanco de bajada
En este Cronograma se detalla su funcionamiento. Por la entrada se introdcuen dos pulsos, y por su salida se obtienen 2 tics, cada uno correspondiente a su flanco de bajada
En este ejemplo se detectan los flancos de bajada de una señal como la mostrada en el cronograma anterior: está formada por un pulso de 3 ciclos de anchura, seguido de un de 2 ciclos de anchura. Ambos están separados 1 ciclo, y el primero comienza en el ciclo 1
Este es el circuito:
La señal generada se pasa por el detector de Flancos de bajada y se introduce en el LEDOscopio para medirla. El resultado se muestra en esta figura. Se ha incluido también la medición de la señal original, para compararla con el cronograma del apartado anterior
El detector de flancos de bajada tiene un retraso de 0 ciclos con respecto al ciclo en el que la señal se pone a 0. En este cronograma se introduce un tic
por su entrada. En la salida obtenemos otro tic
que está retrasado un ciclo:
Sin embargo, NO hay retraso en el flanco de bajada. En la señal de entrada la señal se pone a 0 en el ciclo 2. Y es justo en ese ciclo, el 2, donde la señal de salida se pone a 1, indicando que hay un flanco de bajada. El flanco de bajada se produce en el ciclo 2. Y en ese mismo ciclo se señaliza su aparación
En el ejemplo 27 lo comprobamos experimentalmente. Por un lado medimos un pulso inicial (tic) y por otro lado, lo pasamos por el detector de flancos de bajada y lo medimos
En esta figura se muestra el resultado de las mediciones
El detector de flancos de bajada utiliza un biestable D del sistema para almacenar el valor de la señal en el ciclo anterior, y este valor se compara con el que tiene en el ciclo actual. Si el ciclo anterior era 1 y resulta que ahora la señal vale 0, significa que ha llegado un flanco de bajada. Esta comparación se hace con una puerta AND
El bloque para detectar flancos se llama Edges. La señal llega por su entrada, y por la salida se genera un tic
cuando se detecta un flanco de subida o uno de bajada
En este Cronograma se detalla su funcionamiento. Por la entrada se introdcuen dos pulsos, y por su salida se obtienen 4 tics, cada uno correspondiente a un flanco de subida o de bajada
En este ejemplo se detectan los flancos de subida y bajada de una señal como la mostrada en el cronograma anterior: está formada por un pulso de 3 ciclos de anchura, seguido de un de 2 ciclos de anchura. Ambos están separados 1 ciclo, y el primero comienza en el ciclo 1
Este es el circuito:
La señal generada se pasa por el detector de Flancosa y se introduce en el LEDOscopio para medirla. El resultado se muestra en esta figura. Se ha incluido también la medición de la señal original, para compararla con el cronograma del apartado anterior
En un tic
, al igual que en el resto de pulsos, hay 2 flancos. Por tanto, cuando introducimos un tic
en el detector de flancos se obtiene como salida un pulso de 2 ciclos de anchura, que se corresponde con la unión de los dos tics
obtenidos por los detectores de subida y bajadas indepedienetes
En el ejemplo 29 lo comprobamos experimentalmente. Por un lado medimos un pulso inicial (tic) y por otro lado, lo pasamos por el detector de flancos de bajada y lo medimos
En esta figura se muestra el resultado de las mediciones
Una forma sencilla de implementar el detector es mediante la unión de los dos detectores: de subida y bajada, usando una puerta OR. Sin embargo, estamos gastando un biestable para cada detector. Es posible realizar una implementación más optimizada usando sólo un biestable D del sistema y los circuitos combinacionales necesarios para detectar la relación entre el ciclo anterior y el actual
Sólo si hay cambios en estos ciclos, significa que ha llegado un flanco de algún tipo. Por ello basta con usar una puerto XOR que precisamente se pone a 1 sólo cuando hay cambios
Saber manejar y medir las señales del sistema es necesario para generar las señales de sincronización de nuestros circuitos. También sabemos crear pulsos, lo que será muy útil para construir señales periódicas. Con todo esto ya tendremos las herramientas para implementar controladores
- Juan González-Gómez (Obijuan)
- Carlos Venegas. Muchísimas gracias por toda tu ayuda y tus aportaciones 😄
- Unidad de PWM de frecuencia aproximada
- VGA Retro: Puesta en marcha. MonsterLED
- Pines de Entrada/Salida
- Control de LEDs
- SPI esclavo
- SPI Maestro
- Display SPI de 4 dígitos de 7 segmentos
- Entrada y Salida de Bits con Componentes Virtuales
- Memorias
- Entradas y pulsadores
- Señales del sistema. Medición con el LEDOscopio
- Controlador LCD 16x2
- Señales periódicas y temporización
- Buses: Medio compartido
- Memoria Flash SPI
- Conexión de LEDs en la Alhambra II. Placa AP‐LED8‐THT
- Periféricos PMOD
- Fundamentos. Sistema Unario
- Autómatas
- Pantallas de vídeo. Fundamentos. Display de 1x4 LEDs
- Pantallas de vídeo. Fundamentos. Matriz de 4x4 LEDs