Teach Lições com laboratórios remotos

Lição do Teach

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

Construa e modifique uma FSM de Moore para um semáforo na DE1-SoC, com uma extensão opcional de detector Mealy.

  • Altera DE1-SoC
  • 45 min
  • Graduação introdutória
  • Português (Brasil)
  • Sistemas digitais e FPGA

Entre com uma conta de professor para preparar uma sessão. Os estudantes entram com um código da turma.

Máquina de estados finitos de Moore para um semáforo, com três círculos rotulados VERDE, AMARELO e VERMELHO ligados em ciclo. GREEN dura 4 pulsos, YELLOW dura 2 e RED dura 4; cada estado acende um único LED, mostrando que a saída depende somente do estado. Uma seta KEY(0)=reinício aponta para VERDE.
Altera DE1-SoC

Objetivos de aprendizagem

  • Explicar uma máquina de estados finitos em termos de estados, transições e saídas.

  • Explicar por que o controlador de semáforo é uma máquina de Moore e reconhecer um detector de Mealy como extensão opcional.

  • Ler e modificar uma FSM VHDL com dois ou três blocos: registrador de estado, lógica de próximo estado e lógica de saída.

  • Construir e modificar um controlador de semáforo na DE1-SoC real.

  • Explicar por que o reset assíncrono ativo em nível baixo importa quando uma FSM com clock lento precisa voltar a um estado conhecido.

Visualização da atividade do estudante

Conteúdo da atividade

Apenas visualização. Em uma sessão de aula, os estudantes podem preencher respostas e entregar o trabalho ao professor.

1

O que é uma máquina de estados finitos

10 min

Você já construiu circuitos que têm memória: um flip-flop guarda um bit, um registrador guarda vários e um contador guarda a contagem atual. Uma máquina de estados finitos (FSM) organiza essa memória em situações significativas. A cada instante, a máquina está em exatamente um elemento de um conjunto pequeno e fixo de estados. Em um semáforo, esses estados podem ser GREEN, YELLOW e RED. O número de estados é finito, daí o nome, e a máquina sempre está em exatamente um deles.

Uma FSM é definida por três elementos:

  • Estados — o conjunto finito de situações em que a máquina pode estar. Um deles é o estado de reset, no qual a máquina começa.
  • Transições — as regras para passar de um estado a outro. Em cada borda de clock, a máquina observa o estado atual e as entradas e decide qual será o próximo estado. A transição GREEN -> YELLOW significa: “se estiver em GREEN e a condição for satisfeita, vá para YELLOW na próxima borda”.
  • Saídas — os valores que a máquina aplica às saídas, aqui os LEDs, em cada situação.

Toda a máquina avança com o clock: em cada borda, ela pode passar a outro estado com base no estado atual e nas entradas atuais, depois mantém esse estado até a borda seguinte. Entre as bordas, ela apenas espera. É o mesmo comportamento de amostragem e retenção que você viu nos flip-flops, agora usado para percorrer uma sequência de estados.

Moore e Mealy. As FSMs têm dois tipos, que diferem apenas na origem das saídas:

  • Em uma máquina de Moore, as saídas dependem apenas do estado atual. Se você conhece o estado, conhece as saídas; as entradas não aparecem na equação de saída. O semáforo é Moore: quando o estado é RED, o LED vermelho está aceso, independentemente das entradas.
  • Em uma máquina de Mealy, as saídas dependem do estado atual e das entradas atuais em conjunto. O mesmo estado pode produzir saídas diferentes conforme a entrada naquele instante. O detector de sequência afirma “detectado” em certo estado somente quando o bit de entrada também tem o valor correto.

As saídas de Moore permanecem estáveis enquanto a máquina fica em um estado. As saídas de Mealy podem mudar assim que uma entrada muda, mesmo sem sair do estado. Isso as torna rápidas, mas também possivelmente breves e sujeitas a glitches, o que será importante na câmera.

