首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用VHDL实现方程

用VHDL实现方程
EN

Stack Overflow用户
提问于 2015-01-21 09:31:33
回答 3查看 4.3K关注 0票数 2

我试图在VHDL中实现这个方程,它有一些常数和加法的乘法。方程式如下,

代码语言:javascript
复制
  y<=-((x*x*x)*0.1666)+(2.5*(x*x))- (21.666*x) + 36.6653;   ----error

我得到了错误

代码语言:javascript
复制
     HDLCompiler:1731 - found '0' definitions of operator "*",  
     can not determine exact overloaded matching definition for "*".

实体是

代码语言:javascript
复制
    entity eq1 is
        Port ( x : in  signed(15 downto 0);
               y : out signed (15 downto 0) );
    end eq1;

我尝试使用函数调整整数的大小和x,但是它也会产生同样的错误。我应该使用另一种数据类型吗?X具有像2,4,6..etc这样的纯整数值。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-01-21 11:38:38

由于xy是数据类型signed,所以可以将它们相乘。然而,与实数并无相乘之处。即使存在,结果也是真实的(不是有符号或整数)。

因此,首先,您需要弄清楚您想要什么(语义)。然后应该添加类型转换和转换函数。

代码语言:javascript
复制
y <= x*x; -- OK
y <= 0.5 * x; -- not OK
y <= to_signed(integer(0.5 * real(to_integer(x))),y'length); -- OK
票数 3
EN

Stack Overflow用户

发布于 2015-01-21 21:51:50

这是另一种情况,在合成之前的模拟可能是方便的。实例的ghdl告诉您它发现了哪个"*“操作符的第一个错误:

ghdl -a implement.vhdl implement.vhdl:12:21:操作符"*“没有函数声明

代码语言:javascript
复制
 y <= -((x*x*x) * 0.1666) + (2.5 * (x*x)) - (21.666 * x) + 36.6653;
 ---------------^  character position 21, line 12

带有x乘以的表达式有两个操作数和一个类型的signed

(稍后,我们还注意到,信号分配操作右侧的复杂表达式最终将被解释为一个signed值,当分配给y时,该值具有一个狭窄的子类型约束)。

VHDL确定文本0.1666的类型,它是一个抽象文本,即十进制文本或浮点文本(IEEESTD1076-20085.2.5浮点类型,5.2.5.1通用,第5段):

浮点文字是匿名预定义类型的文字,在本标准中称为universal_real。其他浮点类型没有文字.但是,对于每种浮点类型,都存在一个隐式转换,将universal_real类型的值转换为浮点类型的相应值(如果有的话)(参见9.3.6)。

在VHDL中只有一种预定义的浮点类型,参见5.2.5.2,并且universal_real类型的浮点文字被隐式转换为REAL类型。

9.3.6类型转换第14段告诉我们:

在某些情况下,将执行隐式类型转换。将universal_integer类型的操作数隐式转换为另一整数类型,或将universal_real类型的操作数转换为另一浮点类型,只能在操作数是数字文字或属性,或者操作数是由物理类型的值除以相同类型的值组成的表达式时应用;这样的操作数称为可转换的通用操作数。可转换通用操作数的隐式转换是在最内部完整的上下文确定隐式转换的唯一(数值)目标类型的情况下应用的,而且如果没有此转换,则无法对此上下文进行合法解释。

因为您还没有包含一个包含另一个浮点类型的包,使得我们可以搜索一个"*"乘法运算符,其中一个是signed类型的操作数,另一个类型是REAL,返回类型为signed (或者另一个"*"运算符,与操作数类型参数相反),所以VHDL找到了其中的0。

没有

代码语言:javascript
复制
function "*" (l: signed; r: REAL) return REAL;

代码语言:javascript
复制
function "*" (l: signed; r: REAL) return signed;

在numeric_std包中找到。

菲利普建议通过将signed x转换为整数来克服这一问题。

从历史上看,合成并不包括类型REAL,在2008年版本的VHDL标准之前,您可能具有任意的精度,而5.2.5第7段现在告诉我们:

实现应为所有浮点类型选择表示,但符合IEEE 754-1985或IEEE 854-1987的universal_real除外;在任何一种情况下,这种选择的表示都需要64位的最小表示大小。

这对我们没有帮助,除非综合工具支持浮点类型的实和2008年兼容。

VHDL在2008年版本中引入了float_generic_pkg包,它执行综合符合条件的浮点操作,并通过转换它的浮点数类型与signed类型的使用兼容。

在我们建议将所有这些计算作为64位浮点数并进行综合之前,让我们再次注意,结果是一个16位signed,它是一个std_ulogic的数组类型,代表一个16位整数。

您可以将右侧的乘法建模为在浮点或符号表示中执行的不同表达式,以确定错误何时有意义。

由于y使用的是16位有符号值,因此显着性意味着震级上的差异大于1。这两种方法之间的翻转标志或意外的0,很可能会告诉您有一个精度问题。

我编写了一个小的C程序来研究这些差异,它告诉我们16位不足以保持这个数学:

代码语言:javascript
复制
int16_t x, y, Y;
int16_t a,b,c,d;
double A,B,C,D;

a = x*x*x * 0.1666;
A = x*x*x * 0.1666;

b = 2.5 * x*x;
B = 2.5 * x*x;

c = 21.666 * x;
C = 21.666 * x;

d =     36;  
D = 36.6653;  

y = -( a + b - c + d);
Y = (int16_t) -(A + B - C + D);

x最左边值的输出。

代码语言:javascript
复制
x = -32767, a =  11515, b =      0, c =  10967, y =   -584, Y =      0  
x = -32767, A = -178901765.158200, B = 2684190722.500000, C = -709929.822000
 x = -32767 , y =   -584 , Y=      0, double = -2505998923.829100 

输出的第一行是16位乘法,您可以看到所有三个乘法表达式都是不正确的。

第二行说double有足够的精度,但是Y (-(A + bit + D))不适合16位数。除非输入大小保持不变,否则无法通过使结果大小更大来解决这一问题。然后,链接操作就变成了挑选最佳产品和跟踪规模的问题,这意味着您最好使用浮点数。

当然,如果合适的话,你可以做夹紧。输出第三行的双值是非截断值。它比x'LOW更消极。

你也可以在16位的数学域做夹紧,尽管所有这些都告诉你,这个数学在硬件领域没有任何意义,除非它是用浮点数完成的。

因此,如果你试图在硬件上解决一个真正的数学问题,它将需要浮点,很可能是使用包float_generic_pkg完成的,而且不适合16位结果。

票数 3
EN

Stack Overflow用户

发布于 2015-01-21 09:49:36

正如在VHDL中找到运算符“+”的“0”定义中所述,VHDL编译器无法为您的操作找到匹配的操作符,例如,将x*x乘以。您可能希望使用numeric_std (参见这里),以便使signed (和unsigned)的运算符可用。

但是请注意,VHDL不是,而是一种硬件设计语言,而不是。也就是说,如果您的长期目标是将代码转移到FPGA或CPLD,这些功能可能不再工作了,因为它们是不可综合的。

我是这样说的,因为当你试图与例如0.1666相乘时,你会变成更多的问题,因为VHDL通常对方框中的浮点数一无所知。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28063705

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档