Flip-flops y registros: cómo la computadora «recuerda» datos

De la lógica combinacional a la secuencial: entiende el principio de funcionamiento de los flip-flops D y los registros


es el bit más significativo, bit

Imagina que tienes una cámara en tus manos. Antes de pulsar el obturador, el mundo exterior cambia constantemente: peatones que caminan, hojas que se agitan, luces que se alternan entre brillantes y oscuras.

Pero en el instante en que pulsas el obturador (flanco de subida del reloj), la escena actual queda «capturada» en la fotografía.

Después, sin importar cómo cambie el mundo exterior, el contenido de la foto queda congelado para siempre en ese instante. Este es el comportamiento principal del flip-flop D: en el flanco de subida de la señal de reloj, capturar y guardar el dato.


Lógica combinacional vs. lógica secuencial

En las lecciones anteriores, los circuitos que estudiamos como la puerta AND, OR, NOT, etc., pertenecen a lalógica combinacional. Su salida está determinada únicamente por la entrada actual: si la entrada cambia, la salida cambia inmediatamente (ignorando el retardo de propagación).

Pero para que una computadora pueda «recordar» datos, necesita un circuito que pueda mantener la salida incluso después de que la entrada desaparezca. Esto es lalógica secuencial。

Diferencia clave

La lógica combinacional es como una lámpara: se enciende al pulsar el interruptor y se apaga al soltarlo; la salida depende por completo de la entrada actual.

La lógica secuencial es como una caja fuerte: pones algo dentro y la cierras con llave (llega el flanco de subida del reloj); después, incluso si te alejas (la entrada desaparece), lo de dentro sigue allí.

Dimensión de comparación Lógica combinacional Lógica secuencial
Dependencia de la salida Solo depende de la entrada actual Depende de la entrada actual y del estado anterior
Capacidad de memoria No (sin estado) Sí (puede recordar historia)
Circuitos típicos Puertas AND, OR, NOT, sumador Flip-flop D, registros, contadores
Dependencia del reloj No depende del reloj Depende de la señal de reloj para sincronizar las actualizaciones de estado
Bucle de retroalimentación Sin retroalimentación (sin bucle) Tiene bucle de retroalimentación para mantener el estado

Estructura y comportamiento del flip-flop D

El flip-flop D (D Flip-Flop)es la unidad básica de lógica secuencial. Tiene dos entradas y una salida:

D (Data): entrada de datos, representa el valor a almacenar (0 o 1).

CLK (Clock): entrada de reloj, controla cuándo capturar el dato.

Q: salida de datos, genera el valor actualmente almacenado.

Comportamiento clave: el flip-flop D solo en elflanco de subida(el instante en que pasa de 0 a 1) captura el valor de D en Q. En el resto del tiempo, sin importar cómo cambie D, Q permanece igual.

Esto es como la cámara que solo graba la escena en el instante de pulsar el obturador; en otros momentos, por mucho que cambie la escena exterior, la foto no se ve afectada.

¿Por qué se necesita el reloj?

Sin la señal de reloj, la salida del flip-flop D cambiaría continuamente con la entrada, convirtiéndose en otro circuito de lógica combinacional. La «memoria» no sería posible.

La señal de reloj proporciona uncompás de sincronización, que hace que todos los flip-flops actualicen su estado en un instante unificado. Todo el sistema informático se coordina bajo este ritmo.


Registros: múltiples flip-flops en paralelo

Un flip-flop D solo puede almacenar 1 bit de dato. Para almacenar un byte (8 bits) o una palabra (32 bits), se necesitan varios flip-flops conectados en paralelo.

Conecta N flip-flops D en paralelo, haz quecompartan la misma señal de reloj, y así se forma un registro de N bitsregistro (Register)。

Cuando llega el flanco de subida del reloj, todos los flip-flops capturan simultáneamente el valor de su propia entrada D, de modo que se guarda de una vez el dato completo de N bits.

Registros multinivel y pipeline

Dentro de la CPU, la salida de un registro suele conectarse a la siguiente etapa de lógica combinacional y luego al siguiente registro, formando unaestructura de registro - lógica combinacional - registroen pipeline.

En cada ciclo de reloj, los datos pasan de un registro a través del cálculo de lógica combinacional y se almacenan en el siguiente registro en el siguiente flanco de subida. Esta es la base del pipeline de las CPU modernas.


Demostración de código: simulación de flip-flop D y registros en Python

A continuación se simula con código Python el comportamiento de un flip-flop D y de un registro de 4 bits. Presta especial atención a la lógica de detección del flanco de subida: solo cuando se detecta que clk pasa de 0 a 1 se captura el dato.

Ejemplo

class DFlipFlop:
    """
Flip-flop D: captura el dato de entrada en el flanco de subida del reloj

Reglas de comportamiento:
- Cuando el reloj pasa de 0 a 1 (flanco de subida), el valor de la entrada D se captura en la salida Q.
- En el resto del tiempo (clk=0, clk=1 pero sin transición), Q mantiene su valor original sin cambios.
    """

    def __init__(self, name="DFF"):
        self.q = 0           # Salida Q, inicialmente 0
        self.prev_clk = 0    # Valor del reloj en el instante anterior, para detectar el flanco de subida
        self.name = name

    def update(self, d, clk):
        """
Actualizar el estado del flip-flop

Parámetros:
d: Entrada de datos (0 o 1)
clk: Señal de reloj (0 o 1)

Retorna:
El valor actual de la salida Q.

Detección de flanco de subida: prev_clk == 0 y clk == 1
Solo cuando se cumple esta condición, el valor de d se captura en q.
        """

        # === Detección de flanco de subida ===
        if self.prev_clk == 0 and clk == 1:
            self.q = d  # En el flanco de subida, captura el valor de D en Q
        self.prev_clk = clk  # Registra el estado actual del reloj para el siguiente ciclo
        return self.q

    def reset(self):
        """Reinicia el estado del flip-flop"""
        self.q = 0
        self.prev_clk = 0


