Teach Lecciones con laboratorios remotos

Lección Teach

Lógica digital en la DE1-SoC con VHDL (5/6): máquinas de estados finitos

El alumnado construye y modifica una FSM Moore de semáforo en la DE1-SoC, con un detector Mealy opcional.

  • Altera DE1-SoC
  • 45 min
  • Secundaria (16–18 años)
  • Español
  • Sistemas digitales y FPGA
Altera DE1-SoC
Altera DE1-SoC

Resultados de aprendizaje

  • Explicar qué es una máquina de estados finitos en términos de estados, transiciones y salidas.

  • Explicar por qué el semáforo es una máquina Moore y reconocer un detector Mealy como extensión opcional.

  • Leer y modificar una FSM VHDL de dos o tres bloques: registro de estado, lógica de siguiente estado y lógica de salida.

  • Construir y modificar un controlador de semáforo en la DE1-SoC real.

  • Explicar por qué el reset asíncrono activo en bajo importa cuando una FSM con reloj lento debe volver a un estado conocido.

Vista previa de la actividad del estudiante

Contenido de la actividad

Solo vista previa. En una sesión de clase, los estudiantes pueden completar respuestas y entregar su trabajo al docente.

1

Qué es una máquina de estados finitos

10 min

Ya construiste circuitos que recuerdan: un biestable guarda un bit, un registro guarda varios y un contador guarda su cuenta actual. Una máquina de estados finitos (FSM) organiza esa memoria en *situaciones con significado*. En cada instante la máquina está en exactamente uno de un conjunto pequeño y fijo de estados. Para un semáforo, los estados podrían ser VERDE, AMARILLO y ROJO. El número de estados es finito, y la máquina siempre está en uno y solo uno de ellos.

Una FSM se define por tres cosas:

- Estados: el conjunto finito de situaciones posibles. Un estado especial es el estado de reset, donde empieza la máquina.
- Transiciones: las reglas para pasar de un estado a otro. En cada flanco de reloj, la máquina mira su estado actual y sus entradas, y decide cuál será el siguiente estado. La transición VERDE -> AMARILLO significa "si estás en VERDE y se cumple la condición, en el próximo flanco irás a AMARILLO".
- Salidas: lo que la máquina controla en sus salidas (aquí, los LED) en cada situación.

Toda la máquina avanza con el reloj: en cada flanco puede cambiar a un nuevo estado según el estado actual y las entradas actuales, y mantiene ese estado hasta el siguiente flanco. Entre flancos no hace más que esperar: el mismo comportamiento de muestreo y retención que viste con los biestables, ahora usado para recorrer una secuencia de estados.

Moore frente a Mealy. Las FSM se escriben en dos estilos que solo difieren en *de dónde salen las salidas*:

- En una máquina Moore, las salidas dependen solo del estado actual. Si conoces el estado, conoces las salidas; las entradas no aparecen en la ecuación de salida. El semáforo es Moore: cuando el estado es ROJO, el LED rojo está encendido, punto.
- En una máquina Mealy, las salidas dependen del estado actual y de las entradas actuales. El mismo estado puede producir salidas distintas según lo que esté haciendo la entrada en ese instante. El detector de secuencia es Mealy: activa "detectado" en un estado concreto *solo si el bit entrante también tiene el valor correcto*.

Las salidas Moore son estables mientras permaneces en un estado. Las salidas Mealy pueden cambiar en cuanto cambia una entrada, incluso sin salir del estado; eso las hace rápidas, pero también potencialmente breves o sensibles a glitches, algo importante cuando observas por cámara.

Forma típica de una FSM en VHDL. Casi todas las FSM de este curso usan dos o tres bloques:

1. Un registro de estado: proceso VHDL con reloj (if rising_edge(clock) then ...) que guarda el estado actual y copia el siguiente estado en cada flanco. Es el único bloque con memoria.
2. Un bloque de siguiente estado: bloque combinacional (un proceso combinacional de VHDL) que calcula cuál debe ser el siguiente estado a partir del estado actual y las entradas. Debe asignar valores de respaldo antes del case, o cubrir todas las ramas de forma explícita, para que todos los caminos den valor a las salidas y a next_state.
3. Lógica de salida: asignaciones concurrentes o parte de un proceso combinacional que produce las salidas desde el estado (Moore) o desde estado y entradas (Mealy).