A estrutura padrão de uma FSM em VHDL. Quase todas as FSMs deste curso são escritas como dois ou três blocos que trabalham juntos:

  1. Um registrador de estado — um processo VHDL acionado por clock (if rising_edge(clock) then ...) que guarda o estado atual e, em cada borda, copia o próximo estado. É o único bloco com memória.
  2. Um processo de próximo estado — um processo combinacional VHDL que calcula o próximo estado a partir do estado atual e das entradas. Ele deve atribuir valores padrão seguros antes do case ou cobrir explicitamente todos os ramos, para que todo caminho atribua as saídas e next_state.
  3. Lógica de saída — atribuições concorrentes de sinais ou atribuições em processo combinacional que determinam as saídas a partir do estado (Moore) ou do estado e das entradas (Mealy).

Os dois projetos desta lição seguem essa estrutura: um processo de estado acionado por clock, um processo combinacional de próximo estado com valores padrão e a lógica de saída.

Uma máquina de venda automática lembra quanto dinheiro foi inserido e libera um produto quando o total alcança o preço. Ao modelá-la como FSM, o que melhor representa o estado?

Um circuito acende um LED sempre que está no estado BUSY e a entrada go vale 1. Essa saída é Moore ou Mealy? Explique em uma frase.

2

Uma observação necessária: reset assíncrono nestas FSMs

7 min

Antes de construir qualquer coisa, observe uma mudança deliberada em relação às lições anteriores.

Na Lição 3, o flip-flop e o registrador usavam reset síncrono: o reset era testado dentro do processo acionado por clock, como if KEY(0) = '0' then Q <= '0'; dentro de if rising_edge(CLOCK_50) then. A Lição 4 já usou reset assíncrono ativo em nível baixo em circuitos de clock lento; esta lição mantém esse estilo no estado da FSM para que o reset não espere o clock lento.

As FSMs desta lição usam reset assíncrono ativo em nível baixo. Observe a lista de sensibilidade do registrador 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;

Colocar KEY na lista de sensibilidade do processo e testar if KEY(0) = '0' then antes do ramo da borda de clock faz o processo de estado responder no instante em que KEY(0) vai a nível baixo, quando você pressiona o botão, e não somente em uma borda de slow_clk. Assim, pressionar KEY(0) força a máquina ao estado conhecido imediatamente, sem esperar o clock lento.

Expresse claramente a diferença:

  • Reset síncrono (Lições 2–3): entra em vigor somente em uma borda de clock. É limpo e previsível, mas, se o clock for lento, é preciso esperar a borda.
  • Reset assíncrono (Lições 5–6): entra em vigor imediatamente, no instante em que o sinal de reset é ativado, independentemente do clock.

Por que mudar? Estas FSMs são acionadas por um slow_clk dividido, com bordas separadas por segundos. Com reset síncrono, você poderia pressionar KEY(0) e não ver nada acontecer por mais de um segundo, até a próxima borda lenta. Se a máquina estivesse presa, esse seria justamente o momento em que você mais precisaria de uma saída imediata. O reset assíncrono oferece na placa real esse retorno confiável e instantâneo ao início. KEY é ativo em nível baixo: KEY(0) vai a zero quando o botão é pressionado e KEY(0) = '0' permanece verdadeiro enquanto ele é mantido pressionado.

Você pressiona KEY(0) quando ainda falta cerca de um segundo para a próxima borda de slow_clk. Com o reset assíncrono usado nestas FSMs, quando a máquina passa ao estado de reset? Quando um reset síncrono faria essa passagem?

O registrador de estado é escrito como process(slow_clk, KEY), com if KEY(0) = '0' then ... elsif rising_edge(slow_clk) then .... O que o ramo de reset assíncrono (if KEY(0) = '0' then ...) acrescenta? Como o reset se comportaria se você o removesse, deixando apenas um processo acionado por rising_edge(slow_clk)?

3

Exercício 3-A: o semáforo (uma FSM de Moore)

10 min

Sua primeira FSM é um controlador de semáforo. Ele tem três estados e os percorre em um ciclo fixo, mantendo cada luz por um número definido de pulsos:

GREEN -> YELLOW -> RED -> GREEN -> ...

As conexões são LEDR(0) = verde, LEDR(1) = amarelo, LEDR(2) = vermelho e KEY(0) = reset ativo em nível baixo, que devolve a máquina a GREEN. A máquina é acionada por um slow_clk dividido: cada borda de subida é um pulso da máquina de estados. Com este divisor, considere cerca de 0,67 s por pulso visível; a primeira borda de subida após o reset pode chegar antes.

Esta é uma máquina de Moore. A lógica de saída ao final é

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

Cada LED é função somente do estado; nenhuma entrada aparece. Conhecer o estado determina exatamente qual luz está acesa. Essa é a propriedade que define uma máquina de Moore.

Dois registradores separados realizam dois trabalhos diferentes. Leia o registrador de estado com atenção, pois o projeto contém duas memórias fáceis de confundir:

  • state, um sinal do tipo state_t, guarda qual luz está acesa: GREEN, YELLOW ou RED. Esse é o estado da FSM.
  • timer, um sinal unsigned(2 downto 0), é um contador de permanência separado, que conta regressivamente quantos pulsos restam na luz atual. Enquanto timer é maior que zero, ele apenas diminui (timer <= timer - 1) e o estado não muda. Somente quando timer chega a 0 a máquina avança para next_state e recarrega timer para a nova luz.

Portanto, o registrador de estado guarda qual luz está acesa e o temporizador conta por quanto tempo ela permanece acesa. São registradores diferentes, com finalidades diferentes; o temporizador mantém cada luz ativa em vez de deixá-la passar em um único pulso.

Tempos reais de permanência segundo o código. Ao entrar em cada estado, a máquina recarrega timer; contar do valor carregado até 0, inclusive, fornece o número de pulsos:

  • GREEN carrega timer = 3 e conta 3, 2, 1, 0 -> 4 pulsos (cerca de 2,7 s).
  • YELLOW carrega timer = 1 e conta 1, 0 -> 2 pulsos (cerca de 1,3 s).
  • RED carrega timer = 3 -> 4 pulsos (cerca de 2,7 s).

Um ciclo completo tem, portanto, 4 + 2 + 4 = 10 pulsos, aproximadamente 10 × 0,67 s = 6,7 s do início ao fim.

Máquina de estados finitos de Moore para um semáforo, com três círculos rotulados VERDE, AMARELO e VERMELHO ligados em ciclo. GREEN dura 4 pulsos, YELLOW dura 2 e RED dura 4; cada estado acende um único LED, mostrando que a saída depende somente do estado. Uma seta KEY(0)=reinício aponta para VERDE.

O semáforo como máquina de Moore de três estados: GREEN -> YELLOW -> RED -> GREEN. O temporizador mantém cada estado por um número fixo de pulsos: GREEN 4, YELLOW 2 e RED 4; um pulso visível dura cerca de 0,67 s. Cada estado acende exatamente um LED, portanto as saídas dependem somente do estado. KEY(0) reinicia a máquina em GREEN.

Esta é a entidade completa. O divisor produz slow_clk; o processo de estado com reset assíncrono avança a luz quando o temporizador termina; um processo combinacional calcula a próxima luz; e as três atribuições concorrentes aos LEDs formam a lógica de saída de Moore.

-- Código inicial: complete as linhas TODO antes de sintetizar.
-- Lição 5 - Exercício 3-A: controlador de semáforo (FSM de Moore).
-- KEY(0)=reset. LEDR(0)=verde, LEDR(1)=amarelo, LEDR(2)=vermelho.
-- Permanências: GREEN = 4 pulsos, YELLOW = 2 pulsos, RED = 4 pulsos.
-- Um pulso visível é uma borda de subida de slow_clk, cerca de 0,67 s com 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 pulsos
                    when YELLOW => timer <= TODO_YELLOW_RELOAD; -- 2 pulsos
                    when RED    => timer <= TODO_RED_RELOAD; -- 4 pulsos
                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;

As saídas do semáforo são atribuições concorrentes, como LEDR(0) <= '1' when state = GREEN else '0';. Para tornar uma dessas saídas Mealy em vez de Moore, que tipo de termo ausente agora seria necessário acrescentar à expressão?

4

Exercício 3-A na placa: observe e modifique

12 min

