Sei sulla pagina 1di 23

UNIVERSITA DI PISA

CORSO DI LAUREA MAGISTRALE INGEGNERIA INFORMATICA

RELAZIONE PROGETTO APPARATI ELETTRONICI


Docente
Luca Fanucci Candidati: Balducci Gian Maria Cardinale Francesco Del Pizzo Beniamino

Cordic per la trasformazione da coordinate cartesiane a polari


OBIETTIVI

Il nostro obiettivo di progettare un circuito che realizzi la trasformazione da coordinate cartesiane a polari implementando lalgoritmo CORDIC (Coordinate Rotation DIgital Computer) in modalit Vectoring.

CORDIC

Lalgoritmo cordic stato introdotto per permettere il calcolo tramite hardware di essenziali funzioni trigonometriche pu essere utilizzato per sin(), cos(), tan(). Lalgoritmo basato sulla rotazione di un vettore di un angolo . Se assumiamo che un vettore di origine al punto (x1, y1) sia ruotato di un angolo , alla fine il vettore si trover al punto (x2, y2) come in figura: y (x2,y2) (x1,y1)

x La trigonometria elementare d le equazioni di (x2, y2) in termini di (x1, y1) e come: x2 = x1 cos() y1 sin() y2 = x1 sin() + y1 cos() Al fine di semplificare i calcoli, l'algoritmo CORDIC utilizza un numero n di rotazioni, ciascuna delle quali pu essere facilmente calcolata, per costruire langolo . Si decompone langolo come somma di angoli n = n e ogni n scelto come n= arctan(2-n) cio tan(n) = 2n Ora si possono riordinare le equazioni per una singola rotazione in termini di tan(n), e scrivere x(n + 1) = x(n)cos(n) y(n)sin(n) = cos(n)(x(n) y(n)tan(n)) y(n + 1) = x(n)sin(n) + y(n)cos(n) = cos(n)(x(n) tan(n) + y(n)) Indicando con x(n+1) la sequenza dei valori presi da x utilizzando tan(n) = 2n, e inserendo = 1, le equazioni per x(n + 1) e y(n + 1) diventano:

x(n + 1) = cos(n) ( x(n) n 2n y(n) ) y(n + 1) = cos(n) ( y(n) + n 2n x(n) ) Se ignoriamo per il momento il termine cos(n), allora queste equazioni possono essere implementate con un adder e uno shifter. Lalgoritmo del cordic non considera il termine cos(n) infatti il risultato dellalgoritmo a ogni iterazione di un fattore 1/cos (n) pi grande di quanto dovrebbe essere. Il fattore di scala totale quando n tende a infinito : K = (n=0, ) 1/cos(n) = (n=0, )sqrt(1+2-2n ) = 1.6467 Si noti che il fattore di scala indipendente dal segno di ogni rotazione elementare, e cos fisso.

CORDIC VECTORING MODE

Scegliendo in maniera opportuna la modalit CORDIC e il valore degli ingressi possibile ottenere diversi risultati con lapplicazione del medesimo algoritmo: calcolo del seno, coseno o arcotangente di un angolo, rotazione di un vettore di un certo angolo, calcolo del modulo di un vettore, trasformazione da coordinate cartesiane a coordinate polari e viceversa. Per raggiungere il nostro obiettivo di realizzare la trasformata da coordinate cartesiane a polari, dobbiamo utilizzare il cordic in modalit vectoring. Si comincia con un dato (xin, yin) che rappresenta un punto nel piano cartesiano e sinizia a ruotare il vettore corrispondente a tale punto fino a quando la componente y zero. Alla fine della rotazione si avr la conversione in coordinate polari. Il sistema di riferimento polare un sistema di
coordinate bidimensionale nel quale ogni punto del piano identificato da un angolo e da una distanza da un punto fisso detto polo. Una coordinata polare si esprime quindi in modulo e fase.

In vectoring mode le equazioni del CORDIC sono : x(n + 1) = x(n) y(n)n2n y(n + 1) = y(n) + x(n)n2n z(n + 1) = z(n) n arctan(2n)

dove n+1= +1 se y(n)<0 , -1 altrimenti e i risultati sono

