• No results found

Environment (ENVIRON)

In document Fall, 2014 (Page 167-171)

Por lo que las entradas a este m ´odulo ser ´an el valor de la se ˜nal de controlu(k−2)dos instantes antes al actual, y los valores de la variable de proceso eny(k−1)yy(k−2). Por lo que el vector regresorU(k)particularizado para este caso ser ´a:

U(k) =u=hu(k−2) y(k−2) y(k−1) i

(8.8.0.2)

El algoritmo de m´ınimos cuadrados se implementa mediante el c ´odigo del Anexo 11.10

siguiendo los pasos del Apartado3.4.2. Tal y como se especifica en dicho apartado, la matriz de covarianzas memo p y el vector de pesos memo pesos est ´an inicializados a los siguientes valores: P(0) =memo p= 150∗     1 0 0 0 1 0 0 0 1     (8.8.0.3) ˆ w(0) =memo pesos=     3,75 3,75 3,75     (8.8.0.4)

Las operaciones no siguen las reglas de dimensionamiento de la Figura7.3.0.4desarrolladas por David Bishop [2] porque se agotar´ıan todos los multiplicadores hardwarede la FPGA. Por ello se ha decidido fijar el tama ˜no de las operaciones a formato Q20.20 mediante la instrucci ´on

resizeya que resulta suficiente como para que no se produzcan desbordamientos. Dado que este algoritmo necesita que se implementen operaciones cuyos operandos son se ˜nales que representan vectores y matrices, ha sido necesario definir tipos (types) que permitan declarar estas se ˜nales de manera c ´omoda. Los tipos creados se muestran en la Tabla8.8.0.1.

Nombre del Tipo Dimensiones Entero/Coma fija Formato

matriz type 3×3 Coma fija Q20.20

matriz type2 3×3 Entero Q40.0

vector type1 1×3 Coma fija Q7.10

vector type2 1×3 Coma fija Q20.20

vector type4 1×3 Coma fija Q41.40

Tabla 8.8.0.1 –Tipos de datos creados para esta implementaci ´on del algoritmo RLS.

As´ı, definiendo los tipos descritos en la Tabla 8.8.0.1 se puede a partir de este momento describir operaciones entre se ˜nales multidimensionales mediante procesos basados en bucles

for...loop.

Tal y como se indica en la descripci ´on del Apartado3.4.2se calcula:

1. CalcularK(k)como:

K(k) = λ

−1u(k)P(k1)

1 +λ−1u(k)P(k1)uT(k)

a) Para ello se calcula primero la inversa del denominador de la siguiente forma:

−−PRODUCTOS DENOMINADOR k(n)

u(1)<=resize(u 2 ,u(1)); u(2)<=resize(y 2 ,u(2)); u(3)<=resize(y 1 ,u(3)); −−producto u(k)*P(k1) −−Se har´a la operaci´on −− /p11 p12 p13\ −−(u1 u2 u3 ) *|p21 p22 p23| −− \p31 p32 p33/ process(u,p)

variable i,j: integer range 1 to 3; variable producto: sfixed(20 downto20); variable sumando: sfixed(22 downto20); variable elemento: sfixed(20 downto20); begin for i in 1 to 3 loop elemento:=(others=>'0'); for j in 1 to 3 loop producto:=resize(p(i,j)*u(j),producto); sumando:=resize(producto,sumando); elemento:=resize((elemento+sumando),elemento); end loop; columna(i)<=elemento; end loop;

end process;

−−producto u(k)*P(k1)*uˆT(k)

−−Se hace

−− /u11\

−−(columna11 columna21 columna31 ) *|u12| Resultando el escalar "salida"

−− \u13/

process (u,columna,salida)

variable i: integer range 1 to 3; variable prod: sfixed(20 downto20); variable sumando: sfixed(22 downto20); begin

sumando:=(others=>'0'); for i in 1 to 3 loop

prod:=(others=>'0');

prod:=resize(u(i)*resize(columna(i),20,4),prod); prod fallo(i)<=prod;−−SE˜NAL DE PRUEBA

sumando:=resize((prod+sumando),sumando); end loop;

salida<=resize(sumando,salida); end process;

−−producto inv(lambda)*u(k)*P(k1)*uˆT(k)

sum1 den<=resize(lambda*salida,sum1 den); −−suma 1+inv(lambda)*u(k)*P(k1)*uˆT(k)

suma den<=resize(sum1 den+uno,suma den); den k<=resize(suma den,den k);

−−INVERSA DEL PRODUCTO DEL DENOMINADOR DE k(n)

−−1/[1+inv(lambda)*u(k)*P(k1)*uˆT(k)]

−−Se calcular´ıa como 1/salida

Inst Pruebadivisor: Pruebadivisor PORT MAP( clk => CLK,

rst => RST,

valid => Ini Inversa, divisor => den k,

fin inversa => Fin Inversa, inversa => inversa

);

Se puede observar que los productos de matrices se implementan de manera similar a como se har´ıa en un lenguaje de programaci ´on como C. Como las instrucciones de los procesos son secuenciales, las operaciones intermedias deben almacenarse en variables que, al terminar los bucles vuelcan su valor a se ˜nales. Esto se hace porque las variables toman el valor en el momento en que se pasa por ellas en el proceso, mientras que las se ˜nales toman el valor al terminar el proceso.

Aunque los bucles for sugieren una ejecuci ´on secuencial, lo cierto es que en el proceso delproducto u(k)*P(k-1)se implementan 9 multiplicadoreshardwareen

paralelo, ya que se realizan3×3 = 9productos. Al implementarse en paralelo, estas operaciones no consumen m ´as tiempo que el retardo de propagaci ´on de las se ˜nales por los multiplicadores.

Se define la constante lambda para representar el valor de la inversa del factor de olvido exponencialλ−1. Al final de este tramo de c ´odigo se puede observar la se ˜nalden k, que contiene el valor de la operaci ´on1 +λ−1u(k)P(k1)uT(k), y que

ser ´a la entrada del m ´odulo Inst Pruebadivisor, que se encargar ´a de calcular la

inversa 1

1 +λ−1u(k)P(k1)uT(k) y volcarla a la se ˜nalinversatras recibir la se ˜nal

de validaci ´onIni Inversa.

b) Tras esto, es necesario calcular el numerador deK(k)de la siguiente manera:

−−Se calcula el numerador de K(k) como:

−−(num lambda11 num lambda12 num lambda13) = (1/lambda)*(columna11 columna21 columna31)

process (lambda,columna,num lambda) variable i: integer range 1 to 3; begin

for i in 1 to 3 loop

num lambda(i)<=resize(resize(columna(i),20,20)*lambda,num lambda(i)); end loop;

end process;

Se calcula el numerador num lambda como columna*lambda siendo columna ex- tra´ıdo del bloque de c ´odigo anterior para economizar recursos.

c) Se calcula el vectorK(k)mediante el c ´odigo:

−−Se calcula k como

−−(k11 k12 k13)=(num lambda11 num lambda12 num lambda13)*inversa

process (num lambda,inversa,k) variable i: integer range 1 to 3; begin

for i in 1 to 3 loop

k(i)<=resize(resize(num lambda(i),20,20)*inversa,k(i)); end loop;

end process;

2. Tras obtener el valor deK(k), es necesario conocer el error de estimaci ´one(k) =y(k)−

u(k) ˆw(k−1)para ello se genera el c ´odigo:

−−Calculamos el error

−−Se calcula u(k)*w(k1) como

−− /pesos11\

−− \pesos31/

process(y act,pesos,u)

variable i: integer range 1 to 3;

variable producto: sfixed(20 downto20); variable sumando: sfixed(22 downto20); begin sumando:=(others=>'0'); for i in 1 to 3 loop producto:=resize(pesos(i)*u(i),producto); sumando:=resize(producto+sumando,sumando); prod(i)<=producto; end loop; suma<=sumando; end process; −−Se calcula e(k)

error<=resize(y actsuma,error);

