# Sistemi digitali

Un sistema o circuito digitale è un sistema dinamico artificiale che manipola in modo numerico (0 e 1) segnali numerici di ingresso, che rappresentano l'informazione da elaborare, per produrre segnali di uscita anch'essi numerici.

## Nascita

L'uomo, anche senza esserne cosciente, ha sempre avuto a che fare con la logica e con essa la logica binaria, il linguaggio comune che usiamo spesso non fa altro che associare un valore di verità ad una frase, la formalizzazione matematica, e quindi l'idea base che ha dato vita a tutti i circuiti digitali antichi e moderni, della parte dell'algebra che opera con soli due valori possibili si può far risalire a George Boole. Se però all'epoca di Boole questi studi attraevano solo i logici matematici, con l'invenzione delle valvole termoioniche e successivamente dei transistori divennero la base dell'elettronica e tuttora descrivono il modo con cui opera qualsiasi calcolatore dalla calcolatrice al Road Runner di Los Alamos.

## Fondamenti

Un circuito digitale opera con numeri che possono assumere solo due valori, alto o basso, 1 o 0, per questo vengono detti numeri binari. Tutte le operazioni che svolgono gli attuali sistemi, anche le più complesse, derivano da tale semplicità.

### Contare in binario

Contare in binario non è molto diverso dal contare in decimale, l'unica differenza è che si hanno 2 simboli invece che 10. Quindi se in decimale si ha:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
ed una volta finiti i simboli si ricomincia da capo aggiungendo una cifra:
10, 11, 12, 13, 14, 15, 16, 17...
in digitale sarà lo stesso:
0, 1
Finiti i simboli si aggiunge una cifra (detta bit)
10, 11 (che si leggeranno uno, zero e uno, uno e non dieci e undici)
e ancora
100, 101, 110, 111...

### Operazioni logiche

Le operazioni logiche che si possono applicare ad un bit sono:
La negazione, detta NOT che trasforma uno zero in un uno e viceversa.
| IN | OUT |
| 0 | 1 |
| 1 | 0 |
Il circuito che realizza questa funzione, detto porta not, è:
* Porta not
La AND che riguarda due o più bit; il risultato di tale operatore è 1 solo se tutti i bit in ingresso sono 1.
| IN | IN | OUT |
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
Il circuito che realizza questa funzione, detto porta AND, è:
* Porta and
La OR che riguarda due o più bit; il risultato di tale operatore è 1 se uno qualsiasi dei bit di ingresso è 1.
| IN | IN | OUT |
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
Il circuito che realizza questa funzione, detto porta OR, è:
* Porta OR
La OR esclusiva, detta XOR; il risultato di tale operatore è 1 se i bit di ingresso sono esclusivamente ad 1.
| IN | IN | OUT |
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
* Porta XOR

### Rappresentare l'informazione

