【问题标题】:VHDL syntax to drop multiplication remainder删除乘法余数的 VHDL 语法
【发布时间】:2012-11-21 01:03:20
【问题描述】:

我想将 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. 如果我更改变量类型中的位数,是否有一种很好的方法可以使用一些符号属性或类似属性使代码更易于维护?

【问题讨论】:

标签: vhdl slice arithmetic-expressions


【解决方案1】:

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

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

例如;

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

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

后来当你意识到舍入比截断产生的误差更低时,你只需要修改这些函数......

【讨论】:

    【解决方案2】:

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

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

    http://eda-stds.org/fphdl

    【讨论】:

      【解决方案3】:

      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 和定点包。

      【讨论】:

      • 你提到的那个被并入了VHDL-2008,但是有很大的变化。它应该在 VHDL-1993 中使用上述软件包,或使用 VHDL-2008 和内置软件包,具体取决于供应商。
      猜你喜欢
      • 2016-06-19
      • 2012-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多