class Register4Bit:
    """
Registro de 4 bits: 4 flip-flops D en paralelo, compartiendo la misma señal de reloj

Diagrama de estructura:
D3 ──▶ [DFF3] ──▶ Q3 (bit más significativo)
        D2 ──▶ [DFF2] ──▶ Q2
        D1 ──▶ [DFF1] ──▶ Q1
D0 ──▶ [DFF0] ──▶ Q0 (bit menos significativo)
↑↑↑↑ Comparten el mismo CLK

Cuando llega el flanco de subida del reloj, los 4 flip-flops capturan simultáneamente sus respectivas entradas D.
    """

    def __init__(self):
        # Crea 4 flip-flops, bit
        self.flip_flops = [
            DFlipFlop("bit3"),
            DFlipFlop("bit2"),
            DFlipFlop("bit1"),
            DFlipFlop("bit0"),
        ]

    def update(self, data, clk):
        """
Actualizar el registro

Parámetros:
data: Dato a almacenar (entero de 0-15; si se sale del rango se trunca)
clk: Señal de reloj (0 o 1)

Retorna:
El valor actualmente almacenado en el registro (0-15)
        """

        data = data & 0b1111  # Asegura que solo los 4 bits sean válidos
        # Envía cada bit al flip-flop correspondiente, empezando por el más significativo
        for i in range(4):
            # Extrae cada bit de mayor a menor: bit3, bit2, bit1, bit0
            bit = (data >> (3 - i)) & 1
            self.flip_flops[i].update(bit, clk)
        return self.read()

    def read(self):
        """Lee el valor actualmente almacenado en el registro (sin cambiar el estado)"""
        value = 0
        for ff in self.flip_flops:
            value = (value << 1) | ff.q
        return value

    def reset(self):
        """Reinicia todos los flip-flops"""
        for ff in self.flip_flops:
            ff.reset()


# ============================================================
# Simulación de demostración: comportamiento del registro bajo varios ciclos de reloj
# ============================================================
if __name__ == "__main__":
    reg = Register4Bit()

    # Secuencia de datos de prueba: simula la escritura de diferentes datos en distintos ciclos de reloj
    test_data = [5, 10, 15, 0, 7, 13, 3, 8, 1, 14]
    # 5=0101, 10=1010, 15=1111, 0=0000, 7=0111
    # 13=1101, 3=0011, 8=1000, 1=0001, 14=1110

    print("=" * 55)
    print(ejemplo - Simulación de registro de 4 bits)
    print(Observación: los datos solo se capturan en el registro en el flanco de subida del reloj)
    print("=" * 55)
    print(f{'Ciclo':<6} {'Reloj':<10} {'Dato de entrada D':<12} {'Valor del registro Q':<12} {'Descripción'})
    print("-" * 55)

    for cycle in range(10):
        data = test_data[cycle]

        # Fase 1: nivel bajo del reloj (clk=0), el valor del registro no debe cambiar
        reg.update(data, 0)

        # Fase 2: flanco de subida del reloj (clk pasa de 0→1), se captura el dato
        result = reg.update(data, 1)

        data_bin = f"{data:04b}"
        result_bin = f"{result:04b}"
        note = ← Captura en flanco de subida if result == data else El estado no cambia

        print(f"{cycle:<6} {'0→1':<10} {data}({data_bin}){'':<4} {result}({result_bin}){'':<4} {note}")

    print("-" * 55)
    print()

    # ============================================================
    # Demostración adicional: los datos solo se capturan en el flanco de subida; el resto del tiempo se mantienen
    # ============================================================
    print("=" * 55)
    print(Demostración 2: cuando no es flanco de subida, los cambios de datos no se capturan)
    print("=" * 55)

    reg2 = Register4Bit()
    # Primero escribe el valor inicial 5
    reg2.update(5, 0)
    reg2.update(5, 1)
    print(fEscritura de 5 en flanco de subida → Valor del registro: {reg2.read()})

    # clk se mantiene en nivel alto; cambia el dato a 10; no debe ser capturado
    reg2.update(10, 1)
    print(fCambiar el dato a 10 con clk=1 → Valor del registro: {reg2.read()} (debería seguir siendo 5))

    # clk vuelve a nivel bajo; luego se aplica un flanco de subida para escribir 10
    reg2.update(10, 0)
    result = reg2.update(10, 1)
    print(f"Cuando clk pasa de 0→1, se escribe 10 → valor del registro: {reg2.read()} (ahora es 10)")

    print()
    print("=" * 55)
    print("¡Demostración completada! ejemplo - Comprender los flip-flops y los registros")
    print("=" * 55)

Demostración interactiva: diagrama de tiempos del flip-flop D

Abajo, usandola opción stepped:true de Chart.jsse dibuja el diagrama de tiempos de la señal de reloj (onda cuadrada) y de la señal de datos.Las líneas verticales rojas marcan cada flanco de subida del reloj (el momento en que CLK pasa de 0 a 1), estos momentos son precisamente los instantes clave en los que el flip-flop D captura los datos.

Diagrama de tiempos del flip-flop D: demostración de captura en flanco de subida

Reloj CLK (onda cuadrada) Entrada de datos D Salida Q (valor capturado)
Línea discontinua roja = momento del flanco de subida (el flip-flop D captura los datos).
La salida Q solo se actualiza en el flanco de subida; permanece sin cambios el resto del tiempo.
Otras extensiones