VHDL programming 
VHDL programming
Sandro Cavalieri Foschini matricola 127764 Andrea Paolo Ferraresi matricola 126947 Elettronica digitale per le reti di telecomunicazioni Professore Fabrizio Vacca RELAZIONE SUL LAVORO SVOLTO IN LABORATORIO POLITECNICO DI TORINO ANNO ACCADEMICO 2004/05 2 1. Esercitazione n° 1 Esercizi affrontati: 1) Descrizione e simulazione di una porta XOR a due ingressi 2) Descrizione e simulazione e sintesi di un SOMMATORE A 16 BIT 3) Descrizione strutturale, simulazione e sintesi di un SOMMATORE A 16 BIT 4) Descrizione strutturale di un REGISTRO A 16 BIT 1.1 Svolgimento esercitazione n° 1 1) Descrizione e simulazione di una porta XOR a due ingressi Commenti E’ stata realizzata la porta logica richiesta utilizzando la funzione di libreria XOR. L’architecture è composta da un unico processo combinatorio, perciò entrambi gli ingressi (segnali binari di tipo std_logic) del dispositivo sono stati inclusi nella sensitivity list e vanno a determinare il valore elettrico assegnato all’uscita della porta logica. Codice allegato folder “1.1es1_exor” 2) Descrizione e simulazione di un SOMMATORE A 16 BIT Figura 1 – Sommatore a 16 bit Commenti Si è descritto il dispositivo richiesto tramite un’architecture comportamentale. E’ stato implementato un semplice processo combinatorio in grado di sommare, sempre utilizzando una funzione di libreria, i due dati in ingresso. Questi, essendo espressi su 16 bit, sono stati modellizzati come segnali di tipo std_logic_vector. Codice allegato folder “1.2es2_add16” 3 3) Descrizione strutturale, simulazione e sintesi di un SOMMATORE A 16 BIT Commenti L’esercizio è stato svolto in due modi diversi a partire dall’entity di un sommatore a 16 bit. In primo luogo abbiamo realizzato un’architecture strutturale del sommatore a 16 bit i cui componenti (halfsinglesum e singlesum, rispettivamente un half adder con parallelismo di un bit ed un full adder con parallelismo di un bit) sono descritti in maniera comportamentale. In secondo luogo, per comprendere le possibilità offerte dal linguaggio in termini di modularità e di livelli gerarchici, abbiamo descritto un’architecture strutturale del sommatore a 16 bit i cui componenti sono in parte descritti in maniera comportamentale (or_2 e half_add, rispettivamente una porta logica or ed un half adder con parallelismo di un bit) ed in parte descritti a loro volta in maniera strutturale (full_adder, un full adder con parallelismo di un bit). Comportamento in termini di forme d’onda Probabilmente non è scopo del corso studiare il comportamento in termini di forme d’onda del dispositivo descritto in VHDL: infatti i valori dei ritardi imposti dal codice sono artificiosi e non corrispondono in linea di massima alla realtà fisica. Tuttavia questo studio, nelle nostre intenzioni mirato a comprendere il funzionamento del componente, è altresì servito per renderci conto di due aspetti che riguardano i circuiti combinatori. In primo luogo abbiamo notato in modo pratico come il tempo necessario affinché l’uscita diventi stabile non è fisso ma dipende dai segnali in ingresso: in particolare il sommatore a componenti descritti in maniera comportamentale impiega dai 6 ns ai 47 ns per terminare i calcoli. Abbiamo quindi imparato una volta di più che, prima di campionare un’uscita di un circuito combinatorio, è necessario attendere la fine della propagazione dei segnali attraverso il percorso con il ritardo maggiore, quello chiamato critical path. In secondo luogo abbiamo constatato che il tempo necessario affinché l’uscita diventi stabile non varia se il dispositivo è stato appena acceso o se lavora dall’inizio dei tempi. Tuttavia dal test bench riportato di seguito abbiamo verificato come i segnali si propaghino con tempistiche differenti se il dispositivo è stato appena acceso o se era in precedenza funzionante: in particolare il tempo totale di propagazione nell’esempio riportato rimane 47 ns, ma il 2° dei 16 bit è aggiornato dopo 5 ns se il dispositivo è stato appena acceso, dopo 3 ns se era precedentemente in funzione. Riportiamo di seguito la stimolazione degli ingressi necessaria ad osservare il fenomeno e rimandiamo alle figure 3ns.bmp e 5ns.bmp per verificare le forme d’onda. in1_i <= "1111111111111111"; in2_i <= "0000000000000000"; wait for 60 ns; in1_i <= "1111111111111111"; in2_i <= "1111111111111111"; wait for 60 ns; in1_i <= "1111111111111111"; in2_i <= "0000000000000000"; wait for 60 ns; 4 Sintesi Abbiamo deciso di confrontare i due diversi sommatori per capire quale nella pratica permette di realizzare circuiti più efficienti. Per entrambi abbiamo impostato il sintetizzatore Leonardo selezionando una FPGA della Xilinx, la Virtex II 2V1000fg456, chiedendo come soluzione un circuito che lavorasse a 200MHz ed impostando il parametro effort ad una tacca (33%). Abbiamo verificato che il sommatore il cui full adder elementare è descritto tramite un’architecture comportamentale abbia prestazioni inferiori rispetto al sommatore il cui full adder elementare è descritto tramite una architecture strutturale. Alleghiamo i summary ottenuti, 1.1full_adder_comportamentale.vhd e 1.2full_adder_strutturale.vhd. Codice allegato folder “1.31Sum 16 091” folder “1.32Full adder strutturale” 4) Descrizione strutturale di un REGISTRO A 16 BIT Figura 2 – Registro a 16 bit Commenti Un registro è un esempio di dispositivo sequenziale, ovvero necessita di un segnale di temporizzazione (il clock) affinché il circuito svolga le operazioni in modo sincrono. Per gestire un circuito di questo tipo è necessario un ulteriore segnale di reset, che può essere attivato in qualunque momento per (re)inizializzare il dispositivo. Pertanto questo segnale va trattato in un modo privilegiato: è asincrono ed ha alta priorità (maggiore anche di quella del clock). Un unico processo sequenziale è sufficiente per la realizzazione del dispositivo secondo una descrizione comportamentale. Il processo che descrive un circuito sequenziale deve essere sensibile a due soli segnali: il clock e il reset. La gestione dell’evento asincrono di reset si inserisce in un costrutto if che testa l’avverarsi di questa condizione e si risolve nell’azzeramento del contenuto del registro. Nel costrutto elsif si inserisce – a priorità minore – il codice che realizza il dispositivo, codice che verrà eseguito nel caso sia presente una transizione del segnale di temporizzazione: in particolare il registro si attiva sul fronte di salita del clock (positive edge triggered). Viene campionato il segnale EN_n (attivo basso) che convalida o meno i dati in ingresso: nel primo caso il valore all’ingresso è riportato all’uscita; nel secondo, non essendo specificato il ramo 5 dell’else ovvero non essendo assegnata un’uscita, è automaticamente mantenuto il valore precedente (configurazione di memoria). Codice allegato folder “1.4reg16” 2. Esercitazione n° 2 Esercizi affrontati: 1) Descrizione, simulazione e sintesi di un registro SIPO 2) Descrizione e simulazione di un semaforo (TLC) 3) Descrizione e simulazione di una coda FIFO 2.1 Svolgimento esercitazione n° 2 1) Descrizione, simulazione e sintesi di un registro SIPO Figura 3 – registro SIPO Commenti La SIPO (Serial Input Parallel Output) è un altro esempio di circuito sequenziale, pertanto valgono le regole di progettazione viste nel registro a 16 bit. L’unica specifica data è quella di mantenere flessibile il dispositivo per quanto riguarda il parallelismo dei dati in uscita. Pertanto il parametro size, che dimensiona la lunghezza del registro, è stato dichiarato con il costrutto VHDL generic ed è impostabile nell’architecture. Si è realizzato un unico processo sequenziale secondo una descrizione comportamentale. La specifica di progettazione del dispositivo prevede il segnale valid che, se attivo, convalida i dati in ingresso che possono così essere processati dalla SIPO. Per creare il registro a scorrimento e consentire ai dati di uscire in parallelo si è utilizzata come base dati un segnale interno, storage, che memorizza i singoli bit in ingresso. Sintesi Abbiamo selezionato una FPGA Xilinx modello Virtex II 2V1000fg456, impostando la frequenza di lavoro del circuito finale a 200MHz e di cercare questa soluzione con un effort pari ad una tacca (33%). Abbiamo ottenuto dalla sintesi un circuito che lavora a 270.3 MHz. Alleghiamo il summary 2.1SIPO.vhd. 6 Codice allegato: folder “2.1sipo” 2) Descrizione e simulazione di un controllore semaforico (TLC) Figura 4 – Controllore semaforico Commenti Il controllore semaforico è stato modellizzato come una FSM sincrona di Moore e realizzato tramite del codice VHDL comportamentale. Innanzitutto si è definito un modello dati di tipo enumerativo che elenca tutti i possibili stati in cui il semaforo si può trovare. Quindi si sono definiti due segnali che portano l’informazione dello stato attuale del sistema e di quello in cui si troverà dopo la prossima transizione di stato. Le operazioni svolte dal dispositivo sono state raggruppate in tre processi: -un processo combinatorio che individua il nuovo stato in base agli ingressi del dispositivo ed allo stato corrente; -un processo sequenziale che si occupa di gestire i cambiamenti di stato del sistema: prevede anche il riscontro di un evento (asincrono e a priorità maggiore) di reset; -un ulteriore processo combinatorio che, a seconda dello stato corrente, determina il valore delle uscite. Codice allegato folder “2.2tlc f” type state_t is (red, green, yel, fail_on, fail_off, rst); signal curr_state : state_t := rst; signal next_state : state_t ; --senza inizializzazione 7 3) Descrizione e simulazione di una coda FIFO Figura 5 – Coda FIFO Commenti La FIFO è stata implementata con una descrizione comportamentale consistente in un unico processo sequenziale. Per ottenere un maggior livello di flessibilità si possono impostare due parametri di tipo intero: · num_bit, indicante il parallelismo dei dati in ingresso. · size, che indica la quantità massima di locazioni di num_bit bit che possono essere scritte. Inoltre, utili per la di simulazione, si possono impostare i tre parametri che specificano il ritardo di propagazione per le operazioni di lettura (tpr), scrittura (tpw) e segnalazione delle due condizioni di coda vuota e piena (tpd). La base dati del programma è costituita da un segnale interno (fifobuf_i)utilizzato come matrice (vettore di “locazioni” ) per la conservazione dei dati. Per scandire questo vettore si utilizzano due variabili intere, pin e pout, puntatori che indicano – rispettivamente – la posizione in cui scrivere il dato campionato all’ingresso e dove leggere quello destinato ad uscire. Si riporta la parte di codice che gestisce la scrittura dei dati nel buffer: type buf_t is array (0 to size) of std_logic_vector(0 to num_bit-1); signal fifobuf_i : buf_t; if (write = '1') then --
if (fi = '0') then fifobuf_i(pin) <= data_in after tpw; pin := (pin + 1) mod size; if (pin = pout) then fi <= '1' after tpd; end if; if (ei = '1') then ei <= '0' after tpd; end if; end if; end if; -- 8 La scrittura può avvenire solo in corrispondenza del valore logico alto del segnale write: in primo luogo è necessario controllare che l’operazione sia possibile, ovvero che la coda non sia piena. Poiché il segnale full che riporta questa condizione è in realtà un segnale di tipo OUT non è possibile leggerlo. La strada più breve sarebbe stata quella di definire il segnale di tipo buffer, si è invece preferito definire un segnale ad uso interno del processo, chiamato fi, e provvedere poi alla fine del processo ad assegnare questo segnale all’uscita così: A questo punto è possibile memorizzare il dato in ingresso nel vettore nella posizione indicata dal puntatore pin. Avendo deciso di gestire la base dati per la memorizzazione dei pacchetti come un buffer circolare, il valore dei puntatori è incrementato modulo size. Seguono due controlli: · il primo sui puntatori di lettura/scrittura, se assumono lo stesso valore allora lo spazio per la memorizzazione dei dati è esaurito: a partire dalla prossima scrittura i dati saranno ignorati (come da specifica); · il secondo sul segnale interno ei che -se attivo -indica la condizione di coda vuota: poiché è stato memorizzato un dato allora il segnale deve sicuramente assumere il valore logico “0”. La parte che gestisce la lettura dei dati è speculare. Sintesi Abbiamo selezionato una FPGA Xilinx modello Virtex II 2V1000bg575, impostando la frequenza di lavoro del circuito finale a 100MHz e un effort pari ad una tacca (33%). Alleghiamo il summary 2.2sintetizz_fifo.vhd. Codice allegato folder “2.3fifo” full <= fi; --collega segnali interni con porte in OUT 9 3. Esercitazione n° 3 Esercizi affrontati: 1) Progetto di commutatore ATM-like 3.1 Svolgimento esercitazione n° 3 Il commutatore è descritto tramite un’architecture strutturale i cui componenti di base sono una coda fifo, un’unità di controllo ed una switching fabric. LA FIFO Le scelte Le specifiche forniteci prevedono che il segnale di frame che giunge al commutatore sia attivo per 53 colpi di clock, ossia per la durata di un pacchetto. Pertanto si è ritenuto opportuno collegare direttamente questo segnale al write in ingresso alla coda fifo: infatti entrambi i segnali assumono nella nostra interpretazione del commutatore i medesimi valori logici negli stessi istanti temporali e data la perfetta corrispondenza sarebbe superfluo mantenerli separati. La coda fifo da noi realizzata non si occupa solo di memorizzare i pacchetti ma anche di riconoscere la fine di un pacchetto e di comunicare alla control unit l’istante in cui deve campionare l’indirizzo del pacchetto in testa alla coda per decidere l’instradamento. È una scelta che presenta tratti anomali in quanto tipicamente è un processore (quindi la control unit) ad occuparsi di tutte le operazioni che riguardano i pacchetti e non può essere giustificata dal fatto che in questo modo si è potuto semplificare il codice della control unit (dove infatti il segnale di frame è assente). È stata ritenuta una scelta comunque accettabile perché se da un lato la coda conta fino a 53, quindi non devono esserle attribuite particolari doti di intelligenza e capacità di processamento, dall’altro lato si può ipotizzare che ogni interfaccia di ingresso ad un commutatore possegga un processore con compiti differenti da quello centrale. Il codice Ogni 53 byte la coda fifo invia attraverso un canale dedicato l’indirizzo (il primo byte del pacchetto in testa alla coda) alla control unit, contemporaneamente invia il segnale di start (custart) alla stessa control unit “validando” in questo modo l’indirizzo inviato: senza il segnale di start non avverrà quel cambiamento di stato che porta la control unit a calcolare l’instradamento. La coda possiede due flag. Il primo, “flag”, ha la funzione di avviare il conteggio dei 53 byte dopo un periodo di reset; poi la coda continua a contare anche nei momenti in cui frame (e quindi write) assume il valore logico zero in modo da smaltire i pacchetti rimasti in coda (oppure segnalare con degli zeri in uscita che non c’è nulla da trasmettere). Il secondo flag, “flag2”, ha la funzione di ritardare di un colpo di clock l’invio dell’indirizzo in uscita, altrimenti (a causa del ritardo con cui i byte sono memorizzati nella coda fifo) troveremmo nel segnale controlunitout il vecchio valore della locazione di memoria in cui deve ancora essere memorizzato l’indirizzo del nuovo pacchetto. CONTROL UNIT Il codice La control unit è una macchina a stati di Moore. La base dati è composta dai segnali currstate e nextstate che tengono traccia dello stato presente e futuro del sistema e dai segnali interni che, una volta assegnati alle uscite, andranno a pilotare il segnale di read delle code in ingresso ed a configurare la switching fabric. 10 Il diagramma è il seguente: Figura 5 – Diagramma a stati unità di controllo I valori dei segnali di uscita Mi (configurazione della switching fabric), extOccupato (vettore delle uscite prenotate) ed extFiforead (comando di lettura alle singole fifo) sono mantenuti nello stato cuschedula e aggiornati in cucommuta. Questi sono replicati internamente: in base ai nuovi valori degli ingressi sono i segnali o le variabili interni ad essere aggiornati, mentre l’aggiornamento si propaga ai segnali esterni solamente quando avverrà la transizione dallo stato di calcolo instradamento allo stato di commutazione. Questa duplicazione fa sì che l’effetto dei cambiamenti degli ingressi non si ripercuota immediatamente sulle uscite come avverrebbe in una macchina di Mealy: le uscite saranno aggiornate al passaggio nello stato di commutazione. Sono quattro i processi che realizzano il dispositivo. · Un primo processo combinatorio è sensibile ai quattro segnali d’ingresso add0, add1, add2, add3, che riportano l’indirizzo di destinazione, espresso su 8 bit, del pacchetto in testa alla coda. Questo processo converte il campo destination in intero e decide l’instradamento dei pacchetti l’indirizzo secondo la seguente tabella: Indirizzo destinazione Porta uscita (1, 63) 0 (64, 127) 1 (128, 191) 2 (192, 255) 3 Una volta individuata l’uscita opportuna, per capire se è libera si testa il vettore di prenotazione intOccupato. Ad esempio si ha un pacchetto per l’uscita 0: se intOccupato(0) = ‘0’ significa che l’uscita 0 è libera, quindi si esegue la prenotazione dell’uscita settando il bit a 1 e si aggiorna il segnale fiforead in modo da dare il comando di read alla coda contenente il pacchetto che SwStart = ‘0’ cuStartCU = ‘0’ cuStartCU = ‘1’ SwStart = ‘1’ cuCommu ta cuStartCU = ‘1’ & FRAME = ‘1’ cuSchedula cuStartCU = ‘0’ & FRAME = ‘0’ Reset 11 sarà instradato. Se invece l’uscita fosse occupata non avverrà la lettura dalla coda perché il segnale fiforead sarà aggiornato con un valore logico basso. Il segnale intMi è stato pensato come un concatenamento di gruppi di 4 bit: la posizione dei bit indica l’ingresso (i primi 4 bit l’ingresso 3, i secondi 4 bit l’ingresso 2, ….), i primi due bit indicano l’uscita della switching fabric a cui è destinato il pacchetto (00 indica l’uscita 0, 01 l’uscita 1, … ). La configurazione “0001” indica che nessun pacchetto è letto dall’ingresso a causa di una contesa. · Un secondo processo combinatorio è sensibile a currstate, custartcu, swstart: in base ai loro valori avverranno le transizioni di stato secondo il diagramma riportato in precedenza. Nello stato di reset il componente non è attivo, tuttavia si inizializzano i segnali e le variabili usate. Nello stato cuschedula si mantengono stabili la configurazione della matrice di instradamento e il vettore di prenotazione delle uscite: ciò permette di completare con la vecchia configurazione una trasmissione eventualmente in corso. La transizione allo stato cucommuta aggiorna la vecchia con la nuova configurazione e segna l’inizio di una nuova trasmissione. · Un terzo processo combinatorio aggiorna le uscite in base allo stato corrente. · Un quarto processo sequenziale aggiorna lo stato corrente del sistema. SWITCHING FABRIC Il codice L’architecture è composta da un unico processo combinatorio: prima si assegnano i pacchetti alle uscite; successivamente, nel ciclo for che chiude il processo, a tutte le uscite su cui non si instradano pacchetti sono assegnati degli zeri. Le scelte Il codice viola una delle regole fondamentali di ogni buon progetto: adoperiamo la clausola “null” a seguito di un “when others”. È stata una scelta ben meditata, infatti il “when others” è eseguito in due situazioni: · quando ci sono due o più pacchetti in contesa per una stessa uscita, perciò inevitabilmente si avrà un’altra uscita da cui non escono pacchetti: in questa situazione sarà il successivo ciclo for ad assegnare dei valori logici nulli alle uscite non pilotate (perciò il codice rispetta la regola di assegnare dei valori a tutte le uscite); · quando i segnali che arrivano dalla control unit non sono corretti a causa di malfunzionamenti nel processamento degli indirizzi o di errori sul canale di trasmissione: in questo caso sono parecchie le soluzioni che è possibile implementare per sostituire la clausola “null” in base al tipo di errore. Un codice più completo potrebbe prevedere un vettore di flag che tenga traccia delle uscite a cui è già stato assegnato un valore, in modo da poter rimediare in caso di uscite non pilotate. La nostra scelta per il momento è stata quella di implementare un codice che non preveda inesattezze, senza appesantirlo da troppi controlli d’errore: diverse considerazioni hanno suggerito l’idea che nessun elemento potesse portare a discriminare tra le tante soluzioni e ad optare per la migliore. Tutte sarebbero state egualmente opportune. Solo nel caso in cui ci si trovasse a realizzare 12 qualcosa di concreto, quindi conoscendo le condizioni in cui il dispositivo si troverà ad operare, avremmo elementi su cui basare le considerazioni e operare scelte precise. Sintesi Abbiamo selezionato una FPGA Xilinx modello Virtex II 2V1000ff896. Per la sintesi della control unit la frequenza di lavoro desiderata è stata fissata a 100MHz. In allegato si trova il summary 3.1ucmacchinasintesi.vhd. Per sintetizzare la switching fabric la frequenza di lavoro desiderata è stata fissata a 300MHz. Alleghiamo il summary 3.2swfabsummary.vhd. La coda FIFO è stata sintetizzata impostando la frequenza di lavoro del circuito finale a 200MHz ed alleghiamo il summary 3.3fifoscsum.vhd. Si noti che per la sintesi della fifo abbiamo dovuto modificare il codice in due punti (file 3.3fifosc.vhd): · il sintetizzatore non accetta l’operazione di modulo svolta con un operando non esprimibile come potenza di 2, pertanto non si è usata la costante cinq (che vale 53); · il codice “while pout > 53*j” non è compreso dal sintetizzatore per motivi che ci sfuggono. Per la sintetizzazione del file commutatore.vhd la frequenza è impostata a 200MHz, alleghiamo il summary 3.4commutatore.vhd. L’intero apparato è quindi stato sintetizzato impostando la frequenza di lavoro del circuito finale a 100MHz. summary 3.5tutto.vhd. Codice allegato folder “3commutatore” 13 4. Esercitazione n° 4 Esercizi affrontati: 1) Progetto FIFO con supporto VOQ 2) Progetto unità di controllo mediante iSLIP 4.1 Svolgimento esercitazione n° 4 1) Progetto FIFO con supporto VOQ Commenti Ogni coda fifo possiede al suo interno quattro buffer ognuno dei quali è “virtualmente”associato ad un’uscita del commutatore: è la coda stessa a preoccuparsi di instradare i pacchetti. Il vettore di request (book) è aggiornato in base all’occupazione dei buffer ed inviato all’unità di controllo. Questa si occuperà dello scheduling ed invierà alla coda il comando di lettura attivo o meno. La coda comprende in quale buffer risiede il pacchetto schedulato e lo invia all’uscita. Codice allegato folder “4fifo” 2) Progetto unità di controllo mediante iSLIP Commenti A differenza dell’esercitazione precedente, la control unit non ha il compito di instradare i pacchetti ma soltanto di schedulare le trasmissioni. Tuttavia la struttura subisce poche modifiche: non cambiano né i principi di funzionamento, né le interazioni, se non nei dettagli, con gli altri componenti (infatti la switching fabric rimane la stessa e riceve gli stessi segnali). In particolare: · i segnali di interfaccia della control unit sono (riportiamo l’entity): port ( cubook0 : IN std_logic_vector(0 to 3); cubook1 : IN std_logic_vector(0 to 3); cubook2 : IN std_logic_vector(0 to 3); cubook3 : IN std_logic_vector(0 to 3); rst_ncu : IN std_logic; clkcu : IN std_logic; custartcu : IN std_logic; extoccupatocu : buffer std_logic_vector(3 downto 0); Mi : buffer std_logic_vector(0 to 15); extfiforead : buffer std_logic_vector(0 to 15); swstart : buffer std_logic ); 14 · il diagramma degli stati non varia: Figura 6 – Diagramma a stati unità di controllo (stessa di Figura 5) · i processi che realizzano l’unità di controllo: i seguenti tre process rimagono immutati: Cambia invece il process che svolge le operazioni: La control unit ha 4 arbitri “di uscita” e 4 arbitri “di ingresso” per decidere a quale richiesta assegnare il grant ed a quale uscita inviare l’accept. Si è ipotizzata una descrizione degli arbitri: la riportiamo per una maggiore chiarezza, tuttavia non pensiamo di creare gli arbitri come componenti. process(currstate, custartcu, swstart) process (clkcu, rst_ncu) process(currstate) process(cubook0, cubook1, cubook2, cubook3) --arbitri “di uscita” port ( cubook0, cubook1, cubook2, cubook3 : IN std_logid_vector (0 to 3); grant : OUT std_logid_vector (0 to 3) ); SwStart = ‘0’ cuStartCU = ‘0’ cuStartCU = ‘1’ SwStart = ‘1’ cuCommu ta cuStartCU = ‘1’ & FRAME = ‘1’ cuSchedula cuStartCU = ‘0’ & FRAME = ‘0’ Reset 15 Ognuno dei 4 arbitri “di uscita” possiede: una variable previouschoice : integer una variable requestarray : std_logic_vector(0 to 3) la prima variabile tiene traccia dell’ingresso a priorità massima; la seconda è aggiornata con le richieste che arrivano dalle code. Nel caso dell’arbitro dell’uscita 0 si avrà In base alla previouschoise ognuno dei 4 arbitri in uscita sceglie a quale richiesta assegnare il grant e compila un vettore grantarray. A questo punto ognuno dei 4 arbitri “di ingresso” riceve dagli arbitri di uscita i vettori grantarray e decide a chi concedere l'accept. L’uscita a cui è concesso l'accept aggiorna previouschoice. A questo punto si configura la switching fabric aggiornando intMi e intOccupato. --arbitri “di ingresso” port ( grant0, grant1, grant2, grant3 : in std_logid_vector (0 to 3); accept : out std_logid_vector (0 to 3); ); requestarray := cubook0(0) & cubook1(0) & cubook2(0) & cubook3(0)