Qm.n multiplicación en VHDL

3

Me estoy enfocando en el proceso de multiplicar dos números Qm.n y generar una respuesta del mismo ancho.

Como ejemplo, pretenderé que tengo un número Q2.5 de 8 bits. Entiendo que este formato puede representar un número en el rango de -4 a 3.96875.

Comprendo que al multiplicar dos SLV de 8 bits se obtiene un SLV de 16 bits, simplemente no estoy seguro de qué significa cada bit en este resultado de 16 bits.

Aquí está mi algoritmo:

  1. multiplique los dos SLV de 8 bits, para obtener un resultado de 16 bits
  2. desplazar el resultado dejado por el número de bits fraccionarios, 5 en este caso
  3. asigne los 8 bits más bajos como resultado

¿Hay algo más que esto? ¿Por qué el número de bits enteros no entra en él? Aquí hay una función que he escrito para intentar hacer esto:

function qmult(a : signed; b : signed; n : integer)
return signed is
    variable tmp0 : signed(a'length * 2 - 1 downto 0);
    variable tmp1 : signed(a'length * 2 - 1 downto 0);
    variable ret_val : signed(a'length - 1 downto 0);

begin
    tmp0 := a * b;
    tmp1 := tmp0 srl n;
    ret_val := tmp1(a'length - 1 downto 0);
    return ret_val;
end qmult;

Dos preguntas principales para concluir:

  1. ¿Por qué no hay tal función en numeric_std si es así de simple?

  2. A mi entender, si no está seguro del formato Q de dos números, es imposible obtener un resultado de multiplicación adecuado (no conoce los bits fraccionarios, por lo que el paso [2] de los anteriores) el algoritmo no funciona) o hay un agujero en mi entendimiento?

pregunta benjwy

3 respuestas

0

Una de las razones por las que una función de este tipo no pertenece a numeric_std es que, en la práctica, es posible que necesite un mayor control de los detalles ...

La adición es bastante sencilla y la mayoría de las herramientas y tecnologías lo implementan bien.

Pero la multiplicación es lo suficientemente difícil como para que los fabricantes de FPGA dediquen partes del área de FPGA a proporcionar multiplicadores con signo de 18 bits con lógica asociada. Las herramientas de síntesis usarán estos, pero tal vez no de manera óptima. Si necesita una multiplicación de 32 bits, puede obtener una multiplicación mal canalizada (¡lenta!) Que puede mejorar al dividir la multiplicación en 4 y sumar productos parciales. (Las herramientas de sintetizador están mejorando, por lo que puede que esto ya no sea cierto).

O puede que necesite redondear, o vacilar, en lugar de truncar el producto.

O una entrada es una constante, de modo que KCM (multiplicadores de coeficientes constantes) desenrollados en el hardware produce una solución más eficiente.

Por lo tanto, la multiplicación no es una operación de talla única, y ciertamente no lo fue cuando se creó numeric_std. Como dice Martin Thompson, mire lo que es posible ahora en la biblioteca de puntos fijos más reciente.

En cuanto a la realización de su propia escala de punto fijo y truncamiento; Me resulta más fácil razonar empezando en el MSB y trabajando hacia abajo ...

Teniendo en cuenta sus números de formato Q2.5 de 8 bits (¡firmados!),

s_mm.nnnnn * s_mm.nnnnn = ss_mmmm.nn_nnnn_nnnn

solo recuerda que multiplicar los bits de signo efectivamente te da 2 bits de signo EXCEPTO para el caso -4.0 * -4.0 (más generalmente, ambas entradas -2 ** m). Si puede garantizar que esto no suceda (por ejemplo, si controla los coeficientes del filtro), puede simplificar el manejo de este caso ...

    
respondido por el Brian Drummond
2

1) Posiblemente porque, como usted dice, es bastante fácil implementarse;

2) Correcto, debes saber dónde está el "punto binario".

Encuentro que el concepto del punto binario (como punto decimal, pero para binario) es muy útil cuando se trata de un punto fijo.

     aaa.aaaaa
x    bbb.bbbbb
= nnnnnn.nnnnnnnnnn

La otra forma de verlo es que todo se multiplica implícitamente por (1 < < número de bits fraccionarios):

A*(1<<5) * B*(1<<5) = (A*B) * (1<<10)
    
respondido por el pjc50
0

fixed_pkg tiene todas las cosas que necesita: enlace

Las reglas de tamaño para las operaciones en fixed_pkg se encuentran detalladamente en la guía del usuario disponible en el sitio web anterior, pero el paquete contiene una función conveniente que le permite cambiar el tamaño sin afectar la escala de la señal y también maneja el truncamiento. y saturación según su configuración:

architecture RTL of mult is
    signal a, b : sfixed(2 downto -5);
    signal y : sfixed(2 downto - 5);
begin

y <= resize( a * b, y);
end;
    
respondido por el trondd

Lea otras preguntas en las etiquetas