Los dos diseños de esta lección siguen exactamente esta forma: registro de estado con reloj, proceso combinacional de siguiente estado con valores por defecto y lógica de salida.

Una máquina expendedora recuerda cuánto dinero se ha insertado y entrega un producto cuando se alcanza el precio. Si la modelas como una FSM, qué representa mejor el estado?

Un circuito enciende un LED cuando está en el estado BUSY y la entrada go vale 1 en ese momento. Esa salida es Moore o Mealy? Explícalo en una frase.

2

Nota obligatoria: reset asíncrono en estas FSM

7 min

Antes de construir nada, hay un cambio deliberado respecto a lecciones anteriores.

En la Lección 3, tu biestable y tu registro usaban reset síncrono: el reset se comprobaba dentro del proceso con reloj, por ejemplo if KEY(0) = '0' then Q <= '0'; dentro de if rising_edge(CLOCK_50) then. La Lección 4 ya usó reset asíncrono activo en bajo en circuitos con reloj lento; esta lección continúa ese estilo para el estado de la FSM, de modo que reset no espere al reloj lento.

Las FSM de esta lección usan un reset asíncrono activo en bajo. Mira la lista de sensibilidad del registro de estado:

process(slow_clk, KEY)
begin
    if KEY(0) = '0' then state <= TODO_RESET_STATE;
    elsif rising_edge(slow_clk) then state <= TODO_NEXT_STATE;
    end if;
end process;

Poner KEY en la lista de sensibilidad y comprobar if KEY(0) = '0' then antes de la rama de reloj significa que el proceso también responde en el instante en que KEY(0) baja (cuando pulsas el botón), no solo en un flanco de slow_clk. Así, al pulsar KEY(0), la máquina fuerza su estado conocido de inmediato, sin esperar al reloj lento.

La diferencia, de forma clara:

- Reset síncrono (Lecciones 2-3): actúa solo en un flanco de reloj. Es limpio y predecible, pero con un reloj lento tienes que esperar al flanco.
- Reset asíncrono (Lecciones 5-6): actúa de inmediato, en cuanto se activa el reset, independientemente del reloj.

¿Por qué cambiar aquí? Estas FSM se mueven con un slow_clk dividido cuyos flancos están separados por segundos. Si el reset fuera síncrono, podrías pulsar KEY(0) y no ver nada durante más de un segundo hasta el siguiente flanco lento; justo cuando una máquina se atasca quieres una salida instantánea. Un reset asíncrono te da ese "volver al inicio" inmediato y fiable en la placa real. KEY es activo en bajo, así que KEY(0) bajando a 0 es el momento en que pulsas el botón y KEY(0) = '0' es verdadero mientras lo mantienes pulsado.

Pulsas KEY(0) cuando falta casi un segundo para el siguiente flanco de slow_clk. Con el reset asíncrono de estas FSM, cuándo salta la máquina a su estado de reset? Cuándo habría saltado con un reset síncrono?

El registro de estado está escrito como process(slow_clk, KEY) con if KEY(0) = '0' then ... elsif rising_edge(slow_clk) then .... Qué añade esa rama de reset asíncrono, y cómo se comportaría el reset si la borraras y dejaras solo un proceso con rising_edge(slow_clk)?

3

Ejercicio 3-A: semáforo (FSM Moore)

10 min

Tu primera FSM es un controlador de semáforo. Tiene tres estados y pasa por ellos en un ciclo fijo, manteniendo cada luz durante cierto número de ticks:

VERDE -> AMARILLO -> ROJO -> VERDE -> ...

Conexiones: LEDR(0) = verde, LEDR(1) = amarillo, LEDR(2) = rojo, y KEY(0) = reset (activo en bajo), que devuelve la máquina a VERDE. La máquina usa un slow_clk dividido: cada flanco de subida de slow_clk es un tick de la máquina de estados. Con este divisor, usa unos 0,67 s por tick visible; el primer flanco de subida tras reset puede llegar antes.