Agora construa o semáforo na DE1-SoC real, meça cada fase e depois modifique-o.

  1. Abra o laboratório VHDL da DE1-SoC. O editor mostra o arquivo blink.vhd.

  2. Selecione todo o conteúdo de blink.vhd e substitua-o pelo código inicial do semáforo acima. Complete todas as linhas TODO, mantenha a entidade blink e preserve CLOCK_50 : in std_logic.

  3. Clique em Synthesize. Se o tour guiado cobrir o botão, feche-o ou pule-o. Aguarde a conclusão, cerca de 1–3 minutos. Os erros mais comuns são a ausência de CLOCK_50 na lista de portas ou de um ponto e vírgula; corrija e sintetize novamente. Prossiga somente quando o estado final indicar compilação bem-sucedida com 0 erros.

  4. Clique em Upload to FPGA e aguarde a placa ao vivo e a câmera.

  5. Observe o ciclo. Acompanhe LEDR(0) (verde), LEDR(1) (amarelo) e LEDR(2) (vermelho). Conte por quantos segundos, ou pulsos de cerca de 0,67 s, cada luz permanece acesa e registre. Compare com o código: GREEN deve durar 4 pulsos, YELLOW 2 e RED 4.

  6. Pressione reset. Enquanto a luz estiver em YELLOW ou RED, pressione e solte KEY(0). A máquina deve voltar imediatamente a GREEN. Esse é o reset assíncrono em ação.

Observe o ciclo do semáforo e meça cada fase na câmera. Registre a duração observada, em segundos ou pulsos de cerca de 0,67 s, e compare com os pulsos esperados no código: GREEN 4, YELLOW 2 e RED 4.

Fase (LED aceso) Pulsos esperados (código) Duração observada (s ou pulsos)

Envie sua evidência. Aguarde a fase YELLOW e faça uma captura da câmera quando LEDR(1) (amarelo) estiver aceso e LEDR(0) (verde) e LEDR(2) (vermelho) estiverem apagados. Anexe-a abaixo.

Agora faça uma alteração obrigatória de temporização no projeto.

(Modifique) Altere os tempos de permanência. Edite os valores de recarga de timer para que o ciclo seja GREEN = 6 pulsos, YELLOW = 4 pulsos, RED = 6 pulsos. O temporizador conta do valor carregado até 0, inclusive; portanto, N pulsos exigem carregar N - 1: use "101" (5) para GREEN, "011" (3) para YELLOW e "101" (5) para RED, tanto no case do registrador de estado quanto na linha de reset, se o valor inicial mudar. Sintetize, envie à FPGA, confirme os novos tempos na câmera e calcule a nova duração total do ciclo em pulsos.

Extensão opcional: acrescente um estado vermelho piscante. Adicione um quarto estado, FLASH_RED, depois de RED somente se o professor pedir. Para não acionar LEDR(2) em dois lugares, substitua a atribuição atual do LED vermelho por um único acionador combinado, como LEDR(2) <= '1' when state = RED else timer(0) when state = FLASH_RED else '0';. Depois, acrescente FLASH_RED ao tipo VHDL state_t e ao case de próximo estado, dê a ele uma permanência no case do temporizador, sintetize, envie e confirme que o LED vermelho pisca antes de voltar ao verde.

Para fazer YELLOW durar o dobro, qual valor de registrador você alteraria (state ou timer), em que ponto exato do código e qual registrador deixaria completamente inalterado?

Depois de alterar os valores de recarga, execute o semáforo novamente. Registre o número modificado de pulsos observado em cada estado para comprovar a alteração no código, não apenas descrevê-la.

Estado Pulsos modificados observados Valor de recarga usado no código

Com os tempos modificados (GREEN = 6, YELLOW = 4 e RED = 6 pulsos), qual é a duração total de um ciclo completo em pulsos? Mostre a soma.

Usando o código e sua observação, justifique em duas ou três frases que esta é uma máquina de Moore. Identifique a lógica de saída e explique por que os LEDs são função somente do estado, e não de uma entrada.

5

Extensão opcional: detector da sequência 1011 (FSM de Mealy)

11 min

Sua segunda FSM observa um fluxo de bits que chegam, um por pulso de clock, em SW(0) e acende um LED quando acaba de encontrar o padrão 1011. Esta é uma máquina de Mealy: ela afirma “detectado” em certo estado somente quando o bit de entrada também é o correto, portanto a saída depende do estado e da entrada em conjunto.