Una successione di bit qualsiasi potrebbe significare qualsiasi cosa, essere una porzione di una riga di codice, una parte di informazione di una immagine oppure un semplice numero, da questa "confusione" nasce l'esigenza di una corretta codifica delle stringhe binarie, ovvero bisogna sapere cosa si vuole rappresentare ed esplicitare come lo si sta facendo affinché tutti interpretino bene i dati che stanno leggendo.
Si prendano ora in esame solo i numeri interi positivi e relativi decimali.
La prima ed intuitiva regola per rappresentare i numeri interi positivi decimali in binario è peso-posizione, cioè si associa a ciascun numero decimale il suo corrispettivo binario, tale metodo è detto binario naturale
| Decimale | Binario |
| 0 | 000 |
| 1 | 001 |
| 2 | 010 |
| 3 | 011 |
| 4 | 100 |
| 5 | 101 |
| 6 | 110 |
| 7 | 111 |
Da questa semplice tabella è facile vedere la semplice associazione che si fa tra binario e decimale.
Inoltre è possibile capire un'altra semplice regola: In base dieci con una cifra (un bit) posso rappresentare dieci numeri poiché ho dieci diversi simboli (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) In base 2 con un bit posso rappresentare due numeri poiché ho due diversi simboli 0 e 1, quindi posso contare da 0 a 1.
In base dieci con 2 cifre posso contare fino a 99 cioè rappresentare 100 numeri (compreso lo 0), in base 2 con 2 bit posso contare 00, 01, 10, 11 cioè 4 numeri;
Generalizzando questo discorso possiamo concludere che in base B con N bit si possono rappresentare
$B^{N}$ numeri e contare da 0 a $B^{N}-1$
Un occhio di riguardo per il simbolo $10$ (uno, zero) esso in qualsiasi base si conta rappresenta sempre la base, se tradotto in decimale, in numeri:
in base 2, 10 è il decimale 2, infatti se si prova a contare 00 = 0, 01 = 1, 10 = 2!
In base 3, 10 è il decimale 3, 00 = 0, 01 = 1, 02 = 2, 10 = 3!
In base 4, 10 è il decimale 4, 00 = 0, 01 = 1, 02 = 2, 03 = 3, 10 = 4! E così via.
Questa rappresentazione così semplice ha un grosso limite, non riesce a rappresentare numeri negativi! Per ovviare a tale inconveniente è stata inventata la codifica binario naturale modulo e segno. In tale codifica il primo bit di ogni numero rappresenta il segno, se 0 il numero è positivo, se 1 il numero è negativo.
| Decimale | Binario |
| 0 | 000 |
| 1 | 001 |
| 2 | 010 |
| 3 | 011 |
| -0 | 100 |
| -1 | 101 |
| -2 | 110 |
| -3 | 111 |
Anche sapendo rappresentare i numeri negativi, questa codifica non è utilizzata sia perché si perde un bit per rappresentare il segno ma soprattutto perché lo zero è rappresentato due volte!
Un altro passo intermedio verso la codifica "ideale" è stato fatto con l'introduzione del complemento a 1. In questa codifica per passare da numero positivo a numero negativo basta "negare" tutte le cifre:
| Decimale | Binario |
| 0 | 000 |
| 1 | 001 |
| 2 | 010 |
| 3 | 011 |
| -0 | 111 |
| -1 | 110 |
| -2 | 101 |
| -3 | 100 |
Ma anche qui la doppia codifica dello zero rappresenta una debolezza importante.
L'ultimo passo è stato compiuto con la rappresentazione in complemento a 2. Questa codifica si ottiene dal binario naturale in due passi:
* complemento a 1 del numero in BN
* somma con 1 del numero così ottenuto
| Decimale | Binario |
| 0 | 000 |
| 1 | 001 |
| 2 | 010 |
| 3 | 011 |
| -1 | 111 |
| -2 | 110 |
| -3 | 101 |
| -4 | 100 |
Sfrutta tutte le combinazioni possibili con N bit, ed elimina la ridondanza dello zero.

## Sintesi dei circuiti logici combinatori
### Mappe K

Le mappe K è un metodo per determinare la forma minima di una switching expression. Ovviamente a tale risultato si può arrivare applicando in modo corretto l'algebra di Boole.

### Esempi, Mux, Demux, Comparatore

MUX= Multiplexer: un dispositivo che consente di indirizzare in uscita le informazioni presenti su uno degli n ingressi dati tramite l'attivazione degli ingressi di selezione. Il dispositivo si attiva con l'enable.

## Macchina a stati finiti