x = K sqrt(xin2+yin2) y=0 z=zin + arctan(yin/xin)

IMPLEMENTAZIONE

la descrizione dellimplementazione della rete Cordic Vectoring mostrando lo schema generale dei due circuiti principali: Cordic Main e Iterate.
Iniziamo

La figura seguente mostra il circuito sequenziale Cordic Main.

Come possiamo vedere dalla figura il circuito costituito da due ingressi x ed y, che rappresentano le due coordinate cartesianedi ingresso e da due uscite rho e theta, che rappresentano le coordinate polari cio modulo e fase rispettivamente. Nel circuito sono presenti tre registri Regx, Regy e Regz che andranno a memorizzare i valori di x(i+1), y(i+1) e z(i+1) che verranno poi utilizzati dalliterate per implementare il passo successivo dellalgoritmo. E prevista inoltre una rete control, la quale ha il compito di comandare il multiplexer con luscita load e con luscita i andiamo a comandare il numero di shift da effettuare sulle variabili x ed y allinterno delliterate.

La figura sopra mostra nel suo insieme il circuito iterate. Literate costituito da un processo interno con il quale viene assegnato il valore 0 o 1 ai due comandi cmd1 e cmd2 che vengono utilizzati per comandare la giusta operazione da svolgere allinterno della rete addsub. Sono previsti i due registri shift_reg nei quali viene effettuato lo shift di i posizioni su x e y ed una Rom nella quale sono stati memorizzati i valori dell arctan(2-i). Adesso andiamo ad analizzare limplementazione in VHDL dei vari componenti che costituiscono il nostro circuito. Reg Il registro Reg stato implementato come un semplice registro sincronizzato, il quale prende in ingresso un segnale di 16 bit e lo restituisce in uscita al clock successivo. entity reg is generic (N: integer:=16); port( d : in std_logic_vector(N-1 downto 0); clk : in std_logic; reset : in std_logic; q : out std_logic_vector(N-1 downto 0) ); end reg;

-- segnale di ingresso al registro

--segnale di uscita dal registro

