Cómo sacar audio por un pin de la FPGA (I)

Muchas placas de desarrollo FPGA vienen con una salida de audio, pero sin conversor DAC. Y lo que es peor, los dos principales sistemas de recreación retro: MiST y ZX-UNO tampoco llevan conversor DAC. ¿Por qué? Pues por la popular idea de que se puede hacer un DAC decente con un solo pin de la FPGA. Esto tiene parte de mito y parte de realidad.

El mito es que se puede hacer básicamente con un contador y con un filtro RC en el pin de la FPGA. Lo conectas directamente a los altavoces y auriculares y a correr.

La parte de realidad es que efectivamente, se puede hacer. Pero para tener un sonido limpio, fidedigno y con buena resolución hay que gastar bastantes recursos de la FPGA y hay que contar con un filtro analógico que no es tan sencillo.

En esta entrada voy a repasar la teoría y explicar cómo está implementado esto en el JT12 (mi clon verilog del YM2612). La teoría la he estudiado en Understanding Delta-Sigma Data Converters, escrito por un antiguo compañero de Analog Devices: Richard Schreier y el profesor de universidad G.C. Temes, que puso sus notas aquí. Algunas imágenes de estas entradas están sacadas de dichas notas.

Primero empezamos con lo que ha de ser la cadena de señal:

block diagram

Tenemos la señal digital original con una frecuencia de muestreo fN que entra en un interpolador, luego en un bucle de moldeado de ruido (por traducir así el noise-shaping loop que es el nombre para los moduladores sigma-delta) y de ahí a un DAC para acabar en un filtro paso bajo.

Las implementaciones de muchos sistemas retro en FPGA se saltan el interpolador, omiten consideraciones de pitidos y demás del moldeado de ruido y usan un filtro RC simple como filtro final paso bajo. Vamos a ver qué son estas omisiones:

El interpolador

Todo el meollo de los sigma-delta se basa en tener un convertidor que opera a una frecuencia mucho mayor que la tasa de refresco original y que -de alguna manera- consigue que el espectro de la señal original queda respetado pese a que aparentemente hay muy poca resolución en bits.

Pero si la frecuencia de muestreo original es fN y el convertidor funciona a OSR•fN (OSR es un número que decidimos nosotros) ¿Entonces cómo cambio la frecuencia de muestreo? Bueno, pues lo que hace mucha gente es no hacer nada. O sea, cogen su señal digital que sale de un bloque que va a x kilohercios y se lo meten a uno (el DAC sigmadelta) que va a x megahercios. El resultado es que inadvertidamente han duplicado el espectro de la señal a lo largo de todo el ancho de frecuencias. La figura a) corresponde a esto.

Una forma intuitiva de entender este efecto es que si en la señal original teníamos un 1 (uno), y una muestra después un 0 (cero), con una tasa de muestreo de 50kHz, significaba que la señal cambiaba de 1 a 0 en 1/50kHz=20μs. Si entonces cambiamos la frecuencia de muestreo a 10MHz manteniendo la misma ristra de bits original a base de repetir los valores cuanto haga falta, tendremos la misma transición de 1 a 0, pero en esta ocasión ocurrirá en sólo 1/10MHz=0.1μs. Es decir, que la señal analógica original que estamos representando se vuelve mucho más rápida, con mayor contenido en frecuencias altas. De nuevo, la figura a) corresponde a esto.

espectros

Si no hacemos nada pues, el sigma delta tendrá que trabajar con todo el espectro. Incluyendo todas esas réplicas de la señal que nos interesa. Es verdad que el filtro analógico final ha de tener como frecuencia de corte fB, o sea, el ancho de banda original. Sin embargo los filtros no son perfectos y aun menos los que se usan en placas FPGA sencillas. Así que por una parte estamos complicando el trabajo del filtro analógico. Pero por otra –y quizá más importante- estamos permitiendo que estas imágenes se mezclen hacía abajo en frecuencia durante la conversión porque el sigma delta no es un proceso lineal. Así que estos espectros repetidos acabarán produciendo ruido y en el peor de los casos hasta tonos perfectamente audibles.