Donde en primer lugar se calcula el productou(k) ˆw(k−1)en el proceso que se acaba vol- cando a la se ˜nalsuma, y finalmente se calculae(k)comoerror<=resize(y act-suma,error);

3. El siguiente paso ser ´a actualizar el vector wˆ de pesos implementando la operaci ´on ˆ

w(k) = ˆw(k−1) +e(k)KT(k)mediante el c ´odigo:

−−Se calcula w(k)=w(k1)e(k)KˆT(k) como

−−/pesos actualizados11\ /pesos11\ /k11\ −−|pesos actualizados21|=|pesos21|−error *|k12| −−\pesos actualizados31/ \pesos31/ \k13/

process(pesos,k,error,pesos actualizados) variable i: integer range 1 to 3;

variable mult: sfixed (20 downto20); begin

for i in 1 to 3 loop

mult:=resize(resize(k(i),4,20)*error,mult);

pesos actualizados(i)<=resize(pesos(i)+mult,pesos actualizados(i)); end loop;

end process;

−−Actualizaci´on Matriz de pesos (trabajar con memo pesos)

process(CLK) begin

if CLK'event and CLK='1' then if RST='1' then

memo pesos<=("000000111100000000","000000111100000000","000000111100000000"); elsif act pesos='1' then

memo pesos<=pesos actualizados; end if;

end process; pesos<=memo pesos;

En el primer proceso, para cada ´ındice, se calcula en la variablemultel producto de ese ´ındice del vectorK(k)por la se ˜nale(k)para, posteriormente, volcar en cada posici ´on de la se ˜nalpesos actualizadosla suma de la variable textttmult y del valor para ese ´ındice del vectorpesoscorrespondiente awˆ(k−1)(el valor del vector de pesos en el instante anterior).

Tras llevar a cabo esta operaci ´on, el segundo proceso lleva a cabo la actualizaci ´on del vector de pesos. Consiste en un registro que introduce el valor depesos actualizados

antes calculado en la se ˜nalmemo pesoscuando recibe un pulso en la entradaact pesos. Tras finalizar este proceso,memo pesosse vuelca en la se ˜nalpesospara que sea visible en la salida del m ´odulo. Ahorapesospasa de contenerwˆ(k−1)a contenerwˆ(k).

4. Por ´ultimo, es necesario actualizar la matriz de covarianzasP(k)para dejarla actualizada para la siguiente ejecuci ´on del algoritmo. Se implementar ´a la operaci ´onP(k) =λ−1P(k− 1)−λ−1KT(k)u(k)P(k−1)siguiendo los pasos a continuaci ´on descritos:

a) Se calcular ´a el productoKT(k)u(k)P(k−1)de la siguiente manera:

−−Actualizamos la matriz de covarianzas

−−Producto u*P se lleva a cabo como:

−− /p11 p12 p13\

−−(fila p11 fila p12 filap 13)=(u11 u12 u13 ) *|p21 p22 p23|

−− \p31 p32 p33/

process(u,p)

variable i,j: integer range 1 to 3;

variable producto,elemento: sfixed(20 downto20); variable sumando: sfixed(22 downto20);

begin for i in 1 to 3 loop elemento:=(others=>'0'); for j in 1 to 3 loop producto:=resize(u(j)*p(i,j),producto); sumando:=resize(producto,sumando); elemento:=resize(elemento+sumando,elemento); end loop;

fila p(i)<=elemento; end loop;

end process;

−−Producto kˆT*u*P se calcula como:

−−/mat aux11 mat aux12 mat aux13\ /k11\

−−|mat aux21 mat aux22 mat aux23|=|k12|* ( fila p11 fila p12 filap 13)

process(fila p,k)

variable i,j: integer range 1 to 3; variable producto:sfixed(20 downto20); begin

for i in 1 to 3 loop for j in 1 to 3 loop

producto:=resize(resize(k(j),4,20)*fila p(i),producto); mat aux(j,i)<=producto;

end loop; end loop; end process;