As conexões são SW(0) = bit serial de entrada, KEY(0) = reset ativo em nível baixo, LEDR(0) = detecção e LEDR(5 downto 1) = estado atual em codificação one-hot, um LED por estado, para acompanhar a máquina. A borda de subida do slow_clk dividido, isto é, um pulso, ocorre aproximadamente a cada 1,33 s com este divisor.

Os estados. O detector lembra quanto de 1011 já foi reconhecido:

  • S0 — nada reconhecido ainda; é o estado de reset.
  • S1 — o último bit foi 1; reconheceu 1.
  • S2 — reconheceu 10.
  • S3 — reconheceu 101.
  • S4 — reconheceu o 1011 completo. A partir daqui, a máquina ainda pode iniciar um novo reconhecimento, permitindo detecções sobrepostas: o 1 final de um 1011 pode ser o 1 inicial do seguinte.

Em cada pulso, o bloco de próximo estado observa o estado atual e o bit em SW(0). A saída detect é ativada dentro de S3 somente quando o bit recebido é 1, pois 101 seguido por 1 completa 1011. Essa é a saída de Mealy, determinada pelo estado e pela entrada.

Por que retemos a saída — leia com atenção. O sinal de Mealy bruto detect fica alto por apenas um pulso. Em clock rápido, seria invisível; mesmo neste clock lento, um lampejo de cerca de 1,33 s pode passar despercebido na câmera remota. Por isso, o projeto não liga detect diretamente ao LED. Em vez disso, ele retém a detecção: um registrador separado, detected_latch, recebe 1 quando detect dispara e permanece em 1 até você pressionar reset. LEDR(0) mostra esse latch. Depois de detectar 1011, o LED acende e fica aceso até KEY(0). Assim, um evento breve se torna uma indicação estável e fotografável.

Máquina de estados finitos de Mealy que detecta a sequência 1011, com cinco estados S0 a S4. As setas mostram transições conforme o bit de entrada. Em S3, a entrada 1 completa 1011 e ativa detect; a entrada 0 volta a S2 para preservar o sufixo 10 e permitir sobreposição. De S4, 1 volta a S1 e 0 a S0. O pulso de detecção fica retido em LEDR(0) até o reset.

O detector de 1011 como máquina de Mealy com cinco estados. S0 a S4 indicam quanto de 1011 já foi reconhecido. A saída detect, marcada na transição de S3, depende do estado S3 e da entrada 1 em conjunto, portanto é Mealy. A regra de sobreposição mantém a máquina pronta para outro reconhecimento; por exemplo, S3 com 0 volta a S2, não a S0. O pulso detect de um ciclo fica retido em LEDR(0) até o reset.

Esta é a entidade completa. Observe os dois processos: um processo combinacional calcula next_state e o sinal Mealy detect; um process(slow_clk, KEY) acionado por clock guarda o estado e o latch, com reset assíncrono.

-- Código inicial: complete as linhas TODO antes de sintetizar.
-- Lição 5 - Exercício 3-B: detector da sequência 1011 (FSM de Mealy) com detecção retida.
-- SW(0)=bit serial de entrada. KEY(0)=reset. LEDR(0)=latch de detecção.
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;

Seria possível prever exatamente quando detect dispara observando apenas os LEDs de estado LEDR(5 downto 1), sem saber o valor de SW(0)? Use sua resposta para explicar por que essa saída é Mealy, não Moore.

6

Extensão opcional na placa: insira bits e recupere

12 min