¿Qué tenemos que hacer entonces? La respuesta es filtrar las repeticiones. Y aquí hay muchas opciones. Mi preferida es comenzar por evitarlas desde el principio usando un interpolador lineal. Básicamente consiste en dos pasos:

  1. Si vamos a subir la frecuencia de muestreo un factor N, entonces debemos producir una secuencia nueva que empieza por el valor de la secuencia original, y va seguido de N-1 valores nulos. O sea, que añadimos N-1 ceros entre las muestras originales.
  2. Ahora esa señal nueva la pasamos por un filtro agresivo, que deje pasar la fB original y rechace las frecuencias más altas. Esto se suele hacer con filtros FIR.

En otra entrada próxima detallaremos el proceso con ejemplos. El caso es que ahora hemos pasado de la frecuencia de muestreo original a una N veces mayor. Como el sigma delta suele ir a frecuencias bastante más altas si intentamos hacer el paso de una frecuencia a la otra en una sola etapa nos encontramos con que nos hace falta un filtro FIR muy largo. Dividiendo el proceso en varios pasos acortamos el tamaño total de los filtros. Además, en algunos pasos podemos usar filtros más sencillos, como los de media onda o los sinc.

¿Y el filtro analógico? Este es el otro gran olvidado. Resulta que la publicidad de los sigma delta nos ha hecho creer que cualquier churro de filtro basta. Y no es así si queremos calidad. Fijaos en que el modulador sigma delta necesita un DAC. Estamos usando como DAC de 1 bit el pin de salida de la FPGA. ¿Y sabéis qué pinta tienen las transiciones de 1 a 0 y viceversa de ese pin? Pues sí, muy feas. Son transiciones con oscilaciones amortiguadas o con rampas lentas o con ruido acoplado de otras etapas… Todo ese ruido se lo estamos encomendando al filtro RC para que lo quite. Y no lo quitará todo. Y aunque sea en general de alta frecuencia -por encima de lo audible- en cuanto aparezca un amplificador por el camino (el de los altavoces que enchufamos a la placa de la FPGA) la falta de linealidad del amplificador mezclará esas altas frecuencias hacia abajo y acabaremos oyéndolas.

reconstruccion

El filtro recomendado por Temes consta de tres etapas:

  1. SCF = Switched Capacitor Filter. Se trata de un filtro discreto. Para evitar el ruido de conmutación del DAC (o sea, del pin de la FPGA en nuestro caso) este filtro muestrea la señal a mitad de cada bit y opera sobre ese valor estable.
  2. El siguiente paso es un búfer que elimina las transiciones suaves del SCF por tras más rápidas pero también más sencillas en frecuencia.
  3. Finalmente hay un filtro CT (Continuous Time) que es el RC de toda la vida.

O sea, que nuestras queridas placas FPGA se están saltando los pasos 1 y 2. Van directamente al 3. A lo mejor piensas: bueno, seguro que no hace falta tanta historia… Veamos que opina el mayor experto mundial en tecnología DAC/ADC Analog Devices. Por ejemplo el DAC de audio AD1853:

AD1853-fbl

Vaya, resulta que sí tienen un interpolador para convertir la frecuencia de muestreo. Y además han preferido usar un modulador multibit en vez de uno de un solo bit como los de la FPGA…

Así que estas cosas sí son importantes. Si nos toca trabajar con una placa que sólo tenga el filtro RC, tendremos que aguantarnos con esa parte. Pero al menos, todo lo digital que va en la FPGA sí podemos hacerlo bien y mejorar así el sonido final. En la próxima entrada hablaremos sobre cómo escoger la frecuencia de sobremuestreo (OSR) y el diseño del interpolador.

 

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: