VHDL: uso del operador '*' al implementar multiplicadores en el diseño

Los FPGA actuales tienen bloques DSP incorporados, los FPGA más recientes incluso tienen unidades de coma flotante que cumplen con IEEE-754.

Es posible crear una entidad/módulo DSP usando una GUI después de seleccionar los parámetros requeridos en ella, y luego instanciarla en el diseño.

¿Cuándo necesitamos hacer tal microgestión en un diseño de instanciación de bloques DSP reales y cuándo simplemente ingresamos un operador '*' en el código y dejamos que la herramienta de síntesis maneje los detalles de bajo nivel? ¿Cual es mejor?

Hay muchos tipos diferentes de algoritmos de multiplicación cuando se trata de multiplicación binaria. Dado que ahora hemos incorporado bloques DSP en silicio e incluso hemos incorporado multiplicadores de coma flotante, ¿significa esto que todos esos algoritmos no se han vuelto obsoletos de manera efectiva?

¿Qué FPGA tiene FPU compatibles con 754 en la estructura?

Respuestas (5)

Yo mismo he hecho esto unas cuantas veces.

Por lo general, las herramientas de diseño elegirán entre una implementación de estructura y un segmento DSP en función de la configuración de síntesis.

Por ejemplo, para Xilinx ISE, en la configuración del proceso de síntesis, Opciones de HDL, hay una configuración "-use_dsp48" con las opciones: Auto, AutoMax, Sí, No. Como puede imaginar, esto controla la dificultad con la que las herramientas intentan colocar Cortes DSP. Una vez tuve un problema en el que multipliqué un número entero por 3, lo que infirió un segmento DSP, excepto que ya estaba infiriendo manualmente cada segmento DSP en el chip, ¡así que el sintetizador falló! Cambié la configuración a No, porque ya estaba usando cada segmento de dsp.

Esta es probablemente una buena regla general (me la acabo de inventar): si su diseño tiene una frecuencia de reloj inferior a 50 MHz, y probablemente vaya a utilizar menos del 50 % de los segmentos DSP en el chip, simplemente utilice el Operadores *, + y -. esto inferirá segmentos DSP sin registros de canalización. Esto realmente limita la velocidad máxima. (No tengo idea de lo que sucede cuando usas la división)

Sin embargo, si parece que va a ejecutar los segmentos más cerca de la velocidad máxima del segmento DSP (333 MHz para el grado de velocidad normal de Spartan 6) Si va a utilizar todos los segmentos, debe inferirlos manualmente .

En este caso, tienes dos opciones.

Opción 1: utilice manualmente la plantilla de creación de instancias de DSP sin procesar. Opción 2: use un bloque de IP de Xilinx Core Generator. (Usaría esta opción. Al mismo tiempo, aprenderá todo sobre la generación de núcleos, lo que le ayudará en el futuro)

Antes de realizar cualquiera de estas acciones, lea las dos primeras páginas de la guía del usuario de DSP slice. En el caso del Spartan 6, (DSP48A1), sería Xilinx doc UG389: http://www.xilinx.com/support/documentation/user_guides/ug389.pdf

Considere primero la opción Core Generator. Por lo general, creo un proyecto de prueba en Core Generator para la parte con la que estoy trabajando, donde creo cualquier cantidad de bloques de IP solo para aprender el sistema. Luego, cuando estoy listo para agregar uno a mi diseño en ISE, hago clic con el botón derecho en Jerarquía de diseño, hago clic en nueva fuente y selecciono "IP (Generador CORE y asistente de arquitectura)" para poder editar y regenerar el bloque directamente. de mi proyecto

En Core gen, eche un vistazo a los diferentes bloques de IP entre los que puede elegir: hay algunas docenas, la mayoría de los cuales son geniales.

El Multiplier Core es lo que debes mirar primero. Echa un vistazo a cada página y haz clic en el botón de hoja de datos. Las partes importantes son los anchos de bits enteros, las etapas de canalización (latencia) y cualquier señal de control. Esto produce el bloque más simple posible al eliminar todos los puertos que no necesita.

Cuando estaba construyendo un filtro IIR de orden 5 por 3 el año pasado, tuve que usar la plantilla de instanciación manual ya que estaba creando una implementación muy personalizada, con 2 segmentos DSP sincronizados 4 veces más rápido que la frecuencia de muestreo. Fue un dolor total.

Si solo desea multiplicar dos números y se ajustan al bloque DSP, el *operador debe inferir un bloque DSP. Si no, devuelva la herramienta de síntesis :)