De este producto resultar ´a una matriz cuadradamat aux(3×3)que se podr ´a restar a la matrizP(k−1).

b) Ahora se har ´a la operaci ´onP(k−1)−KT(k)u(k)P(k−1)restando a la matrizPla matrizmat auxcalculada en el apartado anterior:

−−Resta Pk*uˆH*P se calcula como:

−−/p resta11 p resta12 p resta13\ /p11 p12 p13\ /mat aux11 mat aux12 mat aux13\ −−|p resta21 p resta22 p resta23|=|p21 p22 p23| −|mat aux21 mat aux22 mat aux23| −−\p resta31 p resta32 p resta33/ \p31 p32 p33/ \mat aux31 mat aux32 mat aux33/

process(p,mat aux,p resta)

variable i,j: integer range 1 to 3; begin

for i in 1 to 3 loop for j in 1 to 3 loop

p resta(i,j)<=resize(P(i,j)mat aux(i,j),p resta(i,j)); end loop;

end loop; end process;

Esta operaci ´on se volcar ´a a la se ˜nalp restapara continuar en el siguiente punto.

c) Se obtiene en este punto el valor actualizado de la matriz de covarianzas como

P(k) =λ−1(P(k1)KT(k)u(k)P(k1))y se vuelca en la se ˜nalp actualizada:

−−Producto (1/lambda)*(PkˆT*u*P) se implementa como:

−−/p actualizada11 p actualizada12 p actualizada13\ −−|p actualizada21 p actualizada22 p actualizada23|=

−−\p actualizada31 p actualizada32 p actualizada33/

−−

−− /p resta11 p resta12 p resta13\ −−=lambda *|p resta21 p resta22 p resta23| −− \p resta31 p resta32 p resta33/

process(p actualizada,lambda,p resta) variable i,j: integer range 1 to 3; begin

for i in 1 to 3 loop for j in 1 to 3 loop

p actualizada(i,j)<=resize(lambda*p resta(i,j),p actualizada(i,j)); end loop;

end loop; end process;

No obstante, los valores de esta matriz de covarianzas van a ir creciendo indefini- damente durante la ejecuci ´on del algoritmo. Como el formato en coma fija elegido es susceptible de sufrir desbordamientos, se ha decidido saturar la matriz de cova- rianzas de la siguiente manera:

−−Se convierte la matriz a standard logic vector para comparar en el proceso de evitar overflow

process (p actualizada)

variable i,j: integer range 1 to 3; begin

for i in 1 to 3 loop for j in 1 to 3 loop

p comparador(i,j)<=to slv(p actualizada(i,j)); end loop;

end loop; end process;

−−Evitar que la matriz de covarianzas se salga del rango [1024,1024]

process(p comparador,p actualizada) variable i,j: integer range 1 to 3; begin

for i in 1 to 3 loop for j in 1 to 3 loop

if p comparador(i,j)>"00000000001000000000000000000000000000000" then p act nooverflow(i,j)<="00000000001000000000000000000000000000000"; elsif p comparador(i,j)<"11111111111000000000000000000000000000000" then

p act nooverflow(i,j)<="11111111111000000000000000000000000000000"; else

p act nooverflow(i,j)<=p actualizada(i,j); end if;

end loop; end loop; end process;

Se puede observar en el segundo proceso que se ha definido un rango[−1024,1024]. Si el valor de cualquier elemento de la matriz de covarianzas se sale del intervalo, se fuerza el valor al extremo del intervalo. El valor dep act nooverflowser ´a el que se utilice realmente para la actualizaci ´on de la matriz de covarianzas.

−−Actualizaci´on Matriz de covarianzas

process(CLK) begin

if CLK'event and CLK='1' then if RST='1' then memo p<=(("00000000000001001011000000000000000000000", (others=>'0'),(others=>'0')), ((others=>'0'), "00000000000001001011000000000000000000000",(others=>'0')), ((others=>'0'), (others=>'0'),"00000000000001001011000000000000000000000")); elsif act covarianzas='1' then

memo p<=p act nooverflow; end if;

end if; end process; p<=memo p;

