Firmware della CPLD
Sviluppare applicazioni
per CPLD e FPGA può essere molto divertente. Fino a poco tempo fa però questi
dispositivi erano praticamente preclusi agli hobbisti per colpa del loro costo
proibitivo (sia per quanto riguardava i dispositivi che per i tool di sviluppo).
Fortunatamente le cose stanno decisamente cambiando.
Cos'è una CPLD?
CPLD è un acronimo che
sta per "Complex Programmable Logic Device". Idealmente potete
immaginarli come dispositivi che contengono un elevatissimo numero di elementi
di logica combinatoria e sequenziale, che potete collegare fra loro "via
software" come più
preferite per ottenere la funzione desiderata. Ovviamente questa è una
descrizione molto grossolana; se volete approfondire l'argomento vi consiglio di
visitare i siti dei due maggiori produttori: Altera
e Xilinx.
Le CPLD uniscono la
velocità della logica cablata alla potenza e comodità di microprocessori e DSP. I
"fratelli maggiori" delle CPLD, le FPGA, sono in grado ormai di
ospitare (ed emulare perfettamente) diversi microprocessori da centinaia di MIPS!
Ad esempio Xilinx è famosa per il suo MicroBlaze,
ma è anche possibile implementare dei core PowerPC e altri ancora.
Programmare una CPLD
ormai è piuttosto semplice (ovviamente tutto dipende anche da ciò che volete fare!).
Esistono tool grafici per "disegnare" gli schemi interni come se
fossero normali circuiti digitali, nonché editor per costruire e sintetizzare
macchine a stati finiti. La tecnica più consigliata dai professionisti resta
comunque quella di utilizzare i linguaggi ad alto livello per il design dei
dispositivi logici programmabili, come VHDL e ABEL.
Se vi volete divertire con i tool di sviluppo per CPLD e
FPGA, vi consiglio di scaricare ISE
WebPack della Xilinx: è gratuito e contiene tutto il necessario per
sviluppare applicazioni anche di una certa complessità. Se volete potete
anche autocostruirvi il programmatore
in-circuit a basso costo per i dispositivi Xilinx; funziona sicuramente
per tutte le CPLD della serie XC9500XL, ma credo che supporti anche altre
famiglie.
Gestione del trigger
Ho intenzione di
implementare solo uno dei trigger disponibili nei modelli commerciali: quello
sul raggiungimento di un determinato livello del segnale (in salita o in
discesa) di un canale. È il tipo di trigger che io - e presumo molti altri -
uso più spesso: si sceglie il canale di trigger e con i cursori si imposta un punto per il quale si vuole che passi il segnale. Implementerò
tutte e tre le modalità di questo trigger: single shot (cattura un
singolo trigger e attende che l'operatore "riarmi" l'acquisizione), on
trigger (cattura tutti i trigger e aggiorna lo schermo soltanto quando essi
si verificano) oppure free running (sincronizza in base ai trigger, ma
aggiorna lo schermo a una frequenza costante anche quando essi non si
verificano).
Scarto in partenza
l'ipotesi di implementare trigger condizionati ad altri canali, trigger su
canali multipli o su segnali esterni.
Incredibile a dirsi, ma
la descrizione di come funzionerà la gestione del trigger è rappresentabile da
un vetusto diagramma di flusso:
Il diagramma a
sinistra riguarda la CPU, mentre quello a destra riguarda le varie CPLD
(ovviamente solo una di esse avrà abilitato il rilevamento del trigger, mentre le
altre si limiteranno a riempire la SRAM all'infinito). I dispositivi si
sincronizzano in maniera molto semplice attraverso un segnale condiviso (GO) che
presumibilmente sarà di tipo open-collector (e quindi negato rispetto al diagramma).
Tutto parte da un
interrupt del timer della CPU, che è settato a una frequenza uguale a quella
desiderata per l'aggiornamento del display (diciamo 25 Hz, sufficienti per
ottenere una buona fluidità). La CPU fa partire le CPLD ponendo GO a 1, e poi
aspetta uno di questi due eventi:
- Passaggio del flag GO
a zero. Ciò indica che la CPLD che doveva rilevare il trigger l'ha
effettivamente catturato, ed è pronta assieme alle altre a trasferire i
dati.
- Superamento di una
"deadline" temporale, ossia di un intervallo di tempo che
renderebbe impossibile trasferire la schermata prima che arrivi il prossimo
interrupt del timer (questo controllo viene fatto solo per il trigger in
configurazione free running). Se si verifica questo evento è la CPU
stessa a porre nuovamente GO a zero.
A questo punto la CPU
legge da ogni CPLD la posizione del puntatore del buffer circolare, trasferisce
il contenuto delle SRAM via USB e si rimette in attesa.
Per quanto riguarda le
CPLD, il loro funzionamento è piuttosto semplice. Sarebbe perfetto da
implementare tramite una macchina a stati finiti, ma temo che non ci starebbe
nella nostra CPLD (o comunque in un dispositivo con poche macrocelle come quello
che dobbiamo necessariamente usare per motivi di costo). Se GO è zero, la CPLD
non fa assolutamente nulla; in qualsiasi stato fosse in precedenza, essa blocca
il trasferimento nella SRAM e si mette in attesa di un nuovo passaggio di GO a
1. Quando quest'ultimo evento si verifica, per prima cosa vengono memorizzati
N/2 campioni (con N=dimensione della SRAM) dall'ADC. Poi la SRAM continua ad
essere riempita circolarmente all'infinito finché non si verifica la condizione
di trigger. A quel punto vengono memorizzati altri N/2 campioni, infine la CPLD
segnala il suo stato di pronto alla CPU ponendo GO a zero. La lettura all'inizio
e alla fine degli N/2 campioni è fatta per poter disporre sempre di più
campioni possibili prima e dopo del trigger; in questo modo è possibile
spostare il cursore del trigger dove si preferisce (anche al difuori dello
schermo) e continuare a vedere un'intera schermata di dati validi.
Implementazione
Rispetto alla versione
precedente del firmware ho corretto diversi piccoli particolari che mi erano
sfuggiti, fatto simulazioni più accurate e aggiunto l'implementazione anche per
i canali digitali (per l'analizzatore di stati logici). Nel progetto trovate i
due schematici; dovete includere soltanto quello che vi interessa (trigger_a.sch
per i canali analogici e trigger_d per quelli digitali). Ho avuto qualche
difficoltà a fare stare tutto nella nostra XC9572XL-10TQ100,
ma sembra che essa regga ancora bene. Spero di non essermi dimenticato nulla,
perché utilizzo praticamente tutte le macrocelle del dispositivo e non potrei
aggiungere nemmeno un altro flip-flop...
Nel prossimo capitolo
abbozzerò una descrizione delle varie funzionalità della CPLD, anche se per un
vero e proprio "reference manual" mi serve un po' di tempo extra.
Indice
(precedente) Schema
a blocchi
(prossimo) Blocco
di acquisizione analogico
|