Vhdl 在alteraquartus Prime中编译fphdl

Vhdl 在alteraquartus Prime中编译fphdl,vhdl,point,floating,quartus,Vhdl,Point,Floating,Quartus,我试图编译使用fphdl库进行浮点操作的设计。而在modelsim中,当在Quartus中合成时,hdl编译器会抱怨以下语句: result := to_integer (fract (frac'high downto frac'high-base)) 理由是:“表达式不是常数” 通过查看类似的帖子,我了解到这个编译器不喜欢frac'high-base不受约束。我尝试约束所有相关信号,如下所示: variable frac : UNSIGNED (23 downto 0); vari

我试图编译使用fphdl库进行浮点操作的设计。而在modelsim中,当在Quartus中合成时,hdl编译器会抱怨以下语句:

result := to_integer (fract (frac'high downto frac'high-base))
理由是:“表达式不是常数” 通过查看类似的帖子,我了解到这个编译器不喜欢
frac'high-base
不受约束。我尝试约束所有相关信号,如下所示:

variable frac    : UNSIGNED (23 downto 0);  
variable base    : INTEGER range 0 to 23;
但错误仍在继续。。。
hdl级别或Quartus本身是否有任何解决方法?

请注意,错误消息显示:

表达式不是常数

而不是:

受限

因此,出现错误消息的原因是当
fract
的范围在运行时是可变的,而在精化时不是固定的时,无法合成
to_integer
函数

Quartus的解决方案可以是:

variable part : UNSIGNED(23 downto 0);
...
part := (others => '0');
part(base downto 0) := frac(frac'high downto frac'high - base);
result := to_integer(part);

然后从
frac
中提取的部分被零扩展,然后给
到_integer
的向量长度被固定,从而允许Quartus合成。

问题中的代码片段似乎与fphdl包没有任何直接关系。它不依赖于它们中声明的任何类型

表达式给出了一个来自
frac
的整数
结果,精度为
frac'HIGH-base
'bits'

原始表达式的等价物可以是:

    variable dist:  integer range 0 to 23;

    dist := frac'HIGH - base;
    result := to_integer (SHIFT_RIGHT(frac, dist));
SHIFT_RIGHT来自IEEE库包numeric_std,因为
frac
是无符号的

精明的观察家可能会注意到,这相当于一个整数除以二的幂,通常由综合支持,提供或多或少相同的硬件

在这里,你可能会想到,你的语句是一个多路复用器,输入移位,零填充,整个过程需要优化

历史上IEEE标准1076.6-2004(撤销)8.6.5提供的切片名称-

对于作为切片名称一部分出现的离散范围,离散范围的边界应直接或间接指定为属于整数类型的静态值

Morten告诉我们Quartus Prime可以处理

    part := (others => '0');
    part(base downto 0) := frac(frac'high downto frac'high - base);
    result := to_integer(part);
其中
base
不是静态的(尽管您认为它应该受到约束)

对于那些不能处理非静态离散范围的合成工具,同样的事情也可以在For循环中完成,具体取决于循环参数,该参数在展开循环中是常量:

IEEE Std 1076=2008 10.10循环语句告诉我们:

对于具有For迭代方案的循环语句,循环参数规范是具有给定标识符的循环参数的声明。循环参数是一个对象,其类型是离散范围的基本类型。在语句序列中,循环参数是一个常量


for循环给出相同的结果,并且应该产生相同的硬件。

这似乎可行。我尝试过做类似的事情,但可能我没有正确声明临时部分变量,错误转移到该语句……但是您的代码通过了合成。谢谢
    part := (others => '0');
    for i in part'range loop
        if i = b then
            part(i downto 0) := frac(frac'high downto frac'high - i);
        end if;
    end loop;
    result := to_integer(part);