Es una máquina Moore. La lógica de salida al final es:

LEDR(0) <= TODO_GREEN_LED;
LEDR(1) <= TODO_YELLOW_LED;
LEDR(2) <= TODO_RED_LED;

Cada LED es función solo del estado: no aparece ninguna entrada. Conocer el estado te dice exactamente qué luz está encendida. Esa es la propiedad que define una máquina Moore.

Dos registros distintos hacen dos trabajos distintos. Lee con cuidado el registro de estado, porque contiene *dos* memorias fáciles de confundir:

- state (una señal de tipo state_t) guarda qué luz está encendida ahora: GREEN, YELLOW o RED. Ese es el estado de la FSM.
- timer (una señal unsigned(2 downto 0)) es un contador de permanencia que cuenta cuántos ticks quedan en la luz actual. Mientras timer sea mayor que cero, simplemente decrementa (timer <= timer - 1) y el estado no cambia. Solo cuando timer llega a 0 la máquina avanza a next_state y recarga timer para la nueva luz.

Así que state guarda *cuál* luz está encendida, y timer cuenta *cuánto tiempo* permanece. Son registros diferentes con objetivos diferentes; timer es lo que hace que cada luz dure varios ticks en vez de pasar en un solo tick.

Tiempos reales del código. Cuando la máquina entra en cada estado, recarga timer, y contar desde el valor cargado hasta 0 inclusive da el número de ticks:

- GREEN carga timer = 3 y cuenta 3, 2, 1, 0 -> 4 ticks (aprox. 2,7 s).
- YELLOW carga timer = 1 y cuenta 1, 0 -> 2 ticks (aprox. 1,3 s).
- RED carga timer = 3 -> 4 ticks (aprox. 2,7 s).

Un ciclo completo dura entonces 4 + 2 + 4 = 10 ticks, aproximadamente 10 x 0,67 s = 6,7 s.

Máquina de estados Moore de tres estados para un semáforo: estados VHDL GREEN (verde), YELLOW (amarillo) y RED (rojo) conectados en ciclo. Cada estado tiene su permanencia en ticks, GREEN 4, YELLOW 2 y RED 4, y lista el único LED que enciende. Una flecha de reinicio KEY(0) entra al estado GREEN.

El semáforo como máquina Moore de tres estados: GREEN -> YELLOW -> RED -> GREEN, con un temporizador que mantiene cada estado un número fijo de ticks (GREEN 4, YELLOW 2, RED 4; un tick visible dura unos 0,67 s). Cada estado enciende exactamente un LED, así que las salidas dependen solo del estado. KEY(0) resetea la máquina a GREEN.

Entidad completa. El divisor produce slow_clk; el proceso de estado con reset asíncrono avanza la luz cuando expira el temporizador; un proceso combinacional calcula la siguiente luz; y las tres asignaciones concurrentes a LED son la lógica de salida Moore.

-- Plantilla de estudiante: completa las lineas TODO antes de sintetizar.
-- Lección 5 - Ejercicio 3-A: controlador de semáforo (FSM Moore).
-- KEY(0)=reset. LEDR(0)=verde, LEDR(1)=amarillo, LEDR(2)=rojo.
-- Permanencias: GREEN = 4 ticks, YELLOW = 2 ticks, RED = 4 ticks.
-- Un tick visible de la FSM es un flanco de subida de slow_clk, unos 0,67 s con este divisor.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity blink is
    port (
        CLOCK_50 : in  std_logic;
        KEY      : in  std_logic_vector(3 downto 0);
        LEDR     : out std_logic_vector(9 downto 0)
    );
end entity blink;

architecture rtl of blink is
    type state_t is (GREEN, YELLOW, RED);
    signal state, next_state : state_t := GREEN;
    signal timer : unsigned(2 downto 0) := "011";
    constant DIV : unsigned(24 downto 0) := to_unsigned(16666666, 25);
    signal div_count : unsigned(24 downto 0) := (others => '0');
    signal slow_clk : std_logic := '0';
