Simulazioni e verifiche - fsartori.altervista.orgfsartori.altervista.org/capitolo_3.pdf · verifica...
Transcript of Simulazioni e verifiche - fsartori.altervista.orgfsartori.altervista.org/capitolo_3.pdf · verifica...
Capitolo 3
Simulazioni e verifiche
Capitolo 3 – Simulazioni e verifiche 64
3.1 Introduzione
La verifica del sistema nel suo complesso è stata effettuata simulando il funzionamento
di ogni modulo separatamente. La sintesi di ogni singolo blocco, realizzata mediante
linguaggio VHDL, è avvenuta mediante il software “Active VHDL” della Aldec [6].
L’implementazione nella FPGA, presente sulla scheda demo della Avnet [7], dei soli
moduli di codifica/decodifica FHSS non consente di per se una totale verifica sul
funzionamento dell’apparato. Si deve perciò trovare un modo semplice per fornire al
codificatore i dati, sottoforma di ottetti, provenienti dal sottolivello MAC. In pratica,
deve avvenire una simulazione dell’interazione tra il livello fisico (costituito dal
codificatore FHSS) ed il sottolivello MAC.
In un primo tempo si era pensato di utilizzare una ROM di 4096 bytes, implementata
direttamente sulla FPGA, per fornire gli ottetti di dati MAC. In uscita al decodificatore
FHSS, una RAM di 4096 bytes consentiva la memorizzazine dei dati ricevuti. A
trasmissione effettuata, la verifica comparata di ogni singolo ottetto di dati contenuto
nella ROM e nella RAM permetteva la verifica della trasmissione.
Successivamente si è pensato che un modo più veloce e meno restrittivo per eseguire la
simulazione fosse quello di utilizzare al posto della ROM una RAM precaricata di
informazioni. Restava tuttavia il problema su come eseguire questa precarica. La
presenza della porta seriale sulla scheda FPGA è stata fondamentale consentendo
l’utilizzo di un computer, collegato tramite un cavo “null modem” (vedi Appendice) al
connettore RS-232 della scheda, come simulatore della “sorgente” di informazioni
MAC. Questi dati, giunti alla scheda mediante la porta seriale, venivano memorizzate
nella RAM ed erano pronti per essere utilizzati dal codificatore durante la costruzione
del pacchetto.
I dati in uscita al decodificatore, salvati nella seconda RAM, vengono ritrasmessi al
computer mediante il solito collegamento seriale. Il computer riesce così a confrontare i
dati in arrivo sulla porta RS-232 con quelli che aveva trasmesso in precedenza. Questa
verifica permette di rilevare se il processo di codifica-decodifica è andato a buon fine.
Capitolo 3 – Simulazioni e verifiche 65
3.2 Sistema completo
Dal paragrafo precedente si denota la necessità di implementare sulla FPGA moduli
aggiuntivi per il supporto della comunicazione seriale, della simulazione della sorgente
dati del livello MAC e della gestione delle interfacce presenti sulla scheda (pulsanti e
displays a 7 segmenti).
Si devono così creare due memorie RAM, di tipo dual port, di 4096 bytes ognuna.
Per la gestione degli indirizzi di tali memorie sono necessari due contatori a 12 bits
(ram addr counter).
Il computer, prima dei dati MAC, deve inviare anche i valori PLW e PSF (16 bits) per
inizializzare il codificatore e quindi sono necessari due registri di 8 bits per la loro
memorizzazione (header register).
S3 push anti-bumper
7 segments displays handler
S2 push anti-bumper
header (low word) register (8 bits)
header (high word) register (8 bits)
Clock
reset
Push_S2
reset
reset
clock
push
push_ab
Clock
reset
Push_S3
push
reset
clock
push
push_ab
Clock
reset
display1(3:0)
Segment(7:0)
reset
clock
display1(3:0)
segment(7:0)
display2(3:0) display2(3:0)
display3(3:0) display3(3:0)
display4(3:0) display4(3:0)
Digit(3:0)digit(3:0)
Clock
reset
enable_reg_1
plw(11:4)
reset
clock
enable
reg(7:0)
serial_out(7:0) data_in(7:0)
Clock
reset
enable_reg_2
plw(3:0) & psf(3:0)
reset
clock
enable
reg(7:0)
serial_out(7:0) data_in(7:0)
Clock
reset
start_tx
finish_tx
FHSSPHY encoder
reset
clock
start
finish
plw(11:0) plw(11:0)
psf(3:0) psf(3.0)
mac_data_tx(7:0) mac_data(7:0)
busy busy_tx
next_mac_data next_mac_data
data_out TP1
error error_tx
unsupported_data_rate error_1
nr_PSDU_octets_null error_2
Clock
reset
start_rx
finish_rx
FHSSPHY decoder
reset
clock
start
finishTP1 data_in
mac_data_ready mac_data_ready
mac_data(7:0) mac_data_rx(7:0)
error error_rx
error_3 unsupported_data_rate
error_4 crc_error
rate rate_tx
plw(11:0) plw_rx(7:0)
rate rate_rx
Clock
reset
UART transmitter
reset
clock
serial_in(7:0) data_in(7:0)
UART_busy busy
transmit_serial_data transmit_data
Clock
reset
UART receiver
reset
clock
RxD RxD
serial_data_sentdata_sent
TxD TxD
serial_data_readydata_ready
serial_out(7:0)data_out(7:0)
Figura 1: Moduli implementati sulla FPGA (I parte)
Capitolo 3 – Simulazioni e verifiche 66
Clock
reset
pushreset_ram_addr
main control unit
reset
clock
pushreset_ram_addrdipswitch(0) dipswitch(0)
serial_data_sent serial_data_sent
error_1
serial_data_ready serial_data_ready
plw(11:0) plw(11:0)
psf(3:0) psf(3:0)
ram_addr_tx(11:0) ram_addr_tx(11:0)
ram_addr_rx(11:0) ram_addr_rx(11:0)
enable_reg_1 enable_reg_1
enable_reg_2 enable_reg_2
enable_ram_addr_tx
error_2
enable_ram_addr_rx
error_tx
we_ram_tx
finish_tx
start_tx
error_3
start_rx
error_4
transmit_serial_data
display1(3:0)
error_rx
finish_rx
enable_ram_addr_tx
enable_ram_addr_rx
we_ram_tx
start_fhss_rx
start_fhss_tx
transmit_serial_data
display1(3:0)
display2(3:0) display2(3:0)
display3(3:0) display3(3:0)
display4(3:0) display4(3:0)
error_1
error_2
error_tx
finish_tx
error_3
error_4
error_rx
finish_rx
serial_out(7:0) serial_out(7:0)
serial_in(7:0) serial_in(7:0)
Clock
Clock
we_ram_tx
FHSSPHY encoder dual port ram (4096 x 8 bits)
clkb
clka
wea
ram_addr_tx(11:0) addra(11:0)
ram_addr_tx(11:0) addrb(11.0)
serial_out(7:0) dina(7:0)
doutb(7:0) mac_data_tx(7:0) Clock
Clock
mac_data_ready
FHSSPHY decoder dual port ram (4096 x 8 bits)
clkb
clka
wea
ram_addr_rx(11:0) addra(11:0)
ram_addr_rx(11:0) addrb(11.0)
mac_data_rx(7:0) dina(7:0)
doutb(7:0) serial_in(7:0)
Clock
reset_ram_addr
enable_ram_addr_txor next_mac_data
ram_addr_tx(11:0)
FHSSPHY encoder ram addr counter (12 bits)
reset
clock
enable
count(11:0) Clock
reset_ram_addr
enable_ram_addr_rx or mac_data_ready
ram_addr_rx(11:0)
FHSSPHY decoder ram addr counter (12 bits)
reset
clock
enable
count(11:0)
Figura 2: Moduli implementati sulla FPGA (II parte)
La comunicazione seriale viene realizzata dell’UART transmitter e dall’UART receiver
[8].
La gestione dei pulsanti viene effettuata dai moduli push anti-bumper. Essi evitano il
problema della presenza di segnali spuri alla durante la pressione e forniscono in uscita
un impulso sincrono al clock e di durata di un solo periodo ad ogni attivazione.
Il modulo 7 segments displays handler permette la visualizzazione, sui displays a sette
segmenti della scheda, dei valori in ingresso al modulo in formato esadecimale.
La main control unit si occupa delle varie fasi che compongono il processo di verifica
del funzionamento dei dispositivi FHSSPHY encoder e FHSSPHY decoder in prova.
La Figura 1 e la Figura 2 mostrano lo schema del sistema completo con i vari dispositivi
implementati sulla FPGA.
Capitolo 3 – Simulazioni e verifiche 67
3.2.1 Push anti-bumper
Per realizzare il dispositivo di eliminazione dei segnali spuri sono sufficienti un flip flop
SR ed un contatore. La pressione del pulsante della scheda comporta che il segnale,
associato ad esso e che normalmente è a livello alto, si porti al livello basso. Questo
cambiamento fa commutare l’uscita del flip flop al livello alto abilitando così il
contatore che fornisce l’impulso desiderato (sincrono al clock e di durata di un periodo)
quando il conteggio raggiunge il valore 1. Durante questa fase l’ingresso SET del flip
flop, essendo in relazione con l’uscita Q, non è più attivabile. Una pressione sul
pulsante si traduce ancora in un impulso in uscita solo quando il contatore è arrivato a
“fine corsa”. Infatti, quando il contatore raggiunge il valore “111...1”, si ha un segnale
di RESET sul flip flop, l’uscita Q si riporta a valore basso e si riabilita nuovamente
l’ingresso SET che resta in attesa di una nuova pressione del pulsante. Il periodo di
disabilitazione del pulsante è pari al periodo di clock per il valore di “fine corsa” del
contatore, cioè:
419,021040121 24
624 =⋅
⋅=⋅=
clockdis f
T [secondi]
La figura seguente mostra lo schema dell’anti-bumper.
clock
reset or end_disabling
disabling push counter (24 bits)
reset
clock count=1
push_disabled
end_disabling
push_ab
enable
clock
reset or end_disabling
push nor push_disabled
enabling counter ff sr
set
clock
reset
q push_disabled
count=”111…11”
Figura 3: Push anti-bumper
3.2.2 7 segments displays handler
I quattro displays a 7 segmenti presenti sulla scheda non possono essere accesi
contemporaneamente ma uno alla volta. Per poter visualizzare tutte e quattro le cifre è
così necessario un sistema che sia in grado di accendere in modo sequenziale un display
alla volta con una frequenza tale da farli apparire accesi tutti e quattro.
Capitolo 3 – Simulazioni e verifiche 68
La frequenza scelta è fornita dal contatore switch display digit ed è pari a:
1522
10402 18
6
18 =⋅
== clockswitch
ff [Hz]
La ROM ha il compito di indicare quali segmenti del display accendere per visualizzare
il valore in ingresso in formato esadecimale.
Il decoder ed il multiplexer sono comandati entrambi dal contatore fornendo
l’accensione dei displays in sequenza desiderata.
display segments rom (16 x 8 bits)
clock
reset
sel_digit(1:0)
switch display digit counter (19 bits)
reset
clock count(18:17)
display(3:0) segment(7:0)addr(3:0) out(7:0)
sel_digit(1:0) digit(3:0)
digit select decoder
addr(1:0) out(3:0)display select mux
sel_digit(1:0)
display1(3:0)
display2(3:0)
display(3:0)
a(3:0)
sel(1:0)
b(3:0)
out(3:0)
display3(3:0)
display4(3:0) d(3:0)
c(3:0)
Figura 4: 7 segments displays handler
3.2.3 UART transmitter
La trasmissione dei dati dalla FPGA al computer viene realizzata da questo dispositivo.
La specifica comunicazione seriale implementata è caratterizza da una velocità di
trasmissione di 9600 bps, otto bits di dati, nessun bit di parità e un solo bit di stop.
UART tx data reverse
shift register (9 bits) clock
reset
trigger
reset (reg=”11…1”)
clock
enable
data_in(7:0) & ‘0’ data_in(8:0)
load_data load
clock
reset
transmit_data
UART transmitter control unit
reset
clock
transmit_data
finish and trigger finish
reset_div_freqreset_div_freq
clock
reset or data_sent
UART tx nr bits counter (4 bits)
reset
clock finish count=9TxD
load_dataload_data
busy busy
reg(0)
din‘1’
trigger enable
data_sentdata_sentclock
reset_div_freqor trigger
UART tx divide frequency counter (13 bits)
reset
clock triggercount=4166
Figura 5: UART transmitter
Capitolo 3 – Simulazioni e verifiche 69
Il contatore divide frequency permette allo shift register di uscita di fornire i dati alla
frequenza di trasmissione desiderata (9600 bps). I dati da trasmettere vengono caricati
nello shift register in modo parallelo e trasmessi serialmente in uscita. Il contatore nr
bits determina la fine della trasmissione di un frame di dati (un bit di start, otto bits di
dati ed un bit di stop).
L’UART transmitter control unit è costituita da due stati: il primo è di attesa mentre nel
secondo avviene la trasmissione del frame seriale.
finish=’1’ andtransmit_data=’0’
reset_div_freq <= ‘0’ busy <= ‘1’
load_data <= transmit_data and finishdata_sent <= finish
1
reset_div_freq <= ‘1’ busy <= ‘0’
load_data <= transmit_data
0
transmit_data=’1’
reset=’1’
Figura 6: Diagramma a stati della UART transmitter control unit
3.2.4 UART receiver
Il sistema acquisisce i dati provenienti dalla porta seriale del computer mediante questo
ricevitore. Le informazioni seriali in arrivo vengono memorizzate nello shift register. I
parametri che specificano il tipo di comunicazione seriale sono identiche a quelle
utilizzate nel trasmettitore UART. Il contatore divide frequency serve a sincronizzare lo
shift register alla velocità di 9600 bps. Il contatore nr bits, oltre a determinare l’ultimo
bit del frame (bit di stop), indica quando il bit che si sta ricevendo fa parte degli otto bits
dati ed abilita lo shift register di ingresso per la memorizzazione. Al termine della
ricezione, l’ottetto dati è disponibile all’uscita parallela del registro a scorrimento.
Capitolo 3 – Simulazioni e verifiche 70
UART rx data reverse shift register (8 bits)
clock
reset
data_bit and trigger
reset
clock
enable
data_out(7:0) data_out(7:0)
clock
reset
not Rxd
UART receiver control unit
reset
clock
receive_data
finish and trigger finish
reset_div_freqreset_div_freq
clock
reset or data_ready
UART rx nr bits counter (4 bits)
reset
clock
finish count=9
data_readydata_ready
din RxD
trigger enable
data_bitcount=1,2,3,4,5,6,7,8
clock
reset_div_freq orcount=4166
UART rx divide frequency counter (13 bits)
reset
clock triggercount=2083
Figura 7: UART receiver
Il diagramma a stati della UART receiver control unit è mostrato in Figura 8. Lo stato 0
è di attesa di un frame seriale e lo stato 1 si occupa dell’estrazione del dato contenuto in
quest’ultimo.
finish=’1’
reset_div_freq <= ‘0’ data_ready <= finish
1
reset_div_freq <= ‘1’ 0
receive_data=’1’
reset=’1’
Figura 8: Diagramma a stati della UART receiver control unit
3.2.5 Main control unit
Il processo di verifica del funzionamento dei avviene principalmente in tre fasi.
La prima fase (stati 0, 1, 2 e 3) riguarda la ricezione e la memorizzazione dei dati
provenienti dal computer nei due registri (memorizzazione di PLW e PSF) e nella RAM
(dati di simulazione livello MAC).
Capitolo 3 – Simulazioni e verifiche 71
serial_data_ready=’1’
serial_data_ready=’1’
enable_reg_1 <= serial_data_ready display1 <= serial_in(7:4) display2 <= serial_in(3:0)
display3 <= serial_out(7:4) display4 <= serial_out(3:0)
0
reset=’1’
reset_ram_addr <= serial_data_ready enable_reg_2 <= serial_data_ready
1
we_ram_tx <= serial_data_ready enable_ram_addr_tx <=
serial_data_ready reset_ram_addr <= ‘1’ when
ram_addr_tx=plw start_fhss_rx <= ‘1’ when
ram_addr_tx=plw
2
display1 <= plw(11:8) display2 <= plw(7:4) display3 <= plw(3:0)
display4 <= psf start_fhss_tx <= push or
dipswitch
3
ram_addr_tx=plw
display1 <= “1111” display2 <= “1111” display3 <= “1111” display4 <= “1111”
enable_ram_addr_rx <= push or dipswitch
transmit_serial_data <= push or dipswitch
6
push=’1’ ordipswitch=’1’
display1 <= “0000” display2 <= “0000” display3 <= “0000” display4 <= “0000”
reset_ram_addr <= finish_rx
4
finish_rx=’1’ orerror_rx=’1’ or
error_tx=’1’
enable_ram_addr_rx <= serial_data_sent
transmit_serial_data <= serial_data_sent when
ram_addr_rx/=plw display1 <= serial_in(7:4) display2 <= serial_in(3:0)
display3 <= serial_out(7:4) display4 <= serial_out(3:0)
7
serial_data_sent=’1’ and
ram_addr_rx=plw
push=’1’ or dipswitch=’1’
display1,display2,display3,display4 <= “0001” when error_1=’1’ else “0010” when error_2=’1’ else “0011” when error_3=’1’ else “0100” when error_4=’1’
else “0000”
5
error_rx=’0’ and error_tx=’0’
Figura 9: Diagramma a stati della main control unit
Nella seconda fase (stati 4, 5 e 6) avverrà il processo codifica e decodifica FHSS con i
dati MAC decodificati memorizzati nella seconda RAM.
Nella terza ed ultima fase (stato 7) si effettuerà la trasmissione dei dati decodificati al
computer che verificherà se il processo di codifica-decodifica è andato a buon fine
comparando i dati trasmessi con quelli ricevuti.
Il dipswitch 0, presente sulla scheda, consente di comandare il passaggio da una fase a
quella successiva mediante la pressione del pulsante S3. Se il dipswitch 0 non è attivato
allora il passaggio avviene automaticamente.
Capitolo 3 – Simulazioni e verifiche 72
Sui displays della scheda, durante ogni fase, vengono visualizzate diverse informazioni.
Durante la prima e la terza fase vengono visualizzati in successione i dati seriali in
arrivo ed in partenza; inoltre, a ricezione avvenuta, vengono mostrati i valori di PLW e
PSF. Nella seconda fase i displays permettono di evidenziare il verificarsi di uno dei
quattro possibili errori (“1111” o “2222” indicano gli errori di codifica “unsupported
data rate” o “number of PSDU octets null”, “3333” o “4444” indicano agli errori di
decodifica “unsupported data rate” o “crc error”) oppure di comunicare una codifica-
decodifica corretta (“FFFF”).
La Figura 10 rappresenta la la scheda FPGA utilizzata per la prova. Da questa foto si
notano i vari dispositivi di I/O come i pulsanti, il dipswitch e i displays a 7 segmenti.
Figura 10: Fotografia della scheda FPGA
Capitolo 3 – Simulazioni e verifiche 73
3.3 Programma di comunicazione
Esistono due metodi per la scrittura del codice di un programma di comunicazione
seriale (vedi Appendice). Si può eseguire un “polling” sulla UART, per vedere se
qualche nuovo dato è disponibile oppure si può configurare la gestione degli interrupts
[9] per rimuovere i dati dall’UART quando quest’ultima genera un interrupt. La
gestione di tipo “polling” è un metodo molto lento poiché utilizza intensivamente la
CPU del sistema. Quindi si può raggiungere una velocità massima di trasmissione di
circa 38,4 kbps prima di iniziare a perdere dati. L’altra opzione è quella della gestione
degli interrupts ed è quella che verrà utilizzata. Essa supporta facilmente velocità di
115,2 kbps anche su computer di fascia bassa.
INT (Hex) IRQ Uso comune 08 0 Timer di sistema 09 1 Tastiera 0A 2 Reindirizzato 0B 3 Comunicazione seriale: COM2/COM4 0C 4 Comunicazione seriale: COM1/COM3 0D 5 Riservato/Scheda audio 0E 6 Controller del floppy disk 0F 7 Comunicazione parallela 70 8 Real Time Clock 71 9 Riservato 72 10 Riservato 73 11 Riservato 74 12 Mouse PS/2 75 13 Coprocessore matematico 76 14 Hard Disk Drive 77 15 Riservato
Tabella 1: Vettori di interrupt (Solo hardware)
Il polling della UART è, per esempio, un buon metodo per la diagnostica o per capire a
quale indirizzo o a quale IRQ fa riferimento la porta seriale in esame. Nella Tabella 1
sono riportati gli indirizzi di base e gli IRQ più comunemente usati.
Capitolo 3 – Simulazioni e verifiche 74
3.3.1 Vettori di interrupt
Dopo aver trovato l’IRQ della porta seriale, il passo successivo è di cercare il suo
vettore di interrupt. Fondamentalmente, ogni processore della famiglia 8086, ha un set
di 256 vettori di interrupt, numerati da 0 a 255. Ognuno di questi vettori contiene un
codice a 4 byte che è un indirizzo dell’ISR (Interrupt Service Routine) [9].
Fortunatamente il C, essendo un linguaggio di alto livello, si prende cura degli indirizzi
autonomamente. Tutto quello che interessa è quindi solo il vettore di interrupt effettivo.
La Tabella 1 mostra solo gli interrupt che sono associati con gli IRQ. Gli altri 240 non
interessano nella programmazione di una comunicazione di tipo RS-232.
Per esempio se si sta utilizzando la porta COM3 che ha un IRQ pari a 4, allora il vettore
dell’interrupt deve essere 0C in esadecimale. Usando il linguaggio C dovremo settare il
vettore tramite l’istruzione setvect(0x0C, PORT1INT); dove PORT1INT conduce ad un
set di istruzioni di servizio per l’interrupt.
Comunque, prima di procedere, è buona norma salvare i dati relativi agli indirizzi del
vecchio vettore e ripristinarli alla fine dell’esecuzione del programma. Questo è fatto
grazie all’istruzione oldport1isr = getvect(INTVECT); dove oldport1isr è
definito usando la dichiarazione void interrupt (*oldport1isr)();
3.3.2 Interrupt Service Routine
La PORT1INT vista prima è l’etichetta riferita alla procedura di gestione dell’interrupt
denominata Interrupt Service Routine (ISR). Essa è la seguente:
void interrupt PORT1INT() /* Interrupt Service Routine for PORT1 */ { int c; do
{ c = inportb(PORT1 + 5); if (c & 1)
{ buffer[bufferin] = inportb(PORT1); bufferin++; if (bufferin == 1024) {bufferin = 0;} }
} while (c & 1); outportb(0x20,0x20); }
Capitolo 3 – Simulazioni e verifiche 75
La procedura controlla se c’è un carattere da ricevere ed in caso affermativo lo rimuove
dal dalla UART e lo salva in un buffer contenuto nella memoria. Il controllo sulla
UART viene mantenuto, nel caso in cui i buffers FIFO siano abilitati, in modo tale da
poter prelevare tutti i dati disponibili all’istante di manifestazione dell’interrupt (e non
un solo carattere).
L’ultima riga contiene l’istruzione outportb(0x20,0x20); che comunica al
Programmable Interrupt Controller [9] che l’interrupt ha finito. Ora verrà analizzato
proprio il Programmable Interrupt Controller (PIC). Tutte le routine precedenti sono
state analizzate considerando che tutto sia configurato correttamente e che tutto sia
pronto per l’uso; ciò significa che i registri dell’UART ed il Programmable Interrupt
Controller siano stati inizializzati senza commettere errori.
Il Programmable Interrupt Controller gestisce gli interrupts hardware. La maggior parte
dei PC ne hanno due collocati a due indirizzi diversi.
Uno gestisce gli IRQ da 0 a 7 e l’altro gli IRQ da 8 a 15. Nella maggior parte dei casi
gli interrupts delle comunicazioni seriali risiedono negli IRQ da 0 a 7, quindi viene
usato il PIC1, che è localizzato all’indirizzo esadecimale “0x20”.
Bit Disabilitazione IRQ Funzione 7 IRQ7 Porta parallela 6 IRQ6 Controller del floppy disk 5 IRQ5 Riservato/Scheda audio 4 IRQ4 Porta seriale 3 IRQ3 Porta seriale 2 IRQ2 PIC2 1 IRQ1 Tastiera 0 IRQ0 Timer di sistema
Tabella 2: Control Word del PIC1 ("0x21")
Bit Disabilitazione IRQ Funzione 7 IRQ15 Riservato 6 IRQ14 Hard disk drive 5 IRQ13 Coprocessore matematico 4 IRQ12 Mouse PS/2 3 IRQ11 Riservato 2 IRQ10 Riservato 1 IRQ9 IRQ2 0 IRQ8 Real Time Clock
Tabella 3: Control Word del PIC2 ("0xA1")
Capitolo 3 – Simulazioni e verifiche 76
Porte di tipo Multi-Comm stanno diventando abbastanza comuni e quindi la Tabella 3
include i dati per il PIC2, che è localizzato all’indirizzo esadecimale “0xA0”. Il PIC2 è
responsabile degli IRQ da 8 a 15. Esso opera esattamente allo stesso modo del PIC1 ad
eccezione del fatto che gli EOI (End Of Interrupt) vanno alla porta “0xA0” mentre le
disabilitazioni (“Masking”) degli IRQ sono eseguite usando la porta “0xA1”.
Molte delle procedure di inizializzazione sono fatte dal BIOS. Il nostro interesse si deve
quindi focalizzare solo su due istruzioni di setup. La prima è
outportb(0x21,(inportb(0x21) & 0xFE); che seleziona quali interrupts devono
essere disabilitati (“Mask”). Così se vogliamo abilitare l’IRQ4 dobbiamo
complementare ad uno la word “0x10” (16) e quindi ottenere la word “0xEF” (239).
Questo significa disabilitare gli IRQ 7,6,5,3,2,1 e 0 lasciando abilitato l’IRQ 4.
Naturalmente questa istruzione non altera l’abilitazione degli IRQ fatta da altri
programmi poiché la funzione & (and o prodotto logico) tra la word corrispondente
all’istruzione inportb(0x21) e la word “0xFE” è uno solo quando i rispettivi bit sono
entrambi ad uno. Per esempio, se un altro programma aveva abilitato l’IRQ5 e quindi il
bit corrispondente era a zero, il prodotto logico di zero con uno da come risultato ancora
zero e quindi l’interrupt resta abilitato.
L’altra istruzione da considerare è outportb(0x20,0x20); che segnala la fine
dell’interrupt al PIC. Si utilizza questo comando alla fine della procedura di servizio
dell’interrupt in modo tale che si possano di nuovo accettare gli interrupts a bassa
priorità.
3.3.3 Configurazione dell’UART
Come prima istruzione bisogna disattivare la generazione di interrupt della UART per
far in modo che l’inizializzazione della stessa non possa essere interrotta. Quindi si ha, a
questo punto, il setup dei vettori di interrupt. Il passo successivo è quello di scegliere la
velocità della comunicazione; si deve perciò impostare il bit 7 (DLAB) dell’LCR (Line
Control Register) per poter accedere ai bytes alto e basso del Divisor Latch. Se, ad
esempio, si vuole una velocità di 38,4 kbps bisogna impostare una divisione per tre e
quindi byte alto del Divisor Latch deve essere “0x00” e quello basso “0x03”.
L’operazione successiva è quella di disattivare il Divisor Latch Access Bit (DLAB) in
modo da poter accedere all’Interrupt Enable Register ed ai buffers di ricezione e di
trasmissione. Per disattivare il DLAB e contemporaneamente impostare la
Capitolo 3 – Simulazioni e verifiche 77
comunicazione (per esempio a 8 bits dati, nessuna partità e 1 bit di stop) bisogna
caricare nel registro di controllo di linea (LCR) la word “0x03”.
La linea di codice successiva abilita i buffers FIFO agendo sul First In/First Out Control
Register (FCR). Per avere il livello di trigger a 14 bytes, i bits 6 e 7 sono a valore alto e
per attivare i buffers FIFO il bit 0 è alto. Inoltre per ripulire i due buffers si devono
impostare ad uno i bit 2 e 3 (che passano a valore basso automaticamente dopo il reset
dei buffers). Si trova perciò che la word da caricare nel registro FCR deve essere
“0xC7”.
Successivamente vengono attivati i segnali DTR, RTS e OUT 2 (quest’ultimo per
maggiore compatibilità) grazie all’istruzione outportb(PORT1 + 4,0x0B);. Ora non
resta che riattivare gli interrupt; poiché il programma è interessata solo all’interrupt
segnalante nuovi dati ricevuti occorrerà abilitare solo questo tipo di interrupt tramite
l’istruzione outportb(PORT1 + 1,0x01);. L’Appendice fornisce una descrizione
completa dei registri appena menzionati. Ecco la parte di codice in questione:
outportb(PORT1 + 1 , 0); /* Turn off interrupts - Port1 */ oldport1isr = getvect(INTVECT); /* Save old Interrupt Vector of later recovery */ setvect(INTVECT, PORT1INT); /* Set Interrupt Vector Entry */ /* PORT 1 - Communication Settings */ outportb(PORT1 + 3 , 0x80); /* SET DLAB ON */ outportb(PORT1 + 0 , 0x0C); /* Set Baud rate-Divisor Latch Low Byte */ /* Default 0x03 = 38,400 BPS */ /* 0x01 = 115,200 BPS */ /* 0x02 = 57,600 BPS */ /* 0x06 = 19,200 BPS */ /* 0x0C = 9,600 BPS */ /* 0x18 = 4,800 BPS */ /* 0x30 = 2,400 BPS */ outportb(PORT1 + 1 , 0x00); /* Set Baud rate-Divisor Latch High Byte*/ outportb(PORT1 + 3 , 0x03); /* 8 Bits, No Parity, 1 Stop Bit */ outportb(PORT1 + 2 , 0xC7); /* FIFO Control Register */ outportb(PORT1 + 4 , 0x0B); /* Turn on DTR, RTS, and OUT2 */ outportb(0x21,(inportb(0x21) & 0xEF)); /* Set Programmable Interrupt Controller */ /* COM1 (IRQ4) - 0xEF */ /* COM2 (IRQ3) - 0xF7 */ /* COM3 (IRQ4) - 0xEF */ /* COM4 (IRQ3) - 0xF7 */ outportb(PORT1 + 1 , 0x01); /* Interrupt when data received */
Capitolo 3 – Simulazioni e verifiche 78
3.3.4 Routine principale
Il programma si occupa di verificare che il file specificato nella linea di comando sia
valido e che sia possibile aprire in scrittura il file ausiliario per salvare i dati ricevuti.
Dalla linea di comando è inoltre possibile specificare il rate di codifica desiderato
digitando “1” oppure “2” subito dopo il file di ingresso. Se questo controllo da esito
positivo, il programma attende la pressione di un tasto prima di inviare i dati alla seriale.
Il codice della routine principale è il seguente:
do { if (bufferin != bufferout) { ch = buffer[bufferout]; bufferout++; if (bufferout == 1024) {bufferout = 0;} fputc(ch,foutput); bytessalvati++; } if (byteslettitotali==bytessalvati) { if (!feof(finput)) { bytesletti=0; while ((bytesletti<4095)&&(!feof(finput))) { carattere=fgetc(finput); if (!feof(finput)) { bufferfile[bytesletti]=carattere; bytesletti++; } } byteslettitotali+=bytesletti; header1=bytesletti/16; header2=(bytesletti%16)*16+rate*2; outportb(PORT1, header1); outportb(PORT1, header2); for(i=0;i<bytesletti;i++) outportb(PORT1, bufferfile[i]); printf("Inviati %d bytes\n",bytesletti); } } if (kbhit()) c = getch(); } while (((!feof(finput))||(byteslettitotali!=bytessalvati))&&(c!=27)); outportb(PORT1 + 1 , 0); /* Turn off interrupts - Port1 */ outportb(0x21,(inportb(0x21) | 0x10)); /* MASK IRQ using PIC */ /* COM1 (IRQ4) - 0x10 */ /* COM2 (IRQ3) - 0x08 */ /* COM3 (IRQ4) - 0x10 */ /* COM4 (IRQ3) - 0x08 */ setvect(INTVECT, oldport1isr); /* Restore old interrupt vector */
Capitolo 3 – Simulazioni e verifiche 79
Sono presenti in un ciclo do-while tre controlli if:
• Controllo della presenza di nuovi dati in arrivo e salvataggio degli stessi in un
file;
• Controllo della possibilità di spedire nuovi dati sulla porta seriale se si sono già
ricevuti quelli spediti in precedenza (o non si è ancora spedito niente);
• Controllo della pressione di un tasto.
Prima dei dati del file vengono inviati i dati header1 e header2 che contengono i valori
di PLW e PSF (calcolati dal numero di word del file da inviare e dal rate scelto).
Il loop di controllo termine quando tutti i dati del file da spedire sono stati trasmessi e
ricevuti oppure se viene premuto il tasto “ESC” sulla tastiera. Le righe successive
servono per chiudere correttamente la trasmissione seriale, riportando ai valori di
partenza l’IRQ e l’interrupt vector della porta seriale usata. Successivamente il
programma si occupa di confrontare i dati ricevuti, memorizzati nel file ausiliario, con
quelli contenuti nel file di ingresso. Se il programma riscontra una differenza,
comparando i due files, si ha una segnalazione di errore e viene evidenziata la posizione
nella quale c’è stata l’incongruenza.
La figura seguente mostra il programma in esecuzione. Come file di ingresso si è scelto
l’eseguibile del programma stesso e il rate scelto è di 2 Mbps come specificato nella
linea di comando. Si può notare l’invio e la ricezione di 4095 bytes di informazioni alla
volta.
Figura 11: Programma per la prova in esecuzione
Capitolo 3 – Simulazioni e verifiche 80
3.4 Verifica
Dopo aver introdotto i moduli aggiuntivi implementati sulla FPGA ed il programma in
esecuzione sul PC per la comunicazione seriale si può ora procedere alla descrizione del
processo di verifica vero e proprio dei dispositivi di codifica-decodifica FHSS.
Il sistema nel suo complesso può essere schematizzato nella figura seguente:
Clock
Dipswitch(7:0)
Push_S2
TxD
RxD
Push_S3
Digit(3:0)
Segment(7:0)
TP1
FPGAOscillatore (40 MHz)
Pulsanti
Dipswitch
Computer
Oscilloscopio
Display
TxD
RxD
Figura 12: Sistema completo
La figura seguente mostra una fotografia del banco di prova utilizzato.
Figura 13: Fotografia del banco di prova
Capitolo 3 – Simulazioni e verifiche 81
Per la simulazione dei dati MAC è possibile utilizzare qualsiasi tipo di file
(naturalmente di lunghezza non nulla) poiché le informazioni sono sempre memorizzate
come una successione di bytes (8 bits) di dati.
Se il file in ingresso ha una dimensione maggiore di 4095 bytes (il payload del
pacchetto può essere costituito al massimo da 4095 ottetti), il programma invierà alla
FPGA blocchi di 4095 bytes per volta aspettando di ricevere i dati decodificati prima
dell’invio del blocco successivo (vedi Figura 11).
Per la prova si è scelto di utilizzare un semplice file di testo (“prova.txt”) di 19 bytes. Le
informazioni contenute nel file verranno inserite nel payload del pacchetto durante la
codifica.
La scelta di un file di dimensione ridotta permette di visualizzare in modo soddisfacente
la forma d’onda del pacchetto sull’oscilloscopio nella sua interezza.
Prima di iniziare la prova è necessario il RESET del sistema che si ottiene premendo il
pulsante S2 della scheda. La connessione tra il PC e la scheda avviene tramite un cavo
“null modem” (vedi Appendice) che permette la comunicazione tra le due porte seriali.
Sulla scheda sono presenti diversi “test point” che permettono di rendere disponibili
all’esterno segnali interni della FPGA. Questi collegamenti devono essere specificati
opportunamente nel constraints file letto dal software durante la fase di
implementazione della FPGA. Uno di questi “test point” (TP1) viene quindi collegato al
pin DATA_OUT dell’encoder che, a sua volta, è cortocircuitato con il pin DATA_IN
del decoder. Rilevando la tensione presente su questo morsetto mediante una delle
sonde dell’oscilloscopio, è possibile visualizzare la forma d’onda del pacchetto FHSS.
L’oscilloscopio deve essere configurato in modo tale da campionare il segnale rilevato
sulla sonda per un certo intervallo di tempo e partendo dal fronte di salita del segnale.
3.4.1 Pacchetto FHSS codificato al rate di 1 Mbps
Per effettuare la prova occorre digitare dalla linea di comando DOS del PC:
> starttxrx prova.txt
La Figura 14 mostra il contenuto della finestra “Prompt dei comandi” dopo tale
digitazione. Si può notare che la verifica del processo di codifica-decodifica è andato a
buon fine.
La fotografia di Figura 15 rappresenta la forma d’onda del pacchetto visualizzata sullo
schermo dell’oscilloscopio.
Capitolo 3 – Simulazioni e verifiche 82
L’oscilloscopio consente di salvare la forma d’onda campionata durante la prova su un
dischetto. I dati vengono salvati in un formato tale da poter essere elaborati, in un
secondo tempo, con programmi tipo Microsoft Excel o MATLAB.
Figura 14: Prova ad 1 Mbps
Figura 15: Fotografia dell'oscilloscopio in fase di salvataggio dei campioni sul dischetto
Capitolo 3 – Simulazioni e verifiche 83
I campioni, salvati nel file creato dall’oscilloscopio, sono costituiti da una serie di
coppie (tempo, ampiezza). Importando tale file in Microsoft Excel è possibile creare il
grafico della forma d’onda campionata. La figura seguente mostra il grafico del
pacchetto FHSS.
Pacchetto FHSS (1 Mbps)
-0,20
0,20,40,60,8
11,21,41,61,8
22,22,42,62,8
33,23,4
-1 19 39 59 79 99 119 139 159 179 199 219 239 259 279
Tempo (μs)
Am
piez
za (V
)
Figura 16: Forma d'onda del pacchetto FHSS (1 Mbps)
L’asse dei tempi inizia da –1 μs poiché l’oscilloscopio pone l’origine dei tempi in
corrispondenza del primo fronte di salita del segnale.
Si possono analizzare separatamente le varie parti che compongono il pacchetto:
La parte Sync durerà per i primi 80 μs come evidenziato in Figura 17.
Nei successivi 16 μs si avrà lo Start Frame Delimiter (SFD) costituito dalla sequenza
“0000110010111101” (Figura 18)
Dopo lo SFD si avrà l’Header del pacchetto di durata pari a 32 μs (Figura 19). I primi
12 valori (“11001000000”) corrispondono al PLW che è stato spedito partendo bit meno
significativo. Il valore in decimale è 19 e rappresenta il numero di ottetti contenuti nel
payload. I successivi quattro valori (“0000”) identificano il PSF. Infine gli ultimi 16
valori dell’Header determinano il campo HEC.
Capitolo 3 – Simulazioni e verifiche 84
In Figura 20 è presente il grafico del primo blocco di 33 simboli della parte “Whitened
PSDU” del pacchetto. Il primo valore rappresenta il simbolo detto “stuff” che ha valore
“1”; ciò determina che i successivi 32 simboli saranno invertiti.
Sync
-0,20
0,20,40,60,8
11,21,41,61,8
22,22,42,62,8
33,23,4
-1 9 19 29 39 49 59 69 79
Tempo (μs)
Am
piez
za (V
)
Figura 17: Parte Sync del pacchetto FHSS
SFD
-0,20
0,20,40,60,8
11,21,41,61,8
22,22,42,62,8
33,23,4
79 81 83 85 87 89 91 93 95
Tempo (μs)
Am
piez
za (V
)
Figura 18: Parte SFD del pacchetto FHSS
Capitolo 3 – Simulazioni e verifiche 85
Header
-0,20
0,20,40,60,8
11,21,41,61,8
22,22,42,62,8
33,23,4
95 100 105 110 115 120 125
Tempo (μs)
Am
piez
za (V
)
Figura 19: Parte Header del pacchetto FHSS (1 Mbps)
Whitened PSDU (Primo blocco di 33 simboli)
-0,20
0,20,40,60,8
11,21,41,61,8
22,22,42,62,8
33,23,4
127 132 137 142 147 152 157
Tempo (μs)
Am
piez
za (V
)
Figura 20: Primo blocco di 33 simboli “Whitened PSDU” (1 Mbps)
Capitolo 3 – Simulazioni e verifiche 86
3.4.2 Pacchetto FHSS codificato al rate di 2 Mbps
Per effettuare la prova occorre digitare dalla linea di comando DOS del PC:
> starttxrx prova.txt 2
La Figura 21 mostra il contenuto della finestra “Prompt dei comandi” dopo tale
digitazione.
Figura 21: Prova a 2 Mbps
Ancora una volta è possibile analizzare separatamente le varie parti che compongono il
pacchetto grazie al segnale campionato al morsetto TP1 dall’oscilloscopio.
La parte di Preambolo viene sempre codificata alla velocità di 1 Mbps ed è quindi del
tutto identica a quella vista nel paragrafo precedente (vedi Figura 17 e Figura 18).
In Figura 23 è rappresentato l’Header del pacchetto: i primi 12 valori indicano, partendo
dal bit meno significativo, il PLW che è ancora pari a 19 (in decimale); i successivi 4
valori (“0010”) identificano, partendo ancora dal bit meno significativo, il campo PSF; i
rimanenti 16 valori appartengono al campo HEC dell’Header.
La Figura 24 mostra il primo blocco di 33 simboli della parte “Whitened PSDU” del
pacchetto codificato al rate di 2 Mbps. Il primo simbolo (“10”) specifica che i successivi
32 simboli hanno subito una inversione.
Capitolo 3 – Simulazioni e verifiche 87
Pacchetto FHSS (2 Mbps)
-0,20
0,20,40,60,8
11,21,41,61,8
22,22,42,62,8
33,23,4
-1 19 39 59 79 99 119 139 159 179 199
Tempo (μs)
Am
piez
za (V
)
Figura 22: Forma d'onda del pacchetto FHSS (2 Mbps)
Header
-0,20
0,20,40,60,8
11,21,41,61,8
22,22,42,62,8
33,23,4
95 100 105 110 115 120 125
Tempo (μs)
Am
piez
za (V
)
Figura 23: Parte Header del pacchetto FHSS (2 Mbps)
Capitolo 3 – Simulazioni e verifiche 88
Whitened PSDU (Primo blocco di 33 simboli)
-0,20
0,20,40,60,8
11,21,41,61,8
22,22,42,62,8
33,23,4
127 132 137 142 147 152 157
Tempo (μs)
Am
piez
za (V
)
Figura 24: Primo blocco di 33 simboli “Whitened PSDU” (2 Mbps)