Modulatore QPSK
Transcript
Modulatore QPSK
Università di Roma Tor Vergata - Facoltà di Ingegneria Dipartimento di Elettronica Digitale Definizione, progetto VHDL-RTL e realizzazione tramite FPGA di un modulatore QPSK con sagomatura di impulso a coseno rialzato a sintesi diretta Relatore Ch. mo Prof. Giancarlo Cardarilli Correlatore Ing. Marco Re Correlatore Ing. Domenico Giancristofaro Anno Accademico 2000-2001 Tesi di laurea di Antonio D’Ottavio matr. II009409 Indice Elenco delle figure vi 1 Modulazioni digitali 1.1 Sommario . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Modulazione . . . . . . . . . . . . . . . . . . . . . . 1.2.1 Traslazione in frequenza . . . . . . . . . . . . 1.2.1.1 Spazio dei segnali . . . . . . . . . . 1.2.1.2 Tipologie di modulazioni satellitari 1.3 Principi di demodulazione . . . . . . . . . . . . . . . 1.3.1 Demodulatore . . . . . . . . . . . . . . . . . . 1.3.2 Decisore . . . . . . . . . . . . . . . . . . . . . 1.3.3 Interferenza intersimbolica . . . . . . . . . . . 1.3.4 Principi di codifica . . . . . . . . . . . . . . . 1.3.5 Capacità trasmissiva . . . . . . . . . . . . . . 2 Architetture modulatori QPSK 2.1 Sommario . . . . . . . . . . . . . . . . . . . 2.2 Realizzazioni digitali di modulatori QPSK . 2.2.1 Modulatore DDFS . . . . . . . . . . 2.2.2 Modulatore classico . . . . . . . . . 2.2.2.1 Modulatore classico con fclk 3 Implementazione SRRC polifase 3.1 Sommario . . . . . . . . . . . . . . . . 3.2 Progetto del filtro SRRC . . . . . . . . 3.3 Implementazione polifase SRRC . . . . 3.3.1 Modello Matlab . . . . . . . . . 3.4 Modello VHDL . . . . . . . . . . . . . 3.4.1 Polifase standard gated-clock . 3.4.1.1 SRRCxN . . . . . . . 3.4.1.2 Rate Adapter . . . . . 3.4.1.3 Risultati sperimentali 3.4.2 ROM Polifase clock-enable . . . i . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = 4 × fif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 3 4 6 6 12 12 14 17 21 23 . . . . . 26 26 27 27 28 30 . . . . . . . . . . 33 33 33 35 35 37 37 37 39 40 40 3.4.2.1 Risultati sperimentali . . . . . . . . . . . . . 4 Implementazione Modulatore QPSK 4.1 Sommario . . . . . . . . . . . . . . . . 4.2 Modello Matlab . . . . . . . . . . . . . 4.3 Modelli VHDL . . . . . . . . . . . . . 4.3.1 Modulatore classico . . . . . . 4.3.2 ThinModulator . . . . . . . . . 4.3.2.1 Risultati sperimentali 4.3.2.1.1 Test VHDL . 4.3.2.1.2 Test FPGA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 44 44 44 47 47 49 53 53 54 5 Conclusioni 58 A Sintesi diretta di frequenza digitale A.1 Sommario . . . . . . . . . . . . . . . A.2 DDFS . . . . . . . . . . . . . . . . . A.3 Pianificazione delle frequenze . . . . A.3.1 Spurie dovute al DAC . . . . A.3.2 Spurie dovute al troncamento A.4 Convertitore Fase-Frequenza . . . . . A.4.1 Algoritmo CORDIC . . . . . A.5 Descrizione modello matematico . . A.6 Descrizione modello VHDL . . . . . . . . . . . . . . . . . della . . . . . . . . . . . . . . . . . . . . . . . . fase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 59 59 61 61 62 63 64 65 66 B Sistemi Multirate B.1 Sommario . . . . . . . . . . . B.2 Downsampling e Upsampling B.3 Architetture Multirate . . . . B.3.1 CIC . . . . . . . . . . B.3.2 Polifase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 71 71 74 75 78 C Logiche programmabili C.1 Sommario . . . . . . . . . . . . . . C.2 Tipologie di logiche programmabili C.3 Architettura Virtex . . . . . . . . . C.3.1 CLB . . . . . . . . . . . . . C.3.2 IOB . . . . . . . . . . . . . C.3.3 Risorse di connessione . . . C.3.4 Circuiti di utilità . . . . . . C.3.4.1 DLL . . . . . . . . C.3.4.2 BlockRAM . . . . C.3.4.3 SRL16 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 81 81 83 83 85 86 86 87 87 88 ii . . . . . . . . . . D Flusso di progettazione D.1 Sommario . . . . . . . . . . . D.2 Modello Matematico . . . . . D.3 Modello VHDL . . . . . . . . D.4 Sintesi del progetto . . . . . . D.5 Mappatura . . . . . . . . . . D.6 Piazzamento delle risorse . . D.7 Connessione delle risorse . . . D.8 Simulazione back-annotata . D.9 Programmazione della FPGA D.10 Verifica sperimentale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 89 89 89 90 90 91 91 91 91 92 E Listati Matlab E.1 NCO . . . . . . . . . . . . . . . . . . . . . . . . . NCO Q.m . . . . . . . . . . . . . . . . . . . . . Imposta frequenze Q.m . . . . . . . . . Imposta NCO Q.m . . . . . . . . . . . . Crea super accumulatore Q.m . . . . . Tronca Q.m . . . . . . . . . . . . . . . . Crea coseno e seno Q.m . . . . . . . . Forward cordic Q.m . . . . . . . . . . . Calcola rotazioni Cordic.m . . . Visualizza spettro e SFDR p.m Calcola SFDR.m . . . . . . . . . . . . . Calcola incremento fase NCO.m . . . . . . . . Visualizza spettro NCO VHDL.m . . . . . . . E.2 Creazione vettori di test . . . . . . . . . . . . . . CreaVettoriTest.m . . . . . . . . . . . . . . . . . CreaSequenzaPatternGenerator.m . . . . . . . . E.3 Polifase . . . . . . . . . . . . . . . . . . . . . . . Creazione coefficienti . . . . . . . . . . . . . . . . CreaCoeffsFreqSamplScaled.m . . . . . . applica polifase.m . . . . . . . . . . . . . RaisedCosineResponse.m . . . . . . . . . CreaROM.m . . . . . . . . . . . . . . . . Test VHDL . . . . . . . . . . . . . . . . . . . . . PolyphasePSDVHDLvsPSDMatlab.m . . applica polifase.m . . . . . . . . . Test FPGA . . . . . . . . . . . . . . . . . . . . . VisualizzaPSDPolifaseVHDLFPGAout.m applica polifase.m . . . . . . . . . E.4 Modulatore . . . . . . . . . . . . . . . . . . . . . Tabella e grafico BER . . . . . . . . . . . . . . . CreaTabellaBER.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 93 93 94 94 94 94 95 96 96 96 97 97 97 97 98 100 100 100 101 102 102 103 104 105 105 105 106 106 106 106 107 iii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . calcolaBER.m . . . . . . . . . . . . Test VHDL . . . . . . . . . . . . . . . . . . . . . QPSKModemPSDeBERVHDLvsMatlab.m applica polifase.m . . . . . . . . . Test FPGA . . . . . . . . . . . . . . . . . . . . . QPSKModemPSDFPGAvsPSDMatlab.m applica polifase.m . . . . . . . . . F Listati VHDL nco.vhd . . . . . . . . . . . . . . . . . accumulator.vhd . . . . . . . . . cordic pipelined unrolled.vhd . cordic base j.vhd . . . . adder 12.vhd . . . adder 13.vhd . . . reg 12.vhd . . . . reg 13.vhd . . . . shifter.vhd . . . . . cosine rebuild.vhd . . . . . . . . delay 13.vhd . . . . . . . . . . . sine rebuild.vhd . . . . . . . . . to first quadrant.vhd . . . . . . troncatore 12.vhd . . . . . . . . polyphase gatedClock.vhd . . . . . . srrc coeffs.vhd . . . . . . . . . . rate adapter.vhd . . . . . . . . . coeffs selector.vhd . . . . counter divider 3.vhd . counter divider 4.vhd . fftr.vhd . . . . . . counter divider 6.vhd . selector.vhd . . . . . . . . srrc x n.vhd . . . . . . . . . . . fir 1.vhd . . . . . . . . . adder 7.vhd . . . fir multiplier.vhd shift reg.vhd . . . mux 6.vhd . . . . . . . . ROM polyphase.vhd . . . . . . . . . counter.vhd . . . . . . . . . . . . srrc x n.vhd . . . . . . . . . . . demux 3x10.vhd . . . . . mux 3x12.vhd . . . . . . ROMx3.vhd . . . . . . . . iv . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 108 112 112 112 113 114 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 116 117 120 121 121 122 122 122 123 123 123 124 124 124 125 125 126 130 130 131 131 132 132 136 138 139 139 139 140 140 141 143 143 143 148 ROMx4.vhd . . . . . . . . . . . . . . ROMx6.vhd . . . . . . . . . . . . . . shift reg.vhd . . . . . . . . . . . . . Modulator BlockRAM.vhd . . . . . . . . . . . . adder I Q.vhd . . . . . . . . . . . . . . . . counter.vhd . . . . . . . . . . . . . . . . . . multiplier I Q.vhd . . . . . . . . . . . . . NCO basic.vhd . . . . . . . . . . . . . . . srrc x n.vhd . . . . . . . . . . . . . . . . . ram.vhd . . . . . . . . . . . . . . . . shift reg.vhd . . . . . . . . . . . . . FIFO RAM ThinModulator.vhd . . . . . . . . counter.vhd . . . . . . . . . . . . . . . . . . Data Source Interface.vhd . . . . . . . . . asynch fifo 2x15.vhd . . . . . . . . ffd.vhd . . . . . . . . . . . . . . . . . ffd en.vhd . . . . . . . . . . . . . . ffs.vhd . . . . . . . . . . . . . . . . . ThinModulator.vhd . . . . . . . . . . . . . mult C2 adder.vhd . . . . . . . . . mux 2x7.vhd . . . . . . . . . . . . . ram 12x4096 rising registered.vhd shift reg.vhd . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 161 162 163 164 164 164 165 166 166 166 168 168 169 170 170 170 171 172 173 173 174 174 G Acronimi 175 Bibliografia 178 Indice analitico 183 v Elenco delle figure 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 1.10 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.18 1.19 1.20 1.21 1.22 1.23 1.24 Spettro segnale NRZ . . . . . . . . . . . . . . . . . . . . . Spettro di un segnale in banda traslata . . . . . . . . . . . Trasformata di Hilbert nel dominio della frequenza . . . . Modulazione QPSK nel tempo . . . . . . . . . . . . . . . Tipologie di QPSK . . . . . . . . . . . . . . . . . . . . . . Confronto costellazioni M–QAM e M–PSK . . . . . . . . . Andamento temporale BFSK . . . . . . . . . . . . . . . . Andamento temporale fase del segnale MSK . . . . . . . . Risposta all’impulso del filtro gaussiano . . . . . . . . . . Confronto spettri QPSK, MSK e GMSK . . . . . . . . . . Demodulatore con banco di correlatori . . . . . . . . . . . Demodulatore con filtro adattato . . . . . . . . . . . . . . Effetto filtro adattato . . . . . . . . . . . . . . . . . . . . Costellazione BPSK e densità di probabilità condizionate Effetto . . . . . . . . . . . . . . intersimbolica P∞ interferenza m 1 X f + T per T < 2W . . . . . . . . . . . . . . Pm=−∞ ∞ 1 X f+m m=−∞ T per T = 2W . . . . . . . . . . . . . . t sinc P∞ π T . . . .m. . . . . . . 1. . . . . . . . . . . . . . . . m=−∞ X f + T per T > 2W . . . . . . . . . . . . . . Sagomatura d’impulso a coseno rialzato . . . . . . . . . . Diagrammi vettoriali QPSK con sagomatura d’impulso . . Trasmissione numerica . . . . . . . . . . . . . . . . . . . . Codificatore (3, 1, 3) . . . . . . . . . . . . . . . . . . . . . Piano di Shannon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 5 8 8 9 10 11 11 12 13 14 15 16 18 19 19 19 20 21 21 22 23 25 2.1 2.2 2.3 2.4 2.5 2.6 Modulatore Modulatore Modulatore Modulatore Modulatore Modulatore . . . . . . . . . . . . 26 27 29 30 31 32 3.1 SRRC 19 coefficienti interpolante 3 . . . . . . . . . . . . . . . 36 Standard . . . . . . . . . . DDFS . . . . . . . . . . . QPSK classico per un solo QPSK classico 3 data rate QPSK classico 3 data rate QPSK classico 3 data rate vi . . . . . . . . . . . . . . . . data rate . . . . . . . . . . Ottimizzato . fclk = 4 × fif . . . . . . . . . . . . . . . . . . 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 SRRC 25 coefficienti interpolante 4 . . . . . SRRC 39 coefficienti interpolante 6 . . . . . SRRC interpolante 3, 4, 6 . . . . . . . . . . FIR iesimo . . . . . . . . . . . . . . . . . . . Rate Adapter . . . . . . . . . . . . . . . . . SRRCxN versione ROM . . . . . . . . . . . Confronto Polifase VHDL – Polifase Matlab Confronto Polifase FPGA – Polifase Matlab . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 36 37 38 39 41 42 43 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 4.11 4.12 4.13 4.14 Effetto del canale sul segnale modulato QPSK . . . . . Grafico prestazioni modem Matlab in termini di BER Modulatore classico . . . . . . . . . . . . . . . . . . . . SRRCxN versione RAM . . . . . . . . . . . . . . . . . RAM 12 × 4096 . . . . . . . . . . . . . . . . . . . . . . Temporizzazioni modulatore classico . . . . . . . . . . ThinModulator . . . . . . . . . . . . . . . . . . . . . . FIFO RAM ThinModulator . . . . . . . . . . . . . . . Clock×2 . . . . . . . . . . . . . . . . . . . . . . . . . . Interfaccia modulatore – sorgente dati . . . . . . . . . Confronto Modulatore x3 VHDL – Matlab . . . . . . . Confronto Modulatore x3 FPGA – Matlab . . . . . . . Confronto Modulatore x4 FPGA – Matlab . . . . . . . Confronto Modulatore x6 FPGA – Matlab . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 46 47 48 48 49 50 51 52 52 53 56 57 57 A.1 Schema di principio DDFS . . . . . . . . . . . A.2 Spettro in uscita dal DAC . . . . . . . . . . . A.3 Andamento nel tempo della parola troncata . A.4 Spettro dente di sega . . . . . . . . . . . . . . A.5 Ottimizzazione del convertitore fase-ampiezza A.6 Rotazione planare . . . . . . . . . . . . . . . A.7 Uscita DDFS nel tempo . . . . . . . . . . . . A.8 Spettro Coseno Matlab . . . . . . . . . . . . . A.9 NCO VHDL . . . . . . . . . . . . . . . . . . . A.10 Iterazione iesima . . . . . . . . . . . . . . . . A.11 Cordic Pipelined Unrolled . . . . . . . . . . . A.12 Spettro coseno generato dal DDFS VHDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 61 62 62 63 64 66 67 67 68 69 70 B.1 B.2 B.3 B.4 B.5 B.6 B.7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 73 73 74 74 75 76 Upsampling . . . . . . . . . . . . . . . Upsampler . . . . . . . . . . . . . . . . Downsampling . . . . . . . . . . . . . Downsampler . . . . . . . . . . . . . . Cambiamento di rate frazionario . . . Nobili Identità . . . . . . . . . . . . . Integratore e sua risposta in frequenza vii . . . . . . . . . . . . . . . . . . . . . . . . . . . . B.8 B.9 B.10 B.11 B.12 B.13 Comb e sua risposta in frequenza . . . Interpolatore CIC . . . . . . . . . . . . Decimatore CIC . . . . . . . . . . . . Spettro del CIC per R=2, N=1, M=1 Effetto di M sulla frequenza del CIC . Trasformazioni interpolatore polifase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76 76 77 77 78 79 C.1 C.2 C.3 C.4 C.5 C.6 C.7 Gerarchia implementazioni circuiti logici Implementazione di un moltiplicatore . . Slice Virtex . . . . . . . . . . . . . . . . CLB Virtex . . . . . . . . . . . . . . . . VersaBlock . . . . . . . . . . . . . . . . Clock globale . . . . . . . . . . . . . . . Configurazione delle BlockRAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 84 85 85 86 87 88 viii Ringraziamenti Dal punto di vista didattico desidero ringraziare molti dei miei insegnanti, un pensiero particolare per Francesco Valdoni che mi ha introdotto ad una visione più ingegneristica delle Comunicazioni Elettriche, e per Giancarlo Cardarilli, Marco Re, Andrea Del Re e Dario Gelfusa grazie ai quali quegli stessi concetti hanno trovato applicazione pratica in questa Tesi in un contesto fortemente motivante. Un ringraziamento ad Alenia Spazio per l’occasione formativa ed in particolare all’Ing. Domenico Giancristofaro per la pazienza dimostrata nei miei confronti ed il notevole apporto teorico. Un rilevante contributo è giunto anche dai NewsGroup Comp.arch.fpga, comp.lang.vhdl e comp.dsp nei quali Ray Andraka, Allan Herrimann, Jacky Renaux e Brian Philopsky svolgono un importante servizio di volontariato culturale. Come dimenticare i compagni con cui sin dall’inizio abbiamo affrontato insieme questa avventura, i loro nomi sono nella mia mente e nei tanti ricordi che ci accomunano, un grazie particolare a chi ha sempre corso dinanzi a me dimostrandomi giorno per giorno che ciò che sembrava impossibile in realtà non lo era, l’auspicio è di rimanere in contatto con tutti. Ancora un grazie per la mia famiglia, per tutto ciò che non mi viene in mente perché è banale, scontato, però esiste e mi ha consentito di arrivare a questo traguardo, grazie Mamma perché ogni giorno trascorso con te è un giorno felice. ix Introduzione Le comunicazioni spaziali rappresentano probabilmente uno dei settori di maggiore interesse dell’elettronica e delle telecomunicazioni, ad esse direttamente o indirettamente si debbono molti dei progressi scientifici degli ultimi 50 anni, numerose sono infatti le applicazioni nella vita quotidiana di idee e materiali derivati da attività spaziali. Queste comunicazioni erano un tempo adibite esclusivamente ad attività militare o scientifica e pertanto presentavano costi elevati e scarsa efficienza, l’avvento di servizi quale la tv digitale, la telefonia, il GPS ed altri le hanno rese maggiormente soggette alle leggi del mercato conseguentemente si è assistito ad un miglioramento progressivo delle prestazioni, dei costi e dell’efficienza. In questa rapida evoluzione l’unico aspetto che non è mai stato messo in discussione è la modulazione adottata, infatti da sempre per la trasmissione in ambito spaziale di segnali non di servizio si utilizza la modulazione QPSK in quanto essa come vedremo individua il punto di minimo in un ideale spazio sui cui assi ci sono l’efficienza spettrale, la semplicità circuitale1 e l’efficienza energetica2 . L’argomento della Tesi si può pertanto definire datato ed in fondo ben conosciuto tuttavia il rapido e costante evolversi delle tecniche digitali, affiancato dai processi di integrazione su larga scala, consente di dire qualcosa di nuovo anche nella realizzazione di un modulatore QPSK, al riguardo basta osservare che attualmente le FPGA3 sono utilizzate in applicazioni spaziali soltanto per circuiti marginali mentre esse sono destinate ad un ruolo primario nelle future realizzazioni in virtù delle prestazioni in rapida ascesa, della loro riprogrammabilità a distanza e soprattutto della riduzione di costi e tempi di progettazione che implicitamente consentono. Le specifiche tecniche dalle quali trae origine il modulatore QPSK sono state emesse dall’Alenia Aerospazio, una Società del gruppo Finmeccanica all’avanguardia nell’industria aerospaziale mondiale. Tra i suoi prodotti di maggior successo indubbiamente SkyPlex, un processore che consente l’accesso al satellite non più ad un unico flusso dati assemblato dalla stazione 1 che si traduce in spazi e pesi ridotti ovvero costi di lancio ridotti molta della energia del satellite viene utilizzata per comunicare, ottimizzando questo consumo si può aumentare sensibilmente la vita delle batterie e quindi del satellite stesso 3 Field Programmable Gate Array 2 1 2 gateway, bensi a più flussi i quali vengono demodulati separatamente, opportunamente assemblati e successivamente di nuovo modulati ed inviati verso Terra in un unico flusso. I satelliti che attualmente utilizzano Skyplex sono gli HotBird 4 e 5, dei geostazionari appartenenti all’operatore EUTELSAT [4] impiegati prevalentemente per la televisione digitale, al riguardo la presenza di molteplici piccole emittenti che hanno accesso al satellite, sembra confermare l’idea che Skyplex abbia effettivamente rappresentato un modo nuovo di concepire le comunicazioni satellitari. Le portanti utilizzate sono a 14GHz per HotBird 5 e 19Ghz per HotBird 4, è naturalmente impensabile allo stato attuale della tecnologia digitale pensare di produrre direttamente questi segnali, tuttavia i vantaggi del digitale sono fortemente desiderati ed allora nella presente Tesi si propone una soluzione di compromesso ossia l’utilizzo di un modulatore digitale che modula una portante intermedia a 40MHz generata in forma digitale mediante un DDFS4 a partire da un clock superiore a 160MHz, successive conversioni di frequenza analogiche traslano poi il segnale modulato alle frequenze realmente applicate all’amplificatore di potenza TWTA5 che alimenta l’antenna irradiante verso Terra. Le specifiche del modulatore digitale richiedono che esso sia in grado di accettare tre distinti data rate, 55Mbps, 82, 5Mbps e 110Mbps, inoltre al fine di eliminare l’interferenza intersimbolica deve essere applicata una sagomatura d’impulso con spettro a coseno rialzato e α = 0, 35 quale fattore di roll-off. 4 5 Direct Digital Frequency Synthesizer Travelling Wave Tube Amplifier Capitolo 1 Modulazioni digitali 1.1 Sommario La trasmissione di informazione tra una sorgente ed un destinatario attraverso un mezzo trasmissivo comporta sempre il ricorso alla modulazione che, a seconda della particolare applicazione, si propone di ottenere uno o più dei seguenti obiettivi: • minimizzare la potenza irradiata. • minimizzare la banda occupata. • minimizzare la complessità e quindi i costi. in questo capitolo si cercherà di evidenziare i motivi che da sempre portano a considerare la modulazione QPSK1 come la più adatta a comunicazioni spaziali ad elevato data rate, in quest’ottica vengono anche introdotti concetti quali la sagomatura dell’impulso, la demodulazione con filtro adattato, i criteri di decisione e la codifica. 1.2 Modulazione Molte delle moderne comunicazioni elettriche avvengono in forma digitale indipendentemente dal fatto che la sorgente sia digitale oppure analogica, il motivo di ciò è che a monte e/o a valle del canale trasmissivo il segnale subisce comunque delle elaborazioni digitali volte ad ottimizzarne le caratteristiche, pertanto la scelta di una trasmissione digitale rappresenta una soluzione di continuità. Lo spettro di un generico segnale randomico NRZ2 mostrato in Figura(1.1) evidenzia tuttavia come i segnali digitali non siano adatti alle tra1 2 Quadrature Phase Shift Keying No Return to Zero 3 CAPITOLO 1. MODULAZIONI DIGITALI 4 Figura 1.1: Spettro segnale NRZ smissioni in mezzi fisici reali, vi è infatti troppa potenza distribuita sui lobi laterali, essa è sia inutile ai fini della trasmissione dell’informazione che deleteria in quanto aumenta il livello del rumore in eventuali canali adiacenti. La potenza utile è invece addensata nei pressi della continua pertanto si rende necessaria una traslazione in frequenza al fine di poter inviare più sequenze digitali su di un unico mezzo trasmissivo. 1.2.1 Traslazione in frequenza La traslazione in frequenza nella sua forma più semplice si ottiene moltiplicando il segnale digitale in banda base, opportunamente filtrato, per una portante analogica a frequenza fc , ne deriva uno spettro bilatero centrato su questa frequenza come in Figura(1.2). Figura 1.2: Spettro di un segnale in banda traslata Al fine di poter confrontare sistemi operanti a frequenze diverse è importante poter rappresentare in banda base un qualsiasi segnale in banda CAPITOLO 1. MODULAZIONI DIGITALI 5 traslata s (t), a tal riguardo, in riferimento a sistemi reali, è di interesse il solo asse positivo delle frequenze, descritto dal segnale analitico [2] s+ (t) = s (t) + ŝ (t) (1.1) dove ŝ (t) = 1 ∗ s (t) πt (1.2) è la trasformata di Hilbert di s (t) il cui effetto nel dominio della frequenza è visualizzato in Figura(1.3), essa ruota di +90◦ le componenti a frequenza Figura 1.3: Trasformata di Hilbert nel dominio della frequenza positiva e di −90◦ quelle a frequenza negativa, ricordando inoltre che la traslazione in frequenza corrisponde ad una moltiplicazione per l’esponenziale complesso nel dominio del tempo si ottiene l’espressione dell’inviluppo complesso sl (t): sl (t) = s+ (t) e−2πfc t (1.3) Il segnale in banda traslata s (t) può pertanto essere rappresentato in tre diverse forme: Inviluppo Complesso: s (t) = < sl (t) e−2πfc t (1.4) s (t) = a (t) cos (2πfc t + ϕ (t)) (1.5) Modulo e fase: dove a (t) e ϕ (t) sono dei segnali reali in banda base che rappresentano rispettivamente l’ampiezza e la fase del segnale in banda traslata s (t). Quadratura: s (t) = sc (t) cos (2πfc t) − ss (t) sin (2πfc t) (1.6) CAPITOLO 1. MODULAZIONI DIGITALI 6 essendo sc (t) e ss (t) dei segnali in banda base denominati rispettivamente componente in fase e componente in quadratura del segnale in banda traslata s (t). La formulazione(1.6) è di fondamentale importanza in questa Tesi in quanto da essa si evince in maniera immediata lo schema di un possibile modulatore. 1.2.1.1 Spazio dei segnali Un qualsiasi segnale reale può essere rappresentato come un vettore nello spazio dei segnali, tale spazio eredita le proprietà classiche degli spazi vettoriali definiti dall’algebra lineare, in particolare è caratterizzato da una norma: s Z b p |s (t)|2 dt (1.7) ks (t) k = hs (t) , s (t)i = a che consente di individuare una base ossia un gruppo di N segnali ψj aventi norma unitaria ed ortogonali tra loro: hψj , ψk i = 0 ∀ j, k : j 6= k (1.8) Ogni segnale sm (t) appartenente allo spazio dei segnali può essere rappresentato come combinazione lineare dei vettori ψj (t) della base sm (t) = N X smj ψj (t) (1.9) J=1 essendo smj (t) la proiezione di sm (t) lungo la direzione dello spazio vettoriale individuata dal jesimo vettore ψj (t) della base. Nel caso di uno spazio bidimensionale si ha che m ∈ (1, 2) pertanto tralasciando la base che è uguale per ogni segnale si ha che il generico segnale sm (t) è individuato dal vettore s = [sm1 sm2 ]. Il progetto di una modulazione digitale si basa quindi sulla scelta di una base ortonormale nella quale rappresentare M segnali disposti a formare una costellazione le cui caratteristiche geometriche influenzano il progetto del trasmettitore e la qualità della ricezione. La sequenza di bit da trasmettere viene suddivisa in gruppi costituiti da b = log2 M bits, ogni gruppo individua un simbolo tra gli M di un alfabeto cui sono associati gli M segnali della costellazione. 1.2.1.2 Tipologie di modulazioni satellitari Il segnale in banda traslata espresso dall’equazione(1.5) evidenzia come l’informazione in banda base possa essere codificata sia nel modulo che nella CAPITOLO 1. MODULAZIONI DIGITALI 7 fase3 della portante. Per applicazioni satellitari non si utilizzano modulazioni che associano informazione al modulo della portante in quanto richiedono amplificatori lineari in classe A che non sfruttano al meglio la scarsa energia disponibile, inoltre tali modulazioni sono vulnerabili alle variazioni del guadagno del canale stesso. Nel caso di una modulazione M–PSK4 utilizzante una portante a frequenza fc e per la quale ogni simbolo da trasmettere sia caratterizzato da energia ES si ha l’espressione del segnale modulato: r 2ES 2π sm (t) = g (t) cos (m − 1) cos (2πfc t) − T M (1.10) r 2ES 2π g (t) cos (m − 1) sin (2πfc t) T M dove g(t) è la sagomatura d’impulso5 ed m = 1, 2, . . . , M è un intero associato al simbolo del quale è richiesta la trasmissione. La base è costituita dalle funzioni r 2 ψ1 (t) = g (t) cos (2πfc t) T r 2 ψ2 (t) = g (t) sin (2πfc t) T (1.11) pertanto ogni segnale modulato può essere rappresentato da un vettore: sm = [sm1 sm2 ] = √ Es cos 2π M (m − 1) √ Es sin 2π M (m − 1) (1.12) Le tipologie più comuni di M–PSK sono la BPSK6 (M= 2) e la QPSK(M= 4), per quest’ultima l’andamento nel tempo è illustrato in Figura(1.4), dove non essendo stata applicata la sagomatura dell’impulso si ha che l’inviluppo è costante, tale soluzione è di solo interesse teorico in quanto l’efficienza energetica che ne deriva non bilancia i numerosi problemi derivanti dall’insorgere dell’interferenza intersimbolica. La costellazione QPSK è costituita da 4 punti individuati sostituendo m = 1, 2, 3, 4 nella equazione(1.13), Z smj = T sm (t) ψj (t) 0 i loro valori sono riportati in Tabella(1.1). 3 e quindi nella frequenza Phase Shift Keying 5 Sezione(1.3.3) 6 Binary Phase Shift Keying 4 (1.13) CAPITOLO 1. MODULAZIONI DIGITALI 8 Figura 1.4: Modulazione QPSK nel tempo Simbolo 00 01 10 11 Segnale s0 s1 s2 s3 Coordinata I +1 -1 -1 +1 Coordinata Q +1 +1 -1 -1 Tabella 1.1: Punti della costellazione QPSK Le brusche transizioni della fase in Figura(1.4) si hanno nel passaggio dal simbolo che nella costellazione di Figura(1.5a) ha coordinate (1, 1) al simbolo con coordinate (−1, −1) , l’inviluppo complesso passa per l’origine e compie una ampia escursione in ampiezza inadatta agli amplificatori non lineari utilizzati per ottimizzare l’impiego dell’energia nel satellite. La Figura 1.5: Tipologie di QPSK modulazione OQPSK7 la cui costellazione è rappresentata in Figura(1.5b) è una variante della QPSK che risolve il problema delle transizioni di fase 7 Offset Quadrature Phase Shift Keying CAPITOLO 1. MODULAZIONI DIGITALI 9 mediante uno sfasamento temporale tra la componente in fase e quella in quadratura, esse non cambiano mai contemporaneamente pertanto la massima variazione dell’ampiezza dell’inviluppo complesso è di circa 3dB contro i 40dB della QPSK. La modulazione π4 QPSK [1] risolve il medesimo problema ruotando di π 4 la costellazione ad ogni simbolo come in Figura(1.5c), in tal modo la escursione di fase massima è di 135◦ , intermedia tra i 180◦ della QPSK convenzionale ed i 90◦ della OQPSK, rispetto a quest’ultima però si ha il vantaggio di poter utilizzare la demodulazione incoerente, l’informazione è infatti associata all’ampiezza della variazione di fase ed alla direzione in cui avviene la rotazione pertanto non è necessario che il ricevitore conosca la fase in anticipo visto che il riferimento per la demodulazione del simbolo attuale è costituito dal simbolo precedente. Il ricevitore π4 QPSK ha un’architettura più semplice ma la probabilità d’errore è maggiore di circa 3dB rispetto all’equivalente ricevitore coerente in quanto sono possibili due sorgenti d’errore, un simbolo corrotto oppure un riferimento errato. Una diretta estensione della modulazione M–PSK è la M–QAM8 , le loro costellazioni coincidono nel caso di M = 4 mentre per valori diversi differiscono profondamente come evidenziato in Figura(1.6) nel caso di M = 16. Figura 1.6: Confronto costellazioni M–QAM e M–PSK Per entrambe l’efficienza spettrale è ηs = 4 in quanto ad ogni simbolo sono associati 4 bit mentre nella QPSK soltanto due, i segnali della costellazione QAM tuttavia non hanno tutti la stessa energia pertanto, per i motivi precedentemente esposti, non sono adatti ad applicazioni spaziali. Dalla costellazione della 16–PSK si può osservare come i segnali siano ravvicinati tra loro molto più che nella QPSK dove se ne ha uno in ogni quadrante, ciò determina un aumento della probabilità di scambiare un 8 Quadrature Amplitude Modulation CAPITOLO 1. MODULAZIONI DIGITALI 10 segnale per uno dei segnali adiacenti pertanto occorre aumentare la potenza al fine di ottenere la stessa probabilità d’errore della QPSK. L’altra grande famiglia di modulazioni digitali utilizzata in ambito spaziale è quella che interessa le variazioni della frequenza della portante e che va sotto il nome di M–FSK9 [7], continua o discontinua a seconda che la variazione tra le M frequenze associate ai simboli da trasmettere avvenga con continuità di fase o meno. In Figura(1.7) è riportato l’andamento tem- Figura 1.7: Andamento temporale BFSK porale di una M–FSK incoerente per il caso di M = 2, essa si realizza con due oscillatori, a seconda del simbolo da trasmettere il modulatore emette una portante oppure l’altra. Le discontinuità nella fase che si hanno nella M–FSK incoerente determinano una banda molto ampia e pertanto una scarsa efficienza spettrale, per questo motivo si sono affermate le tecniche a fase continua CPFSK10 il cui generico segnale modulato è descritto dalla: r sm (t) = Z t 2Eb cos 2πfc t + 2πkf m (τ ) dτ Tb −∞ (1.14) dove la fase del segnale modulato è continua in quanto non direttamente proporzionale al segnale modulante digitale m (t) ma al suo integrale. L’indice di modulazione kf = 2∆f Rb determina la separazione tra i toni, essa è minima nel caso della MSK11 per la quale si ha kf = 0, 5. L’andamento della fase nel tempo per la MSK è rappresentato in Figura(1.8), ad ogni bit 1 da trasmettere viene associato un aumento della fase pari a +90◦ mentre ad ogni bit 0 si associa una diminuzione di −90◦ della stessa. Una derivazione della MSK è la GMSK12 che riduce ulteriormente la banda filtrando la modulante digitale con un filtro gaussiano avente risposta 9 Frequency Shift Keying Continuous Phase Frequency Shift Keying 11 Minimum Shift Keying 12 Gaussian Minimum Shift Keying 10 CAPITOLO 1. MODULAZIONI DIGITALI 11 Figura 1.8: Andamento temporale fase del segnale MSK all’impulso √ hG (t) = π − π22 t2 e α α (1.15) rappresentata in Figura(1.9), Figura 1.9: Risposta all’impulso del filtro gaussiano esso è completamente descritto dal prodotto BT dove T è l’intervallo di simbolo e B la banda a 3dB determinata da α = 1,8 B , quanto più BT diminuisce tanto più lo spettro diviene compatto comportando però un aumento dell’interferenza intersimbolica13 . La Figura(1.10) illustra un confronto spettrale tra le modulazioni MSK, GMSK e QPSK, lo spettro di quest’ultima è il più stretto per quel che riguarda la banda utile me presenta molta energia distribuita inutilmente sui lobi secondari, la modulazione più efficiente sotto questo punto di vista è la GMSK che, per tal motivo, è utilizzata nella telefonia cellulare GSM 13 Sezione(1.3.3) CAPITOLO 1. MODULAZIONI DIGITALI 12 Figura 1.10: Confronto spettri QPSK, MSK e GMSK dove i canali sono molto vicini tra loro e si richiede elevata autonomia delle batterie. 1.3 Principi di demodulazione Questa Tesi è volta alla realizzazione di un modulatore QPSK, ciò implica tuttavia la conoscenza almeno dei principi della demodulazione che vengono qui brevemente esposti tralasciando il caso in cui il segnale in ingresso al ricevitore presenti una deriva di fase, frequenza o temporizzazione. Un generico ricevitore digitale è costituito dalla cascata di due circuiti, un demodulatore ed un decisore, il primo si occupa di estrarre dal segnale modulato affetto da rumore le componenti nelle direzioni dei vettori ψi della base dello spazio dei segnali utilizzato, compito poi del decisore è di scegliere quale tra i segnali appartenenti alla costellazione trasmessa sia da associare al segnale ricevuto. 1.3.1 Demodulatore Il segnale r (t) in ingresso al ricevitore è la somma del segnale modulato sm (t) e del rumore n (t) introdotto dal canale, quest’ultimo può essere espresso come combinazione lineare dei vettori ψi della base14 , si ha 14 la parte di n (t) che non è rappresentabile come combinazione lineare degli ψi è irrilevante nel processo di decisione CAPITOLO 1. MODULAZIONI DIGITALI 13 pertanto: T Z rj (t) = r (t) ψj (t) dt 0 T Z Z = sm (t) ψj (t) dt + 0 T n (t) ψj (t) dt (1.16) 0 = smj (t) + nj (t) questa equazione descrive in maniera immediata il demodulatore che può essere realizzato con un banco di correlatori ciascuno dei quali correla il segnale ricevuto r (t) con uno dei vettori della base restituendone la proiezione in quella direzione, tale demodulatore è descritto in Figura(1.11). Figura 1.11: Demodulatore con banco di correlatori Un demodulatore ben più semplice può essere dedotto dalla medesima equazione(1.16) scrivendo la correlazione come una convoluzione: Z T rj = r (τ ) ψj (τ ) dτ 0 Z T r (τ ) ψj (T − t + τ ) dτ |t=T = (1.17) 0 = [r (t) ∗ ψj (T − t)] |t=T ne consegue che la componente rj (t) del segnale ricevuto può essere calcolata campionando al tempo t = T l’uscita di un filtro avente risposta all’impulso h (t) = ψj (T − t). Il demodulatore basato su questo banco di filtri che si dicono adattati ai segnali della base è illustrato in Figura(1.12), per esso una considerazione importante è che l’uscita dai filtri adattati è CAPITOLO 1. MODULAZIONI DIGITALI 14 Figura 1.12: Demodulatore con filtro adattato campionata soltanto a t = T, essendo T il tempo di simbolo, e quindi non è richiesto che essa sia uguale all’impulso trasmesso in ogni istante, è sufficiente che lo sia nel solo istante di campionamento. Il filtro adattato è il demodulatore che consente di ottenere il più alto SNR15 , la sua risposta in frequenza è infatti: HRX (f ) = HT∗ X (f ) e−2πf t (1.18) che corrisponde a ruotare tutte le componenti del segnale d’ingresso in modo che abbiano la stessa fase come illustrato graficamente in Figura(1.13), si ottiene cosı̀ che i moduli delle singole componenti del segnale si sommano in maniera costruttiva massimizzando l’energia del segnale mentre quella del rumore rimane invariata. 1.3.2 Decisore L’uscita del demodulatore lungo il jesimo vettore della base dello spazio dei segnali è somma di una componente deterministica e di una componente aleatoria gaussiana generata dall’elaborazione di un processo di rumore gaussiano, la componente deterministica individua con precisione nello spazio dei segnali il segnale trasmesso mentre la componente gaussiana provoca una deviazione rispetto ad esso la cui ampiezza è individuata dal valore della densità spettrale di rumore N20 . 15 Signal to Noise Ratio CAPITOLO 1. MODULAZIONI DIGITALI (a) Segnale trasmesso 15 (b) Uscita adattato del filtro Figura 1.13: Effetto filtro adattato Il processo di decisione [13] che associa il segnale demodulato r0 ad uno dei vettori della costellazione può essere implementato secondo il criterio ML16 oppure il MAP17 : ML: consiste nello scegliere il vettore sj della costellazione che ha la maggior probabilità di coincidere col segnale sm emesso. MAP: è uguale al criterio ML ma tiene anche conto del fatto che non necessariamente tutti i segnali appartenenti alla costellazione hanno la stessa probabilità di essere emessi. Se i segnali della costellazione sono equiprobabili allora i due criteri coincidono e il decisore non fa altro che calcolare le distanze tra il segnale demodulato r0 e tutti i segnali sj della costellazione optando poi a favore del più vicino, in sostanza quindi il decisore suddivide lo spazio dei segnali in M regioni dette di decisione, ciascuna contiene un punto sj della costellazione e tutti i punti che sono più vicini ad esso che non agli altri punti della costellazione. Nel caso si utilizzi il criterio MAP le regioni si ampliano per quei punti della costellazione che hanno maggiore probabilità di essere emessi a discapito delle regioni che contengono i punti con minore probabilità. Le probabilità d’errore [8] di BPSK e QPSK coincidono in quanto la QPSK è data dall’unione di due √ costellazioni BPSK ortogonali tra loro, I √ due segnali s1 = Eb e s2 = − Eb della costellazione BPSK sono rappresentati in Figura(1.14) insieme alla densità di probabilità condizionate: √ (r− Eb ) 1 − N0 p (r|s1 ) = √ e πN0 16 17 Maximum Likelihood Maximum A Posteriori probability 2 (1.19) CAPITOLO 1. MODULAZIONI DIGITALI 16 Figura 1.14: Costellazione BPSK e densità di probabilità condizionate √ (r+ Eb ) 1 − N0 p (r|s2 ) = √ e πN0 2 (1.20) Nell’ipotesi che sia stato emesso s1 (t) la probabilità d’errore si ottiene integrando la gaussiana da −∞ a 0 infatti quella è la regione di decisione associata al simbolo s2 , si ha: Z 0 P (e|s1 ) = P (r|s1 ) dr −∞ √ Z 0 (r− Eb )2 1 − N0 e =√ dr πN0 −∞ r Z 2Eb N0 x2 1 e− 2 dx =√ 2π −∞ Z +∞ 2 1 − x2 r e dx =√ 2Eb 2π N0 s ! r 2 Eb 2Eb d12 1 =Q = Q = erf c N0 2N0 2 N0 (1.21) essendo erf c (x) la funzione complementare di errore erf c (x) = 2 π Z +∞ 2 e−y dy (1.22) x Il medesimo risultato si ha per P (e|s2 ) e, per via della simmetria della costellazione, entrambe coincidono con la probabilità d’errore della mo- CAPITOLO 1. MODULAZIONI DIGITALI 17 dulazione BPSK e quindi anche della QPSK che tuttavia ha un’efficienza spettrale doppia in quanto ad ogni simbolo associa due bit e non uno. L’ultima formulazione della (1.21) consente due osservazioni importanti: Eb 1. la probabilità d’errore dipende unicamente dal rapporto N denomi0 nato rapporto segnale/rumore per bit e non da altre caratteristiche del segnale o del rumore. 2. quanto più sono ravvicinati i simboli della costellazione tanto più peggiora la probabilità d’errore, questo è il motivo per il quale alla 16–PSK si preferisce la QPSK anche se l’efficienza spettrale è inferiore. La BER18 esprime lo stesso concetto della probabilità d’errore ma in maniera più immediata, essa è infatti il rapporto tra il numero dei bit ricevuti in maniera errata ed il numero totale dei bit trasmessi, una analoga misura è la SER19 che esprime invece il rapporto tra il numero dei simboli ricevuti in maniera errata ed il numero totale dei simboli trasmessi, esse coincidono per la QPSK a patto di utilizzare la codifica di Gray la quale associa a segnali adiacenti della costellazione gruppi di bit che differiscono tra loro soltanto per un bit. 1.3.3 Interferenza intersimbolica L’equazione delle onde per un mezzo debolmente disomogeneo e non dissipativo ∇2 E + κ20 n2 (r) E = 0 (1.23) p è funzione dell’indice di rifrazione n(r) = 0 (r) essendo 0 la parte reale della costante dielettrica del mezzo. Ipotizzando per la (1.23) una soluzione espressa nella forma della espansione asintotica di Luneburg-Kline −jκ0 Φ(r) E (r) = e ∞ X Em (r) (κ0 )m (1.24) m=0 si perviene all’importante risultato secondo il quale nel caso in cui l’indice di rifrazione del mezzo trasmissivo dipende dalla frequenza si ha che un impulso trasmesso subisce un allargamento temporalmente e per il principio della conservazione dell’energia diminuisce in ampiezza [11]. Il fenomeno viene denominato ISI20 ed è particolarmente deleterio nelle trasmissioni di impulsi digitali reali come quelli tratteggiati in Figura(1.15a), essi vengono deformati come in Figura(1.15b) pertanto negli istanti di campionamento 18 Bit Error Rate Symbol Error Rate 20 Inter Symbol Interference 19 CAPITOLO 1. MODULAZIONI DIGITALI (a) Segnale Tx ed Rx 18 (b) Effetto ISI su impulsi Figura 1.15: Effetto interferenza intersimbolica del ricevitore si hanno contributi derivanti da più impulsi il che può generare errori come ad esempio nell’istante (3) dove il segnale ricevuto ha ampiezza dimezzata rispetto al simbolo trasmesso. Il problema dell’interferenza intersimbolica è stato individuato sin dalle prime trasmissioni transoceaniche di Morse, una soluzione intuitiva fu quella di operare al massimo data rate in grado di consentire una ricezione di buona qualità21 , tuttavia l’evolversi delle tecnologia e la sempre più stringente necessità di trasmettere in tempi brevi grandi moli di informazione ha portato ad una soluzione più ingegnosa. Ricordando che il ricevitore basato sul filtro adattato richiede l’uguaglianza tra l’impulso trasmesso e quello ricevuto soltanto nell’istante di campionamento ne consegue che si può scegliere una forma dell’impulso qualsiasi a patto che si annulli in tutti i multipli dell’istante di campionamento tranne uno, il suo andamento temporale è pertanto: 1 se n = 0 (1.25) x (nT ) = 0 se n 6= 0 in virtù della condizione di Nyquist [8] per l’annullamento dell’ISI si ha che gli impulsi x (t) che rispettano la (1.25) sono tutti quelli la cui trasformata di Fourier risponde al vincolo ∞ X m X f+ =T T m=−∞ (1.26) dove W è la banda del canale. I casi possibili sono tre: T < 1 2W : T = 1 2W : 21 le repliche di X (f ) non si sovrappongono pertanto non c’è modo di rispettare il criterio di Nyquist e quindi l’utilizzo di queste tipologie di impulsi porta a trasmissioni affette da ISI. questa condizione implica che le repliche spettrali si tocchino solo in un punto come in Figura(1.17), l’unico spettro che soddisfa questa circa 200Baud per il telegrafo CAPITOLO 1. MODULAZIONI DIGITALI 19 T -W -1/T Figura 1.16: -1/T W 0 P∞ m=−∞ X f+ m T per T < 1 2W T -W -1/T Figura 1.17: -1/T W 0 P∞ m=−∞ X f+ m T per T = 1 2W condizione è descritto dalla X (f ) = se |f | < W altrimenti T 0 (1.27) si tratta di un rettangolo in frequenza cui corrisponde la sin π Tt x (t) = π Tt t ≡ sinc π T (1.28) rappresentata in Figura(1.18), essa presenta la banda minima ma è praticamente irrealizzabile per via della anticausalità e delle lunghe code che si estendono illimitatamente e decadono come x1 . Figura 1.18: sinc π Tt T > 1 2W : le repliche spettrali in questo caso si sovrappongono, vi sono quindi molti impulsi che rispettano il criterio di Nyquist, la famiglia più CAPITOLO 1. MODULAZIONI DIGITALI 20 T -W -1/T Figura 1.19: 0 P∞ m=−∞ X -1/T W f+ m T per T > 1 2W utilizzata è quella degli spettri a coseno rialzato descritti dalla 0 ≤ |f | ≤ Th i se (1−α) (1+α) T πT Hrc (f ) = |f | − 2T se 2 1 + cos α 2T ≤ |f | ≤ 0 se 0 ≤ |f | ≥ (1+α) 2T (1−α) 2T (1−α) 2T (1.29) dove α è il fattore di roll-off ed assume valori compresi tra 0 ed 1, in particolare per α = 0 la banda occupata dall’impulso è proprio la minima di Nyquist22 , al crescere di α essa aumenta sino a raddoppiare per α = 1. L’individuazione degli spettri a coseno rialzato parte dalla antitrasformata di Fourier: sin 2πt TS cos (2παt) (1.30) h (t) = 2πT 1 − 2αt 2 π che evidenzia come la sinc viene corretta con il coseno al fine di migliorarne le caratteristiche, rilevante l’ossevazione che le code dell’impulso sagomato pur continuando ad estendersi illimitatamente decadono come x13 pertanto molto più rapidamente che non nel caso in cui l’impulso sagomato sia una sinc. Nelle applicazioni pratiche si utilizza la sagomatura d’impulso con spettro a coseno rialzato, la risposta in frequenza e nel tempo è illustrata al variare di α in Figura(1.20) si può osservare come quanto più α tende a zero, tanto più hanno ampiezza elevata i lobi laterali, ciò determina forti escursioni dell’inviluppo complesso come mostrato in Figura(1.21), pertanto per consentire un utilizzo ottimale degli amplificatori, nelle applicazioni spaziali si utilizza il valore α = 0, 35. Alla luce dei concetti esposti per il filtro adattato, si comprende come sia sensato suddividere la sagomatura a coseno rialzato tra il trasmettitore ed il ricevitore secondo la Hrc (f ) = HT x (f ) HRx (f ) 22 ossia Rs 2 (1.31) CAPITOLO 1. MODULAZIONI DIGITALI (a) Risposta in frequenza 21 (b) Risposta nel tempo Figura 1.20: Sagomatura d’impulso a coseno rialzato Figura 1.21: Diagrammi vettoriali QPSK con sagomatura d’impulso in entrambe sono infatti necessari dei filtri23 che possono essere progettati in modo da eseguire anche la sagomatura dell’impulso, il modulo della risposta in frequenza per entrambe gli SRRC24 sarà pertanto: |HT x (f )| = |HRx (f )| = p Hrc (f ) (1.32) 1.3.4 Principi di codifica Tralasciando l’eventuale conversione in digitale di una sorgente analogica, si ha che una generica trasmissione numerica può essere realizzata come in figura(1.22) dove la codifica di sorgente si propone di rimuovere le dipendenze tra i simboli da trasmettere al fine di ridurne il numero come nel caso degli algoritmi che nei computer vengono utilizzati per la compressione dei file. 23 il filtro in trasmissione riduce le emissioni nelle bande adiacenti mentre quello in ricezione effettua la demodulazione ed elimina il rumore esterno alla banda utile. 24 Square Root Raised Cosine CAPITOLO 1. MODULAZIONI DIGITALI 22 Figura 1.22: Trasmissione numerica La codifica di canale si basa sull’introduzione di simboli addizionali nella sequenza trasmessa, essi sono scelti in modo da presentare una qualche correlazione tra loro consentendo cosı̀ la rivelazione degli errori e conseguentemente la riduzione della probabilità di errore intrinseca del canale. Le principali tecniche di correzione degli errori sono due, la ARQ25 e la FEC26 : ARQ: suddivide in blocchi l’informazione da trasmettere, se in ricezione si individua la presenza di errori in un blocco ne viene richiesta la ritrasmissione, necessita di un canale duplex ed ha lo svantaggio che anche un singolo errore comporta la ritrasmissione dell’intero blocco in cui è contenuto. FEC: non richiede un canale duplex ma il numero di simboli ridondanti da aggiungere è molto maggiore rispetto all’ARQ, ne consegue che il data rate effettivo si riduce ma, per il teorema di Shannon sulla Capacità trasmissiva27 si riduce anche la potenza necessaria per ottenere una trasmissione numerica praticamente esente da errori. In ambito satellitare si utilizza la codifica di canale di tipo FEC, in una o più delle seguenti forme: Codifica a blocchi: la più importante è la Reed-Salomon (204,188), essa aggiunge 16 bytes di ridondanza per ogni 188 bytes da trasmettere, in tal modo si possono correggere sino a 8 errori e la BER richiesta passa da 10−4 a più di 10−10 . Il principio è che con l’aggiunta di bit si ottengono delle combinazioni le quali possono essere ricevute soltanto in caso di errore, una volta che esso è stato rilevato si sceglie nell’alfabeto dei possibili simboli trasmessi quello che presenta la distanza di Hamming28 minore rispetto al simbolo ricevuto. Codifica convoluzionale: viene specificata con i tre parametri (n,k,m) dove k è il numero di bit in ingresso ed n il numero di bit in uscita dal codificatore, entrambe assumono valori compresi tra 1 ed 8, m è invece il numero di registri utilizzati ed è compreso tra 2 e 10. 25 Automatic ReQuest for repeat Forward Error Correction 27 Sezione(1.3.5) 28 è il numero di bit diversi tra due simboli 26 CAPITOLO 1. MODULAZIONI DIGITALI 23 Un esempio di codificatore è riportato in Figura(1.23), esso produce 3 Figura 1.23: Codificatore (3, 1, 3) bit di uscita per ogni bit di ingresso quindi il ritmo di codifica è 1/3, ogni bit d’uscita è generato quale somma di alcuni dei bit presenti negli m = 3 registri di memoria, il criterio di selezione di questi polinomi generatori determina la qualità della codifica. Laddove si desideri un ritmo di codifica variabile si ricorre alla versione Punctured, in particolare se si richiede la massima qualità vengono utilizzano tutte le n uscite del codificatore convoluzionale, altrimenti soltanto una parte di esse. Interleaving: le codifiche precedenti hanno prestazioni eccellenti ma in presenza di un gruppo di errori ravvicinati non sono in grado di ricostruire la sequenza trasmessa, il problema si risolve mescolando i bit della sequenza da trasmettere ad esempio caricando una ROM lungo le righe e leggendone il contenuto lungo le colonne. 1.3.5 Capacità trasmissiva Per confrontare differenti tipi di modulazione e comprendere come l’effetto dei codici possa migliorare la qualità di una trasmissione numerica è molto utile il teorema [3] seguente: Teorema 1 (di Shannon) Un qualsiasi canale caratterizzato da una velocità di segnalazione Rs = T1s , una varianza29 di rumore al ricevitore σS2 ed 2 pone un limite, denominato capacità una varianza del segnale ricevuto σN di canale C, al massimo flusso informativo che transita in esso: C= 29 potenza 1 2TS log2 1+ 2 σS 2 σN (bit/s) (1.33) CAPITOLO 1. MODULAZIONI DIGITALI 24 nel caso di rumore gaussiano additivo bianco con densità spettrale di 2 = N B potenza SW (f ) = N20 si ha che la potenza di rumore è PW = σW 0 inoltre se la sorgente è gaussiana e limitata nella banda B può essere rappresentata con 2B campioni30 ciascuno con la medesima potenza PS = σS2 , ne deriva che l’equazione(1.33) può essere riscritta nella forma: C = Blog2 1 + PS N0 B (bit/s) (1.34) dalla quale si deduce che a parità di rumore se si vuole aumentare la capacità trasmissiva di un canale conviene aumentare la banda B, un aumento della potenza ha infatti minore effetto essendo mitigato dal logaritmo. E’ interessante una rappresentazione grafica dell’equazione(1.34) nel cosiddetto piano di Shannon, si giunge ad essa partendo dall’ipotesi che il ritmo binario in trasmissione sia uguale alla capacità del canale, si ha cioè C = Rb = T1b pertanto C R b PS T b C PS Tb C Eb = log2 1 + = log2 1 + = log2 1 + B N0 B B N0 B N0 (1.35) da cui si ottiene C Eb 2B − 1 (1.36) = C N0 B che rappresenta la curva limite nel piano di Shannon illustrato in Figura(1.24), la regione sottostante è quella permessa ed in essa giacciono i punti corrispondenti alle varie modulazioni, quanto più essi si avvicinano Eb alla curva limite riuscendo a mantenere basso il rapporto N tanto più la 0 modulazione è efficiente. I punti corrispondenti alle modulazioni si ottengono imponendo per tutte una determinata probabilità d’errore, 10−5 per il piano in Figura(1.24), Eb ad essa nel caso della QPSK corrisponde N = 9, 6dB mentre l’efficienza 0 Rb spettrale è ηS = B = 2 in quanto ad ogni coppia di bit si associa un simbolo, le coordinate del punto sono pertanto (9, 6 , 2). La modulazione BPSK Eb presenta lo stesso N e quindi la stessa efficienza energetica ma l’efficienza 0 spettrale vale 1 pertanto sotto questo punto di vista è più lontana dalla curva limite e quindi le sue prestazioni sono inferiori. Nel caso di una QPSK con codifica convoluzionale, caratterizzata da un ritmo di codifica 1/2 e k = 7 bit, si ha un guadagno di codifica di 5, 2dB rispetto alla QPSK non codificata mentre l’efficienza spettrale vale 1 pertanto le coordinate del punto sono (4, 4 , 1), la forte vicinanza alla curva limite giustifica il crescente interesse per i turbocodici. E’ interessante osservare come le modulazioni di 30 per il teorema del campionamento CAPITOLO 1. MODULAZIONI DIGITALI 25 Figura 1.24: Piano di Shannon tipo M–QAM con costellazione quadrata incrementano l’efficienza spettrale della trasmissione, ma penalizzano l’efficienza energetica di circa 6 dB per ogni quadruplicazione dei punti della costellazione. Capitolo 2 Architetture modulatori QPSK 2.1 Sommario Dalla formula che descrive la generica modulazione M–PSK r 2ES 2π g (t) cos (m − 1) cos (2πfc t) − sm (t) = T M r 2ES 2π g (t) cos (m − 1) sin (2πfc t) T M (2.1) si ricava immediatamente lo schema di un modulatore che la implementi infatti cos (2πfc t) e sin (2πfc t) sono due portanti in quadratura generabili in forma analogica come in Figura(2.1) Figura 2.1: Modulatore Standard o in forma digitale ottenendo in tal caso risultati nettamente superiori in termini di purezza spettrale e risoluzione. 26 CAPITOLO 2. ARCHITETTURE MODULATORI QPSK 27 La modulante agisce su m ∈ (0, 1, 2, 3), corrispondentemente il termine (m − 1) si valorizza nell’insieme (−1, 0, +1) e quindi ben si presta cos 2π M ad una realizzazione digitale. La sagomatura dell’impulso1 g (t) necessaria ai fini dell’eliminazione dell’ISI si realizza con un filtro analogico o digitale, quest’ultimo è da preferire in quanto non necessita di tarature individuali ed è meno ingombrante. L’orientamento pertanto è stato sin dall’inizio per una realizzazione completamente digitale, tuttavia anche nel solo ambito digitale vi sono diverse modalità di implementare alcuni dei blocchi costituenti il modulatore, nel seguito verranno esposte le diverse soluzioni prese in considerazione ed i criteri che hanno portato alla selezione dell’architettura adottata. 2.2 Realizzazioni digitali di modulatori QPSK Sono state individuate due diverse architetture per la realizzazione del modulatore QPSK, la prima lo vede realizzato variando alcuni dei parametri di un DDFS mentre la seconda si ottiene digitalizzando uno o più blocchi dello schema classico di Figura(2.1). 2.2.1 Modulatore DDFS Il DDFS2 è costituito da un accumulatore di fase il quale somma al suo valore precedente un contributo fisso generando cosı̀ una rampa di fase, applicandola poi ad un convertitore fase-ampiezza si ottiene la funzione sinusoidale desiderata. Il DDFS può essere utilizzato per realizzare tre differenti modulazioni come illustrato in Figura(2.2). Figura 2.2: Modulatore DDFS La scelta dell’incremento di fase, congiuntamente alla frequenza di clock del sistema, determina la frequenza generata, sommando all’incremento fisso 1 2 Sezione(1.3.3) Appendice(A.2) CAPITOLO 2. ARCHITETTURE MODULATORI QPSK 28 un valore variabile in funzione della modulante si realizza una modulazione di frequenza con ottime prestazioni in quanto il cambio frequenza avviene con continuità di fase ed istantaneamente. La modulazione di fase si ottiene in maniera analoga sommando la modulante alla rampa di fase generata dall’accumulatore, l’inviluppo costante che ne deriva non consente di implementare sagomatura dell’impulso3 in quanto questa, come visto in Figura(1.21), produce un inviluppo il cui modulo varia nel tempo e viene a coincidere con i punti della costellazione nei soli istanti di simbolo. La terza modulazione implementabile è quella d’ampiezza che si ottiene secondo lo schema classico ossia moltiplicando la portante sinusoidale che si ha in uscita dal convertitore fase-ampiezza per la modulante. In definitiva il modulatore basato sul DDFS è molto flessibile e consente di applicare contemporaneamente ad una stessa modulante una o più modulazioni4 tuttavia la limitazione che riguarda l’inviluppo complesso lo rende inutilizzabile per la realizzazione di un modulatore QPSK per applicazioni spaziali. 2.2.2 Modulatore classico L’implementazione digitale del modulatore classico si basa anche essa sul DDFS5 il quale genera due portanti in quadratura aventi frequenza che da specifica deve essere 40MHz, esse sono in formato digitale pertanto ogni loro campione assume un valore compreso tra −1 e +1 ed è espresso in complemento a due su 12 bit. I campioni delle portanti vengono emessi alla frequenza di clock di 165MHz che è stata scelta in quanto multiplo intero dei 3 ritmi di simbolo di cui si richiede l’implementazione, in questo modo gli interpolatori6 sono più semplici da realizzare rispetto al caso frazionario. I valori dell’interpolazione sono riportati in Tabella(2.1) e vengono realiData Rate Ingresso (Mbps) 55 82, 5 110 Symbol Rate (MSpS) 27, 5 41, 25 55 Interpolazione 6 4 3 Tabella 2.1: Valori interpolazione richiesti zzati tutti mediante una architettura polifase7 sia perché l’architettura CIC8 3 Sezione(1.3.3) ottenendo cosı̀ una cifratura della comunicazione che ne può aumentare la segretezza 5 Appendice(A.2) 6 Appendice(B.2) 7 Appendice(B.3.2) 8 Appendice(B.3.1) 4 CAPITOLO 2. ARCHITETTURE MODULATORI QPSK 29 per valori cosı̀ bassi richiede la compensazione del guadagno, che per il fatto che nel CIC la sagomatura d’impulso e l’eliminazione delle immagini9 richiedono un ulteriore filtro che invece nel polifase è intrinseco. Il DDFS viene realizzato utilizzando come convertitore fase-ampiezza un processore CORDIC10 il quale ottimizza l’implementazione su FPGA ed è particolarmente adatto per modulatori in quadratura in quanto genera simultaneamente ed in maniera implicita sia il seno che il coseno. Considerando per semplicità il solo data rate di 55Mbps in ingresso al modulatore, lo schema che risulta dalle precedenti considerazioni è mostrato in Figura(2.3), Figura 2.3: Modulatore QPSK classico per un solo data rate essa evidenzia l’utilizzo di un blocco S/P il quale ha in ingresso un flusso binario a 55Mbps che suddivide in due flussi a 27, 5MSpS semplicemente distribuendo i bit pari sul ramo superiore11 del modulatore ed i bit dispari sul ramo inferiore12 . L’architettura polifase richiede un clock con frequenza pari al ritmo di simbolo, nel caso in Figura(2.3) il divisore per 6 genera un clock a 27, 5MHz a partire da un clock a 165MHz, la complessità che deriva dall’implementazione del divisore di frequenza è compensata dal fatto che gran parte della architettura polifase opera con un clock che è 6 volte inferiore rispetto al clock di sistema, di qui una minore dissipazione ed una più semplice progettazione del filtro ospitato dall’architettura stessa. Lo schema del modulatore classico che consente di accettare 3 diversi 9 create con l’inserzione di zeri nel processo di interpolazione Appendice(A.4.1) 11 nel seguito denominato ramo I 12 nel seguito denominato ramo Q 10 CAPITOLO 2. ARCHITETTURE MODULATORI QPSK 30 data rate in ingresso è in Figura(2.4), ad ogni data rate corrisponde un Figura 2.4: Modulatore QPSK classico 3 data rate clock ridotto ed un diverso interpolatore polifase, si tratta pertanto di una soluzione abbastanza onerosa in termini di implementazione su FPGA richiede infatti 6 interpolatori, il che significa nella migliore delle ipotesi la necessità di 6 sommatori ciascuno avente fino ad un massimo di 7 ingressi a 12 bit, la complessità è molto elevata quindi la massima frequenza ottenibile con questa architettura è bassa. Rispetto all’architettura in Figura(2.4) si possono introdurre diverse ottimizzazioni, come mostrato dalla Figura(2.5) nella quale si utilizzano due soli interpolatori, uno per il ramo I e l’altro per il ramo Q, essi sono dimensionati per il massimo rate d’interpolazione, cioè 6, per esso la decomposizione polifase prevede 6 filtri FIR ognuno dei quali utilizza 7 coefficienti13 . Nel caso che invece di interpolare 6, che è il valore di default, si voglia interpolare 4 oppure 3 occorre caricare l’insieme dei coefficienti corrispondente ed impostare la divisione in modo da avere il giusto valore del clock ridotto, l’iterazione ciclica deve poi coinvolgere i primi 4 oppure i primi 3 rami della decomposizione polifase invece che tutti e 6 i rami. 2.2.2.1 Modulatore classico con fclk = 4 × fif Lo schema in Figura(2.5) comporta una notevole riduzione della complessità tuttavia prevede ancora l’utilizzo di un DDFS e di una coppia di moltiplicatori ciascuno con due ingressi a 12 bit, una loro implementazione su FPGA 13 valore desunto analizzando la risposta in frequenza ai tre diversi data rate CAPITOLO 2. ARCHITETTURE MODULATORI QPSK 31 Figura 2.5: Modulatore QPSK classico 3 data rate Ottimizzato è particolarmente onerosa, basti pensare che nella Xilinx Virtex2 essi vengono realizzati come blocchi ad alto livello implementati nella BlockRAM14 e pertanto ottimizzati per velocità e dissipazione. In realtà imponendo tra la frequenza di clock fclk e la frequenza intermedia desiderata fif il vincolo: fclk = 4 × fif (2.2) si ha che il seno ed il coseno vengono campionati in corrispondenza degli angoli π2 , π, 3π 2 , 2π e loro multipli in corrispondenza dei quali le due funzioni assumono uno dei 3 valori (−1, 0, 1) come illustra la Tabella(2.2). Angolo (rad) π 2n πn 3π 2 n 2πn Coseno 0 −1 0 1 Seno 1 0 −1 0 Tabella 2.2: Coseno e seno nel caso di fclk = 4 × fif Il DDFS compie una enorme elaborazione cercando di approssimare questi valori come evidenziato dalla Figura(A.7) relativa ad una simulazione VHDL, tuttavia gli stessi possono essere ottenuti in maniera molto più efficiente e precisa utilizzando un contatore ed una ROM i quali sono in grado di generare una qualsiasi sequenza ripetitiva. Dati i valori assunti da seno e coseno la moltiplicazione non è una vera moltiplicazione ma si riduce a 14 Appendice(C.3.4.2) CAPITOLO 2. ARCHITETTURE MODULATORI QPSK 32 lasciar passare il campione proveniente dall’interpolatore SRRC, annullarlo oppure invertirlo in complemento a due a seconda che la funzione trigonometrica valga rispettivamente 1, 0 oppure −1. Lo schema che deriva dalle precedenti considerazioni è mostrato in Figura(2.6) Figura 2.6: Modulatore QPSK classico 3 data rate fclk = 4 × fif Un’ultima importante osservazione sulle sequenze seno e coseno che si hanno sotto l’ipotesi fclk = 4 × fif è che esse alternano uno zero ad un altro valore, quindi in sostanza effettuano un’interpolazione di valore 2 che è in cascata a quella prodotta dall’SRRC polifase, essa può pertanto essere ridotta consentendo al polifase di operare ad una frequenza più bassa, tale opportunità non è stata utilizzata in quanto l’ortogonalità delle due sequenze consente un’ottimizzazione ancor più rilevante come descritto nel Capitolo(4). L’unico svantaggio arrecato dal vincolo fclk = 4 × fif è che fif non è più 40MHz bensı̀ 41, 25MHz, non appare tuttavia come una grande limitazione in quanto in ogni caso l’uscita modulata, centrata sulla frequenza intermedia, deve essere traslata a frequenze più consone alla trasmissione satellitare. Capitolo 3 Implementazione SRRC polifase 3.1 Sommario La struttura polifase ha un ruolo preponderante nell’architettura del modulatore pertanto ogni miglioramento ad essa apportato si riversa in maniera proporzionale sulle prestazioni globali del circuito. Dopo aver descritto il progetto del filtro SRRC da essa ospitato, si passa a definire due diverse realizzazioni, la prima deriva direttamente dalla teoria e non è adatta ad una implementazione su FPGA, la seconda comporta una progettazione più elaborata ma l’implementazione è semplificata, vengono presentate entrambe al fine di mettere in evidenza le scelte progettuali. 3.2 Progetto del filtro SRRC Le considerazioni emerse nella trattazione dell’ISI1 hanno portato ad individuare la seguente famiglia di spettri a coseno rialzato: Hrc (f ) = Th T 2 1 + cos πT α i se (1−α) |f | − 2T se 0 se 0 ≤ |f | ≤ (1+α) 2T ≤ |f | ≤ 0 ≤ |f | ≥ (1+α) 2T (1−α) 2T (1−α) 2T (3.1) per essa le specifiche prevedono un fattore di roll-off α = 0, 35 scelto come compromesso tra utilizzazione della banda e complessità della realizzazione, la risposta in frequenza viene suddivisa equamente tra trasmissione e ricezione p |HT x (f )| = |HRx (f )| = Hrc (f ) (3.2) 1 Sezione(1.3.3) 33 CAPITOLO 3. IMPLEMENTAZIONE SRRC POLIFASE 34 in modo da poter utilizzare il filtro in ricezione anche come filtro adattato e quindi demodulatore secondo quanto visto in Sezione(1.3.1). Il progetto del filtro è stato effettuato col metodo del campionamento della risposta in frequenza data dalle equazioni (3.1) e (3.2), di essa si prendono N 2−1 campioni e per simmetria si ricavano i restanti N 2−1 , effettuando per ciascuno di essi la IDFT2 si ottiene un campionamento della risposta impulsiva e quindi gli N coefficienti del filtro SRRC. L’espressione della IDFT è: N −1 X 2π hd (n) = Hd (k) e( N )kn (3.3) k=0 che per la condizione di simmetria si riduce a: N −1 2 hd (n) = Hd (0) + X Hd (k) cos k=0 2π kn N (3.4) L’anticausalità viene rimossa traslando la risposta impulsiva di N 2−1 campioni. Non necessariamente un numero di campioni maggiore si traduce in un aumento dell’attenuazione del filtro in banda oscura, ad esempio il filtro SRRC interpolante 6 è stato realizzato con 39 coefficienti piuttosto che con i 42 consentiti dall’architettura in quanto per quest’ultimo valore gli estremi della risposta impulsiva hanno un’ampiezza maggiore che si traduce in un innalzamento della soglia del rumore. Partendo da questa considerazione e tenendo conto del fatto che i tre valori di interpolazione vengono implementati tutti con una unica architettura, si è individuato il n◦ di coefficienti ottimale nei tre casi, in particolare l’interpolazione 3 viene realizzata con 19 coefficienti, l’interpolazione 4 con 25 coefficienti e l’interpolazione 6 con 39 coefficienti. La tecnica di progetto basata sul campionamento in frequenza ben si presta ad una eventuale compensazione della risposta in frequenza del DAC3 dovuta al mantenimento di ordine zero: sin HDAC (f ) = πf fs πf −π e f fs (3.5) tale compensazione si realizza moltiplicando la risposta in frequenza dell’SRRC per l’inverso della risposta in frequenza del DAC per poi procedere al campionamento della risposta globale. 2 3 Inverse Discrete Fourier Transform Digital Analog Converter CAPITOLO 3. IMPLEMENTAZIONE SRRC POLIFASE 35 3.3 Implementazione polifase SRRC La decomposizione polifase4 può essere implementata in maniera immediata distribuendo ciclicamente i coefficienti del filtro SRRC su un banco di N filtri FIR con N pari al valore di interpolazione desiderata. Ogni FIR utilizza 7 coefficienti pertanto per interpolare 3 i 19 coefficienti con l’aggiunta di due coefficienti nulli vengono distribuiti sui primi 3 FIR, per interpolare 4 i 25 coefficienti più 3 nulli sono applicati ai primi 4 FIR ed infine per interpolare 6 i 39 coefficienti più due nulli vengono distribuiti su tutti i FIR. 3.3.1 Modello Matlab Lo script Matlab CreaCoeffsFreqSamplScaled.m (Listato E.3.1) effettua il calcolo dei coefficienti del filtro SRRC in accordo alla teoria espressa in Sezione(3.2), in particolare la risposta in frequenza descritta dall’equazione(3.1) è implementata dalla funzione RaisedCosineResponse.m (Listato E.3.3) . La distribuzione dei coefficienti sui diversi filtri viene eseguita tramite la funzione applica polifase.m (Listato E.3.2) , essa calcola il numero dei FIR in base al valore dell’interpolazione poi associa a ciascuno di essi una riga in una matrice che viene riempita una colonna alla volta sino all’esaurimento dei coefficienti. La sequenza dati di test viene applicata ad ognuno di questi FIR tramite la funzione filter, di Matlab, ottenendo una matrice con un numero di righe pari al numero di FIR ed un numero di colonne pari alla dimensione del vettore di test, gli elementi di questa matrice vengono prelevati colonna per colonna modellando cosı̀ il comportamento del commutatore presente nella descrizione della architettura polifase ottimizzata, di questo vettore viene calcolato lo spettro. CreaCoeffsFreqSamplScaled.m (Listato E.3.1) consente anche di scalare i coefficienti al fine di utilizzare al massimo la dinamica della rappresentazione in complemento a due utilizzata5 in particolare la somma che si effettua in ogni FIR del polifase deve valere al massimo 1, essa è nota a priori in quanto sono noti i coefficienti ed il segnale d’ingresso appartiene all’insieme (+1, −1). Lo stesso CreaCoeffsFreqSamplScaled.m (Listato E.3.1) consente il confronto tra il filtro progettato col campionamento in frequenza e quello che Matlab progetta automaticamente con la funzione rcosine, tale confronto mostra come le prestazioni del campionamento in frequenza siano nettamente superiori. La risposta in frequenza ed all’impulso degli SRRC per i tre data rate richiesti in specifica è rappresentata nelle Figure (3.1), (3.2) e (3.3) che evidenziano una differenza di circa 40dB tra banda passante e banda oscura. 4 5 Appendice(B.3.2) 12 bit di cui 1 per il segno ed i restanti per la parte dopo la virgola CAPITOLO 3. IMPLEMENTAZIONE SRRC POLIFASE (a) Risposta in frequenza (b) Risposta all’impulso Figura 3.1: SRRC 19 coefficienti interpolante 3 (a) Risposta in frequenza (b) Risposta all’impulso Figura 3.2: SRRC 25 coefficienti interpolante 4 (a) Risposta in frequenza (b) Risposta all’impulso Figura 3.3: SRRC 39 coefficienti interpolante 6 36 CAPITOLO 3. IMPLEMENTAZIONE SRRC POLIFASE 37 3.4 Modello VHDL Le differenze sostanziali tra le due implementazioni VHDL del polifase risiedono nella strategia di creazione e distribuzione dei clock ridotti, generati a partire dal clock di sistema a 165MHz, e nella dislocazione della logica combinatoria. 3.4.1 Polifase standard gated-clock Questa realizzazione è costituita principalmente da due blocchi: SRRCxN: incorpora i FIR ed un multiplexer che seleziona ciclicamente, ad ogni colpo di clock, l’uscita di uno di essi. RateAdapter: in funzione del data rate selezionato applica ad SRRCxN il giusto set di coefficienti, il clock ridotto ed una conta ciclica da 0 a N-1 essendo N il valore dell’interpolazione. 3.4.1.1 SRRCxN Nello schema a blocchi in Figura(3.4), associato al file srrc x n.vhd Figura 3.4: SRRC interpolante 3, 4, 6 CAPITOLO 3. IMPLEMENTAZIONE SRRC POLIFASE 38 (Listato F.2.10) , si ha che il multiplexer descritto in mux 6.vhd (Listato F.2.15) opera alla frequenza di clock mentre ciascuno dei 6 FIR descritto da fir 1.vhd (Listato F.2.11) e rappresentato in Figura(3.5) utilizza la Figura 3.5: FIR iesimo stessa temporizzazione dei dati in ingresso. I moltiplicatori sono in genere la parte più delicata nelle implementazioni di algoritmi DSP6 su FPGA, laddove possibile è bene non utilizzarli o semplificarli al massimo, nel modulatore QPSK il segnale d’ingresso ai FIR può assumere soltanto i valori7 +1 e −1 pertanto ogni moltiplicatore può essere sostituito con una descrizione VHDL che ad ogni colpo del clock ridotto presenta in uscita il valore del coefficiente o il suo negato. La negazione di un numero rappresentato in complemento a due si realizza invertendone tutti i bit e sommando 1, necessita pertanto di un sommatore che è un altro dei circuiti critici dei DSP, per evitarlo dato il numero esiguo di coefficienti si è scelto di fornire alla descrizione VHDL fir multiplier.vhd (Listato F.2.13) che di fatto sostituisce il moltiplicatore, sia il coefficiente che il suo negato. La somma delle uscite dei moltiplicatori viene effettuata in adder 7.vhd (Listato F.2.12) , un sommatore la cui complessità limita le prestazioni del modulatore sia perché è costituito da 7 ingressi a 12bit sia perché lo schema del modulatore in Figura(2.6) ne richiede 12. Gli elementi di ritardo tipici dei FIR sono realizzati con un registro a 6 Digital Signal Processing due valori si rappresentano con 1 solo bit anche se in complemento a due a +1 corrisponde 01 e a −1 corrisponde 11 7 CAPITOLO 3. IMPLEMENTAZIONE SRRC POLIFASE 39 scorrimento SIPO8 il cui VHDL è in shift reg.vhd (Listato F.2.14) , tale soluzione è migliore rispetto al mettere in cascata 7 descrizioni FFD9 in quanto segnala chiaramente al sintetizzatore VHDL che essi debbono esser posti quanto più vicini possibile tra di loro. 3.4.1.2 Rate Adapter Nello schema a blocchi in Figura(3.6), associato al file rate adapter.vhd Figura 3.6: Rate Adapter (Listato F.2.3) , si ha che selector.vhd (Listato F.2.9) a seconda del data rate impostato tramite rate sel seleziona uno tra i contatori/divisori descritti da counter divider 3.vhd (Listato F.2.5) , counter divider 4.vhd (Listato F.2.6) e counter divider 6.vhd (Listato F.2.8) , tra essi il più critico è senza dubbio il contatore/divisore per 3 in quanto utilizza entrambe i fronti del clock e pertanto è come se operasse ad una velocità di clock doppia rispetto agli altri due. La selezione di quale banco di coefficienti utilizzare viene effettuata in coeffs selector.vhd (Listato F.2.4) basandosi sul valore di rate sel, si tratta di una descrizione non efficiente in quanto il sintetizzatore la implementa 8 9 Serial In Parallel Out Flip Flop D CAPITOLO 3. IMPLEMENTAZIONE SRRC POLIFASE 40 con un multiplexer le cui dimensioni divengono molto grandi al crescere del numero di coefficienti. Trattandosi di una architettura gated-clock , si ha che i clock ridotti vengono generati con elaborazioni combinatorie sul clock di sistema, ciò è da evitare in quanto un semplice rumore, termico o ambientale, può dar luogo a problemi di corsa critica, per questo motivo viene preferita la tecnica clockenable nella quale tutti i blocchi che richiedono il clock ridotto operano in realtà col clock di sistema ma dispongono di un segnale di abilitazione clockenable pilotato tramite della logica combinatoria anch’essa temporizzata dal clock di sistema, in tal modo non è nemmeno più necessario che i clock ridotti abbiano un duty-cycle del 50%. 3.4.1.3 Risultati sperimentali Il VHDL di questo progetto è stato ampliamente testato ed ha rappresentato un punto di partenza verso una conoscenza più approfondita delle tematiche della sintesi tuttavia non è stata effettuata alcuna implementazione su FPGA in quanto l’eccessiva sensibilità del gated-clock lo rende inadatto ad applicazioni spaziali dove i circuiti sono soggetti a radiazioni, stress meccanici e termici. 3.4.2 ROM Polifase clock-enable La Figura(3.5) è il punto di partenza per una semplificazione sostanziale del polifase e quindi del modulatore, essa evidenzia come ognuno degli addendi che giungono al sommatore può assumere solo due valori, quello del coefficiente o il suo negato, pertanto il numero di combinazioni possibili al suo ingresso è 27 = 128, un numero finito e tutto sommato limitato, di qui l’idea di inserire in una ROM i risultati delle somme corrispondenti a queste 128 combinazioni, eliminando in tal modo il grosso sommatore che limita la massima frequenza di clock applicabile al modulatore. Ogni FIR viene pertanto realizzato con una ROM ed un registro a scorrimento nel quale fluiscono i simboli da trasmettere, le uscite in parallelo del registro individuano una locazione di memoria nella quale è memorizzato su 12 bit il risultato della somma. Un polifase che interpoli N si realizza con una unica ROM avente nelle prime 128 locazioni le somme per il primo FIR, nelle successive 128 le somme per il secondo FIR e cosı̀ via sino alle somme per il FIR Nesimo . Il multiplexer che ha il compito di iterare ciclicamente sulle uscite dei FIR si ottiene aggiungendo dei bit alla ROM e facendoli pilotare direttamente dal contatore/divisore che quindi in ogni periodo di clock va a selezionare un diverso banco di 128 locazioni di memoria corrispondente ad uno degli N FIR. Sulla base delle precedenti considerazioni il polifase che consente di implementare i 3 data rate richiesti dalle specifiche diviene quello in Fi- CAPITOLO 3. IMPLEMENTAZIONE SRRC POLIFASE 41 gura(3.7), cui corrisponde il file srrc x n.vhd (Listato F.3.3) , in esso Figura 3.7: SRRCxN versione ROM il segnale rate sel imposta il data rate e conseguentemente il multiplexer descritto in mux 3x12 (Listato F.3.5) insieme al demultiplexer demux 3x10.vhd (Listato F.3.4) seleziona la ROM da utilizzare tra quelle descritte in ROMx3.vhd (Listato F.3.6) , ROMx4.vhd (Listato F.3.7) e ROMx6.vhd (Listato F.3.8) . I valori da inserire nelle ROM sono determinati da CreaROM.m (Listato E.3.4) a partire dal file contenente i coefficienti scalati, esso calcola tutte le possibili somme per ogni FIR, le pone in cascata, implementando cosı̀ un intero polifase, e produce delle descrizioni della ROM in uno dei 3 formati: COSTANTE: è il formato utilizzato per piccole ROM, viene sintetizzato infatti come un multiplexer le cui dimensioni possono divenire rilevanti. CASE: è adatto a ROM di medie dimensioni in quanto il costrutto VHDL CASE viene riconosciuto dal sintetizzatore XST che lo implementa sulla RAM distribuita in ogni CLB10 . BlockRAM: viene utilizzato per ROM di dimensioni molto grandi implementate tramite la BlockRAM11 presente nella FPGA Virtex, è una soluzione che consente velocità di clock inferiori rispetto alla ROM distribuita nelle CLB, tuttavia è decisamente più agevole il Floorplanning12 . Il file di testo prodotto può essere applicato al Core Generator per ottenere la BlockRAM inizializzata. 10 Configurable Logic Block Appendice(C.3.4.2) 12 Appendice(D.6) 11 CAPITOLO 3. IMPLEMENTAZIONE SRRC POLIFASE 42 La produzione e distribuzione dei clock ridotti a partire dal clock di sistema a 165MHz per i motivi precedentemente espressi non avviene più secondo la tecnica gated-clock ma secondo la clock-enable. I 3 contatori/divisori utilizzati nel precedente progetto vengono soppiantati dal contatore/divisore programmabile descritto in counter.vhd (Listato F.3.2) , esso produce sia la conta ciclica sino ad N − 1 che la produzione di un impulso di abilitazione ogni N colpi di clock destinato alle descrizioni che debbono operare a velocità ridotta. Apparentemente, per quello che riguarda i vincoli sulle temporizzazioni, il clock-enable introduce un abbassamento della massima frequenza di clock in quanto circuiti ai quali prima si applicava il vincolo del clock ridotto ora si vedono applicato il vincolo del clock di sistema che è più stringente, tuttavia per essi si può settare una specifica denominata multi-cycle che comunica al sintetizzatore di rilassare le loro temporizzazioni di un fattore N. 3.4.2.1 Risultati sperimentali Per la versione ROM clock-enable del polifase sono state effettuate le due seguenti verifiche sperimentali: VHDL: si è applicata alla descrizione VHDL del polifase la medesima sequenza applicata al polifase Matlab, gli spettri risultanti sono praticamente coincidenti come illustra la Figura(3.8) riferita ad un clock di Figura 3.8: Confronto Polifase VHDL – Polifase Matlab CAPITOLO 3. IMPLEMENTAZIONE SRRC POLIFASE 43 sistema di 40MHz generata tramite PolyphasePSDVHDLvsPSDMatlab.m (Listato E.3.5) . FPGA: l’implementazione su FPGA è stata abbastanza elaborata per via della necessità di adattare il ritmo dei dati provenienti dal patterngenerator con il ritmo del segnale di abilitazione generato a partire dal clock di sistema, la soluzione trovata viene descritta in Sezione(4.3.2), qui ci si limita a riportare i risultati ottenuti tramite PolyphasePSDFPGAvsPSDMatlab.m (Listato E.3.7) in termini di confronto spettrale col modello Matlab, essi sono graficati in Figura(3.9) che Figura 3.9: Confronto Polifase FPGA – Polifase Matlab ricalca quella ottenuta per il modello VHDL. Capitolo 4 Implementazione Modulatore QPSK 4.1 Sommario I principali risultati di questa Tesi sono racchiusi in questo capitolo dove vengono illustrati due diverse realizzazioni, una ricalca lo schema classico del modulatore QPSK mentre l’altra è una diretta estensione del progetto ROM Polifase clock-enable 1 . Il modello Matlab dell’intero canale di comunicazione comprendente trasmettitore, canale e ricevitore, ha consentito sia una valutazione qualitativa dei risultati tramite gli spettri che una misura quantitativa tramite la BER agevolando inoltre lo sviluppo di entrambe i modelli VHDL. 4.2 Modello Matlab La descrizione del modello è sia in QPSKModemPSDeBERVHDLvsMatlab.m (Listato E.4.4) che in QPSKModemPSDFPGAvsPSDMatlab.m (Listato E.4.6) , la sua definizione si basa, per quel che riguarda il trasmettitore, sullo schema del modulatore classico con fclk = 4 × fif di Figura(2.6) mentre per il ricevitore si è utilizzata la teoria della demodulazione con filtro adattato2 ed il criterio di decisione ML descritto in Sezione(1.3.2), essa è di riferimento anche per la caratterizzazione del rumore introdotto dal canale. Segue una breve descrizione del modello: Trasmettitore: dal rapporto tra la frequenza di clock ed il ritmo di simbolo viene dedotto il file di coefficienti da utilizzare, essi sono calcolati da CreaCoeffsFreqSamplScaled.m (Listato E.3.1) e memorizzati in SRRCx3 FreqSampl scaled.dat, SRRCx4 FreqSampl scaled.dat e 1 2 Sezione(3.4.2) Sezione(1.3.1) 44 CAPITOLO 4. IMPLEMENTAZIONE MODULATORE QPSK 45 SRRCx6 FreqSampl scaled.dat. La sequenza randomica dei bit da trasmettere viene caricata da bit tx.dat ed è anche utilizzata per caratterizzare il modello VHDL e l’implementazione su FPGA al fine di poter effettuare confronti in termini di BER. Dalla sequenza bit tx se ne ottengono due, quella contenente i bit dispari viene applicata al ramo I del modulatore mentre l’altra, contenente i bit pari, viene applicata al ramo Q per poi essere applicate entrambe ai due filtri SRRC polifase, implementati tramite applica polifase.m (Listato E.3.2) . Le uscite degli interpolatori sono moltiplicate rispettivamente con i campioni del coseno e del seno rispondenti al vincolo fclk = 4 × fif , i campioni risultanti vengono poi sommati. Canale: viene sommato del rumore gaussiano al segnale in uscita dal modulatore, nel caso di un rumore quantificato con Eb/No = 6dB l’effetto è rappresentato in Figura(4.1). (a) Uscita Tx QPSK (b) Ingresso Rx QPSK Figura 4.1: Effetto del canale sul segnale modulato QPSK Ricevitore: il segnale QPSK affetto da rumore viene applicato ad un ADC3 e successivamente moltiplicato per i campioni delle due portanti in quadratura, il successivo filtro adattato utilizza i medesimi coefficienti dell’SRRC in trasmissione ma mantiene inalterato il ritmo dei campioni, i simboli che si ottengono alla sua uscita vengono applicati al decisore implementato tramite la funzione demodmap di Matlab. La sequenza di bit ricevuta viene confrontata con quella trasmessa, non essendo stati utilizzati dei bit di segnalazione tale operazione si effettua traslando la sequenza ricevuta di un numero di bit N bit sfasamento Matlab rispetto a quella trasmessa, il valore viene determinato in maniera empirica effettuando diverse traslazioni e scegliendo quella cui corrisponde il minimo numero di bit errati. 3 Analog Digital Converter CAPITOLO 4. IMPLEMENTAZIONE MODULATORE QPSK 46 Lo script CreaTabellaBER.m (Listato E.4.1) consente una valutazione globale delle prestazioni del modulatore, esso infatti confronta sia in forma tabellare che grafica la probabilità d’errore teorica con la BER ricavata sperimentalmente, a tal fine si avvale della funzione calcolaBER.m (Listato E.4.2) che valuta la BER in corrispondenza di un dato valore di Eb/No. Il numero di bit applicati al modulatore è funzione di Eb/No infatti se ad esempio per un dato valore di Eb/No la probabilità d’errore è dell’ordine di 10−4 allora il numero di bit da trasmettere è 10×104 . La Tabella(4.1) è riferita al data rate 110Mbps e alla frequenza di clock 165MHz cui corrisponde Eb/No (dB) 0 1 2 3 4 5 6 7 8 9 Probabilità d’errore teorica 0.07864960 0.05628195 0.03750612 0.02287840 0.01250081 0.00595386 0.00238829 0.00077267 0.00019090 0.00003362 BER Modem QPSK Matlab 0.07849516 0.05538872 0.03828828 0.02435769 0.01584918 0.00667334 0.00309671 0.00084889 0.00020659 0.00003194 Tabella 4.1: Tabella prestazioni modem Matlab in termini di BER la curva del BER rappresentata in Figura(4.2). Figura 4.2: Grafico prestazioni modem Matlab in termini di BER CAPITOLO 4. IMPLEMENTAZIONE MODULATORE QPSK 47 4.3 Modelli VHDL Dopo aver introdotto la realizzazione VHDL dello schema di principio presentato in Figura(2.6) si passa alla descrizione del progetto ThinModulator che incorpora tutte le ottimizzazioni dedotte nel capitolo precedente e ne introduce altre consentite dall’ortogonalità dei due rami del modulatore QPSK. 4.3.1 Modulatore classico Lo schema in Figura(4.3) corrisponde a Modulator BlockRAM.vhd Figura 4.3: Modulatore classico (Listato F.4.1) , si assume che il modulatore riceva in ingresso sia la sequenza dei bit pari che quella dei bit dispari, esse vengono applicate al filtro SRRC polifase in Figura(4.4) che si differenzia da quello di Figura(3.7) unicamente per il modo in cui vengono memorizzati i risultati delle somme, non più in 3 ROM distribuite nelle CLB bensı̀ in un’unica RAM4 abilitata soltanto in lettura ed implementata nella BlockRAM5 tramite un Core Xilinx. Trattandosi di un modulatore QPSK per applicazioni spaziali sono importanti sia le dimensioni che la massima frequenza di clock implementabile, nel progetto della RAM si è scelto di ottimizzare quest’ultimo aspetto inserendo le somme per ogni interpolatore SRRC in 1024 locazioni di memoria 4 5 inizializzata con il file generato da CreaROM.m (Listato E.3.4) Appendice(C.3.4.2) CAPITOLO 4. IMPLEMENTAZIONE MODULATORE QPSK 48 Figura 4.4: SRRCxN versione RAM indipendentemente dal fatto che siano tutte necessarie oppure no, in tal modo si può selezionare un SRRC oppure un altro applicando il segnale rate sel ad ulteriori 2 bit di indirizzo della RAM la quale quindi non richiede alcuna logica combinatoria a monte della sua rete di indirizzamento intrinseca. La descrizione VHDL del polifase è in srrc x n.vhd (Listato F.4.6) mentre il file per la simulazione della RAM è ram.vhd (Listato F.4.7) tuttavia si può evitare l’utilizzo del Core Xilinx istanziando 12 BlockRAM nel formato 1 × 4096bit come in Figura(4.5). Figura 4.5: RAM 12 × 4096 Le due portanti in quadratura sono generate da NCO basic.vhd (Listato F.4.5) a partire dal clock di sistema mediante un contatore modulo 4 CAPITOLO 4. IMPLEMENTAZIONE MODULATORE QPSK 49 alla cui conta ciclica vengono associati i valori di coseno e seno riportati in Tabella(4.2), i campioni delle portanti cosı̀ generate vengono moltiplicati per Valore contatore 0 1 2 3 Coseno 1 0 −1 0 Seno 0 −1 0 1 Tabella 4.2: Generazione funzioni trigonometriche col contatore i campioni provenienti dagli SRRC, in particolare in multiplier I Q.vhd (Listato F.4.4) essi vengono lasciati passare, annullati oppure invertiti a se- conda del valore della corrispondente portante per poi essere sommati in adder I Q.vhd (Listato F.4.2) la cui complessità può essere evitata, sostituendo il sommatore con un più semplice commutatore operante alla frequenza di clock, i due ingressi sono infatti alternativamente nulli. Tale ottimizzazione, cosı̀ come le prove sperimentali e la successiva implementazione su FPGA, è stata inserita nella rielaborazione del progetto denominata ThinModulator la quale include anche l’interfacciamento tra il modulatore e la sorgente dei dati. 4.3.2 ThinModulator Il nome ThinModulator6 evidenzia come in questo progetto siano state inserite tutte le ottimizzazioni rese possibili dalla modulazione QPSK, esse sono evidenziate dal diagramma temporale in Figura(4.6), relativo alla rea- Figura 4.6: Temporizzazioni modulatore classico 6 modulatore snello in inglese CAPITOLO 4. IMPLEMENTAZIONE MODULATORE QPSK 50 lizzazione VHDL del modulatore classico di Figura(4.3), in particolare si evincono due considerazioni: 1. l’uscita QPSK out del modulatore si ottiene prelevando alternativamente l’uscita QPSK I del moltiplicatore sul ramo I oppure l’uscita QPSK Q del moltiplicatore sul ramo Q. 2. le sequenze seno e coseno sono sfasate tra loro di 90◦ , immaginando di sommarle algebricamente si ottiene una sequenza che per due periodi di clock vale +1 e per i successivi due periodi vale −1. su di esse si basa il ThinModulator mostrato in Figura(4.7), Figura 4.7: ThinModulator i due interpolatori SRRC vengono realizzati con una unica RAM in quanto il contenuto per il ramo I è uguale a quello del ramo Q inoltre, come evidenziato in Figura(4.6), un campione ogni due dell’uscita del polifase viene annullato nel successivo moltiplicatore, pertanto è sensato intercalare i campioni, cosa che del resto nello schema in Figura(4.3) veniva effettuata dal sommatore d’uscita. Il commutatore mux 2x7.vhd (Listato F.5.10) provvede ad inviare alternativamente all’unica RAM un indirizzo oppure l’altro, vengono poi aggiunti 2 bit per la selezione del FIR7 ed altri 2 bit per la selezione del data rate. Nell’architettura ThinModulator le moltiplicazioni e la somma finale vengono tutte effettuate in mult C2 adder.vhd (Listato F.5.9) che opera in maniera ciclica lasciando passare inalterati 2 campioni provenienti dalla RAM ed invertendo i successivi due. Il ThinModulator necessita per il suo funzionamento del contatore programmabile counter.vhd (Listato F.3.2) descritto nella Sezione(3.4.2), esso genera il segnale di abilitazione per la tecnica clock-enable e la conta ciclica che va a selezionare l’Nesimo banco di 128 locazioni nella RAM corrispondente all’Nesimo FIR del polifase SRRC. 7 e quindi del banco di 128 locazioni di memoria CAPITOLO 4. IMPLEMENTAZIONE MODULATORE QPSK 51 Il modulatore QPSK effettivamente implementato sulla FPGA è quello il cui schema a blocchi è rappresentato in Figura(4.8), esso include anche Figura 4.8: FIFO RAM ThinModulator una interfaccia verso il mondo esterno resasi necessaria in quanto il clock associato ai dati provenienti dal pattern-generator ha la stessa frequenza del segnale clock-enable ma la relazione di fase tra i due è aleatoria e pertanto si possono verificare situazioni non previste in fase di progetto. Le possibili soluzioni al problema sono due: 1. utilizzare il clock dei dati per produrre il clock di sistema, da esso poi si ricava il segnale clock-enable, la soluzione è impraticabile in quanto le specifiche implicano la moltiplicazione del clock per fattori 3, 4 e 6 mentre la FPGA Virtex consente soltanto la moltiplicazione per 2 utilizzando una ClkDLL89 come in Figura(4.9). oppure per 4 mettendone due in cascata. 2. una FIFO10 consente di mettere in fase le due temporizzazioni, essa è costituita da un registro a scorrimento nel quale i dati vengono scritti utilizzando la temporizzazione che giunge dal pattern-generator e letti utilizzando quella prodotta localmente dal contatore programmabile counter.vhd (Listato F.3.2) . L’unica soluzione che soddisfa le specifiche del modulatore è la 2) tuttavia essa richiede che le due temporizzazioni abbiano la stessa frequenza altrimenti dopo poco tempo la FIFO o si svuota o si riempie completamente determinando cosı̀ perdita di informazione, per soddisfare questo vincolo si 8 Appendice(C.3.4.1) la frequenza minima in ingresso alla ClkDLL è 25MHz 10 First In First Out 9 CAPITOLO 4. IMPLEMENTAZIONE MODULATORE QPSK 52 Figura 4.9: Clock×2 è scelto di inviare al pattern-generator, quale sincronismo per l’emissione dei dati, il segnale di clock-enable che si ottiene a partire dal clock di sistema11 . Lo schema dell’interfaccia tra il modulatore e la sorgente dati è in Figura(4.10) cui corrisponde Data Source Interface.vhd (Listato F.5.3) , la Figura 4.10: Interfaccia modulatore – sorgente dati FIFO è stata implementata con un Core Xilinx per la cui simulazione si utilizza asynch fifo 2x15.vhd (Listato F.5.4) , il clock in scrittura è quello proveniente dal pattern-generator mentre quello in lettura è il clock di sistema tuttavia l’abilitazione alla lettura è determinata dal segnale clock-enable proveniente dal counter.vhd (Listato F.3.2) . La logica che gravita intorno 11 40MHz per la scheda DINI sulla quale è stato implementato il modulatore CAPITOLO 4. IMPLEMENTAZIONE MODULATORE QPSK 53 alla FIFO ha il compito di consentire la prima lettura soltanto dopo che essa sia stata parzialmente riempita, si deve cioè attendere che il segnale almost-empty passi per la prima volta al livello logico basso. 4.3.2.1 Risultati sperimentali 4.3.2.1.1 Test VHDL La medesima sequenza dati applicata al modello Matlab è stata applicata alla descrizione VHDL, l’uscita è poi nuovamente esportata in Matlab dove, dopo una conversione dalla rappresentazione in complemento a due al formato reale, ne viene prodotto e visualizzato lo spettro confrontandolo con quello ottenuto con il modello Matlab del modem, i due sostanzialmente coincidono come mostrato in Figura(4.11) riferita ad un modulatore interpolante 3 e che, per garantire conformità con Figura 4.11: Confronto Modulatore x3 VHDL – Matlab i risultati dell’implementazione su FPGA12 , opera ad una frequenza di clock di 40MHz. Per una verifica più puntuale lo stesso script QPSKModemPSDeBERVHDLvsMatlab.m (Listato E.4.4) realizza anche una misura di BER, a tal fine viene aggiunto del rumore gaussiano dovuto al canale ed il segnale risultante è poi applicato al demodulatore che richiede di esser tarato con la procedura inserita quale commento nello script, la corretta taratura del demodulatore consente di ottenere misure di BER praticamente identiche ai risultati teorici. 12 la scheda DINI ospita un quarzo a 40MHz eventualmente modificabile CAPITOLO 4. IMPLEMENTAZIONE MODULATORE QPSK 54 4.3.2.1.2 Test FPGA La sequenza da trasmettere è stata caricata nel Pattern Generator tramite il file di testo prodotto da CreaSequenzaPatternGenerator.m (Listato E.2.2) del quale si propone il seguente stralcio: ASCII 000000 ASCDOWN FORMAT:MODE FULL FORMAT:CLOCK EXTERNAL, LEFifty LABEL dummy, 24 LABEL data_in_SRRCxN_tx_Q, 4 LABEL rate_sel_x3, 4 LABEL reset, 4 LABEL data_in_SRRCxN_tx_I, 4 VECTOR 000000 0 0 1 0 000000 0 0 1 0 000000 0 0 1 0 000000 0 0 1 0 000000 0 0 1 0 000000 0 0 0 0 000000 0 0 0 0 000000 0 0 0 0 000000 0 0 0 0 000000 0 0 0 0 *M 000000 0 0 0 0 000000 1 0 0 0 000000 1 0 0 0 000000 0 0 0 1 000000 0 0 0 0 000000 0 0 0 1 000000 1 0 0 1 000000 1 0 0 1 000000 0 0 0 0 ...... . . . . 000000 0 0 0 1 essa segnala al pattern-generator di predisporsi per ricevere dall’esterno il sincronismo per il clock associato ai dati emessi i quali sono allocati sui canali data in SRRCxN tx I e data in SRRCxN tx Q mentre rate sel x3 imposta il data rate e reset consente l’inizializzazione della FPGA. Il segnale reset è al livello 1 soltanto nella sequenza che precede *M in quanto questa viene emessa una sola volta mentre la sequenza successiva viene ripetuta ciclicamente un numero infinito di volte. CAPITOLO 4. IMPLEMENTAZIONE MODULATORE QPSK 55 Le connessioni tra pattern-generator, scheda DINI ed analizzatore di stati logici sono descritte nel seguente testo estratto dal file .ucf il quale viene utilizzato per immettere i vincoli fisici e temporali nella sintesi del progetto sulla FPGA Xilinx Virtex1000BG560-4: ################################################ NET "clk" LOC = "D17"; #clock a 40MHz interno ################################################ # POD CLK PATTERN GENERATOR # ################################################ NET "data_in_clk" LOC = "A17"; #JP11 pin 12 NET "data_in_clk_sync" LOC = "C28"; #JP1 pin 20 ################################################ # POD 1 PATTERN GENERATOR # ################################################ NET "reset" LOC = "AE31"; #JP12 pin 10 NET "data_in_I" LOC = "AD29"; #JP12 pin 8 NET "data_in_q" LOC = "V29"; #JP12 pin 3 ################################################ # POD 2 PATTERN GENERATOR # ################################################ NET "rate_sel<0>" LOC = "V31"; #JP12 pin 4 NET "rate_sel<1>" LOC = "Y29"; #JP12 pin 6 # ################################################ # POD 2 ANALIZZATORE STATI # ################################################ NET "modulator_out<0>" LOC = "C29"; #JP6 pin 1 NET "modulator_out<1>" LOC = "A31"; #JP6 pin 3 NET "modulator_out<2>" LOC = "B30"; #JP6 pin 5 NET "modulator_out<3>" LOC = "C30"; #JP6 pin 7 NET "modulator_out<4>" LOC = "D28"; #JP6 pin 9 NET "modulator_out<5>" LOC = "F29"; #JP6 pin 13 NET "modulator_out<6>" LOC = "H31"; #JP6 pin 15 NET "modulator_out<7>" LOC = "P30"; #JP6 pin 19 NET "modulator_out<8>" LOC = "A28"; #JP6 pin 4 NET "modulator_out<9>" LOC = "C27"; #JP6 pin 8 NET "modulator_out<10>" LOC = "D32"; #JP6 pin 10 NET "modulator_out<11>" LOC = "E30"; #JP6 pin 12 NET "data_out_clk" LOC = "B29"; #JP1 pin 19 ################################################ # AZIONAMENTO MANUALE # ################################################ NET "count_clk_en_reset" LOC = "AK24"; #JP12 pin 15 CAPITOLO 4. IMPLEMENTAZIONE MODULATORE QPSK 56 Al fine di agevolare il raggiungimento dei vincoli temporali con stati scelti i pin della FPGA più vicini alle 12 BlockRAM utilizzate nel progetto, esse si trovano infatti distribuite in due colonne laterali. L’analizzatore di stati logici consente di prelevare dall’uscita del modulatore un pacchetto di 64000 campioni adiacenti, applicandoli allo script Matlab QPSKModemPSDFPGAvsPSDMatlab.m (Listato E.4.6) sono stati ottenuti gli spettri mostrati nelle figure (4.12), (4.13) e (4.14), essi evidenziano una forte similitudine tra il risultato teorico ed il risultato sperimentale. Figura 4.12: Confronto Modulatore x3 FPGA – Matlab CAPITOLO 4. IMPLEMENTAZIONE MODULATORE QPSK Figura 4.13: Confronto Modulatore x4 FPGA – Matlab Figura 4.14: Confronto Modulatore x6 FPGA – Matlab 57 Capitolo 5 Conclusioni E’ stato progettato ed implementato su FPGA un modulatore QPSK con ottime prestazioni sia in termini di purezza spettrale che di BER, la semplicità dell’architettura individuata la rende fortemente suscettibile ai continui progressi apportati alle moderne FPGA dalle principali fonderie. Possibili evoluzioni di questo lavoro di Tesi possono riguardare i seguenti aspetti: • determinazione del numero di bit effettivamente necessari in uscita dal modulatore, una riduzione in tal senso si rifletterebbe proporzionalmente sulle dimensioni della ROM. • il modulatore è pensato per applicazioni spaziali, un ambiente particolarmente ostile per i circuiti a larga scala di integrazione richiede pertanto l’implementazione di una tecnica di riconfigurazione ciclica volta a ridurre gli effetti delle radiazioni sul funzionamento del circuito. • realizzazione di una scheda che applichi l’uscita del modulatore ad un convertitore digitale/analogico il quale dovrà essere precompensato tramite i coefficienti del filtro ospitato dalla struttura polifase. L’architettura proposta è stata sviluppata su FPGA tuttavia essa si compone di una ROM, dei registri a scorrimento e poca altra logica combinatoria, si può pertanto ipotizzare una realizzazione non su logiche programmabili quali FPGA o ASIC bensı̀ su componenti VLSI commerciali. 58 Appendice A Sintesi diretta di frequenza digitale A.1 Sommario La generazione di portanti sinusoidali, una delle funzioni chiave dell’elettronica applicata alle telecomunicazioni, è stata realizzata con tecniche analogiche sino agli anni ’70 quando l’avvento dei circuiti a larga scala d’integrazione ha aperto la strada a realizzazioni digitali con prestazioni decisamente superiori, esse permettono infatti di variare la frequenza in istantaneamente e con continuità di fase raggiungendo risoluzioni dell’ordine del µHz, il tutto con costi e dimensioni contenuti. L’unico aspetto nel quale le tecniche analogiche sono superiori è l’estensione spettrale che raggiunge diversi GHz pertanto la norma di progetto è di utilizzare tecniche digitali laddove possibile ed integrarle con tecniche analogiche negli altri casi. A.2 DDFS La sintesi diretta di frequenza digitale si basa sullo schema in Figura(A.1) che viene indifferentemente denominato DDS1 , NCO2 oppure DDFS, esso genera una funzione a frequenza arbitraria e non lineare, quale il seno o il coseno3 , nei tre seguenti passi: 1. genera una sequenza di valori dell’argomento variabile in funzione della frequenza che si desidera ottenere. 2. associa alla sequenza generata le corrispondenti ampiezze del seno o del coseno. 1 Direct Digital Synthesizer Numerical Control Oscillator 3 caratterizzate tuttavia da un argomento ϕ lineare nel tempo 2 59 APPENDICE A. SINTESI DIRETTA DI FREQUENZA DIGITALE 60 Accumulatore di fase A-1 Registro Incremento A-1 fase (T) A Registro di fase A P Convertitore Fase-Ampiezza B Convertitore Digitale/Analogico Filtro A Figura A.1: Schema di principio DDFS 3. converte in analogico l’ampiezza espressa in digitale. Con riferimento alla Figura(A.1) la sequenza dei valori dell’argomento, ciascuno rappresentato con A bit, viene generata mediante l’accumulatore di fase, esso si compone di un registro di fase e di un sommatore che aggiunge al valore precedentemente contenuto nel registro il valore T di una parola di sintonia contenuta in un registro ad A−1 bit4 . Variando il valore T contenuto nel registro di incremento il progettista o l’operatore ha modo di variare la frequenza generata dal DDFS: fout = T × fclk 2A (A.1) per variare la risoluzione in frequenza occorre invece cambiare il numero di bit A del registro di fase, si tratta di un valore da decidere in sede di progetto tenendo conto della applicazione cui è destinato il DDFS, valori elevati di A infatti aumentano la risoluzione, pari a f2clk A , ma comportano una maggiore complessità circuitale e conseguentemente una minor frequenza di clock applicabile al sistema il ché per il teorema di Nyquist5 si traduce in una riduzione della massima frequenza generabile. Dopo aver generato la rampa di fase il convertitore fase/ampiezza la trasforma nella funzione sinusoidale prescelta, esso ha in ingresso P bits con P A in quanto l’utilizzo di tutti i bit che provengono dall’accumulatore di fase determina una complessità non gestibile indipendentemente dal modo in cui il convertitore è realizzato. Il troncamento della fase determina in uscita dal DDFS la presenza di spurie la cui distribuzione ed ampiezza può tuttavia essere controllata mediante una opportuna pianificazione delle frequenze. 4 5 per ottemperare al criterio di Nyquist Appendice(B.2) APPENDICE A. SINTESI DIRETTA DI FREQUENZA DIGITALE 61 La sequenza discreta ottenuta dal convertitore fase-ampiezza viene applicata ad un DAC il cui numero di bit B in ingresso determina il massimo livello delle spurie da esso prodotte, l’ordine zero del campionamento da poi luogo ad una sagomatura sin(x) dello spettro che richiede una precompensax zione. Il filtro anti-aliasing ha il compito di lasciare passare in uscita il solo Figura A.2: Spettro in uscita dal DAC spettro compreso nella banda 0 < fout < fclk 2 detta di Nyquist. A.3 Pianificazione delle frequenze A.3.1 Spurie dovute al DAC Come evidenziato in Figura(A.2) la non-linearità del DAC genera alla sua uscita oltre alla frequenza fondamentale fout anche delle immagini aventi frequenza fclk ± fout , scegliendo fout > fN yquist abbiamo che la prima immagine cade nella banda di Nyquist e quindi non può essere filtrata pertanto, tenendo conto anche della banda di transizione non nulla del filtro anti-aliasing, si ha che la massima frequenza generabile è dell’ordine di 0, 4fout . La distribuzione delle spurie dovute al DAC è imposta dalla relazione tra fclk e fout mentre la loro ampiezza è determinata dal numero di bit B S in particolare abbiamo che il rapporto N espresso in dB tra il segnale ed il rumore di quantizzazione [10] vale: S N (dB) = 6.02 × B + 1.76 + 20 log10 (F F S) (A.2) dove con FFS si indica la percentuale del fondoscala a cui lavora il DAC. La potenza del rumore di quantizzazione è costante per un dato valore di B pertanto se si riduce la banda utile ossia si lavora in una frazione della S banda di Nyquist si ottiene un miglioramento del rapporto N . APPENDICE A. SINTESI DIRETTA DI FREQUENZA DIGITALE 62 A.3.2 Spurie dovute al troncamento della fase La risoluzione in frequenza aumenta al crescere del numero di bit A nell’accumulatore di fase tuttavia, allo stato attuale della tecnica, soltanto i P bit più significativi possono essere applicati al convertitore fase-ampiezza che altrimenti diviene irrealizzabile. Il troncamento da luogo ad un errore che è periodico e pertanto produce delle frequenze spurie in uscita dal DDFS, la loro ampiezza varia da un minimo di 0 quando i P bit eliminati sono tutti 0, condizione che si verifica per6 : GCD T, 2(A−P ) = 2(A−P ) (A.3) ad un massimo di −6.02P dBc nel caso l’MSB7 dei P bit troncati sia 1 e tutti gli altri siano 0 il che accade se: GCD T, 2(A−P ) = 2(A−P ) (A.4) Per comprendere la distribuzione di queste spurie si parte dall’osservazione che il segnale d’errore è proprio la parola troncata espressa su R = A−P bits, la parola di sintonia ad essa associata è ET W = T mod 2R la quale accumulandosi da luogo alla forma d’onda a dente di sega di Figura(A.3) ET W avente frequenza fondamentale F0 = Fclk × 2R e spettro rappresentato Figura A.3: Andamento nel tempo della parola troncata in Figura(A.4). Le righe spettrali che cadono in multipli dispari della banda Figura A.4: Spettro dente di sega di Nyquist hanno delle immagini proprio all’interno di essa e pertanto non sono eliminabili mediante filtraggio, si può soltanto ridistribuirne la potenza 6 7 GDC indica il massimo comun divisore tra i due argomenti Most Significant Bit APPENDICE A. SINTESI DIRETTA DI FREQUENZA DIGITALE 63 mediante la tecnica del dithering che consiste nel distruggere la periodicità aggiungendo delle quantità randomiche prima del troncamento. A.4 Convertitore Fase-Frequenza Vi sono due tipi di convertitore fase-ampiezza: ROM le fasi troncate in uscita dall’accumulatore di fase individuano delle locazioni di memoria in una ROM le quali contengono la corrispondente ampiezza del seno o del coseno. La simmetria del coseno e del seno consente di ridurre le dimensioni della ROM limitandosi a memorizzare i valori delle ampiezze per le sole fasi comprese tra 0 e 90◦ ed utilizzando i due bit più significativi della parola di fase troncata per ricostruire l’ampiezza corretta come in Figura(A.5). Figura A.5: Ottimizzazione del convertitore fase-ampiezza CORDIC la simmetria del coseno e del seno viene utilizzata anche nella soluzione CORDIC [9], della quale esistono due forme denominate Vectoring CORDIC e Rotation CORDIC, quest’ultima è quella utile per la generazione di seno e coseno a partire dall’argomento, si cerca infatti di annullare l’angolo ϕ iniziale sommando e sottraendo ad esso degli angoli via via più piccoli, al crescere del numero di iterazioni aumenta la precisione del risultato e conseguentemente migliora l’approssimazione sia per il seno che per il coseno dell’angolo di partenza. L’algoritmo è adatto ad applicazioni digitali in quanto le rotazioni si basano su moltiplicazioni per potenze di due. La ROM risulta una soluzione conveniente nel caso si scelga una fase troncata con al massimo 14 bit [14], oltre conviene la soluzione CORDIC la quale ha anche il vantaggio di produrre congiuntamente ed in maniera APPENDICE A. SINTESI DIRETTA DI FREQUENZA DIGITALE 64 intrinseca sia seno che coseno risultando ottimale per la realizzazione di un modulatore con portanti in quadratura, per questi motivi nel seguito verrà tralasciata la trattazione del DDFS basato sulla ROM. A.4.1 Algoritmo CORDIC Si basa su di una rotazione planare che trasforma un vettore (Xi , Yi ) in un nuovo vettore (Xn , Yn ), la forma matriciale di una generica rotazione Y (Xn , Yn) (Xi , Yi) X Figura A.6: Rotazione planare planare di un angolo ϕ è Xn Yn cos ϕ sin ϕ sin ϕ cos ϕ = Xi Yi (A.5) trattandosi di un algoritmo iterativo la rotazione ϕ viene scomposta in n rotazioni ϕi ciascuna delle quali è espressa dalla Xi+1 Yi+1 cos ϕi sin ϕi sin ϕi cos ϕi = Xi Yi (A.6) da cui raccogliendo cos (ϕi ) si ha Xi+1 Yi+1 = cos ϕi 1 − tan ϕi tan ϕi 1 Xi Yi (A.7) quest’ultima forma è vantaggiosa in quanto il numero di moltiplicazioni passa da 4 a 3, l’ulteriore vincolo tan ϕi = Si 2(−i) (A.8) APPENDICE A. SINTESI DIRETTA DI FREQUENZA DIGITALE 65 con Si ∈ {−1; +1} consente di ottimizzare l’implementazione su sistemi digitali in quanto le moltiplicazioni per potenze di due si ottengono facendo scorrere il contenuto di un registro in una direzione o nell’altra. Il valore di Si alla iesima iterazione viene determinato richiedendo che sia minima la differenza tra l’angolo iniziale e l’angolo che si ottiene dalla somma degli angoli delle iterazioni precedenti, se tale differenza è minore di zero allora Si = −1 altrimenti Si = +1. Il vincolo descritto dall’equazione(A.8) è fondamentale nella semplificazione dell’algoritmo in quanto cos (ϕi ) = cos (−ϕi ) e quindi per una data iterazione n la produttoria dei cos (ϕi ) delle iterazioni precedenti è nota a priori e vale Kn = n−1 Y i=0 Ki = n−1 Y i=0 cos arctan 1 2i = n−1 Yp 1 + 2(−2i) (A.9) i=0 tale valore approssima 0, 607252935008881 per n → ∞ ma già per n = 5 vale 0, 607351770141296 pertanto per algoritmi CORDIC con un numero di iterazioni maggiori di 10 si può considerare un numero costante soprattutto in considerazione della lunghezza finita dei registri. Il reciproco di K vale approssimativamente 1, 64676025812107 ed è denominato guadagno del CORDIC, se occorre che il vettore risultante abbia modulo unitario deve essere compensato utilizzando una delle seguenti strategie: 1. per la prima iterazione si ha Xi = 1 , Yi = 0 , alla fine occorre dividere sia Xn che Yn per il guadagno. 2. iniziando con Xi = 0.607351770141296 , Yi = 0 non è poi necessario dividere per il guadagno tuttavia le prestazioni sono inferiori rispetto alla soluzione precedente in quanto 0, 607351770141296 non è potenza di due e quindi la sua implementazione in un registro implica un errore iniziale. 3. compensazione del guadagno ad ogni iterazione. Omettendo K per semplicità di rappresentazione si ha che l’iesima iterazione del CORDIC è descritta dalle equazioni: Xi+1 = Xi − Si 2(−2i) Yi Y = Yi + Si 2(−2i) Xi i+1 ϕi+1 = ϕi − Si arctan 2(−2i) (A.10) A.5 Descrizione modello matematico Lo script Matlab che descrive l’NCO è NCO Q.m (Listato E.1.1) , tramite Imposta frequenze Q (Listato E.1.2) vengono impostate la frequen- APPENDICE A. SINTESI DIRETTA DI FREQUENZA DIGITALE 66 za di clock e quella desiderata in uscita mentre Imposta NCO Q.m (Listato E.1.3) consente di impostare i parametri: n n n n n bit acc periods bit cordic it cordic bit dac N◦ N◦ N◦ N◦ N◦ di di di di di bit accumulatore di fase periodi della funzione generata bit per la fase troncata iterazioni del CORDIC bit per seno e coseno prodotti dal CORDIC L’accumulatore di fase in Crea super accumulatore Q.m (Listato E.1.4) è modellato con un vettore contenente tutti i valori consecutivi della fase da applicare al CORDIC, in tale vettore sono memorizzate n periods rampe di fase. Tronca Q.m (Listato E.1.5) consente di passare da una rappresentazione della fase su n bit acc bits ad una su n bit cordic bits, tale vettore quantizzato è poi utilizzato da Crea coseno e seno Q.m (Listato E.1.6) il quale per ogni campione di fase invoca Forward cordic Q.m (Listato E.1.7) che opera riportando tutte le fasi nel primo quadrante in accordo alla Figura(A.5) ed eseguendo iterativamente per n it cordic volte le equazioni(A.10). Partendo con il coseno che vale 0, 607252936517011 invece che 1 non è necessario dividere dopo l’ultima iterazione per il guadagno del CORDIC8 tuttavia occorre riportare i valori calcolati nel giusto quadrante, del seno e coseno ottenuti viene visualizzato un periodo nel dominio del tempo come in Figura(A.7) relativa al caso di fclk = 4 × fout . (a) Coseno (b) Seno Figura A.7: Uscita DDFS nel tempo Per la determinazione dello spettro viene utilizzato il metodo MultiTaper in Visualizza spettro e SFDR p.m (Listato E.1.9) il quale mostra anche l’SFDR9 determinato in Calcola SFDR.m (Listato E.1.10) quale differenza tra il massimo assoluto dello spettro ed il maggior massimo relativo, un esempio dei risultati ottenuti è in Figura(A.8). A.6 Descrizione modello VHDL Il file NCO.vhd (Listato F.1.1) descrive lo schematico di Figura(A.9), quando 8 9 Appendice(A.9) Spurious Free Dynamic Range APPENDICE A. SINTESI DIRETTA DI FREQUENZA DIGITALE 67 Figura A.8: Spettro Coseno Matlab U2 Theta_tr(12) ctrl(1) clk in_delay_13 out_delay_13 delay_13 ctrl(1:0) U1 Theta_tr(11) ctrl(0) clk in_delay_13 out_delay_13 delay_13 ctrl(1:0) cos(11:0) accumulator clk freq_word(31:0) freq_word(31:0) load coseno(11:0) in_cosine_rebuild(11:0) out_cosine_rebuild(11:0) U4 U5 troncatore_12 Theta(31:0) theta(31:0) ingresso(31:0) clear uscita(12:0) U6 Theta_tr(12:0) U0 in_tfq(12:0) out_tfq(12:0) fase(12:0) U8 clk coseno(11:0) cosine_rebuild fase(12:0) seno(11:0) to_first_quadrant cordic_pipelined_unrolled load sin(11:0) clear U3 Theta_tr(12) clk in_delay_13 out_delay_13 out_sine_rebuild(11:0) in_sine_rebuild(11:0) ctrl U7 sine_rebuild seno(11:0) ctrl_segno_seno delay_13 Figura A.9: NCO VHDL LOAD è alto l’accumulatore Accumulator.vhd (Listato F.1.2) viene caricato con la parola di sintonia il cui valore in binario viene calcolato tramite lo script Matlab Calcola incremento fase NCO.m (Listato E.1.11) ad ogni colpo di clock questo incremento si somma al valore precedentemente APPENDICE A. SINTESI DIRETTA DI FREQUENZA DIGITALE 68 contenuto nel registro a 32 bit per poi essere troncato a 12 bit tramite Troncatore 12.vhd (Listato F.1.14) , i 2 bit più significativi vengono ritardati da Delay 13.vhd (Listato F.1.11) di 13 periodi di clock in modo da poter associare al giusto quadrante il seno ed il coseno calcolati per un dato valore della fase che viene confinata tra 0◦ e 90◦ da To first quadrant.vhd (Listato F.1.13) , in pratica questi due bit vanno a pilotare delle inversioni in complemento a due realizzate condizionatamente in Cosine rebuild.vhd (Listato F.1.10) e Sine rebuild.vhd (Listato F.1.12) . Coseno e seno vengono calcolati mediante un’architettura CORDIC non iterativa al fine di ottenere la massima velocità di clock di sistema, ogni iterazione è effettuata tramite Cordic base j.vhd (Listato F.1.4) in accordo alle equazioni(A.10) visivamente descritte in Figura(A.10). U0 clk reg_12 clk in_x(11:0) adder_12 U4 x_out_reg(11:0) in_reg_12(11:0)out_reg_12(11:0) in_a(11:0) U2 shifter coseno(11:0) out_adder_12(11:0) shifter_to_adder_x(11:0) in_b(11:0) sgn in_shifter(11:0) out_shifter(11:0) clk U3 clk U1 in_b(11:0) clk in_a(11:0) a_cost_j(12:0) reg_13 clk seno(11:0) out_adder_12(11:0) y_out_reg(11:0) in_reg_12(11:0)out_reg_12(11:0) U6 sgn shifter_to_adder_y(11:0) reg_12 clk in_z(12:0) sgn in_shifter(11:0) out_shifter(11:0) clk in_y(11:0) z_out_reg(12) shifter U5 adder_12 U7 adder_13 in_b(12:0) out_adder_13(12:0) z_out_reg(12:0) in_reg_13(12:0)out_reg_13(12:0) in_a(12:0) fase_j(12:0) sgn z_out_reg(12) Figura A.10: Iterazione iesima Vengono eseguite 13 iterazioni in cascata, tramite la descrizione Cordic pipelined unrolled.vhd (Listato F.1.3) cui è associato lo schema in Figura(A.11) in esso i valori degli angoli elementari da sommare o sottrarre vengono calcolati ed espressi in binario tramite lo script Matlab Calcola rotazioni Cordic.m (Listato E.1.8) i cui risultati sono visualizzati in Tabella(A.1) che ben evidenzia come l’entità della rotazione i esima si dimezza rispetto alla rotazione precedente. Tramite lo script Matlab Visualizza spettro NCO VHDL.m (Listato E.1.12) è possibile ottenere lo spettro del coseno generato dal CORDIC VHDL, un esempio di risultato è riportato in Figura(A.12). APPENDICE A. SINTESI DIRETTA DI FREQUENZA DIGITALE cordic_base_j clk in_x(11:0) coseno(11:0) x0(11:0) y0(11:0) in_y(11:0) z0(12:0) y1(11:0) seno(11:0) in_z(12:0) z1(12:0) fase_j(12:0) cordic_base_j clk in_x(11:0) coseno(11:0) x1(11:0) in_y(11:0) seno(11:0) in_z(12:0) fase_j(12:0) cordic_base_j clk in_x(11:0) coseno(11:0) x2(11:0) y2(11:0) in_y(11:0) seno(11:0) in_z(12:0) fase_j(12:0) z2(12:0) cordic_base_j clk in_x(11:0) coseno(11:0) x3(11:0) y3(11:0) in_y(11:0) z3(12:0) y4(11:0) seno(11:0) in_z(12:0) cordic_base_j clk in_x(11:0) coseno(11:0) x4(11:0) in_y(11:0) seno(11:0) in_z(12:0) fase_j(12:0) z4(12:0) fase_j(12:0) cordic_base_j clk in_x(11:0) coseno(11:0) x5(11:0) y5(11:0) in_y(11:0) z5(12:0) seno(11:0) in_z(12:0) fase_j(12:0) x6(11:0) y6(11:0) z6(12:0) 69 cordic_base_j clk in_x(11:0) coseno(11:0) in_y(11:0) seno(11:0) in_z(12:0) fase_j(12:0) x7(11:0) y7(11:0) z7(12:0) fase(12:0) a_cost_j(12:0) U0 a_cost_j(12:0) U1 a_0(12:0) SignalAssignments_2 SignalAssignments_3 a_0<= "0010000000000" ; in_y(11:0) in_z(12:0) seno(11:0) fase_j(12:0) y8(11:0) in_y(11:0) z8(12:0) in_z(12:0) a_cost_j(12:0) U7 a_7(12:0) SignalAssignments_9 a_7 <= "0000000001010" ; seno(11:0) fase_j(12:0) y9(11:0) in_y(11:0) z9(12:0) in_z(12:0) a_cost_j(12:0) U8 a_8(12:0) SignalAssignments_10 a_8 <= "0000000000101" ; seno(11:0) fase_j(12:0) x10(11:0) y10(11:0) z10(12:0) in_y(11:0) in_z(12:0) a_cost_j(12:0) U9 a_9(12:0) SignalAssignments_11 a_9 <= "0000000000010" ; seno(11:0) fase_j(12:0) x11(11:0) y11(11:0) z11(12:0) clk x12(11:0) in_x(11:0) coseno(11:0) in_y(11:0) seno(11:0) y12(11:0) in_y(11:0) fase_j(12:0) z12(12:0) in_z(12:0) in_z(12:0) a_10(12:0) SignalAssignments_12 a_10 <= "0000000000001" ; a_cost_j(12:0) U11 a_11(12:0) SignalAssignments_13 a_11 <= "0000000000000" ; seno(11:0) x13(11:0)coseno(11:0) y13(11:0)seno(11:0) fase_j(12:0) a_cost_j(12:0) U12 a_12(12:0) SignalAssignments_14 a_12 <= "0000000000000" ; Figura A.11: Cordic Pipelined Unrolled Iterazione 1 2 3 4 5 6 7 8 9 10 11 12 13 a_6 <= "0000000010100" ; cordic_base_j clk in_x(11:0) coseno(11:0) a_cost_j(12:0) U10 a_6(12:0) SignalAssignments_8 a_5 <= "0000000101000" ; cordic_base_j a_cost_j(12:0) U6 a_5(12:0) SignalAssignments_7 a_4 <="0000001010001" ; cordic_base_j clk in_x(11:0) coseno(11:0) a_cost_j(12:0) U5 a_4(12:0) SignalAssignments_6 a_3 <= "0000010100010" ; cordic_base_j clk in_x(11:0) coseno(11:0) x9(11:0) a_cost_j(12:0) U4 a_3(12:0) SignalAssignments_5 a_2 <="0000100111111" ; cordic_base_j clk in_x(11:0) coseno(11:0) x8(11:0) a_cost_j(12:0) U3 a_2(12:0) SignalAssignments_4 a_1 <="0001001011100" ; cordic_base_j clk in_x(11:0) coseno(11:0) a_cost_j(12:0) U2 a_1(12:0) Angolo ϕi 45, 0000 26, 5651 14, 0362 7, 1250 3, 5763 1, 7899 0, 8952 0, 4476 0, 2238 0, 1119 0, 0560 0, 0280 0, 0140 Tabella A.1: Rotazioni elementari CORDIC SignalAssignments_15 x0 <= "010011011100" ; y0 <= "000000000000" ; APPENDICE A. SINTESI DIRETTA DI FREQUENZA DIGITALE Figura A.12: Spettro coseno generato dal DDFS VHDL 70 Appendice B Sistemi Multirate B.1 Sommario Tutti i sistemi dove l’elettronica analogica deve interfacciarsi con l’elettronica digitale sono dei sistemi multirate nei quali vi sono campioni generati con frequenze di campionamento FS diverse, in particolare si può pensare che la parte analogica del sistema operi con FS → ∞ mentre la parte digitale con la minima FS sufficiente all’elaborazione desiderata, vengono cosı̀ mantenute basse sia la complessità che la dissipazione del sistema digitale. Numerosi sono gli esempi di sistemi multirate completamente digitali, ad esempio per l’audio digitale si ha che gli studi di produzione campionano a 48kHz mentre lo standard per i CD è a 44, 1kHz ed il broadcasting a 32kHz, per passare informazioni da un ambiente all’altro si rende quindi necessario a seconda dei casi un upsampler1 che consente di salire ad un rate più alto oppure un downsampler2 col quale scendere ad un rate più basso. B.2 Downsampling e Upsampling Nei sistemi multirate il seguente teorema del campionamento assume importanza fondamentale: Teorema 2 (di Shannon e Nyquist) Se un segnale continuo x (t) possiede trasformata di Fourier X (f ) a banda limitata (i.e. |X (f )| = 0 ∀ |f | 6∈ [f0 , f0 + B]) allora x (t) può essere ricostruito in maniera univoca e senza errore a partire dai suoi campioni x (kT ) a patto che la frequenza di campionamento Fs = T1 sia maggiore della frequenza di Nyquist FN yquist = 2B del segnale. Nel caso la condizione sulla banda limitata non sia rispettata si ha aliasing [10], le code di una replica spettrale centrate su di un multiplo 1 2 il termine interpolatore non include il filtro anti-immagine situato a valle il termine decimatore non include il filtro anti-aliasing situato a monte 71 APPENDICE B. SISTEMI MULTIRATE 72 della frequenza di campionamento si vanno cioè a sovrapporre a quelle della replica antecedente e della replica successiva. L’upsampler si basa sull’interpolatore il quale deve produrre in uscita più campioni di quanti ne abbia in ingresso mantenendo uno spettro simile, ciò si può ottenere o aggiungendo L − 1 zeri tra due campioni d’ingresso adiacenti nel caso si voglia interpolare L, oppure ripetendo L − 1 volte ogni campione, quest’ultima soluzione è più complessa da un punto di vista circuitale e conduce a risultati peggiori in quanto si tratta di un campionamento con tenuta di ordine zero. Per comprendere la necessità di un filtro a valle dell’interpolatore si fa riferimento alla Figura(B.1), in particolare in Figura B.1: Upsampling (B.1.a) si ha lo spettro di un generico segnale campionato caratterizzato da una banda inferiore alla banda di Nyquist e con delle repliche centrate intorno ai multipli della frequenza di campionamento FS1 , lo spettro all’uscita dell’interpolatore è rappresentato in (B.1.b) e si differenzia dal precedente in quanto all’uscita dell’interpolatore la frequenza di campionamento è FS2 e pertanto all’interno della banda di Nyquist sono presenti delle componenti spettrali che non c’erano a monte dell’interpolatore, esse sono dette immagini ed il filtro passabasso tramite il quale vengono eliminate è detto filtro APPENDICE B. SISTEMI MULTIRATE 73 anti-immagine. L’upsampler è pertanto costituito da un interpolatore ed un filtro anti-immagine come in Figura(B.2). Figura B.2: Upsampler Il downsampler è basato sul decimatore il quale deve produrre in uscita meno campioni di quanti ne abbia in ingresso mantenendo uno spettro simile, ciò si ottiene prendendo un campione ogni M nel caso si voglia decimare il rate di un valore M. La Figura(B.3) illustra la necessità di un filtro a monte del decimatore in particolare in (B.3.a) si ha lo spettro di Figura B.3: Downsampling un generico segnale campionato caratterizzato da una banda inferiore alla banda di Nyquist riferita alla frequenza di campionamento FS1 in ingresso al downsampler, il segnale in uscita dal decimatore occupa la medesima APPENDICE B. SISTEMI MULTIRATE 74 banda tuttavia essendo diminuita la frequenza di campionamento3 , è diminuita anche la banda di Nyquist che essendo divenuta inferiore a quella del segnale, in virtù del teorema del campionamento, determina aliasing. A monte del decimatore è pertanto necessario un filtro detto antialiasing che limiti la banda del segnale d’ingresso all’interno della banda di Nyquist relativa al rate più basso conseguentemente lo schema a blocchi del downsampler è quello rappresentato in Figura(B.4). Figura B.4: Downsampler Lavorando sui campioni è implicito siano possibili soltanto fattori interi d’interpolazione o decimazione, nel caso in cui se ne richiedano di frazionari occorre mettere in cascata il decimatore e l’interpolatore facendo attenzione che l’interpolatore preceda il decimatore come in Figura(B.5) in quanto alFS trimenti la banda del segnale d’ingresso deve essere confinata in 2M essendo M il fattore di decimazione. Figura B.5: Cambiamento di rate frazionario Nel caso in cui si desideri realizzare dei fattori di interpolazione o decimazione elevati occorre suddividere la catena in più stadi, in genere due o tre, ed implementare il rate più elevato nell’ultimo stadio, tornano molto utili inoltre le Nobili Identità in Figura(B.6), dimostrate in [12], le quali consentono di spostare l’operazione di filtraggio verso la regione del sistema che opera con il rate più basso ottenendo cosı̀ una notevole semplificazione. B.3 Architetture Multirate Diverse architetture sono state sviluppate allo scopo di realizzare sistemi multirate tuttavia al momento le opzioni più valide ed utilizzate sembrano 3 che in figura vale FS2 = FS1 3 APPENDICE B. SISTEMI MULTIRATE 75 Figura B.6: Nobili Identità essere la decomposizione polifase ed il CIC4 , esse presentano caratteristiche abbastanza diverse pertanto a seconda dell’applicazione si può trovare una oppure l’altra o anche entrambe. B.3.1 CIC Il CIC è stato introdotto da Hogenhauer [6] nel 1981 si caratterizza per la sua estrema semplicità che ne porta a trascurare i difetti quali la risposta in frequenza non piatta e l’eccessivo guadagno. E’ costituito da una cascata di n blocchi integratori5 ed n blocchi comb6 , ciascuno di essi contiene un sommatore ed un ritardo, sono quindi assenti i moltiplicatori la cui implementazione su FPGA determina spesso la massima frequenza di clock utilizzabile nel circuito, l’architettura CIC è quindi ideale per sistemi dove siano richiesti elevati cambiamenti di rate corrispondenti ad alte frequenze non raggiungibili dai moltiplicatori. La funzione di trasferimento dell’integratore nel piano Z è HI (z) = 1 1 − z −1 (B.1) ha pertanto un polo in z= −1 che ne determina il comportamento passabasso ma con un guadagno infinito nell’origine, si tratta pertanto di un sistema instabile che viene compensato inserendo in cascata un comb la cui funzione di trasferimento è HC (z) = 1 − z −RM (B.2) dove R è la variazione del data rate desiderata mentre M è il ritardo differenziale che sovente assume i valori 1 o 2 ed in pratica si realizza inserendo M blocchi di ritardo nella catena che porta al sommatore. L’interpolatore o il decimatore CIC si ottengono rispettivamente ponendo in cascata N comb 4 Cascaded Integrator Comb Figura(B.7) 6 Figura(B.8) 5 APPENDICE B. SISTEMI MULTIRATE 76 (a) Integrator (b) Integrator Figura B.7: Integratore e sua risposta in frequenza (a) Comb (b) Comb Figura B.8: Comb e sua risposta in frequenza ed N integratori oppure viceversa, se però tra i blocchi si effettua il cambiamento del rate come nelle Figure (B.9) e (B.10) si ottiene che metà del CIC opera ad un rate più basso con gli indubbi vantaggi che ne conseguono ed inoltre il progetto dei due blocchi diviene indipendente dal cambiamento di rate desiderato quindi la struttura può esser resa programmabile. Figura B.9: Interpolatore CIC In entrambe i casi la risposta in frequenza nel piano z è: H (z) = HIN (z) HCN (z) = 1 − z −RM N (1 − z −1 )N = RM −1 X k=0 !N z −k (B.3) APPENDICE B. SISTEMI MULTIRATE 77 Figura B.10: Decimatore CIC il cui spettro nel caso di R = 2 rappresentato in Figura(B.11) evidenzia un Figura B.11: Spettro del CIC per R=2, N=1, M=1 nullo in corrispondenza della frequenza di campionamento relativa al rate minore, mentre in corrispondenza della sua frequenza di Nyquist ossia al margine della banda utile presenta un’attenuazione di circa 5 dB, questa osservazione da sola è sufficiente ad affermare che il CIC è inadatto per implementazioni di piccoli cambi di data rate, nel qual caso occorre compensare la risposta in frequenza in modo da renderla maggiormente piatta nella banda utile. Per ampi valori del cambiamento di rate R si ottiene dall’Equazione(B.3) l’approssimazione N πM f H (f ) = RM sinπM f se 0 ≤ f < 1 M (B.4) che consente le seguenti tre osservazioni importanti ai fini del progetto: 1 1. nello spettro vi sono dei nulli in corrispondenza dei multipli di f = M modificando M, R ed N opportunamente si può fare in modo che i termini di aliasing o immagine cadano in queste regioni come evidenziato in Figura(B.12). 2. al crescere di N aumenta velocemente l’attenuazione il che significa che la banda nella quale la risposta in frequenza è piatta si restringe ulteriormente, diviene pertanto sempre più necessario l’inserimento a monte di una precompensazione. APPENDICE B. SISTEMI MULTIRATE (a) N = 4, M = 1, R = 7 78 (b) N = 4, M = 2, R = 7 Figura B.12: Effetto di M sulla frequenza del CIC 3. si ha un guadagno molto elevato infatti a fronte di Bin bits in ingresso si hanno Bout = [N log2 RM + Bin ] bits in uscita7 , la dipendenza da R comporta che la decisione sul numero di bit debba tenere conto sia del massimo che del minimo rate8 a cui il CIC deve operare. B.3.2 Polifase La struttura polifase [5] ha il grande vantaggio di essere un upsampler vero e proprio infatti l’architettura determina il cambiamento di rate mentre i suoi coefficienti impostano la risposta dei filtri anti-aliasing o anti-immagine. Ipotizzando di voler interpolare 3 e di disporre dei coefficienti h (n) del filtro anti-immagine, cui corrisponde la trasformata H (z) = N −1 X h (n) z −n (B.5) n=0 7 8 nel caso di un decimatore implementato con una aritmetica in complemento a due determina il numero di bit da mantenere nello stadio finale APPENDICE B. SISTEMI MULTIRATE 79 scomponibile nelle tre componenti polifase H0 (z), H1 (z) ed H2 (z): H (z) = N −1 X h (n) z −n n=0 = N −1 3 N −1 3 X X h (3n) z −(3n) + n=0 = N −1 3 h (3n + 1) z −(3n+1) + n=0 N −1 3 X X n=0 = H0 (z) + z −1 H1 (z) + z h (3n + 2) z −(3n+2) n=0 N −1 3 h (3n) z −(3n) + z −1 X n=0 −2 N −1 3 h (3n) z −(3n) + z −2 X h (3n) z −(3n) n=0 H2 (z) (B.6) si ha che l’ultima equazione è implementabile con lo schema in Figura(B.13 a), da essa tramite un risultato classico della teoria dei sistemi si ottiene lo schema(B.13 b) quindi utilizzando la Nobile Identità (b) si giunge allo schema(B.13 c) nel quale la parte terminale non è altro che un commutatore che ad ogni intervallo di clock preleva in maniera ciclica una delle tre componenti polifase come evidenziato in Figura(B.13 d). Figura B.13: Trasformazioni interpolatore polifase Rispetto alla forma polifase di partenza quella ottenuta è più efficiente in quanto le tre componenti operano ad un rate minore rispetto al commutatore inoltre estendendo la precedente trattazione si possono ottenere risultati simili sia per un interpolatore polifase di ordine N che per un decimatore polifase. Nella realizzazione pratica non si fa altro che distribuire i coefficienti del filtro di partenza su L filtri se L è il fattore di interpolazione, ognuno di questi filtri implementa una decomposizione polifase, l’uscita dei filtri può APPENDICE B. SISTEMI MULTIRATE 80 andare ad un sommatore oppure più intelligentemente ad un commutatore il quale ne trasferisce in uscita solo uno alla volta in maniera ciclica ad un rate L volte superiore al rate dei dati in ingresso al polifase, ciò è possibile in quanto il processo d’interpolazione inserisce L − 1 zeri per ogni campione d’ingresso, è pertanto inutile calcolare il prodotto di questo campione nullo per il rispettivo coefficiente del filtro. Appendice C Logiche programmabili C.1 Sommario Dopo aver elencato le diverse tipologie di logiche programmabili evidenziandone i principali pregi e difetti si passa ad una descrizione particolareggiata dell’architettura Virtex [15] alla quale appartiene l’FPGA utilizzata nell’implementazione del modulatore. C.2 Tipologie di logiche programmabili Le logiche programmabili sono una delle diverse possibità di implementazione di un circuito digitale, la gerarchia delle possibili soluzioni è illustrata in Figura(C.1). Figura C.1: Gerarchia implementazioni circuiti logici La prima tipologia di logica programmabile è stata la PAL1 che implementa una somma di prodotti programmabile una sola volta, la sua diretta 1 Programmable Array Logic 81 APPENDICE C. LOGICHE PROGRAMMABILI 82 estensione è rappresentata dalle PLD2 le quali dispongono di un elevato numero di blocchi logici interconnessi tra loro, ciascuno di essi implementa una somma di prodotti che può essere registrata o meno, il ritardo che ne deriva è quindi ben definito. Vi sono poi le CPLD3 le quali non presentano delle interconnessioni globali bensi delle strutture di routing raccolte in fasci pertanto il ritardo risulta definito soltanto a livello locale mentre non è possibile conoscere a priori quali gruppi di fasci verranno effettivamente utilizzati per le interconnessioni. Diverse CPLD sono del tipo ISP4 possono cioè essere programmate senza estrazione dal circuito, tale programmazione rimane memorizzata sin quando non è necessario mutare il funzionamento della CPLD in accordo a mutate esigenze della logica d’utente. Chiudono il quadro delle logiche programmabili le FPGA, dispositivi molto complessi nei quali sono immersi un numero elevato di blocchi logici abbastanza semplici ma tutti interconnessi tra loro, il ritardo è pertanto non predicibile a priori. Si sono nel tempo affermate due diverse tipologie di FPGA, le OTP5 e le ISP anche dette SRAM6 , tra le OTP la tecnologia più rilevante è la antifuse caratterizzata da elementi molto piccoli e veloci da programmare i quali però per tale operazione richiedono ai bordi del circuito integrato un numero elevato di transistori aventi il compito di fondere il polisilicio amorfo. I veri vantaggi sono pertanto: 1. non è possibile carpire la logica a partire dal dispositivo che pertanto è adatto ad applicazioni dove sia richiesto un certo grado di segretezza. 2. sopporta elevate radiazioni elettromagnetiche senza subire alterazioni funzionali il che è importante in applicazioni spaziali. Le FPGA con tecnologia SRAM richiedono la riprogrammazione ad ogni riaccensione, a tal fine si utilizza una PROM esterna la quale contiene la configurazione in maniera stabile e ad ogni ripartenza la passa ad una o più FPGA disposte in catena. Attualmente si tratta della tecnologia che consente di raggiungere le prestazioni più elevate sia in termini di velocità di clock che di complessità delle funzioni realizzate, nella seguente sezione viene descritta l’architettura Virtex della Xilinx che ha riscosso un notevole successo commerciale in virtù delle numerose innovazioni tecnologiche da essa introdotte. L’evoluzione verso le famiglie Virtex E , Virtex 2 e Virtex 2 Pro ha riguardato i seguenti aspetti: 1. diminuzione dello spessore dello strato di ossido7 . 2 Programmable Logic Device Complex Programmable Logic Device 4 In System Programmable 5 One Time Programmable 6 Static Random Access Memory 7 dai 0.22-µm della Virtex ai 0.13-µm della Virtex 2 Pro 3 APPENDICE C. LOGICHE PROGRAMMABILI 83 2. aumento del numero di strati di metallo8 . 3. progressiva integrazione ed ottimizzazione dei dispositivi aritmetici alla base delle applicazioni DSP. La Virtex 2 e la Virtex 2 PRO sono inoltre delle platform FPGA le quali consentono di realizzare in un solo dispositivo delle funzionalità complesse che attualmente vengono implementate con più circuiti integrati, a tal fine oltre a essere disponibili in formati molto grandi9 implementano numerose agevolazioni quali dei blocchi di memoria RAM, moltiplicatori precablati ed ottimizzati, possibilità di ospitare dei moduli altrui protetti da licenze quali ad esempio il Power PC IBM e i Multi-Gigabit Transceivers presenti di default nella Virtex 2 PRO. C.3 Architettura Virtex La famiglia Virtex si compone di nove diverse FPGA diverse tra loro per le dimensioni che vanno da 50mila porte logiche sino ad 1milione, quest’ultimo formato è quello utilizzato per l’implementazione del modulatore, nella fattispecie la scheda DINI utilizza 6 FPGA XCV1000BG560-4 dove BG560 indica il formato BallGrid da 560 pin, mentre -4 è lo speed grade il quale viene calcolato statisticamente, migliori prestazioni in termini di velocità di clock si possono ottenere utilizzando versioni con speed grade -5 o -6. Alla base della architettura Virtex ci sono i CLB e gli IOB10 , i primi si occupano di realizzare le funzionalità che il progettista richiede mediante un linguaggio ad alto livello quale il VHDL11 o il VERILOG, i secondi realizzano invece dell’interfacciamento di questa logica con il mondo esterno. Oltre a CLB e IOB ogni FPGA contiene anche un numero elevato di risorse dedicate alle connessioni, esse sono diversificate in termini di estensione e capacità di pilotaggio ed alcune sono espressamente dedicate al routing di segnali particolarmente importanti come ad esempio il clock. C.3.1 CLB L’entità logica programmabile di base della architettura Virtex è la LC12 , essa include: 8 dai 5 strati della Virtex ai 9 della Virtex 2 Pro sino a 10M gate 10 Input Output Block 11 VHSIC Hardware Description Language 12 Logic Cell 9 APPENDICE C. LOGICHE PROGRAMMABILI 84 • un generatore di funzioni13 che può anche essere utilizzato come RAM14 sincrona distribuita nel formato 16 × 1 bit oppure come SRL1615 . • logica dedicata al riporto nelle operazioni aritmetiche, tra cui una porta XOR denominata XORCY che consente l’implementazione di un full-adder ad 1 bit, un multiplexer denominato MUXCY ed una porta AND che ottimizza l’implementazione dei moltiplicatori. Figura C.2: Implementazione di un moltiplicatore • un registro che può essere configurato sia come FFD sensibile al fronte del clock che come latch sensibile al livello. L’unione di due LC viene denominata Slice, come evidenziato in Figura(C.3) il multiplexer F5 combina le uscite delle LUT consentendo di realizzare le seguenti strutture: • generatore di funzioni a 5 ingressi. • multiplexer 4:1. • funzioni specifiche sino ad un massimo di 9 ingressi. inoltre la combinazione delle due LUT può dar luogo ad una RAM sincrona 16 × 2 bit o 32 × 1 bit oppure una RAM sincrona a doppia porta 16 × 1 bit. Il CLB rappresentato in Figura(C.4) contiene 2 Slice e quindi 4 LC, in esso il multiplexer F6 coadiuvato dal multiplexer F5 combina le uscite delle 4 LUT consentendo di implementare: • generatore di funzioni a 6 ingressi. • multiplexer 8:1. • funzioni specifiche sino ad un massimo di 19 ingressi. 13 implementato con una LUT a 4 ingressi Random Access Memory 15 Shift Register Left 16-bit 14 APPENDICE C. LOGICHE PROGRAMMABILI 85 Figura C.3: Slice Virtex Figura C.4: CLB Virtex C.3.2 IOB Come precedentemente affermato gli IOB si occupano dell’interfacciamento della logica implementata nelle CLB con il mondo esterno, ognuno si essi è dotato di 3 registri che possono essere configurati sia come sensibili al livello che al fronte, da progetto si può decidere di includere della logica in questi registri oppure non utilizzarli. Vi sono inoltre dei resistori di pull-up APPENDICE C. LOGICHE PROGRAMMABILI 86 e di pull-down di valore compreso tra 50 e 100Ω. Sono possibili 13 diversi standard di interfacciamento col mondo esterno, nella fattispecie LVTTL, LVCMOS2, PCI 5V, PCI 3, 3V, GTL, GTL+, HSTL I, HSTL III, HSTL IV, SSTL3 I e II, SSTL2 I e II, CTT e AGP dei quali molti richiedono una tensione di riferimento, in particolare gli IOB sono suddivisi in 8 banchi all’interno di ognuno dei quali può essere utilizzata soltanto una tensione di riferimento. C.3.3 Risorse di connessione Le CLB sono connesse tra di loro tramite la GRM16 costituita da matrici di commutazione locate nell’intersezione dei canali di smistamento orizzontali e verticali, ogni CLB appartiene ad un VersaBLOCK il quale realizza il routing locale come illustrato in Figura(C.5). Figura C.5: VersaBlock Ogni GRM è connessa tramite 24 linee ad ognuna delle 4 GRM adiacenti, 96 linee esadecimali connettono inoltre ogni GRM con quella che dista da essa 6 GRM in ogni direzione, lungo i bordi della FPGA c’è poi il VersaRing che rende flessibile il progetto mappato rispetto all’assegnamento dei pin del dispositivo. Si hanno delle linee di routing dedicate per i bus 3-state e per i segnali di riporto verso le CLB verticalmente adiacenti, inoltre ogni CLB è raggiunta da 4 linee di clock globali, che debbono essere pilotate da opportuni buffer, e da 24 linee secondarie dedicate allo smistamento di segnali ad ampio fan-out non necessariamente segnali di clock. C.3.4 Circuiti di utilità All’interno della Virtex oltre alle CLB vi sono dei circuiti che implementano alcune funzionalità molto utilizzate nella progettazione digitale, tra di essi 16 General Routing Matrix APPENDICE C. LOGICHE PROGRAMMABILI 87 Figura C.6: Clock globale vi sono le DLL17 , le BlockRAM e gli SRL16. C.3.4.1 DLL Le DLL ottimizzano lo smistamento del segnale di clock all’interno delle grandi FPGA infatti sulla base della differenza tra il clock in ingresso ed il clock distribuito applicano a quest’ultimo un ritardo opportuno eliminando pertanto lo skew. La struttura può essere utilizzata sia per raddoppiare o quadruplicare la frequenza di clock in ingresso alla FPGA18 che per effettuare su di essa delle divisioni del clock per i valori 1, 5 , 2 , 2, 5 , 3 , 4 , 5 , 8 o 16. Nella Virtex vi sono 4 DLL, una per ogni linea di clock globale e per ogni buffer globale come illustrato in Figura(C.6). C.3.4.2 BlockRAM La BlockRAM è un blocco di memoria SRAM che complementa la RAM distribuita nelle LUT delle CLB, nella Virtex ogni blocco è alto 4 CLB, ne consegue che sulla XCV1000 ve ne sono 16 ai bordi di ognuno dei due lati verticali. Ogni blocco dispone di 4096 celle di memoria alle quali si può accedere in configurazione singola porta o doppia porta19 . Ogni BlockRAM può essere anche configurata in sola lettura, per la sua inizializzazione si possono utilizzare i Core opportuni oppure istanziare la primitiva desiderata ed assegnare dei valori alle 16 stringhe di inizializzazione ciascuna delle quali è composta da 64 cifre esadecimali e pertanto copre 256 bit. 17 Delay Locked Loop la frequenza di clock in ingresso deve essere maggiore di 25MHz 19 le due porte hanno in comune le stesse 4096 celle di memoria 18 APPENDICE C. LOGICHE PROGRAMMABILI (a) Primitive BlockRAM 88 (b) Stringhe d’inizializzazione Figura C.7: Configurazione delle BlockRAM C.3.4.3 SRL16 La LUT presente in ogni LC viene utilizzata come multiplexer 16:1 avente 4 ingressi che seleziona come uscita seriale di un registro a scorrimento a 16 bit. Una tale struttura consente di creare delle reti di ritardo molto compatte particolarmente adatte all’implementazione della tecnica del pipelining. Appendice D Flusso di progettazione D.1 Sommario In questa appendice viene descritto tutto il processo che consente di passare da una descrizione matematica del sistema che si intende implementare su FPGA sino alla verifica del suo effettivo funzionamento passando per la verifica funzionale del VHDL. D.2 Modello Matematico La stesura di un modello matematico è di aiuto sia nella verifica della correttezza di una idea che nella comprensione stessa di determinati aspetti di una tematica che possono inizialmente rimanere poco chiari, soprattutto i numerosi esempi del Toolbox per le comunicazioni di Matlab oltre alle funzioni ad alto livello consentono un approccio semplice a tematiche quali modulazioni e demodulazioni, progettazione di filtri, codifiche e decodifiche. Sostanziale è anche l’utilità di Matlab laddove si desideri spostare tutta la complessità del progetto in migliaia di cifre contenute in una RAM, l’allestimento di script parametrici consente infatti di rispondere con rapidità a modifiche delle specifiche di progetto. Si può passare alla fase successiva del progetto solo dopo aver realizzato delle simulazioni su dei modelli matematici il più possibile vicini alla reale architettura che si intende implementare, in tal modo si possono ad esempio dimensionare opportunamente il numero di bit da assegnare a determinati segnali influenzando cosı̀ la stesura del modello VHDL. D.3 Modello VHDL Anche nella realizzazione del modello VHDL occorre tener conto del passo successivo, l’implementazione, questo in quanto il VHDL è anche un linguaggio descrittivo pertanto alcuni modelli che potrebbero soddisfare 89 APPENDICE D. FLUSSO DI PROGETTAZIONE 90 una verifica funzionale possono risultare non sintetizzabili, ciò si verifica ad esempio se all’interno di un processo si richiede che si operi su entrambe i fronti del clock. La verifica funzionale avviene applicando degli stimoli al modello e verificando le risposte o in termini di forme d’onda digitali oppure nel dominio del tempo o della frequenza previa creazione di un file e sua esportazione in Matlab dove si possono utilizzare delle varianti degli script che compongono il modello matematico. Quale software per la verifica e la stesura del modello VHDL si è utilizzato ActiveHDL, esso realizza anche un ambiente integrato verso diversi tipi di sintetizzatori VHDL e software per l’implementazione effettiva su FPGA consentendo di uno stesso progetto la verifica funzionale, RTL1 e back-annotata. D.4 Sintesi del progetto La sintesi consente di passare dalla descrizione VHDL del progetto alla descrizione RTL ossia la sua espressione in termini di registri e logica combinatoria, in questa fase è importante l’utilizzo di un software quale Synplify che illustra graficamente la corrispondenza tra le due descrizioni ed effettua anche una verifica delle prestazioni in risposta a determinati vincoli sul timing di alcuni segnali di rilievo tra cui certamente il clock. La Xilinx distribuisce con i suoi prodotti anche XST un sintetizzatore meno grafico rispetto a Synplify ma con prestazioni abbastanza simili, esso ha il vantaggio di riconoscere automaticamente le stringhe di inizializzazione delle BlockRAM2 consentendo pertanto un più veloce passaggio dal VHDL per la verifica al VHDL per la sintesi. In questa fase oltre ai vincoli temporali al progetto è bene inserire anche i vincoli sui pin che si desiderano utilizzare, al fine di ottimizzare il timing ad esempio nel progetto ThinModulator son stati prescelti tutti pin che si trovano dal lato della FPGA dove sono dislocate le BlockRAM utilizzate, con questo semplice accorgimento si risparmia una inutile fatica al software d’implementazione, occorre però tener presente che non tutti i pin della FPGA sono disponibili sugli slot che sulla scheda DINI sono adiacenti ad essa. D.5 Mappatura Impostando in Synplify anche il tipo di FPGA sul quale si desidera realizzare il progetto è possibile ottenere la vista tecnologica che mostra come il progetto RTL e quindi il progetto VHDL viene effettivamente implementato nel dispositivo, in sostanza in questa fase vengono stabilite quali tipologie di risorse verranno utilizzate. 1 2 Register Transfer Logic Appendice(C.3.4.2) APPENDICE D. FLUSSO DI PROGETTAZIONE 91 D.6 Piazzamento delle risorse Una volta individuate la tipologia di risorse da utilizzare rimane da effettuare il piazzamento, ossia la selezione nominale delle risorse da utilizzare, questa fase è in genere abbastanza veloce ed il progettista la può influenzare mediante il FloorPlanner con il quale si specificano quali siti all’interno della FPGA debbono ospitare una determinata funzione, in sostanza si impongono dei vincoli fisici che possono essere memorizzati in un file UCF3 o PCF4 . Il Floorplanner può risultare utile ad esempio per impostare le BlockRAM da utilizzare per un dato segnale in modo da rendere il più breve possibile il percorso dalla sua uscita sino al registro ed al pin d’uscita. D.7 Connessione delle risorse Questa fase è sicuramente la più lunga e complessa, vengono selezionate le risorse di connessione5 che consentono di soddisfare al meglio i vincoli temporali impostati nel file UCF garantendo comunque i vincoli fisici impostati nel file UCF o PCF. Anche per questa fase Xilinx mette a disposizione del progettista un Tool quale FPGA Editor che gli consente di imporre determinate connessioni o modificare le connessioni effettuate dal tool automatico. D.8 Simulazione back-annotata Dopo aver verificato mediante lo STA6 che i vincoli sul timing sono soddisfatti si può generare il modello di simulazione del progetto ottenuto dopo il PAR7 , esso è costituito da due file uno con estensione .sdk e l’altro .vhd, quest’ultimo realizza l’architettura structure del modello VHDL, creando per essa un TestBench si debbono ottenere a parità di stimoli le stesse forme d’onda che si ottengono dal modello funzionale. D.9 Programmazione della FPGA Se anche la simulazione back-annotata ha avuto esito positivo si passa alla creazione del file .bit e successivamente del file .hex da inserire nella PROM che ad ogni riaccensione si occupa di riprogrammare le FPGA presenti sulla scheda DINI. E’ necessario impostare per il file il formato HEX e non selezionare l’opzione swap bits. Il Data Stream deve contenere nell’ordine il 3 User Constrain File Physical Constrain File 5 Appendice(C.3.3) 6 Static Timing Analyzer 7 Place And Route 4 APPENDICE D. FLUSSO DI PROGETTAZIONE 92 file fpga f.bit per la gestione del bus PCI, il file .bit relativo al progetto che andrà ad occupare la FPGA A e 4 file blank 1.bit che riempiranno le altre FPGA. Salvando viene automaticamente generato il file .hex, per trasferirlo nella Prom occorre seguire la seguente procedura sul computer nel quale è stata installata la scheda DINI: 1. inserire il Jumper J2 sulla scheda e premere il tasto giallo. 2. riavviare il computer. 3. spostare il file .hex generato dal prom formatter nella directory F:/SchedaDini/AETEST/aetest_nt . 4. far partire il programma AETEST.EXE ed eseguire i diversi passi di programma: • selezionare Open Device. • selezionare 3) Flash menu. • selezionare 6) Download Hex File. • scrivere il nome del file .hex e premere invio. • premere due volte invio quindi uscire. 5. togliere il Jumper J2 e premere il tasto giallo. 6. controllare che si spengano i led rossi superiori. D.10 Verifica sperimentale Per la verifica sperimentale vengono utilizzati un pattern-generator che viene caricato con dei vettori di test da applicare alla FPGA in maniera ripetitiva o singola, lo script Matlab CreaSequenzaPatternGenerator.m (Listato E.2.2) consente di creare in maniera automatica il file di testo con il quale caricare il pattern-generator, in esso si può anche impostare se il clock di emissione dei dati debba esser prodotto autonomamente dal patterngenerator oppure sincronizzato ad un clock esterno come è avvenuto per le prove del modulatore. Le uscite del modulatore vengono invece inviate all’analizzatore di stati logici, si effettua una singola acquisizione di 64mila campioni in accordo ai 6mila applicati ed il file ottenuto viene esportato verso Matlab dove un’analisi dello spettro consente di confrontare il risultato teorico col risultato sperimentale. Appendice E Listati Matlab E.1 NCO Listato E.1.1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 % Pulizia ambiente Matlab clear all ; close all ; clc ; % Imposto la frequenza di clock e la frequenza richiesta in uscita dall ’ NCO [f_out , f_clk] = imposta_frequenze_Q ; % Imposto le caratteristiche dell ’ NCO [n_bit_acc, n_bit_cordic, n_bit_dac, n_it_cordic, n_periods] = imposta_NCO_Q ; % creo l ’ accumulatore il quale contiene i soli valori delle fasi che elaborati % alla frequenza di clock generano in uscita la frequenza desiderata super_acc = crea_super_accumulatore_Q(f_out , f_clk , n_bit_acc, n_periods) ; % le fasi vengono troncate da una rappresentazione con n_bit_acc bits ad una % rappresentazione con n_bit_cordic bits super_acc_T = tronca_Q(super_acc , n_bit_cordic) ; % vengono generati tramite l ’ algoritmo CORDIC i valori del seno e del coseno % corrispondenti agli angoli presenti in super_acc [coseno , seno] = crea_coseno_e_seno_Q(super_acc_T, n_bit_cordic, ... n_bit_dac, n_it_cordic) ; % grafico un periodo del seno e del coseno calcolati con il CORDIC figure ; subplot(2,1,1); stairs(super_acc , coseno) ; xlim( [ 0 , 6.2832 ] ); ylim( [ -1.01 , +1.01 ] ); subplot(2,1,2); stairs(super_acc , seno ); xlim( [ 0 , 6.2832 ] ); ylim( [ -1.01 , +1.01 ] ); % Rappresentazione nel dominio della frequenza del coseno generato dal CORDIC visualizza_spettro_e_sfdr_p( coseno , f_clk ); % salva il coseno nel file coseno . dat fid = fopen(’coseno_Q.dat’,’w’) ; fprintf(fid,’%20.19f\n’, coseno) ; fclose(fid) ; % salva il seno nel file seno . dat fid = fopen(’seno_Q.dat’,’w’) ; fprintf(fid,’%20.19f\n’, seno) ; fclose(fid) ; Listato E.1.2: 1 2 3 4 5 6 7 8 9 NCO Q.m % DESCRIPTION : Implementa un NCO quantizzato , ne grafica i risultati sia nel % dominio del tempo che della frequenza e valuta l ’ SFDR Imposta frequenze Q.m % DESCRIPTION : consente d ’ impostare frequenza di clock e d ’ uscita dall ’ NCO function [f_out,f_clk]=imposta_frequenze_Q prompt = {’Frequenza desiderata in uscita (Hz) :’, ’Frequenza di clock (Hz) :’}; title = ’Caratteristiche NCO’; lines = 1; def = {’41.25e6’,’165e6’}; 93 APPENDICE E. LISTATI MATLAB 94 10 11 12 answer = inputdlg(prompt,title,lines,def) ; f_out = str2double(answer(1)); f_clk = str2double(answer(2)); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 % DESCRIPTION : consente d ’ impostare le dimensioni dei bus dell ’ accumulatore , % del Cordic e del DAC Listato E.1.3: function [n_bit_acc,n_bit_cordic,n_bit_dac,n_it_cordic,n_periods]=imposta_NCO_Q = {’N◦◦ di bit accumulatore di fase : ’, ’N◦ di bit per la fase in ingresso al Cordic : ’, ’N◦ di bit per seno e coseno prodotti dal Cordic : ’, ’N di iterazioni del Cordic : ’, ’N◦ di periodi della funzione generata : ’}; title = ’Caratteristiche NCO’; lines = 1; def = {’32’,’13’,’12’,’13’,’3000’}; answer = inputdlg(prompt,title,lines,def) ; ◦ % n di bit in ingresso all ’ accumulatore di fase n_bit_acc = str2double(answer(1)); % n◦ di bit per la fase in ingresso al Cordic n_bit_cordic = str2double(answer(2)); % n◦ di bit per seno e coseno prodotti dal Cordic n_bit_dac = str2double(answer(3)); % n◦ di iterazioni del Cordic n_it_cordic = str2double(answer(4)); % n◦ di periodi generati n_periods = str2double(answer(5)); prompt Listato E.1.4: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 Imposta NCO Q.m Crea super accumulatore Q.m % DESCRIPTION : implementa un accumulatore contenente le fasi che lette % alla velocità del clock producono in uscita dal Cordic % la frequenza desiderata , può memorizzare più periodi function super_acc = crea_super_accumulatore_Q(f_out,f_clk,n_bit_acc,n_periods) % caratteristiche dell ’ accumulatore di fase % massimo numero di fasi memorizzabili nell ’ accumulatore range_acc = 2^n_bit_acc ; % minima frequenza generabile f_res = f_clk / range_acc ; % minima fase memorizzabile phi_res = 2*pi / range_acc ; % determina l ’ incremento di fase necessario ad ottenere f_out f_word = f_out / f_res ; % incremento di fase che alla frequenza di clock produce in uscita la % frequenza desiderata delta_phi = f_word * phi_res ; % dimensioni dell ’ accumulatore contenente 1 periodo con le sole fasi che danno % luogo alla corretta frequenza generata dim_acc = round(range_acc/f_word) ; % massimo numero di fasi memorizzabili nel superaccumulatore dim_super_acc = dim_acc * n_periods ; % creazione del superaccumulatore super_acc = 0 : 1 : dim_super_acc ; super_acc = delta_phi * super_acc ; Listato E.1.5: 1 2 3 4 5 6 7 8 Tronca Q.m % DESCRIPTION : le fasi vengono troncate da una rappresentazione con % n_bit_acc bits ad una rappresentazione con n_bit_cordic bits function super_acc_T = tronca_Q(super_acc , n_bit_cordic) super_acc = rem(super_acc , 2*pi) ; new_risoluzione_fase = 2*pi / 2^n_bit_cordic ; super_acc_T = [fix(super_acc / new_risoluzione_fase)] * new_risoluzione_fase ; APPENDICE E. LISTATI MATLAB Listato E.1.6: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Crea coseno e seno Q.m % DESCRIPTION : imposta le caratteristiche del CORDIC e calcola seno e % coseno per tutte le fasi presenti nel vettore super_acc function [coseno , seno] = crea_coseno_e_seno_Q(super_acc_T, n_bit_cordic,... n_bit_dac, n_it) % ottengo le dimensioni del super_accumulatore dim_super_acc_T = size(super_acc_T , 2) ; % queste inizializzazioni velocizzano l ’ esecuzione del ciclo CORDIC coseno = zeros(1,dim_super_acc_T) ; seno = zeros(1,dim_super_acc_T) ; new_capacity_fase = 2^(n_bit_cordic - 1) ; new_capacity_ampiezza = 2^(n_bit_dac - 1) ; for j = 1 : dim_super_acc_T [coseno(j),seno(j)] = forward_cordic_Q(n_it,super_acc_T(j), ... new_capacity_fase, new_capacity_ampiezza); end ; Listato E.1.7: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 95 Forward cordic Q.m % DESCRIPTION : esegue N iterazioni dell ’ algoritmo Cordic per calcolare il % seno ed il coseno dell ’ angolo Theta che riceve in ingresso , % si parte dal valore 0.607252936517011 per il coseno in modo % da evitare la moltiplicazione finale ed evitare l ’ utilizzo % di un bit per il solo valore 1 del coseno che del seno . % m =1 individua le coordinate circolari mentre Nit è il n◦ di iterazioni function [coseno, seno] = forward_cordic(N_it, Theta, new_capacity_fase,... new_capacity_ampiezza); % per semplificare il CORDIC riportiamo l ’ angolo nel primo quadrante , % l ’ angolo effettivo potrà poi essere ricavato mediante multcos e multsin multcos = 1; multsin = 1; if ( Theta > pi/2 & Theta < pi) % l ’ angolo viene riportato dal 2 ◦ quadrante al 1 ◦ Theta = pi/2 - rem(Theta,pi/2); multcos = -1; end if (Theta >= pi & Theta < (3/2)*pi) % l ’ angolo viene riportato dal 3 ◦ quadrante al 1 ◦ Theta = rem(Theta,pi/2); multcos = -1; multsin = -1; end if (Theta >= (3/2)*pi & Theta < 2*pi) % l ’ angolo viene riportato dal 4 ◦ quadrante al 1 ◦ Theta = pi/2 - rem(Theta,pi/2); multsin = -1; end % x ed y sono vettori aventi lunghezza pari al n◦ di iterazioni , contengono % il coseno ed il seno dell ’ angolo inizialmente è memorizzato in z_attuale x_attuale = [floor(0.607252936517011* new_capacity_ampiezza)] / ... new_capacity_ampiezza ; y_attuale = 0 ; z_attuale = Theta ; % calcola il seno ed il coseno mediante N_it iterazioni dell ’ algoritmo CORDIC for i = 0:(N_it-1) % calcola il fattore moltiplicativo mu per la p_esima iterazione if z_attuale <= 0 mu = -1; else mu = 1; end S = 2^(-i) ; % Standard Cordic iteration , m = 1 per le coordinate circolari x_succ = x_attuale - [floor((mu * S * y_attuale) * ... new_capacity_ampiezza)] / new_capacity_ampiezza; y_succ = y_attuale + [floor((mu * S * x_attuale) * ... new_capacity_ampiezza)] / new_capacity_ampiezza; z_succ = z_attuale - [floor((mu * atan( S ))* ... new_capacity_fase)] / new_capacity_fase; x_attuale = x_succ ; y_attuale = y_succ ; z_attuale = z_succ ; end % Vengono restituiti il coseno ed il seno opportunamente scalati e riportati % nelal giusto quadrante % new_capacity_ampiezza = 2^(12 - 1) ; coseno = [floor((multcos * x_attuale)*new_capacity_ampiezza)]/... new_capacity_ampiezza; seno = [floor((multsin * y_attuale)*new_capacity_ampiezza)]/... new_capacity_ampiezza; APPENDICE E. LISTATI MATLAB Listato E.1.8: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 % Pulizia ambiente Matlab clear all ; close all ; clc ; disp(’Valore degli angoli di rotazione a(n)’) ; % Calcolo dei valori degli a ( n ) for i = 0:1:12 a(i+1) = atan(2^(-i)); end ; i = [1:1:13] ; valore = [ i’ , ((a)* 180 / pi)’ ] a_tot = sum((a)* 180 / pi) % converto ora gli a ( i ) in complemento a due su 1 bit per il segno e dodici % per la parte intera n_bit = 13 ; a_bin = dec2bin( (2^n_bit .* a(i) )/ (2*pi) ) disp(’Valore dei fattori di scaling k(n)’) ; % Calcolo il valore degli scalamenti da effettuare ad ogni rotazione k = sqrt(2) ; valore = [ 0 , k] for i = 1:1:13 k = k*sqrt(1 + 2^(-2*i)) ; valore = [i , k] end ; Listato E.1.9: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Calcola rotazioni Cordic.m % DESCRIPTION : Per ogni iterazione del Cordic calcola l ’ angolo di rotazione % e il fattore di scaling Visualizza spettro e SFDR p.m % DESCRIPTION : plotta la stima dello spettro e l ’ SFDR function visualizza_spettro_e_SFDR_p( segnale , f_clk ); % ottengo le dimensioni del vettore segnale dim_segnale = ( size(segnale , 2) )- 1 ; % viene calcolata e plottata la densità spettrale di potenza [Pxx , f] = pmtm(segnale , 8 , 4096 , f_clk) ; Pxx_dB = 10*log10(Pxx) ; figure; plot(f , Pxx_dB - max(Pxx_dB) ); grid ; xlim([0 f_clk/2]) ; title(’Power spectral density MultiTaper’); xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); % viene calcolato e visualizzato il valore dello SFDR valore_sfdr = calcola_sfdr(Pxx) ; text(1e7,-50,[’SFDR = ’,num2str(valore_sfdr)],’FontSize’,13); Listato E.1.10: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Calcola SFDR.m % DESCRIPTION : calcola l ’ SFDR del vettore passato in ingresso function [valore_sfdr] = calcola_sfdr(Pxx) % diff prende il vettore Pxx e costruisce un vettore i cui elementi sono % la differenza tra elementi adiacenti del vettore Pxx , si ottiene quindi % un vettore più corto di uno . der = diff(Pxx); % dal vettore precedente ottengo il vettore dei segni corrispondenti signs=sign(der); % viene inizializzato il ciclo che individua i massimi della PSD signold = 0 ; % contiene il valore del segno precedente signnew = 0 ; % contiene il valore del segno attuale p = 1 ; % puntatore per riempire il vettore dei massimi % Siamo in presenza di un massimo se il segno della derivata nel punto % precedente è negativo mentre il segno della derivata nel punto attuale % è positivo , viene scandito il vettore dei segni alla ricerca di questa % condizione e solo se verificata il massimo viene memorizzato for k=1:(length(signs)-1) signold = signs(k) ; 96 APPENDICE E. LISTATI MATLAB 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 signew = signs(k+1) ; % individua la presenza di un massimo ed eventualmente lo memorizza if (signold == 1 & signew == -1) vettore_massimi(p) = Pxx(k+1) ; p=p+1 ; end end % ottengo posizione e valore del massimo assoluto [max_assoluto , pos] = max(vettore_massimi); % annullo il valore del massimo assoluto in modo da poter ricercare il % primo massimo relativo vettore_massimi(1 , pos) = 0; % ottengo il valore del 1 ◦ massimo relativo primo_max_relativo = max(vettore_massimi) ; % restituisco l ’ SFDR valore_sfdr = 10.*log10(max_assoluto)-10.*log10(primo_max_relativo); Listato E.1.11: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 % Pulizia ambiente Matlab clear all ; close all ; clc ; f_clk = 165e6 ; f_out = 41.25e6 ; n_bit_acc = 32 ; n_bit_cordic = 13 ; fw = round( (f_out * 2^n_bit_acc) / f_clk ) fw_hex = dec2hex(fw) fw_bin = dec2bin(fw) Listato E.1.12: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 Calcola incremento fase NCO.m % DESCRIPTION : calcola la Frequency Word dell ’ NCO in 3 formati diversi Visualizza spettro NCO VHDL.m % DESCRIPTION : visualizza lo spettro del seno prodotto dall ’ NCO VHDL % Pulizia ambiente Matlab clear all ; close all ; clc ; % Imposto la frequenza di clock del sistema e quella prodotta dall ’ NCO f_out = 40e6 ; f_clk = 165e6 ; % carica la sequenza filtrata dal file data_out_SRRC_I . dat fid = fopen(’sine_to_matlab.dat’ , ’r’) ; seno_vhdl_dec = fscanf(fid,’%f’) ; fclose(fid) ; n_bit_dopo_virgola = 11 ; seno_vhdl = seno_vhdl_dec .* 2^(- n_bit_dopo_virgola) ; % Rappresentazione nel dominio della frequenza del coseno generato dall ’ NCO visualizza_spettro_e_sfdr_p( seno_vhdl , f_clk ); E.2 Creazione vettori di test Listato E.2.1: 1 2 3 4 5 6 7 8 9 10 11 CreaVettoriTest.m % DESCRIPTION : Crea dei vettori NRZ e RZ da applicare al VHDL % Pulizia ambiente Matlab clear all ; close all ; clc ; % vengono impostate le caratteristiche del polifase prompt = {’N◦ bit Reset attivo :’, ’Interpolazione :’, ’Nome del file sorgente :’ }; title = ’Impostazione delle caratteristiche dei segnali di test’; 97 APPENDICE E. LISTATI MATLAB 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 lines = 1; def = {’5’ , ’4’, ’bit_tx.dat’ }; answer = inputdlg(prompt,title,lines,def) ; n_bit_reset_alto = str2double(answer(1)); interp_rate = str2double(answer(2)); nome_file_sorgente = char(answer(3)); % legge da un file i bit randomici da trasmettere fid = fopen( nome_file_sorgente , ’r’) ; bit_tx = fscanf(fid,’%f’) ; fclose(fid) ; % determinazione del numero di bit di test da applicare n_bits2tx = length(bit_tx) ; % creazione del segnale di reset n_bit_dummy = 4*n_bit_reset_alto ; reset = zeros(n_bits2tx/2, 1) ; % vengono aggiunti 10 bit 1 all ’ inizio del segnale di reset più altri 10 reset =[ones(1,n_bit_reset_alto) zeros(1,n_bit_dummy/4) reset’]’; % salva su file il vettore di test RZ per la componente Q fid = fopen(’reset.dat’,’w’) ; fprintf(fid,’%d\n’, reset) ; fclose(fid) ; % vengono aggiunti dei bit di inizializzazione alla sequenza da trasmettere bit_tx =[zeros(1,n_bit_dummy) bit_tx’]’; % viene creato il vettore dei bit pari e quello dei bit dispari bit_I = bit_tx(1 : 2 : n_bits2tx + n_bit_dummy) ; bit_Q = bit_tx(2 : 2 : n_bits2tx + n_bit_dummy) ; % salva su file il vettore di test RZ per la componente I fid = fopen(’data_in_SRRCxN_tx_I_rz.dat’,’w’) ; fprintf(fid,’%d\n’, bit_I) ; fclose(fid) ; % salva su file il vettore di test RZ per la componente Q fid = fopen(’data_in_SRRCxN_tx_Q_rz.dat’,’w’) ; fprintf(fid,’%d\n’, bit_Q) ; fclose(fid) ; % i bit vengono opportunamente mappati data_in_SRRC_tx_I = -2*bit_I + 1 ; data_in_SRRC_tx_Q = -2*bit_Q + 1 ; % salva su file il vettore di test RZ per la componente I fid = fopen(’data_in_SRRCxN_tx_I_nrz.dat’,’w’) ; fprintf(fid,’%+d\n’, data_in_SRRC_tx_I) ; fclose(fid) ; % salva su file il vettore di test RZ per la componente Q fid = fopen(’data_in_SRRCxN_tx_Q_nrz.dat’,’w’) ; fprintf(fid,’%+d\n’, data_in_SRRC_tx_Q) ; fclose(fid) ; % si tiene conto del fatto che rate_sel è codificato su due bit switch interp_rate case 3 rate_sel_coded = 0 ; case 4 rate_sel_coded = 1 ; case 6 rate_sel_coded = 2 ; otherwise error(’Impossible !!! ’) end % creazione del segnale rate_sel per l ’ impostazione del data_rate rate_sel = rate_sel_coded * ones(length(data_in_SRRC_tx_Q) , 1) ; fid = fopen(strcat(’rate_sel_x’, num2str(interp_rate), ’.dat’),’w’); fprintf(fid,’%+d\n’, rate_sel) ; fclose(fid) ; disp(’Vettori di test generati correttamente.’) ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 % DESCRIPTION : Ha in ingresso i file con le sequenze da applicare ai % rispettivi canali del pattern generator Listato E.2.2: CreaSequenzaPatternGenerator.m % Pulizia ambiente Matlab clear all ; close all ; clc ; fclose(’all’); % vengono impostate le caratteristiche del polifase prompt = {’Tipo di clock (int , ext) :’, ’N◦◦ di segnali :’, ’N di bit nella sequenza d’’inizializzazione :’, ’Nome file di test da produrre :’ }; title = ’Caratteristiche dei vettori di test da applicare all’’FPGA’; lines = 1; def = {’ext’ , ’3’, ’10’ , ’I_testVector_x3.dat’}; answer = inputdlg(prompt,title,lines,def) ; tipo_clock = char(answer(1)); n_segnali = str2double(answer(2)); n_bit_start = str2double(answer(3)); nome_file_test = char(answer(4)); 98 APPENDICE E. LISTATI MATLAB 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 99 switch lower(tipo_clock) case ’int’, % viene richiesto di impostare il valore del clock interno answer = inputdlg( {’frequenza del clock interno :’}, ... ’Impostazione del clock interno del Pattern Generator’,1,{’40’}) ; f_clk = str2double(answer(1))*10^6; clk_string = [’FORMAT:CLOCK INTERNAL,’ num2str((1/f_clk)*10^9)’E-9’]; case ’ext’, % viene richiesto di impostare il range del clock esterno clk_ext = questdlg(’Selezionare range clock al Pattern Generator:’,... ’Selezione clock esterno’, ... ’f_clk_ext < 50MHz’,’50MHz < f_clk_ext < 100MHz’, ... ’f_clk_ext > 100MHz’,’f_clk_ext < 50MHz’); % viene ricavata la stringa da settare per il range esterno selezionato switch clk_ext case ’f_clk_ext < 50MHz’, ... clk_string = ’FORMAT:CLOCK EXTERNAL, LEFifty’; case ’50MHz < f_clk_ext < 100MHz’, ... clk_string = ’FORMAT:CLOCK EXTERNAL, GTFifty’; case ’f_clk_ext < 50MHz’, ... clk_string = ’FORMAT:CLOCK EXTERNAL, GTONe’; end end % si itera per acquisire i valori da assegnare ai diversi canali for s = 1 : 1 : n_segnali prompt = {’Nome del segnale :’, ’N◦ di bit associati (multiplo di 4) :’, ’Nome file sorgente :’ }; title = [’Caratteristiche del segnale ’ num2str(s) ]; lines = 1; def = {’data_in_SRRCxN_tx_I’,’4’,’data_in_SRRCxN_tx_I_rz.dat’}; answer = inputdlg(prompt,title,lines,def) ; label(s) = answer(1); n_bit_label(s) = str2double(answer(2)); eing_file(s) = answer(3); end % vengono caricati da file i segnali di test da applicare for s = 1 : n_segnali fid_in(s) = fopen( char(eing_file(s)) , ’r’) ; segnale(:,s) = fscanf(fid_in(s),’%d’) ; end % viene calcolata la lunghezza della stringa dummy costituita da tutti 0 n_cifreHEX_dummy = num2str( (40 - sum(n_bit_label) )/ 4 ); % scrivo su file le stringhe esadecimali calcolate fid_out = fopen([tipo_clock ’Clk_’ nome_file_test ],’w’); % aggiungo al file l ’ intestazione fprintf(fid_out,’%s\n’, ’ASCII 000000’) ; fprintf(fid_out,’%s\n’, ’ASCDOWN’) ; fprintf(fid_out,’%s\n’, ’FORMAT:MODE FULL’) ; fprintf(fid_out,’%s\n’ , clk_string ); % vengono aggiunte le label fprintf(fid_out,’%s’, ’LABEL dummy, ’) ; fprintf(fid_out,’%s\n’, num2str(40 - sum(n_bit_label) )); for s = 1 : n_segnali fprintf(fid_out,’%s’, ’LABEL ’) ; fprintf(fid_out,’%s’, char(label(s)) ); fprintf(fid_out,’%s’, ’, ’) ; fprintf(fid_out,’%s\n’, num2str( n_bit_label(s) )); end fprintf(fid_out,’%s\n’, ’VECTOR’) ; % si itera su tutta la lunghezza della sequenza d ’ inizializzazione for row = 1 : 1 : n_bit_start % viene stampata una riga del vettore di test finale fprintf(fid_out,strcat(’%0’, n_cifreHEX_dummy ,’d’), 0 ); for s = 1 : n_segnali fprintf(fid_out,’%s’, ’ ’) ; fprintf(fid_out, strcat(’%0’, num2str(n_bit_label(s) / 4 ), ’X’), ... segnale(row,s) ); end fprintf(fid_out,’%s\n’, ’’) ; end fprintf(fid_out,’%s\n’, ’*M’) ; % si itera su tutta la lunghezza dei vettori di test d ’ ingresso for row = n_bit_start + 1 : 1 : length(segnale) % viene stampata una riga del vettore di test finale fprintf(fid_out,strcat(’%0’, n_cifreHEX_dummy ,’d’), 0 ); for s = 1 : n_segnali fprintf(fid_out,’%s’, ’ ’) ; fprintf(fid_out, strcat(’%0’, num2str(n_bit_label(s) / 4 ), ’X’), ... segnale(row,s) ); end fprintf(fid_out,’%s\n’, ’’) ; end % chiusura dei file contenenti i segnali di test da applicare for s = 1 : n_segnali fclose(fid_in(s)); end % chiusura del file di test da applicare alla FPGA fclose(fid_out); % segnalazione di fine creazione del file sound(wavread(’drumroll.wav’)); APPENDICE E. LISTATI MATLAB 113 100 disp(’Vettore di test generato correttamente.’) E.3 Polifase Creazione coefficienti Listato E.3.1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 CreaCoeffsFreqSamplScaled.m % DESCRIPTION : calcola e confronta l ’ SRRC Matlab col FreqSampl e % condizionatamente scala i coefficienti % pulizia ambiente Matlab clear all ; close all ; clc ; % vengono impostate le caratteristiche del polifase prompt = {’Frequenza di clock :’, ’Data Rate :’, ’Roll Off :’, ’N◦◦ coefficienti del FIR desiderati :’, ’N di bit dopo la virgola :’, ’Scaling :’ }; title = ’Caratteristiche del polifase’; def = {’165’, ’110’, ’0.35’, ’19’, ’11’, ’Si’}; answer = inputdlg(prompt, title, 1, def) ; f_clk = str2double(answer(1))*10^6; symbol_rate = str2double(answer(2))*10^6 / 2; roll_off = str2double(answer(3)); n_coeffs = str2double(answer(4)); n_bit_dopo_virgola = str2double(answer(5)); Scaling = answer(6); % calcolo della interpolazione richiesta SpS = f_clk/symbol_rate ; % carica da file la sequenza dei dati da filtrare fid = fopen(’data_in_SRRCxN_tx_I_nrz.dat’ , ’r’) ; data_in_SRRCxN_tx_I = fscanf(fid,’%f’) ; fclose(fid) ; % ***************************** MATLAB SRRC ********************************** delay = 3 ; input_rate_SRRC = symbol_rate ; output_rate_SRRC = f_clk ; num_fir = rcosine(input_rate_SRRC,output_rate_SRRC,’fir/sqrt’,roll_off,delay); % viene filtrata la sequenza d ’ ingresso data_out_SRRC_matlab = applica_polifase(data_in_SRRCxN_tx_I, SpS , num_fir); % Power Spectral Density plotting [Pyy_matlab , f_out] = pwelch(data_out_SRRC_matlab, [] , [] , ’onesided’, ... length(data_out_SRRC_matlab) - 1 , f_clk) ; Pyy_matlab_dB = 10*log10(Pyy_matlab) ; figure ; plot(f_out , Pyy_matlab_dB - max(Pyy_matlab_dB) ); grid ; xlim([0 f_clk/2]) ; ylim([-70 0]); legend([’SRRCx’ num2str(SpS) ’ Matlab ’ [num2str(symbol_rate/10^6)] ’ MSpS’]); xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); figure ; impz(num_fir) ; % ***************************** FreqSampl SRRC **************************** Ts = 1/symbol_rate ; % tempo di simbolo % risposta in frequenza nell ’ origine del filtro a radice di coseno rialzato H(1) = sqrt(RaisedCosineResponse(0,roll_off,Ts)); % per la simmetria occorrono solo N /2 campioni della risposta in frequenza for k = 1 : (n_coeffs - 1)/2, H(k + 1) = sqrt(RaisedCosineResponse(k*f_clk/n_coeffs, roll_off, Ts)); H(n_coeffs - k + 1) = H(k + 1); end % mediante la trasformata di Fourier discreta inversa IDFT viene calcolata la % risposta all ’ impulso e traslata per garantire la causalità for n = (-(n_coeffs - 1)/2) : ((n_coeffs - 1)/2) num_fir_FreqSampl(n + ((n_coeffs - 1)/2) +1) = H(0 + 1); for m = 1 : (n_coeffs - 1)/2, num_fir_FreqSampl(n + ((n_coeffs - 1)/2) +1) = ... num_fir_FreqSampl(n + ((n_coeffs-1)/2)+1) + ... 2*H(m + 1)*cos(2*pi*m*n / n_coeffs); end end % calcolo il fattore di scaling e l ’ aggiunta al nome del file dei coefficienti if strcmp(Scaling, ’No’) % i coefficienti non scalati vengono salvati nel file fid = fopen(strcat(’SRRCx’ , num2str(SpS) , ’_FreqSampl.dat’) , ’w’); fprintf(fid,’%20.19f\n’, num_fir_FreqSampl) ; APPENDICE E. LISTATI MATLAB 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 fclose(fid) ; % la sequenza dati è applicata all ’ SRRC progettato campionando in frequenza data_out_SRRC_FreqSampl = ... applica_polifase(data_in_SRRCxN_tx_I, SpS , num_fir_FreqSampl); % Power Spectral Density plotting [Pyy_FreqSampl , f_out] = pwelch(data_out_SRRC_FreqSampl, [] , [] , ... ’onesided’, length(data_out_SRRC_FreqSampl) - 1 , f_clk) ; Pyy_FreqSampl_dB = 10*log10(Pyy_FreqSampl) ; figure ; plot(f_out , Pyy_FreqSampl_dB - max(Pyy_FreqSampl_dB) ); grid ; xlim([0 f_clk/2]) ; ylim([-70 0]); legend([’SRRCx’ num2str(SpS) ’ FreqSampl ’ ... [num2str(symbol_rate/10^6)] ’MSpS’]); xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); figure ; impz(num_fir_FreqSampl) ; else % n◦ di FIR che effettivamente costituiscono il polifase n_fir = SpS ; % lunghezza massima dei FIR costituenti il polifase max_dim_fir = ceil( n_coeffs / n_fir) ; % creo una matrice che in ogni riga ha i coefficienti % di uno dei rami del filtro SRRC polifase % la inizializzo per velocizzare il riempimento matrice_dei_fir = zeros(n_fir, max_dim_fir) ; for i = 1 : n_fir % riempio una riga alla volta % estraggo i coefficenti dell ’ i_esimo fir fir_i = num_fir_FreqSampl(i : n_fir : n_coeffs) ; % figure ; freqz ( fir_i ) ; figure ; impz ( fir_i ) ; % li copio nella matrice dei fir matrice_dei_fir(i , 1:length(fir_i) )= fir_i ; end % sommo i moduli dei coefficienti di ogni FIR for i = 1 : n_fir modulo_i = sum(abs(matrice_dei_fir(i,:))); vettore_moduli(i) = modulo_i ; end % calcolo il fattore di scaling scaling_factor = max(vettore_moduli) / 0.95 ; % viene applicato il fattore di scaling num_fir_FreqSampl_scaled = num_fir_FreqSampl / scaling_factor ; % i coefficienti scalati vengono salvati nel file fid = fopen(strcat(’SRRCx’,num2str(SpS),’_FreqSampl_scaled.dat’),’w’); fprintf(fid,’%20.19f\n’, num_fir_FreqSampl_scaled); fclose(fid); % la sequenza dati è applicata all ’ SRRC coi coefficienti scalati data_out_SRRC_FreqSampl_scaled = applica_polifase(data_in_SRRCxN_tx_I, ... SpS , num_fir_FreqSampl_scaled); % Power Spectral Density plotting [Pyy_FreqSampl_scaled , f_out] = pwelch(data_out_SRRC_FreqSampl_scaled,... [],[], ’onesided’, length(data_out_SRRC_FreqSampl_scaled) - 1 , f_clk); Pyy_FreqSampl_scaled_dB = 10*log10(Pyy_FreqSampl_scaled) ; figure; plot(f_out,Pyy_FreqSampl_scaled_dB-max(Pyy_FreqSampl_scaled_dB)); grid ; xlim([0 f_clk/2]) ; ylim([-70 0]); legend([’SRRCx’ num2str(SpS) ’ FreqSampl scaled ’ ... [num2str(symbol_rate/10^6)] ’ MSpS’ ]); xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); figure ; impz(num_fir_FreqSampl_scaled) ; end Listato E.3.2: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 101 applica polifase.m % DESCRIPTION : Applica il filtraggio secondo lo schema polifase function data_out_polifase=applica_polifase(data_in_polifase,SpS,coefficienti) % n◦ di FIR che costituiscono il polifase n_fir = SpS ; n_symb = length(data_in_polifase) ; ◦ % n di coefficienti del filtro da realizzare n_coefficienti = length(coefficienti) ; % lunghezza massima dei FIR costituenti il polifase max_dim_fir = ceil( n_coefficienti / n_fir) ; % creo una matrice che in ogni riga ha i coefficienti di uno dei rami del % filtro SRRC polifase matrice_dei_fir = zeros(n_fir, max_dim_fir) ; for i = 1 : n_fir % riempio una riga alla volta % estraggo i coefficenti dell ’ i_esimo fir fir_i = coefficienti(i : n_fir : n_coefficienti) ; % figure ; freqz ( fir_i ) ; figure ; impz ( fir_i ) ; % li copio nella matrice dei fir matrice_dei_fir(i , 1:length(fir_i) )= fir_i ; end % applico la sequenza dati ad ogni fir matrice_fir_out = zeros( n_fir , n_symb ); for i = 1 : n_fir matrice_fir_out(i,:)=filter(matrice_dei_fir(i,:),1,data_in_polifase’); APPENDICE E. LISTATI MATLAB 102 26 27 28 29 30 31 32 33 34 35 36 end % creo un vettore con le uscite dal filtro prese come le prenderebbe un % multiplexer questo vettore in pratica è il risultato dell ’ interpolazione data_out_polifase = zeros( 1 , n_symb * n_fir ); k = 0 ; % è un puntatore per scandire il vettore da riempire for colonna = 1 : n_symb % considero un simbolo alla volta for riga = 1 : n_fir % ed un fir alla volta k = k + 1 ; data_out_polifase(k) = matrice_fir_out(riga , colonna); end end 1 2 3 4 5 6 7 8 9 10 % DESCRIPTION : Calcola la risposta in frequenza del filtro a coseno rialzato Listato E.3.3: RaisedCosineResponse.m function [y] = RaisedCosineResponse(f,roll_off,T) if (abs(f) > ((1+roll_off)/(2*T))), y = 0; elseif (abs(f) > ((1-roll_off)/(2*T))), y = (T/2)*(1+cos((pi*T/roll_off)*(abs(f)-(1-roll_off)/(2*T)))); else y = T; end Listato E.3.4: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 CreaROM.m % DESCRIPTION : genera i valori da inserire nella ROM del polifase mediante % il costrutto VHDL case oppure il Constant oppure genera un % file in formato . coe adatto ad essere fornito ad un Core % Xilinx che implementa una BlockRAM % Pulizia ambiente Matlab clear all ; close all ; clc ; % vengono impostate le caratteristiche del polifase prompt = {’Interpolazione :’, ’N◦ di bit dopo la virgola :’}; title = ’Caratteristiche del polifase’; def = {’3’, ’11’}; answer = inputdlg(prompt, title, 1, def) ; SpS = str2double(answer(1)); n_bit_dopo_virgola = str2double(answer(2)); % scelta tra l ’ implementazione della ROM con il CASE o con una costante implementazione = questdlg(’Scegliere il codice VHDL da generare ’, ... ’Selezione implementazione ROM’,’Case’,’Costante’,’BlockRAM’,’Case’); % carico da file il vettore contenente i coefficienti del filtro gia scalati fid = fopen(strcat(’SRRCx’,num2str(SpS),’_FreqSampl_scaled.dat’),’r’); num_fir = fscanf(fid,’%f’) ; num_fir = num_fir’ ; fclose(fid) ; % n◦ di FIR che costituiscono il polifase n_fir = SpS ; % n◦ di coefficienti del filtro da realizzare n_coefficienti = length(num_fir) ; % lunghezza massima dei FIR costituenti il polifase max_dim_fir = ceil( n_coefficienti / n_fir) ; % matrice che in ogni riga ha i coefficienti di uno dei rami del filtro SRRC % inizializzo per velocizzare il riempimento matrice_dei_fir = zeros(n_fir, max_dim_fir) ; for i = 1 : n_fir % riempio una riga alla volta % estraggo i coefficienti dell ’ i_esimo fir fir_i = num_fir(i : n_fir : n_coefficienti) ; % li copio nella matrice dei fir matrice_dei_fir(i , 1:length(fir_i) )= fir_i ; end % indirizzo della ROM da inserire nel file rom_addr = 0 ; % viene aperto il file nel quale memorizzare i valori della ROM fid = fopen(strcat(’SRRCx’,num2str(SpS),’ROM_’,implementazione,’.dat’),’w’); switch(implementazione) case ’BlockRAM’, % viene richiesto se generare una RAM zero padded RamPadded = questdlg(’Generare una RAM zero padded ’, ... ’Selezione tipo ROM’,’Si’,’No’,’Si’); % sintassi per il file . coe da fornire al CORE BlockRAM fprintf(fid,’%s\n’, ’MEMORY_INITIALIZATION_RADIX=16;’) ; fprintf(fid,’%s\n’, ’MEMORY_INITIALIZATION_VECTOR=’) ; APPENDICE E. LISTATI MATLAB 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 103 end % itero sui fir che costituiscono il polifase % for i = 1 : n_fir for i = n_fir : -1 : 1 % viene scritta sul file l ’ istruzione per l ’ assegnamento di default % per i valori non assegnati switch(implementazione) case {’Case’,’Costante’}, % aggiungo al file il commento che indica il numero del FIR fprintf(fid,’%s\n’, ’ ’) ; fprintf(fid,’%s’, ’ -- somme per il FIR ’) ; % fprintf ( fid ,’% s \ n ’, num2str ( i ) ) ; fprintf(fid,’%s\n’, num2str(n_fir - i)) ; end % calcolo le somme da inserire nel file per il filtro i_esimo % itero su tutte le combinazioni d ’ ingresso for eing = 0 : 1 : 2^max_dim_fir - 1 % la sequenza d ’ ingresso attuale viene convertita in formato rz +1,0 eing_rz = bitget(eing,max_dim_fir:-1:1) ; % la sequenza d ’ ingresso attuale viene convertita in formato nrz +1,-1 eing_nrz = ( -2 .* eing_rz )+ 1 ; % vengono sommati i coefficienti pesati del filtro i_esimo somma = sum( eing_nrz .* matrice_dei_fir(i,:) ) ; % le somme vengono convertite in interi e arrotondate in modo da poter % esser elaborate dal VHDL somma_int = round( somma * 2^n_bit_dopo_virgola ); % calcolo l ’ intero in complemento a due corrispondente alla somma if sign(somma_int) == -1 % coefficiente negativo somma_int_C2 = 2^(n_bit_dopo_virgola+1) - abs(somma_int); %2^ N - | x | else % coefficiente positivo somma_int_C2 = abs(somma_int) ; % | x | end % aggiungo al file l ’ i_esimo valore della somma del fir switch(implementazione) case ’Case’, % sintassi per il costrutto VHDL Case fprintf(fid,’%s’, ’ when ’) ; fprintf(fid,’%3d’, rom_addr ); fprintf(fid,’%s’, ’ => SRRC_out <= X"’) ; fprintf(fid,’%03X’, somma_int_C2) ; fprintf(fid,’%s\n’, ’";’) ; case ’Costante’, % sintassi per il costrutto VHDL Constant fprintf(fid,’%s’, ’ ROM_value’’(X"’) ; fprintf(fid,’%03X’, somma_int_C2) ; fprintf(fid,’%s’, ’") , -- ’) ; fprintf(fid,’%3d’, rom_addr) ; fprintf(fid,’%s\n’, ’ ’) ; case ’BlockRAM’, % sintassi per il file . coe da fornire al CORE BlockRAM fprintf(fid,’%03X’, somma_int_C2) ; fprintf(fid,’%s\n’, ’, ’) ; otherwise, disp(’Unknown method.’) end % punto alla successiva cella di memoria da riempire rom_addr = rom_addr + 1 ; end end % viene scritta sul file l ’ istruzione per l ’ assegnamento di default % per i valori non assegnati switch(implementazione) case ’Case’, % sintassi per il costrutto VHDL Case fprintf(fid,’%s\n’, ’ when OTHERS => SRRC_out <= X"000";’); case ’Costante’, % sintassi per il costrutto VHDL Constant fprintf(fid,’%s\n’, ’ ’) ; fprintf(fid,’%s\n’, ’ OTHERS => ROM_value’’(X"000") );’); case ’BlockRAM’, % se la RAM è padded aggiungo degli 0 che la occupano tutta in questo % modo si possono mettere in un ’ unica RAM tutti e tre gli SRRC if strcmp(RamPadded , ’Si’) % per l ’ indirizzamento considero la ROM di dimensioni maggiori for addr = rom_addr : 1 : 2^(max_dim_fir + round(log2(6))) - 1 fprintf(fid,’%03X’, 0) ; fprintf(fid,’%s\n’, ’, ’) ; end end fprintf(fid,’%s\n’, ’;’) ; otherwise, disp(’Unknown method.’) end % viene chiuso il file contenente i valori delle somme da porre nella ROM fclose(fid) ; disp(’Generato file valori ROM .’) ; APPENDICE E. LISTATI MATLAB 104 Test VHDL Listato E.3.5: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 PolyphasePSDVHDLvsPSDMatlab.m % DESCRIPTION : Confronta lo spettro della sequenza filtrata tramite il VHDL % con quello della sequenza filtrata tramite Matlab % Pulizia ambiente Matlab clear all ; close all ; clc ; % ************** IMPOSTAZIONE CARATTERISTICHE DEL MODULATORE ************** % vengono impostate le caratteristiche del polifase prompt = {’Frequenza di clock :’, ’Symbol Rate :’, ’N◦ di bit dopo la virgola :’}; title = ’Caratteristiche del polifase’; def = {’40’, ’40/3’, ’11’}; answer = inputdlg(prompt, title, 1, def) ; f_clk = str2double(answer(1))*10^6; symbol_rate = eval( char(answer(2)) )*10^6; n_bit_dopo_virgola = str2double(answer(3)); % viene determinato il valore dell ’ interpolazione SpS = f_clk / symbol_rate ; % selezione del file sorgente tra quello prodotto dalla simulazione semplice e % quello della back - annotata file_simulazione = questdlg(’Selezionare il nome del file sorgente VHDL :’,... ’Selezione simulazione back-annotata o semplice’,... ’data_out_SRRCxN_tx_I.dat’,’TB_data_out_SRRCxN_tx_I.dat’,... ’data_out_SRRCxN_tx_I.dat’); % **** VIENE APPLICATA LA DECOMPOSIZIONE POLIFASE MATLAB DI RIFERIMENTO **** % carica da file la sequenza dei dati da filtrare fid = fopen(’data_in_SRRCxN_tx_I_nrz.dat’ , ’r’) ; data_in_SRRCxN_tx_I = fscanf(fid,’%f’) ; fclose(fid) ; % carica da file i coefficienti del filtro polifase fid = fopen( strcat(’SRRCx’, num2str(SpS), ’_FreqSampl_scaled.dat’),’r’); num_fir = fscanf(fid,’%f’) ; num_fir = num_fir’ ; fclose(fid) ; % applica il filtraggio polifase Matlab data_out_SRRCxN_tx_I = applica_polifase(data_in_SRRCxN_tx_I, SpS , num_fir); % con il metodo di Welch viene calcolato lo spettro della sequenza filtrata % mediante il polifase MATLAB [Pyy_Matlab , f_out] = pwelch(data_out_SRRCxN_tx_I, [] , [] , ’onesided’,... length(data_out_SRRCxN_tx_I) - 1 , f_clk) ; Pyy_dB_Matlab = 10*log10(Pyy_Matlab) ; figure ; plot(f_out , Pyy_dB_Matlab - max(Pyy_dB_Matlab) ); grid ; xlim([0 f_clk/2]) ; ylim([-70 0]); legend([’Out SRRCx’,num2str(SpS),’ Matlab ’,num2str(symbol_rate/1e6),’ MSpS’]); xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); % ************** VIENE APPLICATA LA DECOMPOSIZIONE POLIFASE VHDL ********* % carica da file la sequenza filtrata dal polifase VHDL fid = fopen(file_simulazione , ’r’) ; % viene scartato il primo numero che è un overflow string_unuseful = fscanf(fid, ’%s’ , 1); % vengono letti un numero di campioni pari a quelli del polifase Matlab data_out_SRRCxN_tx_I_dec=fscanf(fid,’%f’,length(data_in_SRRCxN_tx_I)*SpS); fclose(fid); data_out_SRRCxN_tx_I_VHDL=data_out_SRRCxN_tx_I_dec.*2^(- n_bit_dopo_virgola); % viene prodotta una stringa da aggiungere alla label nel caso di simulazione % back - annotata if strcmp(file_simulazione , ’TB_data_out_SRRCxN_tx_I.dat’) tipo_simulazione = ’B.A. ’ ; else tipo_simulazione = ’’ ; end % con il metodo di Welch viene calcolato lo spettro della sequenza filtrata % dal polifase VHDL [Pyy_VHDL , f_out]=pwelch(data_out_SRRCxN_tx_I_VHDL, [] , [] , ’onesided’,... length(data_out_SRRCxN_tx_I_VHDL) - 1 , f_clk) ; Pyy_dB_VHDL = 10*log10(Pyy_VHDL) ; figure ; plot(f_out , Pyy_dB_VHDL - max(Pyy_dB_VHDL) , ’-r’); grid ; xlim([0 f_clk/2]) ; ylim([-70 0]); legend([’Out SRRCx’,num2str(SpS),’ VHDL ’,tipo_simulazione,... num2str(symbol_rate/1e6),’ MSpS’]); xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); % ****************************** CONFRONTO SPETTRALE ********************* % visualizzazione contemporanea dei due spettri figure ; plot(f_out,Pyy_dB_Matlab-max(Pyy_dB_Matlab),’-b’,f_out,... Pyy_dB_VHDL-max(Pyy_dB_VHDL),’-r’); grid ; xlim([0 f_clk/2]) ; ylim([-70 0]); legend([’Out SRRCx’, num2str(SpS), ’ Matlab ’ , num2str(symbol_rate/1e6),... APPENDICE E. LISTATI MATLAB 84 85 86 87 88 89 90 91 ’ MSpS’ ],[’Out SRRCx’, num2str(SpS),’ VHDL ’,tipo_simulazione,... num2str(symbol_rate/1e6) , ’ MSpS’ ] ); xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); % ******************************* CONFRONTO TEMPORALE ********************* % n_bits = length ( data_out_SRRCxN_tx_I ) ; % N_bit_sfasamento = 8 ; % [ data_out_SRRCxN_tx_I (( N_bit_sfasamento +1) : n_bits ) ’,... % data_out_SRRCxN_tx_I_VHDL (1:( n_bits - N_bit_sfasamento ) ) ] Listato E.3.6: applica polifase.m vedi listato(E.3.2) Test FPGA Listato E.3.7: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 VisualizzaPSDPolifaseVHDLFPGAout.m % DESCRIPTION : carica da file la sequenza dati filtrata tramite l ’ FPGA e % ne fa l ’ analisi spettrale % Pulizia ambiente Matlab clear all ; close all ; clc ; % ************ IMPOSTAZIONE CARATTERISTICHE DEL MODULATORE ************ % vengono impostate le caratteristiche del polifase prompt = {’Frequenza di clock :’, ’Symbol Rate :’, ’N◦ di bit dopo la virgola :’, ’N◦ di campioni da considerare :’}; title = ’Caratteristiche del polifase’; def = {’40’, ’40/3’, ’11’, ’18000’}; answer = inputdlg(prompt, title, 1, def) ; f_clk = str2double(answer(1))*10^6; symbol_rate = eval( char(answer(2)) )*10^6; n_bit_dopo_virgola = str2double(answer(3)); n_values = str2double(answer(4)); % viene determinato il valore dell ’ interpolazione SpS = f_clk / symbol_rate ; % **** VIENE APPLICATA LA DECOMPOSIZIONE POLIFASE MATLAB DI RIFERIMENTO **** % carica da file la sequenza dei dati da filtrare fid = fopen(’data_in_SRRCxN_tx_I_nrz.dat’ , ’r’) ; data_in_SRRCxN_tx_I = fscanf(fid,’%f’) ; fclose(fid) ; % carica da file i coefficienti del filtro polifase fid = fopen( strcat(’SRRCx’,num2str(SpS),’_FreqSampl_scaled.dat’),’r’); num_fir = fscanf(fid,’%f’) ; num_fir = num_fir’ ; fclose(fid) ; % applica il filtraggio polifase Matlab data_out_SRRCxN_tx_I = applica_polifase(data_in_SRRCxN_tx_I, SpS , num_fir); % con il metodo di Welch viene calcolato lo spettro della sequenza % filtrata dal polifase MATLAB [Pyy_Matlab , f_out] = pwelch(data_out_SRRCxN_tx_I, [] , [] , ’onesided’,... length(data_out_SRRCxN_tx_I) - 1 , f_clk) ; Pyy_dB_Matlab = 10*log10(Pyy_Matlab) ; figure ; plot(f_out , Pyy_dB_Matlab - max(Pyy_dB_Matlab) , ’-b’); grid ; xlim([0 f_clk/2]) ; ylim([-70 0]); legend([’Out SRRCx’, num2str(SpS), ’ Matlab ’ , ... num2str(symbol_rate/1e6) , ’ MSpS’ ]); xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); % ************ ELABORAZIONE DELLA SEQUENZA FILTRATA DALL ’ FPGA ************* % carica la sequenza proveniente dall ’ analizzatore di stati logici fid = fopen(’file_out.txt’ , ’r’); % vengono scartate le prime 7 stringhe string_unuseful = fscanf(fid, ’%s’ , 7); % viene prelevata la stringa che indica il formato formato = fscanf(fid, ’%s’ , 1) ; % viene scartata una stringa con tutti - 105 APPENDICE E. LISTATI MATLAB 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 106 string_unuseful = fscanf(fid, ’%s’ , 1); % i dati vengono letti dal file nel giusto formato switch(formato) case ’Hex’, value_int_C2 = fscanf(fid, ’%x’ , n_values) ; case ’Decimal’, value_int_C2 = fscanf(fid, ’%f’ , n_values) ; end fclose(fid) ; % converte l ’ intero unsigned in complemento a due in un intero con segno value_int = zeros(n_values,1); for i = 1 : 1 : n_values if bitget( value_int_C2(i) , 12) == 1 % valore negativo % x_C2 = 2^ N - | x | value_int(i) = -( 2^(n_bit_dopo_virgola+1) - value_int_C2(i) ); else % coefficiente positivo value_int(i) = value_int_C2(i) ; % x_C2 = | x | end end % converte da intero con segno a numero reale con segno value_real = value_int .* 2^(- n_bit_dopo_virgola); data_out_SRRCxN_tx_I_FPGA = value_real ; % con il metodo di Welch viene calcolato lo spettro della sequenza % filtrata dal polifase VHDL e plottata [Pyy_FPGA , f_out] = pwelch(data_out_SRRCxN_tx_I_FPGA, [] , [] , ... ’onesided’, length(data_out_SRRCxN_tx_I_FPGA) - 1 , f_clk) ; Pyy_dB_FPGA = 10*log10(Pyy_FPGA) ; figure ; plot(f_out , Pyy_dB_FPGA - max(Pyy_dB_FPGA) , ’-r’ ); grid ; xlim([0 f_clk/2]) ; ylim([-70 0]); legend([’Out SRRCx’, num2str(SpS), ’ FPGA ’ , ... num2str(symbol_rate/1e6), ’ MSpS’ ]); xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); % ************** CONFRONTO SPETTRALE ********************************* % visualizzazione contemporanea dei due spettri figure ; plot(f_out , Pyy_dB_Matlab - max(Pyy_dB_Matlab) , ’-b’ , f_out , ... Pyy_dB_FPGA - max(Pyy_dB_FPGA) , ’-r’); grid ; xlim([0 f_clk/2]) ; ylim([-70 0]); legend([’Out SRRCx’, num2str(SpS), ’ Matlab ’ , num2str(symbol_rate/1e6),... ’ MSpS’ ], [’Out SRRCx’, num2str(SpS), ’ FPGA ’ , ... num2str(symbol_rate/1e6) , ’ MSpS’ ] ); xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); % ******************* CONFRONTO TEMPORALE ***************************** % n_bits = length ( data_out_SRRCxN_tx_I ) ; % N_bit_sfasamento = 8 ; % [ data_out_SRRCxN_tx_I (( N_bit_sfasamento +1) : n_bits ) ’ , ... % data_out_SRRCxN_tx_I_FPGA (1:( n_bits - N_bit_sfasamento ) ) ] Listato E.3.8: applica polifase.m vedi listato(E.3.2) E.4 Modulatore Tabella e grafico BER Listato E.4.1: 1 2 3 4 5 6 7 8 CreaTabellaBER.m % MODULE NAME : CreaTabellaBER . m % DESCRIPTION : Crea una tabella ed un grafico del BER in funzione di Eb / N0 % Pulizia ambiente Matlab clear all ; close all ; clc ; % **************************************************************************** APPENDICE E. LISTATI MATLAB 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 % ****************** IMPOSTAZIONE CARATTERISTICHE MISURA ***************** % **************************************************************************** prompt = {’Frequenza di clock :’, ’Data Rate :’, ’Eb/No minimo (dB) :’, ’Eb/No massimo (dB) :’, ’N◦ di ripetizioni per ogni valore di Eb/No :’}; title = ’Impostazione della simulazione Modem QPSK’; def = {’165’, ’110’, ’2’, ’6’, ’2’}; answer = inputdlg(prompt, title, 1, def) ; f_clk = str2double(answer(1))*10^6; data_rate = str2double(answer(2))*10^6; EbNo_dB_min = str2double(answer(3)); EbNo_dB_max = str2double(answer(4)); Repeat = str2double(answer(5)); % messaggio per rassicurare l ’ operatore , qualcosa si muove anche se non sembra disp(’...elaborazione della tabella dei BER in corso’) disp(’ ’) disp(’ ’) % iterazione sui diversi valori di EbNo_dB for EbNo_dB = EbNo_dB_min : 1 : EbNo_dB_max EbNo = 10.^(EbNo_dB/10) ; expBER = 0.5 .* erfc(sqrt(EbNo)) ; expBER_vect(EbNo_dB + 1 - EbNo_dB_min) = expBER ; n_bits = 60 * 12 .* round( [1 ./ expBER’] ./ 12) ; if n_bits < 12000 n_bits = 12000 ; end for i = 1:1:Repeat [n_bit_errati , BER] = calcolaBER(n_bits , EbNo_dB, f_clk , data_rate) ; temp_BER(i) = BER ; end BER_vect(EbNo_dB + 1 - EbNo_dB_min) = ( sum(temp_BER) )/ Repeat ; end % Viene plottato il BER teorico affiancato al BER sperimentale EbNo_dB = [EbNo_dB_min : 1 : EbNo_dB_max] ; semilogy(EbNo_dB(:), BER_vect, ’b-’, EbNo_dB(:), expBER_vect, ’r-’); legend(’BER sperimentale ’,’BER Teorico’,0); grid on; xlabel(’EbNo (dB)’); ylabel(’BER’); disp(’ Eb/No BER teorico BER sperimentale’) [EbNo_dB’ expBER_vect’ BER_vect’] Listato E.4.2: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 107 calcolaBER.m % MODULE NAME : Modulatore QPSK con applica_polifase SRRC . m % DESCRIPTION : Funzione per la misura del BER % DATE : 19-10-2001 function [n_bit_errati_Matlab , BER_Matlab] = ... BER_sperimentale(n_bits , EbNo_dB , f_clk , data_rate) %%%%%%%%%%%%%%%%%%%%%%%% IMPOSTAZIONE MODULATORE %%%%%%%%%%%%%%%%%%%%%%%%% symbol_rate = data_rate / 2 ; SpS = f_clk / symbol_rate ; n_symb = n_bits / 2 ; n_sample = n_symb * SpS ; % crea un vettore di bits randomici bit_tx = randint(n_bits, 1, [0 1] ); n_bits_tx = length(bit_tx) ; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% MODULAZIONE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % carica da file i coefficienti del filtro polifase fid = fopen( strcat(’SRRCx’, num2str(SpS), ’_FreqSampl_scaled.dat’),’r’); num_fir = fscanf(fid,’%f’) ; num_fir = num_fir’ ; fclose(fid) ; % viene creato il vettore dei bit pari e quello dei bit dispari bit_tx_I = bit_tx(1 : 2 : n_bits_tx) ; bit_tx_Q = bit_tx(2 : 2 : n_bits_tx) ; % si passa dalla codifica RZ alla codifica NRZ data_in_SRRCxN_tx_I_Matlab = -2*bit_tx_I + 1 ; data_in_SRRCxN_tx_Q_Matlab = -2*bit_tx_Q + 1 ; % applica il filtraggio polifase Matlab data_out_SRRCxN_tx_I_Matlab = applica_polifase(data_in_SRRCxN_tx_I_Matlab,... SpS , num_fir); data_out_SRRCxN_tx_Q_Matlab = applica_polifase(data_in_SRRCxN_tx_Q_Matlab,... SpS , num_fir); % Vengono generati i campioni di seno e coseno considerando f_IF = f_clk / 4 % n◦ di campioni da generare per le portanti n_sample = length(data_out_SRRCxN_tx_I_Matlab); % periodo di campionamento t_clk = 1 / f_clk ; % istanti di campionamento APPENDICE E. LISTATI MATLAB 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 t = 0 : t_clk : (n_sample-1)*t_clk ; % incrementi di fase theta = 2*pi*(f_clk/4)*t ; % generazione di un coseno coseno = [cos(theta)] ; % generazione di un seno seno = [sin(theta)] ; data_out_QPSK_Mod_Matlab = [coseno .* data_out_SRRCxN_tx_I_Matlab] - ... [seno .* data_out_SRRCxN_tx_Q_Matlab] ; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% EFFETTO DEL CANALE %%%%%%%%%%%%%%%%%%%%%%%%%%% data_in_QPSK_DeMod_Matlab = awgn(data_out_QPSK_Mod_Matlab, ... EbNo_dB + 10*log10(2) -10*log10(0.5.*SpS), ’measured’, [], ’dB’); %%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEMODULAZIONE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % il segnale in banda traslata viene suddiviso nelle componenti in banda base data_in_SRRCxN_rx_I_Matlab = coseno .* data_in_QPSK_DeMod_Matlab ; data_in_SRRCxN_rx_Q_Matlab = -seno .* data_in_QPSK_DeMod_Matlab ; % applico il filtro adattato ad entrambe le componenti data_out_SRRCxN_rx_I_Matlab = filter(num_fir, 1 , data_in_SRRCxN_rx_I_Matlab); data_out_SRRCxN_rx_Q_Matlab = filter(num_fir, 1 , data_in_SRRCxN_rx_Q_Matlab); data_I_Q_rx_Matlab = ... [data_out_SRRCxN_rx_I_Matlab’ data_out_SRRCxN_rx_Q_Matlab’]; % viene effettuato uno sfasamento , una decimazione ed applicato il decisore symbols_Matlab = demodmap(data_I_Q_rx_Matlab , [symbol_rate 1] , f_clk , ... ’qask’ , 4) ; % l ’ uscita del decisore viene convertita in formato NRZ for n = 1:length(symbols_Matlab) switch symbols_Matlab(n) case 0 symbols_I_Matlab(n) = 1 ; symbols_Q_Matlab(n) = 1 ; case 1 symbols_I_Matlab(n) = -1 ; symbols_Q_Matlab(n) = 1 ; case 2 symbols_I_Matlab(n) = 1 ; symbols_Q_Matlab(n) = -1 ; case 3 symbols_I_Matlab(n) = -1 ; symbols_Q_Matlab(n) = -1 ; end end % si passa dalla codifica NRZ alla codifica RZ bit_rx_I_Matlab = ( symbols_I_Matlab - 1) / (-2) ; bit_rx_Q_Matlab = ( symbols_Q_Matlab - 1) / (-2) ; % dai simboli si riottiene la sequenza composta da bit I e Q alternati bit_rx_Matlab = 4*ones(1 , n_bits_tx) ; bit_rx_Matlab(1 : 2 : n_bits_tx) = bit_rx_I_Matlab ; bit_rx_Matlab(2 : 2 : n_bits_tx) = bit_rx_Q_Matlab ; % viene compensato lo sfasamento tra la sequenza trasmessa e quella ricevuta N_bit_sfasamento_Matlab = 12 ; [n_bit_errati_Matlab BER_Matlab] = ... biterr(bit_tx(1:(n_bits_tx - N_bit_sfasamento_Matlab)), ... bit_rx_Matlab( (N_bit_sfasamento_Matlab + 1):n_bits_tx)’) ; Listato E.4.3: applica polifase.m vedi listato(E.3.2) Test VHDL Listato E.4.4: 1 2 3 4 5 6 7 8 9 10 11 108 QPSKModemPSDeBERVHDLvsMatlab.m % DESCRIPTION : Confronta lo spettro ed il BER della sequenza modulata % tramite il VHDL con quello Matlab % Pulizia ambiente Matlab clear all ; close all ; clc ; % **************************************************************************** % **************** IMPOSTAZIONE CARATTERISTICHE DEL MODEM **************** % **************************************************************************** prompt = {’Frequenza di clock :’, APPENDICE E. LISTATI MATLAB 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 109 ’Symbol Rate :’, ’N◦ di bit dopo la virgola :’ ’Eb/No (dB)’ }; title = ’Impostazione della simulazione Modem QPSK’; def = {’40’, ’40/3’, ’11’, ’6’}; answer = inputdlg(prompt, title, 1, def) ; f_clk = str2double(answer(1))*10^6; symbol_rate = eval( char(answer(2)) )*10^6; n_bit_dopo_virgola = str2double(answer(3)); EbNo_dB = str2double(answer(4)); EbNo = 10^(EbNo_dB/10); % viene determinato il valore dell ’ interpolazione SpS = f_clk / symbol_rate ; % selezione del file sorgente tra quello prodotto dalla simulazione semplice e % quello della back - annotata file_simulazione = questdlg(’Selezionare il nome del file sorgente VHDL :’,... ’Selezione simulazione back-annotata o semplice’, ... ’data_out_QPSK_modulator.dat’,’TB_data_out_QPSK_modulator.dat’,... ’data_out_QPSK_modulator.dat’); % **************************************************************************** % ********************* MODEM QPSK MATLAB DI RIFERIMENTO ********************* % **************************************************************************** %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% MODULAZIONE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % carica da file i coefficienti del filtro polifase fid = fopen( strcat(’SRRCx’, num2str(SpS), ’_FreqSampl_scaled.dat’),’r’); num_fir = fscanf(fid,’%f’) ; num_fir = num_fir’ ; fclose(fid) ; % carica da file la sequenza randomica da modulare fid = fopen(’bit_tx.dat’ , ’r’) ; bit_tx = fscanf(fid,’%f’) ; fclose(fid) ; n_bits_tx = length(bit_tx) ; % viene creato il vettore dei bit pari e quello dei bit dispari bit_tx_I = bit_tx(1 : 2 : n_bits_tx) ; bit_tx_Q = bit_tx(2 : 2 : n_bits_tx) ; % si passa dalla codifica RZ alla codifica NRZ data_in_SRRCxN_tx_I_Matlab = -2*bit_tx_I + 1 ; data_in_SRRCxN_tx_Q_Matlab = -2*bit_tx_Q + 1 ; % applica il filtraggio polifase Matlab data_out_SRRCxN_tx_I_Matlab = applica_polifase(data_in_SRRCxN_tx_I_Matlab,... SpS , num_fir); data_out_SRRCxN_tx_Q_Matlab = applica_polifase(data_in_SRRCxN_tx_Q_Matlab,... SpS , num_fir); % Vengono generati i campioni di seno e coseno considerando f_IF = f_clk / 4 % n◦ di campioni da generare per le portanti n_sample = length(data_out_SRRCxN_tx_I_Matlab); % periodo di campionamento t_clk = 1 / f_clk ; % istanti di campionamento t = 0 : t_clk : (n_sample-1)*t_clk ; % incrementi di fase theta = 2*pi*(f_clk/4)*t ; % generazione di un coseno coseno = [cos(theta)] ; % generazione di un seno seno = [sin(theta)] ; data_out_QPSK_Mod_Matlab = [coseno .* data_out_SRRCxN_tx_I_Matlab] - ... [seno .* data_out_SRRCxN_tx_Q_Matlab] ; % spettro del segnale QPSK modulato tramite Matlab [Pyy_Mod_Matlab , f_out] = pwelch(data_out_QPSK_Mod_Matlab, [] , [] , ... ’onesided’, length(data_out_QPSK_Mod_Matlab) - 1 , f_clk) ; Pyy_Mod_Matlab_dB = 10*log10(Pyy_Mod_Matlab) ; figure ; plot(f_out , Pyy_Mod_Matlab_dB - max(Pyy_Mod_Matlab_dB) ); grid ; xlim([0 f_clk/2]) ; ylim([-60 0]); legend([’Out QPSK Modem Matlab ’ , num2str(2*symbol_rate/1e6) , ’ MbpS’], 3); xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% EFFETTO DEL CANALE %%%%%%%%%%%%%%%%%%%%%%%%%%% data_in_QPSK_DeMod_Matlab = awgn(data_out_QPSK_Mod_Matlab, ... EbNo_dB + 10*log10(2) -10*log10(0.5.*SpS), ’measured’, [], ’dB’); % viene calcolata e plottata la densità spettrale di potenza del segnale % QPSK affetto da rumore [Pyy_DeMod_in_Matlab , f_out] = pwelch(data_in_QPSK_DeMod_Matlab,[],[], ... ’onesided’, length(data_in_QPSK_DeMod_Matlab) - 1 , f_clk) ; Pyy_DeMod_in_Matlab_dB = 10*log10(Pyy_DeMod_in_Matlab) ; figure ; plot(f_out, Pyy_DeMod_in_Matlab_dB - max(Pyy_DeMod_in_Matlab_dB)); grid ; xlim([0 f_clk/2]); legend([’In QPSK DeMod Matlab ’ , num2str(2*symbol_rate/1e6) , ’ MbpS’], 3); xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); %%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEMODULAZIONE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % il segnale in banda traslata viene suddiviso nelle componenti in banda base data_in_SRRCxN_rx_I_Matlab = coseno .* data_in_QPSK_DeMod_Matlab ; data_in_SRRCxN_rx_Q_Matlab = -seno .* data_in_QPSK_DeMod_Matlab ; % applico il filtro adattato ad entrambe le componenti data_out_SRRCxN_rx_I_Matlab = filter(num_fir, 1 , data_in_SRRCxN_rx_I_Matlab); data_out_SRRCxN_rx_Q_Matlab = filter(num_fir, 1 , data_in_SRRCxN_rx_Q_Matlab); APPENDICE E. LISTATI MATLAB 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 110 % diagramma ad occhio della sequenza I ricevuta eyediagram(data_out_SRRCxN_rx_I_Matlab(601:2400) , SpS , 1/symbol_rate , 2); data_I_Q_rx_Matlab = ... [data_out_SRRCxN_rx_I_Matlab’ data_out_SRRCxN_rx_Q_Matlab’]; % scatterplot del segnale ricevuto scatterplot(data_I_Q_rx_Matlab , SpS , 2) ; % viene effettuato uno sfasamento , una decimazione ed applicato il decisore symbols_Matlab = demodmap(data_I_Q_rx_Matlab , [symbol_rate 1] , f_clk , ... ’qask’ , 4) ; % l ’ uscita del decisore viene convertita in formato NRZ for n = 1:length(symbols_Matlab) switch symbols_Matlab(n) case 0 symbols_I_Matlab(n) = 1 ; symbols_Q_Matlab(n) = 1 ; case 1 symbols_I_Matlab(n) = -1 ; symbols_Q_Matlab(n) = 1 ; case 2 symbols_I_Matlab(n) = 1 ; symbols_Q_Matlab(n) = -1 ; case 3 symbols_I_Matlab(n) = -1 ; symbols_Q_Matlab(n) = -1 ; end end % si passa dalla codifica NRZ alla codifica RZ bit_rx_I_Matlab = ( symbols_I_Matlab - 1) / (-2) ; bit_rx_Q_Matlab = ( symbols_Q_Matlab - 1) / (-2) ; % dai simboli si riottiene la sequenza composta da bit I e Q alternati bit_rx_Matlab = 4*ones(1 , n_bits_tx) ; bit_rx_Matlab(1 : 2 : n_bits_tx) = bit_rx_I_Matlab ; bit_rx_Matlab(2 : 2 : n_bits_tx) = bit_rx_Q_Matlab ; % viene compensato lo sfasamento tra la sequenza trasmessa e quella ricevuta N_bit_sfasamento_Matlab = 12 ; [n_bit_errati_Matlab BER_Matlab] = ... biterr(bit_tx(1:(n_bits_tx - N_bit_sfasamento_Matlab)), ... bit_rx_Matlab( (N_bit_sfasamento_Matlab + 1):n_bits_tx)’) ; disp([’ Risultati Modulatore Matlab -> Demodulatore Matlab ’]); disp([’N◦ di bit di sfasamento : ’ num2str(N_bit_sfasamento_Matlab)]); disp([’N◦ di bit errati : ’ num2str(n_bit_errati_Matlab)]); disp([’BER : ’ num2str(BER_Matlab)]); % viene calcolato il valore dello sfasamento per il quale si ha la minore BER for N_bit_sfasamento_Matlab = 1:1:15 [n_bit_errati_Matlab(N_bit_sfasamento_Matlab) ... BER_Matlab(N_bit_sfasamento_Matlab)] = ... biterr(bit_tx(1:(n_bits_tx - N_bit_sfasamento_Matlab)) , ... bit_rx_Matlab( (N_bit_sfasamento_Matlab + 1):n_bits_tx)’); disp(’ ’); disp([’N◦ di bit di sfasamento : ’ num2str(N_bit_sfasamento_Matlab)]); disp([’N◦ di bit errati : ’ ... num2str(n_bit_errati_Matlab(N_bit_sfasamento_Matlab))]); disp([’BER : ’ ... num2str(BER_Matlab(N_bit_sfasamento_Matlab))]); end [ber_Matlab , N_bit_sfasamento_Matlab] = min(BER_Matlab) ; disp(’ ’); disp(’ ’); disp([’BER minima : ’ num2str(ber_Matlab)]); disp([’N◦ di bit errati : ’ ... num2str(n_bit_errati_Matlab(N_bit_sfasamento_Matlab))]); disp([’Sfasamento : ’ num2str(N_bit_sfasamento_Matlab)]); % Visualizza il valore teorico per il BER theoretical_BER = 0.5 .* erfc(sqrt(EbNo)) ; disp(’ ’); disp([’BER teorico : ’ num2str(theoretical_BER)]); disp(’ ’); % **************************************************************************** % ************** MODULATORE QPSK VHDL E DEMODULATORE MATLAB ****************** % **************************************************************************** % carica da file la sequenza modulata tramite il VHDL fid = fopen(file_simulazione , ’r’) ; % viene scartato il primo numero che è un overflow string_unuseful = fscanf(fid, ’%s’ , 1); % vengono letti un numero di campioni pari a quelli del polifase Matlab data_out_QPSK_Mod_dec = fscanf(fid,’%f’, ... length(data_in_SRRCxN_tx_I_Matlab) * SpS); fclose(fid); data_out_QPSK_Mod_VHDL = data_out_QPSK_Mod_dec .* 2^(- n_bit_dopo_virgola); % viene prodotta una stringa da aggiungere alla label nel caso di simulazione % back - annotata if strcmp(file_simulazione , ’TB_data_out_QPSK_modulator.dat’) tipo_simulazione = ’B.A. ’ ; else tipo_simulazione = ’’ ; end % spettro del segnale QPSK modulato tramite il VHDL [Pyy_Mod_VHDL , f_out] = pwelch(data_out_QPSK_Mod_VHDL,[],[],’onesided’,... length(data_out_QPSK_Mod_VHDL) - 1 , f_clk) ; Pyy_Mod_VHDL_dB = 10*log10(Pyy_Mod_VHDL) ; figure ; plot(f_out , Pyy_Mod_VHDL_dB - max(Pyy_Mod_VHDL_dB) , ’-r’); grid ; xlim([0 f_clk/2]) ; ylim([-60 0]); legend([’Out QPSK Modem VHDL ’ , tipo_simulazione , ... APPENDICE E. LISTATI MATLAB 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 111 num2str(2*symbol_rate/1e6) , ’ MbpS’], 3); xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% EFFETTO DEL CANALE %%%%%%%%%%%%%%%%%%%%%%%%%%%% data_in_QPSK_DeMod_VHDL = awgn(data_out_QPSK_Mod_VHDL, EbNo_dB +10*log10(2)... -10*log10(0.5.*SpS), ’measured’, [], ’dB’); % viene calcolata e plottata la densità spettrale di potenza del segnale QPSK % affetto da rumore [Pyy_DeMod_in_VHDL , f_out] = pwelch(data_in_QPSK_DeMod_VHDL, [] , [] , ... ’onesided’, length(data_in_QPSK_DeMod_VHDL) - 1 , f_clk) ; Pyy_DeMod_in_VHDL_dB = 10*log10(Pyy_DeMod_in_VHDL) ; figure ; plot(f_out , Pyy_DeMod_in_VHDL_dB-max(Pyy_DeMod_in_VHDL_dB),’-r’) ; grid ; xlim([0 f_clk/2]) ; legend([’In QPSK DeMod VHDL ’ , num2str(2*symbol_rate/1e6) , ’ MbpS’], 3) ; xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEMODULAZIONE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % PROCEDURA PER L ’ ALLINEAMENTO DEL DEMODULATORE : % Il demodulatore è suscettibile a tre variabili : % quadrante_iniziale , offset_demodmap , N_bit_sfasamento_VHDL % a ) togliere il commento dal ciclo FOR che itera su N_bit_sfasamento_VHDL % b ) assegnare quadrante_iniziale = 0 % c ) far partire la simulazione , alla fine si ha il minimo BER e il % corrispondente N_bit_sfasamento_VHDL % d ) fare lo stesso variando per i valori 1, 2, 3 di quadrante_iniziale % e ) fissando il valore minimo per quadrante_iniziale e N_bit_sfasamento_VHDL % ricercare il minimo di offset_demodmap % Vengono generati i campioni di seno e coseno considerando f_IF = f_clk / 4 quadrante_iniziale = 1 ; % incrementi di fase theta_rx_VHDL = 2*pi*(f_clk/4)*t + quadrante_iniziale*pi/2 ; coseno_rx_VHDL = [cos(theta_rx_VHDL)] ; % generazione del coseno seno_rx_VHDL = [sin(theta_rx_VHDL)] ; % generazione del seno % il segnale in banda traslata viene suddiviso nelle componenti in banda base data_in_SRRCxN_rx_I_VHDL = coseno_rx_VHDL .* data_in_QPSK_DeMod_VHDL’ ; data_in_SRRCxN_rx_Q_VHDL = -seno_rx_VHDL .* data_in_QPSK_DeMod_VHDL’ ; % applico il filtro adattato ad entrambe le componenti data_out_SRRCxN_rx_I_VHDL = filter(num_fir, 1 , data_in_SRRCxN_rx_I_VHDL); data_out_SRRCxN_rx_Q_VHDL = filter(num_fir, 1 , data_in_SRRCxN_rx_Q_VHDL); % diagramma ad occhio della sequenza I ricevuta % eyediagram ( data_out_SRRCxN_rx_I_VHDL (601:2400) , SpS ,1/ symbol_rate ,3,’- r ’) ; data_I_Q_rx_VHDL = [data_out_SRRCxN_rx_I_VHDL’ data_out_SRRCxN_rx_Q_VHDL’]; % scatterplot del segnale ricevuto % scatterplot ( data_I_Q_rx_VHDL , SpS , 3) ; % viene effettuato uno sfasamento , una decimazione ed applicato il decisore offset_demodmap = 1 ; symbols_VHDL = demodmap(data_I_Q_rx_VHDL , [symbol_rate offset_demodmap] ,... f_clk , ’qask’ , 4) ; % l ’ uscita del decisore viene convertita in formato NRZ for n = 1:length(symbols_VHDL) switch symbols_VHDL(n) case 0 symbols_I_VHDL(n) = 1 ; symbols_Q_VHDL(n) = 1 ; case 1 symbols_I_VHDL(n) = -1 ; symbols_Q_VHDL(n) = 1 ; case 2 symbols_I_VHDL(n) = 1 ; symbols_Q_VHDL(n) = -1 ; case 3 symbols_I_VHDL(n) = -1 ; symbols_Q_VHDL(n) = -1 ; end end % si passa dalla codifica NRZ alla codifica RZ bit_rx_I_VHDL = ( symbols_I_VHDL - 1) / (-2) ; bit_rx_Q_VHDL = ( symbols_Q_VHDL - 1) / (-2) ; % dai simboli si riottiene la sequenza composta da bit I e Q alternati bit_rx_VHDL = 4*ones(1 , n_bits_tx) ; bit_rx_VHDL(1 : 2 : n_bits_tx) = bit_rx_I_VHDL ; bit_rx_VHDL(2 : 2 : n_bits_tx) = bit_rx_Q_VHDL ; % viene compensato lo sfasamento tra la sequenza trasmessa e quella ricevuta N_bit_sfasamento_VHDL = 16 ; [n_bit_errati_VHDL BER_VHDL] = ... biterr(bit_tx(1:(n_bits_tx - N_bit_sfasamento_VHDL)) , ... bit_rx_VHDL( (N_bit_sfasamento_VHDL + 1):n_bits_tx)’) ; disp([’ Risultati Modulatore VHDL -> Demodulatore Matlab ’]); disp([’N◦ di bit di sfasamento : ’ num2str(N_bit_sfasamento_VHDL)]); ◦ disp([’N di bit errati : ’ num2str(n_bit_errati_VHDL)]); disp([’BER : ’ num2str(BER_VHDL)]); % viene calcolato il valore dello sfasamento per il quale si ha la minore BER for N_bit_sfasamento_VHDL = 1:1:30 [n_bit_errati_VHDL(N_bit_sfasamento_VHDL) BER_VHDL(N_bit_sfasamento_VHDL)]... = biterr(bit_tx(1:(n_bits_tx - N_bit_sfasamento_VHDL)) , ... bit_rx_VHDL( (N_bit_sfasamento_VHDL + 1):n_bits_tx)’); disp(’ ’); disp([’N◦ di bit di sfasamento : ’ num2str(N_bit_sfasamento_VHDL)]); disp([’N◦ di bit errati : ’ ... num2str(n_bit_errati_VHDL(N_bit_sfasamento_VHDL))]); disp([’BER : ’ num2str(BER_VHDL(N_bit_sfasamento_VHDL))]); end [ber_VHDL , N_bit_sfasamento_VHDL] = min(BER_VHDL) ; APPENDICE E. LISTATI MATLAB 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 disp(’ ’); disp(’ ’); disp([’BER minima : ’num2str(ber_VHDL)]); disp([’N◦ di bit errati : ’num2str(n_bit_errati_VHDL(N_bit_sfasamento_VHDL))]); disp([’Sfasamento : ’num2str(N_bit_sfasamento_VHDL)]); % Visualizza il valore teorico per il BER theoretical_BER = 0.5 .* erfc(sqrt(EbNo)) ; disp(’ ’); disp([’BER teorico : ’ num2str(theoretical_BER)]); disp(’ ’); % **************************************************************************** % *************************** CONFRONTO MODULATORI ************************* % **************************************************************************** %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CONFRONTO SPETTRALE %%%%%%%%%%%%%%%%%%%%%%%%%% % visualizzazione contemporanea dei due spettri figure ; plot(f_out , Pyy_Mod_Matlab_dB - max(Pyy_Mod_Matlab_dB),... ’-b’ , f_out , Pyy_Mod_VHDL_dB - max(Pyy_Mod_VHDL_dB) , ’-r’); grid ; xlim([0 f_clk/2]) ; ylim([-60 0]); legend([’Out QPSK Modem Matlab ’ , num2str(2*symbol_rate/1e6) , ’ MbpS’ ],... [’Out QPSK Modem VHDL ’,tipo_simulazione,num2str(2*symbol_rate/1e6),... ’ MbpS’ ] , 3); xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CONFRONTO TEMPORALE %%%%%%%%%%%%%%%%%%%%%%%%%% % n_bits = 1000; % N_bit_sfasamento = 7 ; % [ data_out_QPSK_Mod_Matlab (1:( n_bits - N_bit_sfasamento ) ) ’ , ... % data_out_QPSK_Mod_VHDL (( N_bit_sfasamento +1) : n_bits ) ] Listato E.4.5: applica polifase.m vedi listato(E.3.2) Test FPGA Listato E.4.6: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 QPSKModemPSDFPGAvsPSDMatlab.m % DESCRIPTION : Confronta lo spettro della sequenza modulata tramite il VHDL % con quello della sequenza modulata tramite Matlab % Pulizia ambiente Matlab clear all ; close all ; clc ; % ************** IMPOSTAZIONE CARATTERISTICHE DEL MODULATORE ************* % vengono impostate le caratteristiche del modulatore prompt = {’Frequenza di clock :’, ’Symbol Rate :’, ’N◦ di bit dopo la virgola :’, ’N◦ di campioni da considerare :’}; title = ’Caratteristiche del modulatore’; def = {’40’, ’40/3’, ’11’,’18000’}; answer = inputdlg(prompt, title, 1, def) ; f_clk = str2double(answer(1))*10^6; symbol_rate = eval( char(answer(2)) )*10^6; n_bit_dopo_virgola = str2double(answer(3)); n_values = str2double(answer(4)); % viene determinato il valore dell ’ interpolazione SpS = f_clk / symbol_rate ; % ********* VIENE APPLICATA LA MODULAZIONE QPSK MATLAB DI RIFERIMENTO ****** % carica da file la sequenza dei dati da filtrare sul ramo I fid = fopen(’data_in_SRRCxN_tx_I_nrz.dat’ , ’r’) ; data_in_SRRCxN_tx_I = fscanf(fid,’%f’) ; fclose(fid) ; % carica da file la sequenza dei dati da filtrare sul ramo Q fid = fopen(’data_in_SRRCxN_tx_Q_nrz.dat’ , ’r’) ; data_in_SRRCxN_tx_Q = fscanf(fid,’%f’) ; fclose(fid) ; 112 APPENDICE E. LISTATI MATLAB 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 113 % carica da file i coefficienti del filtro polifase fid = fopen( strcat(’SRRCx’, num2str(SpS), ’_FreqSampl_scaled.dat’),’r’); num_fir = fscanf(fid,’%f’) ; num_fir = num_fir’ ; fclose(fid) ; % applica il filtraggio polifase Matlab data_out_SRRCxN_tx_I = applica_polifase(data_in_SRRCxN_tx_I, SpS , num_fir); data_out_SRRCxN_tx_Q = applica_polifase(data_in_SRRCxN_tx_Q, SpS , num_fir); % Vengono generati i campioni di seno e coseno considerando che f_IF = f_clk /4 % n◦ di campioni da generare per le portanti n_sample = length(data_out_SRRCxN_tx_I) ; % periodo di campionamento t_clk = 1 / f_clk ; % istanti di campionamento t = 0 : t_clk : (n_sample-1)*t_clk ; % incrementi di fase per generare 41.25 MHz theta = 2*pi*(f_clk/4)*t ; % generazione del coseno coseno = [cos(theta)] ; % generazione del seno seno = [sin(theta)] ; data_out_QPSK_modulator = [coseno .* data_out_SRRCxN_tx_I] - ... [seno .* data_out_SRRCxN_tx_Q] ; % viene calcolata e plottata la densità spettrale di potenza [Pyy_Matlab , f_out] = pwelch(data_out_QPSK_modulator, [] , [] , ... ’onesided’, length(data_out_QPSK_modulator) - 1 , f_clk) ; Pyy_dB_Matlab = 10*log10(Pyy_Matlab) ; figure ; plot(f_out , Pyy_dB_Matlab - max(Pyy_dB_Matlab) ); grid ; xlim([0 f_clk/2]) ; ylim([-60 0]); legend([’Out QPSK Modem Matlab ’ , num2str(2*symbol_rate/1e6) , ’ MbpS’], 3); xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); % **************** VIENE APPLICATA LA MODULAZIONE QPSK VHDL ************** % ************ ELABORAZIONE DELLA SEQUENZA FILTRATA DALL ’ FPGA ************ % carica la sequenza proveniente dall ’ analizzatore di stati logici fid = fopen(’file_out.txt’ , ’r’); % vengono scartate le prime 7 stringhe string_unuseful = fscanf(fid, ’%s’ , 7); % viene prelevata la stringa che indica il formato formato = fscanf(fid, ’%s’ , 1) ; % viene scartata una stringa con tutti string_unuseful = fscanf(fid, ’%s’ , 1); % i dati vengono letti dal file nel giusto formato switch(formato) case ’Hex’, value_int_C2 = fscanf(fid, ’%x’ , n_values) ; case ’Decimal’, value_int_C2 = fscanf(fid, ’%f’ , n_values) ; end fclose(fid) ; % converte l ’ intero unsigned in complemento a due in un intero con segno value_int = zeros(n_values,1); for i = 1 : 1 : n_values if bitget( value_int_C2(i) , 12) == 1 % valore negativo % x_C2 = 2^ N - | x | value_int(i) = -( 2^(n_bit_dopo_virgola+1) - value_int_C2(i) ); else % coefficiente positivo value_int(i) = value_int_C2(i) ; % x_C2 = | x | end end % converte da intero con segno a numero reale con segno value_real = value_int .* 2^(- n_bit_dopo_virgola); data_out_QPSK_modulator_FPGA = value_real ; % viene calcolato lo spettro della sequenza modulata dal VHDL [Pyy_FPGA , f_out] = pwelch(data_out_QPSK_modulator_FPGA, [] , [] , ... ’onesided’, length(data_out_QPSK_modulator_FPGA) - 1 , f_clk) ; Pyy_dB_FPGA = 10*log10(Pyy_FPGA) ; figure ; plot(f_out , Pyy_dB_FPGA - max(Pyy_dB_FPGA) , ’-r’) ; grid ; xlim([0 f_clk/2]) ; ylim([-60 0]) ; legend([’Out QPSK Modem FPGA ’ , num2str(symbol_rate*2/1e6) , ’ MbpS’], 3) ; xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); % *************************** CONFRONTO SPETTRALE ************************* % visualizzazione contemporanea dei due spettri figure ; plot(f_out , Pyy_dB_Matlab - max(Pyy_dB_Matlab),’-b’,... f_out , Pyy_dB_FPGA - max(Pyy_dB_FPGA) , ’-r’); grid ; xlim([0 f_clk/2]) ; ylim([-60 0]); legend([’Out QPSK Modem Matlab ’ , num2str(symbol_rate*2/1e6) , ’ MbpS’ ] , ... [’Out QPSK Modem FPGA ’ , num2str(symbol_rate*2/1e6) , ’ MbpS’ ] , 3); xlabel(’Frequency (Hz)’); ylabel(’dB / Hz’); % **************************** CONFRONTO TEMPORALE ************************ % n_bits = length ( data_out_QPSK_modulator ) ; % n_bits = 12000; % N_bit_sfasamento = 0 ; % [ data_out_QPSK_modulator (1:( n_bits - N_bit_sfasamento ) ) ’ , ... % data_out_QPSK_modulator_FPGA (( N_bit_sfasamento +1) : n_bits ) ] APPENDICE E. LISTATI MATLAB Listato E.4.7: applica polifase.m vedi listato(E.3.2) 114 Appendice F Listati VHDL Listato F.1.1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 nco.vhd library IEEE; use IEEE.std_logic_1164.all; entity NCO is port( clear : in STD_LOGIC; clk : in STD_LOGIC; load : in STD_LOGIC; freq_word : in STD_LOGIC_VECTOR (31 downto 0); coseno : out STD_LOGIC_VECTOR (11 downto 0); seno : out STD_LOGIC_VECTOR (11 downto 0) ); end NCO; architecture NCO of NCO is ---- Signal declarations used on the diagram ---signal COS : STD_LOGIC_VECTOR (11 downto 0); signal CTRL : STD_LOGIC_VECTOR (1 downto 0); signal CTRL_SEGNO_SENO : STD_LOGIC ; signal FASE : STD_LOGIC_VECTOR (12 downto 0); signal SIN : STD_LOGIC_VECTOR (11 downto 0); signal THETA : STD_LOGIC_VECTOR (31 downto 0); signal THETA_TR : STD_LOGIC_VECTOR (12 downto 0); ---- Component declarations ----component ACCUMULATOR port ( clear : in STD_LOGIC; clk : in STD_LOGIC; freq_word : in STD_LOGIC_VECTOR (31 downto 0); load : in STD_LOGIC; theta : inout STD_LOGIC_VECTOR (31 downto 0) ); end component ; component CORDIC_PIPELINED_UNROLLED port ( clk : in STD_LOGIC; fase : in STD_LOGIC_VECTOR (12 downto 0); coseno : out STD_LOGIC_VECTOR (11 downto 0); seno : out STD_LOGIC_VECTOR (11 downto 0) ); end component ; component COSINE_REBUILD port ( ctrl : in STD_LOGIC_VECTOR (1 downto 0); in_cosine_rebuild : in STD_LOGIC_VECTOR (11 downto 0); out_cosine_rebuild : out STD_LOGIC_VECTOR (11 downto 0) ); end component ; component DELAY_13 port ( clk : in STD_LOGIC; in_delay_13 : in STD_LOGIC; out_delay_13 : out STD_LOGIC ); end component ; component SINE_REBUILD port ( ctrl : in STD_LOGIC; in_sine_rebuild : in STD_LOGIC_VECTOR (11 downto 0); out_sine_rebuild : out STD_LOGIC_VECTOR (11 downto 0) ); 115 APPENDICE F. LISTATI VHDL 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 end component ; component TO_FIRST_QUADRANT port ( in_tfq : in STD_LOGIC_VECTOR (12 downto 0); out_tfq : out STD_LOGIC_VECTOR (12 downto 0) ); end component ; component TRONCATORE_12 port ( ingresso : in STD_LOGIC_VECTOR (31 downto 0); uscita : out STD_LOGIC_VECTOR (12 downto 0) ); end component ; begin ---- Component instantiations ---U0 : CORDIC_PIPELINED_UNROLLED port map( clk => clk, coseno => cos, fase => fase, seno => sin ); U1 : DELAY_13 port map( clk => clk, in_delay_13 => Theta_tr(11), out_delay_13 => ctrl(0) ); U2 : DELAY_13 port map( clk => clk, in_delay_13 => Theta_tr(12), out_delay_13 => ctrl(1) ); U3 : DELAY_13 port map( clk => clk, in_delay_13 => Theta_tr(12), out_delay_13 => ctrl_segno_seno ); U5 : TRONCATORE_12 port map( ingresso => Theta, uscita => Theta_tr ); U4 : ACCUMULATOR port map( clear => clear, clk => clk, freq_word => freq_word, load => load, theta => Theta ); U6 : TO_FIRST_QUADRANT port map( in_tfq => Theta_tr, out_tfq => fase ); U8 : COSINE_REBUILD port map( ctrl => ctrl, in_cosine_rebuild => cos, out_cosine_rebuild => coseno ); U7 : SINE_REBUILD port map( ctrl => ctrl_segno_seno, in_sine_rebuild => sin, out_sine_rebuild => seno ); end NCO; Listato F.1.2: 1 2 3 4 5 6 7 8 9 10 11 12 13 116 accumulator.vhd library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_signed.all; entity accumulator is port ( freq_word : in std_logic_vector(31 downto 0); clk, load, clear : in std_logic; theta : inout std_logic_vector(31 downto 0) ); end accumulator; architecture acc_arch of accumulator is APPENDICE F. LISTATI VHDL signal reg_theta : std_logic_vector(31 downto 0); begin process(load, clear, freq_word, theta) begin if load=’1’ then reg_theta <= freq_word; else if clear=’1’ then reg_theta <= "00000000000000000000000000000000"; else reg_theta <= freq_word + theta; end if; end if; end process; 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 process(clk) begin if clk’event and clk=’1’ then theta <= reg_theta; end if; end process; end acc_arch; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 library IEEE; use IEEE.std_logic_1164.all; entity cordic_pipelined_unrolled is port( clk : in STD_LOGIC; fase : in STD_LOGIC_VECTOR (12 downto 0); coseno : out STD_LOGIC_VECTOR (11 downto 0); seno : out STD_LOGIC_VECTOR (11 downto 0) ); end cordic_pipelined_unrolled; architecture CORDIC_PIPELINED_UNROLLED of cordic_pipelined_unrolled is signal A_0 : STD_LOGIC_VECTOR (12 downto 0); signal A_1 : STD_LOGIC_VECTOR (12 downto 0); signal A_10 : STD_LOGIC_VECTOR (12 downto 0); signal A_11 : STD_LOGIC_VECTOR (12 downto 0); signal A_12 : STD_LOGIC_VECTOR (12 downto 0); signal A_2 : STD_LOGIC_VECTOR (12 downto 0); signal A_3 : STD_LOGIC_VECTOR (12 downto 0); signal A_4 : STD_LOGIC_VECTOR (12 downto 0); signal A_5 : STD_LOGIC_VECTOR (12 downto 0); signal A_6 : STD_LOGIC_VECTOR (12 downto 0); signal A_7 : STD_LOGIC_VECTOR (12 downto 0); signal A_8 : STD_LOGIC_VECTOR (12 downto 0); signal A_9 : STD_LOGIC_VECTOR (12 downto 0); signal X0 : STD_LOGIC_VECTOR (11 downto 0); signal X1 : STD_LOGIC_VECTOR (11 downto 0); signal X10 : STD_LOGIC_VECTOR (11 downto 0); signal X11 : STD_LOGIC_VECTOR (11 downto 0); signal X12 : STD_LOGIC_VECTOR (11 downto 0); signal X13 : STD_LOGIC_VECTOR (11 downto 0); signal X2 : STD_LOGIC_VECTOR (11 downto 0); signal X3 : STD_LOGIC_VECTOR (11 downto 0); signal X4 : STD_LOGIC_VECTOR (11 downto 0); signal X5 : STD_LOGIC_VECTOR (11 downto 0); signal X6 : STD_LOGIC_VECTOR (11 downto 0); signal X7 : STD_LOGIC_VECTOR (11 downto 0); signal X8 : STD_LOGIC_VECTOR (11 downto 0); signal X9 : STD_LOGIC_VECTOR (11 downto 0); signal Y0 : STD_LOGIC_VECTOR (11 downto 0); signal Y1 : STD_LOGIC_VECTOR (11 downto 0); signal Y10 : STD_LOGIC_VECTOR (11 downto 0); signal Y11 : STD_LOGIC_VECTOR (11 downto 0); signal Y12 : STD_LOGIC_VECTOR (11 downto 0); signal Y13 : STD_LOGIC_VECTOR (11 downto 0); signal Y2 : STD_LOGIC_VECTOR (11 downto 0); signal Y3 : STD_LOGIC_VECTOR (11 downto 0); signal Y4 : STD_LOGIC_VECTOR (11 downto 0); signal Y5 : STD_LOGIC_VECTOR (11 downto 0); signal Y6 : STD_LOGIC_VECTOR (11 downto 0); signal Y7 : STD_LOGIC_VECTOR (11 downto 0); signal Y8 : STD_LOGIC_VECTOR (11 downto 0); signal Y9 : STD_LOGIC_VECTOR (11 downto 0); signal Z0 : STD_LOGIC_VECTOR (12 downto 0); signal Z1 : STD_LOGIC_VECTOR (12 downto 0); signal Z10 : STD_LOGIC_VECTOR (12 downto 0); signal Z11 : STD_LOGIC_VECTOR (12 downto 0); signal Z12 : STD_LOGIC_VECTOR (12 downto 0); signal Z2 : STD_LOGIC_VECTOR (12 downto 0); signal Z3 : STD_LOGIC_VECTOR (12 downto 0); signal Z4 : STD_LOGIC_VECTOR (12 downto 0); Listato F.1.3: cordic pipelined unrolled.vhd 117 APPENDICE F. LISTATI VHDL 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 signal Z5 : STD_LOGIC_VECTOR (12 downto 0); signal Z6 : STD_LOGIC_VECTOR (12 downto 0); signal Z7 : STD_LOGIC_VECTOR (12 downto 0); signal Z8 : STD_LOGIC_VECTOR (12 downto 0); signal Z9 : STD_LOGIC_VECTOR (12 downto 0); ---- Component declarations ----component CORDIC_BASE_J generic( n : INTEGER ); port ( a_cost_j : in STD_LOGIC_VECTOR (12 downto 0); clk : in STD_LOGIC; in_x : in STD_LOGIC_VECTOR (11 downto 0); in_y : in STD_LOGIC_VECTOR (11 downto 0); in_z : in STD_LOGIC_VECTOR (12 downto 0); coseno : out STD_LOGIC_VECTOR (11 downto 0); fase_j : out STD_LOGIC_VECTOR (12 downto 0); seno : out STD_LOGIC_VECTOR (11 downto 0) ); end component ; begin x0 <= "010011011100" ; y0 <= "000000000000" ; a_0 <= "0010000000000" ; a_1 <= "0001001011100" ; a_2 <= "0000100111111" ; a_3 <= "0000010100010" ; a_4 <= "0000001010001" ; a_5 <= "0000000101000" ; a_6 <= "0000000010100" ; a_7 <= "0000000001010" ; a_8 <= "0000000000101" ; a_9 <= "0000000000010" ; a_10 <= "0000000000001" ; a_11 <= "0000000000000" ; a_12 <= "0000000000000" ; ---- Component instantiations ---U0 : CORDIC_BASE_J generic map ( n => 0 ) port map( a_cost_j => a_0, clk => clk, coseno => x1, fase_j => z1, in_x => x0, in_y => y0, in_z => z0, seno => y1 ); U1 : CORDIC_BASE_J generic map ( n => 1 ) port map( a_cost_j => a_1, clk => clk, coseno => x2, fase_j => z2, in_x => x1, in_y => y1, in_z => z1, seno => y2 ); U2 : CORDIC_BASE_J generic map ( n => 2 ) port map( a_cost_j => a_2, clk => clk, coseno => x3, fase_j => z3, in_x => x2, in_y => y2, in_z => z2, seno => y3 ); U3 : CORDIC_BASE_J generic map ( n => 3 ) port map( a_cost_j => a_3, clk => clk, coseno => x4, fase_j => z4, in_x => x3, in_y => y3, in_z => z3, seno => y4 ); U4 : CORDIC_BASE_J generic map ( n => 4 ) port map( a_cost_j => a_4, clk => clk, coseno => x5, fase_j => z5, in_x => x4, in_y => y4, in_z => z4, 118 APPENDICE F. LISTATI VHDL 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 seno => y5 ); U5 : CORDIC_BASE_J generic map ( n => 5 ) port map( a_cost_j => a_5, clk => clk, coseno => x6, fase_j => z6, in_x => x5, in_y => y5, in_z => z5, seno => y6 ); U6 : CORDIC_BASE_J generic map ( n => 6 ) port map( a_cost_j => a_6, clk => clk, coseno => x7, fase_j => z7, in_x => x6, in_y => y6, in_z => z6, seno => y7 ); U7 : CORDIC_BASE_J generic map ( n => 7 ) port map( a_cost_j => a_7, clk => clk, coseno => x8, fase_j => z8, in_x => x7, in_y => y7, in_z => z7, seno => y8 ); U8 : CORDIC_BASE_J generic map ( n => 8 ) port map( a_cost_j => a_8, clk => clk, coseno => x9, fase_j => z9, in_x => x8, in_y => y8, in_z => z8, seno => y9 ); U9 : CORDIC_BASE_J generic map ( n => 9 ) port map( a_cost_j => a_9, clk => clk, coseno => x10, fase_j => z10, in_x => x9, in_y => y9, in_z => z9, seno => y10 ); U10 : CORDIC_BASE_J generic map ( n => 10 ) port map( a_cost_j => a_10, clk => clk, coseno => x11, fase_j => z11, in_x => x10, in_y => y10, in_z => z10, seno => y11 ); U11 : CORDIC_BASE_J generic map ( n => 11 ) port map( a_cost_j => a_11, clk => clk, coseno => x12, fase_j => z12, in_x => x11, in_y => y11, in_z => z11, seno => y12 ); U12 : CORDIC_BASE_J generic map ( n => 12 ) port map( a_cost_j => a_12, clk => clk, coseno => x13, in_x => x12, in_y => y12, in_z => z12, 119 APPENDICE F. LISTATI VHDL 253 254 255 256 257 258 seno => y13 ); z0 <= FASE; COSENO <= x13; SENO <= y13; end CORDIC_PIPELINED_UNROLLED; Listato F.1.4: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 120 cordic base j.vhd library IEEE; use IEEE.std_logic_1164.all; entity cordic_base_j is generic( n : integer ); port( clk : in STD_LOGIC; a_cost_j : in STD_LOGIC_VECTOR (12 downto 0); in_x : in STD_LOGIC_VECTOR (11 downto 0); in_y : in STD_LOGIC_VECTOR (11 downto 0); in_z : in STD_LOGIC_VECTOR (12 downto 0); coseno : out STD_LOGIC_VECTOR (11 downto 0); fase_j : out STD_LOGIC_VECTOR (12 downto 0); seno : out STD_LOGIC_VECTOR (11 downto 0) ); end cordic_base_j; architecture CORDIC_BASE_J of cordic_base_j is signal SGN : STD_LOGIC ; signal SHIFTER_TO_ADDER_X : STD_LOGIC_VECTOR (11 downto 0); signal SHIFTER_TO_ADDER_Y : STD_LOGIC_VECTOR (11 downto 0); signal X_OUT_REG : STD_LOGIC_VECTOR (11 downto 0); signal Y_OUT_REG : STD_LOGIC_VECTOR (11 downto 0); signal Z_OUT_REG : STD_LOGIC_VECTOR (12 downto 0); component ADDER_12 port ( in_a : in STD_LOGIC_VECTOR (11 downto 0); in_b : in STD_LOGIC_VECTOR (11 downto 0); sgn : in STD_LOGIC; out_adder_12 : out STD_LOGIC_VECTOR (11 downto 0) ); end component ; component ADDER_13 port ( in_a : in STD_LOGIC_VECTOR (12 downto 0); in_b : in STD_LOGIC_VECTOR (12 downto 0); sgn : in STD_LOGIC; out_adder_13 : out STD_LOGIC_VECTOR (12 downto 0) ); end component ; component REG_12 port ( clk : in STD_LOGIC; in_reg_12 : in STD_LOGIC_VECTOR (11 downto 0); out_reg_12 : out STD_LOGIC_VECTOR (11 downto 0) ); end component ; component REG_13 port ( clk : in STD_LOGIC; in_reg_13 : in STD_LOGIC_VECTOR (12 downto 0); out_reg_13 : out STD_LOGIC_VECTOR (12 downto 0) ); end component ; component SHIFTER generic( n : INTEGER ); port ( in_shifter : in STD_LOGIC_VECTOR (11 downto 0); out_shifter : out STD_LOGIC_VECTOR (11 downto 0) ); end component ; begin sgn <= not(z_out_reg(12)) ; U0 : REG_12 port map( clk => clk, in_reg_12 => in_x, out_reg_12 => x_out_reg ); U1 : REG_12 port map( clk => clk, in_reg_12 => in_y, out_reg_12 => y_out_reg ); U2 : SHIFTER generic map ( n => n ) APPENDICE F. LISTATI VHDL 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 121 port map( in_shifter => x_out_reg, out_shifter => shifter_to_adder_y ); U4 : ADDER_12 port map( in_a => x_out_reg, in_b => shifter_to_adder_x, out_adder_12 => coseno, sgn => z_out_reg(12) ); U5 : ADDER_12 port map( in_a => y_out_reg, in_b => shifter_to_adder_y, out_adder_12 => seno, sgn => sgn ); U7 : ADDER_13 port map( in_a => z_out_reg, in_b => a_cost_j, out_adder_13 => fase_j, sgn => z_out_reg(12) ); U6 : REG_13 port map( clk => clk, in_reg_13 => in_z, out_reg_13 => z_out_reg ); U3 : SHIFTER generic map ( n => n ) port map( in_shifter => y_out_reg, out_shifter => shifter_to_adder_x ); end CORDIC_BASE_J; Listato F.1.5: adder 12.vhd 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_signed.all; entity adder_12 is port(in_a , in_b : in std_logic_vector(11 downto 0); sgn : in std_logic; out_adder_12 : out std_logic_vector(11 downto 0)); end adder_12; architecture adder_12_arch of adder_12 is begin process(in_a , in_b , sgn) begin if sgn = ’0’ then out_adder_12 <= in_a - in_b ; else out_adder_12 <= in_a + in_b ; end if; end process; end adder_12_arch; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_signed.all; entity adder_13 is port(in_a , in_b : in std_logic_vector(12 downto 0); sgn : in std_logic; out_adder_13 : out std_logic_vector(12 downto 0)); end adder_13; architecture adder_13_arch of adder_13 is begin process(in_a , in_b , sgn) begin if sgn = ’0’ then out_adder_13 <= in_a - in_b ; else out_adder_13 <= in_a + in_b ; end if; Listato F.1.6: adder 13.vhd APPENDICE F. LISTATI VHDL 122 20 21 end process; end adder_13_arch ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 library ieee; use ieee.std_logic_1164.all; entity reg_12 is port( in_reg_12 : in std_logic_vector(11 downto 0); clk : in std_logic; out_reg_12 : out std_logic_vector(11 downto 0)); end reg_12; architecture reg_12_arch of reg_12 is begin process(clk , in_reg_12) begin if rising_edge(clk) then out_reg_12 <= in_reg_12; end if; end process; end reg_12_arch ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 library ieee; use ieee.std_logic_1164.all; entity reg_13 is port( in_reg_13 : in std_logic_vector(12 downto 0); clk : in std_logic; out_reg_13 : out std_logic_vector(12 downto 0) ); end reg_13; architecture reg_13_arch of reg_13 is begin process(clk , in_reg_13) begin if rising_edge(clk) then out_reg_13 <= in_reg_13; end if; end process; end reg_13_arch ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 library ieee; use ieee.std_logic_1164.all; entity shifter is generic(n:integer); port( in_shifter : in std_logic_vector(11 downto 0); out_shifter : out std_logic_vector(11 downto 0)); end shifter; architecture shifter_arch of shifter is begin process(in_shifter) variable i:integer; begin if n < 12 then out_shifter(11-n downto 0) <= in_shifter(11 downto n); for i in 11 downto (11-n) loop if in_shifter(11)=’0’ then out_shifter(11 downto 11-n) <= ( others=>’0’); else out_shifter(11 downto 11-n) <= ( others=>’1’); end if; end loop; else out_shifter <= "000000000000" ; end if; end process; Listato F.1.7: Listato F.1.8: Listato F.1.9: 17 18 19 20 21 22 23 24 25 26 reg 12.vhd reg 13.vhd shifter.vhd APPENDICE F. LISTATI VHDL 123 27 end shifter_arch ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 21 22 23 24 25 26 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_signed.all; entity cosine_rebuild is port( in_cosine_rebuild : in std_logic_vector(11 downto 0); ctrl : in std_logic_vector(1 downto 0); out_cosine_rebuild : out std_logic_vector(11 downto 0)); end cosine_rebuild ; architecture cosine_rebuild_arch of cosine_rebuild is begin process(in_cosine_rebuild, ctrl) variable temp : std_logic_vector(11 downto 0); begin temp(11 downto 0) := in_cosine_rebuild ; case ctrl is when "00" => null ; -- primo quadrante when "01" => temp := ("111111111111" xor temp)+1; -- secondo quadrante when "10" => temp := ("111111111111" xor temp)+1; -- terzo quadrante when "11" => null ; -- quarto quadrante when others => temp := "000000000000" ; end case; out_cosine_rebuild(11 downto 0) <= temp(11 downto 0) ; end process; end cosine_rebuild_arch ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 library IEEE; use IEEE.STD_LOGIC_1164.all; entity delay_13 is port ( clk : in STD_LOGIC; in_delay_13 : in STD_LOGIC; out_delay_13 : out STD_LOGIC ); end delay_13; architecture delay_13_arch of delay_13 is signal reg_int : STD_LOGIC_VECTOR(12 downto 0); begin process (clk) begin if clk’event and clk=’1’ then reg_int <= in_delay_13 & reg_int(12 downto 1); end if; end process; out_delay_13 <= reg_int(0); end delay_13_arch; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_signed.all; entity sine_rebuild is port( in_sine_rebuild : in std_logic_vector(11 downto 0); ctrl : in std_logic; out_sine_rebuild : out std_logic_vector(11 downto 0)); end sine_rebuild ; architecture sine_rebuild_arch of sine_rebuild is begin process(in_sine_rebuild, ctrl) variable temp : std_logic_vector(11 downto 0); begin temp(11 downto 0) := in_sine_rebuild ; case ctrl is Listato F.1.10: 20 Listato F.1.11: Listato F.1.12: cosine rebuild.vhd delay 13.vhd sine rebuild.vhd APPENDICE F. LISTATI VHDL 124 18 19 20 21 22 23 24 when ’1’ => temp := ("111111111111" xor temp)+1 ; when ’0’ => null ; when others => temp := "000000000000" ; end case; out_sine_rebuild(11 downto 0) <= temp(11 downto 0) ; end process; end sine_rebuild_arch ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_signed.all; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 library ieee; use ieee.std_logic_1164.all; entity troncatore_12 is port( ingresso : in std_logic_vector(31 downto 0); uscita : out std_logic_vector(12 downto 0) ); end troncatore_12; architecture tro_12_arch of troncatore_12 is begin process(ingresso) begin for i in 0 to 12 loop uscita(i) <= ingresso(i+19); end loop; end process; end tro_12_arch; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 library IEEE; use IEEE.std_logic_1164.all; use work.SRRC_coeffs.all; entity polyphase_gatedClock is port( clk : in STD_LOGIC; reset : in STD_LOGIC; to_SRRC_I : in STD_LOGIC; rate_sel : in STD_LOGIC_VECTOR(1 downto 0); clk_sync : out STD_LOGIC; poly_out : out STD_LOGIC_VECTOR(11 downto 0) ); end polyphase_gatedClock; architecture polyphase_gatedClock of polyphase_gatedClock is component rate_adapter port ( clk : in STD_LOGIC; rate_sel : in STD_LOGIC_VECTOR(1 downto 0); Listato F.1.13: to first quadrant.vhd entity to_first_quadrant is port( in_tfq : in std_logic_vector(12 downto 0); out_tfq : out std_logic_vector(12 downto 0)); end to_first_quadrant; architecture to_first_quadrant_arch of to_first_quadrant is begin process(in_tfq) variable temp : std_logic_vector(10 downto 0); begin temp(10 downto 0) := in_tfq(10 downto 0) ; case in_tfq(11) is when ’1’ => temp := ("11111111111" xor temp)+1 ; when ’0’ => null ; when others => temp := "00000000000" ; end case; out_tfq(10 downto 0) <= temp(10 downto 0) ; out_tfq(12 downto 11) <= "00" ; end process; end to_first_quadrant_arch ; Listato F.1.14: Listato F.2.1: troncatore 12.vhd polyphase gatedClock.vhd APPENDICE F. LISTATI VHDL 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 reset : in STD_LOGIC; clk_div_n : out STD_LOGIC; coeffs_to_SRRCxN : out coeffs; count_n : out STD_LOGIC_VECTOR(2 downto 0) ); end component; component srrc_x_n port ( SRRCxN_coeffs : in coeffs; clk : in STD_LOGIC; clk_div_n : in STD_LOGIC; count_n : in STD_LOGIC_VECTOR(2 downto 0); in_fir_MSB : in STD_LOGIC; reset : in STD_LOGIC; polyphase_out : out STD_LOGIC_VECTOR(11 downto 0) ); end component; signal clk_div_n : STD_LOGIC; signal coefficients : coeffs; signal count_n : STD_LOGIC_VECTOR (2 downto 0); begin U1 : srrc_x_n port map( SRRCxN_coeffs => coefficients, clk => clk, clk_div_n => clk_div_n, count_n => count_n, in_fir_MSB => to_SRRC_I, polyphase_out => poly_out, reset => reset ); U2 : rate_adapter port map( clk => clk, clk_div_n => clk_div_n, coeffs_to_SRRCxN => coefficients, count_n => count_n, rate_sel => rate_sel, reset => reset ); clk_sync <= clk; end polyphase_gatedClock; Listato F.2.2: 1 2 3 4 5 6 7 8 srrc coeffs.vhd library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_signed.all; package SRRC_coeffs is subtype coeff is std_logic_vector(11 downto 0); type coeffs is array(0 to 83) of coeff; end SRRC_coeffs ; Listato F.2.3: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 125 rate adapter.vhd library IEEE; use IEEE.std_logic_1164.all; use work.SRRC_coeffs.all; entity rate_adapter is port( clk : in STD_LOGIC; reset : in STD_LOGIC; rate_sel : in STD_LOGIC_VECTOR(1 downto 0); clk_div_n : out STD_LOGIC; coeffs_to_SRRCxN : out coeffs; count_n : out STD_LOGIC_VECTOR(2 downto 0) ); end rate_adapter; architecture rate_adapter of rate_adapter is component coeffs_selector port ( rate_sel : in STD_LOGIC_VECTOR(1 downto 0); coeffs_SRRC : out coeffs ); end component; component counter_divider_3 port ( clk : in STD_LOGIC; reset : in STD_LOGIC; APPENDICE F. LISTATI VHDL 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 clk_div_3 : out STD_LOGIC; count_3 : out STD_LOGIC_VECTOR(2 downto 0) ); end component; component counter_divider_4 port ( clk : in STD_LOGIC; reset : in STD_LOGIC; clk_div_4 : out STD_LOGIC; count_4 : out STD_LOGIC_VECTOR(2 downto 0) ); end component; component counter_divider_6 port ( clk : in STD_LOGIC; reset : in STD_LOGIC; clk_div_6 : out STD_LOGIC; count_6 : out STD_LOGIC_VECTOR(2 downto 0) ); end component; component selector port ( clk_div_3 : in STD_LOGIC; clk_div_4 : in STD_LOGIC; clk_div_6 : in STD_LOGIC; count_3 : in STD_LOGIC_VECTOR(2 downto 0); count_4 : in STD_LOGIC_VECTOR(2 downto 0); count_6 : in STD_LOGIC_VECTOR(2 downto 0); rate_sel : in STD_LOGIC_VECTOR(1 downto 0); clk_div_n : out STD_LOGIC; count_n : out STD_LOGIC_VECTOR(2 downto 0) ); end component; signal signal signal signal signal signal signal SRRC_coefficients : coeffs; to_clk_div_3 : STD_LOGIC; to_clk_div_4 : STD_LOGIC; to_clk_div_6 : STD_LOGIC; count_4 : STD_LOGIC_VECTOR (2 downto 0); to_count_3 : STD_LOGIC_VECTOR (2 downto 0); to_count_6 : STD_LOGIC_VECTOR (2 downto 0); begin U0 : counter_divider_3 port map( clk => clk, clk_div_3 => to_clk_div_3, count_3 => to_count_3, reset => reset ); U1 : counter_divider_4 port map( clk => clk, clk_div_4 => to_clk_div_4, count_4 => count_4, reset => reset ); U2 : counter_divider_6 port map( clk => clk, clk_div_6 => to_clk_div_6, count_6 => to_count_6, reset => reset ); U3 : selector port map( clk_div_3 => to_clk_div_3, clk_div_4 => to_clk_div_4, clk_div_6 => to_clk_div_6, clk_div_n => clk_div_n, count_3 => to_count_3, count_4 => count_4, count_6 => to_count_6, count_n => count_n, rate_sel => rate_sel ); U5 : coeffs_selector port map( coeffs_SRRC => SRRC_coefficients, rate_sel => rate_sel ); coeffs_to_SRRCxN <= SRRC_coefficients; end rate_adapter; Listato F.2.4: 1 2 3 126 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_signed.all; coeffs selector.vhd APPENDICE F. LISTATI VHDL 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 use work.SRRC_coeffs.all; entity coeffs_selector is port( rate_sel : in std_logic_vector(1 downto 0); coeffs_SRR : out coeffs ); end coeffs_selector; architecture coeffs_selector_arch of coeffs_selector is -- calcolati con campionamento in frequenza e scalati Constant coeffs_SRRCx3 : coeffs := coeffs’( -- coefficienti del FIR 1 coeff’(X"FE0") , -- 1 coeff’(X"020") , -- 1 inverted coeff’(X"03D") , -- 2 coeff’(X"FC3") , -- 2 inverted coeff’(X"F94") , -- 3 coeff’(X"06C") , -- 3 inverted coeff’(X"59E") , -- 4 coeff’(X"A62") , -- 4 inverted coeff’(X"F94") , -- 5 coeff’(X"06C") , -- 5 inverted coeff’(X"03D") , -- 6 coeff’(X"FC3") , -- 6 inverted coeff’(X"FE0") , -- 7 coeff’(X"020") , -- 7 inverted -- coefficienti del FIR 2 coeff’(X"00A") , -- 8 coeff’(X"FF6") , -- 8 inverted coeff’(X"FB0") , -- 9 coeff’(X"050") , -- 9 inverted coeff’(X"1B1") , -- 10 coeff’(X"E4F") , -- 10 inverted coeff’(X"461") , -- 11 coeff’(X"B9F") , -- 11 inverted coeff’(X"F19") , -- 12 coeff’(X"0E7") , -- 12 inverted coeff’(X"046") , -- 13 coeff’(X"FBA") , -- 13 inverted coeff’(X"000") , -- 14 coeff’(X"000") , -- 14 inverted -- coefficienti del FIR 3 coeff’(X"046") , -- 15 coeff’(X"FBA") , -- 15 inverted coeff’(X"F19") , -- 16 coeff’(X"0E7") , -- 16 inverted coeff’(X"461") , -- 17 coeff’(X"B9F") , -- 17 inverted coeff’(X"1B1") , -- 18 coeff’(X"E4F") , -- 18 inverted coeff’(X"FB0") , -- 19 coeff’(X"050") , -- 19 inverted coeff’(X"00A") , -- 20 coeff’(X"FF6") , -- 20 inverted coeff’(X"000") , -- 21 coeff’(X"000") , -- 21 inverted -- coefficienti del FIR 4 coeff’(X"000") , -- 22 coeff’(X"000") , -- 22 inverted coeff’(X"000") , -- 23 coeff’(X"000") , -- 23 inverted coeff’(X"000") , -- 24 coeff’(X"000") , -- 24 inverted coeff’(X"000") , -- 25 coeff’(X"000") , -- 25 inverted coeff’(X"000") , -- 26 coeff’(X"000") , -- 26 inverted coeff’(X"000") , -- 27 coeff’(X"000") , -- 27 inverted coeff’(X"000") , -- 28 coeff’(X"000") , -- 28 inverted -- coefficienti del FIR 5 coeff’(X"000") , -- 29 coeff’(X"000") , -- 29 inverted coeff’(X"000") , -- 30 coeff’(X"000") , -- 30 inverted coeff’(X"000") , -- 31 coeff’(X"000") , -- 31 inverted coeff’(X"000") , -- 32 coeff’(X"000") , -- 32 inverted coeff’(X"000") , -- 33 coeff’(X"000") , -- 33 inverted coeff’(X"000") , -- 34 coeff’(X"000") , -- 34 inverted coeff’(X"000") , -- 35 coeff’(X"000") , -- 35 inverted -- coefficienti del FIR 6 coeff’(X"000") , -- 36 coeff’(X"000") , -- 36 inverted 127 APPENDICE F. LISTATI VHDL 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 coeff’(X"000") , -- 37 coeff’(X"000") , -- 37 inverted coeff’(X"000") , -- 38 coeff’(X"000") , -- 38 inverted coeff’(X"000") , -- 39 coeff’(X"000") , -- 39 inverted coeff’(X"000") , -- 40 coeff’(X"000") , -- 40 inverted coeff’(X"000") , -- 41 coeff’(X"000") , -- 41 inverted coeff’(X"000") , -- 42 coeff’(X"000") -- 42 inverted ); -- calcolati con campionamento in frequenza e scalati Constant coeffs_SRRCx4 : coeffs := coeffs’( -- coefficienti del FIR 1 coeff’(X"FD8") , -- 1 coeff’(X"028") , -- 1 inverted coeff’(X"03D") , -- 2 coeff’(X"FC3") , -- 2 inverted coeff’(X"F9B") , -- 3 coeff’(X"065") , -- 3 inverted coeff’(X"55D") , -- 4 coeff’(X"AA3") , -- 4 inverted coeff’(X"F9B") , -- 5 coeff’(X"065") , -- 5 inverted coeff’(X"03D") , -- 6 coeff’(X"FC3") , -- 6 inverted coeff’(X"FD8") , -- 7 coeff’(X"028") , -- 7 inverted -- coefficienti del FIR 2 coeff’(X"FF9") , -- 8 coeff’(X"007") , -- 8 inverted coeff’(X"FDB") , -- 9 coeff’(X"025") , -- 9 inverted coeff’(X"104") , -- 10 coeff’(X"EFC") , -- 10 inverted coeff’(X"4AE") , -- 11 coeff’(X"B52") , -- 11 inverted coeff’(X"F1A") , -- 12 coeff’(X"0E6") , -- 12 inverted coeff’(X"051") , -- 13 coeff’(X"FAF") , -- 13 inverted coeff’(X"000") , -- 14 coeff’(X"000") , -- 14 inverted -- coefficienti del FIR 3 coeff’(X"02C") , -- 15 coeff’(X"FD4") , -- 15 inverted coeff’(X"F57") , -- 16 coeff’(X"0A9") , -- 16 inverted coeff’(X"2F7") , -- 17 coeff’(X"D09") , -- 17 inverted coeff’(X"2F7") , -- 18 coeff’(X"D09") , -- 18 inverted coeff’(X"F57") , -- 19 coeff’(X"0A9") , -- 19 inverted coeff’(X"02C") , -- 20 coeff’(X"FD4") , -- 20 inverted coeff’(X"000") , -- 21 coeff’(X"000") , -- 21 inverted -- coefficienti del FIR 4 coeff’(X"051") , -- 22 coeff’(X"FAF") , -- 22 inverted coeff’(X"F1A") , -- 23 coeff’(X"0E6") , -- 23 inverted coeff’(X"4AE") , -- 24 coeff’(X"B52") , -- 24 inverted coeff’(X"104") , -- 25 coeff’(X"EFC") , -- 25 inverted coeff’(X"FDB") , -- 26 coeff’(X"025") , -- 26 inverted coeff’(X"FF9") , -- 27 coeff’(X"007") , -- 27 inverted coeff’(X"000") , -- 28 coeff’(X"000") , -- 28 inverted -- coefficienti del FIR 5 coeff’(X"000") , -- 29 coeff’(X"000") , -- 29 inverted coeff’(X"000") , -- 30 coeff’(X"000") , -- 30 inverted coeff’(X"000") , -- 31 coeff’(X"000") , -- 31 inverted coeff’(X"000") , -- 32 coeff’(X"000") , -- 32 inverted coeff’(X"000") , -- 33 coeff’(X"000") , -- 33 inverted coeff’(X"000") , -- 34 coeff’(X"000") , -- 34 inverted coeff’(X"000") , -- 35 128 APPENDICE F. LISTATI VHDL 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 coeff’(X"000") , -- 35 inverted -- coefficienti coeff’(X"000") , -- 36 coeff’(X"000") , -- 36 inverted coeff’(X"000") , -- 37 coeff’(X"000") , -- 37 inverted coeff’(X"000") , -- 38 coeff’(X"000") , -- 38 inverted coeff’(X"000") , -- 39 coeff’(X"000") , -- 39 inverted coeff’(X"000") , -- 40 coeff’(X"000") , -- 40 inverted coeff’(X"000") , -- 41 coeff’(X"000") , -- 41 inverted coeff’(X"000") , -- 42 coeff’(X"000") -- 42 inverted ); -- calcolati con campionamento in Constant coeffs_SRRCx6 : coeffs -- coefficienti coeff’(X"FEB") , -- 1 coeff’(X"015") , -- 1 inverted coeff’(X"04A") , -- 2 coeff’(X"FB6") , -- 2 inverted coeff’(X"F25") , -- 3 coeff’(X"0DB") , -- 3 inverted coeff’(X"53D") , -- 4 coeff’(X"AC3") , -- 4 inverted coeff’(X"06E") , -- 5 coeff’(X"F92") , -- 5 inverted coeff’(X"00B") , -- 6 coeff’(X"FF5") , -- 6 inverted coeff’(X"FF5") , -- 7 coeff’(X"00B") , -- 7 inverted -- coefficienti coeff’(X"FED") , -- 8 coeff’(X"013") , -- 8 inverted coeff’(X"03D") , -- 9 coeff’(X"FC3") , -- 9 inverted coeff’(X"F91") , -- 10 coeff’(X"06F") , -- 10 inverted coeff’(X"591") , -- 11 coeff’(X"A6F") , -- 11 inverted coeff’(X"F91") , -- 12 coeff’(X"06F") , -- 12 inverted coeff’(X"03D") , -- 13 coeff’(X"FC3") , -- 13 inverted coeff’(X"FED") , -- 14 coeff’(X"013") , -- 14 inverted -- coefficienti coeff’(X"FF5") , -- 15 coeff’(X"00B") , -- 15 inverted coeff’(X"00B") , -- 16 coeff’(X"FF5") , -- 16 inverted coeff’(X"06E") , -- 17 coeff’(X"F92") , -- 17 inverted coeff’(X"53D") , -- 18 coeff’(X"AC3") , -- 18 inverted coeff’(X"F25") , -- 19 coeff’(X"0DB") , -- 19 inverted coeff’(X"04A") , -- 20 coeff’(X"FB6") , -- 20 inverted coeff’(X"FEB") , -- 21 coeff’(X"015") , -- 21 inverted -- coefficienti coeff’(X"006") , -- 22 coeff’(X"FFA") , -- 22 inverted coeff’(X"FB9") , -- 23 coeff’(X"047") , -- 23 inverted coeff’(X"1A7") , -- 24 coeff’(X"E59") , -- 24 inverted coeff’(X"455") , -- 25 coeff’(X"BAB") , -- 25 inverted coeff’(X"F1F") , -- 26 coeff’(X"0E1") , -- 26 inverted coeff’(X"03B") , -- 27 coeff’(X"FC5") , -- 27 inverted coeff’(X"000") , -- 28 coeff’(X"000") , -- 28 inverted -- coefficienti coeff’(X"020") , -- 29 coeff’(X"FE0") , -- 29 inverted coeff’(X"F5E") , -- 30 coeff’(X"0A2") , -- 30 inverted coeff’(X"30B") , -- 31 coeff’(X"CF5") , -- 31 inverted coeff’(X"30B") , -- 32 coeff’(X"CF5") , -- 32 inverted coeff’(X"F5E") , -- 33 129 del FIR 6 frequenza e scalati := coeffs’( del FIR 1 del FIR 2 del FIR 3 del FIR 4 del FIR 5 APPENDICE F. LISTATI VHDL 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 coeff’(X"0A2") coeff’(X"020") coeff’(X"FE0") coeff’(X"000") coeff’(X"000") , , , , , -- 33 inverted -- 34 -- 34 inverted -- 35 -- 35 inverted -- coefficienti del FIR 6 , -- 36 , -- 36 inverted , -- 37 , -- 37 inverted , -- 38 , -- 38 inverted , -- 39 , -- 39 inverted , -- 40 , -- 40 inverted , -- 41 , -- 41 inverted , -- 42 -- 42 inverted coeff’(X"03B") coeff’(X"FC5") coeff’(X"F1F") coeff’(X"0E1") coeff’(X"455") coeff’(X"BAB") coeff’(X"1A7") coeff’(X"E59") coeff’(X"FB9") coeff’(X"047") coeff’(X"006") coeff’(X"FFA") coeff’(X"000") coeff’(X"000") ); begin with rate_sel select coeffs_SRRC <= coeffs_SRRCx3 when "00" , coeffs_SRRCx4 when "01" , coeffs_SRRCx6 when others ; end coeffs_selector_arch; Listato F.2.5: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 entity counter_divider_3 is port ( clk : in STD_LOGIC; reset : in STD_LOGIC; count_3 : out STD_LOGIC_VECTOR (2 downto 0); clk_div_3 : out STD_LOGIC ); end counter_divider_3; architecture counter_divider_3_arch of counter_divider_3 is signal int_count_3 : STD_LOGIC_VECTOR (1 downto 0) ; signal count_0_delayed : STD_LOGIC; begin process (clk , reset) begin if reset=’1’ then int_count_3 <= "01"; elsif falling_edge(clk) then int_count_3 <= int_count_3(0)¬(int_count_3(0) or int_count_3(1)); end if; end process; process(clk) begin if rising_edge(clk) then count_0_delayed <= int_count_3(0); end if; end process; clk_div_3 <= int_count_3(0) nor count_0_delayed; process(clk) begin if falling_edge(clk) then count_3 <= ’0’ & int_count_3; end if; end process; end counter_divider_3_arch; Listato F.2.6: 1 2 3 4 5 6 7 counter divider 3.vhd library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; library IEEE; use IEEE.std_logic_1164.all; entity counter_divider_4 is port( clk : in STD_LOGIC; reset : in STD_LOGIC; counter divider 4.vhd 130 APPENDICE F. LISTATI VHDL 131 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 clk_div_4 : out STD_LOGIC; count_4 : out STD_LOGIC_VECTOR(2 downto 0) ); end counter_divider_4; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 library IEEE; use IEEE.std_logic_1164.all; entity fftr is port ( reset : in std_logic; clk : in std_logic; eing : in std_logic; aus : out std_logic ); end entity; architecture fftr_arch of fftr is signal TEMP_aus: std_logic; begin process (clk, reset) begin if reset = ’1’ then TEMP_aus <= ’0’; elsif falling_edge(clk) then if eing = ’1’ then TEMP_aus <= not TEMP_AUS; else null; end if; end if; end process; aus <= TEMP_aus; end architecture; architecture counter_divider_4 of counter_divider_4 is component fftr port ( clk : in STD_LOGIC; eing : in STD_LOGIC; reset : in STD_LOGIC; aus : out STD_LOGIC ); end component; constant VCC_CONSTANT : STD_LOGIC := ’1’; constant GND_CONSTANT : STD_LOGIC := ’0’; signal GND : STD_LOGIC; signal VCC : STD_LOGIC; signal aus : STD_LOGIC_VECTOR (2 downto 0); begin U1 : fftr port map( aus => aus(1), clk => clk, eing => aus(0), reset => reset ); U2 : fftr port map( aus => aus(0), clk => clk, eing => VCC, reset => reset ); VCC <= VCC_CONSTANT; GND <= GND_CONSTANT; aus(2) <= GND; clk_div_4 <= aus(1); count_4 <= aus; end counter_divider_4; Listato F.2.7: Listato F.2.8: 1 2 3 4 5 6 7 8 fftr.vhd counter divider 6.vhd library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; entity counter_divider_6 is port ( clk : in STD_LOGIC; reset : in STD_LOGIC; APPENDICE F. LISTATI VHDL 132 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 count_6 : out STD_LOGIC_VECTOR (2 downto 0); clk_div_6 : out STD_LOGIC ); end counter_divider_6; architecture counter_divider_6_arch of counter_divider_6 is begin process (clk, reset) variable count_6_interno : STD_LOGIC_VECTOR (2 downto 0); begin if reset=’1’ then count_6_interno := "000"; clk_div_6 <= ’0’ ; else if falling_edge(clk) then if count_6_interno < 5 then count_6_interno := count_6_interno + 1; if count_6_interno = 3 then clk_div_6 <= ’1’ ; else null; end if ; else count_6_interno := "000"; clk_div_6 <= ’0’ ; end if; end if; end if; count_6 <= count_6_interno; end process; end counter_divider_6_arch; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 library ieee; use ieee.std_logic_1164.all; 1 2 3 4 5 6 7 8 9 10 11 12 13 library IEEE; use IEEE.std_logic_1164.all; use work.SRRC_coeffs.all; entity SRRC_x_N is port( SRRCxN_coeffs : in coeffs; clk : in STD_LOGIC; clk_div_n : in STD_LOGIC; in_fir_MSB : in STD_LOGIC; reset : in STD_LOGIC; count_n : in STD_LOGIC_VECTOR(2 downto 0); polyphase_out : out STD_LOGIC_VECTOR(11 downto 0) Listato F.2.9: selector.vhd entity selector is port( rate_sel : in std_logic_vector( 1 downto 0); clk_div_3 : in std_logic ; count_3 : in std_logic_vector(2 downto 0); clk_div_4 : in std_logic ; count_4 : in std_logic_vector(2 downto 0); clk_div_6 : in std_logic ; count_6 : in std_logic_vector(2 downto 0); clk_div_n : out std_logic ; count_n : out std_logic_vector(2 downto 0) ); end selector; architecture selector_arch of selector is begin process (rate_sel,clk_div_3,clk_div_4,clk_div_6,count_3,count_4,count_6) begin case rate_sel is when "00" => clk_div_n <= clk_div_3 ; count_n <= count_3 ; when "01" => clk_div_n <= clk_div_4 ; count_n <= count_4 ; when "10" => clk_div_n <= clk_div_6 ; count_n <= count_6 ; when others => clk_div_n <= ’X’ ; count_n <= "XXX" ; end case; end process; end selector_arch; Listato F.2.10: srrc x n.vhd APPENDICE F. LISTATI VHDL 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 ); end SRRC_x_N; architecture SRRC_x_N of SRRC_x_N is component fir_1 port ( clk_div_n : in STD_LOGIC; coeff_a : in coeff; coeff_b : in coeff; coeff_c : in coeff; coeff_d : in coeff; coeff_e : in coeff; coeff_f : in coeff; coeff_g : in coeff; in_fir_MSB : in STD_LOGIC; n_coeff_a : in coeff; n_coeff_b : in coeff; n_coeff_c : in coeff; n_coeff_d : in coeff; n_coeff_e : in coeff; n_coeff_f : in coeff; n_coeff_g : in coeff; reset : in STD_LOGIC; out_fir : out STD_LOGIC_VECTOR(11 downto 0) ); end component; component mux_6 port ( clk : in STD_LOGIC; count_n : in STD_LOGIC_VECTOR(2 downto 0); in_0 : in STD_LOGIC_VECTOR(11 downto 0); in_1 : in STD_LOGIC_VECTOR(11 downto 0); in_2 : in STD_LOGIC_VECTOR(11 downto 0); in_3 : in STD_LOGIC_VECTOR(11 downto 0); in_4 : in STD_LOGIC_VECTOR(11 downto 0); in_5 : in STD_LOGIC_VECTOR(11 downto 0); out_mux : out STD_LOGIC_VECTOR(11 downto 0) ); end component; signal coeff_1 : coeff; signal coeff_2 : coeff; signal coeff_3 : coeff; signal coeff_4 : coeff; signal coeff_5 : coeff; signal coeff_6 : coeff; signal coeff_7 : coeff; signal coeff_8 : coeff; signal coeff_9 : coeff; signal coeff_10 : coeff; signal coeff_11 : coeff; signal coeff_12 : coeff; signal coeff_13 : coeff; signal coeff_14 : coeff; signal coeff_15 : coeff; signal coeff_16 : coeff; signal coeff_17 : coeff; signal coeff_18 : coeff; signal coeff_19 : coeff; signal coeff_20 : coeff; signal coeff_21 : coeff; signal coeff_22 : coeff; signal coeff_23 : coeff; signal coeff_24 : coeff; signal coeff_25 : coeff; signal coeff_26 : coeff; signal coeff_27 : coeff; signal coeff_28 : coeff; signal coeff_29 : coeff; signal coeff_30 : coeff; signal coeff_31 : coeff; signal coeff_32 : coeff; signal coeff_33 : coeff; signal coeff_34 : coeff; signal coeff_35 : coeff; signal coeff_36 : coeff; signal coeff_37 : coeff; signal coeff_38 : coeff; signal coeff_39 : coeff; signal coeff_40 : coeff; signal coeff_41 : coeff; signal coeff_42 : coeff; signal n_coeff_1 : coeff; signal n_coeff_2 : coeff; signal n_coeff_3 : coeff; signal n_coeff_4 : coeff; signal n_coeff_5 : coeff; signal n_coeff_6 : coeff; signal n_coeff_7 : coeff; signal n_coeff_8 : coeff; signal n_coeff_9 : coeff; signal n_coeff_10 : coeff; signal n_coeff_11 : coeff; signal n_coeff_12 : coeff; signal n_coeff_13 : coeff; signal n_coeff_14 : coeff; 133 APPENDICE F. LISTATI VHDL 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 signal signal signal signal signal signal signal signal signal signal signal signal signal signal signal signal signal signal signal signal signal signal signal signal signal signal signal signal n_coeff_15 n_coeff_16 n_coeff_17 n_coeff_18 n_coeff_19 n_coeff_20 n_coeff_21 n_coeff_22 n_coeff_23 n_coeff_24 n_coeff_25 n_coeff_26 n_coeff_27 n_coeff_28 n_coeff_29 n_coeff_30 n_coeff_31 n_coeff_32 n_coeff_33 n_coeff_34 n_coeff_35 n_coeff_36 n_coeff_37 n_coeff_38 n_coeff_39 n_coeff_40 n_coeff_41 n_coeff_42 : : : : : : : : : : : : : : : : : : : : : : : : : : : : 134 coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; coeff; signal to_in_0 : STD_LOGIC_VECTOR (11 signal to_in_1 : STD_LOGIC_VECTOR (11 signal to_in_2 : STD_LOGIC_VECTOR (11 signal to_in_3 : STD_LOGIC_VECTOR (11 signal to_in_4 : STD_LOGIC_VECTOR (11 signal to_in_5 : STD_LOGIC_VECTOR (11 begin coeff_1 <= SRRCxN_coeffs(0); n_coeff_1 <= SRRCxN_coeffs(1); coeff_2 <= SRRCxN_coeffs(2); n_coeff_2 <= SRRCxN_coeffs(3); coeff_3 <= SRRCxN_coeffs(4); n_coeff_3 <= SRRCxN_coeffs(5); coeff_4 <= SRRCxN_coeffs(6); n_coeff_4 <= SRRCxN_coeffs(7); coeff_5 <= SRRCxN_coeffs(8); n_coeff_5 <= SRRCxN_coeffs(9); coeff_6 <= SRRCxN_coeffs(10); n_coeff_6 <= SRRCxN_coeffs(11); coeff_7 <= SRRCxN_coeffs(12); n_coeff_7 <= SRRCxN_coeffs(13); coeff_8 <= SRRCxN_coeffs(14); n_coeff_8 <= SRRCxN_coeffs(15); coeff_9 <= SRRCxN_coeffs(16); n_coeff_9 <= SRRCxN_coeffs(17); coeff_10 <= SRRCxN_coeffs(18); n_coeff_10 <= SRRCxN_coeffs(19); coeff_11 <= SRRCxN_coeffs(20); n_coeff_11 <= SRRCxN_coeffs(21); coeff_12 <= SRRCxN_coeffs(22); n_coeff_12 <= SRRCxN_coeffs(23); coeff_13 <= SRRCxN_coeffs(24); n_coeff_13 <= SRRCxN_coeffs(25); coeff_14 <= SRRCxN_coeffs(26); n_coeff_14 <= SRRCxN_coeffs(27); coeff_15 <= SRRCxN_coeffs(28); n_coeff_15 <= SRRCxN_coeffs(29); coeff_16 <= SRRCxN_coeffs(30); n_coeff_16 <= SRRCxN_coeffs(31); coeff_17 <= SRRCxN_coeffs(32); n_coeff_17 <= SRRCxN_coeffs(33); coeff_18 <= SRRCxN_coeffs(34); n_coeff_18 <= SRRCxN_coeffs(35); coeff_19 <= SRRCxN_coeffs(36); n_coeff_19 <= SRRCxN_coeffs(37); coeff_20 <= SRRCxN_coeffs(38); n_coeff_20 <= SRRCxN_coeffs(39); coeff_21 <= SRRCxN_coeffs(40); n_coeff_21 <= SRRCxN_coeffs(41); coeff_22 <= SRRCxN_coeffs(42); n_coeff_22 <= SRRCxN_coeffs(43); coeff_23 <= SRRCxN_coeffs(44); n_coeff_23 <= SRRCxN_coeffs(45); coeff_24 <= SRRCxN_coeffs(46); n_coeff_24 <= SRRCxN_coeffs(47); coeff_25 <= SRRCxN_coeffs(48); n_coeff_25 <= SRRCxN_coeffs(49); coeff_26 <= SRRCxN_coeffs(50); n_coeff_26 <= SRRCxN_coeffs(51); coeff_27 <= SRRCxN_coeffs(52); n_coeff_27 <= SRRCxN_coeffs(53); downto downto downto downto downto downto 0); 0); 0); 0); 0); 0); APPENDICE F. LISTATI VHDL 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 coeff_28 <= SRRCxN_coeffs(54); n_coeff_28 <= SRRCxN_coeffs(55); coeff_29 <= SRRCxN_coeffs(56); n_coeff_29 <= SRRCxN_coeffs(57); coeff_30 <= SRRCxN_coeffs(58); n_coeff_30 <= SRRCxN_coeffs(59); coeff_31 <= SRRCxN_coeffs(60); n_coeff_31 <= SRRCxN_coeffs(61); coeff_32 <= SRRCxN_coeffs(62); n_coeff_32 <= SRRCxN_coeffs(63); coeff_33 <= SRRCxN_coeffs(64); n_coeff_33 <= SRRCxN_coeffs(65); coeff_34 <= SRRCxN_coeffs(66); n_coeff_34 <= SRRCxN_coeffs(67); coeff_35 <= SRRCxN_coeffs(68); n_coeff_35 <= SRRCxN_coeffs(69); coeff_36 <= SRRCxN_coeffs(70); n_coeff_36 <= SRRCxN_coeffs(71); coeff_37 <= SRRCxN_coeffs(72); n_coeff_37 <= SRRCxN_coeffs(73); coeff_38 <= SRRCxN_coeffs(74); n_coeff_38 <= SRRCxN_coeffs(75); coeff_39 <= SRRCxN_coeffs(76); n_coeff_39 <= SRRCxN_coeffs(77); coeff_40 <= SRRCxN_coeffs(78); n_coeff_40 <= SRRCxN_coeffs(79); coeff_41 <= SRRCxN_coeffs(80); n_coeff_41 <= SRRCxN_coeffs(81); coeff_42 <= SRRCxN_coeffs(82); n_coeff_42 <= SRRCxN_coeffs(83); U1 : fir_1 port map( clk_div_n => clk_div_n, coeff_a => coeff_1, coeff_b => coeff_2, coeff_c => coeff_3, coeff_d => coeff_4, coeff_e => coeff_5, coeff_f => coeff_6, coeff_g => coeff_7, in_fir_MSB => in_fir_MSB, n_coeff_a => n_coeff_1, n_coeff_b => n_coeff_2, n_coeff_c => n_coeff_3, n_coeff_d => n_coeff_4, n_coeff_e => n_coeff_5, n_coeff_f => n_coeff_6, n_coeff_g => n_coeff_7, out_fir => to_in_0, reset => reset ); U2 : fir_1 port map( clk_div_n => clk_div_n, coeff_a => coeff_8, coeff_b => coeff_9, coeff_c => coeff_10, coeff_d => coeff_11, coeff_e => coeff_12, coeff_f => coeff_13, coeff_g => coeff_14, in_fir_MSB => in_fir_MSB, n_coeff_a => n_coeff_8, n_coeff_b => n_coeff_9, n_coeff_c => n_coeff_10, n_coeff_d => n_coeff_11, n_coeff_e => n_coeff_12, n_coeff_f => n_coeff_13, n_coeff_g => n_coeff_14, out_fir => to_in_1, reset => reset ); U3 : fir_1 port map( clk_div_n => clk_div_n, coeff_a => coeff_15, coeff_b => coeff_16, coeff_c => coeff_17, coeff_d => coeff_18, coeff_e => coeff_19, coeff_f => coeff_20, coeff_g => coeff_21, in_fir_MSB => in_fir_MSB, n_coeff_a => n_coeff_15, n_coeff_b => n_coeff_16, n_coeff_c => n_coeff_17, n_coeff_d => n_coeff_18, n_coeff_e => n_coeff_19, n_coeff_f => n_coeff_20, n_coeff_g => n_coeff_21, out_fir => to_in_2, reset => reset ); 135 APPENDICE F. LISTATI VHDL 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 U4 : fir_1 port map( clk_div_n => clk_div_n, coeff_a => coeff_22, coeff_b => coeff_23, coeff_c => coeff_24, coeff_d => coeff_25, coeff_e => coeff_26, coeff_f => coeff_27, coeff_g => coeff_28, in_fir_MSB => in_fir_MSB, n_coeff_a => n_coeff_22, n_coeff_b => n_coeff_23, n_coeff_c => n_coeff_24, n_coeff_d => n_coeff_25, n_coeff_e => n_coeff_26, n_coeff_f => n_coeff_27, n_coeff_g => n_coeff_28, out_fir => to_in_3, reset => reset ); U5 : fir_1 port map( clk_div_n => clk_div_n, coeff_a => coeff_29, coeff_b => coeff_30, coeff_c => coeff_31, coeff_d => coeff_32, coeff_e => coeff_33, coeff_f => coeff_34, coeff_g => coeff_35, in_fir_MSB => in_fir_MSB, n_coeff_a => n_coeff_29, n_coeff_b => n_coeff_30, n_coeff_c => n_coeff_31, n_coeff_d => n_coeff_32, n_coeff_e => n_coeff_33, n_coeff_f => n_coeff_34, n_coeff_g => n_coeff_35, out_fir => to_in_4, reset => reset ); U6 : fir_1 port map( clk_div_n => clk_div_n, coeff_a => coeff_36, coeff_b => coeff_37, coeff_c => coeff_38, coeff_d => coeff_39, coeff_e => coeff_40, coeff_f => coeff_41, coeff_g => coeff_42, in_fir_MSB => in_fir_MSB, n_coeff_a => n_coeff_36, n_coeff_b => n_coeff_37, n_coeff_c => n_coeff_38, n_coeff_d => n_coeff_39, n_coeff_e => n_coeff_40, n_coeff_f => n_coeff_41, n_coeff_g => n_coeff_42, out_fir => to_in_5, reset => reset ); U7 : mux_6 port map( clk => clk, count_n => count_n, in_0 => to_in_0, in_1 => to_in_1, in_2 => to_in_2, in_3 => to_in_3, in_4 => to_in_4, in_5 => to_in_5, out_mux => polyphase_out ); end SRRC_x_N; Listato F.2.11: 1 2 3 4 5 6 7 8 9 10 11 12 136 library IEEE; use IEEE.std_logic_1164.all; use work.SRRC_coeffs.all; entity fir_1 is port( clk_div_n : in STD_LOGIC; coeff_a : in coeff; coeff_b : in coeff; coeff_c : in coeff; coeff_d : in coeff; coeff_e : in coeff; fir 1.vhd APPENDICE F. LISTATI VHDL 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 coeff_f : in coeff; coeff_g : in coeff; in_fir_MSB : in STD_LOGIC; n_coeff_a : in coeff; n_coeff_b : in coeff; n_coeff_c : in coeff; n_coeff_d : in coeff; n_coeff_e : in coeff; n_coeff_f : in coeff; n_coeff_g : in coeff; reset : in STD_LOGIC; out_fir : out STD_LOGIC_VECTOR(11 downto 0) ); end fir_1; architecture fir_1 of fir_1 is component adder_7 port ( clk_div_n : in STD_LOGIC; in_a : in STD_LOGIC_VECTOR(11 downto 0); in_b : in STD_LOGIC_VECTOR(11 downto 0); in_c : in STD_LOGIC_VECTOR(11 downto 0); in_d : in STD_LOGIC_VECTOR(11 downto 0); in_e : in STD_LOGIC_VECTOR(11 downto 0); in_f : in STD_LOGIC_VECTOR(11 downto 0); in_g : in STD_LOGIC_VECTOR(11 downto 0); reset : in STD_LOGIC; out_adder : out STD_LOGIC_VECTOR(11 downto 0) ); end component; component fir_multiplier port ( clk_div_n : in STD_LOGIC; coeff_n : in coeff; in_a : in STD_LOGIC; n_coeff_n : in coeff; reset : in STD_LOGIC; out_mult : out STD_LOGIC_VECTOR(11 downto 0) ); end component; component shift_reg port ( clk_div_n : in STD_LOGIC; in_reg : in STD_LOGIC; reset : in STD_LOGIC; out_ffd_1 : out STD_LOGIC; out_ffd_2 : out STD_LOGIC; out_ffd_3 : out STD_LOGIC; out_ffd_4 : out STD_LOGIC; out_ffd_5 : out STD_LOGIC; out_ffd_6 : out STD_LOGIC ); end component; signal in_ffd_1 : STD_LOGIC; signal out_ffd_1 : STD_LOGIC; signal out_ffd_2 : STD_LOGIC; signal out_ffd_3 : STD_LOGIC; signal out_ffd_4 : STD_LOGIC; signal out_ffd_5 : STD_LOGIC; signal out_ffd_6 : STD_LOGIC; signal to_add_a : STD_LOGIC_VECTOR (11 downto 0); signal to_add_b : STD_LOGIC_VECTOR (11 downto 0); signal to_add_c : STD_LOGIC_VECTOR (11 downto 0); signal to_add_d : STD_LOGIC_VECTOR (11 downto 0); signal to_add_e : STD_LOGIC_VECTOR (11 downto 0); signal to_add_f : STD_LOGIC_VECTOR (11 downto 0); signal to_add_g : STD_LOGIC_VECTOR (11 downto 0); begin U1 : shift_reg port map( clk_div_n => clk_div_n, in_reg => in_ffd_1, out_ffd_1 => out_ffd_1, out_ffd_2 => out_ffd_2, out_ffd_3 => out_ffd_3, out_ffd_4 => out_ffd_4, out_ffd_5 => out_ffd_5, out_ffd_6 => out_ffd_6, reset => reset ); U2 : fir_multiplier port map( clk_div_n => clk_div_n, coeff_n => coeff_a, in_a => in_ffd_1, n_coeff_n => n_coeff_a, out_mult => to_add_a, reset => reset ); U3 : fir_multiplier port map( clk_div_n => clk_div_n, coeff_n => coeff_b, in_a => out_ffd_1, 137 APPENDICE F. LISTATI VHDL 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 n_coeff_n => n_coeff_b, out_mult => to_add_b, reset => reset ); U4 : fir_multiplier port map( clk_div_n => clk_div_n, coeff_n => coeff_c, in_a => out_ffd_2, n_coeff_n => n_coeff_c, out_mult => to_add_c, reset => reset ); U5 : fir_multiplier port map( clk_div_n => clk_div_n, coeff_n => coeff_d, in_a => out_ffd_3, n_coeff_n => n_coeff_d, out_mult => to_add_d, reset => reset ); U6 : fir_multiplier port map( clk_div_n => clk_div_n, coeff_n => coeff_e, in_a => out_ffd_4, n_coeff_n => n_coeff_e, out_mult => to_add_e, reset => reset ); U7 : fir_multiplier port map( clk_div_n => clk_div_n, coeff_n => coeff_f, in_a => out_ffd_5, n_coeff_n => n_coeff_f, out_mult => to_add_f, reset => reset ); U8 : fir_multiplier port map( clk_div_n => clk_div_n, coeff_n => coeff_g, in_a => out_ffd_6, n_coeff_n => n_coeff_g, out_mult => to_add_g, reset => reset ); U9 : adder_7 port map( clk_div_n => clk_div_n, in_a => to_add_a, in_b => to_add_b, in_c => to_add_c, in_d => to_add_d, in_e => to_add_e, in_f => to_add_f, in_g => to_add_g, out_adder => out_fir, reset => reset ); in_ffd_1 <= in_fir_MSB; end fir_1; Listato F.2.12: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 138 adder 7.vhd library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_signed.all; entity adder_7 is port(in_a, in_b, in_c, in_d : in std_logic_vector(11 downto 0); in_e, in_f, in_g : in std_logic_vector(11 downto 0); clk_div_n , reset : in std_logic; out_adder : out std_logic_vector(11 downto 0)); end adder_7 ; architecture adder_7_arch of adder_7 is begin process(reset, clk_div_n , in_a , in_b , in_c , in_d, in_e, in_f, in_g) begin if reset = ’1’ then out_adder <= "000000000000"; elsif falling_edge(clk_div_n) then out_adder <= in_a + in_b + in_c + in_d + in_e + in_f + in_g; end if ; end process; end adder_7_arch ; APPENDICE F. LISTATI VHDL Listato F.2.13: 139 fir multiplier.vhd 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_signed.all; use work.SRRC_coeffs.all; entity fir_multiplier is port( in_a : in std_logic ; reset : in std_logic ; coeff_n : in coeff ; n_coeff_n : in coeff ; clk_div_n : in std_logic ; out_mult : out std_logic_vector(11 downto 0)); end fir_multiplier; architecture fir_multiplier_arch of fir_multiplier is begin process(in_a , coeff_n, n_coeff_n, clk_div_n, reset) begin if reset = ’1’ then out_mult <= "000000000000" ; elsif falling_edge(clk_div_n) then case in_a is when ’0’ => out_mult <= coeff_n ; when ’1’ => out_mult <= n_coeff_n ; when others => out_mult <= "000000000000" ; end case; end if; end process; end fir_multiplier_arch; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 library IEEE; use IEEE.std_logic_1164.all; entity shift_reg is port ( clk_div_n : in std_logic ; reset : in std_logic ; in_reg : in std_logic ; out_ffd_1 : out std_logic ; out_ffd_2 : out std_logic ; out_ffd_3 : out std_logic ; out_ffd_4 : out std_logic ; out_ffd_5 : out std_logic ; out_ffd_6 : out std_logic ); end entity; Listato F.2.14: architecture shift_reg_arch of shift_reg is signal temp_out_reg : std_logic_vector(5 downto 0); signal temp_go_mult : std_logic_vector(6 downto 0); begin process(clk_div_n, reset) begin if reset = ’1’ then temp_out_reg <= "000000"; elsif falling_edge(clk_div_n) then temp_out_reg <= in_reg & temp_out_reg(5 downto 1); end if; end process; out_ffd_6 <= temp_out_reg(0); out_ffd_5 <= temp_out_reg(1); out_ffd_4 <= temp_out_reg(2); out_ffd_3 <= temp_out_reg(3); out_ffd_2 <= temp_out_reg(4); out_ffd_1 <= temp_out_reg(5); end architecture; Listato F.2.15: 1 2 3 shift reg.vhd library ieee; use ieee.std_logic_1164.all; mux 6.vhd APPENDICE F. LISTATI VHDL 140 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 entity mux_6 is port(in_0, in_1, in_2, in_3, in_4, in_5 : in std_logic_vector(11 downto 0); count_n : in std_logic_vector(2 downto 0); clk : in std_logic; out_mux : out std_logic_vector(11 downto 0)); end mux_6; architecture mux_arch of mux_6 is begin process (clk, count_n, in_0, in_1, in_2, in_3, in_4, in_5) begin if falling_edge(clk) then case count_n is when "000" => out_mux <= in_0 ; when "001" => out_mux <= in_1 ; when "010" => out_mux <= in_2 ; when "011" => out_mux <= in_3 ; when "100" => out_mux <= in_4 ; when "101" => out_mux <= in_5 ; when others => out_mux <= "XXXXXXXXXXXX" ; end case; else null ; end if; end process; end mux_arch ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 library IEEE; use IEEE.std_logic_1164.all; entity ROM_polyphase is port( clk : in STD_LOGIC; reset : in STD_LOGIC; to_SRRC_I : in STD_LOGIC; rate_sel : in STD_LOGIC_VECTOR(1 downto 0); clk_sync : out STD_LOGIC; poly_out : out STD_LOGIC_VECTOR(11 downto 0) ); end ROM_polyphase; architecture ROM_polyphase of ROM_polyphase is component counter port ( clk : in STD_LOGIC; rate_sel : in STD_LOGIC_VECTOR(1 downto 0); reset : in STD_LOGIC; clk_en : out STD_LOGIC; count : out STD_LOGIC_VECTOR(2 downto 0) ); end component; component srrc_x_n port ( clk : in STD_LOGIC; clk_en : in STD_LOGIC; fir_sel : in STD_LOGIC_VECTOR(2 downto 0); in_fir_MSB : in STD_LOGIC; rate_sel : in STD_LOGIC_VECTOR(1 downto 0); reset : in STD_LOGIC; out_srrc : out STD_LOGIC_VECTOR(11 downto 0) ); end component; signal clk_en : STD_LOGIC; signal count_n : STD_LOGIC_VECTOR (2 downto 0); begin U1 : counter port map( clk => clk, clk_en => clk_en, count => count_n, rate_sel => rate_sel, reset => reset ); U2 : srrc_x_n port map( clk => clk, clk_en => clk_en, fir_sel => count_n, in_fir_MSB => to_SRRC_I, out_srrc => poly_out, rate_sel => rate_sel, reset => reset ); clk_sync <= clk; end ROM_polyphase; Listato F.3.1: ROM polyphase.vhd APPENDICE F. LISTATI VHDL Listato F.3.2: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 counter.vhd library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; entity counter is port ( clk : in std_logic; reset : in std_logic; rate_sel : in std_logic_vector(1 downto 0); count : out std_logic_vector(2 downto 0); clk_en : out std_logic ); end entity; architecture counter_arch of counter is type rate_table_type is array (0 to 2) of std_logic_vector (2 downto 0); -- definisco un array con i valori dei rate diminuiti di 1 -- per migliorare l ’ implementazione constant count_limit_table : rate_table_type := ("010","011","101"); signal TEMP_count : std_logic_vector(2 downto 0); signal TEMP_clk_en : std_logic; begin process(clk, reset) begin if reset = ’1’ then TEMP_count <= "000"; TEMP_clk_en <= ’1’ ; elsif rising_edge(clk) then if (TEMP_count = count_limit_table(conv_integer(rate_sel))-1) then TEMP_clk_en <= ’1’ ; TEMP_count <= TEMP_count + 1; elsif (TEMP_count = count_limit_table(conv_integer(rate_sel)) )then TEMP_clk_en <= ’0’ ; TEMP_count <= "000"; else TEMP_clk_en <= ’0’ ; TEMP_count <= TEMP_count + 1; end if; end if; end process; count <= TEMP_count; clk_en <= TEMP_clk_en; end counter_arch; Listato F.3.3: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 141 srrc x n.vhd library IEEE; use IEEE.std_logic_1164.all; entity srrc_x_n is port( clk : in STD_LOGIC; clk_en : in STD_LOGIC; in_fir_MSB : in STD_LOGIC; reset : in STD_LOGIC; fir_sel : in STD_LOGIC_VECTOR(2 downto 0); rate_sel : in STD_LOGIC_VECTOR(1 downto 0); out_srrc : out STD_LOGIC_VECTOR(11 downto 0) ); end srrc_x_n; architecture srrc_x_n of srrc_x_n is component demux_3x10 port ( clk : in STD_LOGIC; in_mux : in STD_LOGIC_VECTOR(9 downto 0); sel : in STD_LOGIC_VECTOR(1 downto 0); out_0 : out STD_LOGIC_VECTOR(8 downto 0); out_1 : out STD_LOGIC_VECTOR(8 downto 0); out_2 : out STD_LOGIC_VECTOR(9 downto 0) ); end component; component mux_3x12 port ( clk : in STD_LOGIC; in_0 : in STD_LOGIC_VECTOR(11 downto 0); in_1 : in STD_LOGIC_VECTOR(11 downto 0); in_2 : in STD_LOGIC_VECTOR(11 downto 0); sel : in STD_LOGIC_VECTOR(1 downto 0); out_mux : out STD_LOGIC_VECTOR(11 downto 0) ); end component; APPENDICE F. LISTATI VHDL 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 component romx3 port ( address : in STD_LOGIC_VECTOR(8 downto 0); SRRC_out : out STD_LOGIC_VECTOR(11 downto 0) ); end component; component ROMx4 port ( address : in STD_LOGIC_VECTOR(8 downto 0); SRRC_out : out STD_LOGIC_VECTOR(11 downto 0) ); end component; component ROMx6 port ( address : in STD_LOGIC_VECTOR(9 downto 0); SRRC_out : out STD_LOGIC_VECTOR(11 downto 0) ); end component; component shift_reg port ( clk : in STD_LOGIC; clk_en : in STD_LOGIC; in_reg : in STD_LOGIC; reset : in STD_LOGIC; out_ffd_1 : out STD_LOGIC; out_ffd_2 : out STD_LOGIC; out_ffd_3 : out STD_LOGIC; out_ffd_4 : out STD_LOGIC; out_ffd_5 : out STD_LOGIC; out_ffd_6 : out STD_LOGIC ); end component; signal address : STD_LOGIC_VECTOR (9 downto 0); signal BUS615 : STD_LOGIC_VECTOR (11 downto 0); signal BUS619 : STD_LOGIC_VECTOR (11 downto 0); signal BUS623 : STD_LOGIC_VECTOR (11 downto 0); signal sel : STD_LOGIC_VECTOR (1 downto 0); signal to_romx3 : STD_LOGIC_VECTOR (8 downto 0); signal to_romx4 : STD_LOGIC_VECTOR (8 downto 0); signal to_romx6 : STD_LOGIC_VECTOR (9 downto 0); begin U1 : shift_reg port map( clk => clk, clk_en => clk_en, in_reg => address(0), out_ffd_1 => address(1), out_ffd_2 => address(2), out_ffd_3 => address(3), out_ffd_4 => address(4), out_ffd_5 => address(5), out_ffd_6 => address(6), reset => reset ); U2 : demux_3x10 port map( clk => clk, in_mux => address, out_0 => to_romx3, out_1 => to_romx4, out_2 => to_romx6, sel => sel ); U3 : romx3 port map( SRRC_out => BUS615, address => to_romx3 ); U4 : ROMx4 port map( SRRC_out => BUS619, address => to_romx4 ); U5 : ROMx6 port map( SRRC_out => BUS623, address => to_romx6 ); U6 : mux_3x12 port map( clk => clk, in_0 => BUS615, in_1 => BUS619, in_2 => BUS623, out_mux => out_srrc, sel => sel ); address(7) <= fir_sel(0); address(8) <= fir_sel(1); address(9) <= fir_sel(2); address(0) <= in_fir_MSB; sel <= rate_sel; 142 APPENDICE F. LISTATI VHDL 130 143 end srrc_x_n; Listato F.3.4: demux 3x10.vhd library ieee; use ieee.std_logic_1164.all; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 entity demux_3x10 is port(in_mux : in std_logic_vector(9 downto 0); clk : in std_logic; sel : in std_logic_vector(1 downto 0); out_0 : out std_logic_vector(8 downto 0); out_1 : out std_logic_vector(8 downto 0); out_2 : out std_logic_vector(9 downto 0) ); end demux_3x10; architecture demux_3x10_arch of demux_3x10 is begin process (sel, in_mux, clk) begin if rising_edge(clk) then case sel is when "00" => out_0 <= in_mux(8 downto 0) ; when "01" => out_1 <= in_mux(8 downto 0) ; when "10" => out_2 <= in_mux ; when others => null; end case; end if; end process; end demux_3x10_arch ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 library ieee; use ieee.std_logic_1164.all; entity mux_3x12 is port(in_0, in_1, in_2 : in std_logic_vector(11 downto 0); clk : in std_logic ; sel : in std_logic_vector(1 downto 0); out_mux : out std_logic_vector(11 downto 0)); end mux_3x12; architecture mux_3x12_arch of mux_3x12 is begin process (sel, in_0, in_1, in_2, clk) begin if rising_edge(clk) then case sel is when "00" => out_mux <=in_0 ; when "01" => out_mux <=in_1 ; when "10" => out_mux <=in_2 ; when others => out_mux <= "XXXXXXXXXXXX" ; end case; end if; end process; end mux_3x12_arch; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity ROMx3 is port(address : in STD_LOGIC_vector(8 downto 0); SRRC_out : out STD_LOGIC_VECTOR(11 downto 0) ); end; architecture ROMx3_arch of ROMx3 is begin process(address) variable addr : integer ; begin addr := conv_integer(address) ; case addr is Listato F.3.5: Listato F.3.6: mux 3x12.vhd ROMx3.vhd APPENDICE F. LISTATI VHDL 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 -- somme per il FIR 0 when 0 => SRRC_out when 1 => SRRC_out when 2 => SRRC_out when 3 => SRRC_out when 4 => SRRC_out when 5 => SRRC_out when 6 => SRRC_out when 7 => SRRC_out when 8 => SRRC_out when 9 => SRRC_out when 10 => SRRC_out when 11 => SRRC_out when 12 => SRRC_out when 13 => SRRC_out when 14 => SRRC_out when 15 => SRRC_out when 16 => SRRC_out when 17 => SRRC_out when 18 => SRRC_out when 19 => SRRC_out when 20 => SRRC_out when 21 => SRRC_out when 22 => SRRC_out when 23 => SRRC_out when 24 => SRRC_out when 25 => SRRC_out when 26 => SRRC_out when 27 => SRRC_out when 28 => SRRC_out when 29 => SRRC_out when 30 => SRRC_out when 31 => SRRC_out when 32 => SRRC_out when 33 => SRRC_out when 34 => SRRC_out when 35 => SRRC_out when 36 => SRRC_out when 37 => SRRC_out when 38 => SRRC_out when 39 => SRRC_out when 40 => SRRC_out when 41 => SRRC_out when 42 => SRRC_out when 43 => SRRC_out when 44 => SRRC_out when 45 => SRRC_out when 46 => SRRC_out when 47 => SRRC_out when 48 => SRRC_out when 49 => SRRC_out when 50 => SRRC_out when 51 => SRRC_out when 52 => SRRC_out when 53 => SRRC_out when 54 => SRRC_out when 55 => SRRC_out when 56 => SRRC_out when 57 => SRRC_out when 58 => SRRC_out when 59 => SRRC_out when 60 => SRRC_out when 61 => SRRC_out when 62 => SRRC_out when 63 => SRRC_out when 64 => SRRC_out when 65 => SRRC_out when 66 => SRRC_out when 67 => SRRC_out when 68 => SRRC_out when 69 => SRRC_out when 70 => SRRC_out when 71 => SRRC_out when 72 => SRRC_out when 73 => SRRC_out when 74 => SRRC_out when 75 => SRRC_out when 76 => SRRC_out when 77 => SRRC_out when 78 => SRRC_out when 79 => SRRC_out when 80 => SRRC_out when 81 => SRRC_out when 82 => SRRC_out when 83 => SRRC_out when 84 => SRRC_out when 85 => SRRC_out when 86 => SRRC_out when 87 => SRRC_out when 88 => SRRC_out when 89 => SRRC_out when 90 => SRRC_out when 91 => SRRC_out when 92 => SRRC_out when 93 => SRRC_out when 94 => SRRC_out when 95 => SRRC_out when 96 => SRRC_out <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= X"52B"; X"52B"; X"517"; X"517"; X"5CB"; X"5CB"; X"5B6"; X"5B6"; X"1C8"; X"1C8"; X"1B4"; X"1B4"; X"268"; X"268"; X"253"; X"253"; X"C69"; X"C69"; X"C55"; X"C55"; X"D09"; X"D09"; X"CF4"; X"CF4"; X"907"; X"907"; X"8F2"; X"8F2"; X"9A6"; X"9A6"; X"992"; X"992"; X"6FA"; X"6FA"; X"6E6"; X"6E6"; X"79A"; X"79A"; X"785"; X"785"; X"397"; X"397"; X"383"; X"383"; X"437"; X"437"; X"422"; X"422"; X"E38"; X"E38"; X"E24"; X"E24"; X"ED8"; X"ED8"; X"EC3"; X"EC3"; X"AD6"; X"AD6"; X"AC1"; X"AC1"; X"B75"; X"B75"; X"B61"; X"B61"; X"49F"; X"49F"; X"48B"; X"48B"; X"53F"; X"53F"; X"52A"; X"52A"; X"13D"; X"13D"; X"128"; X"128"; X"1DC"; X"1DC"; X"1C8"; X"1C8"; X"BDE"; X"BDE"; X"BC9"; X"BC9"; X"C7D"; X"C7D"; X"C69"; X"C69"; X"87B"; X"87B"; X"866"; X"866"; X"91A"; X"91A"; X"906"; X"906"; X"66E"; 144 APPENDICE F. LISTATI VHDL 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 when 97 => SRRC_out when 98 => SRRC_out when 99 => SRRC_out when 100 => SRRC_out when 101 => SRRC_out when 102 => SRRC_out when 103 => SRRC_out when 104 => SRRC_out when 105 => SRRC_out when 106 => SRRC_out when 107 => SRRC_out when 108 => SRRC_out when 109 => SRRC_out when 110 => SRRC_out when 111 => SRRC_out when 112 => SRRC_out when 113 => SRRC_out when 114 => SRRC_out when 115 => SRRC_out when 116 => SRRC_out when 117 => SRRC_out when 118 => SRRC_out when 119 => SRRC_out when 120 => SRRC_out when 121 => SRRC_out when 122 => SRRC_out when 123 => SRRC_out when 124 => SRRC_out when 125 => SRRC_out when 126 => SRRC_out when 127 => SRRC_out -- somme per il FIR 1 when 128 => SRRC_out when 129 => SRRC_out when 130 => SRRC_out when 131 => SRRC_out when 132 => SRRC_out when 133 => SRRC_out when 134 => SRRC_out when 135 => SRRC_out when 136 => SRRC_out when 137 => SRRC_out when 138 => SRRC_out when 139 => SRRC_out when 140 => SRRC_out when 141 => SRRC_out when 142 => SRRC_out when 143 => SRRC_out when 144 => SRRC_out when 145 => SRRC_out when 146 => SRRC_out when 147 => SRRC_out when 148 => SRRC_out when 149 => SRRC_out when 150 => SRRC_out when 151 => SRRC_out when 152 => SRRC_out when 153 => SRRC_out when 154 => SRRC_out when 155 => SRRC_out when 156 => SRRC_out when 157 => SRRC_out when 158 => SRRC_out when 159 => SRRC_out when 160 => SRRC_out when 161 => SRRC_out when 162 => SRRC_out when 163 => SRRC_out when 164 => SRRC_out when 165 => SRRC_out when 166 => SRRC_out when 167 => SRRC_out when 168 => SRRC_out when 169 => SRRC_out when 170 => SRRC_out when 171 => SRRC_out when 172 => SRRC_out when 173 => SRRC_out when 174 => SRRC_out when 175 => SRRC_out when 176 => SRRC_out when 177 => SRRC_out when 178 => SRRC_out when 179 => SRRC_out when 180 => SRRC_out when 181 => SRRC_out when 182 => SRRC_out when 183 => SRRC_out when 184 => SRRC_out when 185 => SRRC_out when 186 => SRRC_out when 187 => SRRC_out when 188 => SRRC_out when 189 => SRRC_out when 190 => SRRC_out when 191 => SRRC_out when 192 => SRRC_out when 193 => SRRC_out <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= X"66E"; X"65A"; X"65A"; X"70E"; X"70E"; X"6F9"; X"6F9"; X"30C"; X"30C"; X"2F7"; X"2F7"; X"3AB"; X"3AB"; X"397"; X"397"; X"DAD"; X"DAD"; X"D98"; X"D98"; X"E4C"; X"E4C"; X"E38"; X"E38"; X"A4A"; X"A4A"; X"A35"; X"A35"; X"AE9"; X"AE9"; X"AD5"; X"AD5"; X"52B"; X"52B"; X"49F"; X"49F"; X"6FA"; X"6FA"; X"66E"; X"66E"; X"C69"; X"C69"; X"BDE"; X"BDE"; X"E38"; X"E38"; X"DAD"; X"DAD"; X"1C8"; X"1C8"; X"13D"; X"13D"; X"397"; X"397"; X"30C"; X"30C"; X"907"; X"907"; X"87B"; X"87B"; X"AD6"; X"AD6"; X"A4A"; X"A4A"; X"5CB"; X"5CB"; X"53F"; X"53F"; X"79A"; X"79A"; X"70E"; X"70E"; X"D09"; X"D09"; X"C7D"; X"C7D"; X"ED8"; X"ED8"; X"E4C"; X"E4C"; X"268"; X"268"; X"1DC"; X"1DC"; X"437"; X"437"; X"3AB"; X"3AB"; X"9A6"; X"9A6"; X"91A"; X"91A"; X"B75"; X"B75"; X"AE9"; X"AE9"; X"517"; X"517"; 145 APPENDICE F. LISTATI VHDL 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 when 194 => SRRC_out when 195 => SRRC_out when 196 => SRRC_out when 197 => SRRC_out when 198 => SRRC_out when 199 => SRRC_out when 200 => SRRC_out when 201 => SRRC_out when 202 => SRRC_out when 203 => SRRC_out when 204 => SRRC_out when 205 => SRRC_out when 206 => SRRC_out when 207 => SRRC_out when 208 => SRRC_out when 209 => SRRC_out when 210 => SRRC_out when 211 => SRRC_out when 212 => SRRC_out when 213 => SRRC_out when 214 => SRRC_out when 215 => SRRC_out when 216 => SRRC_out when 217 => SRRC_out when 218 => SRRC_out when 219 => SRRC_out when 220 => SRRC_out when 221 => SRRC_out when 222 => SRRC_out when 223 => SRRC_out when 224 => SRRC_out when 225 => SRRC_out when 226 => SRRC_out when 227 => SRRC_out when 228 => SRRC_out when 229 => SRRC_out when 230 => SRRC_out when 231 => SRRC_out when 232 => SRRC_out when 233 => SRRC_out when 234 => SRRC_out when 235 => SRRC_out when 236 => SRRC_out when 237 => SRRC_out when 238 => SRRC_out when 239 => SRRC_out when 240 => SRRC_out when 241 => SRRC_out when 242 => SRRC_out when 243 => SRRC_out when 244 => SRRC_out when 245 => SRRC_out when 246 => SRRC_out when 247 => SRRC_out when 248 => SRRC_out when 249 => SRRC_out when 250 => SRRC_out when 251 => SRRC_out when 252 => SRRC_out when 253 => SRRC_out when 254 => SRRC_out when 255 => SRRC_out -- somme per il FIR 2 when 256 => SRRC_out when 257 => SRRC_out when 258 => SRRC_out when 259 => SRRC_out when 260 => SRRC_out when 261 => SRRC_out when 262 => SRRC_out when 263 => SRRC_out when 264 => SRRC_out when 265 => SRRC_out when 266 => SRRC_out when 267 => SRRC_out when 268 => SRRC_out when 269 => SRRC_out when 270 => SRRC_out when 271 => SRRC_out when 272 => SRRC_out when 273 => SRRC_out when 274 => SRRC_out when 275 => SRRC_out when 276 => SRRC_out when 277 => SRRC_out when 278 => SRRC_out when 279 => SRRC_out when 280 => SRRC_out when 281 => SRRC_out when 282 => SRRC_out when 283 => SRRC_out when 284 => SRRC_out when 285 => SRRC_out when 286 => SRRC_out when 287 => SRRC_out when 288 => SRRC_out when 289 => SRRC_out when 290 => SRRC_out <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= X"48B"; X"48B"; X"6E6"; X"6E6"; X"65A"; X"65A"; X"C55"; X"C55"; X"BC9"; X"BC9"; X"E24"; X"E24"; X"D98"; X"D98"; X"1B4"; X"1B4"; X"128"; X"128"; X"383"; X"383"; X"2F7"; X"2F7"; X"8F2"; X"8F2"; X"866"; X"866"; X"AC1"; X"AC1"; X"A35"; X"A35"; X"5B6"; X"5B6"; X"52A"; X"52A"; X"785"; X"785"; X"6F9"; X"6F9"; X"CF4"; X"CF4"; X"C69"; X"C69"; X"EC3"; X"EC3"; X"E38"; X"E38"; X"253"; X"253"; X"1C8"; X"1C8"; X"422"; X"422"; X"397"; X"397"; X"992"; X"992"; X"906"; X"906"; X"B61"; X"B61"; X"AD5"; X"AD5"; X"500"; X"541"; X"485"; X"4C6"; X"5D7"; X"618"; X"55D"; X"59E"; X"9C4"; X"A05"; X"94A"; X"98B"; X"A9C"; X"ADC"; X"A21"; X"A62"; X"5D7"; X"618"; X"55D"; X"59E"; X"6AF"; X"6F0"; X"634"; X"675"; X"A9C"; X"ADC"; X"A21"; X"A62"; X"B73"; X"BB4"; X"AF9"; X"B3A"; X"485"; X"4C6"; X"40B"; 146 APPENDICE F. LISTATI VHDL 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 when 291 => SRRC_out <= X"44C"; when 292 => SRRC_out <= X"55D"; when 293 => SRRC_out <= X"59E"; when 294 => SRRC_out <= X"4E3"; when 295 => SRRC_out <= X"524"; when 296 => SRRC_out <= X"94A"; when 297 => SRRC_out <= X"98B"; when 298 => SRRC_out <= X"8CF"; when 299 => SRRC_out <= X"910"; when 300 => SRRC_out <= X"A21"; when 301 => SRRC_out <= X"A62"; when 302 => SRRC_out <= X"9A7"; when 303 => SRRC_out <= X"9E8"; when 304 => SRRC_out <= X"55D"; when 305 => SRRC_out <= X"59E"; when 306 => SRRC_out <= X"4E3"; when 307 => SRRC_out <= X"524"; when 308 => SRRC_out <= X"634"; when 309 => SRRC_out <= X"675"; when 310 => SRRC_out <= X"5BA"; when 311 => SRRC_out <= X"5FB"; when 312 => SRRC_out <= X"A21"; when 313 => SRRC_out <= X"A62"; when 314 => SRRC_out <= X"9A7"; when 315 => SRRC_out <= X"9E8"; when 316 => SRRC_out <= X"AF9"; when 317 => SRRC_out <= X"B3A"; when 318 => SRRC_out <= X"A7E"; when 319 => SRRC_out <= X"ABF"; when 320 => SRRC_out <= X"541"; when 321 => SRRC_out <= X"582"; when 322 => SRRC_out <= X"4C6"; when 323 => SRRC_out <= X"507"; when 324 => SRRC_out <= X"618"; when 325 => SRRC_out <= X"659"; when 326 => SRRC_out <= X"59E"; when 327 => SRRC_out <= X"5DF"; when 328 => SRRC_out <= X"A05"; when 329 => SRRC_out <= X"A46"; when 330 => SRRC_out <= X"98B"; when 331 => SRRC_out <= X"9CC"; when 332 => SRRC_out <= X"ADC"; when 333 => SRRC_out <= X"B1D"; when 334 => SRRC_out <= X"A62"; when 335 => SRRC_out <= X"AA3"; when 336 => SRRC_out <= X"618"; when 337 => SRRC_out <= X"659"; when 338 => SRRC_out <= X"59E"; when 339 => SRRC_out <= X"5DF"; when 340 => SRRC_out <= X"6F0"; when 341 => SRRC_out <= X"731"; when 342 => SRRC_out <= X"675"; when 343 => SRRC_out <= X"6B6"; when 344 => SRRC_out <= X"ADC"; when 345 => SRRC_out <= X"B1D"; when 346 => SRRC_out <= X"A62"; when 347 => SRRC_out <= X"AA3"; when 348 => SRRC_out <= X"BB4"; when 349 => SRRC_out <= X"BF5"; when 350 => SRRC_out <= X"B3A"; when 351 => SRRC_out <= X"B7B"; when 352 => SRRC_out <= X"4C6"; when 353 => SRRC_out <= X"507"; when 354 => SRRC_out <= X"44C"; when 355 => SRRC_out <= X"48D"; when 356 => SRRC_out <= X"59E"; when 357 => SRRC_out <= X"5DF"; when 358 => SRRC_out <= X"524"; when 359 => SRRC_out <= X"564"; when 360 => SRRC_out <= X"98B"; when 361 => SRRC_out <= X"9CC"; when 362 => SRRC_out <= X"910"; when 363 => SRRC_out <= X"951"; when 364 => SRRC_out <= X"A62"; when 365 => SRRC_out <= X"AA3"; when 366 => SRRC_out <= X"9E8"; when 367 => SRRC_out <= X"A29"; when 368 => SRRC_out <= X"59E"; when 369 => SRRC_out <= X"5DF"; when 370 => SRRC_out <= X"524"; when 371 => SRRC_out <= X"564"; when 372 => SRRC_out <= X"675"; when 373 => SRRC_out <= X"6B6"; when 374 => SRRC_out <= X"5FB"; when 375 => SRRC_out <= X"63C"; when 376 => SRRC_out <= X"A62"; when 377 => SRRC_out <= X"AA3"; when 378 => SRRC_out <= X"9E8"; when 379 => SRRC_out <= X"A29"; when 380 => SRRC_out <= X"B3A"; when 381 => SRRC_out <= X"B7B"; when 382 => SRRC_out <= X"ABF"; when 383 => SRRC_out <= X"B00"; when OTHERS => SRRC_out <= X"000"; end case; end process; end ROMx3_arch; 147 APPENDICE F. LISTATI VHDL Listato F.3.7: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 148 ROMx4.vhd library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity ROMx4 is port(address : in STD_LOGIC_vector(8 downto 0); SRRC_out : out STD_LOGIC_VECTOR(11 downto 0) ); end; architecture ROMx4_arch of ROMx4 is begin process(address) variable addr : integer ; begin addr := conv_integer(address) ; case addr is -- somme per il FIR 0 when 0 => SRRC_out <= X"4F1"; when 1 => SRRC_out <= X"4F1"; when 2 => SRRC_out <= X"500"; when 3 => SRRC_out <= X"500"; when 4 => SRRC_out <= X"53B"; when 5 => SRRC_out <= X"53B"; when 6 => SRRC_out <= X"549"; when 7 => SRRC_out <= X"549"; when 8 => SRRC_out <= X"2EA"; when 9 => SRRC_out <= X"2EA"; when 10 => SRRC_out <= X"2F9"; when 11 => SRRC_out <= X"2F9"; when 12 => SRRC_out <= X"334"; when 13 => SRRC_out <= X"334"; when 14 => SRRC_out <= X"342"; when 15 => SRRC_out <= X"342"; when 16 => SRRC_out <= X"B95"; when 17 => SRRC_out <= X"B95"; when 18 => SRRC_out <= X"BA3"; when 19 => SRRC_out <= X"BA3"; when 20 => SRRC_out <= X"BDE"; when 21 => SRRC_out <= X"BDE"; when 22 => SRRC_out <= X"BED"; when 23 => SRRC_out <= X"BED"; when 24 => SRRC_out <= X"98E"; when 25 => SRRC_out <= X"98E"; when 26 => SRRC_out <= X"99C"; when 27 => SRRC_out <= X"99C"; when 28 => SRRC_out <= X"9D7"; when 29 => SRRC_out <= X"9D7"; when 30 => SRRC_out <= X"9E6"; when 31 => SRRC_out <= X"9E6"; when 32 => SRRC_out <= X"6BD"; when 33 => SRRC_out <= X"6BD"; when 34 => SRRC_out <= X"6CB"; when 35 => SRRC_out <= X"6CB"; when 36 => SRRC_out <= X"706"; when 37 => SRRC_out <= X"706"; when 38 => SRRC_out <= X"715"; when 39 => SRRC_out <= X"715"; when 40 => SRRC_out <= X"4B6"; when 41 => SRRC_out <= X"4B6"; when 42 => SRRC_out <= X"4C4"; when 43 => SRRC_out <= X"4C4"; when 44 => SRRC_out <= X"4FF"; when 45 => SRRC_out <= X"4FF"; when 46 => SRRC_out <= X"50E"; when 47 => SRRC_out <= X"50E"; when 48 => SRRC_out <= X"D60"; when 49 => SRRC_out <= X"D60"; when 50 => SRRC_out <= X"D6E"; when 51 => SRRC_out <= X"D6E"; when 52 => SRRC_out <= X"DAA"; when 53 => SRRC_out <= X"DAA"; when 54 => SRRC_out <= X"DB8"; when 55 => SRRC_out <= X"DB8"; when 56 => SRRC_out <= X"B59"; when 57 => SRRC_out <= X"B59"; when 58 => SRRC_out <= X"B67"; when 59 => SRRC_out <= X"B67"; when 60 => SRRC_out <= X"BA3"; when 61 => SRRC_out <= X"BA3"; when 62 => SRRC_out <= X"BB1"; when 63 => SRRC_out <= X"BB1"; when 64 => SRRC_out <= X"44F"; when 65 => SRRC_out <= X"44F"; when 66 => SRRC_out <= X"45D"; when 67 => SRRC_out <= X"45D"; when 68 => SRRC_out <= X"499"; when 69 => SRRC_out <= X"499"; APPENDICE F. LISTATI VHDL 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 when 70 => SRRC_out when 71 => SRRC_out when 72 => SRRC_out when 73 => SRRC_out when 74 => SRRC_out when 75 => SRRC_out when 76 => SRRC_out when 77 => SRRC_out when 78 => SRRC_out when 79 => SRRC_out when 80 => SRRC_out when 81 => SRRC_out when 82 => SRRC_out when 83 => SRRC_out when 84 => SRRC_out when 85 => SRRC_out when 86 => SRRC_out when 87 => SRRC_out when 88 => SRRC_out when 89 => SRRC_out when 90 => SRRC_out when 91 => SRRC_out when 92 => SRRC_out when 93 => SRRC_out when 94 => SRRC_out when 95 => SRRC_out when 96 => SRRC_out when 97 => SRRC_out when 98 => SRRC_out when 99 => SRRC_out when 100 => SRRC_out when 101 => SRRC_out when 102 => SRRC_out when 103 => SRRC_out when 104 => SRRC_out when 105 => SRRC_out when 106 => SRRC_out when 107 => SRRC_out when 108 => SRRC_out when 109 => SRRC_out when 110 => SRRC_out when 111 => SRRC_out when 112 => SRRC_out when 113 => SRRC_out when 114 => SRRC_out when 115 => SRRC_out when 116 => SRRC_out when 117 => SRRC_out when 118 => SRRC_out when 119 => SRRC_out when 120 => SRRC_out when 121 => SRRC_out when 122 => SRRC_out when 123 => SRRC_out when 124 => SRRC_out when 125 => SRRC_out when 126 => SRRC_out when 127 => SRRC_out -- somme per il FIR 1 when 128 => SRRC_out when 129 => SRRC_out when 130 => SRRC_out when 131 => SRRC_out when 132 => SRRC_out when 133 => SRRC_out when 134 => SRRC_out when 135 => SRRC_out when 136 => SRRC_out when 137 => SRRC_out when 138 => SRRC_out when 139 => SRRC_out when 140 => SRRC_out when 141 => SRRC_out when 142 => SRRC_out when 143 => SRRC_out when 144 => SRRC_out when 145 => SRRC_out when 146 => SRRC_out when 147 => SRRC_out when 148 => SRRC_out when 149 => SRRC_out when 150 => SRRC_out when 151 => SRRC_out when 152 => SRRC_out when 153 => SRRC_out when 154 => SRRC_out when 155 => SRRC_out when 156 => SRRC_out when 157 => SRRC_out when 158 => SRRC_out when 159 => SRRC_out when 160 => SRRC_out when 161 => SRRC_out when 162 => SRRC_out when 163 => SRRC_out when 164 => SRRC_out when 165 => SRRC_out when 166 => SRRC_out <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= X"4A7"; X"4A7"; X"248"; X"248"; X"256"; X"256"; X"292"; X"292"; X"2A0"; X"2A0"; X"AF2"; X"AF2"; X"B01"; X"B01"; X"B3C"; X"B3C"; X"B4A"; X"B4A"; X"8EB"; X"8EB"; X"8FA"; X"8FA"; X"935"; X"935"; X"943"; X"943"; X"61A"; X"61A"; X"629"; X"629"; X"664"; X"664"; X"672"; X"672"; X"413"; X"413"; X"422"; X"422"; X"45D"; X"45D"; X"46B"; X"46B"; X"CBE"; X"CBE"; X"CCC"; X"CCC"; X"D07"; X"D07"; X"D16"; X"D16"; X"AB7"; X"AB7"; X"AC5"; X"AC5"; X"B00"; X"B00"; X"B0F"; X"B0F"; X"4F5"; X"4F5"; X"49D"; X"49D"; X"647"; X"647"; X"5EF"; X"5EF"; X"F07"; X"F07"; X"EAE"; X"EAE"; X"059"; X"059"; X"000"; X"000"; X"F07"; X"F07"; X"EAE"; X"EAE"; X"059"; X"059"; X"000"; X"000"; X"918"; X"918"; X"8BF"; X"8BF"; X"A6A"; X"A6A"; X"A11"; X"A11"; X"647"; X"647"; X"5EF"; X"5EF"; X"79A"; X"79A"; X"741"; 149 APPENDICE F. LISTATI VHDL 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 when 167 => SRRC_out when 168 => SRRC_out when 169 => SRRC_out when 170 => SRRC_out when 171 => SRRC_out when 172 => SRRC_out when 173 => SRRC_out when 174 => SRRC_out when 175 => SRRC_out when 176 => SRRC_out when 177 => SRRC_out when 178 => SRRC_out when 179 => SRRC_out when 180 => SRRC_out when 181 => SRRC_out when 182 => SRRC_out when 183 => SRRC_out when 184 => SRRC_out when 185 => SRRC_out when 186 => SRRC_out when 187 => SRRC_out when 188 => SRRC_out when 189 => SRRC_out when 190 => SRRC_out when 191 => SRRC_out when 192 => SRRC_out when 193 => SRRC_out when 194 => SRRC_out when 195 => SRRC_out when 196 => SRRC_out when 197 => SRRC_out when 198 => SRRC_out when 199 => SRRC_out when 200 => SRRC_out when 201 => SRRC_out when 202 => SRRC_out when 203 => SRRC_out when 204 => SRRC_out when 205 => SRRC_out when 206 => SRRC_out when 207 => SRRC_out when 208 => SRRC_out when 209 => SRRC_out when 210 => SRRC_out when 211 => SRRC_out when 212 => SRRC_out when 213 => SRRC_out when 214 => SRRC_out when 215 => SRRC_out when 216 => SRRC_out when 217 => SRRC_out when 218 => SRRC_out when 219 => SRRC_out when 220 => SRRC_out when 221 => SRRC_out when 222 => SRRC_out when 223 => SRRC_out when 224 => SRRC_out when 225 => SRRC_out when 226 => SRRC_out when 227 => SRRC_out when 228 => SRRC_out when 229 => SRRC_out when 230 => SRRC_out when 231 => SRRC_out when 232 => SRRC_out when 233 => SRRC_out when 234 => SRRC_out when 235 => SRRC_out when 236 => SRRC_out when 237 => SRRC_out when 238 => SRRC_out when 239 => SRRC_out when 240 => SRRC_out when 241 => SRRC_out when 242 => SRRC_out when 243 => SRRC_out when 244 => SRRC_out when 245 => SRRC_out when 246 => SRRC_out when 247 => SRRC_out when 248 => SRRC_out when 249 => SRRC_out when 250 => SRRC_out when 251 => SRRC_out when 252 => SRRC_out when 253 => SRRC_out when 254 => SRRC_out when 255 => SRRC_out -- somme per il FIR 2 when 256 => SRRC_out when 257 => SRRC_out when 258 => SRRC_out when 259 => SRRC_out when 260 => SRRC_out when 261 => SRRC_out when 262 => SRRC_out when 263 => SRRC_out <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= X"741"; X"059"; X"059"; X"000"; X"000"; X"1AB"; X"1AB"; X"152"; X"152"; X"059"; X"059"; X"000"; X"000"; X"1AB"; X"1AB"; X"152"; X"152"; X"A6A"; X"A6A"; X"A11"; X"A11"; X"BBC"; X"BBC"; X"B63"; X"B63"; X"49D"; X"49D"; X"444"; X"444"; X"5EF"; X"5EF"; X"596"; X"596"; X"EAE"; X"EAE"; X"E55"; X"E55"; X"000"; X"000"; X"FA7"; X"FA7"; X"EAE"; X"EAE"; X"E55"; X"E55"; X"000"; X"000"; X"FA7"; X"FA7"; X"8BF"; X"8BF"; X"866"; X"866"; X"A11"; X"A11"; X"9B9"; X"9B9"; X"5EF"; X"5EF"; X"596"; X"596"; X"741"; X"741"; X"6E8"; X"6E8"; X"000"; X"000"; X"FA7"; X"FA7"; X"152"; X"152"; X"0F9"; X"0F9"; X"000"; X"000"; X"FA7"; X"FA7"; X"152"; X"152"; X"0F9"; X"0F9"; X"A11"; X"A11"; X"9B9"; X"9B9"; X"B63"; X"B63"; X"B0B"; X"B0B"; X"4F1"; X"4F1"; X"44F"; X"44F"; X"6BD"; X"6BD"; X"61A"; X"61A"; 150 APPENDICE F. LISTATI VHDL 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= X"B95"; X"B95"; X"AF2"; X"AF2"; X"D60"; X"D60"; X"CBE"; X"CBE"; X"2EA"; X"2EA"; X"248"; X"248"; X"4B6"; X"4B6"; X"413"; X"413"; X"98E"; X"98E"; X"8EB"; X"8EB"; X"B59"; X"B59"; X"AB7"; X"AB7"; X"53B"; X"53B"; X"499"; X"499"; X"706"; X"706"; X"664"; X"664"; X"BDE"; X"BDE"; X"B3C"; X"B3C"; X"DAA"; X"DAA"; X"D07"; X"D07"; X"334"; X"334"; X"292"; X"292"; X"4FF"; X"4FF"; X"45D"; X"45D"; X"9D7"; X"9D7"; X"935"; X"935"; X"BA3"; X"BA3"; X"B00"; X"B00"; X"500"; X"500"; X"45D"; X"45D"; X"6CB"; X"6CB"; X"629"; X"629"; X"BA3"; X"BA3"; X"B01"; X"B01"; X"D6E"; X"D6E"; X"CCC"; X"CCC"; X"2F9"; X"2F9"; X"256"; X"256"; X"4C4"; X"4C4"; X"422"; X"422"; X"99C"; X"99C"; X"8FA"; X"8FA"; X"B67"; X"B67"; X"AC5"; X"AC5"; X"549"; X"549"; X"4A7"; X"4A7"; X"715"; X"715"; X"672"; X"672"; X"BED"; X"BED"; 151 APPENDICE F. LISTATI VHDL 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 when 362 => SRRC_out when 363 => SRRC_out when 364 => SRRC_out when 365 => SRRC_out when 366 => SRRC_out when 367 => SRRC_out when 368 => SRRC_out when 369 => SRRC_out when 370 => SRRC_out when 371 => SRRC_out when 372 => SRRC_out when 373 => SRRC_out when 374 => SRRC_out when 375 => SRRC_out when 376 => SRRC_out when 377 => SRRC_out when 378 => SRRC_out when 379 => SRRC_out when 380 => SRRC_out when 381 => SRRC_out when 382 => SRRC_out when 383 => SRRC_out -- somme per il FIR 3 when 384 => SRRC_out when 385 => SRRC_out when 386 => SRRC_out when 387 => SRRC_out when 388 => SRRC_out when 389 => SRRC_out when 390 => SRRC_out when 391 => SRRC_out when 392 => SRRC_out when 393 => SRRC_out when 394 => SRRC_out when 395 => SRRC_out when 396 => SRRC_out when 397 => SRRC_out when 398 => SRRC_out when 399 => SRRC_out when 400 => SRRC_out when 401 => SRRC_out when 402 => SRRC_out when 403 => SRRC_out when 404 => SRRC_out when 405 => SRRC_out when 406 => SRRC_out when 407 => SRRC_out when 408 => SRRC_out when 409 => SRRC_out when 410 => SRRC_out when 411 => SRRC_out when 412 => SRRC_out when 413 => SRRC_out when 414 => SRRC_out when 415 => SRRC_out when 416 => SRRC_out when 417 => SRRC_out when 418 => SRRC_out when 419 => SRRC_out when 420 => SRRC_out when 421 => SRRC_out when 422 => SRRC_out when 423 => SRRC_out when 424 => SRRC_out when 425 => SRRC_out when 426 => SRRC_out when 427 => SRRC_out when 428 => SRRC_out when 429 => SRRC_out when 430 => SRRC_out when 431 => SRRC_out when 432 => SRRC_out when 433 => SRRC_out when 434 => SRRC_out when 435 => SRRC_out when 436 => SRRC_out when 437 => SRRC_out when 438 => SRRC_out when 439 => SRRC_out when 440 => SRRC_out when 441 => SRRC_out when 442 => SRRC_out when 443 => SRRC_out when 444 => SRRC_out when 445 => SRRC_out when 446 => SRRC_out when 447 => SRRC_out when 448 => SRRC_out when 449 => SRRC_out when 450 => SRRC_out when 451 => SRRC_out when 452 => SRRC_out when 453 => SRRC_out when 454 => SRRC_out when 455 => SRRC_out when 456 => SRRC_out when 457 => SRRC_out when 458 => SRRC_out <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= X"B4A"; X"B4A"; X"DB8"; X"DB8"; X"D16"; X"D16"; X"342"; X"342"; X"2A0"; X"2A0"; X"50E"; X"50E"; X"46B"; X"46B"; X"9E6"; X"9E6"; X"943"; X"943"; X"BB1"; X"BB1"; X"B0F"; X"B0F"; X"4BC"; X"50D"; X"443"; X"493"; X"586"; X"5D6"; X"50D"; X"55D"; X"A02"; X"A53"; X"989"; X"9D9"; X"ACC"; X"B1C"; X"A53"; X"AA3"; X"586"; X"5D6"; X"50D"; X"55D"; X"64F"; X"6A0"; X"5D6"; X"627"; X"ACC"; X"B1C"; X"A53"; X"AA3"; X"B95"; X"BE6"; X"B1C"; X"B6D"; X"443"; X"493"; X"3CA"; X"41A"; X"50D"; X"55D"; X"494"; X"4E4"; X"989"; X"9D9"; X"910"; X"960"; X"A53"; X"AA3"; X"9DA"; X"A2A"; X"50D"; X"55D"; X"494"; X"4E4"; X"5D6"; X"627"; X"55D"; X"5AD"; X"A53"; X"AA3"; X"9DA"; X"A2A"; X"B1C"; X"B6D"; X"AA3"; X"AF3"; X"50D"; X"55D"; X"493"; X"4E4"; X"5D6"; X"626"; X"55D"; X"5AD"; X"A53"; X"AA3"; X"9D9"; 152 APPENDICE F. LISTATI VHDL 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 when 459 => SRRC_out <= X"A2A"; when 460 => SRRC_out <= X"B1C"; when 461 => SRRC_out <= X"B6C"; when 462 => SRRC_out <= X"AA3"; when 463 => SRRC_out <= X"AF3"; when 464 => SRRC_out <= X"5D6"; when 465 => SRRC_out <= X"626"; when 466 => SRRC_out <= X"55D"; when 467 => SRRC_out <= X"5AD"; when 468 => SRRC_out <= X"6A0"; when 469 => SRRC_out <= X"6F0"; when 470 => SRRC_out <= X"627"; when 471 => SRRC_out <= X"677"; when 472 => SRRC_out <= X"B1C"; when 473 => SRRC_out <= X"B6C"; when 474 => SRRC_out <= X"AA3"; when 475 => SRRC_out <= X"AF3"; when 476 => SRRC_out <= X"BE6"; when 477 => SRRC_out <= X"C36"; when 478 => SRRC_out <= X"B6D"; when 479 => SRRC_out <= X"BBD"; when 480 => SRRC_out <= X"493"; when 481 => SRRC_out <= X"4E4"; when 482 => SRRC_out <= X"41A"; when 483 => SRRC_out <= X"46B"; when 484 => SRRC_out <= X"55D"; when 485 => SRRC_out <= X"5AD"; when 486 => SRRC_out <= X"4E4"; when 487 => SRRC_out <= X"534"; when 488 => SRRC_out <= X"9D9"; when 489 => SRRC_out <= X"A2A"; when 490 => SRRC_out <= X"960"; when 491 => SRRC_out <= X"9B1"; when 492 => SRRC_out <= X"AA3"; when 493 => SRRC_out <= X"AF3"; when 494 => SRRC_out <= X"A2A"; when 495 => SRRC_out <= X"A7A"; when 496 => SRRC_out <= X"55D"; when 497 => SRRC_out <= X"5AD"; when 498 => SRRC_out <= X"4E4"; when 499 => SRRC_out <= X"534"; when 500 => SRRC_out <= X"627"; when 501 => SRRC_out <= X"677"; when 502 => SRRC_out <= X"5AD"; when 503 => SRRC_out <= X"5FE"; when 504 => SRRC_out <= X"AA3"; when 505 => SRRC_out <= X"AF3"; when 506 => SRRC_out <= X"A2A"; when 507 => SRRC_out <= X"A7A"; when 508 => SRRC_out <= X"B6D"; when 509 => SRRC_out <= X"BBD"; when 510 => SRRC_out <= X"AF3"; when 511 => SRRC_out <= X"B44"; when OTHERS => SRRC_out <= X"000"; end case; end process; end ROMx4_arch; Listato F.3.8: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 153 ROMx6.vhd library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity ROMx6 is port(address : in STD_LOGIC_vector(9 downto 0); SRRC_out : out STD_LOGIC_VECTOR(11 downto 0) ); end; architecture ROMx6_arch of ROMx6 is begin process(address) variable addr : integer ; begin addr := conv_integer(address) ; case addr is -- somme per il FIR 0 when 0 => SRRC_out <= X"515"; when 1 => SRRC_out <= X"515"; when 2 => SRRC_out <= X"509"; when 3 => SRRC_out <= X"509"; when 4 => SRRC_out <= X"5A3"; when 5 => SRRC_out <= X"5A3"; when 6 => SRRC_out <= X"597"; when 7 => SRRC_out <= X"597"; when 8 => SRRC_out <= X"1C7"; when 9 => SRRC_out <= X"1C7"; when 10 => SRRC_out <= X"1BB"; when 11 => SRRC_out <= X"1BB"; when 12 => SRRC_out <= X"254"; when 13 => SRRC_out <= X"254"; APPENDICE F. LISTATI VHDL 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= X"248"; X"248"; X"C6C"; X"C6C"; X"C60"; X"C60"; X"CF9"; X"CF9"; X"CED"; X"CED"; X"91D"; X"91D"; X"911"; X"911"; X"9AA"; X"9AA"; X"99F"; X"99F"; X"6D8"; X"6D8"; X"6CC"; X"6CC"; X"765"; X"765"; X"759"; X"759"; X"389"; X"389"; X"37D"; X"37D"; X"416"; X"416"; X"40A"; X"40A"; X"E2E"; X"E2E"; X"E23"; X"E23"; X"EBC"; X"EBC"; X"EB0"; X"EB0"; X"AE0"; X"AE0"; X"AD4"; X"AD4"; X"B6D"; X"B6D"; X"B61"; X"B61"; X"49F"; X"49F"; X"493"; X"493"; X"52C"; X"52C"; X"520"; X"520"; X"150"; X"150"; X"144"; X"144"; X"1DD"; X"1DD"; X"1D2"; X"1D2"; X"BF6"; X"BF6"; X"BEA"; X"BEA"; X"C83"; X"C83"; X"C77"; X"C77"; X"8A7"; X"8A7"; X"89B"; X"89B"; X"934"; X"934"; X"928"; X"928"; X"661"; X"661"; X"656"; X"656"; X"6EF"; X"6EF"; X"6E3"; X"6E3"; X"313"; X"313"; X"307"; X"307"; X"3A0"; X"3A0"; X"394"; X"394"; 154 APPENDICE F. LISTATI VHDL 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 when 112 => SRRC_out when 113 => SRRC_out when 114 => SRRC_out when 115 => SRRC_out when 116 => SRRC_out when 117 => SRRC_out when 118 => SRRC_out when 119 => SRRC_out when 120 => SRRC_out when 121 => SRRC_out when 122 => SRRC_out when 123 => SRRC_out when 124 => SRRC_out when 125 => SRRC_out when 126 => SRRC_out when 127 => SRRC_out -- somme per il FIR 1 when 128 => SRRC_out when 129 => SRRC_out when 130 => SRRC_out when 131 => SRRC_out when 132 => SRRC_out when 133 => SRRC_out when 134 => SRRC_out when 135 => SRRC_out when 136 => SRRC_out when 137 => SRRC_out when 138 => SRRC_out when 139 => SRRC_out when 140 => SRRC_out when 141 => SRRC_out when 142 => SRRC_out when 143 => SRRC_out when 144 => SRRC_out when 145 => SRRC_out when 146 => SRRC_out when 147 => SRRC_out when 148 => SRRC_out when 149 => SRRC_out when 150 => SRRC_out when 151 => SRRC_out when 152 => SRRC_out when 153 => SRRC_out when 154 => SRRC_out when 155 => SRRC_out when 156 => SRRC_out when 157 => SRRC_out when 158 => SRRC_out when 159 => SRRC_out when 160 => SRRC_out when 161 => SRRC_out when 162 => SRRC_out when 163 => SRRC_out when 164 => SRRC_out when 165 => SRRC_out when 166 => SRRC_out when 167 => SRRC_out when 168 => SRRC_out when 169 => SRRC_out when 170 => SRRC_out when 171 => SRRC_out when 172 => SRRC_out when 173 => SRRC_out when 174 => SRRC_out when 175 => SRRC_out when 176 => SRRC_out when 177 => SRRC_out when 178 => SRRC_out when 179 => SRRC_out when 180 => SRRC_out when 181 => SRRC_out when 182 => SRRC_out when 183 => SRRC_out when 184 => SRRC_out when 185 => SRRC_out when 186 => SRRC_out when 187 => SRRC_out when 188 => SRRC_out when 189 => SRRC_out when 190 => SRRC_out when 191 => SRRC_out when 192 => SRRC_out when 193 => SRRC_out when 194 => SRRC_out when 195 => SRRC_out when 196 => SRRC_out when 197 => SRRC_out when 198 => SRRC_out when 199 => SRRC_out when 200 => SRRC_out when 201 => SRRC_out when 202 => SRRC_out when 203 => SRRC_out when 204 => SRRC_out when 205 => SRRC_out when 206 => SRRC_out when 207 => SRRC_out when 208 => SRRC_out <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= X"DB8"; X"DB8"; X"DAC"; X"DAC"; X"E45"; X"E45"; X"E39"; X"E39"; X"A69"; X"A69"; X"A5D"; X"A5D"; X"AF7"; X"AF7"; X"AEB"; X"AEB"; <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= X"513"; X"513"; X"4D3"; X"4D3"; X"656"; X"656"; X"616"; X"616"; X"EFC"; X"EFC"; X"EBD"; X"EBD"; X"040"; X"040"; X"000"; X"000"; X"EFC"; X"EFC"; X"EBD"; X"EBD"; X"040"; X"040"; X"000"; X"000"; X"8E6"; X"8E6"; X"8A6"; X"8A6"; X"A29"; X"A29"; X"9EA"; X"9EA"; X"656"; X"656"; X"616"; X"616"; X"79A"; X"79A"; X"75A"; X"75A"; X"040"; X"040"; X"000"; X"000"; X"183"; X"183"; X"143"; X"143"; X"040"; X"040"; X"000"; X"000"; X"183"; X"183"; X"143"; X"143"; X"A29"; X"A29"; X"9EA"; X"9EA"; X"B6D"; X"B6D"; X"B2D"; X"B2D"; X"4D3"; X"4D3"; X"493"; X"493"; X"616"; X"616"; X"5D7"; X"5D7"; X"EBD"; X"EBD"; X"E7D"; X"E7D"; X"000"; X"000"; X"FC0"; X"FC0"; X"EBD"; 155 APPENDICE F. LISTATI VHDL 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 when 209 => SRRC_out when 210 => SRRC_out when 211 => SRRC_out when 212 => SRRC_out when 213 => SRRC_out when 214 => SRRC_out when 215 => SRRC_out when 216 => SRRC_out when 217 => SRRC_out when 218 => SRRC_out when 219 => SRRC_out when 220 => SRRC_out when 221 => SRRC_out when 222 => SRRC_out when 223 => SRRC_out when 224 => SRRC_out when 225 => SRRC_out when 226 => SRRC_out when 227 => SRRC_out when 228 => SRRC_out when 229 => SRRC_out when 230 => SRRC_out when 231 => SRRC_out when 232 => SRRC_out when 233 => SRRC_out when 234 => SRRC_out when 235 => SRRC_out when 236 => SRRC_out when 237 => SRRC_out when 238 => SRRC_out when 239 => SRRC_out when 240 => SRRC_out when 241 => SRRC_out when 242 => SRRC_out when 243 => SRRC_out when 244 => SRRC_out when 245 => SRRC_out when 246 => SRRC_out when 247 => SRRC_out when 248 => SRRC_out when 249 => SRRC_out when 250 => SRRC_out when 251 => SRRC_out when 252 => SRRC_out when 253 => SRRC_out when 254 => SRRC_out when 255 => SRRC_out -- somme per il FIR 2 when 256 => SRRC_out when 257 => SRRC_out when 258 => SRRC_out when 259 => SRRC_out when 260 => SRRC_out when 261 => SRRC_out when 262 => SRRC_out when 263 => SRRC_out when 264 => SRRC_out when 265 => SRRC_out when 266 => SRRC_out when 267 => SRRC_out when 268 => SRRC_out when 269 => SRRC_out when 270 => SRRC_out when 271 => SRRC_out when 272 => SRRC_out when 273 => SRRC_out when 274 => SRRC_out when 275 => SRRC_out when 276 => SRRC_out when 277 => SRRC_out when 278 => SRRC_out when 279 => SRRC_out when 280 => SRRC_out when 281 => SRRC_out when 282 => SRRC_out when 283 => SRRC_out when 284 => SRRC_out when 285 => SRRC_out when 286 => SRRC_out when 287 => SRRC_out when 288 => SRRC_out when 289 => SRRC_out when 290 => SRRC_out when 291 => SRRC_out when 292 => SRRC_out when 293 => SRRC_out when 294 => SRRC_out when 295 => SRRC_out when 296 => SRRC_out when 297 => SRRC_out when 298 => SRRC_out when 299 => SRRC_out when 300 => SRRC_out when 301 => SRRC_out when 302 => SRRC_out when 303 => SRRC_out when 304 => SRRC_out when 305 => SRRC_out <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= X"EBD"; X"E7D"; X"E7D"; X"000"; X"000"; X"FC0"; X"FC0"; X"8A6"; X"8A6"; X"866"; X"866"; X"9EA"; X"9EA"; X"9AA"; X"9AA"; X"616"; X"616"; X"5D7"; X"5D7"; X"75A"; X"75A"; X"71A"; X"71A"; X"000"; X"000"; X"FC0"; X"FC0"; X"143"; X"143"; X"104"; X"104"; X"000"; X"000"; X"FC0"; X"FC0"; X"143"; X"143"; X"104"; X"104"; X"9EA"; X"9EA"; X"9AA"; X"9AA"; X"B2D"; X"B2D"; X"AED"; X"AED"; <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= X"515"; X"515"; X"49F"; X"49F"; X"6D8"; X"6D8"; X"661"; X"661"; X"C6C"; X"C6C"; X"BF6"; X"BF6"; X"E2E"; X"E2E"; X"DB8"; X"DB8"; X"1C7"; X"1C7"; X"150"; X"150"; X"389"; X"389"; X"313"; X"313"; X"91D"; X"91D"; X"8A7"; X"8A7"; X"AE0"; X"AE0"; X"A69"; X"A69"; X"5A3"; X"5A3"; X"52C"; X"52C"; X"765"; X"765"; X"6EF"; X"6EF"; X"CF9"; X"CF9"; X"C83"; X"C83"; X"EBC"; X"EBC"; X"E45"; X"E45"; X"254"; X"254"; 156 APPENDICE F. LISTATI VHDL 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 when 306 => SRRC_out when 307 => SRRC_out when 308 => SRRC_out when 309 => SRRC_out when 310 => SRRC_out when 311 => SRRC_out when 312 => SRRC_out when 313 => SRRC_out when 314 => SRRC_out when 315 => SRRC_out when 316 => SRRC_out when 317 => SRRC_out when 318 => SRRC_out when 319 => SRRC_out when 320 => SRRC_out when 321 => SRRC_out when 322 => SRRC_out when 323 => SRRC_out when 324 => SRRC_out when 325 => SRRC_out when 326 => SRRC_out when 327 => SRRC_out when 328 => SRRC_out when 329 => SRRC_out when 330 => SRRC_out when 331 => SRRC_out when 332 => SRRC_out when 333 => SRRC_out when 334 => SRRC_out when 335 => SRRC_out when 336 => SRRC_out when 337 => SRRC_out when 338 => SRRC_out when 339 => SRRC_out when 340 => SRRC_out when 341 => SRRC_out when 342 => SRRC_out when 343 => SRRC_out when 344 => SRRC_out when 345 => SRRC_out when 346 => SRRC_out when 347 => SRRC_out when 348 => SRRC_out when 349 => SRRC_out when 350 => SRRC_out when 351 => SRRC_out when 352 => SRRC_out when 353 => SRRC_out when 354 => SRRC_out when 355 => SRRC_out when 356 => SRRC_out when 357 => SRRC_out when 358 => SRRC_out when 359 => SRRC_out when 360 => SRRC_out when 361 => SRRC_out when 362 => SRRC_out when 363 => SRRC_out when 364 => SRRC_out when 365 => SRRC_out when 366 => SRRC_out when 367 => SRRC_out when 368 => SRRC_out when 369 => SRRC_out when 370 => SRRC_out when 371 => SRRC_out when 372 => SRRC_out when 373 => SRRC_out when 374 => SRRC_out when 375 => SRRC_out when 376 => SRRC_out when 377 => SRRC_out when 378 => SRRC_out when 379 => SRRC_out when 380 => SRRC_out when 381 => SRRC_out when 382 => SRRC_out when 383 => SRRC_out -- somme per il FIR 3 when 384 => SRRC_out when 385 => SRRC_out when 386 => SRRC_out when 387 => SRRC_out when 388 => SRRC_out when 389 => SRRC_out when 390 => SRRC_out when 391 => SRRC_out when 392 => SRRC_out when 393 => SRRC_out when 394 => SRRC_out when 395 => SRRC_out when 396 => SRRC_out when 397 => SRRC_out when 398 => SRRC_out when 399 => SRRC_out when 400 => SRRC_out when 401 => SRRC_out when 402 => SRRC_out <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= X"1DD"; X"1DD"; X"416"; X"416"; X"3A0"; X"3A0"; X"9AA"; X"9AA"; X"934"; X"934"; X"B6D"; X"B6D"; X"AF7"; X"AF7"; X"509"; X"509"; X"493"; X"493"; X"6CC"; X"6CC"; X"656"; X"656"; X"C60"; X"C60"; X"BEA"; X"BEA"; X"E23"; X"E23"; X"DAC"; X"DAC"; X"1BB"; X"1BB"; X"144"; X"144"; X"37D"; X"37D"; X"307"; X"307"; X"911"; X"911"; X"89B"; X"89B"; X"AD4"; X"AD4"; X"A5D"; X"A5D"; X"597"; X"597"; X"520"; X"520"; X"759"; X"759"; X"6E3"; X"6E3"; X"CED"; X"CED"; X"C77"; X"C77"; X"EB0"; X"EB0"; X"E39"; X"E39"; X"248"; X"248"; X"1D2"; X"1D2"; X"40A"; X"40A"; X"394"; X"394"; X"99F"; X"99F"; X"928"; X"928"; X"B61"; X"B61"; X"AEB"; X"AEB"; X"505"; X"52F"; X"471"; X"49B"; X"6BB"; X"6E6"; X"628"; X"652"; X"A8A"; X"AB4"; X"9F6"; X"A21"; X"C41"; X"C6B"; X"BAD"; X"BD7"; X"429"; X"453"; X"395"; 157 APPENDICE F. LISTATI VHDL 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when when 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => => SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out SRRC_out <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= X"3BF"; X"5DF"; X"60A"; X"54B"; X"576"; X"9AE"; X"9D8"; X"91A"; X"944"; X"B64"; X"B8F"; X"AD1"; X"AFB"; X"4EF"; X"519"; X"45B"; X"485"; X"6A5"; X"6D0"; X"611"; X"63C"; X"A74"; X"A9E"; X"9E0"; X"A0A"; X"C2A"; X"C55"; X"B96"; X"BC1"; X"413"; X"43D"; X"37F"; X"3A9"; X"5C9"; X"5F4"; X"535"; X"560"; X"998"; X"9C2"; X"904"; X"92E"; X"B4E"; X"B79"; X"ABA"; X"AE5"; X"51B"; X"546"; X"487"; X"4B2"; X"6D2"; X"6FC"; X"63E"; X"668"; X"AA0"; X"ACB"; X"A0C"; X"A37"; X"C57"; X"C81"; X"BC3"; X"BED"; X"43F"; X"46A"; X"3AB"; X"3D6"; X"5F6"; X"620"; X"562"; X"58C"; X"9C4"; X"9EF"; X"930"; X"95B"; X"B7B"; X"BA5"; X"AE7"; X"B11"; X"505"; X"52F"; X"471"; X"49C"; X"6BC"; X"6E6"; X"628"; X"652"; X"A8A"; X"AB5"; X"9F6"; X"A21"; X"C41"; X"C6B"; X"BAD"; X"BD7"; X"429"; X"453"; X"395"; X"3BF"; X"5DF"; 158 APPENDICE F. LISTATI VHDL 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 when 501 => SRRC_out when 502 => SRRC_out when 503 => SRRC_out when 504 => SRRC_out when 505 => SRRC_out when 506 => SRRC_out when 507 => SRRC_out when 508 => SRRC_out when 509 => SRRC_out when 510 => SRRC_out when 511 => SRRC_out -- somme per il FIR 4 when 512 => SRRC_out when 513 => SRRC_out when 514 => SRRC_out when 515 => SRRC_out when 516 => SRRC_out when 517 => SRRC_out when 518 => SRRC_out when 519 => SRRC_out when 520 => SRRC_out when 521 => SRRC_out when 522 => SRRC_out when 523 => SRRC_out when 524 => SRRC_out when 525 => SRRC_out when 526 => SRRC_out when 527 => SRRC_out when 528 => SRRC_out when 529 => SRRC_out when 530 => SRRC_out when 531 => SRRC_out when 532 => SRRC_out when 533 => SRRC_out when 534 => SRRC_out when 535 => SRRC_out when 536 => SRRC_out when 537 => SRRC_out when 538 => SRRC_out when 539 => SRRC_out when 540 => SRRC_out when 541 => SRRC_out when 542 => SRRC_out when 543 => SRRC_out when 544 => SRRC_out when 545 => SRRC_out when 546 => SRRC_out when 547 => SRRC_out when 548 => SRRC_out when 549 => SRRC_out when 550 => SRRC_out when 551 => SRRC_out when 552 => SRRC_out when 553 => SRRC_out when 554 => SRRC_out when 555 => SRRC_out when 556 => SRRC_out when 557 => SRRC_out when 558 => SRRC_out when 559 => SRRC_out when 560 => SRRC_out when 561 => SRRC_out when 562 => SRRC_out when 563 => SRRC_out when 564 => SRRC_out when 565 => SRRC_out when 566 => SRRC_out when 567 => SRRC_out when 568 => SRRC_out when 569 => SRRC_out when 570 => SRRC_out when 571 => SRRC_out when 572 => SRRC_out when 573 => SRRC_out when 574 => SRRC_out when 575 => SRRC_out when 576 => SRRC_out when 577 => SRRC_out when 578 => SRRC_out when 579 => SRRC_out when 580 => SRRC_out when 581 => SRRC_out when 582 => SRRC_out when 583 => SRRC_out when 584 => SRRC_out when 585 => SRRC_out when 586 => SRRC_out when 587 => SRRC_out when 588 => SRRC_out when 589 => SRRC_out when 590 => SRRC_out when 591 => SRRC_out when 592 => SRRC_out when 593 => SRRC_out when 594 => SRRC_out when 595 => SRRC_out when 596 => SRRC_out when 597 => SRRC_out <= <= <= <= <= <= <= <= <= <= <= X"60A"; X"54C"; X"576"; X"9AE"; X"9D8"; X"91A"; X"945"; X"B65"; X"B8F"; X"AD1"; X"AFB"; <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= X"508"; X"52D"; X"48E"; X"4B4"; X"5E5"; X"60B"; X"56C"; X"591"; X"9E5"; X"A0B"; X"96B"; X"991"; X"AC2"; X"AE8"; X"A49"; X"A6F"; X"5E5"; X"60B"; X"56C"; X"591"; X"6C3"; X"6E9"; X"649"; X"66F"; X"AC2"; X"AE8"; X"A49"; X"A6F"; X"BA0"; X"BC6"; X"B26"; X"B4C"; X"48E"; X"4B4"; X"414"; X"43A"; X"56C"; X"591"; X"4F2"; X"518"; X"96B"; X"991"; X"8F1"; X"917"; X"A49"; X"A6F"; X"9CF"; X"9F5"; X"56C"; X"591"; X"4F2"; X"518"; X"649"; X"66F"; X"5D0"; X"5F5"; X"A49"; X"A6F"; X"9CF"; X"9F5"; X"B26"; X"B4C"; X"AAD"; X"AD3"; X"52D"; X"553"; X"4B4"; X"4DA"; X"60B"; X"631"; X"591"; X"5B7"; X"A0B"; X"A30"; X"991"; X"9B7"; X"AE8"; X"B0E"; X"A6F"; X"A94"; X"60B"; X"631"; X"591"; X"5B7"; X"6E9"; X"70F"; 159 APPENDICE F. LISTATI VHDL 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 when 598 => SRRC_out when 599 => SRRC_out when 600 => SRRC_out when 601 => SRRC_out when 602 => SRRC_out when 603 => SRRC_out when 604 => SRRC_out when 605 => SRRC_out when 606 => SRRC_out when 607 => SRRC_out when 608 => SRRC_out when 609 => SRRC_out when 610 => SRRC_out when 611 => SRRC_out when 612 => SRRC_out when 613 => SRRC_out when 614 => SRRC_out when 615 => SRRC_out when 616 => SRRC_out when 617 => SRRC_out when 618 => SRRC_out when 619 => SRRC_out when 620 => SRRC_out when 621 => SRRC_out when 622 => SRRC_out when 623 => SRRC_out when 624 => SRRC_out when 625 => SRRC_out when 626 => SRRC_out when 627 => SRRC_out when 628 => SRRC_out when 629 => SRRC_out when 630 => SRRC_out when 631 => SRRC_out when 632 => SRRC_out when 633 => SRRC_out when 634 => SRRC_out when 635 => SRRC_out when 636 => SRRC_out when 637 => SRRC_out when 638 => SRRC_out when 639 => SRRC_out -- somme per il FIR 5 when 640 => SRRC_out when 641 => SRRC_out when 642 => SRRC_out when 643 => SRRC_out when 644 => SRRC_out when 645 => SRRC_out when 646 => SRRC_out when 647 => SRRC_out when 648 => SRRC_out when 649 => SRRC_out when 650 => SRRC_out when 651 => SRRC_out when 652 => SRRC_out when 653 => SRRC_out when 654 => SRRC_out when 655 => SRRC_out when 656 => SRRC_out when 657 => SRRC_out when 658 => SRRC_out when 659 => SRRC_out when 660 => SRRC_out when 661 => SRRC_out when 662 => SRRC_out when 663 => SRRC_out when 664 => SRRC_out when 665 => SRRC_out when 666 => SRRC_out when 667 => SRRC_out when 668 => SRRC_out when 669 => SRRC_out when 670 => SRRC_out when 671 => SRRC_out when 672 => SRRC_out when 673 => SRRC_out when 674 => SRRC_out when 675 => SRRC_out when 676 => SRRC_out when 677 => SRRC_out when 678 => SRRC_out when 679 => SRRC_out when 680 => SRRC_out when 681 => SRRC_out when 682 => SRRC_out when 683 => SRRC_out when 684 => SRRC_out when 685 => SRRC_out when 686 => SRRC_out when 687 => SRRC_out when 688 => SRRC_out when 689 => SRRC_out when 690 => SRRC_out when 691 => SRRC_out when 692 => SRRC_out when 693 => SRRC_out when 694 => SRRC_out <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= <= X"66F"; X"695"; X"AE8"; X"B0E"; X"A6F"; X"A94"; X"BC6"; X"BEC"; X"B4C"; X"B72"; X"4B4"; X"4DA"; X"43A"; X"460"; X"591"; X"5B7"; X"518"; X"53E"; X"991"; X"9B7"; X"917"; X"93D"; X"A6F"; X"A94"; X"9F5"; X"A1B"; X"591"; X"5B7"; X"518"; X"53E"; X"66F"; X"695"; X"5F5"; X"61B"; X"A6F"; X"A94"; X"9F5"; X"A1B"; X"B4C"; X"B72"; X"AD3"; X"AF8"; X"505"; X"51B"; X"4EF"; X"505"; X"429"; X"43F"; X"413"; X"429"; X"A8A"; X"AA0"; X"A74"; X"A8A"; X"9AE"; X"9C4"; X"998"; X"9AE"; X"6BB"; X"6D2"; X"6A5"; X"6BC"; X"5DF"; X"5F6"; X"5C9"; X"5DF"; X"C41"; X"C57"; X"C2A"; X"C41"; X"B64"; X"B7B"; X"B4E"; X"B65"; X"471"; X"487"; X"45B"; X"471"; X"395"; X"3AB"; X"37F"; X"395"; X"9F6"; X"A0C"; X"9E0"; X"9F6"; X"91A"; X"930"; X"904"; X"91A"; X"628"; X"63E"; X"611"; X"628"; X"54B"; X"562"; X"535"; 160 APPENDICE F. LISTATI VHDL 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 when 695 => SRRC_out <= X"54C"; when 696 => SRRC_out <= X"BAD"; when 697 => SRRC_out <= X"BC3"; when 698 => SRRC_out <= X"B96"; when 699 => SRRC_out <= X"BAD"; when 700 => SRRC_out <= X"AD1"; when 701 => SRRC_out <= X"AE7"; when 702 => SRRC_out <= X"ABA"; when 703 => SRRC_out <= X"AD1"; when 704 => SRRC_out <= X"52F"; when 705 => SRRC_out <= X"546"; when 706 => SRRC_out <= X"519"; when 707 => SRRC_out <= X"52F"; when 708 => SRRC_out <= X"453"; when 709 => SRRC_out <= X"46A"; when 710 => SRRC_out <= X"43D"; when 711 => SRRC_out <= X"453"; when 712 => SRRC_out <= X"AB4"; when 713 => SRRC_out <= X"ACB"; when 714 => SRRC_out <= X"A9E"; when 715 => SRRC_out <= X"AB5"; when 716 => SRRC_out <= X"9D8"; when 717 => SRRC_out <= X"9EF"; when 718 => SRRC_out <= X"9C2"; when 719 => SRRC_out <= X"9D8"; when 720 => SRRC_out <= X"6E6"; when 721 => SRRC_out <= X"6FC"; when 722 => SRRC_out <= X"6D0"; when 723 => SRRC_out <= X"6E6"; when 724 => SRRC_out <= X"60A"; when 725 => SRRC_out <= X"620"; when 726 => SRRC_out <= X"5F4"; when 727 => SRRC_out <= X"60A"; when 728 => SRRC_out <= X"C6B"; when 729 => SRRC_out <= X"C81"; when 730 => SRRC_out <= X"C55"; when 731 => SRRC_out <= X"C6B"; when 732 => SRRC_out <= X"B8F"; when 733 => SRRC_out <= X"BA5"; when 734 => SRRC_out <= X"B79"; when 735 => SRRC_out <= X"B8F"; when 736 => SRRC_out <= X"49B"; when 737 => SRRC_out <= X"4B2"; when 738 => SRRC_out <= X"485"; when 739 => SRRC_out <= X"49C"; when 740 => SRRC_out <= X"3BF"; when 741 => SRRC_out <= X"3D6"; when 742 => SRRC_out <= X"3A9"; when 743 => SRRC_out <= X"3BF"; when 744 => SRRC_out <= X"A21"; when 745 => SRRC_out <= X"A37"; when 746 => SRRC_out <= X"A0A"; when 747 => SRRC_out <= X"A21"; when 748 => SRRC_out <= X"944"; when 749 => SRRC_out <= X"95B"; when 750 => SRRC_out <= X"92E"; when 751 => SRRC_out <= X"945"; when 752 => SRRC_out <= X"652"; when 753 => SRRC_out <= X"668"; when 754 => SRRC_out <= X"63C"; when 755 => SRRC_out <= X"652"; when 756 => SRRC_out <= X"576"; when 757 => SRRC_out <= X"58C"; when 758 => SRRC_out <= X"560"; when 759 => SRRC_out <= X"576"; when 760 => SRRC_out <= X"BD7"; when 761 => SRRC_out <= X"BED"; when 762 => SRRC_out <= X"BC1"; when 763 => SRRC_out <= X"BD7"; when 764 => SRRC_out <= X"AFB"; when 765 => SRRC_out <= X"B11"; when 766 => SRRC_out <= X"AE5"; when 767 => SRRC_out <= X"AFB"; when OTHERS => SRRC_out <= X"000"; end case; end process; end ROMx6_arch; Listato F.3.9: 1 2 3 4 5 6 7 8 9 10 11 12 161 library IEEE; use IEEE.std_logic_1164.all; entity shift_reg is port ( clk : in std_logic ; clk_en : in std_logic ; reset : in std_logic ; in_reg : in std_logic ; out_ffd_1 : out std_logic ; out_ffd_2 : out std_logic ; out_ffd_3 : out std_logic ; shift reg.vhd APPENDICE F. LISTATI VHDL out_ffd_4 : out std_logic ; out_ffd_5 : out std_logic ; out_ffd_6 : out std_logic 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 architecture shift_reg_arch of shift_reg is signal temp_out_reg : std_logic_vector(5 downto 0); begin process(clk, clk_en, reset) begin if reset = ’1’ then temp_out_reg <= "000000"; elsif rising_edge(clk) then if clk_en = ’1’ then temp_out_reg <= in_reg & temp_out_reg(5 downto 1); end if; end if; end process; out_ffd_6 <= temp_out_reg(0); out_ffd_5 <= temp_out_reg(1); out_ffd_4 <= temp_out_reg(2); out_ffd_3 <= temp_out_reg(3); out_ffd_2 <= temp_out_reg(4); out_ffd_1 <= temp_out_reg(5); end architecture; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 library IEEE; use IEEE.std_logic_1164.all; entity Modulator_BlockRAM is port( clk : in STD_LOGIC; reset : in STD_LOGIC; to_SRRC_I : in STD_LOGIC; to_SRRC_Q : in STD_LOGIC; rate_sel : in STD_LOGIC_VECTOR(1 downto 0); clk_2_analyzer : out STD_LOGIC; QPSK_out : out STD_LOGIC_VECTOR(11 downto 0) ); end Modulator_BlockRAM; architecture Modulator_BlockRAM of Modulator_BlockRAM is component adder_I_Q port ( QPSK_I : in STD_LOGIC_VECTOR(11 downto 0); QPSK_Q : in STD_LOGIC_VECTOR(11 downto 0); clk : in STD_LOGIC; reset : in STD_LOGIC; QPSK_out : out STD_LOGIC_VECTOR(11 downto 0) ); end component; component counter port ( clk : in STD_LOGIC; rate_sel : in STD_LOGIC_VECTOR(1 downto 0); reset : in STD_LOGIC; clk_en : out STD_LOGIC; count : out STD_LOGIC_VECTOR(2 downto 0) ); end component; component multiplier_I_Q port ( clk : in STD_LOGIC; from_NCO : in STD_LOGIC_VECTOR(1 downto 0); from_SRRC : in STD_LOGIC_VECTOR(11 downto 0); out_mult : out STD_LOGIC_VECTOR(11 downto 0) ); end component; component NCO_basic port ( clk : in STD_LOGIC; reset : in STD_LOGIC; cosine : out STD_LOGIC_VECTOR(1 downto 0); sine : out STD_LOGIC_VECTOR(1 downto 0) ); end component; component srrc_x_n port ( clk : in STD_LOGIC; clk_en : in STD_LOGIC; fir_sel : in STD_LOGIC_VECTOR(2 downto 0); in_fir_MSB : in STD_LOGIC; rate_sel : in STD_LOGIC_VECTOR(1 downto 0); reset : in STD_LOGIC; out_srrc : out STD_LOGIC_VECTOR(11 downto 0) ); end entity; Listato F.4.1: Modulator BlockRAM.vhd 162 APPENDICE F. LISTATI VHDL 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 ); end component; ---- Signal declarations used on the diagram ---signal clk_en : STD_LOGIC; signal cosine : STD_LOGIC_VECTOR (1 downto 0); signal count_n : STD_LOGIC_VECTOR (2 downto 0); signal QPSK_I : STD_LOGIC_VECTOR (11 downto 0); signal QPSK_Q : STD_LOGIC_VECTOR (11 downto 0); signal sine : STD_LOGIC_VECTOR (1 downto 0); signal to_mult_I : STD_LOGIC_VECTOR (11 downto 0); signal to_mult_Q : STD_LOGIC_VECTOR (11 downto 0); begin U1 : srrc_x_n port map( clk => clk, clk_en => clk_en, fir_sel => count_n, in_fir_MSB => to_SRRC_I, out_srrc => to_mult_I, rate_sel => rate_sel, reset => reset ); U2 : srrc_x_n port map( clk => clk, clk_en => clk_en, fir_sel => count_n, in_fir_MSB => to_SRRC_Q, out_srrc => to_mult_Q, rate_sel => rate_sel, reset => reset ); U3 : counter port map( clk => clk, clk_en => clk_en, count => count_n, rate_sel => rate_sel, reset => reset ); U4 : multiplier_I_Q port map( clk => clk, from_NCO => sine, from_SRRC => to_mult_Q, out_mult => QPSK_Q ); U5 : multiplier_I_Q port map( clk => clk, from_NCO => cosine, from_SRRC => to_mult_I, out_mult => QPSK_I ); U6 : NCO_basic port map( clk => clk, cosine => cosine, reset => reset, sine => sine ); U7 : adder_I_Q port map( QPSK_I => QPSK_I, QPSK_Q => QPSK_Q, QPSK_out => QPSK_out, clk => clk, reset => reset ); clk_2_analyzer <= clk; end Modulator_BlockRAM; Listato F.4.2: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 163 adder I Q.vhd library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_signed.all; entity adder_I_Q is port(QPSK_I, QPSK_Q : in std_logic_vector(11 downto 0); clk , reset : in std_logic; QPSK_out : out std_logic_vector(11 downto 0)); end adder_I_Q ; architecture adder_I_Q_arch of adder_I_Q is begin process(reset, clk , QPSK_I , QPSK_Q) begin if falling_edge(clk) then APPENDICE F. LISTATI VHDL 16 17 18 19 20 21 22 23 164 if reset = ’1’ then QPSK_out <= "000000000000"; else QPSK_out <= QPSK_I + QPSK_Q ; end if; else null ; end if ; end process; end adder_I_Q_arch ; Listato F.4.3: counter.vhd vedi listato(F.3.2) Listato F.4.4: multiplier I Q.vhd 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_signed.all; entity multiplier_I_Q is port( from_SRRC : in std_logic_vector(11 downto 0); from_NCO : in std_logic_vector( 1 downto 0); clk : in std_logic ; out_mult : out std_logic_vector(11 downto 0)); end multiplier_I_Q; architecture multiplier_I_Q_arch of multiplier_I_Q is begin process(clk, from_SRRC ,from_NCO) variable temp : std_logic_vector(11 downto 0); begin if falling_edge(clk) then temp(11 downto 0) := from_SRRC ; case from_NCO is when "11" => temp := ("111111111111" xor temp)+1 ; when "01" => null ; when others => temp := "000000000000" ; end case; out_mult(11 downto 0) <= temp(11 downto 0) ; else null; end if; end process; end multiplier_I_Q_arch; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_signed.all; entity NCO_basic is port( clk : in std_logic ; reset : in std_logic ; cosine : out std_logic_vector(1 downto 0); sine : out std_logic_vector(1 downto 0) ); end NCO_basic; Listato F.4.5: NCO basic.vhd architecture NCO_basic_arch of NCO_basic is signal count_4 : STD_LOGIC_VECTOR (1 downto 0) ; begin process (clk, reset) begin if reset=’1’ then count_4 <= "00"; else if falling_edge(clk) then count_4 <= count_4 + 1 ; else null ; end if; end if; end process; process (clk, count_4) APPENDICE F. LISTATI VHDL 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 begin if falling_edge(clk) then case count_4 is when "00" => cosine <= "01" ; sine <= "00" ; when "01" => cosine <= "00" ; sine <= "11" ; when "10" => cosine <= "11" ; sine <= "00" ; when "11" => cosine <= "00" ; sine <= "01" ; when others => cosine <= "XX" ; sine <= "XX" ; end case; else null; end if; end process; end NCO_basic_arch; Listato F.4.6: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 165 srrc x n.vhd library IEEE; use IEEE.std_logic_1164.all; entity srrc_x_n is port( clk : in STD_LOGIC; clk_en : in STD_LOGIC; in_fir_MSB : in STD_LOGIC; reset : in STD_LOGIC; fir_sel : in STD_LOGIC_VECTOR(2 downto 0); rate_sel : in STD_LOGIC_VECTOR(1 downto 0); out_srrc : out STD_LOGIC_VECTOR(11 downto 0) ); end srrc_x_n; architecture srrc_x_n of srrc_x_n is component shift_reg port ( clk : in STD_LOGIC; clk_en : in STD_LOGIC; in_reg : in STD_LOGIC; reset : in STD_LOGIC; out_ffd_1 : out STD_LOGIC; out_ffd_2 : out STD_LOGIC; out_ffd_3 : out STD_LOGIC; out_ffd_4 : out STD_LOGIC; out_ffd_5 : out STD_LOGIC; out_ffd_6 : out STD_LOGIC ); end component; component ram port ( addr : in STD_LOGIC_VECTOR(11 downto 0); clk : in STD_LOGIC; dout : out STD_LOGIC_VECTOR(11 downto 0) ); end component; signal address : STD_LOGIC_VECTOR (11 downto 0); begin U1 : shift_reg port map( clk => clk, clk_en => clk_en, in_reg => address(0), out_ffd_1 => address(1), out_ffd_2 => address(2), out_ffd_3 => address(3), out_ffd_4 => address(4), out_ffd_5 => address(5), out_ffd_6 => address(6), reset => reset ); U3 : ram port map( addr => address, clk => clk, dout => out_srrc ); address(7) <= fir_sel(0); address(8) <= fir_sel(1); address(9) <= fir_sel(2); address(0) <= in_fir_MSB; address(10) <= rate_sel(0); address(11) <= rate_sel(1); APPENDICE F. LISTATI VHDL 166 66 end srrc_x_n; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 -- synopsys translate_off LIBRARY ieee; USE ieee.std_logic_1164.ALL; Library XilinxCoreLib; ENTITY ram IS port ( addr : IN std_logic_VECTOR(11 downto 0); clk : IN std_logic; dout : OUT std_logic_VECTOR(11 downto 0)); END ram; ARCHITECTURE ram_a OF ram IS component wrapped_ram port ( addr : IN std_logic_VECTOR(11 downto 0); clk : IN std_logic; dout : OUT std_logic_VECTOR(11 downto 0)); end component; -- Configuration specification for all : wrapped_ram use entity XilinxCoreLib.blkmemsp_v3_1(behavioral) generic map( c_reg_inputs => 0, c_addr_width => 12, c_has_sinit => 0, c_has_rdy => 0, c_width => 12, c_has_en => 0, c_mem_init_file => "ram.mif", c_depth => 4096, c_has_nd => 0, c_has_default_data => 0, c_default_data => "0", c_limit_data_pitch => 8, c_pipe_stages => 0, c_has_rfd => 0, c_has_we => 0, c_sinit_value => "0", c_has_limit_data_pitch => 0, c_enable_rlocs => 0, c_has_din => 0, c_write_mode => 0); BEGIN U0 : wrapped_ram port map ( addr => addr, clk => clk, dout => dout); END ram_a; -- synopsys translate_on Listato F.4.7: ram.vhd Listato F.4.8: shift reg.vhd vedi listato(F.3.9) Listato F.5.1: 1 2 3 4 5 6 7 8 9 10 FIFO RAM ThinModulator.vhd library IEEE; use IEEE.std_logic_1164.all; library unisim; use unisim.vcomponents.all; entity FIFO_RAM_ThinModulator is port( clk : in STD_LOGIC; count_clk_en_reset : in STD_LOGIC; APPENDICE F. LISTATI VHDL 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 data_in_I : in STD_LOGIC; data_in_Q : in STD_LOGIC; data_in_clk : in std_ulogic; reset : in STD_LOGIC; rate_sel : in STD_LOGIC_VECTOR(1 downto 0); data_in_clk_sync : out STD_LOGIC; data_out_clk : out STD_LOGIC; modulator_out : out STD_LOGIC_VECTOR(11 downto 0) ); end FIFO_RAM_ThinModulator; architecture FIFO_RAM_ThinModulator of FIFO_RAM_ThinModulator is component counter port ( clk : in STD_LOGIC; rate_sel : in STD_LOGIC_VECTOR(1 downto 0); reset : in STD_LOGIC; clk_en : out STD_LOGIC; count : out STD_LOGIC_VECTOR(2 downto 0) ); end component; component Data_Source_Interface port ( I_to_fifo : in STD_LOGIC; Q_to_fifo : in STD_LOGIC; clk : in STD_LOGIC; clk_en : in STD_LOGIC; data_in_clk : in STD_LOGIC; reset : in STD_LOGIC; I_from_fifo : out STD_LOGIC; Q_from_fifo : out STD_LOGIC ); end component; component ThinModulator port ( I_in_fir_MSB : in STD_LOGIC; Q_in_fir_MSB : in STD_LOGIC; clk : in STD_LOGIC; clk_en : in STD_LOGIC; fir_sel : in STD_LOGIC_VECTOR(2 downto 0); rate_sel : in STD_LOGIC_VECTOR(1 downto 0); reset : in STD_LOGIC; QPSK_out : out STD_LOGIC_VECTOR(11 downto 0) ); end component; component IBUFG port ( I : in std_ulogic; O : out std_ulogic ); end component; signal clk_en : STD_LOGIC; signal clk_to_fifo : STD_LOGIC; signal I_data_from_fifo : STD_LOGIC; signal Q_data_from_fifo : STD_LOGIC; signal fir_sel : STD_LOGIC_VECTOR (2 downto 0); for U4 : IBUFG use entity virtex.IBUFG; begin U1 : Data_Source_Interface port map( I_from_fifo => I_data_from_fifo, I_to_fifo => data_in_I, Q_from_fifo => Q_data_from_fifo, Q_to_fifo => data_in_Q, clk => clk, clk_en => clk_en, data_in_clk => clk_to_fifo, reset => reset ); U2 : ThinModulator port map( I_in_fir_MSB => I_data_from_fifo, QPSK_out => modulator_out, Q_in_fir_MSB => Q_data_from_fifo, clk => clk, clk_en => clk_en, fir_sel => fir_sel, rate_sel => rate_sel, reset => reset ); U3 : counter port map( clk => clk, clk_en => clk_en, count => fir_sel, rate_sel => rate_sel, reset => count_clk_en_reset ); U4 : IBUFG port map( I => data_in_clk, O => clk_to_fifo ); data_in_clk_sync <= clk_en; 167 APPENDICE F. LISTATI VHDL 106 107 data_out_clk <= clk; end FIFO_RAM_ThinModulator; Listato F.5.2: counter.vhd vedi listato(F.3.2) Listato F.5.3: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 Data Source Interface.vhd library IEEE; use IEEE.std_logic_1164.all; entity Data_Source_Interface is port( I_to_fifo : in STD_LOGIC; Q_to_fifo : in STD_LOGIC; clk : in STD_LOGIC; clk_en : in STD_LOGIC; data_in_clk : in STD_LOGIC; reset : in STD_LOGIC; I_from_fifo : out STD_LOGIC; Q_from_fifo : out STD_LOGIC ); end Data_Source_Interface; architecture Data_Source_Interface of Data_Source_Interface is component ffd port ( clk : in STD_LOGIC; in_ffd : in STD_LOGIC; reset : in STD_LOGIC; out_ffd : out STD_LOGIC ); end component; component ffd_en port ( clk : in STD_LOGIC; clk_en : in STD_LOGIC; in_ffd : in STD_LOGIC; reset : in STD_LOGIC; out_ffd : out STD_LOGIC ); end component; component ffs port ( S : in std_ulogic; clk : in std_ulogic; reset : in std_ulogic; Q : out std_ulogic ); end component; component asynch_fifo_2x15 port ( ainit : in STD_LOGIC; din : in STD_LOGIC_VECTOR(1 downto 0); rd_clk : in STD_LOGIC; rd_en : in STD_LOGIC; wr_clk : in STD_LOGIC; wr_en : in STD_LOGIC; almost_empty : out STD_LOGIC; dout : out STD_LOGIC_VECTOR(1 downto 0); empty : out STD_LOGIC; full : out STD_LOGIC ); end component; constant VCC_CONSTANT : STD_LOGIC := ’1’; signal data_in_clk_to_fifo : STD_LOGIC; signal enable_reading : STD_LOGIC; signal fifo_out_enable : STD_LOGIC; signal out_enable : STD_LOGIC; signal read_enable : STD_LOGIC; signal start_rd_en : STD_LOGIC; signal VCC : STD_LOGIC; signal data_from_fifo : STD_LOGIC_VECTOR (1 downto 0); signal data_to_fifo : STD_LOGIC_VECTOR (1 downto 0); begin U1 : asynch_fifo_2x15 168 APPENDICE F. LISTATI VHDL 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 port map( ainit almost_empty din dout rd_clk rd_en wr_clk wr_en ); U11 : ffs port map( Q S clk reset ); U14 : ffd_en port map( clk clk_en in_ffd out_ffd reset ); U15 : ffd port map( clk in_ffd out_ffd reset ); U2 : ffd port map( clk in_ffd out_ffd reset ); fifo_out_enable read_enable VCC data_to_fifo(0) data_to_fifo(1) data_in_clk_to_fifo end Data_Source_Interface; => => => => => => => reset, enable_reading, => data_to_fifo, data_from_fifo, clk, read_enable, data_in_clk_to_fifo, VCC => start_rd_en, => enable_reading, => clk, => reset => => => => => clk, clk_en, start_rd_en, out_enable, reset => clk, => data_from_fifo(1), => Q_from_fifo, => fifo_out_enable => clk, => data_from_fifo(0), => I_from_fifo, => fifo_out_enable <= not(out_enable); <= start_rd_en and clk_en; <= VCC_CONSTANT; <= I_to_fifo; <= Q_to_fifo; <= data_in_clk; Listato F.5.4: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 169 asynch fifo 2x15.vhd -- synopsys translate_off LIBRARY ieee; USE ieee.std_logic_1164.ALL; Library XilinxCoreLib; ENTITY asynch_fifo_2x15 IS port ( din : IN std_logic_VECTOR(1 downto 0); wr_en : IN std_logic; wr_clk : IN std_logic; rd_en : IN std_logic; rd_clk : IN std_logic; ainit : IN std_logic; dout : OUT std_logic_VECTOR(1 downto 0); full : OUT std_logic; empty : OUT std_logic; almost_empty: OUT std_logic); END asynch_fifo_2x15; ARCHITECTURE asynch_fifo_2x15_a OF asynch_fifo_2x15 IS component wrapped_asynch_fifo_2x15 port ( din : IN std_logic_VECTOR(1 downto 0); wr_en : IN std_logic; wr_clk : IN std_logic; rd_en : IN std_logic; rd_clk : IN std_logic; ainit : IN std_logic; dout : OUT std_logic_VECTOR(1 downto 0); full : OUT std_logic; empty : OUT std_logic; almost_empty: OUT std_logic); end component; -- Configuration specification for all : wrapped_asynch_fifo_2x15 use entity XilinxCoreLib.async_fifo_v4_0(behavioral) generic map( c_wr_count_width => 2, c_has_rd_err => 0, c_data_width => 2, c_has_almost_full => 0, c_rd_err_low => 0, c_has_wr_ack => 0, APPENDICE F. LISTATI VHDL 170 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 c_wr_ack_low => 0, c_fifo_depth => 15, c_rd_count_width => 2, c_has_wr_err => 0, c_has_almost_empty => 1, c_rd_ack_low => 0, c_has_wr_count => 0, c_use_blockmem => 1, c_has_rd_ack => 0, c_has_rd_count => 0, c_wr_err_low => 0, c_enable_rlocs => 0); BEGIN U0 : wrapped_asynch_fifo_2x15 port map ( din => din, wr_en => wr_en, wr_clk => wr_clk, rd_en => rd_en, rd_clk => rd_clk, ainit => ainit, dout => dout, full => full, empty => empty, almost_empty => almost_empty); END asynch_fifo_2x15_a; -- synopsys translate_on 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 library ieee; use ieee.std_logic_1164.all; entity ffd is port(in_ffd : in std_logic ; clk : in std_logic ; reset : in std_logic ; out_ffd : out std_logic ); end ffd; architecture ffd_arch of ffd is begin process (clk, reset) begin if reset=’1’ then out_ffd <= ’0’; elsif rising_edge(clk) then out_ffd <= in_ffd; end if; end process; end ffd_arch ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 library ieee; use ieee.std_logic_1164.all; entity ffd_en is port(in_ffd : in std_logic ; clk : in std_logic ; clk_en : in std_logic ; reset : in std_logic ; out_ffd : out std_logic ); end ffd_en; architecture ffd_en_arch of ffd_en is begin process (clk, clk_en, reset) begin if reset=’1’ then out_ffd <= ’0’; elsif rising_edge(clk) then if clk_en = ’1’ then out_ffd <= in_ffd; end if; end if; end process; end ffd_en_arch ; Listato F.5.5: Listato F.5.6: ffd.vhd ffd en.vhd APPENDICE F. LISTATI VHDL 171 Listato F.5.7: ffs.vhd 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 library ieee; use ieee.std_logic_1164.all; entity ffs is port (S, clk, reset : in std_ulogic; Q : out std_ulogic); end entity ffs; architecture ffs_arch of ffs is signal state : std_ulogic; begin process (clk, reset) is begin if (reset = ’1’) then state <= ’0’; elsif rising_edge(clk) then case S is when ’0’ => state <= ’1’; when others => null; end case; end if; end process ; Q <= state; end ffs_arch; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 library IEEE; use IEEE.std_logic_1164.all; entity ThinModulator is port( I_in_fir_MSB : in STD_LOGIC; Q_in_fir_MSB : in STD_LOGIC; clk : in STD_LOGIC; clk_en : in STD_LOGIC; reset : in STD_LOGIC; fir_sel : in STD_LOGIC_VECTOR(2 downto 0); rate_sel : in STD_LOGIC_VECTOR(1 downto 0); QPSK_out : out STD_LOGIC_VECTOR(11 downto 0) ); end ThinModulator; architecture ThinModulator of ThinModulator is component mult_C2_adder port ( clk : in STD_LOGIC; in_mca : in STD_LOGIC_VECTOR(11 downto 0); reset : in STD_LOGIC; out_mca : out STD_LOGIC_VECTOR(11 downto 0) ); end component; component mux_2x7 port ( clk : in STD_LOGIC; in_I : in STD_LOGIC_VECTOR(6 downto 0); in_Q : in STD_LOGIC_VECTOR(6 downto 0); reset : in STD_LOGIC; out_mux : out STD_LOGIC_VECTOR(6 downto 0) ); end component; component shift_reg port ( clk : in STD_LOGIC; clk_en : in STD_LOGIC; in_reg : in STD_LOGIC; reset : in STD_LOGIC; out_ffd_1 : out STD_LOGIC; out_ffd_2 : out STD_LOGIC; out_ffd_3 : out STD_LOGIC; out_ffd_4 : out STD_LOGIC; out_ffd_5 : out STD_LOGIC; out_ffd_6 : out STD_LOGIC ); end component; component ram_12x4096_rising_registered port ( addr : in STD_LOGIC_VECTOR(11 downto 0); clk : in STD_LOGIC; dout : out STD_LOGIC_VECTOR(11 downto 0) ); end component; signal address : STD_LOGIC_VECTOR (11 downto 0); signal I_address : STD_LOGIC_VECTOR (6 downto 0); signal out_ram : STD_LOGIC_VECTOR (11 downto 0); signal Q_address : STD_LOGIC_VECTOR (6 downto 0); begin Listato F.5.8: ThinModulator.vhd APPENDICE F. LISTATI VHDL 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 U1 : shift_reg port map( clk => clk, clk_en => clk_en, in_reg => I_address(0), out_ffd_1 => I_address(1), out_ffd_2 => I_address(2), out_ffd_3 => I_address(3), out_ffd_4 => I_address(4), out_ffd_5 => I_address(5), out_ffd_6 => I_address(6), reset => reset ); U2 : shift_reg port map( clk => clk, clk_en => clk_en, in_reg => Q_address(0), out_ffd_1 => Q_address(1), out_ffd_2 => Q_address(2), out_ffd_3 => Q_address(3), out_ffd_4 => Q_address(4), out_ffd_5 => Q_address(5), out_ffd_6 => Q_address(6), reset => reset ); U3 : ram_12x4096_rising_registered port map( addr => address, clk => clk, dout => out_ram ); U4 : mux_2x7 port map( out_mux(0) => address(0), out_mux(1) => address(1), out_mux(2) => address(2), out_mux(3) => address(3), out_mux(4) => address(4), out_mux(5) => address(5), out_mux(6) => address(6), clk => clk, in_I => I_address, in_Q => Q_address, reset => reset ); U6 : mult_C2_adder port map( clk => clk, in_mca => out_ram, out_mca => QPSK_out, reset => reset ); I_address(0) <= I_in_fir_MSB; Q_address(0) <= Q_in_fir_MSB; address(7) <= fir_sel(0); address(8) <= fir_sel(1); address(9) <= fir_sel(2); address(10) <= rate_sel(0); address(11) <= rate_sel(1); end ThinModulator; Listato F.5.9: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 172 mult C2 adder.vhd library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_signed.all; entity mult_C2_adder is port(in_mca : in std_logic_vector(11 downto 0); reset : in std_logic ; clk : in std_logic ; out_mca : out std_logic_vector(11 downto 0)); end mult_C2_adder; architecture mult_C2_adder_arch of mult_C2_adder is signal TEMP_count : std_logic_vector(1 downto 0); begin process(clk, reset) begin if reset = ’1’ then TEMP_count <= "11"; elsif rising_edge(clk) then TEMP_count <= TEMP_count + 1; end if; end process; process(clk, reset, TEMP_count(1), in_mca) APPENDICE F. LISTATI VHDL 173 begin 24 25 26 27 28 29 30 31 32 33 34 if reset = ’1’ then out_mca <= x"000" ; elsif rising_edge(clk) then out_mca <= in_mca ; if TEMP_count(1) = ’1’ then out_mca <= ( x"FFF" xor in_mca) + 1 ; end if; end if; end process; end mult_C2_adder_arch ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 library ieee; use ieee.std_logic_1164.all; entity mux_2x7 is port(in_I, in_Q : in std_logic_vector(6 downto 0); reset : in std_logic ; clk : in std_logic ; out_mux : out std_logic_vector(6 downto 0)); end mux_2x7; architecture mux_2x7_arch of mux_2x7 is signal sel : std_logic; begin -- processo che genera il segnale di selezione alternato process (clk, reset) begin if reset = ’1’ then sel <= ’1’; elsif rising_edge(clk) then sel <= not sel; end if; end process; out_mux <= in_I when (sel = ’0’) else in_Q ; end mux_2x7_arch ; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 -- synopsys translate_off LIBRARY ieee; USE ieee.std_logic_1164.ALL; Library XilinxCoreLib; ENTITY ram_12x4096_rising_registered IS port ( addr : IN std_logic_VECTOR(11 downto 0); clk : IN std_logic; dout : OUT std_logic_VECTOR(11 downto 0)); END ram_12x4096_rising_registered; ARCHITECTURE ram_12x4096_rising_registered_a OF ram_12x4096_rising_registered IS component wrapped_ram_12x4096_rising_registered port ( addr: IN std_logic_VECTOR(11 downto 0); clk: IN std_logic; dout: OUT std_logic_VECTOR(11 downto 0)); end component; for all : wrapped_ram_12x4096_rising_registered use entity XilinxCoreLib.blkmemsp_v4_0(behavioral) generic map( c_reg_inputs => 1, c_addr_width => 12, c_has_sinit => 0, c_ysinit_is_high => 1, c_has_rdy => 0, c_width => 12, c_has_en => 0, c_ymake_bmm => 0, c_yen_is_high => 1, c_yprimitive_type => "4kx1", c_yhierarchy => "hierarchy1", c_mem_init_file => "ram_12x4096_rising_registered.mif", c_ywe_is_high => 1, c_yuse_single_primitive => 1, c_depth => 4096, c_has_nd => 0, c_has_default_data => 0, c_default_data => "0", c_ytop_addr => "1024", c_limit_data_pitch => 8, c_pipe_stages => 1, Listato F.5.10: Listato F.5.11: mux 2x7.vhd ram 12x4096 rising registered.vhd APPENDICE F. LISTATI VHDL 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 c_ybottom_addr => "0", c_has_rfd => 0, c_yclk_is_rising => 1, c_has_we => 0, c_sinit_value => "0", c_has_limit_data_pitch => 0, c_enable_rlocs => 0, c_has_din => 0, c_write_mode => 0); BEGIN U0 : wrapped_ram_12x4096_rising_registered port map ( addr => addr, clk => clk, dout => dout); END ram_12x4096_rising_registered_a; -- synopsys translate_on Listato F.5.12: shift reg.vhd vedi listato(F.3.9) 174 Appendice G Acronimi ADC Analog Digital Converter ARQ Automatic ReQuest for repeat BER Bit Error Rate BPSK Binary Phase Shift Keying CIC Cascaded Integrator Comb CLB Configurable Logic Block CORDIC COordinate Rotate DIgital Computer CPFSK Continuous Phase Frequency Shift Keying CPLD Complex Programmable Logic Device DAC Digital Analog Converter DDS Direct Digital Synthesizer DDFS Direct Digital Frequency Synthesizer DLL Delay Locked Loop DSP Digital Signal Processing FA Full Adder FEC Forward Error Correction FFD Flip Flop D FIFO First In First Out FPGA Field Programmable Gate Array 175 APPENDICE G. ACRONIMI FSK Frequency Shift Keying GMSK Gaussian Minimum Shift Keying GRM General Routing Matrix IDFT Inverse Discrete Fourier Transform IF Intermediate Frequency IOB Input Output Block ISI Inter Symbol Interference ISP In System Programmable LC Logic Cell LUT Look-Up Table MAP Maximum A Posteriori probability ML Maximum Likelihood MSB Most Significant Bit MSK Minimum Shift Keying NCO Numerical Control Oscillator NRZ No Return to Zero OQPSK Offset Quadrature Phase Shift Keying OTP One Time Programmable PAL Programmable Array Logic PAR Place And Route PCF Physical Constrain File PLD Programmable Logic Device PSK Phase Shift Keying QAM Quadrature Amplitude Modulation QPSK Quadrature Phase Shift Keying RAM Random Access Memory RTL Register Transfer Logic 176 APPENDICE G. ACRONIMI SER Symbol Error Rate SFDR Spurious Free Dynamic Range SIPO Serial In Parallel Out SNR Signal to Noise Ratio SRAM Static Random Access Memory SRL16 Shift Register Left 16-bit SRRC Square Root Raised Cosine STA Static Timing Analyzer TWTA Travelling Wave Tube Amplifier UCF User Constrain File VHDL VHSIC Hardware Description Language VHSIC Very High Speed Integrated Circuit 177 Bibliografia [1] AN1298. Digital modulation in communications systems, an introduction. Technical report, Hewlett Packard, 2000. 9 [2] Dirk A. Baker. Space-time block coding with imperfect channel estimates. Master’s thesis, West Virginia University, 2001. 5 [3] C.E.Shannon. A mathematical theory of communication. The Bell System Technical Journal, 27, 1948. 23 [4] Annex D. Skyplex. Technical report, EUTELSAT, 1999. 2 [5] Robert D.Turney. Multirate filters and wavelets: From theory to implementation. Xilinx. 78 [6] Hogenauer E.B. An economical class of digital filters for decimation and interpolation. IEEE Transactions on acoustics, speech and signal processing, 1981. 75 [7] Dr Mike Fitton. Principles of digital modulation. Technical report, Telecommunications Research Lab Toshiba, 2000. 10 [8] John G.Proakis. Digital Communications. Prentice Hall, 1998. 15, 18 [9] J.E.Volder. The cordic trigonometric computing technique. IRE Trans. on Electron. Comput., pages 330–334, September 1959. 63 [10] A.V. Oppenheim and R.W.Schafer. Elaborazione numerica dei segnali. Franco Angeli, undicesima edition, 1999. 61, 71 [11] Domenico Solimini. Appunti dalle lezioni di Campi Elettromagnetici. TeXMat, 1999. 17 [12] P.P. Vaidyanathan. Multirate Systems and Filter Banks. Prentice-Hall, 1993. 74 [13] Francesco Valdoni. Comunicazioni Elettriche. I due Ladroni, 1998. 15 [14] Jouko Vankka. Methods of mapping from phase to sine amplitude in dds. IEEE international Frequency control symposium, 1996. 63 178 BIBLIOGRAFIA 179 [15] Xilinx. Virtex 2.5V Field Programmable Gate Arrays, July 1999. 81 Elenco dei listati E.1.1 NCO Q.m . . . . . . . . . . . . . . . . . . E.1.2 Imposta frequenze Q.m . . . . . . . . . . E.1.3 Imposta NCO Q.m . . . . . . . . . . . . E.1.4 Crea super accumulatore Q.m . . . . . . E.1.5 Tronca Q.m . . . . . . . . . . . . . . . . . E.1.6 Crea coseno e seno Q.m . . . . . . . . . E.1.7 Forward cordic Q.m . . . . . . . . . . . . E.1.8 Calcola rotazioni Cordic.m . . . . . . . . E.1.9 Visualizza spettro e SFDR p.m . . . . E.1.10 Calcola SFDR.m . . . . . . . . . . . . . . E.1.11 Calcola incremento fase NCO.m . . . . . E.1.12 Visualizza spettro NCO VHDL.m . . . . E.2.1 CreaVettoriTest.m . . . . . . . . . . . . . . E.2.2 CreaSequenzaPatternGenerator.m . . . . . E.3.1 CreaCoeffsFreqSamplScaled.m . . . . . . . E.3.2 applica polifase.m . . . . . . . . . . . . . . E.3.3 RaisedCosineResponse.m . . . . . . . . . . E.3.4 CreaROM.m . . . . . . . . . . . . . . . . . E.3.5 PolyphasePSDVHDLvsPSDMatlab.m . . . E.3.6applica polifase.m . . . . . . . . . . . . . . . E.3.7 VisualizzaPSDPolifaseVHDLFPGAout.m . E.3.8applica polifase.m . . . . . . . . . . . . . . . E.4.1 CreaTabellaBER.m . . . . . . . . . . . . . E.4.2 calcolaBER.m . . . . . . . . . . . . . . . . E.4.3applica polifase.m . . . . . . . . . . . . . . . E.4.4 QPSKModemPSDeBERVHDLvsMatlab.m E.4.5applica polifase.m . . . . . . . . . . . . . . . E.4.6 QPSKModemPSDFPGAvsPSDMatlab.m . E.4.7applica polifase.m . . . . . . . . . . . . . . . F.1.1 nco.vhd . . . . . . . . . . . . . . . . . . . . F.1.2 accumulator.vhd . . . . . . . . . . . . . . . F.1.3 cordic pipelined unrolled.vhd . . . . . . . F.1.4 cordic base j.vhd . . . . . . . . . . . . . . F.1.5 adder 12.vhd . . . . . . . . . . . . . . . . 180 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 93 94 94 94 95 95 96 96 96 97 97 97 98 100 101 102 102 104 105 105 106 106 107 108 108 112 112 114 115 116 117 120 121 ELENCO DEI LISTATI F.1.6 adder 13.vhd . . . . . . . . . . . F.1.7 reg 12.vhd . . . . . . . . . . . . . F.1.8 reg 13.vhd . . . . . . . . . . . . . F.1.9 shifter.vhd . . . . . . . . . . . . . F.1.10 cosine rebuild.vhd . . . . . . . . . F.1.11 delay 13.vhd . . . . . . . . . . . . F.1.12 sine rebuild.vhd . . . . . . . . . . F.1.13 to first quadrant.vhd . . . . . . F.1.14 troncatore 12.vhd . . . . . . . . . F.2.1 polyphase gatedClock.vhd . . . . F.2.2 srrc coeffs.vhd . . . . . . . . . . . F.2.3 rate adapter.vhd . . . . . . . . . F.2.4 coeffs selector.vhd . . . . . . . . . F.2.5 counter divider 3.vhd . . . . . . F.2.6 counter divider 4.vhd . . . . . . F.2.7 fftr.vhd . . . . . . . . . . . . . . . F.2.8 counter divider 6.vhd . . . . . . F.2.9 selector.vhd . . . . . . . . . . . . . F.2.10 srrc x n.vhd . . . . . . . . . . . F.2.11 fir 1.vhd . . . . . . . . . . . . . . F.2.12 adder 7.vhd . . . . . . . . . . . . F.2.13 fir multiplier.vhd . . . . . . . . . F.2.14 shift reg.vhd . . . . . . . . . . . . F.2.15 mux 6.vhd . . . . . . . . . . . . . F.3.1 ROM polyphase.vhd . . . . . . . F.3.2 counter.vhd . . . . . . . . . . . . . F.3.3 srrc x n.vhd . . . . . . . . . . . F.3.4 demux 3x10.vhd . . . . . . . . . . F.3.5 mux 3x12.vhd . . . . . . . . . . . F.3.6 ROMx3.vhd . . . . . . . . . . . . F.3.7 ROMx4.vhd . . . . . . . . . . . . F.3.8 ROMx6.vhd . . . . . . . . . . . . F.3.9 shift reg.vhd . . . . . . . . . . . . F.4.1 Modulator BlockRAM.vhd . . . . F.4.2 adder I Q.vhd . . . . . . . . . . F.4.3counter.vhd . . . . . . . . . . . . . . F.4.4 multiplier I Q.vhd . . . . . . . . F.4.5 NCO basic.vhd . . . . . . . . . . F.4.6 srrc x n.vhd . . . . . . . . . . . F.4.7 ram.vhd . . . . . . . . . . . . . . . F.4.8shift reg.vhd . . . . . . . . . . . . . F.5.1 FIFO RAM ThinModulator.vhd F.5.2counter.vhd . . . . . . . . . . . . . . F.5.3 Data Source Interface.vhd . . . 181 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 122 122 122 123 123 123 124 124 124 125 125 126 130 130 131 131 132 132 136 138 139 139 139 140 141 141 143 143 143 148 153 161 162 163 164 164 164 165 166 166 166 168 168 ELENCO DEI LISTATI F.5.4 asynch fifo 2x15.vhd . . . . . . . . F.5.5 ffd.vhd . . . . . . . . . . . . . . . . F.5.6 ffd en.vhd . . . . . . . . . . . . . . F.5.7 ffs.vhd . . . . . . . . . . . . . . . . . F.5.8 ThinModulator.vhd . . . . . . . . . F.5.9 mult C2 adder.vhd . . . . . . . . . F.5.10 mux 2x7.vhd . . . . . . . . . . . . F.5.11 ram 12x4096 rising registered.vhd F.5.12shift reg.vhd . . . . . . . . . . . . . . 182 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 170 170 171 171 172 173 173 174 Indice analitico inviluppo complesso . . . . . . . . . . . . . 5 A accumulatore . . . . . . . . . . . . . . . . . . . 62 antifuse . . . . . . . . . . . . . . . . . . . . . . . . 82 L LUT . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 B base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 M BlockRAM . . . . . . . . . . . . . . . . . . . . . 87 MAP . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 moltiplicatore . . . . . . . . . . . . . . . . . . 30 C clock-enable . . . . . . . . . . . . . . . . . . . . 40 N codifica Gray . . . . . . . . . . . . . . . . . . . 17 NCO . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 commutatore . . . . . . . . . . . . . . . . . . . 49 P CORDIC . . . . . . . . . . . . . . . . . . . . . . . 63 PAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 Core . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 PLD . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 costellazione . . . . . . . . . . . . . . . . . . . . . 7 portante . . . . . . . . . . . . . . . . . . . . . . . . . 7 CPLD . . . . . . . . . . . . . . . . . . . . . . . . . . 82 programmabile . . . . . . . . . . . . . . . . . 42 D DDFS . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Q DDS . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 quadratura . . . . . . . . . . . . . . . . . . . . . 26 DLL . . . . . . . . . . . . . . . . . . . . . . . . . . . 87 R roll-off . . . . . . . . . . . . . . . . . . . . . . . . . . 33 E efficienza spettrale . . . . . . . . . . . . . . . 9 rumore . . . . . . . . . . . . . . . . . . . . . . . . . 45 rumore gaussiano . . . . . . . . . . . . . . . 14 F FEC . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 S FIFO . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 sagomatura . . . . . . . . . . . . . . . . . . . . . 27 FloorPlanner . . . . . . . . . . . . . . . . . . . 91 Scheda Dini . . . . . . . . . . . . . . . . . . . . 83 segnale analitico . . . . . . . . . . . . . . . . . 5 G Shannon . . . . . . . . . . . . . . . . . . . . . . . 22 gated-clock . . . . . . . . . . . . . . . . . . . . . 40 simbolo . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Slice . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 H spazio segnali . . . . . . . . . . . . . . . . . . . . 6 Hilbert . . . . . . . . . . . . . . . . . . . . . . . . . . 5 spurie . . . . . . . . . . . . . . . . . . . . . . . . . . 61 SRAM . . . . . . . . . . . . . . . . . . . . . . . . . 82 I 183 INDICE ANALITICO T ThinModulator . . . . . . . . . . . . . . . . . 49 V VersaBLOCK . . . . . . . . . . . . . . . . . . 86 VersaRING . . . . . . . . . . . . . . . . . . . . . 86 Virtex . . . . . . . . . . . . . . . . . . . . . . . . . . 82 184