Architettura dei calcolatori/Struttura di un bus

Struttura di un bus modifica

\section{Classificazione delle linee di trasmissione} Un \emph{bus} è un insieme di linee di trasmissione che possono essere: \begin{itemize} \item \emph{linee dati a livello} pilotate con porte 3-state, in cui è importante il livello logico presente (alto o basso) in un dato momento \item \emph{linee dati di segnale} normalmente attive basse e pilotate con porte open-collector, in cui è importante l'istante della transizione dal livello logico alto a quello basso \item \emph{linee di alimentazione} e \emph{linee di massa} \end{itemize}

\section{Protocolli} Un \emph{protocollo} è una sequenza di azioni elementari che stabiliscono quale operazione eseguire e quando, si definisce \emph{modulo master} il modulo che richiede la comunicazione e \emph{modulo slave} quello a cui la comunicazione è rivolta.

Supponiamo che ogni bus sia provvisto di linee a livello per la trasmissione degli indirizzi ($ADDR$) e dei dati ($DATA$), oltre che di una linea di segnale ($/REQ$) per gestire la richiesta di comunicazione.

\subsection{Protocollo asincrono} Un bus che supporta un protocollo asincrono deve disporre di un'ulteriore linea di segnale ($/ACK$) pilotata dallo slave per segnalare l'accettazione della comunicazione.

\begin{figure} \centering \intincludegraphics{protasin} \caption{Protocollo asincrono} \end{figure}

Nel caso della lettura: \begin{itemize} \item il master trasmette $ADDR$, \item quando $ADDR$ è stabile porta $/REQ$ a $0$; \item lo slave trasmette $DATA$, \item quando $DATA$ è stabile porta $/ACK$ a $0$: a questo punto le linee $ADDR$ possono cambiare valore \item il master segnala l'avvenuta ricezione portando $/REQ$ a $1$ e legge il valore in $DATA$; \item lo slave porta le linee $DATA$ in alta impedenza e chiude la comunicazione riportando $/ACK$ a $1$, ripristinando le condizioni iniziali del bus. \end{itemize}

Nel caso della scrittura: \begin{itemize} \item il master trasmette $ADDR$ e $DATA$, \item quando $ADDR$ e $DATA$ sono stabili porta $/REQ$ a $0$; \item lo slave legge $DATA$ e $ADDR$ \item quindi porta $/ACK$ a $0$: a questo punto le linee $ADDR$ e $DATA$ possono cambiare valore \item il master segnala il termine dell'invio dati portando $/REQ$ a $1$; \item lo slave riporta$/ACK$ a $1$, ripristinando le condizioni iniziali del bus. \end{itemize}

Usando questo protocollo le velocità del modulo master e slave sono completamente indipendenti, ma è necessario che master e slave dispongano di circuiti appositi per gestire l'handshake e che il bus disponda di una linea $/ACK$; inoltre la gestione dell'handshake stesso rallenda la comunicazione.

\subsection{Protocollo sincrono} Usando un protocollo sincrono la durata di ogni comunicazione è nota con esattezza ed è stabilita dal master

\begin{figure} \centering \intincludegraphics{protsinc} \caption{Protocollo sincrono} \end{figure}

Nel caso della lettura: \begin{itemize} \item il master trasmette $ADDR$, \item quando $ADDR$ è stabile porta $/REQ$ a $0$; \item lo slave trasmette $DATA$, \item il master segnala il momento della ricezione portando $/REQ$ a $1$ e legge il valore in $DATA$ che a questo punto deve essere stabile; \end{itemize}

Nel caso della scrittura: \begin{itemize} \item il master trasmette $ADDR$ e $DATA$, \item quando sono stabili porta $/REQ$ a $0$; \item dopo un tempo prefissato il master chiude la comunicazione portando $/REQ$ a $1$: a questo punto lo slave deva aver già terminato la ricezione e e $ADDR$ e $DATA$ possono variare \end{itemize}

