\chapter{Memorie e Matrici Logiche Programmabili}


\section{Memorie}

\subsection{Introduzione}



Un utilizzo sempre pi\`u diffuso nei sistemi digitali stanno
acquistando le memorie. Una \Index{memoria} \`e un sistema, organizzato in
celle elementari, dove \`e possibile immagazzinare, per tempi pi\`u o
meno lunghi, informazioni digitali quali bits, bytes, etc.. Le memorie
possono essere di tipo ``sequenziale'' o di tipo ``ad \Index{accesso
casuale}''. Un esempio di memoria sequenziale \`e il \Index{nastro
magnetico}. In una memoria di questo tipo occorre leggere tutta
l'informazione memorizzata, in modo appunto sequenziale, prima di
poter accedere a quella voluta. In una memoria ad accesso casuale \`e
invece possibile accedere all'informazione desiderata specificando la
locazione o posizione dove essa \`e stata scritta (ci\`o presuppone
l'esistenza di un ``\Index{registro}'' dove, per ciascun gruppo di dati,
cio\`e per ciascun ``file'', sia stato preventivamente registrato
l'indirizzo).

Un esempio di memoria ad accesso casuale \`e costituito dai
\Index{dischi floppy} o anche dai \Index{dischi rigidi} (Hard Disks)
dei computer. In questi la memorizzazione dell'informazione \`e basata
su processi di magnetizzazione.

L'elaboratore di un computer ha bisogno anche di memorie, sia
permanenti come le \Index{ROM} (Read Only Memories o memorie a sola lettura)
che temporanee come le \Index{RAM} (Random Access Memories o memorie ad
\Index{accesso casuale}) che consentano tempi di accesso e
trasferimento dati molto pi\`u veloci di quelli caratteristici dei
dischi magnetici.

Le \Index{ROM} incontrano le \Index{applicazioni} pi\`u disparate, che vanno
dall'immagazzinamento del codice (istruzioni\index{istruzione}) che
vengono eseguite all'accensione di un calcolatore, alla memorizzazione
di tabelle che forniscono il valore di funzioni predefinite (quali
sin(x), cos(x), log(x) etc), alla memorizzazione di sequenze
predefinite di impulsi e di forme d'onda, alla memorizzazione dei
codici corrispondenti ai vari caratteri (codice \index{Binary Coded
Decimal}BCD, codice EBCDIC, \Index{ASCII}..) e via dicendo.

Le \Index{RAM} sono memorie dinamiche, cio\`e il loro contenuto pu\`o essere
modificato da programmi.  Esse sono di grande utilit\`a nella
memorizzazione temporanea di sequenze o istruzioni generate dal codice
che viene eseguito da un calcolatore.

\subsection{Struttura di una \Index{ROM}}

La struttura della pi\`u diffusa tra le memorie statiche \`e quella
della ROM. Illustriamo il suo funzionamento con un esempio
concreto. Immaginiamo di voler effettuare rapidamente il calcolo del
fattoriale (m) di un intero n (m=n!) con n minore di un valore
prefissato.  Possiamo effettuare il calcolo una volta per tutte, in
corrispondenza ad ogni valore di n, e poi memorizzare il risultato in
una ROM. Quando si abbia bisogno del fattoriale di un certo intero
sar\`a sufficiente fornire in forma binaria tale numero ad una ROM
come quella di figura~\ref{rom_factorial} (dove, per motivi pratici,
ci si \`e limitati ad interi $\le \,5$). La ROM fornir\`a sui suoi 7
piedini d'uscita il fattoriale m richiesto.


\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/rom_factorial,width=9.0 cm,
height=5 cm}}\end{center}
\caption{Esempio di una struttura di \Index{ROM} a 3 bit in ingresso e 7 in
uscita.}  \protect\label{rom_factorial}
\end{figure}



\`E facile vedere che la \Index{ROM} dovr\`a effettuare la conversione
indicata nella tabella~\ref{tab_rom_1}.

\begin{table}[htb!]
        \begin{center}
                \begin{tabular}{| c | c c c | c | c c c c c c c |}
\hline n & $n_2$ & $n_1$ & $n_0$ & m & $m_6$ & $m_5$ & $m_4$ & $m_3$ &
 $m_2$ & $m_1$ & $m_0$ \\ \hline 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0
 & 0 & 1 \\ 1 & 0 & 0 & 1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ 2 & 0 & 1
 & 0 & 2 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ 3 & 0 & 1 & 1 & 6 & 0 & 0 & 0
 & 0 & 1 & 1 & 0 \\ 4 & 1 & 0 & 0 & 24 & 0 & 0 & 1 & 1 & 0 & 0 & 0 \\
 5 & 1 & 0 & 1 & 120 & 1 & 1 & 1 & 1 & 0 & 0 & 0 \\ \hline
                \end{tabular}
\caption{Associazioni tra i numeri tra 0 e 5 ed i rispettivi
  fattoriali espressi in binario.}  \protect\label{tab_rom_1}
        \end{center}
\end{table}


Tale conversione pu\`o essere, con riferimento all figura~\ref{rom_1},
effettuata nel modo seguente. Facendo uso di un decodificatore da 3 a
6 linee, si attiva, per un dato valore di n impostato in ingresso, una
delle sei linee di uscita (indicate in figura con $w_0\cdots w_5$). Ad
esempio, in corrispondenza al codice 011 ingresso, si attiva la linea
$w_3$.
 

\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/rom_1,width=6.0 cm,
height=12 cm, angle=90}}\end{center}
\caption{Struttura che effettua la codifica di
tabella~\ref{tab_rom_1}.}  \protect\label{rom_1}
\end{figure}

 
A questa linea un apposito \Index{codificatore} associa (cio\`e genera
in uscita) il codice 0000110, cio\`e il valore decimale 6, che viene
reso disponibile sulle linee ($m_0 \cdots m_6$).  Analoga
corrispondenza viene stabilita per gli altri valori applicati in
ingresso, indicati nella tabella.
 
La struttura dei circuiti di decodifica e di successiva codifica pu\`o
esser realizzata sulla falsa riga di quelle indicate rispettivamente
nelle figure~\ref{decod_4_10-2} e~\ref{matrice}. Da notare che il
circuito di figura~\ref{decod_4_10-2} \`e relativo ad una decodifica da
4 a 10 linee, mentre nel nostro esempio \`e sufficiente un
decodificatore da 3 a 6 linee. Il circuito di decodifica potrebbe
essere quello mostrato nella parte sinistra della
figura~\ref{decod_3_6}.


\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/decod_4_10,width=9.0 cm,
height=7.5 cm}}\end{center}
\caption{Circuito che effettua una decodifica da 4 a 10 linee.}
\protect\label{decod_4_10-2}
\end{figure}

\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/decod_3_6,width=9.0 cm,
height=14 cm,angle=90}}\end{center}
\caption{Circuito che effettua la decodifica da 3 a 6 linee e la
  codifica.}  \protect\label{decod_3_6}
\end{figure}

Infatti, \`e immediato verificare che le porte \Index{AND} mostrate in
figura implementano la funzione di \emph{\Index{decoding}} indicata
nelle prime quattro righe della tabella.  Ad esempio, per $n \equiv
n_2,n_1,n_0=0,1,1$, si vede che \`e $W_3=\overline{n}_2 \cdot n_1
\cdot n_0\;=\;1$, mentre $W_0=W_1=W_2=W_4=W_5=0$.

La parte destra della medesima figura svolge la funzione di
codifica. Ad esempio possiamo vedere che, nel caso appena esaminato,
in cui $W_3=1$, i diodi collegati alle linee (colonne) $m_1$ ed $m_2$,
conducono, con che $m_1=m_2=1$, mentre le rimanenti colonne rimangono
collegate a massa (livello 0). Avremo quindi:
\[
m\;=\;0,0,0,0,1,1,0\;=\;6_{10}
\]
  
che \`e appunto 3! \`E facile verificare il funzionamento in tutti gli
altri casi.
  
Notiamo che l'architettura utilizzata per il \Index{decodificatore}
implica una porta AND per ciascuna linea (le linee vengono chiamate
\emph{\Index{word-lines}}, le colonne \emph{\Index{bit-lines}}).
  
Tale architettura diviene costosa se il numero di word-lines \`e
elevato.  Per ovviare a tale problema, si pu\`o far uso di una
decodifica del tipo di quella di figura~\ref{rom_2}, relativa al caso
di una \Index{ROM} da $512 \times 4 \;=\;2048\;bits$ (codice in ingresso di 9
bit con codice d'uscita di 4 bit).  Il decodificatore indicato nel
blocco a sinistra in figura effettua la decodifica dei sei bit meno
significativi, corrispondenti a 64 righe ($W_0-W_{63}$). La matrice di
codifica che segue ha 32 colonne (matrice di $64 \times 32\;=\;2048$
\index{memoria! celle di}celle di memoria).  Poich\'e in uscita sono
richiesti quattro bit alla volta, i quattro blocchi selettori che
seguono il codificatore, ciascuno con otto linee di ingresso,
selezionano, per ciascun valore dei tre bit pi\`u significativi
applicati in ingresso, una delle otto linee.
   
\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/rom_2,width=12.0 cm,
height=10 cm}}\end{center}
\caption{\Index{ROM} da $512 \times 4 \;=\;2048\;bits$ (codice in ingresso di
9 bit con codice d'uscita di 4 bit).}  \protect\label{rom_2}
\end{figure}

Tale tipo di indirizzamento \`e noto come indirizzamento X-Y o
bidimensionale.  Nell'esempio indicato sono necessarie solo 64 porte
AND (o NAND) per la decodifica dei sei bit meno significativi.  In
pi\`u sono necessarie altre porte (36) per i selettori indicati. Il
numero di porte richiesto \`e quindi pari a 100, da confrontare con le
512 necessarie nel caso di una struttura del tipo di quella indicata
in figura~\ref{rom_1}.

Notiamo infine che, anche se per semplicit\`a abbiamo discusso le
matrici di codifica basandoci sull'esempio della \Index{matrice a diodi},
questa \`e stata oramai sostituita da matrici in cui la funzione dei
diodi \`e svolta da transistor o da MOSFET.
   
\subsection{\Index{ROM} programmabili}

Le ROM che abbiamo descritto nella sezione precedente sono fornite, su
specifica dell'utente, dai produttori. Le caratteristiche di tali ROM,
cio\`e le informazioni in esse memorizzate, sono definite al momento
della realizzazione e non possono essere alterate successivamente.
\`E possibile far uso, in alternativa, di ROM programmabili
dall'utente, note come \Index{PROM} (field-programmable ROM). Una PROM, al
momento della produzione, contiene tutte le possibili connessioni
(diodi o transistor) interne. L'utente pu\`o, facendo uso di
un'apposito hardware, bruciare o eliminare tutte le connessioni non
volute, in modo da ottenere la tabella di conversione (corrispondenze
ingressi-uscite) desiderata.  L'hardware necessario \`e noto come
''programmatore di \Index{PROM}'' . In una generica PROM, una volta effettuata
la programmazione non \`e pi\`u possibile modificarla.

Esistono tuttavia delle \Index{PROM} in cui la cancellazione dell'informazione
e quindi la modifica della programmazione, \`e possibile. In questa
variet\`a di PROM (note come EPROM o ``erasable PROM'') la
cancellazione dei dati avviene per esposizione alla luce
ultravioletta. Ci\`o richiede che il \Index{chip} venga posto, per
tempi relativamente lunghi (circa un'ora), in un apposito dispositivo
dove sia presente una sorgente UV. Dopo la riprogrammazione, la parte
sensibile della EPROM deve esser protetta (mediante un nastro adesivo
che non trasmetta l'UV) per evitare che l'eventuale esposizione a
radiazione UV (quale quella emessa dal Sole) possa cancellare
l'informazione.

Per facilitare il processo di riprogrammazione sono state realizzate
delle EPROM in cui la cancellazione dei dati viene effettuata con
l'applicazione di una tensione dell'ordine di 10~V agli elementi che
le costituiscono. Queste sono note come ``electrically erasable
\Index{PROM}'s'' o anche $\Index{EEPROM}$ o $E^2PROM$.

\section{Memorie ad \Index{accesso casuale}}\label{RandomAccessMemory} 

Le \Index{ROM}, come detto, sono utilizzate in tutte quelle
\Index{applicazioni} in cui sia necessario disporre di una \Index{memoria} che
conservi permanentemente l'informazione. In moltissime situazioni \`e
invece necessario modificare di continuo l'informazione
memorizzata. Sono quindi necessarie delle memorie che possano esser
\emph{scritte} oltre che \emph{lette}.  Questo \`e ad esempio il caso
di un computer, che elabora dei dati e memorizza i risultati
dell'elaborazione per una successiva stampa, trasmissione o nuova
elaborazione. In tali casi si fa uso di \emph{memorie ad
\Index{accesso casuale}}, note come \Index{RAM}, o delle numerose varianti di
queste.

La denominazione \emph{\Index{accesso casuale}} sta ad indicare il
fatto che \`e possibile specificare un generico indirizzo in ingresso
per avere in uscita la parola memorizzata a tale indirizzo. Ci\`o
distingue questo tipo di memoria da un \Index{nastro magnetico}, in cui
occorre svolgere tutta la parte di nastro che precede quella dove la
parola voluta \`e stata memorizzata. A rigore, anche la ROM \`e una
memoria ad accesso casuale, nel senso appena detto per la RAM.

Esistono molti tipi di \Index{RAM} diverse. Le SRAM (Static RAM) hanno come
elemento di memoria il Flip-Flop. Esse conservano l'informazione
memorizzata fino a che non si interrompa l'alimentazione.  Le DRAM
(Dinamic RAM) sfruttano come elemento di memoria la carica accumulata
su di un dispositivo semiconduttore, integrato in un \Index{chip}.
Tale cella di memoria \`e assimilabile ad un minuscolo condensatore,
di dimensioni micrometriche.  Le DRAM sono disponibili anche con un
numero di \index{memoria! celle di}celle di memoria molto elevato, ma
hanno lo svantaggio di richiedere un continuo \emph{refresh}, cio\`e
debbono, ad intervalli di qualche millisecondo, essere
\emph{ricaricate}.

Esiste infine un tipo di \Index{RAM} statica che conserva l'informazione
quando l'alimentazione venga interrotta. Questa \`e nota come NVRAM o
NVSRAM, sigla che sta per Non Volatile RAM. Essa nasce dall'unione di
una RAM statica con una \Index{EEPROM}, integrate sul medesimo
\Index{chip}.

Un esempio di RAM statica disponibile commercialmente \`e la P4C148
della Performance Semiconductor Corporation. Questa \`e una RAM da
4096 bit (organizzati in una matrice di $1024 \times 4$). La struttura
del blocco funzionale \`e mostrata in
figura~\ref{ram_functional_block}, mentre la configurazione dei pin
\`e mostrata in figura~\ref{ram_pin_config}.

\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/ram_functional_block,width=10.0 cm,
height=10 cm}}\end{center}
\caption{Struttura della \Index{RAM} commerciale a 4096 bit P4C148.}
\protect\label{ram_functional_block}
\end{figure}

\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/ram_pin_config,width=10.0 cm,
height=10 cm}}\end{center}
\caption{Configurazione dei pin della \Index{RAM} commerciale a 4096 bit
P4C148.}  \protect\label{ram_pin_config}
\end{figure}

L'indirizzo (10 bit) viene impostato sulle linee $A_0-A_9$, mentre la
parola (a 4 bit) da scrivere/leggere, viene impostata sulle linee
$(I/O)_4-(I/O)_1$.

Se l'ingresso indicato con $\overline{CE}/\overline{CS}$ (Chip
\Index{Enable}/Chip Select) \`e \emph{alto}, l'uscita \`e in uno stato
di ``\Index{alta impedenza}'', qualunque siano i segnali sulle linee
d'ingresso/uscita e sulla linea $\overline{WE}$ (Write Enable). In
questo stato il consumo da parte del \Index{chip} \`e fortemente
ridotto. Se si vuole scrivere dati in \Index{memoria} occorre mettere al
livello \emph{basso} l'ingresso $\overline{CE}/\overline{CS}$ come
pure quello di $\overline{WE}$ dopo avere impostato i dati sugli
ingressi $I/O$ e l'indirizzo sugli ingressi $A$. Per leggere i dati,
sempre mettendo \emph{basso} l'ingresso $\overline{CE}/\overline{CS}$,
occorre mettere alto l'ingresso $\overline{WE}$ (cio\`e
disabilitarlo). Questa \Index{RAM} \`e molto rapida (tempi di accesso compresi
tra 10 e 25~ns).

Tra le molte \Index{applicazioni} di una RAM, vale la pena di
menzionare quella come \emph{\Index{shift-register}}.  Occorrer\`a, come
mostrato in figura~\ref{ram_as_shift} far uso di un contatore esterno
per generare \index{indirizzo}indirizzi successivi della \Index{RAM}. Quando
arriva un impulso di clock, il registro in ingresso (costituito da
quattro FF di tipo D) carica i 4 bit in Q. L'invertitore fa si che il
contatore agisca solo quando il segnale di clock va \emph{basso}. Il
sistema effettua quindi successivi shift di 4~bit in parallelo.

\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/ram_as_shift,width=12.0 cm,
height=7 cm}}\end{center}
\caption{Utilizzo di una \Index{RAM} come \emph{shift-register}.}
\protect\label{ram_as_shift}
\end{figure}


\section{Matrici logiche\index{matrice logica} programmabili}

In parallelo alle \Index{PROM} ed alle \Index{RAM}, hanno avuto un rapido sviluppo
negli ultimi decenni sistemi costituiti da matrici di \Index{porte logiche} i
cui elementi possono essere, facendo uso di appositi programmi,
opportunamente collegati tra loro in modo da implementare funzioni
logiche complesse. Appartengono a tale categoria le \Index{PAL} (Programmable
Array Logic) le \Index{PLA} (Programmable Logic Array) le \Index{FPGA} (Field
Programmable Gate Arrays) etc. In questa sezione ci occuperemo delle
PLA.

Queste hanno molte similarit\`a con le PROM, per cui pu\`o esser utile
iniziare la discussione partendo dalla struttura della \Index{PROM}. Questa,
come si \`e visto, pu\`o essere schematizzata come un
\Index{decodificatore} accoppiato ad un \Index{codificatore}. Il
decodificatore \`e costituito da una matrice di porte AND, il
codificatore da una matrice di \Index{OR} (che negli esempi esaminati era
realizzata con diodi). In un PROM ancora non programmata, tutte le
connessioni delle porte \Index{AND} e tutte quelle delle porte OR sono
presenti. Si consideri ad esempio il circuito mostrato in
figura~\ref{and-or_1}, che rappresenta una matrice $2 \times 2$.

\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/and-or_1,width=10.0 cm,
height=10 cm}}\end{center}
\caption{Esempio di \Index{PROM} non ancora programmata: matrice $2 \times 2$
  con tutte le connessioni presenti sia nel \Index{decodificatore},
  che nel codificatore.}  \protect\label{and-or_1}
\end{figure}


Qui le crocette indicano i collegamenti esistenti. L'assenza di una
crocetta star\`a a significare un collegamento interrotto. Il circuito
di figura \`e una schematizzazione di quello reale. Ciascuna delle
porte \Index{AND} del circuito avr\`a in realt\`a quattro ingressi
($A,B,\overline{A},\overline{B}$). L'eliminazione di uno o pi\`u dei
collegamenti (operazione che nella EPROM pu\`o esser realizzata in
laboratorio) implica l'eliminazione del relativo ingresso. Analoga
osservazione va fatta per le porte OR, che sono, nel nostro esempio, a
quattro ingressi, cio\`e ricevono le uscite delle porte AND 1,2,3,4 (
almeno fino a che non siano eliminati uno o pi\`u dei relativi
collegamenti).

Normalmente, in una \Index{PROM} (o EPROM) il piano \Index{AND} \`e fisso,
cio\`e non tutti i collegamenti (le crocette nel grafico) sono
presenti e quelli presenti non sono modificabili, mentre il piano \Index{OR}
contiene tutti i collegamenti. In una \Index{PLA} sono presenti tutti i
collegamenti del piano AND e tutti quelli del piano OR. In aggiunta,
in una PLA sono presenti sul medesimo \Index{chip} un certo numero di
Flip-Flop di tipo D (registri) a cui sono collegate le uscite delle
porte OR. Gli output di tali registri (nonch\'e i loro complementi)
sono disponibili, insieme ai normali pin di ingresso, come inputs per
la \Index{matrice logica}. Ci\`o consente di realizzare, oltre a logiche
\emph{combinatorie} anche logiche \emph{sequenziali}.



Ammettiamo di voler realizzare, a partire dalla \Index{PLA} di figura, un
circuito (combinatorio) che fornisca:
\[
Y_1=A \oplus B
\]
\[
Y_0=A + B
\]
cio\`e l'OR esclusivo e l'OR. Per ottenere ci\`o \`e sufficiente, come
\`a facile verificare, eliminare alcuni dei collegamenti, come
mostrato nella figura~\ref{and-or_2}.

\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/and-or_2,width=10.0 cm,
height=10 cm}}\end{center}
\caption{\Index{PLA} che realizza l'OR esclusivo per l'uscita $Y_1$ e l'OR per
l'uscita $Y_0$.}  \protect\label{and-or_2}
\end{figure}

Vediamo che con poche modifiche \`e possibile implementare funzioni
logiche di tipi diversi, a partire da un circuito dato.  Un ulteriore
esempio, relativo ad una matrice PLA $3 \times 4$ \`e mostrato in
figura~\ref{and-or_3}

\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/and-or_3,width=10.0 cm,
height=10 cm}}\end{center}
\caption{Esempio di matrice \Index{PLA} $3 \times 4$.}
\protect\label{and-or_3}
\end{figure}


In aggiunta alle \Index{PLA} sono disponibili in commercio le cosiddette \Index{PAL}
(Programmable Array Logic)~(\footnote{Storicamente, le PLA hanno fatto
la loro prima comparsa nel 1972, mentre le PAL sono divenute standard
nel 1980. Le prime \Index{FPGA}, che esamineremo dopo, sono state
introdotte dalla \Index{Xilinx} nel 1985}). Queste differiscono dalle PLA per
il fatto di avere la matrice delle porte \Index{AND} programmabili
mentre \`e fissata la matrice delle porte \Index{OR}. Sia le \Index{PLA} che le PAL
sono disponibili sia in forma combinatoria (cio\`e senza registri) che
in forma sequenziale (con registri).

\subsection{Matrici per applicazioni sequenziali\index{applicazioni! sequenziali}}

La differenza tra la struttura combinatoria e quella sequenziale \`e
di notevole importanza.  Un circuito combinatorio fornisce infatti
un'uscita che \`e funzione esclusivamente dei segnali presenti in
quell'istante sui pin d'ingresso. Un circuito sequenziale invece
fornisce in uscita, all'arrivo di un segnale di clock, dei livelli che
sono funzioni \emph{sia dei segnali presenti sui terminali d'ingresso
che dei valori presenti alle uscite subito prima dell'arrivo
dell'impulso di clock}.

Esaminiamo, come esempio di circuito sequenziale, il contatore in base
3 mostrato in figura~\ref{div_3}. Indicheremo con l'indice 1 il FF di
sinistra, con l'indice 2 quello di destra.

\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/div_3,width=10.0 cm,
height=6 cm}}\end{center}
\caption{Esempio di circuito sequenziale: contatore in base 3.}
\protect\label{div_3}
\end{figure}


Questo \`e un caso molto particolare di circuito sequenziale, poich\'e
l'unico ingresso esterno \`e quello di clock. La porta NOR di figura
riceve in ingresso l'uscita di entrambi i FF. Ammettiamo che lo stato
iniziale del sistema sia quello con $Q_1$=0, $Q_2$=0. Con ci\`o avremo
$D_2$=1 prima dell'arrivo del primo impulso di clock, come mostrato in
tabella~\ref{tab_logici_more_1}.

\begin{table}[htb!]
  \begin{center}
    \begin{tabular}{| c | c c | c c |}
\hline clock & $D_1$ & $D_2$ & $Q_1$ & $Q_2$ \\ \hline & 0 & 1 & 0 & 0
\\ $\uparrow$ &1 & 0 & 0 & 1 \\ $\uparrow$ &0 & 0 & 1 & 0 \\
$\uparrow$ &0 & 1 & 0 & 0 \\ \hline
    \end{tabular}
    \caption{\index{tabella delle verit\`a}Tabella delle verit\`a per il contatore in base 3
    mostrato in figura~\ref{div_3}.}
    \protect\label{tab_logici_more_1}
  \end{center}
\end{table}


All'arrivo dell'impulso di clock, $D_1$ sar\`a trasferito in $Q_1$
(cio\`e $Q_1$=0) e $D_2$ in $Q_2$ (cio\`e $Q_2$=1). Avremo cos\`i la
situazione mostrata nella seconda riga della tabella. Il successivo
impulso di clock porta $D_1$ (che \`e 1) in $Q_1$, e $D_2$ (che \`e 0)
in $Q_2$. La situazione sar\`a ora quella mostrata nella terza riga
della tabella. Infine il terzo impulso di clock ripristina lo stato
iniziale: $Q_1$=0, $Q_2$=0. Il conteggio ora riprende.

Lo schema di un sistema sequenziale, nel caso generale, \`e quello
mostrato in figura~\ref{and_or_sequenziale}.

\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/and_or_sequenziale,width=9.0 cm,
height=10 cm}}\end{center}
\caption{Schema generale di un sistema sequenziale.}
\protect\label{and_or_sequenziale}
\end{figure}

Le linee solide indicate nella figura costituiscono i ``bus'' che
forniscono da un lato in input, alla parte combinatoria del circuito,
le uscite dei registri (Flip-Flop\index{Flip Flop}) e dall'altro caricano nei registri
le uscite delle porte logiche (gli OR).

In un circuito sequenziale il sistema passa attraverso una sequenza di
stati o livelli dei suoi componenti. Se esso ha raggiunto un certo
stato e se riceve da eventuali linee esterne opportuni impulsi, esso
potr\`a passare ad uno di k possibili stati diversi, a seconda dello
stato in cui esso \`e, e dei valori presenti sulle linee di ingresso
esterne. Un sistema di questo tipo \`e descrivibile come una
\emph{\Index{macchina a stati finiti}}. Esempi sono l'elettronica che
controlla la distribuzione delle bibite in un distributore automatico,
il sistema di controllo del ciclo in una lavabiancheria, di un
semaforo etc.

Pu\`o accadere che un sistema di questo tipo venga a raggiungere uno
\emph{stato stabile}, cio\`e uno stato da cui esso non potr\`a pi\`u
uscire. Tali situazioni, se si vuole che la macchina funzioni come
programmato, vanno opportunamente evitate. Nell'esempio fatto prima,
del divisore per 3, ci\`o non accade. In effetti, anche se il sistema
si trovasse inizialmente nello stato $Q_1=Q_2=1$, non previsto, dopo
il successivo impulso di clock esso passerebbe nello stato $Q_1=0$,
$Q_2=0$, dopo di che ricomincerebbe con la sequenza gi\`a vista.

Esaminiamo ancora, come esempio dell'uso di FF in circuiti
sequenziali, un \emph{\Index{temporizzatore}}.

Ammettiamo che un certo strumento generi, in occasione di un
\Index{evento} esterno (l'accensione di un allarme, il passaggio di
una particella, un brusco salto di tensione su di una linea) un
impulso, e che questo impulso debba esser \emph{letto} da un sistema
``sincrono'', cio\`e da un sistema digitale in cui tutte le
transizioni tra stati hanno luogo in sincronia con un segnale di clock
fissato. L'evento esterno avviene invece ad un istante casuale e non
\`e quindi sincrono con tale clock. Se vogliamo che l'impulso generato
possa agire sul sistema, dobbiamo in qualche modo
``sincronizzarlo''. Cio\`e dobbiamo,a partire da esso, generare un
altro impulso che sia sincrono con l'impulso di clock che arriva
subito dopo l'\Index{evento}. Ci\`o pu\`o esser ottenuto facendo uso
del circuito di figura~\ref{sincronizer}, che fa uso di un FF.

\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/sincronizer,width=8 cm,
height=5.5 cm}}\end{center}
\caption{Circuito sequenziale che funziona da \Index{temporizzatore}.}
\protect\label{sincronizer}
\end{figure}

L'\Index{evento} esterno aziona, per un breve intervallo di tempo, un
deviatore T, portandolo nella posizione A e riportandolo poi, dopo un
tempo $t_D$ (maggiore della durata dell'impulso di clock) nella
posizione B. Il sistema costituito dalle due porte NAND accoppiate
generer\`a un livello alto sull'ingresso D del FF, di durata
$t_D$. Tale segnale non arriver\`a per\`o in Q, e quindi all'uscita
della porta AND, se non all'arrivo del successivo impulso di clock
(nel caso di figura, sul fronte di salita di questo). Vediamo cos\`i
che l'impulso in uscita dalla porta AND \`e sincrono con il clock. Il
funzionamento del circuito \`e visibile in
figura~\ref{sincronizer_out}.

\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/sincronizer_out,width=10.0 cm,
height=9 cm}}\end{center}
\caption{Segnali di input ed output per il \Index{temporizzatore} di
  figura~\ref{sincronizer}.}  \protect\label{sincronizer_out}
\end{figure}

\`E possibile realizzare un circuito sequenziale anche facendo uso di
soli FF, cio\`e senza l'uso di \Index{porte logiche} (AND, NAND etc.). Vediamo
ad esempio un contatore sincrono in base 3, che fa uso di solo due
FF~JK, come mostrato in figura~\ref{div_3_nogates}.


\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/div_3_nogates,width=8.0 cm,
height=5 cm}}\end{center}
\caption{Circuito sequenziale, implementato con soli FF, che funziona
  come \Index{contatore sincrono} in base 3.}
  \protect\label{div_3_nogates}
\end{figure}

\`E facile verificare, come mostrato nella
tabella~\ref{div_3_nogates_table} ed in
figura~\ref{div_3_nogates_out}, il funzionamento del circuito.

\begin{table}[htb!]
  \begin{center}
    \begin{tabular}{| c c c c c c c c c |}
\hline ck & $J_1$ & $K_1$ & $J_2$ & $K_2$ & $Q_1$ & $\overline{Q}_1$ &
$Q_2$ & $\overline{Q}_2$ \\ \hline - & 0 & 1 & 1 & 1 & 0 & 1 & 0 & 1
\\ $\downarrow$ & 1 & 1 & 1 & 1 & 0 & 1 & 1 & 0 \\ $\downarrow$ & 0 &
1 & 0 & 0 & 1 & 0 & 0 & 1 \\ $\downarrow$ & 0 & 1 & 1 & 1 & 0 & 1 & 0
& 1 \\ \hline
    \end{tabular}
    \caption{\index{tabella delle verit\`a}Tabella delle verit\`a relativa al contatore sincrono in
    base 3 di figura~\ref{div_3_nogates}.}
    \protect\label{div_3_nogates_table}
  \end{center}

\end{table}


Vediamo infatti dalla tabella che dopo il terzo impulso (fronte di
discesa) di clock, il sistema torna nello stato iniziale. Esaminiamo
pi\`u in dettaglio il comportamento. Se lo stato iniziale \`e quello
con $Q_1=Q_2=0$, avremo $\overline{Q}_1=1$. Vediamo allora che \`e
$J_2=K_2=1$, mentre $J_1=Q_2=0$. IL primo impulso di clock trova il
secondo FF pronto ad eseguire un cambiamento di stato (toggle), mentre
l'uscita del primo sar\`a ancora 0. Avremo cos\`i: $J_1=Q_2=1$,
$\overline{Q}_2=0$, $Q_1=0$, $\overline{Q}_1=J_2=K_2=1$. Il secondo
impulso di clock trover\`a che ora il primo FF \`e in condizione di
``toggle'', come continua ad esserlo il secondo. La transizione
causata dal clock porter\`a quindi a: $Q_1=1$, $Q_2=0$ e quindi:
$J_1=Q_2=0$, $Q_1=1$, $\overline{Q}_1=0$. Ora il secondo FF non \`e
pi\`u in condizione di ``toggle'', n\`e lo \`e il primo. La
transizione causata dal clock porter\`a allora a $Q_1=0$,
$\overline{Q}_1=1$, mentre $Q_2$ e $\overline{Q}_2$ rimangono
inalterati (essendo $J_2=K_2=0$). Abbiamo cos\`i l'ultima riga della
tabella, identica alla prima. Il ciclo ricomincia quindi dopo tre
cicli di clock.




\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/div_3_nogates_out,width=8.5 cm,
height=9 cm}}\end{center}
\caption{Segnali di input ed output relativi al contatore sincrono in
    base 3 di figura~\ref{div_3_nogates}.}
    \protect\label{div_3_nogates_out}
\end{figure}



\section{Gli integrati \Index{FPGA}}

Gli FPGA (Field Programmable Gate Arrays) sono stati introdotti nel
1985 dalla \Index{Xilinx} Inc.. Essi hanno incontrato una larghissima
diffusione grazie alla loro grande versatilit\`a e relativa facilit\`a
d'uso. Essi, al pari delle \Index{PAL}, \Index{PLA}, EPROM, \Index{EEPROM}, possono
essere programmati in modo da rispondere a tutto un campo di
\Index{applicazioni} particolari. Esistono in commercio FPGA con
strutture e caratteristiche diverse tra loro. Come il nome ci dice, si
tratta di circuiti programmabili ``sul campo'', vale a dire che non
occorrono \emph{programmatori} appositi, come nel caso delle EPROM.

Questi integrati contengono milioni di transistor, che realizzano un
elevato numero di circuiti logici i quali possono essere collegati tra
loro facendo uso di commutatori programmabili.  Gli FPGA sono una
variet\`a di PLD (Programmable Logic Devices). Tuttavia, a differenza
dei PLD, gli FPGA non contengono porte \Index{AND} ed OR. Al loro
posto essi contengono dei \Index{blocchi logici} costituiti da
``\index{lookup table}Lookup Tables'', che vengono adoperati per implementare
\Index{funzioni logiche}. Tali blocchi logici sono accessibili tramite
blocchi di input/output (I/O) che corrono lungo la periferia del
\Index{chip} e sono connessi tra loro per mezzo di blocchi di
interconnessione, come \`e possibile vedere in
figura~\ref{fpga_layout_altera}. Una tipica FPGA contiene da circa
10,000 a milioni di elementi equivalenti a porte logiche, con
interconnessioni programmabili dall'utente, oltre a centinaia di
migliaia di \index{memoria! celle di}celle di memoria. Una qualsiasi
funzione logica, sia di tipo combinatorio che sequenziale, puo' essere
implementata facendo uso delle intrinseche strutture logiche quali le
\index{celle logiche}Celle Logiche (LC) o \index{blocchi
logici}Blocchi Logici (LB). Le LC (LB) sono come delle piccole \Index{ROM}, in
cui sono immagazzinate delle \index{lookup table}Lookup Tables (LUT) che contengono i
valori delle funzioni logiche elementari, per ogni combinazione di
valori impostati in ingresso.


\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/fpga_layout_altera,width=10.0 cm,
height=10 cm}}\end{center}
\caption{Struttura a blocchi di un \Index{FPGA}.}
\protect\label{fpga_layout_altera}
\end{figure}

La figura~\ref{fpga_internal_architecture} mostra un po pi\`u in
dettaglio la struttura di una tipica FPGA. Si possono vedere le celle
logiche, le interconnessioni, le celle di I/O e la memoria. Si vede
anche il dettaglio di una tipica cella logica, costituita in questo
esempio da tre ``generatori di funzioni logiche'' (basati su
lookup-tables\index{lookup table}) ed un FF di tipo D.

La variet\`a delle ``architetture'' disponibili in commercio \`e
enorme. Esse differiscono sia nelle dimensioni che nella struttura
delle LC e delle interconnessioni. Alcune LC si riducono
all'equivalente di porte NAND a due ingressi, altre hanno una
struttura pi\`u complessa e possono esser dotate di Multiplexers e di
Look-Up Tables\index{lookup table} (LUT). In alcune \Index{FPGA} un blocco logico
corrisponde ad una intera struttura del tipo di una \Index{PAL}. In ogni caso,
una caratteristica comune alla pi\`u gran parte delle architetture \`e
la presenza di FF di tipo D in ciascuna LC.

\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/fpga_internal_architecture,width=10.0 cm,height=10 cm}} 
\end{center} 
\caption{Struttura a blocchi di un \Index{FPGA}, con il dettaglio di
  una cella logica.}  \protect\label{fpga_internal_architecture}
\end{figure}

\subsection{Gli \Index{FPGA} della \Index{Xilinx}}

Descriveremo ora, a titolo di esempio, le caratteristiche di una FPGA
prodotta dalla Xilinx.

Tale FPGA ha tre elementi configurabili principali: i Blocchi
Logici\index{blocchi logici} Configurabili (CLB), i Blocchi di
Input-Output (IOB) e le Risorse Programmabili di Interconnessione IPR.
I CLB costituiscono gli elementi funzionali per costruire la logica
voluta dall'utente. Gli IOB forniscono l'interfaccia tra i pins
dell'integrato e le linee interne di segnale. Le IPR forniscono i
percorsi di collegamento per connettere gli ingressi e le uscite dei
CLB e degli IOB alle reti appropriate. \`E possibile programmare le
\index{memoria! celle di}celle di memoria statica interna per
determinare le funzioni logiche da svolgere come pure i collegamenti
esterni dell'\Index{FPGA}.

La figura~\ref{fpga_clb_intercon} mostra una parte dei \Index{blocchi
logici} e delle relative interconnessioni di un \Index{FPGA}. Tutte le
connessioni interne sono composte di segmenti metallici con punti di
contatto programmabili, per implementare i collegamenti desiderati. Le
IPR sono sovrabbondanti, in modo da consentire un'implementazione
efficiente dei collegamenti. Vi sono quattro tipi diversi di
interconnessioni, tre delle quali si distinguono solo per la lunghezza
dei segmenti: linee di lunghezza singola, di lunghezza doppia e linee
lunghe. In aggiunta esistono otto linee globali, adoperate per clocks
o segnali di controllo globali.

\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/fpga_clb_intercon,width=8.0 cm,
height=7 cm}}\end{center}
\caption{Blocchi logici\index{blocchi logici} ed interconnessioni di
un \Index{FPGA}.}  \protect\label{fpga_clb_intercon}
\end{figure}

Un esempio di CLB \`e quello mostrato in
fig~\ref{fpga_clb_internal}. Ciascun CLB contiene una coppia di FF e
due generatori di funzioni logiche indipendenti (indicati con F e G
nella figura), ciascuno dei quali ha quattro ingressi.  Questi
generatori di funzioni logiche hanno un elevato grado di
flessibilit\`a, grazie appunto alla presenza di quattro ingressi (la
pi\`u gran parte delle porte logiche combinatorie hanno meno di
quattro ingressi).  Tuttavia, un terzo generatore di funzioni logiche
(H) \`e aggiunto, come mostrato in figura. Il generatore H ha due
ingressi. Uno o entrambi questi ingressi possono essere le uscite di F
o G; l'altro (o entrambi) possono essere esterni al CLB. Ne segue che
il CLB pu\`o implementare funzioni di un numero di variabili fino ad
un massimo di 9.

I CLB implementano la parte principale della logica di questo
\Index{FPGA}. La flessibilit\`a e la simmetria dell'architettura dei
CLB facilitano il posizionamento ed i collegamenti in una qualsiasi
applicazione.

La figura~\ref{fpgaxc4000e} mostra pi\`u in dettaglio la struttura
interna del CLB. I due FF possono essere adoperati per immagazzinare i
segnali in uscita dai generatori di funzioni logiche. Tuttavia i FF ed
i generatori di funzioni logiche possono anche essere adoperati
indipendentemente. L'ingresso indicato con DIN pu\`o essere adoperato
come un input diretto per ciacuno dei due FF. Il segnale H1 pu\`o
pilotare l'altro FF attraverso il generatore H. Le uscite dei
generatori di funzioni logiche sono anche disponibili all'esterno del
CLB, facendo uso di due outputs indipendenti da quelli dei FF. Tale
versatilit\`a aumenta la densit\`a di componenti logici e semplifica i
collegamenti.


\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/fpga_clb_internal,width=8.0 cm,
height=8 cm}}\end{center}
\caption{Schema interno di un Blocco Logico Configurabile (BLC) di un
\Index{FPGA}.}  \protect\label{fpga_clb_internal}
\end{figure}


\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/fpgaxc4000e,width=10.0 cm,
height=8 cm}}\end{center}
\caption{Dettaglio della struttura interna di un Blocco Logico
  Configurabile (BLC) di un \Index{FPGA}.}
  \protect\label{fpgaxc4000e}
\end{figure}

\subsection{L'\Index{FPGA} della \Index{ALTERA}}

La \Index{ALTERA} produce \Index{FPGA} con un numero di \Index{celle
logiche} (chiamate Logic Elements dalla ALTERA) che va da circa 500 ad
oltre 12000. Concentreremo la nostra attenzione sul modello denominato
\Index{FLEX 10K}.  La sigla FLEX sta per Flexible Logic Element
Matrix, ed indica una struttura in cui i LE sono a loro volta
organizzati in blocchi di matrici logiche (Logic Array Blocks) o
\Index{LAB} (vedasi la
figura~\ref{fpga_layout_altera_detail}). Ciascun LAB contiene otto LE.
Gli elementi di un dato LAB sono collegati tra loro da una connessione
locale (quindi veloce) detta Local Interconnect. Ciascun LE consiste
di una LUT a quattro ingressi, un FF programmabile, oltre ad un certo
numero di linee dedicate. Gli otto LE di un LAB possono essere
adoperati per creare \Index{blocchi logici} di medie dimensioni
(contatori a 8 bit, decodificatori d'indirizzo\index{decodificatore!
d'indirizzo} o macchine di stato). Pi\`u \Index{LAB} possono esser
uniti insieme per creare blocchi di complessit\`a ancora
maggiore. Ciascun LAB rappresenta l'equivalente di 96 \Index{porte logiche}
effettive.



Come si vede in figura~\ref{fpga_layout_altera_detail}, sono presenti
sul \Index{chip} anche un certo numero di \Index{Embedded Array
Block}s (EAB) che sono costituiti essenzialmente da FF, Multiplexers e
\Index{RAM}. Essi possono essere adoperati per implementare ROM, RAM, Registri
FIFO\index{First-IN First-OUT}, funzioni logiche etc.. Nel caso della
serie \Index{FLEX 10K}, ciascun EAB pu\`o contribuire con
l'equivalente di 100-600 porte logiche, per realizzare funzioni
logiche complesse (moltiplicatori,
\index{microcontrollore}microcontrollori, macchine di stato 
etc.).  Ciascun EAB pu\`o esser adoperato indipendentemente, o diversi
EAB possono esser combinati per implementare funzioni di maggior
complessit\`a.


\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/fpga_layout_altera_detail,width=10.0 cm,height=10 cm}} 
\end{center}
\caption{Struttura di un \Index{FPGA} dell'\Index{ALTERA}.}
\protect\label{fpga_layout_altera_detail}
\end{figure}

La figura~\ref{fpga_flex10k_embedded_array} mostra in dettaglio la
struttura di un EAB.

\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/fpga_flex10k_embedded_array,width=10.0 cm,height=10 cm}} 
\end{center}
\caption{Struttura di un \Index{Embedded Array Block} (EAB) di un
\Index{FPGA} dell'\Index{ALTERA}.}
\protect\label{fpga_flex10k_embedded_array}
\end{figure}

Come accennato, questo \`e un blocco flessibile di \Index{RAM}, dotato di
registri sia alle porte d'ingresso che a quelle d'uscita. Esso pu\`o
essere adoperato per implementare quelle funzioni logiche di maggiore
complessit\`a note come ``megafunzioni''. Ad esempio un EAB pu\`o
essere adoperato per programmare moltiplicatori, filtri digitali,
circuiti di correzione di errori etc.. Le funzioni logiche effettuate
dal EAB vengono implementate, al momento della
programmazione, costruendo delle LUT. Ci\`o rende molto pi\`u veloci i
tempi di calcolo. Un EAB pu\`o anche essere adoperato come RAM, con
una struttura di 256 parole di 8 bit, 512 da 4, 1024 da 2 o 2048 da 1.
Inoltre pi\`u EAB possono esser combinati insieme per realizzare dei
blocchi di RAM di dimensioni maggiori.

Un software dedicato aiuta l'utente a realizzare tutte le operazioni
volute. Nei pacchetti software forniti sono gi\`a implementate
moltissime delle funzioni logiche, comprese quelle di maggiore
complessit\`a.

La figura~\ref{fpga_flex10k_lab} mostra la struttura di un insieme di
LE, cio\`e di un \Index{LAB}.

Ciascun LAB consiste di otto LE, nonch\'e dei relativi ingressi e
delle interconnessioni locali.  Inoltre esso fornisce quattro segnali
di controllo (con inversioni programmabili) che possono essere
adoperati da tutti e otto gli LE del blocco. Due di questi ingressi
possono essere adoperati come clocks; gli altri due come ingressi di
controllo di \Index{Clear}/\Index{Preset}.


\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/fpga_flex10k_lab,width=10.0 cm,
height=10 cm}}\end{center}
\caption{Struttura di un \Index{LAB} (formato da otto LE) di un
\Index{FPGA} dell'\Index{ALTERA}.}  \protect\label{fpga_flex10k_lab}
\end{figure}


La figura~\ref{fpga_flex10k_logic_element_new} mostra il dettaglio di
un LE. Questo costituisce la pi\`u piccola delle unit\`a logiche
nell'architettura di questo \Index{FPGA}. Ciascun LE contiene una LUT
a quattro ingressi, che costituisce un generatore di funzioni logiche
attraverso il quale \`e possibile calcolare una generica funzione
logica di quattro variabili. In aggiunta, esso contiene un FF
programmabile, dotato di un \Index{Enable} sincrono, e connessioni
da/per altri elementi analoghi.  Il FF pu\`o esser programmato come un
JK, SR, D etc.. Gli ingressi di clock, \Index{Clear} e \Index{Preset} sul FF
possono esser pilotati da segnali esterni globali, da segnali di I/O,
o da altra logica interna.


\begin{figure}[htb!]
  \begin{center}\mbox{\epsfig{file=logici_more/fpga_flex10k_logic_element_new,width=12.0 cm,
height=10 cm}}\end{center}
\caption{Dettaglio della struttrura di un LE di un \Index{FPGA}
dell'\Index{ALTERA}.}  \protect\label{fpga_flex10k_logic_element_new}
\end{figure}


\section{Una semplice applicazione: frequenzimetro digitale} 

La frequenza di un segnale sinusoidale o di un'onda quadra
corrisponde al numero di oscillazioni che si hanno in un secondo. 
Gli strumenti digitali per la misura di frequenze fanno uso di contatori, e
per determinare la frequenza \`e sufficiente abilitare il conteggio
per un intervallo di tempo noto. 
In tali dispositivi \`e presente quindi
una base dei tempi con funzione di orologio; questa frequenza nota
\`e generalmente fornita da un oscillatore al quarzo. 
Esso pilota un circuito divisore la cui uscita costituisce il periodo 
di riferimento e mantiene l'accuratezza dell'oscillatore stesso.
Naturalmente si parte dal presupposto che il segnale di cui si deve
misurare la frequenza sia stabile durante il lasso di tempo necessario al
conteggio; quest'ultimo \`e definito \emph{intervallo di campionamento}.

Le misure che impiegano contatori elettronici sono affette da diverse cause
di errore. 
La prima \`e l'errore di conteggio di $\pm1$ impulso (errore di 
quantizzazione e mancanza di sincronismo). 
Indipendentemente da ogni altra
fonte di errore, tale errore \`e dovuto al fatto che la finestra temporale
del conteggio non risulta necessariamente multipla del periodo degli
impulsi contati, oppure pu\`o non essere esattamente in fase. 
Per ridurre l'incidenza di tale errore bisogna che il numero di impulsi
complessivamente contati nell'intervallo di campionamento sia elevato. 
Tale errore stabilisce in ultima analisi la risoluzione del dispositivo; 
\`e necessario quindi adeguare il periodo di campionamento al valore della
frequenza da misurare. 
La risoluzione di questo tipo di strumento \`e 
comunque ottima per segnali ad alta frequenza.

Un'altra fonte di errore pu\`o essere 
l'instabilit\`a dell'oscillatore che fornisce il clock; il valore della 
frequenza di un oscillatore al quarzo varia principalmente per effetto 
delle fluttuazioni di temperatura e dell'invecchiamento dei componenti. 

Data la struttura di un dispositivo di questo tipo, basata essenzialmente
su di un contatore, \`e chiaro che la frequenza da misurare
non pu\'o superare un valore massimo stabilito dal numero di bit del
contatore. Il numero di conteggi massimi nell'intervallo di campionamento
\`e pari a:

\[
N_{max}\:=\:2^k
\]
dove $k$ \`e il numero di bit del contatore. 
Cos\`\i\ la frequanza massima \'e:

\[
f_{max}\:=\:\frac{2^k}{T_{camp.}}.
\]
Per ovviare a questo problema, generalmente i frequenzimetri digitali sono
preceduti da un \emph{prescaler} che divide per un valore noto la frequenza del
segnale.

\`E possibile implementare un frequenzimetro digitale facendo uso di un
FPGA; il circuito di figura~\ref{scheme_counter_simple} ne definisce la
logica. 
Il segnale, un'onda quadra con valori logici TTL, viene inviato ad
un contatore tramite un pin, indicato con $sig\_in$ in 
figura~\ref{scheme_counter_simple}). 
La frequenza viene quindi misurata e rappresentata come numero
binario sui 13 LED saldati sulla basetta.

\begin{figure}[htp]
  \begin{center}\mbox{\epsfig{file=logici_more/scheme_counter_simple.eps,angle=90,
	width=18.0 cm,height=23.0 cm}}\end{center}
\caption{Frequenzimetro digitale: schematica}
\protect\label{scheme_counter_simple}
\end{figure}

\newpage

Il circuito comprende un contatore a 13 bit con reset asincrono 
($counter13$), che riceve come segnale di clock il segnale di cui 
si vuole misurare la frequenza ($sig\_in$). 
Il contatore conta quanti impulsi del segnale di clock ci sono nel periodo
di tempo in cui \`e abilitato, cio\`e in cui il segnale di clock enable
($clk\_en$ nella figura) \`e nello stato logico alto. 

Il clock enable \`e fornito dalla prima parte del circuito, nella quale
si ha un contatore a 24 bit ($counter24$) modulo $10$ milioni. 
Il segnale di clock per questo contatore \`e ottenuto utilizzando 
l'oscillatore a quarzo montato sulla basetta, il quale ha frequenza 
pari a $10\ MHz$; dato che il contatore si riazzera ogni $10$ milioni 
di impulsi di clock, si hanno uscite tutte nulle ogni secondo. 
Le uscite del $counter24$ sono collegate ad un
$OR$ a 24 ingressi ($or24$) tramite un bus che nel grafico \`e chiamato 
$t\_time[23..0]$; l'uscita dell'$OR$ \`e negata con una porta $NOT$, 
cos\`\i\ il segnale all'uscita di tale porta \`e alto solo in corrispondenza 
dell'azzeramento contemporaneo di tutte le uscite del contatore. 
Quindi il segnale all'ingresso del primo dei $FF$ di tipo $D$ \`e un 
impulso di durata pari al semi-periodo del clock ($50\ ns$) e  
periodo pari ad 1 secondo. Anche il clock di questo $FF$ \`e 
dato dall'oscillatore ed il segnale sull'ingresso $D$ viene trasferito
all'uscita ad ogni fronte di salita del clock. Questa uscita rappresenta il
clock del $FF$ di tipo $D$ che segue, la cui uscita \`e collegata,
tramite una porta $NOT$, al suo ingresso: esso quindi funziona come Toggle e
l'uscita cambia stato ad ogni impulso di clock. 
Ne segue un segnale che \`e un'onda quadra di periodo pari a 2 secondi; 
essa costituisce il \emph{clock enable} del contatore a 13 bit. 

Dato che il \emph{clock enable }resta alto per un secondo, il $counter13$ 
conter\`a quanti impulsi del segnale in ingresso ci sono in un secondo,
cio\`e ne misurer\`a la frequenza. \\
Il periodo di campionamento di un frequenzimetro con queste
caratteristiche \`e pari ad 1 secondo; si sottintende, quindi, che il
segnale sia stabile in questo arco di tempo. 

L'uscita del contatore \`e collegata,
tramite un bus, ad un vettore di 13 $FF$ di tipo $D$ (in figura
$ff13$). 
Il clock di questi $FF$ \`e dato dallo stesso segnale che
costituisce il clock enable del $counter13$ invertito; 
questo significa che l'uscita del $counter13$ viene trasferita
all'uscita dei $FF$ esattamente al termine del conteggio,
quando il clock enable cambia stato. In questo modo il risultato della
``misura'' viene visualizzato in modo stabile e aggiornato ogni 2
secondi. 

Il contatore a 13 bit \`e dotato anche di un reset asincrono il cui
segnale \`e fornito da due $FF$ di tipo $D$ di cui uno con reset 
asincrono (in figura $FF1$). 
Quest'ultimo ha l'ingresso collegato a $VCC$,
quindi sempre nello stato logico alto, ed il clock \`e un'onda quadra 
con periodo 2 secondi, la quale \`e alta quando il clock enable del 
contatore \`e basso, e viceversa; quindi l'uscita diventa alta nello 
stesso momento in cui il $counter13$ smette di contare. 
Essa rappresenta l'ingresso del
secondo $FF$ il cui clock \`e l'oscillatore della basetta, quindi
la sua uscita diviene alta dopo un periodo di clock (100 $ns$) 
dall'istante in cui il contatore viene disabilitato. Questo segnale
costituisce il reset asincrono sia del $conter13$ che dell'$FF1$. 
Il contatore viene cos\`\i\ azzerato 100 $ns$ dopo che ha finito di 
contare e quando ormai il segnale \`e stato trasferito ai 13 $FF$ che lo
visualizzano quindi stabilmente sui 13 LED.

La frequenza massima misurabile con questo circuito \`e pari a $2^k\ =\
8192\ Hz$; esso pu\`o comunque essere facilmente modificato per misurare
anche frequenze pi\`u alte. \\
Ad esempio, se si vuol fare in modo che il circuito abbia due diverse scale, 
una delle quali misuri frequenze 10 volte pi\`u grandi, \`e
sufficiente introdurre anche un altro contatore iniziale ($counter24$) con
modulo 10 volte pi\`u piccolo del primo. In questo caso il periodo in cui
il clock enable \`e alto (intervallo di campionamento), \`e pari a 100
$ns$, cos\`\i\ la frequenza massima misurabile con questa scala \`e pari a
$2^k\ /\ 100\ ns\ =\ 81.920\ Hz$. \\
Si pu\`o fare in modo che le due scale siano alternativamente 
selezionate agendo dall'esterno su uno dei pulsanti della basetta: l'azione
sul tasto deve indirizzare il segnale prodotto da uno o dall'altro
contatore, al clock enable del $counter13$. \\

Nella simulazione di questo circuito conviene sostituire il $counter24$ con
un contatore sempre a 24 bits, ma modulo $10^4$ (come in
figura~\ref{scheme_counter_simple}), per rendere accettabile il tempo
impiegato dal programma. 
Le forme d'onda in tal modo ottenute sono indicate
in figura~\ref{counter_onde}. 
Naturalmente, cambiando il primo contatore, si \`e cambiato
il periodo di campionamento, che \`e passato da 1 $s$, a 1 $ms$, quindi il
numero visualizzato in uscita corrisponde alla frequenza del segnale
espressa in $kHz$. \\

\begin{figure}[h!]
  \begin{center}\mbox{\epsfig{file=logici_more/counter_onde.eps,
	width=12.0 cm,height=3.5 cm}}\end{center}
\caption{Frequenzimetro digitale: segnali ottenuti dalla simulazione}
\protect\label{counter_onde}
\end{figure}

Usando un circuito analogo, in modo molto semplice, \`e possibile fare
anche misure di intervalli di tempo. 
In questo caso il segnale di cui
vogliamo misurare il periodo costituir\`a l'intervallo di campionamento del
segnale di riferimento che \`e dato dall'oscillatore al quarzo. Il
conteggio registrato sar\`a proporzionale all'intervallo di tempo in cui il
contatore \`e rimasto abilitato e quindi fornir\`a una misura del tempo
desiderato. \\ 
\newpage