begin
    process(CLOCK_50)
    begin
        if rising_edge(CLOCK_50) then
            if KEY(0) = '0' then
                div_count <= (others => '0'); slow_clk <= '0';
            elsif div_count = DIV then
                div_count <= (others => '0'); slow_clk <= not slow_clk;
            else
                div_count <= div_count + 1;
            end if;
        end if;
    end process;

    process(state)
    begin
        case state is
            when GREEN  => next_state <= TODO_AFTER_GREEN;
            when YELLOW => next_state <= TODO_AFTER_YELLOW;
            when RED    => next_state <= TODO_AFTER_RED;
        end case;
    end process;

    process(slow_clk, KEY)
    begin
        if KEY(0) = '0' then
            state <= GREEN; timer <= "011";
        elsif rising_edge(slow_clk) then
            if timer = 0 then
                state <= next_state;
                case next_state is
                    when GREEN  => timer <= TODO_GREEN_RELOAD; -- 4 ticks
                    when YELLOW => timer <= TODO_YELLOW_RELOAD; -- 2 ticks
                    when RED    => timer <= TODO_RED_RELOAD; -- 4 ticks
                end case;
            else
                timer <= timer - 1;
            end if;
        end if;
    end process;

    LEDR(0) <= TODO_GREEN_OUTPUT;
    LEDR(1) <= TODO_YELLOW_OUTPUT;
    LEDR(2) <= TODO_RED_OUTPUT;
    LEDR(9 downto 3) <= (others => '0');
end architecture rtl;

Las salidas del semáforo son asignaciones concurrentes como LEDR(0) <= '1' when state = GREEN else '0';. Si quisieras convertir una de esas salidas en Mealy en vez de Moore, qué tipo de término tendrías que añadir a su expresión que ahora no aparece?

4

Ejercicio 3-A en la placa: observar y modificar

12 min

Ahora construye el semáforo en la DE1-SoC real, mide cada fase y modifícalo.

  1. Abre el laboratorio VHDL de la DE1-SoC. El editor muestra blink.vhd.

  2. Selecciona todo el contenido de blink.vhd y reemplázalo por la plantilla del semáforo. Completa todas las líneas TODO, mantén el nombre blink y conserva CLOCK_50 : in std_logic.

  3. Pulsa Sintetizar. Si una guía tapa el botón, ciérrala o sáltala primero. Espera a que termine (aprox. 1-3 minutos). Los errores más comunes son olvidar CLOCK_50 en la lista de puertos o un punto y coma; corrige y vuelve a sintetizar. Continúa solo cuando el estado final diga 0 errores.

  4. Pulsa Enviar a la FPGA y espera a la placa y la cámara.

  5. Observa el ciclo. Mira cómo LEDR(0) (verde), LEDR(1) (amarillo) y LEDR(2) (rojo) se turnan. Cuenta cuántos segundos o ticks dura cada luz y regístralo. Compara con el código: GREEN 4 ticks, YELLOW 2, RED 4.

  6. Pulsa reset. Mientras esté encendido YELLOW o RED, pulsa y suelta KEY(0). La máquina debe volver directamente a GREEN de inmediato. Estás viendo el reset asíncrono.

Observa el ciclo del semáforo en la cámara. Registra la duración observada de cada fase (en segundos o ticks de unos 0,67 s) y compárala con los ticks esperados del código: GREEN 4, YELLOW 2, RED 4.

Fase (LED encendido) Ticks esperados (código) Duración observada (s o ticks)

Sube tu evidencia. Espera la fase YELLOW, captura una imagen de la cámara cuando LEDR(1) esté encendido y LEDR(0) y LEDR(2) estén apagados, y adjúntala abajo.

Ahora haz un cambio obligatorio de temporización.

