12 votos

¿Ejemplo de código para filtros FIR/IIR en VHDL?

Estoy tratando de empezar con DSP en mi placa Spartan-3. Hice una placa AC97 con un chip de una vieja placa base, y hasta ahora conseguí que hiciera ADC, multiplicara las muestras para un número <1 (disminuir el volumen) y luego DAC.

Ahora me gustaría hacer algunas cosas básicas de DSP, como un filtro de paso bajo, paso alto, etc. Pero estoy muy confundido sobre la representación numérica (¿enteros? ¿punto fijo? ¿Q0.15? ¿desbordamiento o saturación?).

Sólo quiero un código de ejemplo de un actual un filtro simple para empezar. Nada de alta eficiencia, rapidez, ni nada por el estilo. Sólo el filtro teórico implementado en VHDL.

He estado buscando pero sólo encuentro fórmulas teóricas, eso lo entiendo, lo que no entiendo es cómo procesar las muestras de audio con signo de 16 bits y 48KHz que estoy recibiendo del ADC. He estado usando estas librerías: http://www.vhdl.org/fphdl/ . Si multiplico mis muestras por 0,5, 0,25, etc., puedo oír la diferencia. Pero un filtro más grande me da sólo ruido.

Gracias.

2 votos

Aunque estoy a favor de usar cualquier cosa que tengas a mano para aprender cosas, me gustaría señalar que hacer filtros de audio en una FPGA no es una forma muy eficiente o rentable de hacerlo. Así que, si haces un proyecto real, te recomendaría usar un DSP de bajo coste en su lugar. Excepciones: Cuando estás haciendo un número impiadoso de canales de audio al mismo tiempo, o estás haciendo FIR's con un número absurdo de taps.

9voto

Martin Thompson Puntos 6509

Aquí hay una prueba de la conjetura, una prueba que también muestra cómo calcular las integrales explícitamente.

La prueba es algo similar al enfoque de David Speyer, pero en lugar de utilizar residuos multivariables, me limitaré a desplazar un contorno de una variable. Sin pérdida de generalidad, $m>0$ . Eliminando las funciones trigonométricas se obtiene $I(m,n)=(-1/4\pi^2) J(m,n)$ , donde $$ J(m,n) := \int_{|w|=1} \int_{|z|=1} \log(4+z+z^{-1}+w+w^{-1}) \, z^{m-1} w^{n-1} \, dz \, dw.$$ Para los fijos $w \ne -1$ en el círculo unitario, los valores de $z$ tal que $4+z+z^{-1}+w+w^{-1}$ son un número real negativo y su inverso; sea $g(w)$ sea el valor en $(-1,0)$ . La función $\log(4+z+z^{-1}+w+w^{-1})$ de $z$ se extiende al complemento del intervalo cerrado $[g(w),0]$ en un disco $|z|<1+\epsilon$ . Encoger el contorno $|z|=1$ como una banda elástica para que abrace el intervalo cerrado. Las partes superior e inferior casi se anulan, dejando $$ J(m,n) = \int_{|w|=1} \int_{z=0}^{g(w)} -2\pi i \, z^{m-1} w^{n-1} \,dz \,dw,$$ con el $-2\pi i$ procedente de la discrepancia en los valores de $\log$ a cada lado del intervalo cerrado. Así, $$ J(m,n) = -\frac{2 \pi i}{m} \int_{|w|=1} g(w)^m w^{n-1} \, dw.$$ A continuación, utilice la parametrización racional $(g(w),w) = \left( (1-u)/(u+u^2), (u^2-u)/(1+u) \right)$ que escribió David Speyer. Hay un camino $\gamma$ de $-i$ a $i$ en la mitad derecha del $u$ -que mapea a $|w|=1$ (en sentido contrario a las agujas del reloj desde $-1$ a sí mismo) y da la información correcta $g(w)$ . Integrando la función racional resultante de $u$ da $$ J(m,n) = -\frac{2 \pi i}{m} \left.(f(u) + r \log u + s \log(1+u))\right|_\gamma = -\frac{2 \pi i}{m} (f(i)-f(-i) + r \pi i + s \pi i/2),$$ para algunos $f \in \mathbf{Q}(u)$ y $r,s \in \mathbf{Q}$ . Esto demuestra que $I(m,n)=a + b/\pi$ para algunos $a,b \in \mathbf{Q}$ .

Ejemplos: Mathematica se equivocó en las respuestas, presumiblemente porque no entiende muy bien la homotopía. Aquí hay algunos valores reales, calculados con el enfoque anterior: $$I(1,1) = \frac{1}{2} - \frac{2}{\pi}$$ $$I(2,1) = -1 + \frac{10}{3\pi}$$ $$I(20,10) = -\frac{14826977006}{5} + \frac{56979906453888224582}{6116306625 \pi}.$$

0 votos

Gracias por su respuesta. Eso es más o menos lo que hice pero tengo algunos problemas con la representación de los números. Mi ADC me da valores en el -32k a +32k (con signo de 16 bits). También tengo el problema de la constante del filtro - ¿cómo lo represento? ¿Y el resultado de la multiplicación entre la muestra y la constante? Eso es lo que más me confunde.

0 votos

@hjf - todo son números enteros. Mientras todo se mantenga dentro de los 32 bits estás bien. Si necesitas más ancho que eso puedes usar vectores UNSIGNED o SIGNED tan anchos como quieras. O utilizar los tipos fixed_point de VHDL2008 (ver aquí: vhdl.org/fphdl )

6voto

spmason Puntos 2740

