2012-12-03 47 views
1

我想乘以一个U0.8格式常量的U4.10格式定点数并截断我的结果到U4.10。我想,我想是这样的:VHDL语法删除乘法余数

signal A, B : unsigned(13 downto 0); 
signal MULT : unsigned(7 downto 0); 

...

B <= (A * MULT)(21 downto 8); 

但是,这并不编译。两个问题:

  1. 什么是我正在尝试做的正确语法?
  2. 如果我改变我的变量类型中的位数,是否有一种很好的方式来使用某些符号属性或某些方法来使代码更易于维护?
+0

有你看在固定点库? http://www.eda-stds.org/fphdl/ –

+0

我没有 - 谢谢你的链接。 – blueshift

回答

2

使用正确宽度的中间信号。这是丑陋但可靠和易于维护。

如果你不止一次这样做,在一个函数中隐藏丑陋;如果您有多个功能或在多个地方使用它们,请将它们放在一个包中。

例如;

package DSP is 
    subtype Data is unsigned(13 downto 0); 
    subtype Coeff is unsigned(7 downto 0); 

    function Mul_Coeff (A:Data, M:Coeff) return Data; 
end package DSP; 

package body DSP is 
    function Mul_Coeff (A:Data, M:Coeff) return Data is 
     variable Temp : unsigned (Coeff'Length + Data'High downto 0) := A * M; 
    begin 
     return Temp (Temp'High downto Coeff'Length); 
    end Mul_Coeff; 
end package body DSP; 

...

B <= Mul_Coeff(A, Mult); 

正如你所看到的,这也采用了类型系统来保护你从有关数据字宽的决策的变化。

后来,当你意识到四舍五入给出比截断误差下,你只需要修改这些功能...

1

IMO这个要求的属性:

procedure mul_fixed (
    signal a : in unsigned_fixed; 
    signal b : in unsigned_fixed; 
    signal c : out unsigned_fixed 
    ) is 
constant a_temp : unsigned(a'length - 1 downto 0) := to_unsigned(a); 
constant b_temp : unsigned(b'length - 1 downto 0) := to_unsigned(b); 
variable result : unsigned(a'length + b'length - 1 downto 0); 
-- notice this might be negative if a, b are (? downto +n), which is correct 
constant num_fractional : integer := 0 - a'right - b'right; 
-- c integral might be bigger than integral/fractional part, make sure we only access valid indices in result 
constant result_left : integer := min(result'length - 1, num_fractional + c'left); 
constant result_right : integer := max(0    , num_fractional + c'right); 
begin 

    result := a_temp * b_temp; 
    c <= (others => '0'); -- make sure all bits are defined 
    c(result_left - num_fractional downto result_right - num_fractional) <= result(result_left downto result_right); 

end procedure mul_fixed; 

type unsigned_fixed is array(range <>) of std_logic; 

和无符号转换函数存在。

所以你会

... 
signal a : unsigned_fixed(3 downto -10); -- 4Q10 
signal b : unsigned_fixed(-1 downto -8); -- 0Q8 
signal c : unsigned_fixed(3 downto -10); -- 4Q10 

mul_fixed(a, b, c); 

我知道,所有这些属性看起来很吓人的在第一,但我经常发现自己写痴痴很多包,只是因为我有不同的数据类型: -/ IMO一个应该花时间思考关于这一次,找出一个通用的解决方案并继续前进 - 毕竟这就是VHDL的属性。

  • 请注意,我没有进入到测试环境,而写这,所以有可能会或可能不会需要到c分配结果的时候要一个类型转换。

此外,如果可以的话,您至少应该看看定点库。或者使用VHDL-2008和定点软件包。

+0

定点包不限于VHDL 2008是吗? –

+0

你提到的那个被整合到VHDL-2008中,但是有重大的变化。它应该在VHDL-1993中使用上述软件包,或使用VHDL-2008和内置软件包,具体取决于供应商。 – FRob

2

如果我的评论上述由未来的读者被忽视:

有做这类活动的标准方法 - 使用定点库从这里:

http://eda-stds.org/fphdl