Sin embargo, para aprovechar las combinaciones más complejas de la funcionalidad DSP, a menudo se requiere una instanciación directa del bloque y la configuración de sus parámetros. Ejemplos de cosas que pueden no mapearse bien por inferencia (usando el Xilinx DSP48E1 como ejemplo):

  • Uso de presumador
  • Uso del acumulador de correos
  • Uso del detector de patrones
  • Uso de la unidad lógica

Y sobre todo combinaciones de las anteriores.

Las herramientas de síntesis aún no son lo suficientemente buenas para mapear combinaciones completamente arbitrarias de lógica y aritmética tan eficientemente como cabría esperar.

Si hay bloques DSP presentes, debe usarlos si puede porque será más eficiente que usar LUT para hacer lo mismo. A menos que no necesite una multiplicación de alto rendimiento, en cuyo caso debería implementar, por ejemplo, un sumador segmentado y un registro de desplazamiento para ahorrar espacio.

Sin embargo, buscaría inferir bloques DSP antes de ingresar a las herramientas GUI. El manual Xilinx XST tiene 'recetas' HDL sobre cómo crear instancias de bloques DSP con verilog/VHDL puro. Básicamente, si agrega suficientes registros antes y/o después de los multiplicadores, XST usará un bloque DSP para implementar la operación automáticamente. Puede verificar los registros de síntesis para ver si está infiriendo los bloques DSP correctamente. Supongo que Altera tiene algo similar.

Por cierto, estaba reflexionando sobre esto hace unos minutos, ya que actualmente estoy trabajando en una implementación de Mersenne Twister que solo usa un multiplicador para la semilla inicial. La implementación de mi primer paso no cumple con el tiempo, pero la funcionalidad es correcta. XST también puso la operación de multiplicación en bloques DSP, sin embargo, no está optimizado, por lo que funciona aproximadamente la mitad de rápido de lo que me gustaría. Probablemente volveré a implementar la multiplicación usando una técnica de cambiar y agregar que requerirá 32 veces la cantidad de ciclos de reloj, pero ya no requerirá un multiplicador de hardware.

¿Por qué debería fallar el tiempo cuando se usa el multiplicador de hardware?
Aparentemente, la multiplicación no canalizada de 32 bits por 32 bits requiere más de 8 ns.
hmm ya veo, no consideré eso. Por lo tanto, los bloques DSP no están canalizados. Me pregunto cómo implementaron exactamente la multiplicación. ¿Es realmente un multiplicador paralelo duro?
Creo que se puede configurar para que funcione de diferentes maneras. De acuerdo con el manual de XST, agregar suficientes registros en la entrada y la salida permitirá que XST use un multiplicador canalizado en un segmento DSP48. En mi caso, solo había un registro de salida y ningún registro de entrada, por lo que no pude aprovechar esto. Dado que esto era solo para la inicialización (sembrar el PRNG), reemplacé el multiplicador paralelo con un multiplicador serial de bits para ahorrar en la utilización de recursos.

Depende de cuánta optimización necesite y cuán portátil debe ser su diseño. Es un poco como el software, optimizando usando un poco de ensamblaje o dejando que el compilador elija las instrucciones. Es posible que también tenga algunas compensaciones de tamaño/velocidad para que no pueda permitirse un multiplicador combinatorio de doble precisión.

No sabía que había multiplicadores de FP cableados en FPGA.

Un operador de multiplicación compatible con IEEE P754 real adecuado para una CPU implica más que un gran multiplicador: debe agregar los exponentes, cambiar valores anormales, administrar infinitos y algunas banderas en su mayoría inútiles (inexactas, subdesbordamiento ...)

¡Los FPGA de última generación como la serie Altera 10 tienen multiplicadores de punto flotante compatibles con IEEE-754 en el propio hardware! Sin embargo, no he tenido la oportunidad de usarlos yo mismo.
Si hemos incorporado bloques DSP, entonces FPGA debería usarlos en lugar de un multiplicador combinatorio o usar algún otro algoritmo que, por ejemplo, use un bloque de memoria, ¿verdad?

Leí este documento http://www2.warwick.ac.uk/fac/sci/eng/staff/saf/papers/fpl2014-ronak.pdf :

Si bien las funciones que caben en un solo bloque DSP se pueden sintetizar de manera eficiente a partir del código RTL canalizado, hemos descubierto que las funciones más complejas que requieren múltiples bloques DSP tienen un rendimiento más bajo. Una descripción RTL estándar de una función matemática puede estar muy canalizada, por ejemplo, después de cada operación; sin embargo, dado que esta canalización puede no tener en cuenta la estructura y las etapas internas del bloque DSP, el diseño sintetizado resultante puede exhibir un rendimiento inferior al estándar ya que los bloques DSP están combinados de una manera que no les permite funcionar a toda velocidad.

Desearía poder encontrar la fuente de sus herramientas para verificar sus hallazgos.