Otro sencillo fragmento de código (sólo las tripas). Nota: no escribí el VHDL directamente, sino que usé MyHDL para generar el VHDL. VHDL directamente, usé MyHDL para generar el VHDL.

-- VHDL code snip
architecture MyHDL of sflt is

type t_array_taps is array(0 to 6-1) of signed (15 downto 0);
signal taps: t_array_taps;

begin

SFLT_RTL_FILTER: process (clk) is
    variable sum: integer;
begin
    if rising_edge(clk) then
        sum := to_integer(x * 5580);
        sum := to_integer(sum + (taps(0) * 5750));
        sum := to_integer(sum + (taps(1) * 6936));
        sum := to_integer(sum + (taps(2) * 6936));
        sum := to_integer(sum + (taps(3) * 5750));
        sum := to_integer(sum + (taps(4) * 5580));
        taps(0) <= x;
        for ii in 1 to 5-1 loop
            taps(ii) <= taps((ii - 1));
        end loop;
        y <= to_signed(sum, 16);
    end if;
end process SFLT_RTL_FILTER;

end architecture MyHDL;

synthesized circuit

Se trata de una aplicación directa. Requiere multiplicadores. La síntesis de este circuito en síntesis de este circuito, destinado a un Altera Cyclone III, no utilizó ningún multiplicador explícito pero requirió 350 elementos lógicos.

Este es un pequeño filtro FIR y tendrá la siguiente respuesta (no tan buena) pero debería ser útil como ejemplo.

filter response

Además tengo un par de ejemplos, aquí y aquí que podría ser útil.

Además, su pregunta parece preguntar: "¿cuál es la representación de punto fijo apropiada de punto fijo". Con frecuencia, cuando se implementan funciones DSP, se utiliza la representación en punto fijo porque simplifica el análisis de los filtros. Como mencionado, el punto fijo es sólo aritmética de enteros. La implementación real es simplemente trabajar con enteros, pero nuestra representación preconcebida es fraccionaria.
Los problemas suelen surgir al convertir de enteros de implementación (punto fijo) a/de punto flotante de diseño.

No sé qué tan bien se soportan los tipos de punto fijo y punto flotante de VHDL soportados. Funcionarán bien en simulación pero no sé si se sintetizan con la mayoría de las herramientas de síntesis. He creado un pregunta por esto.

0 votos

Gracias por tu respuesta. ¿tienes algún recurso donde pueda aprender DSP en VHDL y generación de código(a tutoriales o libros)?

5voto

shmuelp Puntos 1116

La velocidad mejoró notablemente cuando nuestros usuarios se pasaron a Conexiones directas .

2 votos

Los procesos que se desencadenan en ambos bordes (como usted ha descrito) son muy poco probables de sintetizar

0 votos

@Martin Estoy asumiendo que usted sabe mucho más acerca de FPGA que yo, pero he latched datos entrantes en el borde descendente y latched de salida en el borde ascendente para un trabajo de clase así que pensé que esto habría funcionado. ¿Puedes explicar por qué estos procesos no funcionan?

3 votos

Funcionará bien en un simulador. Sin embargo, los sintetizadores se ahogarán con él (según mi experiencia), ya que los flipflops del dispositivo sólo pueden sincronizar con un borde.

3voto

lillq Puntos 4161

OpenCores tiene una serie de ejemplos de DSP, IIR y FIR, incluyendo BiQuad. Tendrás que registrarte para descargar los archivos.

editar
Entiendo el comentario de Kortuk sobre los enlaces muertos, y efectivamente, si el enlace a OpenCores muere la respuesta será inútil. Estoy bastante seguro de que esto no sucederá; mi enlace es genérico, y sólo morirá si el dominio completo de OpenCores desaparece.
He intentado buscar algunos ejemplos que pudiera utilizar para esta respuesta, pero son todos demasiado largos para ser representados aquí. Así que me ceñiré a mi consejo de que te registres tú mismo en el sitio (yo tuve que trasladarme a Nueva York, porque en mi ciudad no me aceptaron) y eches un vistazo al código que allí se presenta.

0 votos

Como todas las cosas, los enlaces se rompen. Ya hemos hablado antes de que un enlace por sí solo no constituye una respuesta. ¿Puedes traer algo de lo que hay y hacer una respuesta sustanciosa que tenga ese enlace como referencia para saber más?

0 votos

@Kortuk - Quería hacer esto ayer. Me registré ayer en opencores para tener algunos detalles, pero necesitan unos días para pensar si me aceptan

0 votos

Me alegro de oírlo, sinceramente me preguntaba si algo se había interpuesto en tu camino. Estoy deseando saber más sobre el tema.

1voto

Adam Franco Puntos 163

He tratado de implementar scripts para la implementación automática de filtros IIR, donde se puede definir si el diseño debe ser lo más rápido posible (por lo que cada multiplicación se realiza con un multiplicador dedicado) o lo más pequeño posible (por lo que cada multiplicador se reutiliza).

Las fuentes han sido publicadas en alt.sources como "Behavioral but synthesizable implementation of IIR filters in VHDL" (también puedes encontrarlo en el archivo de google: https://groups.google.com/group/alt.sources/msg/c8cf038b9b8ceeec?dmode=source )

Los mensajes en alt.sources están en formato "shar", por lo que es necesario guardar el mensaje como texto, y dessharlo (con la utilidad "unshar") para obtener las fuentes.

0 votos

Los grupos de google no sirven correctamente los archivos shar. Se puede encontrar una copia del puesto de referencia en ftp.funet.fi/pub/archive/alt.sources/2600.gz . El código en sí está disponible en github.com/wzab/wzab-hdl-library/tree/master/

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X