|
Nel progetto del ricevitore seriale incontreremo una serie di problemi dovuti principalmente alla natura asincrona della trasmissione ed alle possibili deformazioni prodotte sul segnale dal canale trasmissivo utilizzato. In una trasmissione asincrona, difatti, non viene trasmesso alcun segnale di clock che possa sincronizzare il ricevitore ed il trasmettitore; vedremo anzi che le temporizzazioni saranno affidate a due clock ben distinti, uno per ciascuno dei due dispositivi che comunicano tra di loro.
In tali condizioni, la frequenza del clock con cui il trasmettitore seriale emette i bit non potrà essere mai perfettamente identica a quella del clock interno al ricevitore seriale, a causa di una serie di fattori come la diversa temperatura dell'ambiente, differenze anche minime nella costruzione interna dell'oscillatore al quarzo, e via dicendo. Dobbiamo pertanto tener conto del fatto che la frequenza di trasmissione può essere leggermente differente da quella di ricezione.
Per di più, a causa dell'assenza di un clock comune, il ricevitore non può conoscere con precisione l'istante di inizio di un pacchetto di bit, ossia di arrivo del bit di start. Se si esegue un campionamento periodico della linea seriale mediante un flip-flop di tipo D, ad esempio, può accadere che il clock applicato a questo flip-flop sia più lento di quello con cui opera il ricevitore, e il passaggio dallo stato di mark a quello di space venga rivelato in un istante troppo vicino alla fine del bit di start. In queste condizioni può addirittura accadere che il ricevitore non riesca a rivelare qualcuno dei bit trasmessi, come si vede nel diagramma di temporizzazione di Fig. 11.
|
In questo diagramma abbiamo indicato con TxCLK il clock interno del trasmettitore rispetto a cui sono sincronizzati i dati serializzati (RxD), con RxCLK il clock interno del ricevitore, leggermente più lento di TxCLK, e con Q l'uscita del flip-flop che cattura i bit in arrivo dalla linea all'interno del ricevitore. Possiamo notare in primo luogo che il progressivo sfasamento dei due clock comporta un'incertezza sul valore del secondo bit di informazione, e la perdita completa del terzo bit. Viceversa, se il campionamento avvenisse molto vicino all'inizio di ciascun bit, e se la frequenza del trasmettitore fosse adesso leggermente minore di quella del ricevitore, il ricevitore potrebbe campionare due volte consecutive lo stesso bit.
Un altro problema, come abbiamo già accennato nel corso del progetto del trasmettitore seriale, è dovuto alle distorsioni del segnale durante la trasmissione e le fasi di modulazione e demodulazione. In seguito a queste distorsioni, ad esempio, può accadere che i bit di valore 1 abbiano durata diversa dai bit di valore 0, il che potrebbe comportare un errato campionamento dal lato del ricevitore.
Per ovviare a tutti questi inconvenienti, occorre anzitutto risincronizzare il clock interno del ricevitore ad ogni bit di start. La sincronizzazione deve avvenire in modo che i fronti attivi (ad esempio, di salita) di questo clock abbiano luogo quanto più possibile al centro dell'intervallo di tempo riservato a ciascun bit trasmesso in linea, in modo da campionare il segnale RxD il più lontano possibile dagli istanti di tempo in cui tale segnale può commutare. In questo modo diventa possibile tollerare lievi differenze, positive o negative, tra la frequenza del trasmettitore e quella del ricevitore.
Per generare questo tipo di clock, è opportuno disporre di un altro segnale di clock che abbia frequenza multipla della frequenza di trasmissione, e poi dividere opportunamente questa frequenza. Supponiamo allora di avere a disposizione un generatore di clock la cui frequenza sia, ad esempio, 8 volte quella di trasmissione, e di generare tramite un flip-flop un segnale Z1, che vale normalmente 0, commuta ad 1 non appena arriva il bit di start, e ritorna infine a 0 quando tutto il pacchetto dei bit è stato ricevuto. Il segnale Z1 viene utilizzato per abilitare un contatore a 3 bit, con uscite Q2 (la più significativa), Q1 e Q0, in modo che quando il segnale Z1 vale 0, allora il contatore è forzato in reset mentre quando Z1 vale 1 il contatore comincia ad avanzare ad ogni fronte di salita del clock. Il diagramma di temporizzazione sarebbe allora quello illustrato in Fig. 12.
Osserviamo allora che il segnale Q2 non solo ha frequenza nominalmente identica a quella di trasmissione, ma i suoi fronti di salita hanno luogo approssimativamente al centro di ogni intervallo (cella) di bit sul segnale RxD: esso può dunque essere utilizzato come segnale principale di clock (RxCLK) per tutti gli altri circuiti del ricevitore seriale.
Osserviamo ancora che dall'arrivo del bit di start fino al primo fronte di salita di CLKx8 passa un intervallo casuale di tempo, e dunque il contatore parte con un certo ritardo rispetto all'arrivo del bit di start. Questo ritardo può valere al massimo un periodo di CLKx8, ossia 1/8 del periodo T della cella di bit, che è un tempo sicuramente accettabile nella gran parte dei casi. Qualora fosse richiesta una precisione maggiore nella determinazione del centro del bit di start, si potrebbe ricorrere ad un clock con frequenza maggiore, ad esempio 32 o 64 volte quella di trasmissione, e un contatore a 5 o, rispettivamente, 6 bit; in tal caso il centro del bit di start verrebbe determinato con un ritardo massimo di 1/32 ovvero di 1/64 della durata T della cella di bit.
Assieme alla sincronizzazione tra il ricevitore ed il trasmettitore abbiamo anche risolto, entro certi limiti, tutti gli altri problemi ad essa connessi, come ad esempio la diversa durata del bit 0 rispetto a quella del bit 1 che, campionando i bit al centro dell'intervallo di tempo ad essi riservato, non dovrebbe più avere conseguenze. È chiaro comunque che se la differenza tra la frequenza del trasmettitore e quella del ricevitore è eccessivamente elevata, il segnale Q2 si discosterà sempre più dal centro della cella di bit man mano che si procede verso la fine del pacchetto di bit, e non è più esclusa la possibilità di perdita di dati o di campionamenti multipli dello stesso bit. Generalmente, tuttavia, l'impiego di oscillatori al quarzo sia lato trasmettitore che lato ricevitore limita la massima differenza di frequenza tra i due clock; i ricevitori seriali commerciali, ad esempio, operano in genere con un clock interno la cui frequenza è 16 o 64 volte superiore a quella di trasmissione, il che fornisce margini di sicurezza senz'altro adeguati .
Possiamo adesso occuparci dell'interfacciamento del ricevitore seriale con il calcolatore. Come abbiamo anticipato sopra, avremo un ingresso a cui viene applicato il segnale proveniente dalla linea, che abbiamo indicato con RxD; avremo anche in uscita gli 8 bit DP0-7 che vengono generati riportando in parallelo i bit ricevuti uno per volta.
Per realizzare una forma di handshake, sarà necessario un segnale RDY in uscita verso il calcolatore, che assuma il valore 1 non appena un pacchetto di bit viene correttamente ricevuto, elaborato e memorizzato in un apposito registro interno del ricevitore. Dovrà anche essere previsto un segnale proveniente dal calcolatore, che chiameremo STROBE, necessario per avvertire il ricevitore seriale che il carattere ricevuto è stato prelevato dalla CPU. Come in ogni handshake, il calcolatore dovrà porre ad 1 questo segnale non appena ha acquisito il dato presente sulle linee DP0-7, e dovrà riportarlo a 0 non appena il segnale di RDY sarà tornato inattivo, cosa che avverrà come conseguenza dell'arrivo dello STROBE. Solo dopo aver ricevuto un segnale di STROBE, il ricevitore seriale potrà memorizzare nel suo registro interno un nuovo dato in arrivo dalla linea seriale.
Se il calcolatore non è sufficientemente veloce nell'acquisizione del carattere assemblato dal ricevitore, può accadere che quest'ultimo riesca ad assemblare un nuovo pacchetto prima che il calcolatore abbia inviato il segnale STROBE (quindi quando RDY è ancora attivo). Sarà allora necessario un ulteriore segnale di errore in uscita, che chiameremo OVERRUN, che diventa attivo non appena si verifica una tale circostanza. Trovando OVERRUN attivo, il calcolatore viene avvertito della perdita di almeno un carattere della trasmissione, e può di conseguenza prendere i provvedimenti del caso.
Vi sono altri tipi di errori che il ricevitore seriale, a differenza del trasmettitore, deve poter segnalare al calcolatore. Ad esempio, può accadere che una volta ricevuto un carattere il bit di parità risulti di valore non corretto. Avremo allora in uscita un altro segnale, che chiamiamo PTY, che diventa attivo non appena si verifica un errore sul controllo di parità.
Può ancora accadere che il campionamento dei bit del pacchetto venga iniziato da una transizione 1-0 che non corrisponde all'inizio di un bit di start; questo inconveniente può aver luogo, ad esempio, quando si applica l'alimentazione al ricevitore mentre il trasmettitore sta già inviando i dati. Supponiamo infatti che il trasmettitore seriale emetta in sequenza le informazioni 00010111 e 00000000; i pacchetti corrispondenti sarebbero allora:
Se il ricevitore viene acceso in ritardo e i primi tre bit vengono persi, la transizione 1-0 tra il quarto ed il quinto bit verrebbe interpretata erroneamente come un bit di start, e la sequenza che il ricevitore interpreterebbe come primo carattere sarebbe la seguente:
In questo caso, oltre alla rivelazione di un errore di parità, il ricevitore può anche rivelare che i due bit di stop valgono entrambi 0, invece che 1. Un errore di ricezione di questo tipo viene detto frame error. Il ricevitore seriale avrà quindi in uscita un segnale FE che verrà attivato al verificarsi di un frame error, ossia quando uno o entrambi i bit di stop vengono trovati a 0. È chiaro che in determinate circostanze (ad esempio se la seconda informazione inviata fosse stata 11111111 invece che 00000000) si potrebbe verificare un errore di sincronizzazione senza che alcuno degli stop bit sia trovato a zero e senza alcun errore di parità: la situazione di frame error non potrebbe in tal caso essere rilevata.
Può infine accadere che un disturbo sulla linea venga erroneamente interpretato come bit di start, e faccia passare il segnale Z1 da 0 ad 1. Se in seguito a questo disturbo il ricevitore seriale iniziasse a campionare la linea RxD, si potrebbe incorrere in una situazione di apparente frame error per aver iniziato a campionare il carattere prima dell'arrivo effettivo del bit di start. Generalmente, tuttavia, questi disturbi hanno una durata minore di quella di una cella di bit, ed è dunque sufficiente verificare che, in corrispondenza al fronte di salita di Q2 corrispondente al centro nominale della cella di bit, il segnale RxD invece di valere ancora 0 è tornato ad 1: in tal caso, si può ignorare il falso bit di start senza che sia necessario generare alcun errore.
L'ultimo segnale di interfaccia necessario è una linea in ingresso, che chiameremo ERS, mediante cui il calcolatore può resettare tutte le segnalazioni di errore emesse dal ricevitore. Il ricevitore seriale può essere allora rappresentato schematicamente come in Fig. 13.
Il ricevitore seriale sarà strutturato in linea di principio attorno a uno shift register che provvede ad assemblare un carattere a partire dal segnale di ingresso seriale; appena il carattere è completo, esso viene inviato ad un registro per consentire al calcolatore di leggere i segnali DP0-7 mentre lo shift register rimane libero di assemblare il carattere successivo.
Come vedremo tra breve, sarà molto utile avere a disposizione un segnale, che chiameremo SAMPLE, che passi dal livello 0 al livello 1 in corrispondenza del centro della cella di bit, ma che, a differenza di Q2, torni a zero dopo un solo periodo del clock CLKx8. La sua breve durata rispetto alla lunghezza della cella di bit potrà garantirci che i dati seriali in ingresso al ricevitore rimangano stabili in corrispondenza sia del suo fronte di salita che del suo fronte di discesa, ed esso potrà così essere usato come strobe per effettuare il campionamento dei dati seriali in arrivo. A tale scopo utilizziamo, così come abbiamo fatto per il trasmettitore seriale, due segnali ausiliari che chiameremo Z2 e Z3: il segnale Z2 vale 0 se Q2 vale 0, e passa ad 1 in corrispondenza al fronte di discesa di CLKx8 immediatamente successivo alla transizione 0-1 del segnale Q2; il segnale Z3 vale anch'esso 0 se Q2 vale 0, ma passa ad 1 dopo due fronti di discesa dopo la transizione 0-1 del segnale Q2. In altri termini, SAMPLE è dato da (Fig. 14).
Il circuito per la generazione di SAMPLE appare in Fig. 15.
Supponiamo ora di utilizzare un contatore a 7 bit, invece che a 3, pur mantenendo la frequenza del clock principale 8 volte superiore a quella di trasmissione. In tal caso, i tre bit meno significativi indicano una posizione all'interno della cella di bit, mentre il fronte di salita di Q2 continua ad identificare, con i limiti di precisione che abbiamo già esaminato, la posizione centrale della cella. I quattro bit più significativi invece, considerati come un unico numero binario a quattro bit, indicano la posizione della cella di bit all'interno del pacchetto, dove il conteggio 0 identifica il bit di start e il conteggio 11 identifica il secondo bit di stop. Se colleghiamo questi quattro bit agli ingressi di selezione di un decodificatore a 16 uscite, e il segnale SAMPLE all'ingresso di abilitazione di questo decodificatore, durante la ricezione del carattere otterremo un impulso rettangolare di durata pari ad 1/8 della durata della cella di bit, che si presenta in sequenza sulle prime 12 uscite del decodificatore, in corrispondenza dei 12 bit che dobbiamo ricevere per ogni pacchetto. A metà del bit di start, avremo di conseguenza un impulso sulla prima uscita, a metà del primo bit di dati avremo un impulso sulla seconda uscita, e così via. Indichiamo le uscite di questo decodificatore con Y0-11 (Y0 è l'uscita che presenta un impulso in corrispondenza del bit di start), ed indichiamo i quattro bit più significativi del contatore, in ordine crescente di peso, con Q3, Q4, Q5 e Q6. Gli impulsi Y verranno usati, come vedremo tra breve, per effettuare i controlli di parità o quelli relativi al frame error. Quanto detto si può riassumere nello schema di Fig. 16.
L'uscita Q2 del contatore verrà utilizzata come clock per uno shift register ad 8 bit il cui ingresso seriale SIN è connnesso al segnale di linea RxD. Non appena arriva l'ottavo bit di dati del pacchetto, dobbiamo inviare il contenuto dello shift register ad un registro che mantenga i dat stabili in modo che il calcolatore possa accedervi. Possiamo in questo caso fare due ipotesi: se il registro è un normale registro costruito con flip-flop di tipo D, allora occorrerà attendere un certo tempo per permettere ai dati in uscita dallo shift register di stabilizzarsi, prima di poter inviare un fronte di caricamento all'ingresso di clock del registro. Ciò esclude la possibilità di utilizzare il fronte di salita di Q2 corrispondente all'arrivo dell'ultimo bit; il fronte di salita del segnale Y8, d'altro canto, presenta un ritardo pari a metà del periodo del clock CLKx8, rispetto al fronte di salita di Q2, ma in genere, soprattutto se le velocità di trasmissione sono elevate, questo intervallo di tempo può non essere sufficiente per garantire la stabilità dei dati in uscita dallo shift register. Per la massima sicurezza, quindi, è preferibile utilizzare il fronte di salita di Q2 successivo, ossia quello corrispondente al bit di parità, quando i dati in uscita dallo shift register, a causa dei ritardi di propagazione, non hanno ancora iniziato a cambiare.
Se invece il registro viene realizzato mediante un latch, possiamo in alternativa utilizzare il segnale Y8 connettendolo all'ingresso di gate G per permettere al latch di seguire l'uscita dello shift register, dal momento che Y8 ritorna basso dopo un tempo pari a 3/2 del periodo del clock CLKx8 a partire dal fronte di salita di Q2, ed abbiamo quindi un tempo 3 volte superiore per permettere alle uscite dello shift register di stabilizzarsi ed essere memorizzate.
Per verificare la correttezza del bit di parità, è sufficiente controllare che la parità calcolata sugli 8 bit di dati arrivati e quella che arriva sul segnale RxD siano uguali. Questo significa che lo XOR tra la parità calcolata e quella ricevuta deve dare sempre 0 per risultato. Possiamo allora mandare l'uscita di questo XOR all'ingresso di un flip-flop di tipo D, e sfruttare il segnale Y9, che si attiva poco dopo la metà della cella di parità, collegandolo all'ingresso di clock di questo flip-flop, secondo lo schema di Fig. 17.
Si noti che l'uscita dall'albero di XOR che calcola la parità ha a disposizione circa 4 periodi di CLKx8 per stabilizzarsi prima dell'arrivo del bit di parità sulla linea RxD, ed altri 4 periodi per poter effettuare il confronto tra RxD ed il valore di parità calcolato. Si noti anche che il calcolo viene fatto in uscita dal latch e non direttamente sullo shift register; ciò perché il segnale Y9 arriva al flip-flop mezzo periodo di CLKx8 dopo l'arrivo del fronte di salita allo shift register tramite il segnale Q2. Se la velocità di trasmissione è sufficientemente alta questo non crea problemi di sorta in quanto i ritardi di propagazione attraverso gli XOR fanno sì che l'ingresso al flip-flop sia ancora stabile quando arriva il fronte di Y9, ma se la velocità di trasmissione è abbastanza bassa (diciamo 1200 o 300 baud) allora c'è il rischio che l'uscita dell'ultimo XOR sia instabile perché le uscite dallo shift register cominciano a variare. L'ingresso di RESET asincrono del flip-flop che memorizza il risultato del controllo di parità andrà ovviamente collegato al segnale ERS inviato dal calcolatore.
Per la verifica di un eventuale frame error, possiamo utilizzare due flip-flop di tipo D, il cui ingresso è per entrambi connesso al segnale RxD. All'ingresso di clock del primo flip-flop colleghiamo il segnale Y10, il cui fronte di salita si presenta a metà del primo bit di stop, e all'ingresso di clock del secondo flip-flop colleghiamo il segnale Y11, il cui fronte di salita si presenta a metà del secondo bit di stop. Se le uscite di questi flip-flop sono entrambe pari ad 1, allora non c'è frame error (o comunque non si riesce a rilevarlo), mentre se anche una sola delle uscite è pari a 0, allora si è sicuramente verificato un frame error. Il segnale FE sarà quindi dato dal NAND tra le uscite di questi due flip-flop.
Anche questi flip-flop verranno resettati dal segnale ERS, questa volta connesso all'ingresso di PRESET asincrono. Lo schema risultante è illustrato in Fig. 18.
Passiamo ora ad analizzare in quali circostanze i circuiti del ricevitore vanno resettati. Una volta ricevuto il secondo bit di stop dobbiamo semplicemente rimetterci in attesa di un nuovo bit di start: sarà allora sufficiente resettare il segnale Z1 e di conseguenza anche il contatore. Il reset dovrà aver luogo non appena il contatore raggiunge il conteggio 12 (quindi appena trascorso il bit di stop) e di conseguenza occorrerà resettare Z1 quando Q5 e Q6 sono entrambi 1 (è difatti inutile verificare che anche i bit Q3 e Q4 siano a 0). Un'altra situazione in cui occorre resettare il ricevitore si presenta all'arrivo di un bit di start spurio: se in corrispondenza ad Y0 = 1 troviamo che RxD è tornato ad 1, allora occorrerà nuovamente resettare Z1. Il segnale di RESET del flip-flop che genera Z1 sarà quindi dato da:
È ovvio che l'ingresso D di tale flip-flop sarà sempre pari ad 1, e che, se il flip-flop commuta sui fronti di salita del clock, il suo ingresso di clock deve essere connesso direttamente al segnale RxD complementato.
Rimane infine da generare il segnale RDY e l'eventuale errore di overrun. Il segnale RDY viene generato dall'uscita di un flip-flop di tipo D, il cui ingresso è sempre pari ad 1 e il cui clock è connesso al segnale Y8. Il segnale STROBE, per quanto detto, andrà collegato al reset asincrono di questo flip-flop. Avremo inoltre errore di OVERRUN se il segnale di RDY è ancora attivo quando entro lo shift register è stato assemblato un nuovo dato: in tal caso è sufficiente connettere RDY come ingresso ad un altro flip-flop al cui clock è applicato il segnale Y8 e al cui ingresso di reset asincrono è connesso il segnale ERS. Lo schema risultante è illustrato in Fig. 19.
Il progetto del ricevitore seriale è a questo punto completo.
© 1997-2003 Paolo Marincola (Rome, Italy)
e-mail: pmaNOSPAM@acm.org (eliminare
i caratteri "NOSPAM" per ottenere l'indirizzo esatto)
Commenti, osservazioni e suggerimenti sono estremamente graditi.
Last revised: 2003-12-06 19:52