Questo tipo di protocollo è molto semplice da implementare ed è veloce, ma la durata delle varie fasi deve essere stabilita a priori e quindi in sostanza la velocità del protocollo dipende dal modulo pi\`u lento

\subsection{Protocollo semisincrono veloce} Usando un protocollo semisincrono la durata di minima di ogni comunicazione è nota con esattezza ed è stabilita dal master, ma il modulo slave lento può ritardare la comunicazione attraverso una linea di segnale aggiuntiva ($/WAIT$)

\begin{figure} \centering \intincludegraphics{protsemv} \caption{Protocollo semisincrono veloce} \end{figure}

Nel caso della lettura: \begin{itemize} \item il master trasmette $ADDR$, \item quando $ADDR$ è stabile porta $/REQ$ a $0$; \item se lo slave è veloce:

 \begin{itemize}
 \item lo slave trasmette $DATA$;
 \item il master segnala il momento della ricezione portando $/REQ$ a $1$ e legge il valore in $DATA$ che a questo punto deve essere stabile ed interrompe la comunicazione.
 \end{itemize}

se lo slave è lento:

 \begin{itemize}
 \item lo slave porta $/WAIT$ a $0$ prima che il master interrompa la comunicazione: a questo punto $ADDR$ può variare,
 \item lo slave dopo il tempo necessario trasmette $DATA$;
 \item quando $DATA$ è stabile porta $/WAIT$ a $1$;
 \item il master segnala il momento della ricezione portando $/REQ$ a $1$ e legge il valore in $DATA$ terminando la comunicazione.
 \end{itemize}

\end{itemize}

Nel caso della scrittura: \begin{itemize} \item il master trasmette $ADDR$ e $DATA$, \item quando sono stabili porta $/REQ$ a $0$; \item se lo slave è veloce:

 \begin{itemize}
 \item il master interrompe la comunicazione portando $/REQ$ a $1$, a questo punto lo slave deve aver letto $DATA$.
 \end{itemize}

se lo slave è lento:

 \begin{itemize}
 \item lo slave porta $/WAIT$ a $0$ prima che il master interrompa la comunicazione: a questo punto $ADDR$ può variare,
 \item lo slave dopo il tempo necessario legge $DATA$ e porta $/WAIT$ a $1$;
 \item il master termina la comunicazione portando $/REQ$ a $1$.
 \end{itemize}

\end{itemize}

Lo slave può essere pi\`u lento del master, ma non troppo lento da non segnalare $/WAIT$ prima che il master chiuda la comunicazione considerandolo veloce; nel caso normale il protocollo è sincrono e allo slave veloce non è richiesta circuiteria aggiuntiva, uno slave lento invece è pi\`u complesso da realizzare.

\subsection{Protocollo semisincrono lento} Usando un protocollo semisincrono lento la durata di massima di ogni comunicazione è nota con esattezza ed è stabilita dal master, ma il modulo slave veloce può abbreviare la comunicazione attraverso una linea di segnale aggiuntiva ($/RDY$)

Nel caso della lettura: \begin{itemize} \item il master trasmette $ADDR$, \item quando $ADDR$ è stabile porta $/REQ$ a $0$; \item se lo slave è lento:

 \begin{itemize}
 \item lo slave trasmette $DATA$;
 \item il master segnala il momento della ricezione portando $/REQ$ a $1$ dopo il tempo normale e legge il valore in $DATA$.
 \end{itemize}

se lo slave è veloce:

 \begin{itemize}
 \item lo slave trasmette $DATA$,
 \item quando $DATA$ è stabile porta $/RDY$ a $0$: a questo punto $ADDR$ può variare,
 \item il master legge $DATA$ e porta $/REQ$ a $1$ prima del tempo normale;
 \item lo slave termina la comunicazione portando $/RDY$ a $1$.
 \end{itemize}

\end{itemize}

Nel caso della scrittura: \begin{itemize} \item il master trasmette $ADDR$ e $DATA$, \item quando sono stabili porta $/REQ$ a $0$; \item se lo slave è lento:

 \begin{itemize}
 \item il master interrompe la comunicazione portando $/REQ$ a $1$ dopo il tempo normale.
 \end{itemize}

se lo slave è veloce:

 \begin{itemize}
 \item lo slave porta $/RDY$ a $0$: a questo punto $ADDR$ e $DATA$ possono variare;
 \item il master riporta $/REQ$ a $1$ prima del tempo normale;
 \item lo slave termina la comunicazione portando $/RDY$ a $1$.
 \end{itemize}

\end{itemize}

Lo slave può essere pi\`u veloce del normale, ma non pu\'o essere pi\`u lento del tempo di attesa normale; il protocollo è sincrono lento e allo slave veloce è richiesta circuiteria aggiuntiva per abbreviare il protocollo, uno slave lento invece è pi\`u semplice da realizzare.

\subsection{Conversione di protocollo e ritardi} Uno slave sincrono può essere utilizzato in un sistema con master asincrono; il segnale $/ACK$ nel protocollo asincrono segue sempre $/REQ$, quindi si utilizza $/REQ$ del master per generare la risposta $/ACK$ al master stesso.

Nel caso di master asincrono con slave sincrono o di master semisincrono lento con slave sincrono veloce si usa un semplice elemento di ritardo, se il master è semisincrono veloce e lo slave sincrono lento si usa una porta NAND con in ingresso $/REQ$ e $/REQ$ ritardato.

I ritardi possono essere realizzati con una porta open collector, una resistenza ed un condensatore, o con linee di ritardo integrate, o con shift register: una serie di $n$ registri in cascata così che occorrono $n$ cicli di clock al segnale per attraversare la catena (si possono avere problemi se la transizione del primo registro si ha quando il segnale non è stabile)

\section{Numero delle linee del bus} Le linee che trasmettono i comandi possono essere progettate con vari approcci.

\subsection{Approccio decodificato} L'\emph{approccio decodificato} prevede che ciascun comando e la sincronizzazione relativa siano sulla stessa linea di segnale e che ci sia una linea per ogni comando e per ogni slave; questo comporta minore logica sugli slave e maggiore rapidità, ma aumenta di molto il numero delle linee e quindi questo approccio può essere usato solo quando il numero di comandi è limitato.

\subsection{Approccio codificato} L'\emph{approccio codificato} prevede che i comandi siano trasmessi su linee a livello e la sincronizzazione su una linea di segnale specifica ($/REQ$); in questo modo si ha un minore numero di linee ma si devono aggiungere barriere logiche sugli slave per decodificare i comandi e questo li rallenta.

Ogni slave deve essere dotato di una rete combinatoria che decodifica le linee di livello dei comandi, il comando deve essere considerato valido quando $/REQ$ è attivo.

È possibile aggiungere un segnale di clock nel caso di moduli sincronizzati.

\subsection{Approccio sincronizzato} L'\emph{approccio sincronizzato} prevede i comandi su linee a livello e la sincronizzazione con il clock di sistema; il numero di linee è ancora minore ma aumenta la complessità degli slave. \subsection{Approccio multiplexato} L'\emph{approccio multiplexato} consiste nel condividere le linee dati con le linee indirizzi (linee $ADDR-DATA$), poich\'e spesso nei protocolli la fase di indirizzamento e quella di trasferimento sono disgiunte questo consente di risparmiare molte linee; si devono aggiungere due segnali $/AS$ (address strobe) e $/DS$ (data strobe) che identificano quando sulle linee sono presenti indirizzi e quando dati. In questo modo lo slave viene rallentato, poiché deve memorizzare prima gli indirizzi in un registro interno e quindi usare le linee dati.

\begin{figure} \centering \intincludegraphics{multiplex} \caption{Periferica sincrona con bus multiplexato} \end{figure}

Il segnale delle linee dati/indirizzi e i comandi sono decodificati da una rete combinatoria e passato ad un registro, che lo memorizza quando arriva il segnale $/AS$ (il registro è più piccolo se posto successivamente alla rete combinatoria di decodifica).

In fase di scrittura il master: \begin{itemize} \item invia l'indirizzo su $ADDR-DATA$ e porta $/AS$ a 0; \item riporta $AS/$ ad 1, in questo momento il registro indirizzi dello slave memorizza il dato; \item invia i dati su $ADDR-DATA$ e porta $/DS$ a 0; \item riporta $DS/$ ad 1, in questo momento il registro dati dello slave memorizza il dato; \end{itemize} In fase di lettura: \begin{itemize} \item il master invia l'indirizzo su $ADDR-DATA$ e porta $/AS$ a 0; \item quindi riporta $/AS$ ad 1 e porta $ADDR-DATA$ in alta impedenza, in questo momento il registro indirizzi dello slave memorizza il dato; \item il master porta $/DS$ a 0; \item lo slave invia i dati su $ADDR-DATA$; \item il master riporta $DS/$ ad 1 e memorizza il dato presente su $ADDR-DATA$. \end{itemize}

\section{Trasferimenti a burst} Si dice \emph{trasferimento a burst} quando si usa un solo indirizzo per riferirsi a pi\`u indirizzi successivi, inviando poi in serie i dati per ciascun indirizzo. La trasmissione dei dati consiste nel ripetere le fasi di trasmissione pi\`u volte.

Considerando linee multiplexate, in fase di scrittura il master: \begin{itemize} \item invia l'indirizzo su $ADDR-DATA$ e porta $/AS$ a 0; \item riporta $/AS$ ad 1, in questo momento il registro indirizzi dello slave memorizza il dato; \item invia i dati su $ADDR-DATA$ e porta $/DS$ a 0; \item riporta $/DS$ ad 1, in questo momento il registro dati dello slave memorizza il dato; \item invia i dati su $ADDR-DATA$ e porta $/DS$ a 0; \item riporta $/DS$ ad 1, in questo momento il registro dati dello slave memorizza il dato; \item ripete le ultime due operazioni per ogni ulteriore \end{itemize} In fase di lettura: \begin{itemize} \item il master invia l'indirizzo su $ADDR-DATA$ e porta $/AS$ a 0; \item quindi riporta $AS/$ ad 1 e porta $ADDR-DATA$ in alta impedenza, in questo momento il registro indirizzi dello slave memorizza il dato; \item il master porta $/DS$ a 0; \item lo slave invia i dati su $ADDR-DATA$; \item il master riporta $/DS$ ad 1 e memorizza il dato presente su $ADDR-DATA$. \item il master porta $/DS$ a 0; \item lo slave invia i dati su $ADDR-DATA$; \item il master riporta $/DS$ ad 1 e memorizza il dato presente su $ADDR-DATA$. \item si ripetono e ultime tre fasi \end{itemize}

\section{Bus multi slave} Quando in un bus ci sono pi\`u slave, il master deve selezionare lo slave con cui comunicare.

Nella \emph{selezione logica} un decoder determina attraverso tutte o parte delle linee di indirizzo il modulo da selezionare; il decoder può essere centralizzato, posto sul modulo master e collegato con una linea per ciascuno slave, oppure distribuito, con una maschera per slave che deve essere configurata.

Nella \emph{selezione geografica} (tipica della tecnologia plug and play) la selezione avviene attraverso linee dedicate per ciascuno slot (oppure con protocolli adeguati). La selezione è indipendente dl tipo di slave e viene usata per configurare dinamicamente la maschera dello slave.

Una maschera configurabile dinamicamente è composta da un registro seguito da una barriera di porte XNOR (uscita 1 se i due ingressi sono uguali) unite da un NAND; il registro memorizza il contenuto delle linee dati del bus quando arriva il segnale di strobe da una linea dedicata, ogni bit del registro è in ingresso ad una porta XNOR insieme ad una linea indirizzi; la porta NAND in uscita ha l'effetto di dare in uscita valore 0 (selezione del modulo attiva) quando il valore contenuto nel registro è uguale alle linee di indirizzo.

\section{Bus multi-master} Nel caso di un bus con pi\`u di un master è necessario che esista un circuito che effettui l'\emph{arbitraggio}, decidere in presenza di richieste multiple di accesso al bus chi deve accedere, garantendo la mutua esclusione; tale circuito si dice \emph{arbitro}: è un'unità che accetta su linee dedicate le richieste di accesso da parte dei master e comunica su altre linee quando è il loro turno. I conflitti in un bus possono essere elettrici o logici, in particolare per le linee di livello.

I vari master devono rispettare il \emph{turn around}: il master che non sta pilotando le linee di livello deve portare le sue uscite in alta impedenza.

Un'unità che funge da arbitro ha una coppia di linee di segnale $/RQn$ (request) e $/GTn$ (grant) per ogni master $n$ del bus: il master segnala attraverso $/RQn$ di voler accedere al bus, l'arbitro comunica l'accettazione della richiesta attraverso $/GTn$ solo ad un master, quando il master ha terminato riporta $/RQn$ alto e porta le sue uscite in alta impedenza, quindi l'arbitro riporta $/GT$ alto.

\subsection{Logica di collegamento tra master, arbitro e bus} La struttura di un sistema a bus multi master, nel caso di arbitro hardware centralizzato e protocollo di comunicazione asincrono, comporta la presenza di logica aggiuntiva; sono necessari per ciascun master: \begin{itemize} \item una rete sequenziale (RS1, collegata a RS2 e al bus) che lasci passare il segnale $/ACK$ che arriva dal bus solo quando il master ha richiesto l'accesso con $/REQ$;

 \begin{equation}
   /ACK_{RS1} = /ACK_{bus} /REQ_{RS2} + /ACK_{RS1}
 \end{equation}

\item una rete combinatoria (RS2, a monte di RS1, tra RS1, il master e l'arbitro) che intercetti il segnale $/REQ$ dal master, lo trasformi in richiesta all'arbitro tramite $/RQ$ e invii $/REQ$ al bus solo quando arriva il segnale $/GT$ dall'arbitro, lasciando quindi passare $/ACK$ dal bus solo in questa ultima fase;

 \begin{equation}
   /RQ = /REQ_{master} /ACK \phantom{30}
   /REQ_{RS2} = /REQ_{master} + /GT \phantom{30}
   /ACK_{master} = /ACK_{RS1} /REQ_{master} + /GT
 \end{equation}

\item una barriera di porte 3-state sulle linee dati del master che siano attive solo quando il master ha richiesto l'accesso e gli è stato garantito (le linee $/REQ$ e $/ACK$ tra le reti RS1 e RS2 devono essere entrambe attive), il segnale $/REQ$ vede essere propagato al bus solo quando la porta 3-state è stabile, quindi può essere necessario inserire un elemento di ritardo. \end{itemize}

\section{Arbitri} Un arbitro può essere hardware (come rete sequenziale) o software, centralizzato o distribuito (è pi\`u scalabile ed ha maggiore tolleranza ai guasti), può avere diverse politiche di scelta del master: a priorità fissa, variabile o variabile rotante, è in genere \emph{non preemptive} (non toglie una richiesta ad un master che non ha terminato l'uso del bus) e deve garantire l'assenza di \emph{starvation} {tutti i master, anche quelli a bassa priorità, devono vedere le loro richieste accettate in un tempo non troppo lungo).

\subsection{Arbitro asincrono elementare} L'erbitro asincrono elementare a due porte è un arbitro hardware in grado di controllare l'accesso di due master al bus, è sintetizzato come una rete sequenziale asincrona con due ingressi ($/RQ0$ e $/RQ1$), due uscite ($/GT0$ e $/GT1$) e quattro stati, più arbitri elementari possono essere interconnessi per ottenere arbitri con differente comportamento.

L'arbitro elementare ha priorità variabile, ovvero quando ci sono due richieste contemporanee questo sceglie casualmente quale soddisfare per prima; questo risultato si ottiene creando una corsa critica delle variabili di uscita, per cui lo stato cambia più volte da 11 a 00 fino a che l'equilibrio si turba e ci sono due soluzioni stabili possibili. \begin{equation}

 /GT_0 = \overline{/GT_1} + /RQ_0 \phantom{30} /GT_1 = \overline{/GT_0} + /RQ_1 

\end{equation} Per evitare che in uscita sia presente lo stato 00 (che è presente per un tempo molto breve) si inseriscono delle porte OR alle uscite collegate anche attraverso un elemento di ritardo all'ingresso corrispondente, il ritardo è scelto maggiore del tempo massimo necessario allo stabilizzarsi delle variabili.

\subsection{Arbitro a priorità rotante} Un arbitro hardware distribuito a priorità variabile può essere costruito interconnettendo un arbitro centralizzato a priorità variabile per ogni master (!!!).

\subsection{Arbitro a priorità fissa}

\subsection{Unità di priorità} Un \emph{unità di priorità} è un tipo di arbitro che ha sempre una sola uscita attiva che indica quale è il master abilitato all'accesso in quel momento.

\section{Sincronizzatori} Un \emph{sincronizzatore} è un elemento che consente il collegamento tra moduli asincroni e sincroni, stabilizzando i segnali provenienti dai moduli asincroni quando essi variano e non sono stabili sui fronti del clock ($\tau$).

Può essere realizzato con due registri (A e B) in cascata sul collegamento, il clock del primo registro viene ritardato di un ritardo $\Delta$.

Se il registro A va in stato metastabile ha un tempo pari a $\tau - \Delta - t_{setup} - t_{propagation}$ per tornare stabile e può assestarsi sul valore corrente o precedente, nel frattempo l'uscita di B rimane stabile; al successivo fronte del clock, il registro B prende il valore che aveva assunto A, questo può essere già corretto, oppure è necessario attendere il successivo ciclo di clock, in quanto adesso il valore sul collegamento è stabile ed A registra sicuramente il valore corretto.

La probabilità che l'uscita di B diventi instabile è $\frac{1}{\tau - \Delta - t_{setup} - t_{propagation}}$; quindi il ritardo $\Delta$ deve essere scelto mediando tra la diminuzione della probabilità di errore ed il ritardo introdotto.

\section{Locking} È possibile concedere ad un master l'utilizzo esclusivo del bus per più operazioni successive con un circuito di lock (L); questo filtra le linee $/GT$ e $/RQ$ tra RS2 e l'arbitro, se è attivo l'ingresso $LOCK$ con cui il master fa richiesta di lock dopo aver ottenuto l'accesso al bus. \begin{equation}

 /RQ_L = /RQ(\overline{LOCK} + /GT) \phantom{30} 
 /GT_L = /GT + /RQ(LOCK + /GT_L)

\end{equation} Se $LOCK$ è inattivo, la rete di lock è trasparente ed in uscita ha $/GT_{L}$ e $/RQ_L$ corrispondenti agli ingressi, altrimenti se $LOCK$ è attivo $/RQ_L$ viene mantenuto attivo e $/GT_L$ segue $/RQ$.