(Modificar) Cambia los tiempos de permanencia. Edita los valores de recarga de timer para que el ciclo sea GREEN = 6 ticks, YELLOW = 4 ticks, RED = 6 ticks. Recuerda que el temporizador cuenta desde el valor cargado hasta 0 inclusive, así que N ticks significa cargar N - 1: carga "101" (5) para GREEN, "011" (3) para YELLOW y "101" (5) para RED (en el case dentro del registro de estado y también en la línea de reset si cambia el valor inicial de ese estado). Sintetiza, carga y confirma los nuevos tiempos en la cámara. Después calcula la nueva longitud total del ciclo en ticks.

Extensión opcional: añade un estado de rojo intermitente. Añade un cuarto estado, FLASH_RED, después de RED solo si tu docente pide la extensión. Para no controlar LEDR(2) desde dos sitios, reemplaza la asignación actual del LED rojo por un único driver combinado, por ejemplo LEDR(2) <= '1' when state = RED else timer(0) when state = FLASH_RED else '0';. Después añade FLASH_RED al tipo VHDL state_t y al case de siguiente estado, dale una duración en el case del temporizador, sintetiza, carga y confirma que el LED rojo parpadea antes de volver a verde.

Para hacer que YELLOW dure el doble, qué registro cambiarías (state o timer), dónde exactamente en el código, y qué registro dejarías completamente intacto?

Después de cambiar los valores de recarga, ejecuta de nuevo el semáforo. Registra los ticks modificados que observas para cada estado, de modo que el cambio de código quede evidenciado y no solo descrito.

Estado Ticks modificados observados Valor de recarga usado en el código

Con tus tiempos modificados (GREEN = 6, YELLOW = 4, RED = 6 ticks), cuánto dura un ciclo completo en ticks? Muestra la suma.

Usando el código y lo que observaste, justifica en dos o tres frases que este semáforo es una máquina Moore. Identifica la lógica de salida y explica por qué los LED son función solo del estado, no de ninguna entrada.

5

Extensión opcional: detector de la secuencia 1011 (FSM Mealy)

11 min

Tu segunda FSM observa una corriente de bits que llega uno por tick en SW(0) y enciende un LED cuando acaba de ver el patrón 1011. Es una máquina Mealy: activa "detectado" en un estado concreto *solo cuando el bit entrante también es correcto*, así que la salida depende de estado y entrada juntos.

Conexiones: SW(0) = bit serial de entrada, KEY(0) = reset (activo en bajo), LEDR(0) = detectado, y LEDR(5 downto 1) = estado actual en formato one-hot (un LED por estado) para depurar. La máquina usa un slow_clk dividido cuyo flanco de subida, un tick, ocurre aproximadamente cada 1,33 s.

Estados. El detector recuerda cuánto del patrón 1011 ha visto hasta ahora:

- S0: nada coincide todavía (estado de reset).
- S1: el último bit fue 1 (coincide 1).
- S2: coincide 10.
- S3: coincide 101.
- S4: coincide el patrón completo 1011. Desde aquí la máquina todavía puede empezar una nueva detección, lo que permite detecciones solapadas.

En cada tick, el bloque de siguiente estado mira el estado actual y el bit de SW(0). La salida detect se activa dentro de S3 solo cuando el bit entrante es 1, porque 101 seguido de 1 completa 1011. Esa es la salida Mealy: depende de estado y entrada.

Por qué enclavamos la salida: léelo con cuidado. La señal Mealy cruda detect está alta solo durante un tick. Con un reloj rápido sería invisible; incluso con este reloj lento, un destello de ~1,33 s es fácil de perder en una cámara remota si parpadeas o si el fotograma cae mal. Por eso este diseño no conecta detect directamente al LED. En su lugar enclava la detección: un registro separado detected_latch se pone a 1 cuando detect se dispara y permanece a 1 hasta que pulses reset. LEDR(0) muestra ese latch, así que una vez detectado 1011, el LED se enciende y *se queda encendido* hasta KEY(0). Es una decisión deliberada para observación remota: convertimos un evento breve en una indicación estable.