I blocchi combinatori finora analizzati, per quanto complessi, operano sempre seguendo una tabella di verità, non sono in grado di implemetare una minima intelligenza. In elettronica digitale c'è la necessità di sviluppare degli algoritmi, ovvero una successione temporalmente stabilita di azioni precise e ripetibili dipendenti dagli ingressi dati alla macchina; ovvero c'è la necessità di creare un automa.
Un automa per definizione è costituito da:
* Un insieme di stati interni X = (X0, X1, X2, X3, X4...Xn)
* Un insieme di elementi di ingresso I = (I0, I1, I2, I3, I4...Im)
* Un insieme di elementi di uscita Y = (Y0, Y1, Y2, Y3, Y4...Yk)
* Un insieme di istruzioni o algoritmo.
L'automa evolve da uno stato interno all'altro a seconda degli ingressi, producendo ogni volta il set desiderato di uscite; tale evoluzione è definita temporalmente. Una precisazione importante riguarda l'evoluzione temporale della macchina:
se il registro di stato varia al solo comando di un segnale detto clock allora la macchina si dice sincrona se questo non è vero la macchina si dice asincrona. Preferiremo le macchine sincrone nelle prossime architetture.
Per descrivere tale complessità il metodo più semplice risulta essere la stesura di una A.S.M.(algoritmic state machine) che sarà traducibile in HW poiché si stabilisce una serie di relazioni biunivoche tra elementi circuitali e ASM.
Riassumendo l'automa sarà circuitalmente implementato da una macchina a stati finiti di cui si definiranno:
* la rete combinatoria degli ingressi
* la rete combinatoria delle uscite
* il registro di stato (FF di tipo D)
Secondo il modello di Moore. Tali elementi saranno sintetizzati da mappe K del diagramma di flusso che rappresenta l'algoritmo da eseguire e far eseguire.
Un diagramma di flusso è costituito da 3 blocchi fondamentali:
Blocco di stato, blocco di uscita condizionale e blocco di condizione
Utilizzando tali blocchi si può descrivere qualsiasi algoritmo.
Vediamo l'esempio di un contatore di eventi sincrono. Ipotizziamo di voler contare fino a 3, quindi 4 numeri, che significa come detto prima 2 bit per il conteggio, e ipotizziamo che la macchina debba essere sensibile solo ai cambiamenti di una linea detta go.
Istanziazione e ASM
Nella prima parte dell'immagine si vede l'istanziazione del blocco con tutte le entrate e le uscite.
Nella seconda parte è riportato il diagramma di flusso del contatore sincrono, che effettivamente traduce l'algoritmo in una serie di blocchi, mentre nell'ultima parte è riportata la sintesi del blocco combinatorio di uscita Y0 e del blocco combinatorio di ingresso A (per semplicità non si riportano gli altri, facilmente intuibili da Y0 e A).
Mentre la composizione della mappa K di Y0 è immediata, così non è per PROX.A la tabella della A prossima deve essere completata guardando appunto il prossimo A e non il presente così che la macchina saprà dove deve andare al clock successivo. Una precisazione importante per quanto riguarda il clock macchina, esso detiene sempre il comando totale sull'automa, se teniamo fermo il clock il dispositivo non si muove qualsiasi sia GO; ecco perché tale macchina è detta asincrona! Se però il clock è molto più lento del segnale GO si rischia di perdere degli eventi.
Esistono due soluzioni:
* O si aumenta la frequenza del segnale di clock fino a renderla idonea alla frequenza di GO
* Oppure si aggancia la linea di clock macchina al segnale GO, così la macchina conterà tutte le commutazioni di GO senza problemi... il prezzo da pagare è la perdita di sincronismo, ovvero tale automa non è più una macchina sincrona!
Per risparmiare commutazioni, e quindi energia consumata dai flip flop dei registri di stato, essi possono anche essere codificati secondo 'Grey' ovvero:
00, 01, 11, 10.
Come si vede varia solo uno dei bit alla volta. Con questi metodi è possibile implementare tutte le macchine a stati finiti che la nostra fantasia riesce a generare per ottemperare ai compiti più disparati. In fin dei conti è la macchina a stati finiti il vero cervello di ogni circuito digitale!

## Memorie
### Flip Flop

* latch (ne esistono di vari tipi tipo-D, tipo-SR)
* flip-flop (tipo-D, tipo-SR, tipo-JK, tipo-T)

## VHDL
### Storia

All'inizio degli anni ottanta, il Dipartimento della Difesa americano desiderava creare un linguaggio standard di descrizione e documentazione di sistemi hardware per avere indipendenza nei confronti dei loro fornitori.
Da queste intenzioni nascerà il VHDL (acronimo di VHSIC Hardware Description Language, dove "VHSIC" è la sigla di Very High Speed Integrated Circuits). Nel tempo il VHDL si affermerà sempre di più e nel 1987 verrà normalizzato dall'IEEE (Institute of Electrical and Electronics Engineers).
Nel 1993 una nuova versione dell'IEEE ha permesso di sfruttare a pieno le potenzialità del linguaggio in particolare per:
* La sintesi automatica dei circuiti a partire dalla descrizione
* La verifica delle costruzioni temporanee
* La verifica formale dell'equivalenza dei circuiti
Il VHDL non è un linguaggio direttamente eseguibile ovvero non descrive quali operazioni un esecutore deve svolgere per ricavare il risultato di una elaborazione, bensì descrive gli elementi che costituiscono il circuito digitale in grado di effettuare l'elaborazione richiesta. Una specifica VHDL non è quindi eseguibile e deve essere pensata come qualche cosa di completamente diverso da un programma o un algoritmo, tuttavia può essere simulata mediante opportuni strumenti. Simulare una specifica VHDL significa simulare il comportamento del circuito che la specifica descrive, quindi, ancora una volta, non si tratta di nulla di simile alla esecuzione di un programma.

