|
|
||||||||||
In questo laboratorio si chiede di completare il progetto di un sistema di comunicazione seriale asincrona (vedi la figura seguente). Dopo la verifica del progetto mediante simulazione, ne realizzeremo un prototipo su FPGA per verificarne il reale funzionamento.
Il sistema è composto da due unità identiche, A e B, interconnesse tra di loro, a distanza, attraverso due linee di comunicazione seriale. Ogni unità comprende un trasmettitore (TX) e un ricevitore (RX) di linea seriale. Ciascuna unità lavora con un clock di frequenza nominale pari a 10 MHz. I generatori di clock delle due unità sono fisicamente diversi e separati: a causa delle tolleranze di fabbricazione, le frequenze effettive dell'uno e dell'altro risulteranno un poco diverse, per cui le due unità devono essere considerate, tra di loro, asincrone. Le due unità comunicano tra loro inviando e ricevendo sequenze seriali a pacchetto (vedi figura seguente): Ogni pacchetto è formato da un bit di START a '1', seguito, nell'ordine, dai bit D0, D1, D2, D3, D4, D5, D6 e D7 e, infine, terminato con un bit di STOP a '0'; il tempo di bit ("Bit Time") è pari a 1,6 µS, corrispondente a 625 Kb/s (10 MHz /16). Si noti che il clock non viene reciprocamente trasmesso: ne risulta quindi una trasmissione seriale asincrona. Nel seguito, progetteremo dapprima separatamente il trasmettitore (TX) e poi il ricevitore (RX), verificandone il funzionamento tramite simulazione. Quindi, integreremo i due moduli in un'unica unità, comprendente sia il trasmettitore che il ricevitore: terminata la simulazione di questa unità completa, passeremo alla sua realizzazione fisica utilizzando una scheda prototipo basata su FPGA. Sarà possibile testare il sistema di comunicazione utilizzando due schede separate (le unità A e B), collegate tra loro con un cavetto. Il trasmettitore seriale TX La figura seguente mostra lo schema del solo trasmettitore, di cui progetteremo il controllore, dopo avere analizzato la funzionalità degli altri elementi del sistema. Compito del trasmettitore è inviare sulla linea SER_OUT, alla pressione del pulsante !TX_GO, un pacchetto seriale contenente il dato D7..D0 presente all'ingresso TX_DATA, rispettando il formato e i tempi descritti in precedenza. Al termine della trasmissione attiva l'uscita TX_END, per la durata di un tempo di bit. In figura osserviamo, evidenziati dai riquadri colorati: un contatore del tempo di bit [A, in rosso], un registro a scorrimento [B, in blu], un contatore del numero di bit [C, in rosso], e il controllore di trasmissione [D, in marrone], realizzato con una macchina a stati finiti (MSF). Contatore del tempo di bit [A] Registro a scorrimento [B] Si noti che la trasmissione seriale inizia quando il dato è caricato nel registro, dal momento che l'operazione di caricamento impone un '1' (il bit di start) sulla linea SER_OUT. Il controllore poi ottiene la trasmissione dei bit successivi del pacchetto, uno dopo l'altro, facendo scorrere a destra il registro (imponendo S1 = '0' e S0 = '1'), per un ciclo di clock, al termine del tempo di ogni bit. Contatore dei bit [C] Controllore di trasmissione [D] Specifiche di progetto del controllore di trasmissione Potete scaricare qui una traccia da completare del diagramma ASM del controllore di trasmissione, dove le variabili di stato X,Y e Z sono già state definite, così come le uscite LD, S0, S1, END ed EN, e gli ingressi GO, TCB e TCN (un click sulla figura aprirà la traccia del diagramma nel d-FsM): Il controllore riceve il comando TX_GO (sulla linea GO), il cui fronte di discesa avvia la trasmissione dei dati. Nel diagramma fornito, gli stati (a) e (b) hanno il compito non solo di attendere il fronte di discesa, ma anche di inizializzare la trasmissione, attivando la linea LD. LD inizializza il contatore del tempo di bit, dal quale il controllore riceverà periodicamente il segnale TCB, che sarà utilizzato per emettere i bit sulla linea a cadenza regolare (ad ogni tempo di bit). L'attivazione di LD predispone anche il contatore dei bit, che informerà il controllore quando la trasmissione seriale dovrà essere conclusa. Il controllore gestisce anche il registro a scorrimento di trasmissione: come descritto in precedenza, per iniziare la trasmissione, ordina al registro di caricare il dato parallelo TX_DATA, insieme ai bit di start e di stop. Il controllore entra poi in un ciclo in cui trasmette gli altri bit imponendo al registro un passo di scorrimento a destra, ad ogni attivazione della linea TCB. Ogni volta che un bit viene trasmesso, il controllore attiva anche la linea EN, per un ciclo di clock, aggiornando il contatore dei bit da trasmettere. Si noti che, se non utilizzassimo un contatore per questo scopo, dovremmo complicare di molto l'algoritmo del controllore, prevedendo ripetitive sequenze di stati, quasi identiche tra loro, per ogni bit da trasmettere. In questo modo, invece, la sequenza è unica, e il ciclo si conclude alla attivazione della linea TCN del contatore (quando il numero dei bit rimanenti raggiunge lo zero). Infine, il controllore attiva l'uscita TND, per segnalare la fine della trasmissione. Per garantire che la durata dell'uscita TND sia pari a un tempo di bit, conviene attendere un'ultima volta il segnale TCB, e poi ritornare in attesa del fronte di discesa di GO. Verificate dapprima, utilizzando la simulazione con il d-FsM, che la funzionalità della MSF progettata corrisponda alle specifiche. Importate poi il componente ottenuto nel d-DcS, nello schema da completare qui disponibile. Nello schema sono state aggiunte alcune uscite di controllo, utili per verificarne il funzionamento mediante la simulazione temporale (è disponibile, nella finestra del diagramma temporale, la sequenza di test "TxSequence"). Il ricevitore seriale RX La figura qui sotto mostra lo schema del solo ricevitore, il cui compito è acquisire i pacchetti seriali in arrivo sulla linea SER_IN, tenendo conto del formato e dei tempi utilizzati in trasmissione. Al termine della decodifica di un pacchetto, il ricevitore produce in parallelo, sulle uscite U7..U0, gli 8 bit che vi erano contenuti, e avvisa della loro disponibilità con l'attivazione dell'uscita RX_RDY, per la durata di un tempo di bit. Anche in questo caso, progetteremo il solo controllore, dopo avere analizzato la funzionalità degli altri elementi. Allo scopo, osserviamo in figura: un contatore del tempo di bit [A, in rosso], un registro a scorrimento [B, in blu], un contatore nel numero di bit [C, in rosso], e il controllore di ricezione [D, in marrone]. Contatore del tempo di bit [A] Registro a scorrimento [B] Contatore dei bit [C] Controllore di ricezione [D] Specifiche di progetto del controllore di ricezione Riassumendo, il controllore a riposo attende l'arrivo di un pacchetto sulla linea seriale SER_IN; non appena individuato il bit di start, ne verifica la validità e, grazie a questo, sincronizza le operazioni del registro a scorrimento in modo da acquisire correttamente i successivi bit del pacchetto e, infine, effettuare la verifica del bit di stop (qui di seguito esaminiamo più nel dettaglio queste operazioni). Come nel caso del trasmettitore, anche qui riusciamo a contenere l'algoritmo del controllore in un numero ragionevole di stati, poiché temporizzazioni e conteggi sono delegati a dispositivi esterni. E' disponibile una traccia del diagramma ASM del controllore. Nel file sono già state definite le variabili di stato X, Y e Z, le uscite LD, S0, S1, RDY e EN, gli ingressi LIN, TCB e TCN e, infine, sono già impostati gli stati (a) e (b)(un click sulla figura aprirà il file da completare nel d-FsM): Osservando il diagramma ASM, nello stato di attesa (a) si controlla la linea seriale tramite l'ingresso LIN, attendendo il bit di start. Durante la permanenza in (a), l'attivazione di LD inizializza i contatori del tempo di bit e del numero di bit: uscendo da questo stato, i contatori saranno poi liberi di contare, a partire dal valore di inizializzazione. All'occorrenza del bit di start, passiamo nello stato (b), dove rimaniamo in attesa che trascorra metà del tempo di bit (e cioè che si attivi TCB). Se nel frattempo LIN ritorna basso, il formato del bit di start non è da considerarsi valido e quindi ritorniamo nello stato iniziale, in attesa di un nuovo bit di start. Ricordiamoci che, come detto prima, il contatore del tempo di bit è stato inizializzato in modo da generare il segnale TCB, la prima volta, alla metà del tempo di bit: mentre siamo nello stato (b), il contatore del tempo di bit sta decrementando il suo valore. All'arrivo di TCB, dichiariamo valido il bit di start, proseguendo oltre. L'attesa di TCB nello stato (b) ci permette inoltre di sincronizzare, rispetto al bit di start, l'acquisizione dei successivi bit di dato. Infatti, dopo la prima attivazione di TCB, avvenuta al centro del bit di start, il contatore del tempo di bit continuerà ad attivare ciclicamente TCB ogni 16 fronti di salita del clock, e quindi sempre in corrispondenza del centro del tempo di tutti i successivi bit. L'acquisizione degli 8 bit di dato è gestita da un ciclo di stati in cui il controllore:
Se TCB e TCN risultano attivi entrambi, non ci sono più bit di dato da ricevere, e in quel momento su LIN è disponibile il bit di stop. Non occorre memorizzare questo bit, ma solo verificare il suo valore. Se il bit di stop è correttamente a zero, dobbiamo solo attivare RDY per la durata di un tempo di bit (aspettando che TCB si attivi di nuovo) e poi tornare nuovamente in attesa di un nuovo pacchetto, nello stato (a). Invece, se il valore del bit di stop è sbagliato, attendiamo, senza generare RDY, che LIN torni a zero, prima di tornare nello stato (a). La funzionalità della MSF può essere verificata dapprima utilizzando la simulazione del d-FsM; poi il componente ottenuto deve essere importato nel d-DcS, in questo schema da completare. Anche in questo caso, lo schema è stato arricchito di alcune uscite di controllo, per rendere più leggibile la simulazione temporale (nella finestra del diagramma temporale è utilizzabile la sequenza di test "RxSequence"). L'unità completa (TX + RX) Nella figura seguente appare lo schema della unità completa (trasmettitore e ricevitore): Il trasmettitore e il ricevitore sono esattamente quelli definiti in precedenza. Il clock CK e il !RESET sono stati unificati e compaiono nella parte in fondo dello schema. E' stato aggiunto un selettore "2-1", evidenziato nello schema con un riquadro rosso. Il nuovo ingresso TEST, quando attivato, consente di collegare il ricevitore direttamente al trasmettitore, per permettere il test indipendente di una sola unità, senza ricorrere al collegamento di due differenti sistemi tra loro. In questo modo, in simulazione riusciremo a inviare un pacchetto e a riceverlo direttamente nello stesso sistema. Ai fini della simulazione dell'intero sistema di trasmissione e ricezione, è qui disponibile uno schema da completare con le due MSF progettate in precedenza. Lo schema, come nei casi precedenti, è stato arricchito di alcune uscite di controllo, per rendere più completa la simulazione temporale (nella finestra del diagramma temporale è disponibile la sequenza di test "TestSequence"). Le uscite aggiunte aiuteranno anche la sperimentazione del sistema sulla scheda FPGA. Si raccomanda di usare lo schema fornito senza eliminare o modificare le terminazioni di ingresso e di uscita perché sono state predisposte per la esportazione del progetto sulla scheda FPGA. Terminata la simulazione dell'intero sistema, passiamo alla sua realizzazione fisica sulla scheda FPGA. La procedura generale è descritta passo passo nei tutorial introduttivi: Realizzazione di un prototipo di circuito su scheda Altera DE2 Il comando "Test on FPGA" (del d-DcS) apre la finestra di dialogo visibile qui sotto: Le associazioni tra schema d-DcS e scheda FPGA, per quanto riguarda gli ingressi e le uscite, sono state già definite nella traccia d-DcS fornita, per cui non è necessario modificarle. Il clock CK è stato impostato a 100 Hz (invece che a 10 MHz), per consentire l'esame visivo del comportamento del sistema. E' stata anche scelta la modalità "Slow Clock Mode": come risulta dai parametri impostati, visibili nella figura, tale modalità è attivabile tramite l'interruttore SW[17]. Lo "Slow Clock" è impostato in modo manuale, comandato dal pulsante Key[03], ed è visualizzato dal led rosso LEDR[17]. In base a questa impostazione, se l'interruttore è a zero, il clock CK lavorerà normalmente a 100 Hz, ma se l'interruttore è a uno, il clock sarà generato in modo manuale, un impulso alla volta, premendo il pulsante. Per ottimizzare la sperimentazione di quanto descritto sulla scheda FPGA, le associazioni sono evidenziate in modo riassuntivo nella figura seguente (il "pannello di controllo" del nostro sistema): Possiamo verificare il funzionamento del sistema da solo, attivando la modalità di test (interruttore di TEST verso l'alto), oppure utilizzando due schede separate, interconnesse mediante un cavo adeguato, tale da scambiare dati in entrambe le direzioni:
Realizziamo il collegamento tramite uno dei due connettori da 40 piedini disponibili su ciascuna scheda FPGA. Come si vede nella figura qui sopra, utilizziamo un collegamento incrociato tra il trasmettitore e il ricevitore, in entrambe le direzioni, per un totale di 3 fili (compreso il riferimento di massa GND). Qui lo schema della connessione, che fa riferimento al connettore di espansione "GPIO_1" presente sulla scheda. Anche senza utilizzare l'interruttore TEST, possiamo eseguire test preliminari con una sola scheda, utilizzando un semplice ponticello ("Jumper") inserito sul connettore, come si vede nella figura seguente (freccia gialla), in modo da collegare insieme trasmettitore e ricevitore:
Si faccia molta attenzione nel piazzare e rimuovere il ponticello, per evitare di danneggiare meccanicamente i piedini del connettore. Per evitare possibili danni al chip FPGA, i cui piedini sono direttamente collegati al connettore, è necessario eseguire tale operazione a scheda non alimentata (spenta). |