Verilog-Multiplicación de puntos flotantes
(1)
La pregunta no cubre completamente lo que se entiende sobre números de punto fijo, por lo tanto, cubrirá un poco de información que podría no ser relevante para el OP.
La ponderación decimal de números binarios sin signo (base 2), 4 bits para el ejemplo sigue esta regla:
2^3 2^2 2^1 2^0 (Base 2)
8 4 2 1
Solo como referencia, los poderes permanecen igual y la base cambia. Para 4 hexes sería:
16^3 16^2 16^1 16^0
4096 256 16 1
Volviendo a la base 2, para dos números con signo de complemento, el MSB (bit más significativo) se vuelve negativo.
-2^3 2^2 2^1 2^0 (Base 2, Twos complement)
-8 4 2 1
Cuando insertamos un punto binario o un bit fraccional, el patrón continúa. 4 bits enteros 4 bits fraccionarios.
Base 2: Twos complement 4 integer, 4 bit frational
-2^3 2^2 2^1 2^0 . 2^-1 2^-2 2^-3 2^-4
-8 4 2 1 . 0.5 0.25 0.125 0.0625
Lamentablemente, Verilog no tiene un formato de punto fijo, por lo que el usuario debe realizar un seguimiento del punto binario y trabajar con números escalados.
Puntos decimales
.
no se puede usar en números verilog almacenados como
reg
o
logic
ya que son esencialmente formatos enteros.
Sin embargo, verilog ignora
_
cuando se coloca en declaraciones de números, por lo que puede usarse como punto binario en números.
Su uso es solo simbólico y no tiene significado para el lenguaje.
En el formato anterior, 2.5 estaría representado por
8''b0010_1000
, la pregunta tiene 16 bits fraccionarios, por lo tanto, debe colocar 16 bits después de
_
para mantener el punto binario en el lugar correcto.
Ancho de bits de multiplicación de punto fijo
Si tenemos dos números A y B, el ancho del resultado A * B será:
Integer bits = A.integer_bits + B.integer_bits.
Fractional bits = A.fractional_bits + B.fractional_bits.
Por lo tanto [4 Int, 4 Frac] * [4 Int, 4 Frac] => [8 Int, 8 Frac]
reg [7:0] a = 0010_1000;
reg [7:0] b = 0010_1000;
reg [15:0] sum;
always @* begin
sum = a * b ;
$displayb(sum); //Binary
$display(sum); //Decimal
end
// sum == 00000110_01000000; //Decimal->6.25
Ejemplo en EDA Playground .
A partir de esto, debería poder cambiar las profundidades para adaptarse a cualquier tipo de número de punto fijo. y volver a un número fraccional 16 Int 16 puede hacerse seleccionando parcialmente los bits correctos. Tenga cuidado si necesita saturar en lugar de desbordar.
Hay un Q&A relacionado que tiene 22 bits fraccionarios.
Tenemos un problema con Verilog. Tenemos que usar la multiplicación con dos puntos flotantes (binario), pero no funciona al 100% perfectamente.
Tenemos un Req m [31: 0]. Los primeros números (antes de la coma) son m [31:16] y los números después de la coma m [15: 0] así que tenemos como:
m [31:16] = 1000000000000000; m [15: 0] = 1000000000000000;
m [31: 0] = 10000000000000000 (.) 1000000000000000;
El problema es: queremos multiplicar números con decimales, pero no sabemos cómo. Por ejemplo: m = 2.5 en binario. El resultado de m * m es 6.25.