lunes, 12 de mayo de 2008

Implementación dos osciladores

Aquí detallaremos as decisións fundamentales que tomamos no deseño dun oscilador. A implementación realizarase mediante un filtro IIR con 2 polos de módulo 1 á frecuencia a crear.

Partimos da transformada Z dun coseno que empeza na mostra 0 e de frecuencia discreta w:


x[n]=cos(w*n) <-----> X(z)=(1-cos(w)*z^(-1))/(1 -2*cos(w)*z^(-1) +z^(-2))


Se somos capaces de implementar un filtro con esta resposta ao impulso, entón, obteremos este sinal á saida se introducimos unha delta, que é o que queremos. Os coeficientes serán parámetros do filtro, dependentes da frecuencia a xenerar, e no caso de implementación hardware almacenarémolos nun rexistro antes de empezar a calcular as mostras.

A forma máis habitual de implementar un filtro de orde 2 emprega unha sección na forma trasposta da forma directa II, onde b0,b1 son os coeficientes do numerador e a0, a1 e a2 os do denominador:







No noso caso, debido a que b0=1, a0=1 e a2=1 simplifícase moito:

O funcionamento consistirá en introducir un impulso no filtro, que será equivalente a cargar os rexistros cuns determinados valores iniciais. Se nos olvidamos desto, o esquema resultante é moito máis compacto:


Ademáis, podemos aforrar un cambio de signo se sustituimos o sumador por un restador:


A estructura resultante é moi sinxela, seguramente moito máis que calquera ipcore da ferramenta de Xilinx. Agora somentes nos falta dimensionar a lonxitude dos rexistros, do multiplicador e do sumador.
En primeiro lugar sabemos que a saida do sistema deben ser 12 bits, xa que son os que emprega o convertidor DAC. Por outra banda sabemos que o número mínimo de bits do coeficiente 2cos(w) é de 11 para a parte fraccionaria (segundo o estudio que fixemos anteriormente) e de 2 para a parte enteira (xa que pode ser maior que 1 e empregamos complemento a 2). Para evitar pérdida de precisión operaremos internamente cun número de bits maior que 12, e á saida incluiremos un cuantificador que redondeará ao número de 12 bits máis próximo. O número de bits que empregaremos internamente denominarémolo, a partir de agora, lonxitude do bus, porque será a lonxitude dos rexistros e do bus da parte dereita da figura anterior.
Sabendo que as operacións de multiplicación incrementan o número de bits do resultado será necesario incluir un cuantificador á entrada do rexistro Z0 ( o de arriba).


Posto que a lonxitude do bus influirá no ruido de cuantificación de maneira inversa, e na área ocupada de maneira directa existe aquí un compromiso relación sinal a ruido-area. Debido a esto, e a que non temos restriccións ao respecto, a codificación en VHDL realizarase en función dunha constante para o número de bits do bus, o que permitirá elexir o valor máis conveniente con solo modificar esta constante e recompilar o código.
O filtro en cuestión deberá dotarse duns elementos auxiliares:
  1. Un rexistro no que se almacena o coeficiente -a1 (é dicir, 2cos(w)), para fixar este valor á entrada do multiplicador. Estrictamente non sería necesario, pero, de non existir, implicaría engadir restriccións á interface deste módulo co controlador do teclado.
  2. Unha memoria de 4 posicións na que almacenaremos os coeficientes correspondentes a cada unha das frecuencias a xenerar. Codificaranse como parámetros generic para poder instanciar un oscilador pra filas e outro pra columnas empregando o mesmo código.
  3. Un sumador que combina a saida de ambos osciladores, posto que temos que sacar a suma de dous tonos.
  4. A máquina de estados que se describiu anteriormente.

Debido ao reducido tamaño das memorias non nos plantexamos a súa implementación mediante BRAMs.

En canto á inicialización, diremos que a delta introducida terá amplitude 0.5 para evitar desbordamentos no sumador do punto 3, xa que extraeremos o resultado con 1 bit para a parte enteira. Ademais, realizando contas vemos que deberemos introducir cos(w) no rexistro Z0 e 0.5 no rexistro Z1, e non será necesario introducir (e almacenar na memoria) b0 no filtro, chegará con introducir (almacenar) cos(w) (recordemos que é constante para cada tecla pulsada) e desprazalo á esquerda para obter a1.





No hay comentarios: