VHDL 克服最大整数限制
VHDL overcome maximum integer limit
我有一个通用值 X,它可以超过最大正整数限制 2147483647。我在实体声明的通用部分得到它:
X : integer := 3000000000;
Y : integer := 128; -- maximum 1024 (11 bits)
Z : integer := 1000 -- maximum 65535 (16 bits)
但是,在体系结构中并没有直接使用 X,而是使用了一个名为 C 的常量。我通过以下方式定义架构中的常量:
constant C : unsigned(63 downto 0) := to_unsigned ( (X / Y) / 1000 * Z, 64);
但是因为X可以超过整数限制,这个方案不可行。因此,我决定在实体声明中使用 unsigned(我正在使用 ieee.numeric_std 库),例如:
X : unsigned(63 downto 0) := x"00000000B2D05E00"; -- equivalent of 3000000000d
Y : integer := 128; -- maximum 1024 (11 bits)
Z : integer := 1000 -- maximum 65535 (16 bits)
然后,计算常量:
constant C : unsigned(63 downto 0) := ((X / to_unsigned(Y, 11)) / to_unsigned(1000,10) * to_unsigned(Z, 21));
我选择Z的长度为21,因为Y和1000d的总长度为21(10+11)。
但是,Vivado 给我一个错误“分配的 rhs 和 lhs 中的数组大小不匹配。”
我该如何克服这种情况?解决它的正确方法是什么?我的方法可能不正确,我对任何方法都持开放态度。
谢谢。
Vivado 是正确的 - 尺寸不匹配。
"/"
函数的结果 returns 左操作数的长度。所以在这里,你有
(X / to_unsigned(Y, 11)
其中 returns 64 位结果
/ to_unsigned(1000,10)
returns 另一个 64 位结果。最后:
* to_unsigned(Z, 21));
是一个64位的值*21位,给出一个85位的数。
您需要使用调整大小函数将结果调整为 64 位:
resize(result, X'length);
除断言警告外,此函数不检查溢出,您需要确保永远不会溢出 64 位数字。
鉴于您为 Z 指定的值范围并假设 Y=1 的最小值,我认为您将不得不使用 real
然后将其分解为整数大小的块,因为 to_unsigned()
需要一个整数。如果您的值适合 64 位,这实际上使用 mod
运算符非常容易。
constant x : real := 300000000.0; -- no constraints provided
constant y : real := 1.0; -- assumed minimum
constant z : real := 65535.0; -- stated maximum
constant c_real : real := x/y/1000.0*z; -- 19660500000.0
constant lower32 : unsigned(31 downto 0) := to_unsigned(integer(c_real mod 2.0**31), 32);
constant upper32 : unsigned(31 downto 0) := to_unsigned(integer(c_real / 2**31), 32);
signal counter : unsigned(63 downto 0) := shift_left(resize(upper32, 64), 31) + lower32;
我有一个通用值 X,它可以超过最大正整数限制 2147483647。我在实体声明的通用部分得到它:
X : integer := 3000000000;
Y : integer := 128; -- maximum 1024 (11 bits)
Z : integer := 1000 -- maximum 65535 (16 bits)
但是,在体系结构中并没有直接使用 X,而是使用了一个名为 C 的常量。我通过以下方式定义架构中的常量:
constant C : unsigned(63 downto 0) := to_unsigned ( (X / Y) / 1000 * Z, 64);
但是因为X可以超过整数限制,这个方案不可行。因此,我决定在实体声明中使用 unsigned(我正在使用 ieee.numeric_std 库),例如:
X : unsigned(63 downto 0) := x"00000000B2D05E00"; -- equivalent of 3000000000d
Y : integer := 128; -- maximum 1024 (11 bits)
Z : integer := 1000 -- maximum 65535 (16 bits)
然后,计算常量:
constant C : unsigned(63 downto 0) := ((X / to_unsigned(Y, 11)) / to_unsigned(1000,10) * to_unsigned(Z, 21));
我选择Z的长度为21,因为Y和1000d的总长度为21(10+11)。
但是,Vivado 给我一个错误“分配的 rhs 和 lhs 中的数组大小不匹配。”
我该如何克服这种情况?解决它的正确方法是什么?我的方法可能不正确,我对任何方法都持开放态度。
谢谢。
Vivado 是正确的 - 尺寸不匹配。
"/"
函数的结果 returns 左操作数的长度。所以在这里,你有
(X / to_unsigned(Y, 11)
其中 returns 64 位结果
/ to_unsigned(1000,10)
returns 另一个 64 位结果。最后:
* to_unsigned(Z, 21));
是一个64位的值*21位,给出一个85位的数。 您需要使用调整大小函数将结果调整为 64 位:
resize(result, X'length);
除断言警告外,此函数不检查溢出,您需要确保永远不会溢出 64 位数字。
鉴于您为 Z 指定的值范围并假设 Y=1 的最小值,我认为您将不得不使用 real
然后将其分解为整数大小的块,因为 to_unsigned()
需要一个整数。如果您的值适合 64 位,这实际上使用 mod
运算符非常容易。
constant x : real := 300000000.0; -- no constraints provided
constant y : real := 1.0; -- assumed minimum
constant z : real := 65535.0; -- stated maximum
constant c_real : real := x/y/1000.0*z; -- 19660500000.0
constant lower32 : unsigned(31 downto 0) := to_unsigned(integer(c_real mod 2.0**31), 32);
constant upper32 : unsigned(31 downto 0) := to_unsigned(integer(c_real / 2**31), 32);
signal counter : unsigned(63 downto 0) := shift_left(resize(upper32, 64), 31) + lower32;