### Principi di funzionamento

È un linguaggio estremamente ricco e flessibile, permette di fornire specifiche di circuiti digitali a diversi livelli di astrazione, in particolare:
* Al livello più basso di astrazione possiamo vedere un circuito come un grafo in cui i nodi rappresentano elementi logici (semplici o complessi) quali porte logiche, multiplexer, flip-flop oppure interi sottocircuiti, mentre gli archi rappresentano le connessioni tra tali elementi.
* Aumentando il livello di astrazione, si passa dal VHDL gate-level al VHDL RTL (Register Transfer Level) o data-flow. Secondo questo paradigma, la specifica descrive esplicitamente le trasformazioni che i dati subiscono durante la propagazione all'interno del circuito. In particolare, il circuito è visto come un insieme di due tipologie di elementi: reti combinatorie (esprimono in forma esplicita le trasformazioni dei dati mediante espressioni algebriche, espressioni aritmetiche e condizioni) e registri (sono deputati a memorizzare i risultati intermedi di elaborazioni complesse). Questa suddivisione spiega il nome Register Transfer: la specifica infatti esprime come avviene il trasferimento e l'elaborazione dei dati tra i registri della rete.
* Il livello behavioural è il massimo livello di astrazione che il VHDL consente. Esso è in grado di descrivere la funzionalità di un circuito mediante uno o più algoritmi. In questo caso, né la struttura, né le singole trasformazioni che i dati subiscono sono esplicite. In particolare non è esplicito come le varie operazioni ed elaborazioni sono assegnate ai diversi cicli di clock. Non è quindi evidente la struttura mostrata per le descrizioni a livello RTL: sarà lo strumento di sintesi ad effettuare lo scheduling delle operazioni sui vari cicli di clock sulla base di vincoli imposti dal progettista quali ad esempio la frequenza di clock minima oppure l'area massima.
Molto importante, quanto meno per capire meglio il funzionamento di un sintetizzatore digitale, è comprendere che la stessa funzione digitale può essere implementata con diverse soluzioni hardware, ad esempio un multiplexer può essere implementato in due modi:
* Nel modo più semplice, utilizzando la sintesi classica sviluppando, quindi, le mappe K, come in figura in cui è presentato un mux con due linee in ingresso di cui solo una è abilitata in uscita tramite una linea di selezione sopb.
* In un modo alternativo, istanziando un buffer tristate collegato alle due linee sempre tramite un bit di selezione si manda in uscita o l'una o l'altra linea.
Già con questi piccoli esempi ci si rende conto di come diversi sintetizzatori possono produrre hardware diversi con lo stesso codice in ingresso, e questo non accade solo per software diversi (tipo VHDL e verilog) ma anche tra diverse versioni dello stesso software, ecco perché diventa molto importante definire dall'inizio quale e che versione di sintetizzatore digitale si usa.

## Schede elettroniche programmabili

Una FPGA (Field Programmable Gate Array) è un circuito integrato digitale ad alta scala di integrazione gestibile dall'utente. In esso sono state localizzate fisicamente un numero consistentemente grande di insiemi di porte logiche equivalenti e flip-flop. La connessione tra queste unita logiche può essere configurata e riconfigurata (da qui il concetto di programmable) dall'utente attraverso opportuni tools SW per realizzare le funzioni e le funzionalità logiche progettate. Il risultato di questo flusso, definibile come programma di utente o applicativo o file di configurazione, è un file binario che contiene l'immagine virtuale della logica di utente che una volta caricata nel componente scelto fornirà un'immagine reale del progetto.
Il caricamento del file nella fisicità della logica configurabile è quell'operazione definita come programmazione del componente. Possiamo dividere, da un punto di vista didattico, le logiche programmabili in due categorie: PLD (Programmable Logic Device) e FPGA (Field Programmable Gate Array).
Gli FPGA sono formati da blocchi logici combinatori corrdati da FF circondati da una complessa struttura di canali di interconnessione (o routing) segmentati. Il blocco logico di un FPGA è basato sulla look-up table (LUT) che rappresenta una funzione booleana di quattro ingressi e una uscita e il flip flop che rappresenta l'elemento sequenziale anche in questo caso escludibile se necessario.