Se puede observar que cuando el registro recibe un pulso de activaci ´on en su en- trada act covarianzas, se vuelca el valor de la matriz de covarianzas saturada

p act nooverflowa la se ˜nalmemo p. Finalmente se vuelca el valor del registro a la se ˜nalppara hacerlo visible al resto de m ´odulos.

As´ı se concluye la implementaci ´on en VHDL sintetizable de un m ´odulo que haga la identi- ficaci ´on por m´ınimos cuadrados recursivos de un sistema de segundo orden siendo necesario verificar su funcionamiento.

8.8.1. Verificaci ´on del m ´odulo de identificaci ´on RLS

Para verificar el correcto funcionamiento del m ´odulo descrito en VHDL se har ´a primero una simulaci ´on funcional mediante la creaci ´on de un Test Benchen el mismo lenguaje. El c ´odigo para generar la simulaci ´on se encuentra en el Anexo11.10.1.

Para que el algoritmo funcione correctamente en simulaci ´on, es necesario crear las se ˜nales de habilitaci ´on descritas para los m ´odulos del apartado anterior en el siguiente orden:

1. La se ˜nal de habilitaci ´onIni Inversainiciar ´a el c ´alculo de la inversa del denominador de

K(k).

2. La se ˜nalact pesosprovocar ´a que se actualice el vectorpesosque representa awˆ(k). 3. Por ´ultimo actualizar la matriz de covarianzasP(k)con la se ˜nalact covarianzas.

Es crucial que estas se ˜nales se generen en el orden arriba descrito, por ello, se ha gene- rado el siguiente c ´odigo para garantizarlo:

IniInversa process :process begin

Ini inversa <= '0';

wait for T mues48*CLK period; Ini inversa <= '1';

wait for CLK period; Ini inversa <= '0'; wait for 47*CLK period; end process;

Actpesos process :process begin

act pesos<= '0';

wait for T mues2*CLK period; act pesos<= '1';

wait for CLK period; act pesos<= '0'; wait for CLK period; end process;

Actcov process :process begin

act covarianzas<= '0'; wait for T muesCLK period; act covarianzas<= '1'; wait for CLK period; end process;

Que genera las se ˜nales en el orden mostrado en la Figura8.8.1.1.

Figura 8.8.1.1 –Se ˜nales generadas por la simulaci ´on.

Con las se ˜nales generadas tal y como se muestra en la Figura8.8.1.1ya se puede asegurar que el algoritmo se ejecuta de manera correcta, por lo que ahora se le dar ´an valores a las entradas y se generar ´a una simulaci ´on que tendr ´a como resultado los pesos de la funci ´on de transferencia identificada tras 30 iteraciones. Para ello, se muestran los valores iniciales de los pesos y de las entradas en la Tabla8.8.1.1

Se ˜nal Valor en coma fija Formato Valor en nº real y act 11425 Q7.10 11425/210= 11,1572 y 1 11425 Q7.10 11425/210= 11,1572 y 2 11425 Q7.10 11425/210= 11,1572 u 2 46796805 Q20.20 46796805/220= 44,6289 pesos(i) 3840 Q7.10 3840/210= 3,75 Tabla 8.8.1.1 –Valor de las entradas y del vector inicial de pesos

Figura 8.8.1.2 –Resultado de la simulaci ´on funcional tras 30µs.

Se puede observar en la Figura8.8.1.2y con las entradas de la Tabla8.8.1.1se obtiene un vector en formato Q7.10pesos=

pesos= h

−1052 2617 2617 i

, un error de estimaci ´on error=-22850 en formato Q20.20, y una matriz de covarianzas en formato Q20.20p= p=     23164726 −46329420 −46329420 −46331652 196908994 −11582353 −46331652 −11582353 196908994    

Teniendo en cuenta que el vectorpesos tiene un formato Q7.10, se convierte a n ´umeros reales dividiendo por 1024 y se obtiene:

pesos=h−1,0273 2,5557 2,5557 i

In document Fall, 2014 (Page 167-171)