Máquina de estados Mealy que detecta la secuencia 1011, con estados S0 a S4. S0 es reset. Las flechas etiquetadas con bits muestran transiciones: S0 con 1 va a S1, S1 con 0 va a S2, S2 con 1 va a S3, y S3 con 1 completa 1011 y la flecha se marca `1 / detecta`.

Detector 1011 como máquina Mealy de cinco estados. Los estados S0..S4 indican cuánto del patrón se ha reconocido. La salida detect se activa desde estado S3 y entrada 1 juntos, por eso es Mealy. La regla de solapamiento mantiene la máquina lista para nuevas coincidencias. El pulso de un tick se enclava en LEDR(0) para que permanezca encendido hasta reset.

Entidad completa. Observa la forma de dos procesos: un proceso combinacional calcula next_state y la salida Mealy detect, y un process(slow_clk, KEY) guarda el estado y el latch con reset asíncrono.

-- Plantilla de estudiante: completa las lineas TODO antes de sintetizar.
-- Lección 5 - Ejercicio 3-B: detector de secuencia 1011 (FSM Mealy) con detección enclavada.
-- SW(0)=bit serie de entrada. KEY(0)=reset. LEDR(0)=detección enclavada.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity blink is
    port (
        CLOCK_50 : in  std_logic;
        KEY      : in  std_logic_vector(3 downto 0);
        SW       : in  std_logic_vector(9 downto 0);
        LEDR     : out std_logic_vector(9 downto 0)
    );
end entity blink;

architecture rtl of blink is
    type state_t is (S0, S1, S2, S3, S4);
    signal state, next_state : state_t := S0;
    signal detect, detected_latch : std_logic := '0';
    constant DIV : unsigned(26 downto 0) := to_unsigned(33333333, 27);
    signal div_count : unsigned(26 downto 0) := (others => '0');
    signal slow_clk : std_logic := '0';
begin
    process(CLOCK_50)
    begin
        if rising_edge(CLOCK_50) then
            if KEY(0) = '0' then
                div_count <= (others => '0'); slow_clk <= '0';
            elsif div_count = DIV then
                div_count <= (others => '0'); slow_clk <= not slow_clk;
            else
                div_count <= div_count + 1;
            end if;
        end if;
    end process;

    process(state, SW)
    begin
        next_state <= S0;
        detect <= '0';
        case state is
            when S0 => TODO_TRANSITION_FROM_S0;
            when S1 => TODO_TRANSITION_FROM_S1;
            when S2 => TODO_TRANSITION_FROM_S2;
            when S3 => TODO_TRANSITION_FROM_S3_AND_DETECT;
            when S4 => TODO_TRANSITION_FROM_S4;
        end case;
    end process;

    process(slow_clk, KEY)
    begin
        if KEY(0) = '0' then
            state <= S0; detected_latch <= '0';
        elsif rising_edge(slow_clk) then
            state <= next_state;
            if TODO_DETECT_CONDITION then detected_latch <= '1'; end if;
        end if;
    end process;

    LEDR(0) <= detected_latch;
    LEDR(5 downto 1) <= "00001" when state = S0 else
                         "00010" when state = S1 else
                         "00100" when state = S2 else
                         "01000" when state = S3 else
                         "10000";
    LEDR(9 downto 6) <= (others => '0');
end architecture rtl;

Podrías predecir exactamente cuándo se dispara detect mirando solo los LED de estado LEDR(5 downto 1), *sin* conocer SW(0)? Usa tu respuesta para explicar por qué es una salida Mealy y no Moore.

6

Extensión opcional en la placa: introducir bits y recuperar

12 min

