Progetto ad alto livello di un sistema embedded integrato su unico chip
Specifica e impostazione del progetto ad alto livello di un sistema embedded integrato su unico chip per il controllo degli accessi e delle presenze tramite uno tra 100 codici personali in un complesso costituito da tre edifici ciascuno con un’unica porta di accesso, segnali di richiesta ingresso e uscita da ogni edificio (con dati codice), tre segnali di apertura porte dopo autenticazione e permesso accesso/uscita. A tale scopo viene richiesta la stesura di un elaborato (in formato Word) in cui dovranno essere svolti in sequenza i seguenti punti e la consegna di tutti i file utilizzati per le simulazioni del punto 2).
- Specifica delle funzionalità del sistema, ingressi/uscite, timing constraints. Definizione di un partizionamento in sottosistemi comunicanti (almeno tre) definendone i periodi di esecuzione e i vincoli temporali e definendo il meccanismo per le comunicazioni.
- Per ciascun sottosistema: definire il codice in linguaggio C; verificarne il funzionamento emulando lo scambio dati con l’esterno; stimare il numero massimo di istruzioni ad alto livello per singolo periodo.
- In base ai dati acquisiti nei punti precedenti e alle architetture disponibili proporre e analizzare criticamente diverse soluzioni di partizionamento software/hardware dei sottosisistemi per la realizzazione di un sistema integrato su unico chip discutendo i criteri di scelta.
PUNTO (1)
Le funzionalità del sistema possono essere divise come:
• immissione del codice personale d’ingresso ai locali
• controllo presenza della persona e conseguente ingresso/uscita
• valutazione dell’edificio a cui si vuole accedere
• apertura porte relative
• aggiornamento di un database sulle presenze negli edifici
Ingresso/Uscita : il sistema è composto da tre edifici, ognuno avente una sola porta porta di accesso, questo significa che ogni volta che si digita il proprio codice (o si passa un badge magnetico con il codice impresso sopra) viene rilevato l’edificio e la porta corrispondente da aprire, se lo stato della persona in precedenza era “PRESENTE” allora la richiesta è da considerarsi di uscita, altrimenti si tratta di un entrata.
Timing constraints : il software è soggetto a ritardi dovuti alle seguenti variabili temporali:
• tempo di rilevamento del codice inserito
• tempo di confronto codice inserito nel database e verifica dell’edificio
• apertura porta corrispondente oppure segnale di “WARNING” nel caso la persona avesse sbagliato la digitazione del codice (o il passaggio del badge)
• tempo di aggiornamento del database, effettuato ogni minuto per consentire l’accesso e la registrazione dei presenti.
Partizionamento in sottosistemi:
Il sistema può venire partizionato in tre sottosistemi:
• Controllo presenza e porta d’ingresso : controlla il codice inserito e il segnale dell’edificio a cui si vuole accedere.
• Database : contiene la lista dei codici delle persone che possono accedere agli edifici, viene
utilizzato per il confronto col codice immesso e viene aggiornato dall’ Update.
• Update Database : sottosistema che gestisce l’aggiornamento del database e quindi delle
presenze all’interno degli edifici.
Il sottosistema di controllo riceve 2 segnali: il codice inserito e la segnalazione dell’edificio (e della conseguente porta da aprire) corrente. Esso deve poter comunicare con il database, in modo che possa ritornare un valore booleano che indica se il codice inserito effettivamente sia reperibile in memoria. Il periodo d’esecuzione di quest’unità è dato dal tempo per ricevere i segnali in ingresso e dal ritardo dovuto dal confronto coi codici nel database, questo può variare da 1 a 100 confronti. Una seconda partizione è rappresentata dalla parte di Update , anch’essa connessa al database. A prescindere da un vincolo temporale (nel codice viene implementato da un ciclo do-while con un contatore ) il sottosistema aggiorna periodicamente il database tenendo in memoria le persone uscite o presenti in uno degli edifici. Il tempo di esecuzione sarà dato dalla scrittura in memoria dei 100 codici coi relativi valori di presenza ed edificio in cui si ha avuto accesso.
Il Database invece non esegue istruzioni ma viene aggiornato ed interrogato continuamente, e rappresenta dunque il cuore dell’unità principale, contiene i codici, le variabili di presenza e l’edificio per ognuna delle 100 persone.
PUNTO (2)
Il codice in C è stato spedito assieme al progetto.
I tre sottosistemi sono stati implementati come segue:
• Il Database è simulato da una struct contenente come campi le variabili presenza, codice ed edificio:
• Il Controllo presenze e porta d’ingresso: è implementato come funzione alla quale viene passato il codice inserito (letto dalla funzione leggicodice ) e la porta da aprire. Il codice inserito viene confrontato con gli altri 100, se la persona era assente allora adesso è presente e una variabile “dooropen” terrà in memoria il valore della porta da aprire (che sarà passata alla funzione open ) , se invece la persona sta uscendo viene si invia un segnale di apertura alla porta che era stata aperta quando il codice era stato immesso per entrare, in questo caso lo stato della persona diventa “assente” e l’edificio in cui ora è presente è 0 (ovvero nessuno dei tre)
• Update Database: anche questo sistema è implementato da una funzione, denominata refresh , il database è simulato da un file di testo aperto dalla funzione fopen (con l’ausilio del puntatore *p). Nel file vengono scritti i codici che per semplicità sono stati posti uguali ai numeri da 1 a 100, seguiti dalla dicitura “presente” o “assente” e da una variabile intera che corrisponde all’edificio in cui si è presenti (1= edificio 1, 2= edificio 2, 3= edificio 3, 0= nessun edificio). Se si è presenti si scrive l’edificio da cui arriva il segnale, altrimenti il campo edificio è 0 e lo stato è “assente”.
Il programma inizializza la struct coi 100 numeri, dopodiché inizia a leggere i codici e a ricevere i segnali dai vari edifici, per simulare questa richiesta si è usata la funzione rand() applicata a una variabile rnd ( int rnd = (rand() % 3), in questo modo si ha una persona fra le 100 che vuole entrare in un edificio a caso. I due segnali sono passati all’unità di controllo che svolge le sue funzioni e agisce sui campi della struct. Se ritorna vero allora si aprirà la porta corrispondente (passando la variabile dooropen alla funzione open ), altrimenti viene attivato un segnale di “warning” che indica l’errore di inserimento codice. Nella figura si ha un esempio:
Vengono premuti i codici 4, 5, 6, 7. Si aprono le porte del terzo edificio per i primi due, e del secondo per il 6 e il 7. Digitando invece 101 appare warning perché il codice non è nel database. A lato il file di testo scrive la presenza e il relativo edificio per i 4 codici corretti. Se ora il 4 fosse premuto di nuovo allora lo stato diverrebbe: “4 assente 0″.
Per ogni singolo periodo:
• Vengono effettuati al più 100 confronti
• Viene assegnata una variabile x (codice inserito)
• Viene assegnata una variabile dooropen (porta da aprire)
• Viene assegnata una variabile rnd (simula un segnale da un edificio a caso)
• Viene assegnata una variabile edificio
• Viene chiamata la funzione open o la funzione warning
• Viene chiamata una funzione refresh che scrive 100 codici, presenze, edifici
Queste sono le istruzioni ad alto livello coinvolte nel ciclo, che si ripete infinitamente aspettando l’ingresso di una persona.
PUNTO (3)
E’ possibile realizzare il nostro progetto con un’architettura di tipo general purpose processor, infatti il nostro progetto non necessità di specifiche unità funzionali ma gli occorre un generale datapath con un adeguato file register, una memoria del programma e un’ ALU generale con cui è possibile effettuare operazioni di somma e confronti.
I benefici di questa architettura sono un basso time-to-market e un basso costo NRE, nonché un’alta flessibilità.
In realtà è possibile realizzare lo stesso progetto perdendo di flessibilità utilizzando un’architettura di tipo single purpose processor che contiene solamente i componenti necessari ad eseguire un singolo programma, nel nostro caso la gestione del controllo presenze, della porta d’ingresso/uscita e del database. In questo caso si avrebbe un aumento della velocità, un minor consumo e dimensioni maggiormente ridotte.
Una volta scelto il possibile tipo di architettura è possibile implementare i sottosistemi attraverso dei dispositivi logici Full Custom /VLSI , PAL (Programmable Array of Logic), CPLD (Complex Programmable Logic Device) o FPGA (Field Programmable Gate Array).
La struttura dei dispositivi logici programmabili è caratterizzata da due elementi architetturali fondamentali: celle logiche e interconnessioni.
Le celle logiche sono elementi composti da strutture logiche (a partire dalle più semplici porte logiche) e le interconnessioni, che sono caratterizzati da interruttori programmabili, determinano come le celle logiche sono connesse tra loro all’interno del dispositivo.
La configurazione delle celle logiche e delle interconnessioni permette di implementare all’interno del dispositivo la logica progettata. Le tipologie di celle logiche e di interconnessione differenziano tra loro i diversi tipi di dispositivi logici programmabili, determinandone prestazioni e capacità.
Il PLA (Programmable Logic Array) è il più semplice dispositivo logico programmabile, gli ingressi e i loro negati sono connessi alle uscite attraverso una rete di connessioni programmabili, un array di porte AND e un insieme di porte OR.
Rispetto agli ASIC Gate Array (Application Specific Integrated Circuit) con gli FPGA non esistono i costi di mascheratura (i cosiddetti costi Non Recurring Engineering, NRE, per realizzare le “maschere” con cui produrre i circuiti integrati con la funzionalità voluta), si riducono drasticamente i tempi di attesa per i prototipi e i rischi connessi con la tecnologia non riprogrammabile, si gode della versatilità offerta dalla riprogrammabilità sia nell’evoluzione del progetto sia durante l’uso del sistema.
La linea di frontiera che limita la convenienza in termini economici dell’impiego degli FPGA rispetto agli ASIC Gate Array è principalmente fissata da due fattori: da un lato il numero di pezzi prodotti e dall’altro la densità di porte logiche necessarie per implementare il progetto, i quali quanto più crescono tanto più rendono conveniente l’impiego degli ASIC Gate Array.
Codice:
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <cstdlib>
void refresh();
int leggicodice(void);
void warning(void);
void open(int numeroporta);
bool controllo(int input, int apriporta);
struct
{
bool presenza; //variabile che tiene conto se si è presenti o assenti
int codice; //variabile del codice inserito
int edificio; //variabile che tiene in memoria l’edificio corrente in cui si è presenti
}accessi[100];
int dooropen; //porta dell’edificio da aprire
main()
{
int x;
bool loop;
dooropen = 0; //inizializzo come “0” la porta corrente in apertura, tutte chiuse quindi
int i;
for(i=0;i<100;i++)
{
accessi[i].presenza=0;
accessi[i].codice=i+1;
accessi[i].edificio=0; //1=edificio 1; 2=edificio 2; 3=edificio 3; 0= nessun edificio
}
int n = 0; //contatore per effetuare il refresh , ogni volta che n%2==0
do //ciclo infinito
{
loop = true;
n++ ;
int rnd = (rand() % 3) ; //ipotizzo che arrivi un segnale dall’edificio in cui si sta digitando il codice
x = leggicodice(); //ipotizzo che arrivi un segnale di digitazione da un edificio
if (controllo(x, rnd+1)) // controllo la presenza nella struct e passo il segnale che indica l’edificio in cui si vuole accedere
open(dooropen); //se sì apro la porta dell’edificio, se invece si sta uscendo apro la porta dell’ edificio in cui ero entrato e pongo 0 il campo edificio della struct
else
warning(); //codice errato
if(n%2==0) refresh(); //aggiorna la presenza su un file di testo qualsiasi
}while(loop);
}
void open(int numeroporta)
{
printf(” —-> OPEN door number %d\n”, numeroporta );
}
int leggicodice(void)
{
int input;
scanf(“%d”,&input);
return input;
}
void warning()
{
printf(“\nWARNING!!!\n”);
}
void refresh()
{
FILE *p;
p=fopen(“C:\\Documents and settings\\All users\\Desktop\\refresh.txt”,”w”);
int i;
for(i=0;i<100;i++)
{
fprintf(p,”%d”,accessi[i].codice);
if(accessi[i].presenza)
{
fprintf (p,” presente “);
fprintf(p,” %d\n”,accessi[i].edificio);
}
else
{
fprintf(p,” assente “);
accessi[i].edificio= 0; // stai uscendo dall’edificio –> non sei in nessun edificio
fprintf(p,” %d\n”,accessi[i].edificio);
}
}
fclose(p);
}
bool controllo(int input, int apriporta)
{
int i;
for(i=0;i<100;i++)
if(input == accessi[i].codice)
{
if (accessi[i].presenza == 0)
{
accessi[i].presenza = !accessi[i].presenza;
accessi[i].edificio = apriporta;
dooropen = apriporta;
return 1;
}
if (accessi[i].presenza == 1)
{
accessi[i].presenza = !accessi[i].presenza;
dooropen = accessi[i].edificio;
return 1;
}
}
return 0;
}