我们有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.
这个问题并未完全涵盖对定点数的理解,因此将涵盖可能与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的号码reg或logic作为它们基本上是整数格式.但是,_当置于数字声明中时,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.
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个小数位.
| 归档时间: |
|
| 查看次数: |
10618 次 |
| 最近记录: |