architecture reg of Reg is begin comb: process(clk,reset) begin if(clk'event and clk='1') then for i in 0 to N-1 loop q(i)<=d(i) and reset; end loop; end if; end process; end Reg; Ctrl

--ciclo per la memorizzazione bit a bit --del segnale di ingresso

La rete Ctrl la rete di controllo, la quale va a pilotare i multiplexer con luscita load e i registri di shift con luscita i. La rete Ctrl deve impostare il valore di load = 0 allistante iniziale, andando cos ad inserire i valori di ingresso della rete Cordic Main nei vari registri: Regx, Regy e Regz. Per i clock successivi questa uscita (load) avr sempre valore 1, in modo tale che il multiplexer mandi in ingresso ai registri i valori di x(i+1), y(i+1) e z(i+1). Inizialmente luscita i stata impostata a -1, in modo tale da avere per il primo passo dellalgoritmo, ovvero per i=0, come valori di ingresso allterate quelli salvati nei registri al clock precedente. La variabile interna count viene incrementata ad ogni iterazione in modo tale da incrementare il numero di shift da effettuare. entity Ctrl is port( i load clk reset ); end Ctrl; architecture BEHAVIOURAL of Ctrl is begin Ctrl:process(clk, reset) variable count: integer:=-1; begin if(clk'event and clk='1') then if ( reset='0' ) then --in fase di reset il valore di load=0, comandando il i<=count; --multiplexer in modo tale da far passare il valore delle load<=0; --variabili di ingresso al circuito else count:=count +1; --incremento della variabile count in modo da i<=count; --incrementare il numero di shift load<=1; -- load dopo listante iniziale avr sempre end if; --valore 1
5

: out integer; -- numero di shift : out integer; -- comando per il multiplexer : in std_logic; : in std_logic

end if; end process Ctrl; end BEHAVIOURAL; Cordic_Main Limplementazione generale del Cordic_Main riporta di seguito. Come possiamo vedere prevista lentit globale Cordic_Main nella quale sono previsti i due ingressi alla rete x e y, le due uscite rho e theta ed inoltre il clk e reset. Allinterno della struttura sono richiamate le componenti Reg e Ctrl, gi illustrate precedentemente e literate. entity Cordic_Main is generic (N: integer:=16); port ( x : in std_logic_vector(N-1 downto 0); -- X ingresso circuito y : in std_logic_vector(N-1 downto 0); -- y ingresso circuito clk : in std_logic; reset : in std_logic; rho : out std_logic_vector(N-1 downto 0); -- valore modulo in uscita theta : out std_logic_vector(N-1 downto 0) -- valore angolo in uscita ); end Cordic_Main; architecture structural of Cordic_Main is -- Componente Registri component Reg generic (N: integer:=16); port( d : in std_logic_vector(N-1 downto 0); clk : in std_logic; reset : in std_logic; q : out std_logic_vector(N-1 downto 0) ); end component; -- componente circuito iterate component iterate generic (N: integer:=16); port ( -- valori di uscita dai registri e di ingresso all iterate xi : in std_logic_vector(N-1 downto 0); yi : in std_logic_vector(N-1 downto 0); zi : in std_logic_vector(N-1 downto 0);
6

-- numero di shift da effettuare comandato dal circuito CTRL i : in integer; -- valori in uscita dalliterate, rappresentano i valori al passo i+1 dell'algoritmo cordic xi1 : out std_logic_vector(N-1 downto 0); yi1 : out std_logic_vector(N-1 downto 0); zi1 : out std_logic_vector(N-1 downto 0) ); end component; -- componente di comando per i multiplex e per lo shift component Ctrl port ( i : out integer; -- numero i shift load : out integer; -- se 0 carico nei registri X0 se 1 carico nei registri Xi clk : in std_logic; reset : in std_logic ); end component; -- uscite ctrl signal i signal l_i

: integer:=0; : integer;

--ingresso registri signal x0 : std_logic_vector(N-1 downto 0 ); signal y0 : std_logic_vector(N-1 downto 0 ); signal z0 : std_logic_vector(N-1 downto 0 ); -- uscita registri signal rx : std_logic_vector(N-1 downto 0); signal ry : std_logic_vector(N-1 downto 0); signal rz : std_logic_vector(N-1 downto 0); -- uscita iterate signal rxi : std_logic_vector(N-1 downto 0); signal ryi : std_logic_vector(N-1 downto 0); signal rzi : std_logic_vector(N-1 downto 0); begin --descrizione collegamenti interni trai i vari componenti control : Ctrl port map(i, l_i, clk, reset); Regx : Reg port map(x0, clk, reset, rx); RegY : Reg port map(y0, clk, reset, ry); RegZ : Reg port map(z0, clk, reset, rz);
7

it

: iterate port map(rx, ry, rz, i, rxi, ryi, rzi);

mux:process(clk,reset) begin if l_i =0 or reset='0' then -- passo iniziale del circuito caricare i valori x0<=x; --X0, Y0 e Z0 nei rispettivi registri. y0<=y; z0<="0000000000000000"; else x0<=rxi; y0<=ryi; z0<=rzi; end if; -- assegnamento uscite con i valori al passo i+1 rho<=rxi; theta<=rzi; end process; end structural; Lunica considerazione da fare solo quella relativa ai valori iniziali da inserire nei registri. Come abbiamo gi spiegato inizialmente il valore di l_i, al qual viene assegnato il valore load in uscita da Ctrl, uguale a 0, di conseguenza i valori in ingresso ai registri saranno x, y e z. Questultima variabile avr come valore iniziale 0. Nei successivi cicli di clock l_i sar uguale a 1 e quindi in ingresso ai registri avremo rxi, ryi e rzi, che sono rispettivamente il valore di x, y e z all i+1-esimo passo dellalgoritmo. Andiamo adesso ad illustrare le componenti che costituisco la rete combinatoria iterate. Shift_reg Il registro Shift_reg il registro con il quale viene effettuato lo shift della variabile di ingresso d di s posizioni ed il valore ottenuto verr inviato in uscita tramite la variabile d. entity shift_reg is generic (N: integer:=16); port ( d : in std_logic_vector(N-1 downto 0); -- variabile di ingresso s : in integer -- numero di shift da effettuare q : out std_logic_vector(N-1 downto 0) -- valore in ingresso shiftato di s posizioni ); end shift_reg; -- nei registri vengono salvati i valori uscenti -- dall'iterate al passo i+1

architecture BEHAVIOURAL of shift_reg is begin process (s) begin if s>=0 and s<N-1 then q(N-1-s downto 0)<=d(N-1 downto s); for j in N-1-s to N-1 loop q(j)<=d(N-1); end loop; else q<=d; end if; end process; end BEHAVIOURAL; Lunico accorgimento del quale dobbiamo fare attenzione nel replicare il valore corretto allinizio della variabile da shiftare. Questo perch lavorando in complemento a due se la variabile in ingresso ha un valore negativo dobbiamo replicare tanti 1 quanti shift abbiamo effettuato, viceversa se il valore positivo dobbiamo replicare gli 0. Addsub La rete addsub la rete che provvede ad effettuare la somma o la sottrazione in base al valore del comando cm. Il comando cm le viene inviato in ingresso dalliterate in base al bit pi significativo di y. entity addsub is generic (N: integer:=16); port ( a : in std_logic_vector(N-1 downto 0); b : in std_logic_vector(N-1 downto 0); cm : in std_logic; c : out std_logic_vector(N-1 downto 0) ); end addsub; architecture BEHAVIOURAL of addsub is begin Sum:process(a,b,cm) begin if (cm='0') then c<=a+b; else
9

c<=a-b; end if; end process Sum; end BEHAVIOURAL; rom 16x16 La rom 16x16 una semplice rom che restituisce il valore arctan(2^-i) in base al valore di i (addr) che rappresenta lindirizzo nella Rom. entity rom16x16 is generic (N: integer:=16); port( addr : in integer; dout : out STD_LOGIC_VECTOR(N-1 downto 0) ); end rom16x16; architecture structural of rom16x16 is constant DIMROM: natural :=16; constant DIMWORD: natural :=16; type ROM_IMAGE is array (natural STD_LOGIC_VECTOR(DIMWORD-1 downto 0); constant ROM: ROM_IMAGE := ( 0 =>"0000000000101101", 1 =>"0000000000010111", 2 =>"0000000000001011", 3 =>"0000000000000110", 4 =>"0000000000000011", 5 =>"0000000000000001", 6 =>"0000000000000001", 7 =>"0000000000000000", 8 =>"0000000000000000", 9 =>"0000000000000000", 10 =>"0000000000000000", 11 =>"0000000000000000", 12 =>"0000000000000000", 13 =>"0000000000000000", 14 =>"0000000000000000", 15 =>"0000000000000000" );

range

to

DIMROM-1)

of

10

begin process(addr) begin if addr<N then if addr >-1 then dout<=ROM(addr); end if; end if; end process; end structural; iterate Di seguito riportato il codice VHDL dellarchitettura iterate dove sono presenti i vari componenti gi illustrati. entity iterate is generic (N: integer:=16); port ( xi : in std_logic_vector(N-1 downto 0); yi : in std_logic_vector(N-1 downto 0); zi : in std_logic_vector(N-1 downto 0); i : in integer; xi1 : out std_logic_vector(N-1 downto 0); yi1 : out std_logic_vector(N-1 downto 0); zi1 : out std_logic_vector(N-1 downto 0) ); end iterate; architecture BEHAVIOURAL of iterate is component shift_reg generic (N: integer:=16); port ( d : in std_logic_vector(N-1 downto 0); s : in integer; q : out std_logic_vector(N-1 downto 0) ); end component; component addsub generic (N: integer:=16); port ( a : in std_logic_vector(N-1 downto 0);
11

b : in std_logic_vector(N-1 downto 0); cm : in std_logic; c : out std_logic_vector(N-1 downto 0) ); end component; component rom16x16 generic (N: integer:=16); port( addr : in integer; dout : out STD_LOGIC_VECTOR(N-1 downto 0) ); end component; -- xi yi shiftati signal xish : std_logic_vector(N-1 downto 0); signal yish : std_logic_vector(N-1 downto 0); -- alluscita dalla Rom vi rappresentato il valore di arctang(2^-i) in binario signal arc : std_logic_vector(N-1 downto 0); -- valore del comando per il pilotaggio della rete addsub signal cmd1 : std_logic; signal cmd2 : std_logic; begin Shx : shift_reg port map(xi, i, xish); Shy : shift_reg port map(yi, i, yish); arctan : rom16x16 port map(i, arc); add1 add2 add3 --shift del segnale x di i passi --shift del segnale y di i passi

: addsub port map(xi, yish, cmd2, xi1); : addsub port map(yi, xish, cmd1, yi1); : addsub port map(zi, arc, cmd2, zi1);

ctriter: process(xi,yi,zi) begin --allinterno dellif abbiamo lassegnamento del bit pi significativo di y ai due comandi, cmd1 e --cmd2, in modo tale da comandare la giusta operazione allinterno di addsub, secondo quanto --specificato dallalgoritmo Cordic vectoring. if yi="0000000000000000" then cmd1<=yi(N-1); cmd2<=not yi(N-1); else
12

cmd1<=not yi(N-1); cmd2<= yi(N-1); end if; end process ctriter; end BEHAVIOURAL; Nellimplementazione delliterate e pi nello specifico nelle condizioni dellif dobbiamo fare una piccola puntualizzazione. Lalgoritmo Cordic Vectoring prevede che il cmd sia +1 quando y<0 e -1 altrimenti. Facendo alcuni test abbiamo notato che questo portava degli errori quando i valori di ingresso erano uguale ma di segno opposto. Abbiamo cos modificato le condizioni di assegnamento alla variabile cmd: +1 quando y<=0 e -1 altrimenti, effettuando questa piccola modifica dal circuito abbiamo ottenuto i giusti valori anche in quei casi particolari. Test bench Nel test bench stato inserito il componente principale Cordic_Main, il quale stato stimolato attraverso i segnali x ed y, di ingresso, per verificare le uscite. Per la verifica abbiamo deciso di utilizzare 16 cicli di clock in quanto abbiamo utilizzando segnali su 16 bit e quindi il numero massimo di shift possibili proprio 16. ARCHITECTURE circuito_test OF circuito_tb IS component Cordic_Main is generic (N: integer:=16); port ( x : in std_logic_vector(N-1 downto 0); y : in std_logic_vector(N-1 downto 0); clk : in std_logic; reset : in std_logic; rho : out std_logic_vector(N-1 downto 0); theta : out std_logic_vector(N-1 downto 0) ); end component; constant N : integer:=16;

CONSTANT MckPer : TIME := 200 ns; -- Master Clk period CONSTANT TestLen : INTEGER := 40; -- Generates clk SIGNAL clk SIGNAL reset SIGNAL clk_cycle

: std_logic := '0'; : std_logic := '0'; : INTEGER:=0;


13

SIGNAL Testing

: Boolean := True;

--Segnali di ingresso signal x : std_logic_vector(N-1 downto 0); signal y : std_logic_vector(N-1 downto 0); --Segnali di uscita signal rho : std_logic_vector(N-1 downto 0); signal theta : std_logic_vector(N-1 downto 0); begin C:Cordic_Main port map(x,y,clk,reset,rho,theta); clk <= NOT clk AFTER MckPer/2 WHEN Testing ELSE '0'; -- Runs simulation for TestLen cycles; Test_Proc: PROCESS(clk) VARIABLE count: INTEGER:= 0; BEGIN clk_cycle <= (count+1)/2; CASE count IS WHEN 1 => reset <= '0'; WHEN 2 => reset <= '1'; x<="0011011011110110"; y<="0011011011110110"; WHEN 32 => reset <= '0'; WHEN (TestLen - 1) => Testing <= False; WHEN OTHERS => NULL; END CASE; count:= count + 1; END PROCESS Test_Proc; END circuito_test;

14

SIMULAZIONE DELLALGORITMO CON MATLAB E VHDL

Per verificare la correttezza dellalgoritmo cordic vectoring e limplementazione della rete in vhdl abbiamo scritto lalgoritmo con il Matlab. Confrontando i risultati di tale algoritmo Matlab con le uscite della rete vhdl abbiamo potuto stabilire che la rete vhdl funziona correttamente. Per prima cosa spieghiamo che i dati di ingresso della rete sono di tipo intero rappresentati in complemento a due e su sedici bit per cui linsieme dei valori accettabili come ingresso per la rete sono i numeri dellintervallo [-32768 ; 32767] ovvero i numeri rappresentabili con il tipo di dato usato. Inoltre la rete stata implementata per accettare in ingresso solo valori di x positivi o al pi nulli. Si scelto di lavorare con numeri su sedici bit solo per semplicit di trattazione in quanto lalgoritmo continua a funzionare correttamente anche su pi bit, lunica cosa importante da considerare in fase di progetto che il numero di bit per la rappresentazione dei numeri collegato al numero di iterazioni della rete in quanto al passo n-esimo gli shift register effettueranno uno shift aritmetico di n posti. Per rappresentare interi in complemento a due su sedici bit in Matlab abbiamo utilizzato il tipo di dato fixed-point numeric object, un oggetto di questo tipo definisce numeri in complemento a due e consente la rappresentazione dei numeri in binario che il formato usat o per limplementazione vhdl. Per questo tipo di dato in Matlab sono gi definite tutte le operazioni aritmetiche, in modo particolare quelle di nostro interesse che sono: accumpos (somma),accumneg (sottrazione) e bitsra (shift). Abbiamo usato quindi degli oggetti di tipo numerico definiti in questo modo: a = fi(v,s,w,f) returns a fixed-point object with value v, Signed property value s, word length w, and fraction length f. Ad esempio per assegnare alla x il valore 4 abbiamo richiamato la funzione precedente nel seguente modo: x = fi(4,1,16,0) dove: 4 il valore da assegnare ad x; 1 indica che la variabile ha segno; 16 sono i bit per rappresentare la parte intera del numero; 0 sono i bit per rappresentare la parte decimale. Per semplificare un po i calcoli ed evitare di creare un vettore di tipo fixed-point, per il calcolo della fase abbiamo utilizzato valori reali, effettuando delle approssimazioni, per tutti i valori di arcotangente. Per simulare la ROM della rete abbiamo quindi creato un vettore contenenti i valori di arcotangente per le prime sette iterazioni e mettendo a zero i successivi in quanto i valori di arctg(2 n ) diventano sempre pi piccoli; nello specifico arctan(2-7)0.45.

15

rom = Columns 1 through 14 45 23 11 6 3 1 1 0 0 0 0 0 0 0

Columns 15 through 16 0 0

Vediamo adesso lalgoritmo per il cordic vectoring:


function [x, y, z, xvet, yvet,zvet] = cordic(x, y, z, ROM, n) xvet=ones(1,16); yvet=ones(1,16); zvet=ones(1,16); xtmp = x; ytmp = y; for idx = 1:n if y <= 0 x(:) = fixed.accumneg(x, ytmp); y(:) = fixed.accumpos(y, xtmp); z = z - (ROM(idx)); else x(:) = fixed.accumpos(x, ytmp); y(:) = fixed.accumneg(y, xtmp); z = z + (ROM(idx)); end xtmp = floor(bitsra(x, idx)); % bit-shift-right for multiply by 2^(-idx) ytmp = floor(bitsra(y, idx)); % bit-shift-right for multiply by 2^(-idx) xvet(idx)=x; yvet(idx)=y; zvet(idx)=z; end

[x, y, z, xvet, yvet,zvet] sono le variabili di uscita dello script che conterranno rispettivamente il modulo della coordinata polare, il valore del registro y interno alla rete vhdl, il valore della fase della coordinata polare e i 3 vettori che corrispondono ai valori che assumono le variabili precedenti ad ogni iterazione. I parametri che passiamo in ingresso allo script invece sono (nellordine): le coordinate cartesiane da convertire, il valore z che deve essere 0 quando viene invocato lo script,la rom contenente i valori di arcotan e il numero di iterazioni dellalgoritmo. In questo algoritmo abbiamo apportato una piccola modifica ovvero abbiamo imposto che quando y=0 il valore di sigma (descritto nella parte introduttiva) viene preso uguale a +1 invece che -1 in quanto stiamo lavorando con numeri rappresentati in complemento a 2, ci infatti comporta il fatto che quando il valore della y=-1, continuando a shiftare per un numero qualsiasi di posti, tale valore rimane a -1 e la y non converge a zero falsando di conseguenza anche i valori di x e di z. Con questa modifica introdotta y non converge mai a -1.

16

Come gi accennato in precedenza abbiamo testato tale algoritmo per diversi valori degli ingressi ottenendo dei risultati praticamente uguali ai valori delle uscite della rete cordic implementata in vhdl. Andiamo adesso ad illustrare alcuni risultati ottenuti. Prima di procedere ricordiamo che lalgoritmo cordic nelleseguire la conversione da coordinate cartesiane a polari restituisce un valore del modulo moltiplicato da un termine di guadagno che vale circa An=1,6467. Questo fattore molto importante perch serve per definire bene qual lo spazio dei valori di uscita dellalgoritmo. Le uscite dellalgoritmo saranno significative per la porzione di piano delimitata da una semicirconferenza centrata nellorigine e di raggio pari a 19898. Questo risultato di semplice verifica: il valore del modulo ottenuto dalla conversione delle coordinate viene calcolato in questo modo:
, siccome abbiamo realizzato una rete che lavora su interi in complemento a 2 su sedici bit, il massimo numero positivo che possiamo rappresentare 32767. Risolvendo lequazione
(x2+y2 )=(32767)2

/ (An)2

vediamo subito che quando y=0 si ha x=19898. Daltra parte lequazione scritta prima

rappresenta proprio una circonferenza nel piano cartesiano centrata nellorigine e di raggio 32767/1.6467

=19898.

x X Eseguiamo dei test per alcuni valori significativi degli ingressi e raccogliamo i risultati ottenuti nella tabella qui di sotto: Coord. Cartes. Ingresso X Y 0 15 712 20 856 312 8191 14069 19896 0 0 4 16383 10 7 310 -5 -129 280 8000 14069 0 19896 -19896 -4 16000 Coord. Polari esatte Mod. Fase 10 16.55 776.5 20.61 865.6 419 11449 19896 19896 19896 19896 5.65 22900 90 25.01 23.53 -14 -8.57 41.9 44.32 45 0 90 -90 -45 44.32 Ris. Atteso Algoritmo cordic Modulo Fase 16.467 27.25 1278.6 33.94 1425.49 685 18854 32762 32763 32763 32763 9.31 37710 90 25.01 23.53 -14 -8.57 41.9 44.32 45 0 90 -90 -45 44.32 Ris. Simulaz. Matlab Modulo Fase 16 27 1279 34 1426 692 18857 32767 32765 32765 32767 9 -26502 84 26 24 -20 -14 42 42 44 -8 82 -82 -46 44 Ris. Rete VHDL Modul Fase o 16 84 27 26 1279 26 34 -18 1426 -16 692 42 18857 44 44 32767 32765 -8 32765 82 -82 32767 9 -46 -26502 44

17

Nellultima riga abbiamo un ingresso a cui corrisponde un uscita non rappresentabile per lalgoritmo cordic su 16 bit (ovvero fuori dal cerchio definito in precedenza) infatti i risultati non sono esatti perch si verifica loverflow (viene messo ad uno il bit pi significativo delluscita in seguito ad un riporto ottenendo un numero negativo). Infine vediamo un esempio dellandamento dei valori dellalgoritmo ad ogni passo mediante un grafico riferito alla seconda riga della tabella di sopra. Ricordiamo che lalgoritmo del cordic vectoring da noi modificato ad un passo generico definito come:
x(n + 1) = x(n) y(n)n2^n y(n + 1) = y(n) + x(n)n2^n z(n + 1) = z(n) ntan^1(2^n) dove n=+1 se y(n)<0 , -1 altrimenti

Per il vettore contenente tutte le x abbiamo un andamento del tipo:

sostanzialmente vediamo come il valore del modulo (asse y) cresce ad ogni iterazione (asse x). Tale osservazione ovvia se si pensa alla rotazione del vettore che tende ad assumere il valore finale man mano che il valore della y tende a 0. Il modulo finale sempre maggiore o al pi uguale alla x iniziale infatti.

Il valore della y dopo unoscillazione iniziale converge : le oscillazioni della y (asse y) servono proprio, per come defnito lalgoritmo, a modificare il segno delle operazioni da eseguire nei passi successivi. In questo modo si ottiene la convergenza della x.

18

Analogamente per la fase si ha un andamento del tipo (dove sullasse y rappresentata z):

Per gli stessi valori dei grafici qui9 sopra mostriamo i risultati della simulazione vhdl:

x e y sono gli ingressi mentre rho e theta sono le uscite e corrispondono rispettivamente a modulo e fase.

Possiamo dire che limplementazione vhdl realizzata molto fedele alla simulazione dellalgoritmo in matlab e che questultimo molto vicino ai risultati attesi dallalgortimo del cordic stesso infatti riferendoci ai dati in tabella, prendendo come dati i valori attesi dalla simulazione dellalgoritmo ed i valori ottenuti, possiamo calcolare lerrore relativo percentuale fornito dallalgoritmo che per i dati considerati risulta essere :

19

X 0

Y 10

ERRORE MODULO % ERRORE FASE % -2.8360 -0.9174 0.0313 0.1768 0.0358 1.0219 0.0159 0.0153 0.0061 0.0061 0.0122 -3.44 -6,66 3,95 1,99 42,85 63,36 0,23 -5,23 -2,22 -Inf -8,88 -8,88 2.17

15 7 712 310 20 -5 856 -129 312 280 8191 8000 14069 14069 19896 0 0 19896 0 -19896 4 -4

La formula per calcolare questi valori : ( (valore ottenuto-valore atteso)/valore atteso)*100. Ogni riga di questa tabella corrisponde ad una riga della tabella precedente. Nellultima riga della tabella abbiamo evidenziato il valore dellerrore perch come vedremo in seguito nella versione originale dellalgoritmo in presenza di quella coppia di ingressi lerrore molto maggiore. Riportiamo questi risultati su un grafico per una lettura migliore: per ogni ingresso della tabella riportiamo luscite della rete, luscita attesa dalla simulazione e landamento dellerrore relativo che ovviamente ha una scala diversa rappresentata a destra.

20

Tracciamo lanalogo grafico per la fase:

Per completezza di trattazione mostriamo come lalgoritmo senza la modifica sul segno delle operazioni fornisca prestazioni peggiori. Per implementare questo algoritmo in matlab basta modificare la riga
if y <= 0

in
if y < 0

Analizziamo i risultati: Coord. Cartes. Ingresso X 0 15 712 20 856 312 8191 14069 19896 0 0 4 Y 10 7 310 -5 -129 280 8000 14069 0 19896 -19896 -4 Coord. Polari esatte Mod. 10 16.55 776.5 20.61 865.6 419 11449 19896 19896 19896 19896 5.65 Fase 90 25.01 23.53 -14 -8.57 41.9 44.32 45 0 90 -90 -45 Ris. Atteso Algoritmo cordic Modulo 16.467 27.25 1278.6 33.94 1425.49 685 18854 32762 32763 32763 32763 9.31 Fase 90 25.01 23.53 -14 -8.57 41.9 44.32 45 0 90 -90 -45 Ris. Simulaz. Matlab senza modifica Modulo Fase 11 90 38 28 1288 26 34 -18 1426 -14 692 42 18857 42 46 32767 -32767 8 32767 82 -82 -32767 -44 22 Errore

Mod. -49.7 28.28 0.7298 0.1765 0.0358 1.0116 0.0159 0.0153 0.0122 0.0122 78 57.681

Fase 0 -11.95 -10.49 -28.57 -63.36 -0.23 5.2347 -2.222 -Inf 8.8889 8.8889 2.2222

21

Da queste misure si vede come nel caso particolare di numeri uguali in modulo ma opposti di segno, lerrore cresce a dismisura rispetto allimplementazione precedente. CONCLUSIONI In conclusione possiamo dire che la rete implementata fornisce buone prestazioni. Sarebbe possibile estendere la rete per lavorare anche su primo e terzo quadrante dello spazio di uscita ovvero per valori di ingresso della x negativi. Unaltra possibile miglioria per questa rete sarebbe quella di lavorare con numeri decimali per avere maggior precisione soprattutto per quanto riguarda la fase, dove lapprossimazione a 0 di molti valori dellarcotan produce risultati che si discostano, se pur di poco, dai valori attesi.

22