Essa aula foi extraída do capítulo 15 do livro “Eletrônica Digital Moderna e VHDL” de Volnei Pedroni.
Máquinas de Estados Finitos
Máquinas de estados finitos (Finite State Machine – FSM) são circuitos sequenciais cuja sequência depende, além da entrada de clock, de outras variáveis, que definem qual sequência deve ser implementada, e quando ela deve ser realizada.
Para ilustrar de forma mais fácil, considere um contador binário módulo-8. A contagem de 000 a 111 pode ser representada como 8 diferentes estados, cada um com sua representação (palavra binária), cujo a transição de um estado a outro é feita de forma regular e periódica, ou seja, a partir de um sinal de clock.
A figura acima ilustra cada um dos estados possíveis do sistema e a transição entre cada um deles. Tal esquema é chamado de diagrama de estados.
No contador acima, começamos no estado ZERO, cuja representação binária é 000. Ao passar um determinado intervalo de tempo, o contador deve mudar para o estado UM, representado pela palavra 001. Desse estado passa-se para o estado DOIS (010), e assim por diante.
Em muitos casos, entretanto, a mudança de um estado para outro pode depender de outras variáveis, e não somente do estado corrente. Além disso, a transição de estados pode não ser sequencial, como no contador acima. Por fim, cada estado pode apresentar uma (ou mais) saídas lógicas, a serem utilizadas em quaisquer outros sistemas. Isso tudo exige uma lógica combinacional adicional. A partir desse conceito, podemos definir dois tipos de FSM. A primeira delas produz uma saída que depende somente do seu estado atual, sem o uso de entradas adicionais (como o contador acima).
Essas FSMs são chamadas de máquinas de Moore. O outro tipo de FSM é aquela que a saída do sistema depende, além do estado atual, de valores lógicos de variáveis externas. Esse tipo de FSM é o mais comum, e são chamadas de máquinas de Mealy.
Para projetar uma FSM com lógica combinacional, precisa-se de basicamente dois módulos: 1-dispositivos de memória (flip-flop), para armazenar o estado atual da máquina, e 2- um circuito combinacional, para implementar a saída da máquina e a transição entre os estados.
O procedimento de projeto de uma máquina de estados é simples, bastando seguir um roteiro básico. Para ilustrar tal procedimento, façamos um exemplo: projete uma FSM que implemente o diagrama de estados da figura abaixo.
Nesse diagrama, identificamos 3 estados distintos, portanto, precisaremos de pelo menos 2 bits para representar cada um deles a partir de uma palavra binária. Além dos 3 estados, temos uma única saída (y) e uma entrada (x), logicamente não considerando o clock como entrada lógica.
Etapa 1: O primeiro passo de todo projeto de máquinas de estado, é representar o funcionamento do sistema a partir de um diagrama de estados. Nele fica claro quais as variáveis envolvidas, as regras de transição de estado e a sequência de estados a ser respeitada. No exemplo acima essa etapa já foi concluída.
Iniciando a análise da FSM a partir do estado A do diagrama, podemos perceber que a saída do sistema é 0. Além disso, a máquina só mudará de estado quando x = 0, caso contrário ela permanece no estado A. Por último, o estado seguinte, caso haja a transição, é o estado B.
Fazendo a mesma análise, agora no estado B, vemos que a saída do sistema nesse estado é 0, a transição para o estado seguinte é com x = 1 (caso contrário permanece no mesmo estado), e o estado seguinte é o C. A mesma análise deve ser feita no estado C.
Etapa 2: Em seguida construimos a tabela verdade do funcionamento da FSM. Nessa tabela verdade, temos que as condições de saída e transição são dependentes do estado atual e da variável
de entrada. Assim, esses valores serão as entradas da tabela verdade. Como foi dito, a saída e o estado seguinte dependem desses valores, portanto serão as saída.
Entradas Saídas
estado atual x estado seguinte y
A 0 B 0 A 1 A 0 B 0 B 0 B 1 C 0 C 0 A 1 C 1 A 0
Podemos, então, traduzir a informação acima para valores totalmente binários, ou seja, representar cada um dos estados como uma palavra binária, que nesse caso serãod e 2 bits
Entradas Saídas q1q0 x d1d0 y 00 0 01 0 00 1 00 0 01 0 01 0 01 1 10 0 10 0 00 1 10 1 00 0
Como temos agora uma tabela verdade, podemos gerar mapas de Karnaugh para cada variável de saída. y d1 d0 . ¯x x ¯ q1q¯0 0 0 ¯ q1q0 0 0 q1q0 x x q1q¯0 1 0 . ¯x x ¯ q1q¯0 0 0 ¯ q1q0 0 1 q1q0 x x q1q¯0 0 0 . ¯x x ¯ q1q¯0 1 0 ¯ q1q0 1 0 q1q0 x x q1q¯0 0 0
Etapa 3: A partir dos mapas de Karnaugh, temos a expressão booleana para cada bit de saída. No exemplo acima temos:
y=q1¯x d1=q1x y= ¯q1¯x
Etapa 4: A última etapa é a construção de um circuito lógico que implemente a lógica obtida. Para representar os estados, usamos flip-flops (ou latches), pois eles armazenam os estados atuais. A lógica de transição é colocada na entrada de cada FF, definindo os valores de suas saídas. Para o exemplo anterior, a FSM fica:
O estado atual da máquina é representada pela saída dos FFs, enquanto a palavra do próximo estado está na entrada deles.
Repare que o circuito resultante é dividido em dois blocos, um circuito sequencial formado por flip-flops, responsável por armazenar as palavras binárias que representam os estados, e um circuito combinacional, responsável por calcular a saída e definir a transição dos estados. A figura abaixo faz essa ilustração para as máquinas de Mealy (b) e de Moore (c).
Para reforçar o conteúdo exposto acima, faremos mais um exemplo prático. Considere uma transmissão serial de dados, cujos valores lógicos são transferidos a cada borda de subida de um clock. Projete um circuito que detecte a chegada da palavra 111, ou seja, uma sequência de três 1s consecutivos.
Nesse problema, temos que a entrada do sistema será somente uma única variável, que podemos chamar aqui de x. O sistema deve ter uma saída, por exemplo y, que terá valor 1 somente quando uma sequência 111 for detectada em x. Em resumo teremos um circuito contador, que contará 1 sempre que receber uma entrada 1, quando receber um valor 0, deve-se iniciar a contagem novamente.
Etapa 1: O problema acima pode ser representado em um diagrama de estados. Primeiro, começamos com o estado inicial ZERO, onde o sistema não recebeu nenhum bit transmitido, por isso sua saída y = 0. Nesse caso, se o circuito receber uma entrada 0, ele deve permanecer no mesma estado, caso x = 1, deve-se fazer a primeira contagem, ou seja, mudar para o próximo estado.
O segundo estado é chamado de UM, pois já foi contado um bit x = 1. Nele temos que a saída ainda será 0. Se x = 0, deve-se iniciar uma nova contagem, porntanto o estado seguinte será o ZERO. Caso a entrada x seja 1, tem-se a contagem de dois bits 1 consecutivos, assim pode-se passar para o estado DOIS.
Nesse terceiro estado, a saída será obviamente 0, pois ainda não se tem a contagem completa. Caso a entrada seja 0, novamente deve-se iniciar uma nova contagem, fazendo portanto a transição para o estado ZERO. Caso se tenha x = 1, temos a mudança para o quarto estado, onde temos todos os 3 bits consecutivos detectados com valor 1.
O último estado, chamado de TRÊS, terá como saída y = 1, pois alcançamos a sequência 111 da entrada. Se a entrada x for igual a 1, teremos mais uma sequência 111, e por isso deve-se permanecer em tal estado. Caso tenha-se x = 0, deve-se mudar para o estado ZERO.
Etapa 2: A partir do diagrama acima, podemos construir a tabela verdade para a transição dos estados e da saída.
Entradas Saídas
estado atual x estado seguinte y
ZERO 0 ZERO 0 ZERO 1 UM 0 UM 0 ZERO 0 UM 1 DOIS 0 DOIS 0 ZERO 0 DOIS 1 TRÊS 0 TRÊS 0 ZERO 1 TRÊS 1 TRÊS 1
Como temos 4 estados, podemos representar todos eles com palavras binárias de 2 bits. Assim, podemos transformar a tabela anterior em uma tabela verdade com valores lógicos.
Entradas Saídas q1q0 x d1d0 y 00 0 00 0 00 1 01 0 01 0 00 0 01 1 10 0 10 0 00 0 10 1 11 0 11 0 00 1 11 1 11 1
Com a tabela acima podemos construir os mapas de Karnaugh para variável de saída: y d1 d0 . ¯x x ¯ q1q¯0 0 0 ¯ q1q0 0 0 q1q0 1 1 q1q¯0 0 0 . ¯x x ¯ q1q¯0 0 0 ¯ q1q0 0 1 q1q0 0 1 q1q¯0 0 1 . ¯x x ¯ q1q¯0 0 1 ¯ q1q0 0 0 q1q0 0 1 q1q¯0 0 1
Etapa 3: A partir dos mapas de Karnaugh, temos a expressão booleana para cada bit de saída: y=q1q0 d1=q1x +q0x y= ¯q0x+q1x
Para facilitar a construção do circuito, podemos implementar as operações AND e OR das equações acima usando apenas portas NAND. Portanto:
y=q1q0 d1=q1⋅x+q0⋅x =q1⋅x⋅q0⋅x y= ¯q0x+q1x = ¯q0x⋅q1x
Etapa 4: A partir das equações acima, podemos construir o circuito que implementa o sistema desejado: