Verilog - 浮点乘法
Verilog - Floating points multiplication
Verilog 有问题。
我们必须使用两个浮点数(二进制)的乘法,但它不能 100% 完美地工作。
我们有一个请求 m[31:0]。第一个数字(逗号之前)是 m[31:16] 和逗号之后的数字 m[15:0] 所以我们有:
米[31:16] = 1000000000000000;
m[15:0] = 1000000000000000;
米[31:0] = 10000000000000000(.)1000000000000000;
问题是:我们想将数字与小数位相乘,但我们不知道如何做。
例如:二进制的 m = 2.5。 m*m的结果是6.25.
这个问题没有完全涵盖对定点数的理解,因此将涵盖一些可能与 OP 无关的背景知识。
无符号二进制(以 2 为底)数的十进制加权,示例中的 4 位遵循此规则:
2^3 2^2 2^1 2^0 (Base 2)
8 4 2 1
仅供参考,权力保持不变,base 发生了变化。对于 4 个十六进制,它将是:
16^3 16^2 16^1 16^0
4096 256 16 1
回到基数 2,对于二进制补码有符号数,MSB(最高有效位)变为负数。
-2^3 2^2 2^1 2^0 (Base 2, Twos complement)
-8 4 2 1
当我们插入二进制小数点或小数位时,模式会继续。 4 个整数位 4 个小数位。
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
不幸的是,Verilog 没有定点格式,因此用户必须跟踪二进制小数点并使用缩放数字。小数点 .
不能用于存储为 reg
或 logic
的 verilog 数字,因为它们本质上是整数格式。然而,verilog 在数字声明中确实会忽略 _
,因此它可以用作数字中的二进制小数点。它的使用只是象征性的,对语言没有任何意义。
在上述格式中,2.5 将由 8'b0010_1000
表示,该问题有 16 个小数位,因此您需要在 _
之后放置 16 个位,以将二进制小数点保持在正确的位置。
定点乘法位宽
如果我们有两个数字A和B结果的宽度A*B 将是:
Integer bits = A.integer_bits + B.integer_bits.
Fractional bits = A.fractional_bits + B.fractional_bits.
因此 [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
EDA Playground 上的示例。
由此您应该能够更改深度以适应任何类型的定点数。并转换回 16 Int 16 小数可以通过部分选择正确的位来完成。如果您需要饱和而不是溢出,请小心。
有一个相关的 Q&A 有 22 个小数位。
Verilog 有问题。 我们必须使用两个浮点数(二进制)的乘法,但它不能 100% 完美地工作。
我们有一个请求 m[31:0]。第一个数字(逗号之前)是 m[31:16] 和逗号之后的数字 m[15:0] 所以我们有:
米[31:16] = 1000000000000000; m[15:0] = 1000000000000000;
米[31:0] = 10000000000000000(.)1000000000000000;
问题是:我们想将数字与小数位相乘,但我们不知道如何做。 例如:二进制的 m = 2.5。 m*m的结果是6.25.
这个问题没有完全涵盖对定点数的理解,因此将涵盖一些可能与 OP 无关的背景知识。
无符号二进制(以 2 为底)数的十进制加权,示例中的 4 位遵循此规则:
2^3 2^2 2^1 2^0 (Base 2)
8 4 2 1
仅供参考,权力保持不变,base 发生了变化。对于 4 个十六进制,它将是:
16^3 16^2 16^1 16^0
4096 256 16 1
回到基数 2,对于二进制补码有符号数,MSB(最高有效位)变为负数。
-2^3 2^2 2^1 2^0 (Base 2, Twos complement)
-8 4 2 1
当我们插入二进制小数点或小数位时,模式会继续。 4 个整数位 4 个小数位。
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
不幸的是,Verilog 没有定点格式,因此用户必须跟踪二进制小数点并使用缩放数字。小数点 .
不能用于存储为 reg
或 logic
的 verilog 数字,因为它们本质上是整数格式。然而,verilog 在数字声明中确实会忽略 _
,因此它可以用作数字中的二进制小数点。它的使用只是象征性的,对语言没有任何意义。
在上述格式中,2.5 将由 8'b0010_1000
表示,该问题有 16 个小数位,因此您需要在 _
之后放置 16 个位,以将二进制小数点保持在正确的位置。
定点乘法位宽
如果我们有两个数字A和B结果的宽度A*B 将是:
Integer bits = A.integer_bits + B.integer_bits.
Fractional bits = A.fractional_bits + B.fractional_bits.
因此 [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
EDA Playground 上的示例。
由此您应该能够更改深度以适应任何类型的定点数。并转换回 16 Int 16 小数可以通过部分选择正确的位来完成。如果您需要饱和而不是溢出,请小心。
有一个相关的 Q&A 有 22 个小数位。