In questo articolo verrà illustrato il funzionamento del bus Versa Module Europa, meglio conosciuto come VMEbus, e una sua possibile implementazione in VHDL.
Il VMEbus è stata sicuramente una delle più importanti vittorie della tecnologia ottenendo nel 1983 da IEC (IEC821) e successivamente nel 1987 da IEEE, come ANSI/IEEE 1014, una standardizzazione ben meritata. Nel tempo lo standard VMEbus è stato continuamente aggiornato inserendo sempre nuove funzionalità, ad esempio si è cercato di aumentare la capacità di indirizzare nuovi moduli esterni fino alle estensioni VME64, ovvero è stato garantito il supporto a 64 bit, o VME64x e VME320. La tabella 1 pone in evidenza l’evoluzione tecnologica del VMEbus, mentre la tabella 2 mostra le sue differenti dimensioni nel formato 3U e 6U.
ARCHITETTURA VMEBUS
L’architettura VMEbus ricalca il comportamento funzionale del processore 68000 della Motorola: un processore molto diffuso negli anni ’80 con prerogative funzionali di vero interesse. Il processore mc68000 è stato un sistema di calcolo con enorme potenzialità in grado di garantire uno spazio di indirizzamento lineare di 16 Mbyte con l’istruzione più veloce di 0.5 microsendi con un clock di 8MHz. L’architettura interna del microprocessore si basa su 32 bit e diverse operazioni possono essere svolte su dati da 8 a 32 bit. Il solo limite del processore era l’impossibilità di utilizzare operazioni di divisione e moltiplicazione a 32 bit. Il mc68000 dispone di 16 registri, ugualmente suddivisi tra dati e indirizzi; inoltre, il processore garantisce 14 modi di indirizzamento degli operandi, l’istruzione di trap e la possibilità di utilizzare operazioni e registri in modalità supervisor. Lo standard VMEbus è divisa in due parti: una sezione tipicamente meccanica e l’altra elettronica. La parte meccanica prevede l’uso di due unità: un circuito stampato con connettore a 96 pin e la presenza di slot, ossia fessure dove inserire un circuito stampato in un rack. La sezione elettronica è costituita da diverse unità funzionali tra loro interconnesse. Ricordiamo la presenza di un’interfaccia di controllo, ossia il modulo funzionale che tiene conto delle caratteristiche del backplane, e di un interrupt controller, la sezione preposta alla gestione di una richiesta di interrupt e della status/ID una volta che il gestore dell’interrupt termina la gestione. Non solo, è anche presente il modulo per l’arbitraggio, ossia gestisce la contesa tra i vari Master presenti in un sistema. Il VMEbus utilizza 32 linee di dato e di indirizzo separate, anche se, per dovere di cronaca. Il 68000 utilizzi verso l’esterno 24 bit di indirizzo e 16 bit di dato. Per assicurare la piena compatibilità con diverse architetture, il VME adotta due connettori ifferenti (P1 e P2), composti da tre e quattro file di pin rispettiva mente, sufficienti ad ospitare i segnali di controllo e le linee di indirizzo e dato le diverse profondità di dati/indirizzi. Come abbiamo già accennato, il VMEbus divide la sua struttura funzionale in diverse insieme di linee, per la precisione in quattro differenti moduli, al fine di gestire diversi modelli comportamentali. I progettisti del VMEbus hanno optato per una soluzione di tipo master/slave con trasferimenti di dati sul bus in modo asincrono. Una caratteristica interessante di un sistema di questo tipo è la possibilità di utilizzare una certa flessibilità nel trattamento dei dati o degli indirizzi. Ad esempio, è possibile utilizzare un sottoinsieme delle possibilità offerte, tra 8 e 64 bit. Il VME consente di utilizzare differenti unità master in un sistema, a questo scopo occorre garantire, però, una politica di arbitraggio per gestire correttamente le risorse. Non solo, in un sistema VME è anche possibile gestire fini a sette differenti livelli di interrupt (da IRQ0 a IRQ7). La figura 1 pone in evidenza il diagramma a blocchi semplificato del VMEbus al fine di chiarire, in maniera schematica, le modalità operative del bus.
Dalla figura possiamo vedere che il bus è identificato da tre unità comportamentali differenti: il System Controller, le unità master e le unità slave. Tipicamente, in un sistema VMEbus, dispone di unità master che sono generalmente identificata da una board con logica di controllo, microprocessore o microcontrollore. Al contrario, un sistema slave è tipicamente costituito da unità di memoria o schede di I/O. Il System Controller è, invece, l’elemento fondamentale di un bus VME e sovrintende alla gestione di sistemi che ospitano sistemi con più master. Al fine di offrire un sistema stabile ed efficiente, il System Controller si occupa della gestione dell’arbiter e dell’assegnazione del ruolo di master sul bus ad uno specifico master (uno solo può essere master sul bus). Per svolgere correttamente questa operazione, il system controller adotta una politica di tipo Round Robin. La sua funzionalità non si ferma qui. In effetti, il System Controller si occupa di monitorare la corretta assegnazione del bus mediante il Bus Timer: in pratica si imposta un watchdog per definire un tempo limite e l’uso di un Interrupt Acknowledge Daisy Chain permette di gestire la relativa temporizzazione. La tabella 3 pone in evidenza le differenti linee di trasferimento coinvolte previsti dallo standard VMEbus.
I segnali di Addressing Line sono utilizzati per indirizzare correttamente le risorse presenti sul bus. In effetti, per i dati si utilizzano 32 linee (D0-D31). A prima vista un protocollo di questo tipo risulta essere abbastanza pesante per via dei diversi segnali coinvolti, anche per trasferire quantità insignificanti di dati, ma una valutazione di questo tipo non corrisponde proprio alla realtà. Infatti, il coinvolgimento di una grande quantità di segnali ad una prima valutazione potrebbe sembrare un inutile appesantimento dei flussi di comunicazione, ma utilizzare almeno sette linee per l’arbitraggio ha una sua specifica ragione. Parte di queste linee sovrintendono la tipologia di protocollo che deve transitare sul bus: AM, DS0 e DS1, LWORD. I segnali di controllo, o Control Lines, sono utilizzati per gestire correttamente le comunicazioni master/slave. A questo riguardo è possibile schematizzare l’uso dei diversi segnali. Così, il segnale di BERR*, o bus error, ha il compito di riportare un errore che si è manifestato durante l’operazione di indirizzamento, ad esempio la locazione di memoria o un dispositivo di I/O non esiste all’interno del sistema VME. In questo caso, la presenza di uno stato low identifica la mancanza di una risposta da uno Slave. Il segnale di RETRY* permette di far conoscere al master la momentanea impossibilità di accedere ad uno specifico modulo slave. In questo caso, la parte master deve adottare le necessarie politiche di recovery. Il DTACK* è un segnale che informa la riuscita di un’operazione di accesso al bus. A questo riguardo, la presenza di uno stato low permette al master di sapere che l’operazione è avvenuta con successo. Un’altro segnale importante ai fini del trasferimento, o ricezione, di dati è il segnale di WRITE*. In effetti, questo segnale determina la funzionalità dell’operazione, da master a slave (scrittura) a slave a master (lettura). Per ultimi troviamo i segnali associati alle linee. Con AS*, address strobe, si informa lo slave che il master ha posizionato gli indirizzi corretti ed è pronto a svolgere l’operazione richiesta. Viceversa, con il data strobe, DS0* e DS1*, si identificano la disponibilità dei dati in ingresso. A questo punto possiamo passare al nostro modulo VMEcore in VHDL. Così, il nostro VMEcore è organizzato in differenti entity VHDL: VMECOREC, BUSSCNTC, LOCLADRC, LOCLDATC, SLAVCNTC, SLAVDECC e VMEBADBC. In questa prima parte ci occuperemo del modulo BUSSCNTC (bus controller), utilizzato all’interno del VMEcore. Al contrario, l’unità SLACDECC decodifica i cinque bit del VMEbus addess e degli address modifier code. Infatti, l’interfaccia VMEbus risponde agli address modifier code (A24): 0x3E, 0x3D, 0x3A e 0x39. A questo riguardo la figura 2 mostra il comportamento dell’interfaccia SLAVDECC. A questo riguardo, quando un’interfaccia VME è selezionata, allora l’entity asserisce l’ADC (Address Compare Signal). Il modulo funzionale risponde con gli address modifier code. I cinque bit alti del VMEbus addess bits, VA_I (23..19), sono confrontati con i local address compare bit, SAC23_I (23..19). Qualora questi valori sono coincidenti allora l’interfaccia viene selezionata per un ciclo di bus. L’interfaccia potrebbe essere selezionata o disabilitata con il segnale SAE24_I. L’interfaccia può essere permanentemente abilitata, SAE24_I ad un livello logico ‘1’, o potrebbe essere utilizzata come segnale generico di controllo al fine di disabilitare o disabilitare, quando richiesto, l’interfaccia. Il segnale VAM_I è il segnale di ingresso dell’address modifier.
VME IN VHDL
Per definire un modulo VHDL in grado di implementare un bus di questo tipo occorre, per prima cosa, identificare le sue macrofunzionalità. In questa parte vedremo quali sono le caratteristiche da tenere presenti per realizzare un progetto di questo tipo. Le linee del bus VME sono suddivise in 4 gruppi logici. Il primo è quello che si occupa della gestione del bus di trasferimento dati (o Data Transfer Bus, DTB). In questo caso, le linee da utilizzare comprendono linee di indirizzo (fino a 31), dati (fino a 32) e validazione (handshaking). Il bus di trasferimento dei dati ha linee separate per i dati e per gli indirizzi. Oltre a queste linee esistono anche 6 bit denominati address modifier, o AM, che consentono di scegliere diverse modalità di trasferimento. Le linee di indirizzo e AM devono essere convalidati dal segnale di Address Strobe che costituisce parte delle linee di validazione di ogni ciclo dati. Lo standard prevede diverse modalità di indirizzamento, da 16 bit (definito short) a 32 bit (extended), ma, non solo, cambia anche l’ampiezza della parola trasferita nel singolo ciclo che può essere di 8 bit (BYTE), 16 bit (WORD) e 32 bit (LONG-WORD). Il trasferimento dati, da e verso la memoria o periferica, deve essere asincrono con handshake completo realizzato utilizzando i segnali di controllo, come l’address strobe e i data strobe (DSn), correttamente gestiti dal master. Il bus VME pone particolare attenzione alle linee di interrupt, formato da otto canali numerati da 0 a 7, che uno slave può opportunamente gestire. Le linee di interrupt dispongono di una priorità. Questo blocco funzionale utilizza anche altre linee che servono ad implementare il protocollo di handshake tra La CPU VME e la scheda (o le schede) che hanno richiesto l’interruzione, ossia nIACK, nIACKIN e nIACKOUT. Un altro aspetto da non sottovalutare è l’arbitraggio del bus. L’assegnazione del master sul bus è gestita dal bus di arbitraggio che comprende 4 linee a priorità diversa (dalla 0 alla 3) su cui un master può fare richiesta e rispetta lo schema di assegnazione di tipo ”round-robin” per dividere equamente la risorsa. Infine, occorrono anche considerare i vari segnali presenti nel sistema: clock di sistema, un segnale di reset, alimentazione, ACFAIL (mancanza di alimentazione). L’interfaccia slave di un bus VME deve essere in grado di supportare tutte le specifiche funzionali, un bus dati e indirizzi come A32:D32, sette livelli di interrupt e l’interfaccia BLT. La nostra realizzazione deve essere in grado di lavorare con tutti i tipi di cicli e linee di controllo al fine di decodificare e pilotare correttamente il trasferimento per rispondere effettivamente allo standard.
MODALITÀ DI INDIRIZZAMENTO
È necessario considerare il rispetto dello standard per le differenti modalità di indirizzamento. In effetti, lo standard VME prevede, al fine di localizzare una locazione di memoria, un insieme di segnali che comprendono le linee di indirizzo propriamente dette, ossia An, i data strobe nDS1 e nDS0 e la linea nLWORD. Si ricorda che la linea di indirizzo A0 non è definita dallo standard quindi non sembrerebbe possibile indirizzare singoli byte. In realtà le cose sono, per fortuna, diverse. Il bus segue la convezione big endian per definire l’ordine dei byte in una rappresentazione a 16 o 32 bit. Al contrario altri dispositivi non seguono la convezione Motorola, ma quella Intel ossia little endian: in questo caso l’ordine è opposto. Questa è una considerazione da tenere vivamente presente perché i dispositivi commerciali possono utilizzare diverse convenzioni, ad esempio le interfacce verso PCI utilizzano little endian. Può essere opportuno fare una piccola precisazione: qualora volessimo realizzare interfacce VME a 64 bit (VME64/64x) è necessario utilizzare, oltre alle linee A[31...1], anche i dati D[31...0] insieme a nDS0, nDS1 e nLWORD. Non solo, la modalità di indirizzamento e i protocolli di trasferimento dipendono anche dal tipo di scheda. In effetti, le schede provviste di connettore P1/J1, come le 3U, possono utilizzare solo i primi 23 bit per l’indirizzo e 16 bit per i dati, di conseguenza si può arrivare al massimo a modalità A24/D16. Per la precisione nelle soluzioni 6U e 9U, se provviste di connettore P2/J2, si utilizzano anche le ulteriori linee che consentono di arrivare ad A64 per gli indirizzi e a D64 per i dati. Si ricorda che il connettore fondamentale del bus VME, in tutte le sue versioni, è il connettore P1 (J1) che raggruppa l’insieme minimo di linee necessarie ad implementare lo standard. Sul connettore dovrebbero essere evidenziati i quattro sottogruppi di linee necessarie ad implementare le diverse funzionalità.
PROTOCOLLI DI TRASFERIMENTO
Il bus VME prevede diversi protocolli di trasferimento identificati dall’Address Modifier code. In questo modo diventa possibile scegliere la differente modalità di indirizzamento che può essere short A16, Standard A24, Extended A32. Non solo, in questo modo è anche possibile intervenire sulle modalità di trasferimento: singolo ciclo (SCT Single Cycle Transfer), blocchi (BLT Block Transfer) o a blocchi multiplexato MBLT(Multiplexed BLock Transfer). Grazie agli address modifier possiamo segmentare la nostra zona di accesso, ”supervisory” o ”nonprivileged”. La figura 3 mostra il diagramma a stati delle operazioni permesse in diversi protocolli di trasferimento, mentre la figura 4 pone in evidenza il diagramma delle operazioni durante un tipico ciclo di lettura singola da parte di un master verso uno slave.
Per prima cosa il master indirizza uno slave presentando sul bus le informazioni preliminari necessarie ad eseguire un ciclo di lettura, ossia l’indirizzo, l’address modifier, nWRITE per indicare allo slave la direzione dei dati e, se si tratta di un trasferimento a 32bit nLONGWORD. L’inizio del ciclo è rappresentato dall’attivazione del segnale nAS che valida l’indirizzo e dei segnali nDS0, nDS1. Successivamente lo slave decodifica l’indirizzo e, se riconosce l’indirizzo come appartenente al proprio dominio con l’address modifier corrispondente ad una modalità di trasferimento conosciuta, risponde al master presentando i dati richiesti sul bus e attivando il segnale nDTACK. Quando il master ha registrato i dati nel proprio buffer di lettura, comunica allo slave l’avvenuta ricezione dei dati rilasciando le linee di Data Strobe. Infine, lo slave chiude il ciclo rilasciando la linea nDTACK.
VME INTERRUPT
Come in qualsiasi sistema anche nello standard VME il ruolo degli interrupt è di primaria importanza e sicuramente non possiamo evitare di implementare il suo blocco funzionale. È necessario prevedere tutte le sette linee come sorgenti indipendenti con la relativa priorità. La figura 5 mostra la macchina a stati dell’Interrupt Acknowledge che dovrà essere realizzata poi in VHDL.
Il progettista hardware deve prevedere un sistema di propagazione da un connettore a quello contiguo i segnali della daisy chain di Interrupt Acknowledge (inackIN/iackOUT) anche nel caso in cui le schede slave nel sistema siano montate in posizioni non contigue. Vediamo che il modulo che sovrintende alla gestione degli interrupt deve richiedere i necessari segnali al fine di generare un interrupt sul bus e per rispondere ad un ciclo di interrupt acknowledge. In effetti, un generico slave richiede l’ attenzione del master attivando una linea IRQx*: la linea IRQ7* ha la massima priorità. Le linee sono condivise tra tutti gli slave. Il master accetta l’interruzione e attiva la linea IACK*: la linea IACK* è collegata allo slot 1 del segnale IACKin*, IACKout* dello slot 1 è invece collegato a IACKin* dello slot 2 e così via. Lo slave che ha generato l’ interruzione deve attendere sia IACK* che IACKin* per rispondere al ciclo di riconoscimento. A questo punto lo slave deve fornire un ID (vettore) al master in modo da fargli sapere come gestire l’interrupt. Gli slave che non hanno generato interruzioni dello stesso livello propagano IACKin* su IACKout*. Gli slave possono essere di due tipi: ROAK (Release On Interrupt AKnowledge) e RORA (Release On Register Access).