Skip to content

Macchine ASM e circuiti sequenziali di base

Il diagramma ASM è simile ai diagrammi di flusso usati in programmazione.

Componenti:

  • I rettangoli rappresentano gli stati e sono etichettati con:

    • un nome;
    • l’eventuale codifica;
    • i valori delle uscite (per le macchine di Moore, dato che non dipendono dagli ingressi);
  • I rombi rappresentano una condizione sugli ingressi e generano 2 rami, in base al risultato.

  • Le transizioni sono rappresentate da frecce che vanno da uno stato ad un altro, eventualmente passando per delle condizioni.

Ad ogni ciclo di clock, è necessario uscire da un rettangolo ed eseguire una transizione (che può tornare anche al punto di partenza).

Riprendendo l’esempio della caldaia:

Esempio di diagramma ASM

Per rappresentare macchine di Mealy, è necessario aggiungere delle uscite condizionate dagli ingressi: un rettangolo ad angoli arrotondati specifica il valore delle uscite durante le transizioni di stato.

L’uscita assume il valore corrispondente mentre il circuito è nello stato di partenza della transizione.

Esempio di diagramma ASM con uscite dipendenti dagli ingressi

Non si deve mai assegnare un valore agli ingressi. Per definizione non si può decidere il valore di un ingresso.

Esempio di circuito non corretto

Non si deve mai usare un’uscita in una condizione di transizione.

Esempio di circuito non corretto

È possibile mettere 2 condizioni in sequenza sulla stessa transizione. È importante però che la transizione finisca sempre su uno stato e non si crei un ciclo composto solamente da condizioni.

Ogni stato definisce il valore dell’uscita. Per convenzione, se non si specifica un valore, si assume sempre che essa ritorni a 00.

L’unità di memoria di base (che contiene un solo bit) è il flip-flop che abbiamo già visto. Un gruppo di flip-flop correlati è detto registro.

Simbolo circuitale del registro

L’ingresso clear pone immediatamente il valore dell’uscita a 00 (è asincrono); il valore rimane a 00 fino al primo fronte attivo del clock successivo al ritiro del segnale.

Talvolta si vuole controllare in quali cicli di clock caricare un nuovo valore. Per fare ciò si deve mascherare il segnale del clock, facendolo restare costante fintanto che si vuole mantenere fissato il valore dell’uscita.

Problema: Tutti i registri devono commutare nello stesso istante per evitare comportamenti errati. Quindi generalmente si dovrebbero usare alberi di distribuzione del segnale per bilanciare la distanza da ogni flip-flop.

Quindi è meglio non toccare il segnale di clock, se non per estreme ottimizzazioni del circuito.

Soluzione: Invece di modificare il segnale del clock, è meglio usare un multiplexer prima del flip-flop. In questo modo, se il segnale di load è attivo, viene restituito il valore già memorizzato, altrimenti si riprende il normale funzionamento.

Circuito del registro con multiplexer per load-enable

In questo tipo di registro, i flip-flop sono collegati in serie e il caricamento dei dati avviene un bit alla volta (per ciclo di clock).

I registri a scorrimento sono utilizzati spesso per la comunicazione seriale tra periferiche (ad esempio protocolli SPI e I2C).

Circuito del registro a scorrimento

Simbolo del registro a scorrimento

Anche qui è pericoloso mascherare il clock, perché il cavo tra clock e flip-flop è generalmente più lungo di quello tra un flip-flop e l’altro.

Quindi si può di nuovo aggiungere un multiplexer all’entrata di ogni cella di memoria.

Circuito del registro a scorrimento con load-enable

Si può facilmente estrarre il dato memorizzato in parallelo prelevando un’uscita da ogni flip-flop, invece che solamente da quello finale.

Per eseguire il caricamento in parallelo basta aggiungere un altro ingresso al multiplexer del load-enable.

Il multiplexer sarà ora controllato da 2 bit: uno per load-enable e l’altro per scegliere tra ingresso seriale e parallelo.

Ogni multiplexer del flip-flop nn seleziona tra l’uscita del flip-flop n1n - 1 (scorrimento avanti), l’uscita del flip-flop n+1n + 1 (scorrimento indietro), il valore corrente (nessun cambiamento) e i dati paralleli (caricamento).

La tabella della verità del multiplexer (dove s0s_0 e s1s_1 sono gli ingressi di controllo) diventa:

s0s_0s1s_1modalità
0000nessun cambiamento (load-enable disabilitato)
0011scorrimento all’indietro
1100caricamento parallelo
1111scorrimento in avanti

Circuito shr bidirezionale

Simbolo shr bidirezionale

Il contatore è un registro che attraversa una sequenza di stati ad ogni impulso del clock.

Se la sequenza di stati è quella dei numeri binari, allora si parla di contatore binario.

È un circuito a 4 uscite che conta in binario da 0 a 15, incrementando di 1 ad ogni ciclo del clock. Quando arriva a 15, l’uscita ritorna a 0 al ciclo successivo.

Questo circuito non ha ingressi (ad eccezione del clock). Un circuito sequenziale può evolvere anche in mancanza di essi, a differenza di uno combinatorio.

L’implementazione può essere quella di un registro parallelo affiancato ad un sommatore tra il valore del registro e 1.

Circuito del contatore

Si può eventualmente aggiungere un segnale di count-enable per fermare l’avanzamento della sequenza.

Situazioni che si verificano spesso nelle macchine a stati.

Si aspetta che un certo segnale S cambi valore, ad esempio da 0 a 1.

Diagramma ASM del busy waiting

La condizione appare soddisfatta solamente al ciclo di clock successivo al cambiamento. Per avere un feedback istantaneo, si può aggiungere un’uscita condizionata collegata al valore dell’ingresso.

Si fa partire un’operazione e si aspetta che essa termini.

Si fa partire un contatore e si aspetta che raggiunga la condizione di termine conteggio (TC). Non ci interessa il suo valore, ma solamente la condizione di TC.

Diagramma ASM del fire and check

Si può usare per operazioni aritmetiche con virgola mobile che spesso richiedono più cicli di clock per raggiungere il risultato.