Verilog - 浮点乘法

Aeo*_*nus 3 verilog

我们有Verilog的问题.我们必须使用两个浮点(二进制)的乘法,但它不能100%完美地工作.

我们有一个Req m [31:0].第一个数字(在逗号之前)是m [31:16]和逗号之后的数字[15:0]所以我们喜欢:

m [31:16] = 1000000000000000; m [15:0] = 1000000000000000;

m [31:0] = 10000000000000000(.)1000000000000000;

问题是:我们想要将数字乘以小数位,但我们不知道如何.例如:m = 2.5二进制.m*m的结果是6.25.

Mor*_*gan 7

这个问题并未完全涵盖对定点数的理解,因此将涵盖可能与OP无关的一些背景.

无符号二进制(基数2)数的十进制加权,例子为4位,遵循以下规则:

2^3  2^2  2^1  2^0 (Base 2)
  8    4    2    1
Run Code Online (Sandbox Code Playgroud)

仅供参考,权力保持不变,基数也会改变.对于4 hex,它将是:

16^3  16^2  16^1  16^0
4096   256    16     1
Run Code Online (Sandbox Code Playgroud)

返回基数2,对于二进制补码有符号数,MSB(最高有效位)变为负数.

-2^3  2^2  2^1  2^0 (Base 2, Twos complement)
  -8    4    2    1
Run Code Online (Sandbox Code Playgroud)

当我们插入二进制点或小数位时,模式继续.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
Run Code Online (Sandbox Code Playgroud)

不幸的是,Verilog没有定点格式,因此用户必须跟踪二进制点并使用缩放数字.小数点.不能用于在存储为Verilog的号码reglogic作为它们基本上是整数格式.但是,_当置于数字声明中时,verilog会忽略,因此它可以用作数字中的二进制点.它的使用只是象征性的,对语言没有意义.

在上面的格式中,2.5表示为8'b0010_1000,问题有16个小数位,因此你需要在16位之后放置_二进制点以保持正确的位置.

定点乘法位宽

如果我们有两个数字AB,结果A*B的宽度将是:

Integer bits    = A.integer_bits    + B.integer_bits.
Fractional bits = A.fractional_bits + B.fractional_bits.
Run Code Online (Sandbox Code Playgroud)

因此[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
Run Code Online (Sandbox Code Playgroud)

EDA游乐场的示例.

从这里你应该能够改变深度以适应任何类型的定点数.并且可以通过部分选择正确的位来回转到16 Int 16小数.如果你需要饱和而不是溢出,要小心.

有一个相关的Q&A有22个小数位.