1

我想将 U4.10 格式的定点数乘以 U0.8 格式的常数,并将结果截断为 U4.10。我想我想要的是这样的:

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

...

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

但这不会编译。两个问题:

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

3 回答 3

3

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

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

例如;

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);

如您所见,这还使用类型系统来保护您免受有关数据字宽的决策的更改。

稍后当您意识到舍入比截断给出的错误更低时,您只需修改这些函数......

于 2012-12-03T16:52:11.860 回答
2

如果我上面的评论没有被未来的读者注意到:

有一种标准方法可以执行此类活动 - 使用此处的定点库:

http://eda-stds.org/fphdl

于 2012-12-04T10:14:32.073 回答
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。

于 2012-12-03T22:34:50.063 回答