Agora construa o detector e insira bits manualmente. Para inserir um bit: ajuste SW(0) ao valor desejado, espere um pulso completo do clock lento, cerca de 1,33 s, para a máquina amostrá-lo na próxima borda de subida, depois mude SW(0) para o bit seguinte e espere outra vez. Observe LEDR(5 downto 1) para acompanhar o estado.

  1. Em blink.vhd, substitua todo o conteúdo pelo código inicial do detector 1011 acima. Complete todas as transições e condições TODO, mantenha a entidade blink e preserve CLOCK_50 : in std_logic.

  2. Clique em Synthesize, aguarde o sucesso e depois clique em Upload to FPGA.

  3. Comece com reset. Pressione e solte KEY(0). LEDR(0) (detectado) deve estar apagado, e os LEDs de estado LEDR(5 downto 1) devem mostrar S0 (00001).

  4. Insira 1, 0, 1, 1. Coloque SW(0) = 1 e espere cerca de 1,33 s; coloque SW(0) = 0 e espere; depois 1 e espere; finalmente 1 e espere. Após o último 1, LEDR(0) deve ficar retido em ligado. Registre os LEDs de estado depois de cada bit.

  5. Reinicie e insira 1, 0, 1, 0, 1, 1, com um bit errado no meio. A máquina não deve disparar falsamente, deve se recuperar e ainda detectar o 1011 final, retendo LEDR(0) ligado. Isso mostra que a FSM se recupera de um bit errado em vez de ficar presa.

  6. Use reset sempre que quiser iniciar um novo fluxo; somente o reset apaga o LEDR(0) retido.

Insira o fluxo 1,0,1,1, um bit por pulso do clock lento, cerca de 1,33 s cada. Após cada bit, leia o estado em LEDR(5 downto 1), com codificação one-hot 00001=S0, 00010=S1, 00100=S2, 01000=S3 e 10000=S4, e indique se LEDR(0), detectado, ficou retido em ligado. A detecção deve ser retida após o último 1.

Bit inserido (SW(0)) LEDR(5 downto 1) observado (one-hot) LEDR(0) detectado? (aceso/apagado)

Envie sua evidência. Depois de inserir 1, 0, 1, 1, LEDR(0) (detectado) fica retido aceso até o reset, um estado estável que pode ser fotografado. Faça uma captura da câmera mostrando LEDR(0) aceso e anexe-a abaixo.

Extensão opcional se houver tempo: modifique o detector para reconhecer 101 em vez de 1011. Primeiro desenhe o novo diagrama de estados: são necessários estados para “nada reconhecido”, “reconheceu 1” e “reconheceu 10”; a saída de detecção deve disparar quando, no estado “reconheceu 10”, o bit seguinte for 1. Se implementar, mantenha o latch e a exibição one-hot, sintetize, envie e confirme que inserir 1, 0, 1 retém LEDR(0) aceso.

A saída Mealy bruta detect é registrada, armazenada em flip-flop, ou combinacional, calculada diretamente a partir do estado e da entrada? Que problema de temporização uma saída Mealy combinacional pode causar e como isso se relaciona à retenção em LEDR(0)?

Suponha que o sinal bruto detect, com um pulso, fosse ligado diretamente a LEDR(0) em vez de ser retido. No clock lento de cerca de 1,33 s, o que você provavelmente veria na câmera quando 1011 fosse detectado e por que essa evidência seria pouco confiável?

Na etapa 5, você inseriu 1, 0, 1, 0, 1, 1 e a máquina ainda detectou 1011 no final. Explique brevemente como a FSM se recuperou do bit errado em vez de ficar presa ou disparar falsamente.

7

O que você construiu

4 min

Você construiu um controlador de semáforo Moore na DE1-SoC real: suas saídas dependem somente do estado, e ele percorre GREEN -> YELLOW -> RED com um temporizador de permanência. Na extensão opcional, você também explorou um detector Mealy de 1011, cuja saída detect depende do estado e da entrada. Você usou a estrutura padrão de FSM: registrador de estado acionado por clock, bloco combinacional de próximo estado com valor padrão e lógica de saída. Também viu como o reset assíncrono ativo em nível baixo devolve imediatamente uma FSM de clock lento ao estado conhecido e, na extensão, por que uma saída de um pulso é retida para a câmera remota capturá-la.

Qual sequência corresponde ao que você fez em cada exercício desta lição?

Em três ou quatro frases: explique por que o semáforo é uma máquina de Moore, citando a lógica de saída; diferencie os registradores state e timer; descreva a alteração de permanência que você testou; e indique uma etapa em que a polaridade ativa em nível baixo de KEY ou o reset assíncrono foi importante. Se fez o detector opcional, acrescente uma frase explicando por que ele é Mealy ou por que LEDR(0) foi retido.

Transforme esta visualização em uma sessão de aula

Continue para o LabsLand Teach para usar esta lição com seus estudantes e conferir o acesso disponível para sua conta.