Comparatori Scopo di un circuito comparatore é il confronto tra due codifiche binarie. Il confronto può essere effettuato per verificare l'uguaglianza oppure una relazione d'ordine del tipo "maggiore", "minore", ecc. Il caso di confronto per stabilire l'uguaglianza può essere risolto in maniera molto semplice ed indipendente dal codice usato, con l'unica ipotesi di avere una rappresentazione unica per ogni valore. I confronti per stabilire relazioni d'ordine invece devono necessariamente tener conto del codice utilizzato. Comparatori di uguaglianza Questi possono essere realizzati a partire dalla funzione elementare XNOR a due ingressi. Dalla tavola di verità di questa funzione vediamo che, interpretando l'uscita 0 come "falso" e l'uscita 1 come "vero", possiamo ottenere immediatamente in uscita il risultato del confronto per rilevare l'uguaglianza tra le due variabili di ingresso. Possiamo estendere il circuito in modo da operare il confronto tra due insiemi di variabili booleane, utilizzando una funzione del tipo XNOR per ogni coppia di variabili da confrontare, calcolando poi l'AND tra i confronti di ogni cifra. Per esempio, in figura é illustrata la realizzazione di un circuito comparatore per rilevare l'uguaglianza tra due ingressi codificati ciascuno su 3 bit (usando ovviamente lo stesso codice per i due ingressi). Comparatori a>b per numeri in codice binario senza segno Cominciamo a considerare il caso di rappresentazioni di numeri senza segno su 2 bit. La seguente Mappa di Karnaugh descrive il funzionamento del circuito che vogliamo realizzare: \ b1 | 0 : 0 : 1 : 1 | \ b0 | 0 : 1 : 0 : 1 | a1 a0 \ | : : : | --------\--+-----:-----:-----:-----+ 0 0 | 0 : 0 : 0 : 0 | ..........|.....:.....:.....:.....| 0 1 | 1 : 0 : 0 : 0 | ..........|.....:.....:.....:.....| 1 0 | 1 : 1 : 0 : 0 | ..........|.....:.....:.....:.....| 1 1 | 1 : 1 : 1 : 0 | -----------+-----:-----:-----:-----+ Un esempio di realizzazione di questa mappa é dato dalla funzione: u = a1·(¬b1) + a0·(¬b0)·(a1+(¬b1)) La complessità della realizzazione tuttavia cresce molto in funzione del numero di bit delle codifiche da confrontare. Nel caso di confronto tra numeri codificati su 3 bit otteniamo la mappa: \ b2 | 0 : 0 : 0 : 0 : 1 : 1 : 1 : 1 | \ b1 | 0 : 0 : 1 : 1 : 0 : 0 : 1 : 1 | \ b0 | 0 : 1 : 0 : 1 : 0 : 1 : 0 : 1 | a2 a1 a0 \ | : : : : : : : | -----------\--+-----:-----:-----:-----:-----:-----:-----:-----+ 0 0 0 | 0 : 0 : 0 : 0 : 0 : 0 : 0 : 0 | .............|.....:.....:.....:.....:.....:.....:.....:.....| 0 0 1 | 1 : 0 : 0 : 0 : 0 : 0 : 0 : 0 | .............|.....:.....:.....:.....:.....:.....:.....:.....| 0 1 0 | 1 : 1 : 0 : 0 : 0 : 0 : 0 : 0 | .............|.....:.....:.....:.....:.....:.....:.....:.....| 0 1 1 | 1 : 1 : 1 : 0 : 0 : 0 : 0 : 0 | .............|.....:.....:.....:.....:.....:.....:.....:.....| 1 0 0 | 1 : 1 : 1 : 1 : 0 : 0 : 0 : 0 | .............|.....:.....:.....:.....:.....:.....:.....:.....| 1 0 1 | 1 : 1 : 1 : 1 : 1 : 0 : 0 : 0 | .............|.....:.....:.....:.....:.....:.....:.....:.....| 1 1 0 | 1 : 1 : 1 : 1 : 1 : 1 : 0 : 0 | .............|.....:.....:.....:.....:.....:.....:.....:.....| 1 1 1 | 1 : 1 : 1 : 1 : 1 : 1 : 1 : 0 | --------------+-----:-----:-----:-----:-----:-----:-----:-----+ Un esempio di realizzazione di questa mappa é dato dalla funzione: u = a2·(¬b2) + a1·(¬b1)·(a2+(¬b2)) +a0·(¬b0)·(a2·(a1+(¬b1))+(¬b2)·(a1+(¬b1))) Si vede bene come l'estensione di questo circuito al caso di più di 3 bit di rappresentazione per i numeri da confrontare diventa improponibile (almeno dal punto di vista della derivazione manuale delle mappe e della funzione che realizza il circuito). L'alternativa consiste quindi nell'individuare un modulo base di confronto tra una coppia di cifre, e nel replicare tale modulo tante volte quante sono le cifre delle rappresentazioni binarie da confrontare. Il confronto deve partire dalla cifra più significativa: se le due rappresentazioni differiscono nella cifra più significativa, allora possiamo subito concludere se la relazione a>b é vera o falsa, senza bisogno di considerare le cifre successive. Solo se le cifre più significative delle due rappresentazioni a confronto sono uguali, allora ddobbiamo passare all'esame delle cifre successive per arrivare a concludere il valore di verità della relazione di confronto. Tale descrizione di massima di un algoritmo iterativo sulle cifre delle rappresentazioni può essere tradotta nella definizione di un modulo circuitale con 4 ingressi e due uscite, che realizza le operazioni di confronto su una singola cifra. Indichiamo con A e B le due variabili di ingresso al modulo corrispondenti alla cifra "corrente" da esaminare per le due rappresentazioni binarie; indichiamo con C e D due variabili di ingresso ausiliarie che ci riportano la codifica del risultato del confronto sulle cifre più significative. In particolare, stabiliamo di indicare con C=1 la condizione "i confronti precedenti non hanno portato nessun risultato definitivo", e con C=0 la condizione "l'esito del confronto é già noto a seguito del confronto delle cifre precedenti". Nel caso C=0, interpretiamo poi D=0 come risposta "no, a non é maggiore di b" ed invece D=1 come risposta "si, a>b". Indichiamo infine con E e R le due uscite che codificano l'esito del confronto. In particolare indicheremo con E=1 la condizione "neanche l'esame di questa cifra ci permette di dare una risposta definitiva", e con E=0 la condizione "la risposta é stata determinata"; in quest'ultimo caso R=0 significa "no", mentre R=1 significa "si, a>b". Il funzionamento del modulo viene definito mediante la seguente mappa: \ C| 0 : 0 : 1 : 1 | \ D| 0 : 1 : 0 : 1 | A B \ |ER:ER:ER:ER| --------\--+-----:-----:-----:-----+ 0 0 |00:01:10:10| ..........|.....:.....:.....:.....| 0 1 |00:01:00:00| ..........|.....:.....:.....:.....| 1 0 |00:01:01:01| ..........|.....:.....:.....:.....| 1 1 |00:01:10:10| -----------+-----:-----:-----:-----+ Tale mappa può essere realizzata in forma minima in logica a 3 livelli mediante le due funzioni: E = (¬A)·(¬B)·C + A·B·C R = A·(¬B)·C + (¬C)·D Per esempio un circuito comparatore a 3 bit può essere realizzato connettendo tre repliche di tale modulo come illustrato in figura: Per esercizio, provare a realizzare un modulo comparatore per la relazione a>=b, ed a connetterne 4 repliche per ottenere un circuito comparatore a 4 bit. Lo stesso tipo di comparatore può essere utilizzato anche per il confronto tra numeri con segno in codice eccesso 2**(N-1). Nel caso di numeri con segno in codice complemento a 2 occorre invece invertire la cifra più significativa delle due rappresentazioni (il bit di segno). Complementatori a 2 La funzione di cambiamento di segno per un numero rappresentato in codice complemento a 2 su N bit può essere realizzata, oltre che (partendo dalla definizione) complementando a 1 e poi sommando la costante 1, anche mediante un algoritmo iterativo che esamina tutte le cifre della rappresentazione partendo da quella meno significativa. L'algoritmo prevede due comportamenti diversi in funzione di una variabile di stato. Nello stato iniziale, si esamina la cifra corrente (partendo dalla meno significativa) e la si lascia invariata; se la cifra corrente é 1 allora si passa al secondo stato, altrimenti si rimane nello stato iniziale. Nel secondo stato si complementa la cifra corrente e si permane nel secondo stato. Tale algoritmo può essere realizzato mediante l'adozione di un modulo circuitale combinatorio a 2 ingressi (denominati I e C) e due uscite (denominate U e S), in grado di calcolare una cifra della rappresentazione del risultato. Il modulo "complementatore a 2" viene specificato mediante la seguente tavola di verità: c2: i 0 0 1 1 c 0 1 0 1 u 0 1 1 0 s 0 1 1 1 Ovviamente la realizzazione del dispositivo può essere ottenuta mediante una funzione XOR per l'uscita U ed una funzione OR per l'uscita S. Un circuito complementatore a 2 per rappresentazioni su N bit viene quindi ottenuto usando N copie del modulo realizzato come sopra specificato. L'ingresso I di ciascun modulo viene connesso ad una cifra della rappresentazione del numero da cambiare di segno. L'uscita U del modulo rappresenta la corrispondente cifra della rappresentazione del risultato. L'ingresso C del modulo corrispondente alla cifra meno significativa viene connesso al valore costante 0. L'ingresso C di tutti gli altri moduli viene connesso all'uscita S del modulo che calcola la cifra immediatamente precedente. Come nel caso del sommatore con ripple carry, questo circuito ha una complessità di realizzazione che cresce linearmente col numero di bit della rappresentazione del numero, ed un tempo di assestamento dei risultati in uscita a seguito di variazioni dei valori in ingresso che cresce anch'esso linearmente col numero di bit della rappresentazione. Moltiplicatori Anche nel caso di circuiti per la moltiplicazione tra numeri espressi in codice binario senza segno su N bit, una realizzazione in logica a tre livelli risulterebbe eccessivamente complessa per grandi valori di N. Vediamo quindi subito una realizzazione modulare. Il punto di partenza per una realizzazione modulare é il cosiddetto algoritmo di moltiplicazione per "somme e scorrimenti", versione binaria del normale algoritmo di moltiplicazione cifra per cifra a cui siamo abituati nel sistema decimale. Cominciamo a considerare il caso semplificato di moltiplicazione di un operando A rappresentato su N cifre per un operando b rappresentato su una sola cifra binaria. L'operando b potrà assumere ovviamente solo i valori 0 e 1. Nel primo caso il risultato del prodotto sarà 0, mentre nel secondo caso il risultato sarà A. Tale risultato può essere ottenuto mediante un circuito combinatorio composto da N funzioni AND a 2 ingressi, ciascuna connessa ad una cifra diversa dell'operando A ed all'unica cifra dell'operando b. Ogni funzione AND produrrà in uscita una cifra del risultato del prodotto. Consideriamo ora il caso di un operando A espresso su N bit, ed un operando B espresso su due bit (ovvero B=b0+2·b1). Il prodotto A·B può quindi essere decomposto in A·b0 + A·b1·2, dove l'operazione di moltiplicazione per 2 viene realizzata mediante lo "scorrimento" della rappresentazione del numero di una cifra verso sinistra, aggiungendo 0 come cifra meno significativa. Da questo possiamo arrivare a produrre uno schema di realizzazione di un circuito moltiplicatore tra due numeri rappresentati su N bit che fa uso solo di circuiti sommatori e di funzioni AND. Un tale moltiplicatore può essere istanziato al caso di N=3 come illustrato in figura a titolo di esempio: La complessità circuitale di un dispositivo di questo tipo cresce col quadrato del numero di bit delle rappresentazioni degli operandi (il numero di somme e di moltiplicazioni per un bit cresce linearmente col numero di bit, e la realizzazione di ciascuno cresce linearmente col numero di bit). Dal punto di vista del tempo di assestamento, questo può crescere secondo N·log(N), utilizzando uno schema di somma ad albero binario (si possono costruire degli alberi binari di sommatori di profondità logaritmica rispetto al numero di termini da sommare, ed ogni sommatore di tipo ripple carry richiede un tempo di assestamento che cresce linearmente col numero di bit).