Ahora construye el detector e introduce bits a mano. Cómo introducir un bit: coloca SW(0) con el valor del bit, espera un tick completo de slow_clk (unos 1,33 s) para que la máquina lo muestree en el siguiente flanco de subida, y después cambia SW(0) al siguiente bit y vuelve a esperar. Mira LEDR(5 downto 1) para seguir el estado.

  1. En blink.vhd, reemplaza todo el contenido por la plantilla del detector 1011 de arriba. Completa las transiciones y condición TODO, mantén el nombre blink y CLOCK_50 : in std_logic.

  2. Pulsa Sintetizar, espera a que termine correctamente y pulsa Enviar a la FPGA.

  3. Resetea primero. Pulsa y suelta KEY(0). LEDR(0) (detectado) debe estar apagado y LEDR(5 downto 1) debe mostrar S0 (00001).

  4. Introduce 1, 0, 1, 1. Pon SW(0) = 1, espera ~1,33 s; pon SW(0) = 0, espera; pon SW(0) = 1, espera; pon SW(0) = 1, espera. Después del último 1, LEDR(0) debe enclavarse encendido y quedarse así. Registra los LED de estado tras cada bit.

  5. Resetea, y después introduce 1, 0, 1, 0, 1, 1 (un bit incorrecto en medio). Introduce cada bit igual. La máquina no debe dispararse falsamente con el bit malo, debe recuperarse y debe detectar el 1011 del final (LEDR(0) se enclava). Esto muestra que la FSM se recupera de un bit incorrecto en vez de quedarse atascada.

  6. Resetea cuando quieras empezar una secuencia nueva; reset es lo único que apaga el LEDR(0) enclavado.

Introduce la secuencia 1,0,1,1, un bit por tick de slow_clk (aprox. 1,33 s cada uno). Después de cada bit, lee el estado en LEDR(5 downto 1) (one-hot: 00001=S0, 00010=S1, 00100=S2, 01000=S3, 10000=S4) y si LEDR(0) se ha enclavado. La detección debe enclavarse tras el último 1.

Bit introducido (SW(0)) LEDR(5 downto 1) observado (one-hot) LEDR(0) detectado? (on/off)

Sube tu evidencia. Después de introducir 1, 0, 1, 1, LEDR(0) se enclava encendido y permanece así hasta reset. Captura una imagen de la cámara mostrando LEDR(0) encendido y adjúntala abajo.

Extensión opcional si queda tiempo: modifica el detector para reconocer 101 en vez de 1011. Primero dibuja el nuevo diagrama de estados en papel: necesitas estados para "nada coincide", "coincide 1" y "coincide 10", y la salida detect debe dispararse cuando, estando en "coincide 10", el siguiente bit sea 1. Si lo implementas, conserva el latch y la visualización one-hot, sintetiza, carga y confirma que introducir 1, 0, 1 enclava LEDR(0).

La salida Mealy cruda detect está registrada (guardada en un biestable) o es combinacional (calculada directamente desde estado y entrada)? Qué problema temporal puede causar una salida Mealy combinacional, y cómo se conecta eso con que hayamos enclavado LEDR(0)?

Supón que conectaras el pulso crudo de un tick detect directamente a LEDR(0) en vez de enclavarlo. Con el reloj lento de ~1,33 s, qué verías probablemente en la cámara al detectar 1011, y por qué sería poco fiable capturarlo?

En el paso 5 introdujiste 1, 0, 1, 0, 1, 1 y aun así la máquina detectó 1011 al final. Explica brevemente cómo la FSM se recuperó del bit incorrecto sin quedarse atascada ni dispararse falsamente.

7

Qué construiste

4 min

Construiste un semáforo Moore en la DE1-SoC real: sus salidas dependen solo del estado y avanza GREEN -> YELLOW -> RED con un temporizador. Usaste la forma típica de FSM: registro de estado con reloj, bloque combinacional de siguiente estado con valores por defecto y lógica de salida, además de un reset asíncrono activo en bajo que fuerza un estado conocido de inmediato. Si hiciste la extensión opcional, también exploraste un detector Mealy de 1011 y por qué una salida de un tick se enclava para que una cámara remota pueda capturarla.

¿Qué secuencia coincide con lo que hiciste en cada ejercicio de esta lección?

En tres o cuatro frases: explica por qué el semáforo es Moore (cita su lógica de salida), diferencia el registro state y el registro timer, describe el cambio de permanencias que probaste, y nombra un momento donde importó la polaridad activa en bajo de KEY o el reset asíncrono. Si hiciste el detector opcional, añade una frase sobre por qué es Mealy o por qué se enclavó LEDR(0).