Capitolo 3 Sistemi sequenziali 3.1 Sincronizzazione dei sistemi sequenziali Consideriamo un flip-flop dinamico di tipo D, a singola fase, sincronizzato sul fronte di discesa del clock (Fig. 3.1). Fig. 3.1 - Flip-flop dinamico di tipo D a singola fase Fig. 3.2 - Temporizzazione del flip-flop Capitolo 3 164 Vediamo quali sono le relazioni temporali da rispettare per avere un corretto funzionamento del flip-flop. Considerando il diagramma temporale di figura 3.2, il segnale D dovrà stabilizzarsi prima del fronte attivo del clock (cioè quello di discesa). L’intervallo di tempo minimo che intercorre fra l’ultima variazione di D e il fronte attivo del clock prende il nome di tempo di setup, ts. Inoltre è necessario che D resti stabile anche per un tempo successivo al fronte del clock. Si definisce allora tempo di hold, th, il minimo intervallo di tempo che deve trascorrere dal fronte attivo del clock prima che si verifichi una variazione di D. Se D varia nell’intervallo ts+th non è più garantito il corretto funzionamento del flip-flop, il quale può entrare in uno stato metastabile (o comunque avere un funzionamento per cui le uscite diventano impredicibili). L’uscita Q, a causa delle non idealità dei dispositivi impiegali, varierà con un certo ritardo rispetto al fronte attivo del clock. Si definisce allora il tempo tq, detto clock-to-q delay, come l’intervallo di tempo minimo, che deve trascorrere dal fronte attivo del clock per avere un’uscita Q stabile. Il ritardo ts è legato al tempo necessario perché la capacità CM si carichi (o si scarichi). Analogamente il tempo tq è legato alla carica o scarica della capacità CS; infatti, l’uscita varia quando la fase φ si abbassa, cioè quando lo slave diventa trasparente. Da questo istante di tempo bisogna dar modo alla capacità Cs di caricarsi o scaricarsi; ci sarà quindi un ritardo (sostanzialmente dovuto all’invertitore) responsabile del tempo tq. Per quanto riguarda il tempo di hold, possiamo pensare che i segnali φ e φ siano generati nel modo mostrato in figura 3.3. Fig. 3.3 - Generazione dei segnali φ e φ Cioè, partendo da un segnale di clock esterno, con un primo invertitore si ricava il segnale φ e mentre un secondo invertitore fornisce il segnale φ.. Quindi cambiamo lo stato del nostro flip-flop non nell’istante di tempo in cui cambia il segnale di clock (ck) accessibile dall’esterno ma un po’ dopo, dato che bisogna dare il tempo al segnale ck di essere invertito e poi attivare le porte di trasmissione. Quindi, il dato che bisogna catturare nel registro deve essere presente anche per un certo intervallo di tempo dopo che il segnale di clock è variato. Notiamo che in questa analisi stiamo facendo una serie di approssimazioni; infatti, ad esempio, il ritardo clock-to-q può essere diverso a seconda che l’uscita Q debba portarsi da O ad i o viceversa (quindi, bisognerebbe considerare tq, 0Æ1 e tq, 1Æ0). Discorso analogo vale per il tempo di setup e quello di hold. Per semplicità di analisi, quindi, ci limitiamo a considerare i tre tempi: ts, th e tq. Una volta definiti questi tre valori vediamo come vengono utilizzati per determinare le condizioni di buon funzionamento di un sistema sequenziale qualsiasi. In particolare facciamo riferimento a dei sistemi sequenziali sincroni, disinteressandoci totalmente di quelli asincroni, per una serie di motivi; Sistemi sequenziali 165 innanzitutto i sistemi sincroni sono quelli più semplici e più affidabili, inoltre sono quelli per i quali è possibile effettuare delle operazioni di testing dopo che il sistema è stato realizzato (i sistemi asincroni, invece, sono praticamente impossibili da testare una volta realizzati). Per questi motivi, quindi, nelle applicazioni vengono esclusivamente utilizzati dei sistemi sincroni, a meno di casi particolari in cui sia necessario realizzare sistemi sequenziali asmcroni. Nei sistemi sincroni, quindi, tutto avviene in corrispondenza dei fronti attivi di un segnale di clock (cioè non sono le variazioni degli ingressi che innescano le transizioni del sistema). In generale, un sistema sequenziale (macchina a stati) può essere rappresentato come in figura 3.4, ovvero un sistema combinatorio connesso con un insieme di elementi di memoria (n flip-flop di tipo D). Tutti i registri sono triggerati da un unico segnale di clock, il quale con i suoi fronti attivi cadenza il funzionamento del sistema sincrono. Lo stato attuale, x, del sistema entra in ingresso al sistema combinatorio, viene calcolato lo stato futuro y, che viene riportato in ingresso al banco di registri. Vi possono poi essere degli ulteriori ingressi e uscite del nostro sistema sequenziale. Per ottenere le condizioni per un corretto funzionamento del nostro sistema disinteressiamoci, per il momento, di questi ingressi ulteriori, ovvero ipotizziamo che anche questi ingressi provengano (così come lo stato attuale) dall’uscita di un banco di registri pilotato dallo stesso segnale di clock. Infatti se questi ingressi variano in maniera scorrelata con il segnale di clock, come vedremo, si potrebbero avere degli errori di sincronizzazione. Fig. 3.4 - Sistema sequenziale sincrono Supponiamo che i registri siano sincronizzati sul fronte di discesa del clock e consideriamo il diagramma temporale di figura 3.5. L’uscita x, stato attuale del nostro sistema combinatorio, in generale sarà formata da n bit (n variabili di stato) e potrà cambiare soltanto dopo il fronte attivo del clock, con un ritardo pari a tq. L’uscita y del sistema combinatorio non potrà che variare dopo che è Capitolo 3 166 variato l’ingresso x. Poiché abbiamo n uscite di questo sistema combinatorio, è probabile che alcune di queste varino più velocemente di altre. Di queste, quindi, alcune si assesteranno subito dopo la variazione dell’ingresso, altre con un ritardo maggiore. Possiamo dunque definire due parametri: un ritardo combinatoriale minimo (tc,min) e un ritardo combinatoriale massimo (tc,max), indicati in Fig. 3.5. Inoltre T è il periodo del clock. Fig. 3.5 - Diagramma temporale del sistema sequenziale sincrono Il ritardo combinatonale massimo dipenderà dal cammino critico presente nel nostro sistema combinatoriale; inoltre il ritardo minimo, ad esempio, può valere 0 perché l’uscita di un registro è collegata direttamente con l’ingresso di un altro flip-flop. Tale sistema prende il nome di registro a scorrimento, caso particolare di macchina a stati in cui il sistema combinatorio che collega l’uscita di un flip-flop con l’ingresso di un altro ha un ritardo combinatoriale minimo (e massimo) sempre pari a zero (a parte il ritardo introdotto dalle interconnessioni). Il sistema funzionerà correttamente se sono rispettati i vincoli relativi al tempo di setup e al tempo di hold. Si riuscirà a catturare il valore corretto dello stato futuro del sistema se l’uscita y diventa stabile sufficientemente prima rispetto al successivo fronte del clock, con un margine che abbiamo chiamato tempo di setup (ts). Quindi la condizione che deve essere rispettata per avere un corretto funzionamento del sistema è la seguente: T > tq + tc,max + ts Questa condizione, da verificate affinché il vincolo sul tempo di setup sia soddisfatto, ci dice che la frequenza massima del clock è limitata dal ritardo massimo del nostro sistema combinatorio. Oltre a Sistemi sequenziali 167 questo, però, entrano in gioco anche due parametri tipici dei registri utilizzati: tq e ts; quindi, un parametro che definisce la velocità dei nostri registri non è soltanto tq, ma la somma tq + ts (non è importante soltanto il ritardo da quando varia il fronte del clock a quando varia l’uscita dei registri, ma è anche importante che ts sia piccolo). Bisogna però rispettare anche il vincolo sul tempo di hold. Osserviamo che in seguito al fronte attivo del clock vi sarà una variazione di x, e quindi una variazione di y; ma y è ancora un ingresso per il registro. Quindi l’inizio della variazione di y, dopo il fronte attivo del clock, deve avvenire sufficientemente dopo rispetto al tempo di hold del flip-flop, altrimenti gli ingressi (y) del flip-flop varierebbero proprio in prossimità del fronte attivo del clock. Quindi deve risultare: tq + tc,min > th Questa seconda condizione (meno scontata della precedente) ci dice che gli ingressi dei nostri flipflop non possono variare proprio in prossimità dei fronte attivo dei clock, ma devono variare dopo un certo intervallo di tempo (pari a th). Notiamo che in questa disequazione non compare né il periodo del clock (T) né il ritardo combinatoriale massimo. Ciò vuoi dire che possiamo sempre pensare di rispettare il primo vincolo (quello su ts) abbassando la frequenza del clock. Nonostante ciò, se non è verificata la condizione sul tempo di hoid, anche se si abbassa la frequenza del clock il circuito continua a non funzionare. Quindi questa seconda condizione non è tanto legata alle prestazioni del nostro circuito ma proprio alla condizione di corretto funzionamento del circuito. Osserviamo, inoltre, che questa seconda condizione è tanto più difficile da rispettare quanto più è piccolo il ritardo combinatoriale minimo; cioè quanto più è veloce il sistema combinatoriale tanto più è difficile rispettare questa disuguaglianza. Da ciò si deduce che in molti casi, per valutare il corretto funzionamento di un circuito, non bisogna considerare come caso peggiore quello in cui il circuito è più lento di quanto ci potevamo aspettare; m alcune circostanze il caso peggiore è l’angolo di processo in cui tutti i circuiti sono un po’ più veloci rispetto alle condizioni nominali di funzionamento. Da quanto detto si deduce che la condizione peggiore possibile è quella in cui tc,min =0 (condizione non ipotetica, ma corrispondente al caso in cui l’uscita di un flip-flop è collegata direttamente ad un flip-flop successivo); in tal caso il nostro circuito funziona correttamente soltanto se: tq > th, condizione valevole per il singolo flip-flop. Quindi il circuito funziona correttamente se i singoli flip-flop sono progettati in modo tale che tq + tc,min > th. In definitiva, il primo vincolo (quello su ts) può essere rispettato abbassando la frequenza di clock, ovvero rallentando il nostro sistema combinatorio; quindi questo vincolo determina le prestazioni del nostro sistema, ovvero la frequenza massima di funzionamento. Il secondo vincolo (quello su th) non dipende né dalla frequenza del clock né tanto meno dal ritardo massimo del sistema combinatorio, viceversa dipende dal ritardo minimo del sistema combinatorio; poiché quest’ultimo può anche essere uguale a zero, per avere un corretto funzionamento del nostro sistema in pratica bisogna garantire che per ogni flip-flop sia tq>th. Capitolo 3 168 In generale questa condizione è, in pratica, sempre verificata dato che th è legato al ritardo fra fronte attivo del clock e l’istante in cui le porte di trasmissione si aprono o si chiudono. Il tempo tq, invece, porta in conto, oltre al ritardo fra l’istante in cui varia il clock e l’istante in cui le porte di trasmissione si aprono o si chiudono, anche il ritardo dovuto al latch che funziona come slave. Ciò fa si che per il singolo flip-flop risulti sempre tq>th (a meno di casi eccezionali). Nonostante ciò, anche se per il singolo flip-flop risulta tq>th, possiamo avere una violazione del vincolo sul tempo di hold. Tale possibilità nasce dal fatto che non siamo sicuri che il segnale di clock arrivi istantaneamente a tutti i flip-flop, ma ci sarà un ritardo introdotto dalla linea di clock. Questo ritardo fa si che non tutti i flip-flop commutino nello stesso istante; anche se questo ritardo può essere molto breve, tuttavia può pregiudicare il funzionamento del nostro sistema. 3.2 Ritardo sul clock (clock-skew) Quindi bisogna estendere le due relazioni precedenti per portare in conto il ritardo sulla linea di clock. Consideriamo il sistema sequenziale di figura 3.6, in cui sulla linea di clock supponiamo sia presente un elemento di ritardo ∆. Fig. 3.6 - Sistema sequenziale con ritardo sulla linea di clock Pertanto al secondo registro arriverà un segnale di clock, ck’, ritardato di ∆ rispetto al segnale ck che giunge al primo. Consideriamo allora il diagramma temporale di figura 3.7 per valutare in quali condizioni sono verificati i vincoli sul tempo di setup e sul tempo di hold. Con un ritardo pari a tq rispetto al fronte attivo del clock varierà l’uscita del primo banco di registri. Alcuni dei bit dell’uscita w del sistema combinatorio cominceranno a variare con un ritardo tc,min dalla transizione di y, per altri sarà necessario un tempo tc,max per assestarsi. Per il secondo banco di registri il segnale di clock non è ck, ma ck’, ritardato di ∆ rispetto a ck. Per quanto riguarda il vincolo sul tempo di setup, il fatto che ci sia questo ritardo ∆ è un fatto positivo, dato che si ha più tempo perché il sistema combinatorio possa completare la sua elaborazione; ciò fa si che questo vincolo sia rispettabile più facilmente. Sistemi sequenziali 169 Fig 3.7 - Diagramma temporale del sistema sequenziale con ritardo sul clock La condizione che deve essere verificata, in questo caso, sarà allora: T + ∆ > tq + tc,max + ts ⇒ T > tq + tc,max + ts - ∆ Quindi, grazie a questo ritardo D è possibile migliorare le prestazioni del nostro sistema, dato che è possibile aumentare la frequenza di clock Osserviamo, però, che ∆ è il ritardo introdotto da una linea d’interconnessione, quindi il suo valore è estremamente ridotto; sicuramente sarà molto più piccolo di tc,max . Inoltre, non si può nemmeno pensare di introdurre deliberatamente un ritardo sulla linea di clock dato che bisogna tener conto del vincolo sul tempo di hold. Infatti, il fatto che ck’ sia ritardato di A rispetto a ck rende più difficile il rispetto del vincolo su th, dato che ora questo vincolo coinvolge il fronte attivo di ck’ e la prima variazione del segnale w. In definitiva la condizione che deve verificarsi è la seguente: tq + tc,min - ∆ > th ⇒ ∆ < tq + tc,min - th Osserviamo, quindi, che quando si ha un ritardo sulla linea di clock è come se il ritardo del flipflop, tq, diventi tq - ∆. Da questo vincolo, pertanto, si deduce che il ritardo sul clock risulta essere alquanto problematico, dato che nel caso peggiore in cui tc,min=0 se ∆ diventa maggiore di tq risulta Capitolo 3 170 impossibile verificare il vincolo sul tempo di hold. Quindi, per garantire un corretto funzionamento del nostro sistema, ovvero una corretta sincronizzazione del nostro sistema, il ritardo sulla linea di clock deve essere sufficientemente piccolo (in base alla condizione precedente). Se tc,min=0, ∆ deve essere minore della differenza fra tq e th, differenza che risulta essere estremamente piccola (sicuramente al di sotto del ns). Questo problema del ritardo sul clock prende il nome di clock-skew, che rappresenta uno dei problemi più complicati da risolvere quando si cerca di migliorare sempre di più le prestazioni dei sistemi digitali. Infatti, grazie soprattutto ai progrèssi tecnologici, si riescono a ridurre sempre di più i tempi di propagazione, ovvero tq e th diventano sempre più piccoli. Se pensiamo allora che attualmente esistono microprocessori che funzionano ad un frequenza di clock dei GHz, per i quali quindi possiamo ipotizzare che tq sia dell’ordine di qualche decina di ps (sicuramente al di sotto del centinaio di ps), è chiaro che il ∆ massimo che può essere tollerato è dell’ordine di grandezza di qualche di ps, all’interno di un circuito che può essere molto complicato (può avere centinaia di milioni di transistors). Quindi non è possibile affatto aumentare ∆ per aumentare la frequenza di funzionamento del nostro sistema, dato che si viola il vincolo sul tempo di hold. Osserviamo però che se riuscissimo a realizzare un ∆ negativo potremmo rispettare molto più facilmente il vincolo sul tempo di hold e avremmo un po’ peggiorato le prestazioni del nostro sistema anche se in maniera irrilevante, dato che ∆ è sempre molto più piccolo di tc,max. Per realizzare un ∆ negativo basta inviare il clock in senso opposto al flusso dei dati; ciò in alcuni casi è possibile, ma non sempre. In particolare, se siamo noi a posizionare manualmente i vari blocchi possiamo avere un controllo sulla direzione del flusso dei dati e del flusso del clock; ma se questi vengono posizionati, ad esempio, in maniera automatica risulta ben difficile realizzare questa situazioni. Inoltre, possono esserci delle condizioni in cui non c’è un’unica direzione in cui fluiscono i dati. Ad esempio, nel sistema mostrato in figura 3.8 riscontriamo che i dati fluiscono in direzioni opposte; pertanto comunque colleghiamo il clock, in una direzione avremo un ∆ negativo e nell’altra un ∆ positivo. Fig. 3.8 - Esempio di sistema con flusso dei dati in direzioni opposte Sistemi sequenziali 171 Nei casi in cui si sa a priori come sono piazzati i sistemi combinatori e i registri, e sappiamo che il flusso dei dati ha sempre una stessa direzione, allora possiamo pensare di distribuire il clock in direzione opposta. Viceversa per garantire che il vincolo sul tempo di hold sia rispettato bisogna ridurre al massimo il valore di ∆. Osserviamo che il fattore che può dar luogo ad un problema di sincronizzazione non è il ritardo fra il punto in cui viene applicato il segnale di clock e i vari registri, ma è importante che il clock arrivi contemporaneamente ai vari registri. Un possibile esempio, molto semplice, di distribuzione del clock è costituito dalla cosiddetta struttura ad H, mostrato in figura 3.9. Fig. 3.9 - Distribuzione del clock: struttura ad H Supponiamo che il nostro sistema sia costituito da un certo numero di blocchi (celle standard, registri, ecc.), cui deve arrivare il segnale di clock, e supponiamo siano disposti in maniera periodica. Si distribuirà il segnale di clock in modo tale che ci sia una distribuzione simmetrica per tutti i blocchi. In pratica si disegnano delle “H” che collegano fra loro i blocchi, evidenziandone il punto centrale. Da questo punto di centro ad ognuno dei vari blocchi il ritardo del clock sarà lo stesso. Procedendo in maniera analoga per tutto il circuito si ottiene la distribuzione (ad albero) ad H del clock. Osserviamo che l’istante in cui si applica il clock nel punto centrale della struttura non è lo stesso in cui il clock arriva ad uno dei blocchi; ciò però non è importante, ciò che conta è che il clock arrivi all’incirca nello stesso istante a tutti i vari blocchi del nostro sistema. Ovviamente le cose non sono così banali dato che non tutti i blocchi saranno uguali, non hanno tutti lo stesso carico (cioè le strutture non sono cosi regolari); in linea di principio, comunque, una tecnica che si può adoperare è quella di bilanciare i ritardi sulla linea di clock, per fare in modo che questo segnale arrivi possibilmente in maniera simultanea a tutti gli elementi di memoria. Un’altra tecnica per contrastare il ritardo ∆ sul clock è quella di aumentare il tq. Ciò può essere fatto o soltanto per quei registri che sono collegati in qualche modo a dei sistemi combinatori che 172 Capitolo 3 presentano un ritardo molto basso (ma ciò ci costringe a identificare per quali registri bisogna aumentare il tq e per quali no), oppure possiamo pensare di aumentare il tq per tutti i registn. Questa seconda strategia, però, se da un lato ci assicurerà il soddisfacimento del vincolo sul tempo di hold, dall’altro comporterà un peggioramento delle prestazioni. Un modo per aumentare il tq su tutti i registri è quello di utilizzare un clock a due fasi (che fra l’altro permette di evitare anche i problemi legati alle sovrapposizioni fra φ e φ), dove le due fasi devono essere non overlapping (Fig. 3.10). In questo caso consideriamo come clock il segnale di fase φ1; per avere un corretto funzionamento del nostro sistema bisogna garantire un margine ts e un margine th rispetto al fronte di discesa del clock. Per quanto riguarda l’uscita Q essa comincerà a variare dopo che φ2 si è alzato, con un ritardo tq,i, che possiamo considerare intrinseco del nostro flip-flop. Se guardiamo il flip-flop dall’esterno esso è comandato dal clock ck (≅φ1), ignorando che ci sia una fase φ2 anch’essa distribuita, e presenta un tempo di ritardo tq = tq,i + tnov. Fig. 3.10 - Utilizzo di un clock a due fasi per risolvere il problema del clock-skew Quindi è possibile aumentare tq aumentando il tempo di non overlap; in particolare, si sceglie questo tempo in modo che tnov ≅ ∆ in modo tale da compensare il ritardo massimo che è possibile avere sulla linea di clock. Quindi, rispetto ad un registro a singola fase, con un registro a due fasi è possibile agire su due parametri: la frequenza di clock, che possiamo aumentare per cercare di soddisfare il vincolo su ts, ed il tempo di non overlap, che possiamo pensare di aumentare per cercare di soddisfare anche il vincolo su th. Tutto ciò, ovviamente, va a discapito delle prestazioni in quanto si rallentano tutti i flip-flop (dato che aumenta tq.). Per questo motivo tale tecnica è ormai poco utilizzata. Sistemi sequenziali 173 Vediamo allora cosa succede se realizziamo il sistema combinatorio in modo tale che il tc,min sia comparabile con il tc,max. Osserviamo, innanzitutto, che ciò è molto difficile da realizzare in quanto bisogna progettare il nostro sistema combinatorio in modo tale che tutti i ritardi soddisfino due vincoli (devono essere minori di una certa grandezza e maggiori di un’altra). Si sceglie allora il ∆ in modo da verificare al limite il vincolo sul tempo di hold, ovvero scegliamo: ∆lim = tq - th + tc,min Andando a sostituire nella relazione che esprime il vincolo sul tempo di setup si ottiene: Tmin = tq + ts + tc,max – (tq - th + tc,min) = ts + th + ( tc,max - tc,min) Questa relazione ci dice che se riusciamo a rendere il tc,min comparabile con il tc,max e siamo in grado di controllare il ∆, possiamo operare ad una frequenza di clock legata non a tc,max, ma alla differenza (tc,max - tc,min), quindi molto più elevata. Questa tecnica di progetto, molto rischiosa perché si basa sull’ipotesi di riuscire a controllare perfettamente il ritardo sulla linea di clock (rendendolo pari a ∆lim) e di riuscire a progettare un sistema combinatorio con un tc,min prossimo a tc,max prende il nome di wave-pipelining. Questo nome deriva dal funzionamento “ad onda” del nostro sistema, in quanto mentre si propaga il segnale rallentiamo anche il clock, in modo che queste due onde procedano nel nostro circuito in modo tale che il fronte del clock riesce comunque di volta in volta a catturare il dato giusto per ogni flip-flop. Questa tecnica è un settore in sviluppo, non è una tecnica standard di progetto; ad esempio, le strutture CPL che sono caratterizzate dal fatto di essere costituite sempre dalla stessa cella (un multiplexer, indipendentemente dalla funzione che si sta realizzando) ben si prestano, sotto certe particolari condizioni, a realizzare dei sistemi in cui il tempo combinatoriale minimo e massimo siano non molto diversi fra loro. Osserviamo che finora abbiamo considerato dei flip-flop come elementi di memoria. In generale, non è possibile utilizzare dei latch come elementi di memoria; infatti consideriamo la nostra macchina a stati (Fig. 3.11) in cui però come registro utilizziamo un insieme di latch. Fig. 3.11 - Macchina a stati con registro a latch Capitolo 3 174 Considerando il diagramma temporale di figura 3.12, supponiamo che i latch siano trasparenti quando il segnale di clock è alto. Dall’istante in cui il clock diventa alto l’uscita x comincia a variare, con un certo ritardo tq. Fig. 3.12 - Diagramma temporale del sistema sequenziale con registro a latch Alcune delle uscite y . a valle del sistema combinatorio cominceranno a variare dopo il segnale x, con un ritardo tc,min, altre con un ritardo maggiore (tc,max) prima di assestarsi. Si deduce, allora, che per avere un corretto funzionamento del nostro sistema deve verificarsi la condizione: tq + tc,min > tON + th Se, infatti, il tempo tq + tc,min fosse minore di tON si ha che alcune uscite comincerebbero a variare quando il latch è ancora trasparente, le quali quindi si presenterebbero in ingresso al sistema combinatorio mentre altre sono ancora in elaborazione. Pertanto, quando il clock si abbassa, per alcune uscite verrebbe memorizzato il valore giusto mentre per altre un valore sbagliato, corrispondente addirittura al clock successivo. Inoltre deve essere rispettato sempre l’altro vincolo sul tempo di setup, ovvero: tq + tc,max + ts < T Quindi abbiamo due vincoli sul clock: uno sul periodo T del clock (che deve essere maggiore di una certa quantità) e l’altro sul periodo tON in cui il clock è alto (che deve essere minore di un’altra quantità). Questo doppio vincolo sul clock è difficile da rispettare; inoltre, se tc,min =0, il tON deve essere dell’ordine di pochi decimi di ns. Per queste difficoltà, in pratica, questa tecnica non può essere utilizzata (a meno che tON non diventi un impulso di durata infinitesimale, il che non è facile da realizzare). Pertanto invece dei latch bisogna fare riferimento sempre a dei flip-flop. Sistemi sequenziali 175 Vediamo adesso come è possibile realizzare un flip-flop che abbia un segnale di abilitazione (enable), che vada ad aggiornare il suo stato se è attivo il segnale di enable, mentre mantenga lo stato precedente se il segnale di enable è zero. Una semplice realizzazione che possiamo pensare di realizzare è quella di figura 3.13, cioè mettiamo il clock in AND col segnale di enable. Fig. 3.13 - Realizzazione del clock-gating Se en=l i segnali ck e ck’ sono uguali fra loro, mentre se en=0 ck’=0 ed il circuito non carica il nuovo valore di D. In questo tipo di approccio ci sono almeno due problemi. Il primo problema, di tipo elettrico, consiste nel fatto che, se il registro è un registro dinamico, sappiamo che questo funziona correttamente se la frequenza di clock è maggiore di un certo valore limite. Con un circuito di questo tipo può verificarsi che il segnale di enable sia pari a zero per un tempo molto lungo; in questo caso ck’ resta pari a zero ed il flip-flop non ha un refresh (le capacità perdono il loro effettivo stato di carica). Il funzionamento del circuito, pertanto, è pregiudicato dato che lo stato di questo flip-flop dopo un po’ di tempo diventa indefinito. A parte questo problema legato all’utilizzo di un flip-flop dinamico, osserviamo che l’altro problema è dovuto al fatto che sulla linea di clock è stato introdotto deliberatamente un ritardo ∆, quello della porta AND. Infatti, se l’ingresso D proviene da un altro registro, il cui clock è ck, c’è la quasi certezza che il circuito non funzioni, dato che per il primo registro il ritardo combinatoriale minimo è praticamente zero, mentre per il secondo c’è un ritardo sul clock dovuto alla porta AND. Quindi, questa tecnica, che prende il nome di clock-gating, non può essere applicata dato che induce problemi di sincronizzazione. In generale, quando si ha un circuito in cui non arriva sempre lo stesso identico segnale a tutti i morsetti di clock, bisogna fare molta attenzione perché potrebbe non funzionare o, comunque, funziona solo se sono verificati certi vincoli. Il corretto funzionamento di un sistema sincrono prevede che lo stesso segnale di clock, possibilmente distribuito in maniera tale che i ritardi siano uguali, arrivi a tutti i flip-flop. Capitolo 3 176 L’abilitazione può allora essere realizzata come mostrato in figura 3.14, premettendo all’ingresso del flip-flop un multiplexer comandato dal segnale di enable (en). Se en=l il dato d’ingresso (Din) prosegue verso il nostro flip-flop, mentre se en=0 si riporta l’uscita Q in ingresso; in questo modo non si introduce alcun ritardo sul clock. Fig. 3.14 - Flip-flop con segnale di enable 3.3 Sistemi a “vera” singola fase di clock (TSPC) Uno dei problemi che si presenta per i flip-flop è quello legato alla sovrapposizione fra i segnali φ e φ ; tale problema è particolarmente evidente per i registri di tipo dinamico. Se infatti consideriamo il flip-flop di figura 3.1, se φ e φ sono entrambi 1 (o entrambi 0) il circuito non funziona correttamente; ad esempio, se sono entrambi 1 i due NMOS delle porte di trasmissione sono in conduzione ed il circuito è trasparente (ovvero ogni variazione sull’ingresso D la si ritrova sull’uscita Q, a parte un certo ritardo). Una prima struttura, molto semplice, che permette di risolvere almeno in parte questo problema si basa sulla realizzazione di un flip-flop dinamico utilizzando dei clocked-inverter (Fig. 3.15). A livello transistor questo circuito si presenta come mostrato in figura 3.16; notiamo che l’occupazione di area è pressappoco quella di due invertitori. Fig. 3.15 - Flip-flop dinamico a clocked-inverter Oltre al vantaggio in termini di occupazione di area, questa struttura risulta essere insensibile all’overlap fra ck e ck. Infatti se supponiamo di trovarci nella condizione in cui, in un certo intervallo di tempo, sia ck che ck sono entrambi pari ad 1, saranno in conduzione sia l’NMOS pilotato da ck sia quello pilotato da ck, mentre i due PMOS saranno interdetti. Quindi il circuito si configura come mostrato in figura 3.17. Sistemi sequenziali 177 Fig. 3.16 - Schema a livello transistor del flip-flop a clocked-inverter Fig. 3.17 - Circuito relativo al flip-flop nel caso in cui ck=ck =1 Notiamo, quindi, che dei due invertitori sono attive soltanto le reti di pull-down. Vediamo allora se, in queste condizioni, una variazione dell’ingresso D può trasferirsi all’uscita Q (cioè se il nostro flip-flop è trasparente). Supponiamo che D (in questo intervallo di tempo) passi da 1 a 0,quindi il potenziale sul nodo M, inizialmente è a 0V. Quando D passa da 1 a 0, l’NMOS s’interdice ed il PMOS entra in conduzione; il nodo M, quindi, rimane a 0V, e la variazione dell’ingresso non si trasmette in uscita. Consideriamo il caso in cui D passi da 0 ad 1; inizialmente, quindi, possiamo supporre che la capacità al nodo M è carica a Vdd. In seguito alla transizione di D tale capacità può scaricarsi attraverso l’NMOS in conduzione. Quindi la variazione di D ha alterato la carica sulla Capitolo 3 178 capacità del nodo M; ciò però non modifica il valore dell’uscita. Infatti, essendo tale capacità inizialmente carica, manteneva in conduzione l’NMOS a valle, e quindi la capacità del nodo d’uscita era inizialmente scarica. Il fatto che si scarichi la capacità del nodo M (in seguito alla transizione 0Æ1 su D) fa entrare in conduzione il PMOS a valle, ma ciò non può alterare il valore dell’uscita (essendo interdetto il PMOS comandato da ck). Quindi grazie al fatto che sono attive le due sole reti di pull-down non è possibile mai trasferire un segnale dall’ingresso D all’uscita Q. Quindi, il nostro flip-flop non è trasparente alle transizioni di D anche quando sia ck che ck sono entrambi pari ad 1. Un discorso analogo può essere fatto anche quando sia ck che ck sono entrambi pari ad 0; in questo caso condurranno le due reti di pull-up del circuito; e con un ragionamento analogo è possibile verificare che il circuito non è mai trasparente alle variazioni di D. La struttura a clocked-inverter, quindi, da questo punto di vista è da preferire quando si realizza un flip-flop dinamico. Tale struttura, però, non risolve del tutto i nostri problemi. Consideriamo, infatti, i due segnali ck e ck (Fig. 3.18), che in generale saranno ritardati fra loro Fig. 3.18 - Diagramma temporale dei segnali ck e ck Idealmente il nostro flip-flop dovrebbe essere triggerato sul fronte di discesa del clock (dato che lo slave diventa trasparente quando il clock diventa basso). Si presenta allora il problema di identificare l’istante in cui il sistema dovrebbe commutare: è l’istante in cui ck si abbassa oppure l’istante in cui ck si alza? In realtà, se bisogna portare l’uscita a livello logico alto è necessario che il segnale di clock si abbassi, dato che entrare in conduzione il relativo PMOS; quindi la transizione 0Æ1 di Q è comandata dal fronte di discesa di ck. Viceversa la transizione 0Æ1 di Q avverrà in corrispondenza del fronte di salita di ck. Quindi, seppure questo circuito non è trasparente negli intervalli di sovrapposizione, in linea di principio non si sa quando può variare l’uscita, se in corrispondenza del fronte di discesa di ck oppure del fronte di salita di ck. Pertanto se supponiamo di utilizzare come fronti di riferimento quelli di discesa del clock, in linea di principio il tq del nostro flip-flop include anche il tempo di overlap fra ck e ck (dato che l’uscita può non variare finché non si alza ck). Per risolvere del tutto questo tipo di problemi sono stati introdotti recentemente altri tipi di flip-flop Sistemi sequenziali 179 (e quindi latch) dinamici che presentano la caratteristica di non richiedere il segnale ck, ma richiedono soltanto l’utilizzo di un segnale di clock. Tali circuiti, quindi, sono a “vera” singola fase di clock (True Single Phase Clock, TSPC). Si parte dalla struttura del clocked-inverter eliminando il PMOS pilotato da ck (Fig. 3.19). Fig. 3.19 - Passaggio da un clocked-inverter ad un half-latch Questo circuito, a volte, viene chiamato “mezzo latch” (half-latch) perché mettendo in cascata due di questi circuiti si ottiene un latch; infatti si ha il circuito mostrato in figura 3.20. Fig. 3.20 - Latch TSPC (trasparente per ck=l, in hold per ck=0) Verifichiamo allora che il funzionamento di questo circuito è quello di un latch dinamico, ovvero che quando il clock è alto il circuito è trasparente e quando il clock è basso il circuito è in fase di hold. Se ck=1, i due NMOS pilotati dal clock sono in conduzione ed il circuito si configura come la cascata di due invertitori; quindi, ogni variazione di D la si ritrova su Q, ovvero il circuito in questa Capitolo 3 180 fase è trasparente. Se ck=0 sono interdette entrambe le reti di pull-down del circuito; ci si trova, quindi, nella stessa situazione del circuito precedente, ovvero del flip-flop realizzato a clockedinverter. Fig. 3.21 - Circuito del latch TSPC per ck=0 Poiché sono attive soltanto le due reti di pull-up, una variazione dell’ingresso non può dar luogo ad una variazione dell’uscita. In questa fase, quindi, il latch è in fase di hold. Infatti, quando il clock è uguale a 0 il circuito si configura come mostrato in figura 3.21. Se D ha una transizione da 1 a 0, il primo PMOS può entrare in conduzione, caricando la capacità al nodo M, avendola supposta inizialmente scarica. Ciò, però, non può modificare il valore dell’uscita Q; infatti, l’unica cosa che accade è che il secondo PMOS si interdice, il che non può alterare il valore memorizzato sull’uscita Q. Analogamente se D ha una transizione da 0 ad 1 il primo PMOS si interdice, ma ciò non altera nemmeno lo stato di carica della capacità al nodo M. Fig. 3.22 - Latch TSPC (trasparente per ck=0, in hold per ck=l) Sistemi sequenziali 181 Possiamo allora realizzare il duale dei circuito precedente, cioè un latch che è trasparente per ck=0 ed in fase di hold per ck=1, sempre senza utilizzare il segnale ck. Il circuito che si ottiene, allora, è quello mostrato in figura 3.22. Mettendo allora in cascata questi due latch (quelli di figura 3.20 e 3.22) realizziamo un flip-flop TSPC. Oltre ai circuiti appena visti esistono delle versioni ulteriormente semplificate che fanno uso di un numero ridotto di dispositivi. Queste versioni prendono il nome di latch, e quindi anche flip-flop, con split-output (ovvero con uscite suddivise). Un latch con split-output è fatto come mostrato in figura 3.23; è costituito da half-latch in cui sono sfruttati sia il morsetto di dram che quello di source dell’NMOS pilotato da ck, i quali pilotano l’NMOS ed il PMOS dello stadio a valle, il quale non necessita di pilotaggio di clock. Il principio di funzionamento di questo latch è semplicemente un’estremizzazione di quello visto finora, ovvero che se abbiamo due reti di pull-down (o di pull-up attive), il circuito non è mai trasparente. Fig. 3.23 - Latch con split-output In questo caso, infatti, se ck=1 il circuito è ovviamente trasparente, dato che si configura come un buffer. Per ck=0 l’NMOS pilotato dai clock si interdice; si hanno allora due stadi in cascata, in cui la rete di pull-up del primo comanda la rete di pull-up del secondo, e la rete di pull-down del primo comanda la rete di pull-down del secondo. Anche in questo caso, allora, una qualsiasi variazione dell’ingresso non potrà mai dar luogo ad una variazione dell’uscita. Se, ad esempio, consideriamo la capacità C1, al variare dell’ingresso essa può al più scaricarsi; nel momento in cui si scarica l’NMOS a valle si interdice, ma ciò non varia in alcun modo l’uscita; un discorso analogo si può fare per la capacità C2 (notiamo che il circuito, per quanto sia un latch, sfrutta in realtà tre capacità, C1, C2 e C3). Un primo vantaggio di questa struttura rispetto alla precedente, anche se non molto significativo, è Capitolo 3 182 che c’è un transistore in meno. Invece il vantaggio principale è che il carico sul clock è ridotto al massimo, infatti il clock è collegato ad un solo mosfet. Quindi la capacità sul clock è molto bassa e la potenza dissipata per comandare il segnale di clock è molto ridotta; inoltre, se è ridotta la capacità sul clock anche i ritardi introdotti dalle interconnessioni relative ai clock si riducono (quindi anche il problema del clock-skew viene a mitigarsi). In realtà, l’unico piccolo svantaggio di questo circuito rispetto al precedente èlegato al fatto che l’escursione logica del nodo M” è O÷(Vdd-VT), ciò significa che l’NMOS a valle non si porta mai al pieno della conduzione; quindi, da questo punto di vista, il circuito può essere considerato leggermente più lento. Inoltre questo tipo di circuiti sono delicati, in quanto l’uscita può trovarsi in una condizione per cui lo stato è mantenuto dalla capacità C3 (ovvero è un soft-node), ma questa uscita è pilotata da un PMOS che a sua volta ha sulla gate un altro soft-node. Quindi se c’è un piccolo accoppiamento capacitivo fra questi nodi, soprattutto quelli interni (M’ ed M”), ed altre linee del nostro circuito, ciò può alterare la conduzione o l’interdizione dei relativi mosfet, e alterare lo stato di carica della capacità d’uscita. Da questo punto di vista, dunque, il circuito è più sensibile ad accoppiamenti parassiti fra questi soft-node ed altre linee del circuito integrate, ovvero ai cosiddetti problemi di cross-coupling. Possiamo allora realizzare un flip-flop collegando in cascata due latch con split-output, come mostrato in figura 3.24. Inoltre è possibile dimostrare che una versione ottimizzata di questo flipflop è quella che si ottiene da questo circuito eliminando il secondo stadio del primo latch e collegando direttamente i nodi A e B, rispettivamente, al PMOS e all’NMOS del primo stadio del secondo latch. Questi circuiti, quindi, vengono utilizzati nelle applicazioni più avanzate, laddove serve la massima velocità e la massima sicurezza rispetto ai problemi di sovrapposizione delle diverse fasi di clock. Fig. 3.24 Flip-flop con split-output Sistemi sequenziali 3.4 183 Pipelining Supponiamo di avere un sistema fatto nel modo mostrato in figura 3.25; abbiamo un segnale d’ingresso A su n bit, un primo banco di registri piotati dal segnale di clock, sulla cui uscita effettuiamo delle elaborazioni attraverso la cascata di tre stadi combinatori F,G ed H. L’uscita di quest’ultimo stadio viene memorizzata in un secondo banco di registri. Tutti i flip-flop, come in ogni buon sistema sincrono, sono pilotati dallo stesso segnale di clock, anzi si farà in modo che tale segnale di clock arrivi quanto più possibile contemporaneamente a tutti i registri. Fig. 3.25 – Sistema tipico cui applicare il pipelining Valutiamo la frequenza massima, ovvero il periodo minimo del nostro segnale di clock. Esso sarà legato ad aspetti di non idealità dei registri, cioè il tempo tq del primo registro ed il tempo ts del secondo, ed alla somma dei tempi di ritardo dei vari sistemi combinatori, ovvero risulta: Tmin = tq +ts+tpF+tpG+tpH In prima approssimazione, se supponiamo che i ritardi dominanti siano quelli dei blocchi combinatori, si ha: Tmin ≅ tpF+tpG+tpH Inoltre, se supponiamo che questi tre ritardi siano uguali ovvero: tpF=tpG=tpH=tp,comb, il periodo minimo è Tmin ≅ 3 tp,comb. Proviamo allora a modificare il nostro circuito introducendo il concetto di pipelining. Si introduce il pipelining nel nostro sistema “spezzando” il nostro sistema combinatorio ed introducendo dei registri, detti regtstri di pipelining. Ad esempio, possiamo pensare di spezzare il nostro sistema combinatorio tra i blocchi F e G e fra G ed H, come mostrato in figura 3.26. Fig. 3.26 – Introduzione del pipelining nel sistema combinatorio Capitolo 3 184 Verifichiamo adesso che il funzionamento di questo circuito è lo stesso di quello originario; a tale scopo consideriamo il diagramma temporale di figura 3.27. Fig. 3.27 – Diagramma temporale del sistema pipelined Supponiamo, ad esempio, che tutti i registri siano triggerati sul fronte di discesa del clock; quindi, sul segnale ck evidenziamo i fronti attivi. Supponiamo che il primo valore dell’ingresso, A1, venga catturato in corrispondenza del primo fronte del clock; dopodiché cambiamo l’ingresso mettendo un nuovo valore A2, poi A3, A4, e così via. Ovviamente A deve variare con un certo margine rispetto ai tempi di setup e di hold dei registri. L’ingresso xF del blocco combinatorio F, dopo un ritardo dal primo colpo di clock pari al tq dei flip-flop, assumerà il valore Al; dopo il secondo colpo di clock assumerà il valore A2, poi A3, e così via. Il blocco F effettuerà la sue elaborazioni e la sua uscita yF si dovrà assestare prima che si abbia il successivo fronte attivo del clock; avremo dunque, con un certo ritardo dal primo fronte attivo del clock, il va1ore F(A1), poi F(A2), F(A3), e così via. Per quanto riguarda l’ingresso del blocco G, abbiamo che in corrispondenza del secondo fronte del clock possiamo catturare l’uscita elaborata dal blocco F, cioè F(A1); in corrispondenza dei successivi fronti del clock sarà poi catturato F(A2), F(A3), e così via. Notiamo quindi che nel periodo successivo al primo fronte del clock viene catturato Al ed il blocco F comincia ad elaborare questo primo vettore d’ingresso. Nel periodo successivo accadono contemporaneamente due cose: cambiamo l’ingresso del blocco F, che comincia già ad elaborare l’ingresso A2, e contemporaneamente il blocco G elabora il risultato della precedente elaborazione, cioè elabora F(A1). Questo processo prosegue fino a quando non si “riempie” tutta la pipeline; quindi, per avere il primo risultato utile bisogna aspettare 4 colpi di clock (necessari per caricare i quattro registri con i valori utili). Questo ritardo, necessario per avere la prima uscita utile, prende il nome di latenza, Sistemi sequenziali 185 ovvero c’è una latenza iniziale nel nostro sistema pipelined. Mentre nel sistema precedente era necessario un colpo di clock per caricare il primo registro ed un secondo colpo di clock per avere la prima uscita, nel sistema pipelined sono necessarie due fasi di clock aggiuntive, avendo aggiunto due registri intermedi. Quindi, l’introduzione dei registri di pipelining ha aumentato la latenza di due colpi di clock. Il vantaggio significativo della struttura pipelined è che si ha un’uscita ad ogni colpo di clock, e la frequenza di clock può essere aumentata significativamente rispetto al sistema originario; infatti, in questo caso, fra un registro e l’altro c’è un solo blocco combinatorio, non più tre. Quindi, in questo caso il periodo minimo del clock è in generale dato da: Tmin = max (tpF,tpG,tpH) ovvero dal massimo dei ritardi dei vari blocchi combinatori. Quindi è chiaro che l’introduzione del pipelining è tanto più efficace. quanto più possiamo bilanciare i ritardi, ovvero se tpF=tpG=tpH sono uguali fra loro; in tal caso si riesce addirittura a migliorare di un fattore3 la frequenza di clock. Il problema che si presenta, però, è che questo miglioramento della frequenza di clock viene a discapito di una latenza. Ci sono, allora, delle applicazioni in cui questa latenza è accettabile, cioè non è un vero problema, ed altre in cui viceversa ciò non accade. Un esempio di applicazione in cui la latenza non comporta problemi è quello di un processing digitale di segnali; se abbiamo dei segnali che sono stati catturati con un convertitore A/D e dobbiamo effettuare un filtraggio numerico (ovvero bisogna effettuare dei prodotti di convoluzione, quindi somme e prodotti) possiamo utilizzare i registri di pipelining. In questo caso la latenza comporta un ritardo dall’istante in cui si ha il primo campione in ingresso all’istante in cui si ha la prima uscita utile; ciò, però non è un problema nel processo dei segnali. Il fatto di poter aumentare la frequenza di clock invece è fondamentale, in quanto sappiamo che essa deve essere almeno il doppio rispetto alla banda dei segnale; quindi s si riesce ad aumentare la frequenza di clock significa che possiamo elaborare segnali a frequenza maggiore, e quindi aumentare il campo delle nostre applicazioni. Viceversa questa latenza può non essere accettabile in altre applicazioni. Ad esempio, se abbiamo un’unità logico/aritmetica (che stiamo introducendo all’interno di un microprocessore) possiamo scomporla in tanti sotto-blocchi, a cui pensiamo di applicare il pipelining. Se l’ALU eseguisse sempre la stessa operazione (ad esempio, delle somme) allora sarebbe una buona idea introdurre il pipelining, dato che aumentando la frequenza di clock le somme verrebbero effettuate ad una frequenza maggiore; la latenza iniziale non comporterebbe alcun tipo di problema. Il problema invece nasce se, come accade, l’ALU a volte deve eseguire delle somme, a volte delle operazioni logiche, e così via.. In questo caso non e possibile intervallare delle operazioni differenti con i vari blocchi; bisognerà aspettare tutta la latenza per avere il primo risultato utile, poi bisogna mettere in stallo la pipeline, mettere poi il nuovo ingresso ed aspettare di nuovo tutta la latenza. In questo caso, quindi, non si ha alcun particolare vantaggio dall’utilizzo del pipelining; il vantaggio lo si ha quando si deve effettuare sempre la stessa sequenza di operazioni. Anche all’interno dei microprocessori, dato che in realtà il ciclo di operazioni è quasi sempre lo stesso (si prende un codice operativo dalla memoria, si aggiustano gli operandi e si effettua Capitolo 3 186 l’operazione desiderata), è utile avere un concetto di pipelining. Cioè, mentre si esegue una certa operazione, si cominciano già a prelevare gli operandi dell’operazione successiva. Però, anche in questo caso, quasi sempre tale pipelining va bene; in alcuni casi l’operazione che bisogna effettuare può essere un’operazione di salto. Quindi, mentre si elabora una certa operazione non si sa se la prossima operazione sarà quella successiva o se, dovendo effettuare un salto, bisogna prelevare questa operazione in qualche altra locazione di memoria. In questo caso, riconoscendo un’operazione di salto, si può procedere mettendo in stallo la pipeline; quindi, si aspetta prima di compiere o meno il salto, prima di accedere in memoria. Oppure si può andare avanti nella pipeline, ipotizzando che il salto non venga effettuato; poi, se alla fine doveva essere effettuato il salto, si scarteranno alcuni risultati e si riprenderanno certe operazioni. 3.5 Esempi di applicazione del pipelining Consideriamo un addizionatore a propagazione del riporto (Fig. 3.28) su tre bit. Sappiamo che c’è un cammino critico, che va dal primo all’ultimo full-adder, a causa del quale l’addizionatore è abbastanza lento. Tuttavia, tale struttura risulta essere costituita da un certo numero di moduli in cascata, per cui ben si presta ad essere migliorata introducendo la tecnica del pipelining. Fig. 3.28 - Addizionatore a propagazione del riporto Per semplicità, nello schema dell’addizionatore pipelined, rappresenteremo i registri di memoria con una linea ed un pallino sopra (—•—); l’ingresso, ovviamente, sarà sulla sinistra, l’uscita sulla destra ed il clock è lo stesso per tutti i registri. Otterremo pertanto il circuito di ‘figura 3.29 Partendo dal primo full-adder, gli ingressi A0, B0 e C0 saranno memorizzati su dei flip-flop, le cui uscite vengono applicate al primo full-adder. Dopo un tempo pari al ritardo del full-adder possiamo catturare le uscite; quindi, sia su S0 che sul riporto uscente inseriamo un flip-flop. Per quanto riguarda il secondo full-adder, sugli ingressi A1 e B1 ci saranno dei flip-flop allo stesso livello di quelli su A0 e B0. Inoltre, ci sarà un secondo livello di flip-flop per far si che al full-adder si Sistemi sequenziali 187 presentino gli ingressi giusti, ovvero A1, B1 ed il riporto uscente dello stadio precedente (che sarà disponibile dopo due colpi di clock). Introdurremo poi un registro sul riporto uscente di questo fulladder e sull’uscita S1. Osserviamo però che bisogna aggiungere un altro quando sarà disponibile l’uscita S1 (dopo tre colpi di clock), perderemo il valore del primo bit somma. Per quanto riguarda il terzo full-adder è semplice intuire dove posizionare i registri; basta seguire i tagli (linee tratteggiate) riportati in figura ed inserire un registro in corrispondenza dell’intersezione di queste linee con i vari segnali. Notiamo che bisogna aggiungere due ulteriori registri, uno sull’uscita S1 e l’alto sull’uscita S0. Fig. 3.29 - Addizionatore pipelined Quindi per realizzare il pipelining bisogna introdurre delle sezioni che separano completamente gli ingressi dalle uscite, ed introdurre un flip-flop per ognuna di queste sezioni. Notiamo come, in questo modo, alcuni flip-flop saranno in serie sugli ingressi mentre altri saranno in serie sulle uscite. Lo scopo di ciò, ovviamente, è quello di avere i segnali giusti al momento giusto. La prima uscita utile la si otterrà dopo quattro colpi di clock. Il periodo minimo (ovvero la frequenza massima) del segnale di clock sarà dato da: Tmin = ts+tq+max(tp,sum,tp,carry) Quindi un progetto ottimale del full-adder, al fine di utilizzato in una struttura pipelined, è quello per cui tp,sum ≅ tp,carry; infatti, in tal caso, non ha molto senso privilegiare un’uscita rispetto all’altra. Osserviamo inoltre che se effettuiamo un pipelining per ogni full-adder, il termine ts+tq comincia ad essere comparabile con il tempo di ritardo del full-adder. Ciò ci suggerisce, allora, che ad un certo punto non conviene proseguire con la tecnica del pipelining, in quanto entreranno in gioco i ritardi del flip-flop, che saranno quelli che limiteranno la velocità di funzionamento del circuito. Possiamo allora pensare di realizzare il pipelining non ogni full-adder, ma ogni due full-adder; ciò è possibile semplicemente eliminando i registri sulla linea (*) indicata in figura. In questo caso si interpongono, fra un flip-flop e l’altro, due full-adder; si riducono le prestazioni ma si risparmiano anche 6 registri. Capitolo 3 188 Essendo una struttura modulare saremo noi a decidere come realizzare il pipelining, in funzione delle prestazioni che bisogna raggiungere. Osserviamo che si potrebbe pensare che l’ultimo livello di registri sulle uscite dell’addizionatore possa essere eliminato (togliendo, quindi, il flip-flop su S2, ed uno su S1 ed S0); in realtà, però, ciò dipende dal circuito che sarebbe collegato a valle dell’addizionatore. Consideriamo, infatti il sistema mostrato in Figura 3.30, in cui abbiamo l’addizionatore pipelined (che somma A e B), un comparatore, che darà un’uscita alta se i due ingressi W e C sono uguali, ed un flip-flop in cui viene memorizzato il risultato del confronto. Fig. 3.30 - Esempio di sistema in cui viene utilizzato l’addizionatore Il periodo del clock, allora, dipenderà dal ritardo combinatorio di questo flip-flop ed il registro precedente. Se mettiamo un registro su tutte le uscite dell’addizionatore sull’ingresso C, il ritardo che bisogna considerare è quello del comparatore (tcomb); se invece mettiamo un registro solo sugli ingressi, il ritardo che bisogna considerare è la somma del ritardo del comparatore più quello dell’addizionatore. Se, nell’addizionatore pipelined non mettiamo il registro sull’ultima uscita S2 (ovvero non mettiamo l’ultimo livello di registri), bisogna considerare il ritardo del comparatore più il ritardo di un full-adder. In generale, quindi, è buona norma mettere un registro alla fine di un blocco combinatorio. 3.6 Esempi di sistemi sequenziali Consideriamo, ad esempio, un addizionatore seriale; esso è un circuito abbastanza semplice che sfrutta un unico full-adder.. Gli ingressi A e B sono forniti serialmente, inviando prima il bit meno significativo, A0 e B0, poi A1 e B1, e così via (Fig. 3.31). Tutti questi valori vengono memorizzati in un registro a scorrimento; quindi, dopo tre colpi di clock avremo nel primo registro, A0, nel secondo A1 e nel terzo A2. A questo punto il full-adder è pronto per effettuare la somma fra A0 e B0; ci sarà anche un riporto entrante, memorizzato anch’esso in un flip-flop, che deve però essere inizialmente resettato. Quindi, Sistemi sequenziali 189 inizialmente, viene fatta la somma fra A0, B0 e 0; il risultato S0 viene salvato in un registro ed il riporto, C0, viene memorizzato nel flip-flop del riporto per essere sommato ad i successivi bit (A1 e B1). Al colpo di clock successivo, quindi, si sommano A1, B1 e C0. In questo modo si calcola S1 e, per non perdere S0, si mette un secondo registro in uscita; in questo modo S0 passa al registro successivo e S1 viene memorizzato nel primo registro. Fig. 3.31 - Addizionatore seriale a 3 bit Al successivo colpo di clock vengono sommati A2, B2 e C1 la somma S2 viene memorizzata nel primo registro, S1 passa nel secondo ed S0 in un terzo registro. Notiamo, quindi, che con un addizionatore a 3 bit sono necessari 3 colpi di clock per ottenere il risultato utile (nell’ipotesi che i registri a scorrimento in ingresso siano già stati caricati). Inoltre è necessario un solo full-adder, dato che il riporto viene salvato in un flip-flop per utilizzarlo al colpo di clock successivo. Tale struttura è ben diversa dalla struttura pipelined vista nel paragrafo precedente dato che, in questo caso, la struttura è seriale. Bisogna caricare prima gli ingressi A e B, poi vengono effettuare le operazioni di somma, e poi si ottengono le uscite un bit alla volta. Se l’addizionatore è ad n bit, bisogna aspettare almeno n colpi di clock prima di avere il risultato della somma. Inoltre, prima di effettuare una nuova somma, bisogna resettare il flip-flop del riporto, dopodiché ci vorranno altri n colpi di clock per avere la nuova somma. Quindi, sotto certi aspetti, questa struttura è esattamente l’opposto di quella pipelined; non abbiamo un risultato ad ogni colpo di clock, ma ce ne vorranno n. Pertanto, nella struttura seriale, si introducono i registri non per aumentare la velocità del sistema ma per ridurne la complessità (risparmio di area): Anche questa struttura non è utilizzabile in un microprocessore; invece è una scelta che si può utilizzare quando bisogna elaborare dei dati (con un circuito di elaborazione numerica di segnali) che arrivano ad una frequenza abbastanza bassa rispetto alla possibile frequenza di clock. Pertanto, non ha senso fare un addizionatore parallelo molto veloce; per risparmiare area, è preferibile utilizzare un addizionatore seriale. Un altro esempio di sistema sequenziale è un contatore, un sistema, che ad ogni colpo di clock fornisce un’uscita crescente (0, 1, 2 e cosi via), ovviamente codificata in binario. Tale circuito può essere semplicemente realizzato come in figura 3.32. Basta utilizzare un banco di registri in cui l’uscita è lo stato attuale, x, e l’ingresso è lo stato futuro, y, che non sarà altro che x+l; quindi bisogna utilizzare un addizionatore che somma sempre 1, ovvero un addizionatore in cui un addendo è zero, l’altro è x e sfruttiamo il riporto entrante (Cin=1) Capitolo 3 190 per sommare un’unità al nostro contatore. Per il banco di registri è opportuno, inoltre, prevedere anche un ingresso di reset; quindi, inizialmente lo si pone a zero e poi si ha un incremento di 1 ad ogni colpo di clock. Fig. 3.32 Schema di un contatore Entrando più in dettaglio nella struttura dell’addizionatore utilizzato in questo caso, facciamo riferimento alla figura 3.33, in cui è stata usata una struttura a propagazione del riporto. Fig.. 3.33 - Schema del contatore: stuttura dell’addizionatore Ognuna delle bit-slice in cui si può decomporre questa struttura sarà costituita come mostrato in figura 3.34, ovvero composta da un full-adder ed un registro. Fig.. 3.34 - Bit –slice del contatore: stuttura dell’addizionatore Sistemi sequenziali 191 Dato che uno degli ingressi del full-adder è sempre zero, analizziamone più a fondo la struttura. Le equazioni che lo descrivono sono le seguenti: ⎧S = Q ⊕ Cin ⎨ ⎩Cout = Q ⋅ Cin Quindi bisogna semplicemente utilizzare una porta AND ed una XOR per ogni bit-slice. Si ottiene, quindi, la struttura mostrata in figura 3.35. Fig. 3.35 - Schema del contatore:struttura del full-adder di ogni bit-slice La frequenza massima di conteggio del nostro circuito sarà limitata dal ritardo massimo del sistema combinatorio. Nel nostro caso, l’addizionatore, per quanto semplificato, è comunque a propagazione del riporto; quindi, possiamo aspettarci che il ritardo massimo sia quello dovuto alla propagazione del riporto. In ogni caso il circuito è più semplice di un normale addizionatore dato che si somma sempre l. Notiamo, inoltre, che il riporto uscente della seconda bit-slice è dato dalla AND dell’uscita X1, dell’uscita X0, e di Cin. Quindi, anziché ”ottenerlo attraverso due porte AND, possiamo pensare di modificare il circuito eliminando la AND della seconda bit-slice ed inserendo una AND a tre ingressi (la XOR della seconda bit slice prenderà il riporto uscente comunque dalla AND della prima). In questo modo è possibile calcolare in maniera più efficace il riporto uscente per una data bit-slice. 3.7 Metastabilità e sincronizzatori Nel caso dei sistemi sequenziali le condizioni che devono essere rispettate perché un circuito funzioni correttamente sono, sostanzialmente, il rispetto dei vincoli sul tempo di setup e sul tempo di hold. Poiché all’interno del nostro circuito possiamo valutare i ritardi dei sistemi combinatori che lo costituiscono, possiamo sempre progettare il sistema in modo tale che questi vincoli siano perfettamente rispettati. Il problema però nasce quando esistono degli ingressi al nostro sistema che sono asincroni, che Capitolo 3 192 provengono dal modo esterno, le cui variazioni non sono in alcun modo legate a quelle del segnale di clock, che scandisce il funzionamento del nostro sistèma. Supponiamo che un segnale asincrono a venga inviato all’ingresso D di un flip-flop (Fig. 3.36). Fig. 3.36 - Flip-flop con ingresso asincrono Il problema è che su questo segnale asincrono non abbiamo alcun tipo di controllo, le sue commutazioni possono avvenire in un istante di tempo qualsiasi. Quindi può accadere che il segnale a vari proprio in prossimità di un fronte attivo del clock (Fig. 3.37) senza rispettare i vincoli di setup e di hold. Fig. 3.37 - Variazione di a in prossimità del fronte attivo del clock Fig. 3.38 - Flip-flop dinamico Sistemi sequenziali 193 Osserviamo che il comportamento sarà diverso a seconda che il flip-flop sia statico o dinamico. Supponiamo che il flip-flop sia di tipo dinamico (Fig. 3.38); in questo caso sappiamo che lo stato del sistema è memorizzato in una carica accumulata sulle capacità presenti nel nostro circuito. Poiché il segnale a varia proprio in corrispondenza del fronte attivo del clock, si può avere una situazione in cui la tensione immagazzinata su queste capacità (Vc) viene a trovarsi proprio in corrispondenza della regione proibita della caratteristica di trasferimento dell’invertitore, ovvero VIL<Vc<VIH. Questo potenziale, quindi, non viene riconosciuto né come livello logico alto né come livello logico basso. Pertanto l’uscita Q del flip-flop, che inizialmente era bassa, può portarsi ad un livello di tensione intermedio compreso fra 0 e VDD (illegale dal punto di vista logico). Nel caso di un flip-flop dinamico, purtroppo, accade che il livello di tensione VC, una volta immagazzinato sulla capacità, rimane invariato fino a quando non si ha il successivo fronte del clock. In corrispondenza di tale fronte, supponendo che a abbia raggiunto il livello logico alto, l’uscita si porterà al valore corretto. Quindi per un registro dinamico, se sono violati i vincoli sul tempo di setup e di hold, l’uscita Q può portarsi ad un valore logico indefinito, e rimarrà bloccata a tale valore fino al successivo fronte del clock. In questo caso si dice anche che un registro dinamico non è in grado di recuperare una condizione di malfunzionamento (a causa delle capacità che rimangono caricate al valore VC). Nel caso di un flip-flop statico sappiamo che l’elemento di base è un circuito bistabile che, oltre ai due punti di equilibrio stabile, presenta un punto di equilibrio instabile. Fig. 3.39 - Caratteristica di trasferimento di un circuito bistabile Sappiamo che per ottenere i punti di equilibrio di tale sistema basta spezzare il loop e valutare la caratteristica fra vi e v0 (Fig. 3.39); i punti .A e B sono di equilibrio stabile, mentre M è di equilibrio instabile. Pertanto se consideriamo un flip-flop statico può accadere che esso si porti a lavorare in prossimità del punto di equilibrio instabile; l’uscita Q, anche in questo caso, quindi, si può portare ad un valore logico indeterminato (Fig. 3.37), corrispondente al fatto che il potenziale relativo al punto M è esso stesso indeterminato dal punto di vista logico. Poiché, però, c’è un ciclo di reazione positiva, ed M è un punto di equilibrio instabile, una qualsiasi minima perturbazione al nostro sistema farà si che l’uscita Q si porti dal punto metastabile o verso il livello logico basso o verso il livello logico alto (in maniera del tutto casuale, dipendente dal disturbo eventualmente sovrapposto Capitolo 3 194 al segnale d’ingresso). In questo caso avremo un tempo di metastabilità, tm, trascorso il quale il flipflop è in grado di “risolvere” l’uscita, ovvero l’uscita si porterà ad un valore logico determinato (0 oppure 1). In definitiva, vi e un differente comportamento fra un flip-flop dinamico ed uno statico; per il primo l’uscita, portatasi nello stato illegale, vi rimane fino al successivo fronte del clock. Il flip-flop statico, grazie al fatto che M è un punto di equilibrio instabile, può risolvere l’uscita in un tempo tm se c’è una minima perturbazione sovrapposta al segnale (in corrispondenza del punto M). Nel caso dei flip-flop dinamici il tempo di metastabilità è pari al periodo del segnale di clock per i flip-flop statici, invece, questo tempo tm vedremo come può essere calcolato, ma in linea di principio può senz’altro essere più basso del periodo del clock. Pertanto dei due tipi di flip-flop, il più adatto ad essere utilizzato come sincronizzatore è certamente quello statico, dato che è in grado da solo di risolvere in qualche modo l’uscita; i flip-flop dinamici non sono adatti per essere utilizzati come sincronizzatori. Osserviamo che anche se l’uscita del flipflop statico non si porta al livello logico corretto dopo il tempo tm, ciò non comporta alcun problema dato che al successivo fronte del clock, con un buon margine sui tempi di setup e di hold, verrà individuato il valore logico corretto (quello alto, nel nostro esempio). In questo caso, quindi, ci si accorge della variazione del segnale asincrono con un ritardo pari al periodo del clock. Ciò però non è un problema perché sicuramente la frequenza del segnale di clock è sufficientemente maggiore rispetto a quella del segnale asincrono esterno (altrimenti, non avrebbe senso campionario alla frequenza di clock). L’importante, quindi, è che il flip-flop non rimanga troppo a lungo nello stato metastabile. Consideriamo, infatti, il sistema mostrato in figura 3.40, in cui abbiamo il segnale asincrono a in ingresso ad un flip-flop che funziona da sincronizzatore, la cui uscita viene inviata in ingresso ad un sistema sequenziale. Fig. 3.40 - Sistema sequenziale con ingresso proveniente da un sincronizzatore Sistemi sequenziali 195 Il problema che si presenterebbe, se il segnale Qa si trovasse ad un potenziale cui corrisponde un livello logico indefinito, è che due porte logiche potrebbero interpretare questo segnale l’una come livello logico alto e l’altra come livello logico basso. Ciò comporta che lo stato futuro in cui si va a posizionare il sistema sia uno stato che non è stato previsto quando è stata progettata la nostra macchina sequenziale. Ciò, ad esempio, potrebbe comportare che il sistema vada a porsi in uno stato da cui non è più in grado di uscire; da questo errore di sincronizzazione, quindi, potrebbe non essere più possibile recuperare il funzionamento del sistema. Vediamo, quindi, come sia possibile porre rimedio a questo problema. Innanzitutto è ovvio che bisogna considerare, come sincronizzatore, un flip-flop statico; valutiamo allora qual è il massimo tempo di metastabilità, tm,max, che è possibile tollerare all’uscita di questo flip-flop. A tale scopo consideriamo il diagramma temporale di figura 3.41, in cui il segnale asincrono varia proprio in corrispondenza del fronte del clock. Fig. 3.41 - Diagramma temporale per la valutazione del tm,max L’uscita Qa del sincronizzatore passa in uno stato metastabile per un tempo tm, dopo il quale si porta, in maniera casuale, a 0 oppure ad 1; al fronte successivo del clock, in ogni caso, viene individuato il valore corretto di Qa. L’uscita y, stato futuro del nostro sistema sequenziale, potrà essere elaborata dal nostro sistema combinatorio certamente non in corrispondenza del primo fronte del clock; bisogna attendere prima che Qa assuma il valore corretto, e poi bisogna considerare il ritardo del sistema combinatorio. Per avere dunque un corretto funzionamento del nostro sistema deve risultare: T ≥ tm+tc,max+ts Quindi, in pratica, il tempo di metastabilità può essere visto come un incremento del ritardo tq del primo flip-flop. Da questa relazione si ricava che il massimo tempo di metastabilità che è possibile Capitolo 3 196 tollerare è dato da: tm, max = T - tc,max - ts Da questa relazione si ricava che se il tempo di metastabilità è minore di tm,max il nostro sistema funzionerà correttamente, dato che l’uscita dei registri viene campionata con un margine sufficiente rispetto al fronte del clock. Se invece questo periodo di metastabilità è maggiore di tm,max, il sistema sequenziale potrebbe non funzionare correttamente, dato che per le uscite non sarebbero più rispettati i vincoli sul tempo di setup e di hold. Questa relazione, inoltre, Ci conferma che non è possibile utilizzare un flip-flop dinamico come sincronizzatore dato che per esso tm=T. Per un flipflop statico, invece, è possibile calcolare tm e valutare in quali condizioni questo tempo è maggiore o minore di tm,max. Per avere una stima di trn facciamo delle ipotesi semplificative; supponiamo che il segnale di clock sia ideale (quindi con tr=tf=0) e che il segnale d’ingresso a abbia dei tempi di salita e di discesa diversi da zero, come mostrato in figura 3.42. Fig. 3.42 - Andamenti di ck ed a per la stima di tm Inoltre supponiamo che il fiip-flop statico si comporti, in qualche modo, come un circuito Sample&Hold, ovvero come un campionatore la cui uscita vq all’istante 0 sia pari alla tensione d’ingresso va a t=0, ovvero vq(0)=va(0). Quindi il valore iniziale che si ha sull’uscita è perfettamente uguale al valore d’ingresso campionato in corrispondenza del fronte attivo del clock. Bisogna, a questo punto, definire la legge con cui questa uscita varia nel tempo. Se il flip-flop fosse stato dinamico l’uscita, come sappiamo, resterebbe bloccata al valore vq(0). Poiché il flip-flop è statico l’uscita parte da vq(0) e poi tenderà o verso VDD o verso 0, secondo una legge che ipotizziamo essere la seguente: vq(t) = VM +(vq(0)- VM)et/τ Sistemi sequenziali 197 in cui VM è la tensione di metastabilità, cioè quella che corrisponde al punto di equilibrio instabile (del circuito costituito dai due invertitori in retroazione). Quindi il nostro flip-flop campiona inizialmente il valore dell’ingresso in corrispondenza del fronte attivo del clock; se questo valore è leggermente più grande di VM si ha un andamento con un polo a parte reale positiva, quindi con una costante di tempo τ tale per cui l’uscita diverge, tendendo idealmente a +∞. Ovviamente l’uscita è limitata dal fatto che non può superare il valore della VDD e, quindi, la traiettoria che ci aspettiamo è quella mostrata in figura 3.42. Questa legge deriva dal fatto che essendo il punto di equilibrio instabile abbiamo un polo a parte reale positiva; se vq(0) è molto prossimo a VM avremo sempre questo andamento divergente, però il coefficiente del termine esponenziale è piccolo e quindi il tempo necessario per risolvere l’uscita tende ad aumentare. In base a questo modello (molto semplificato, ma che ci consente di stimare tm) si deduce che se viene campionato l’ingresso proprio quando la tensione è pari a VM, l’uscita resterebbe bloccata per un tempo indefinito al valore VM. Se invece vq(0) è più piccolo di VM il coefficiente dell’esponenziale è negativo e l’andamento è decrescente, come mostrato in figura 3.42. Il tempo necessario per risolvere l’uscita è, ovviamente, tanto minore quanto più vq(0) è lontano da VM. Per il calcolo di tm supponiamo vq(0) > VM, la traiettoria dell’uscita sarà del tipo mostrato in figura 3.43. Per valutare tm bisogna individuare il valore di VIH; infatti quando la tensione d’uscita del flipflop supera tale valore l’uscita sarà al livello logico alto. Fig. 3.43 - Traiettoria dell’uscita per vq(0) > VM, Osserviamo però che non si commette un grosso errore se si approssima VIH con VDD, inoltre si fa l’ulteriore ipotesi semplificativa che VM=VDD/2. Da ciò si ricava che: v q (t m ) = V DD ⇒ VM + (v q (0 ) − VM )e tm τ V V ⎞ m ⎛ ⇒ DD + ⎜ v q (0 ) − DD ⎟e τ = VDD 2 2 ⎠ ⎝ t = VDD t ⎤ ⎡ VDD ⎞ τm VDD VDD / 2 ⎛ ⎥ ⇒ t m = τ log ⎢ ⇒ ⎜ v q (0 ) − ⎟e = 2 ⎠ 2 ⎝ ⎢⎣ v q (0) − VDD / 2 ⎥⎦ Notiamo che tali relazioni valgono anche nel caso in cui vq(0) < VM; pertanto l’espressione di tm ottenuta, mettendo il valore assoluto al denominatore, vale in entrambi i casi. Capitolo 3 198 Per valutare in quali condizioni il tm appena calcolato può diventare più grande di tm,max, facciamo riferimento al diagramma temporale di figura 3.44, in cui riportiamo il segnale di clock e la tensione d’ingresso va. Fig. 3.44 - Errore di sincronizzazione: fascia di valori proibiti intorno a VM Se va(0)<VM sicuramente si avrà un problema di metastabilità (addirittura, dalla relazione precedente, tm tende all’infinito); in realtà esiste una fascia di valori proibiti intorno a VM, di ampiezza 2vε, per i quali tm > tm,max, e, quindi, si ha un errore di sincronizzazione. Dal punto di vista del progetto, è chiaro che se possiamo agire su qualche parametro progetteremo il nostro sistema in modo da rendere la vε, quanto più piccola possibile, in modo da ridurre al massimo la probabilità di un errore di sincronizzazione. Dunque la vε è data da: t m,max t ⎧ tτm VDD /2 VDD /2 VDD − m,τmax τ e ⇒e = ⇒ vε = ⎪e = v (0) V /2 v 2 − ⎨ a DD ε ⎪t = t m, max ⎩m Osserviamo che è importante sia che il flip-flop sia veloce, quindi una τ quanto più piccola possibile, sia che la vε sia quanto più piccola possibile. Per far si che la vε sia quanto più piccola possibile bisogna accrescere tm,max, (cioè il tempo massimo che possiamo tollerare prima che il sistema dia luogo ad un errore di sincronizzazione), oppure bisogna cercare di ridurre τ. In tal modo quando più è piccola questa fascia d’incertezza (di ampiezza 2vε) tanto meno probabile è che si abbia un errore di sincronizzazione. Consideriamo che il segnale va abbia delle transizioni con uguali tempi di salita e di discesa, come mostrato in figura 3.45; supponiamo, inoltre, che tale segnale effettui le transizioni con una propria frequenza media di commutazione. Sistemi sequenziali 199 Fig. 3.45 - Possibile andamento di va (con tr=tf) Alla fascia di tensione critica di ampiezza 2vε corrisponderanno degli intervalli di tempo critici, di ampiezza tε se il clock cambia proprio durante questi intervalli di tempo si ha un errore di sincronizzazione. Ipotizzando che il segnale vari linearmente si ha che l’ampiezza di questi intervalli è data da: tε = tr 2v ε VDD In realtà, per ogni periodo (Tsignal) del segnale asincrono a, abbiamo due possibili commutazioni, Pε = 2t ε Tsignal ovvero due degli intervalli di ampiezza tε (uno per il fronte di salita ed uno per quello di discesa). La percentuale di tempo rispetto al periodo del segnale in cui possiamo avere degli errori di sincronizzazione è allora data da: Questa rappresenta una sorta di probabilità d’errore, in quanto ci indica il periodo di tempo (relativamente breve) in cui possiamo trovarci nella fascia 2vε. Però, in effetti, il segnale viene campionato utilizzando il segnale di clock; quindi il numero di errori di sincronizzazione al secondo è dato da: ⎡ numero di errori ⎤ N=⎢ ⎥⎦ = Pε ⋅ f ck sec ⎣ Il fattore 1/N prende il nome di MTBF, ovvero è il tempo medio fra due errori di sincronizzazione (Mean Time Between Failures), ed è un parametro che definisce la bontà del nostro sistema. In definitiva risulta: Capitolo 3 200 t m, max 1 1 MTBF = = = N Pε ⋅ f ck t m, max τ 1 1 e e τ = = = 2t ε tr f ck ⋅ f signal 2t r f ck ⋅ f signal t 0 f ck ⋅ f signal 4v ε f ck ⋅ VDD Tsignal Osserviamo che nell’espressione ottenuta, valida in generale, la costante t0 risulta essere pari a 2tr per le ipotesi in cui ci siamo posti, ovvero clock ideale e segnale a con tr=tf finiti (ma si poteva ipotizzare che il segnale d’ingresso fosse ideale ed il clock avesse tr e tf finiti, oppure che entrambi i segnali avessero dei tempi di salita e di discesa molto brevi però variabili quasi in sincronia in una certa fascia); quindi, in generale, il tempo t0 tiene conto di tutte queste non idealità. Ovviamente a noi interessa avere un MTBF quanto più grande possibile, in modo da aumentare il tempo medio fra due errori di sincronizzazione. L’MTBF si riduce al crescere della frequenza di clock, dato che il segnale d’ingresso viene campionato più volte, ed ogni volta si può avere un errore di sincronizzazione; inoltre si riduce al crescere della frequenza dei segnale d’ingresso (infatti, se questo fosse costante non si avrebbe mai errore di sincronizzazione, dato che ad ogni fronte del clock l’ingresso non può variare). L’MTBF può essere migliorato essenzialmente utilizzando dei flip-flop più veloci (quindi riducendo τ) o progettando il sistema in modo tale che tm,max, sia sufficientemente grande. Osserviamo, però, che comunque progettiamo il nostro sistema c’è sempre una possibilità che si abbia un errore di sincronizzazione (cioè non è possibile fare in modo che l’MTBF sia infinito); in altri termini non esiste un sincronizzatore ideale (c’è sempre una probabilità, sebbene bassissima, che si campioni il segnale d’ingresso proprio quando esso è in prossimità della tensione VM). L’unico parametro su cui è possibile operare è l’MTBF; rendendolo sempre più grande si può avere una ragionevole probabilità che questo fenomeno non si manifesti in una maniera che non è possibile tollerare. Supponiamo, ad esempio, che si abbia una frequenza di clock fck= 100 MHz, una frequenza media di variazione del segnale fsignal=10 MHz, un valore di t0=l ns ed una costante di tempo del flip-flop pari a t=0.25 ns. Il valore dell’MTBF risulta allora pari a: MTBF=10-6e 4tm,max dove tm,max è espresso in ns. Dunque se tm,max =1 ns il nostro sistema è proprio al limite, in quanto sappiamo che per avere un corretto funzionamento del sistema sequenziale deve risultare: T ≥ tc,max +ts+tq; in tal caso risulta MTBF≅50µs, valore del tutto inaccettabile. Del resto se si porta tm,max a soli 5 ns si ha MTBF≅8 min., mentre per tm,max =8 ns si ha: MTBF≅60 anni. Quest’ultimo valore può sembrare molto grande, ma è il tempo medio fra due errori di sincronizzazione per uno degli esemplari del nostro circuito; è chiaro allora che se vengono prodotti 60x365 esemplari, mediamente mio di questi ogni giorno ha un errore di sincronizzazione. Inoltre, questo valore può essere grande o meno in base alla tipica applicazione (in base a ciò che può accadere quando si manifesta un errore di sincronizzazione). Da questo esempio si deduce che, nel progetto del nostro sistema, bisogna avere come specifica l’MTBF; dalla relazione precedente si ricava il tm,max in base al quale progettare il sistema. Osserviamo che deve risultare tm,max= T-ts-tq, in cui il tempo combinatoriale massimo viene Sistemi sequenziali 201 comunque ridotto per aumentare la velocità del sistema, come anche si cercano di rendere più veloci possibile i flip-flop (riducendo il ts, ovvero il τ). Sembrerebbe, quindi, che l’unico parametro su cui effettivamente possiamo agire sia il periodo T, ovvero bisogna rallentare la frequenza di clock. Questo non tanto perché nell’espressione dell’MTBF compare fck a denominatore, ma perché fck compare in tm,max che è all’esponente. Bisognerebbe, quindi, accettare una perdita di prestazioni del nostro sistema. Ciò, ovviamente, non può essere accettato e quindi bisogna cercare di progettare un sincronizzatore più efficace; ciò può essere fatto nel modo mostrato in figura 3.46. Fig. 3.46 - Sistema sequenziale con sincronizzatore più efficace Invece di utilizzare un solo flip-flop come sincronizzatore, che in molti casi ci costringe a ridurre la frequenza del clock per soddisfare la specifica sull’MTBF, viene utilizzato un sincronizzatore più efficiente costituito da due flip-flop in cascata (ovvero un registro a scorrimento composto da due flip-flop). Tale circuito è migliore del precedente, seppure abbia la limitazione di avere una latenza maggiore (dopo due colpi di clock ci si accorge della variazione del segnale a), perché non è altro che una versione molto semplificata del sistema sequenziale precedente, in cui c’era il flip-flop sincronizzatore, il sistema combinatorio, che in questo caso è un filo di collegamento, ed un registro. Quindi possiamo riapplicare la formula relativa a tm,max in cui tc,max è uguale a zero, ovvero risulta: tm,max= T-ts ≅ T In pratica viene dato al primo flip-flop tutto un periodo di clock per risolvere l’uscita; appena l’uscita viene risolta il secondo flip-flop fornisce il valore giusto, senza far vedere al resto del 202 Capitolo 3 sistema che il primo flip-flop per un certo periodo di tempo ha dato un’uscita metastabile. Questa soluzione, nel 95 % dei casi, risolvere i nostri problemi. Qualora, anche con questa soluzione, non fosse ancora possibile ottenere l’MTBF voluto, l’unica soluzione è quella di aumentare la lunghezza di questo registro a scorrimento. In questo caso, infatti, con elevata probabilità si riesce a risolvere la metastabilità del primo flip-flop; qualora questo non accada, l’uscita del secondo flip-flop diventa metastabile. Se però utilizziamo un terzo flip-flop, diamo anche al secondo registro un tempo T per poter risolvere l’uscita. Ovviamente si avrà una certa cura nel progetto di questi flip-flop per cercare di renderli veloci (quindi per ridurre la costante di tempo τ). A livello di componenti standard (quindi di porte TTL, CMOS, ecc.) esistono dei registri, fra quelli che si possono già acquistare, che sono predisposti per questo tipo di applicazioni (cioè come sincronizzatori), ovvero hanno una τ particolarmente ridotta.