在 vhdl 中将 sfixed 转换为 std_logic_vector 的正确方法是什么?

What's the right way to cast a sfixed to std_logic_vector in vhdl?

我正在尝试将 sfixed(从 ieee.fixed_pkg)转换为 std_logic_vector,我想知道正确的语法是什么以及为什么以下是(显然是错误的)。我尝试编译以下 3 种架构:

library ieee;
    use ieee.std_logic_1164.all;
    use ieee.fixed_pkg.all;

entity test is
    port (input: in sfixed(0 downto -7) := x"00";
    output: out std_logic_vector(7 downto 0) := x"00");
end;    

架构一:

architecture a of test is begin 
    output <= std_logic_vector(input);
end;

架构b:

architecture b of test is begin 
    proc: process (input) begin 
        output <= std_logic_vector(input);
    end process;
end;

架构 c:

architecture c of test is begin 
    proc: process (input) begin 
        if ('1' and '1') then
            output <= std_logic_vector(input);
        end if;
    end process;
end;

我使用的编译器是"ModelSim ALTERA vcom 10.3d Compiler 2014.10 Oct 7 2014"。 架构 a 和 b 不编译并出现错误消息:

Error: [...] Index value -7 (of type std.STANDARD.NATURAL) is out of range 0 to 2147483647.

但是体系结构 c 编译,同时仍然给我警告信息:

Warning: [...] Index value -7 (of type std.STANDARD.NATURAL) is out of range 0 to 2147483647.

所以我的问题是:什么是正确的投射方式,为什么上面发布的三种架构之间有任何区别?

有趣的是,这实际上可能是 VHDL 语言本身规范中的灰色区域。同样有问题的转换是 discussed as a possible "bug" against the open-source simulator, ghdl.

问题的本质是input被声明为sfixed(0 downto -7)std_logic_vector的定义要求其索引为natural,即正整数或0.

因此类型转换为无约束 std_logic_vector

output <= std_logic_vector(input);

继承源向量的边界(0 和 -7),但失败,因为一个边界超出范围。

但是有一个简单的解决方法:将类型转换为 constrained std_logic_vector ... 例如 std_logic_vector (input'length-1 downto 0) ... 通过使用'length 属性保证大小合适。此转换的语义保持索引有效,因此转换成功,将最左边的位传输到最左边的位,依此类推。

更详细一点,代码如下所示:

-- declarations
subtype result_type is std_logic_vector (input'length-1 downto 0);
signal output : result_type;

-- assignment
output <= result_type (arg);

我不能保证 Altera 会接受相同的解决方法,但我有理由相信它会接受,它显然是有效的 VHDL。我也没有尝试根据需要将 output 声明为端口。

据我们所知,根据 VHDL 语言参考手册 (LRM) 和 "bug"报告已相应关闭。

但是,已经从 VHDL 标准委员会寻求进一步的澄清 - 并且可能在未来放宽规则 - 如果 - 它可以证明完全可以防止困扰一些人的数组边界错误和缓冲区溢出其他语言。

@BrianDrmmond 讨论的对 std_logic_vector 具有负索引的 sfixed 类型转换导致的范围问题是在标准开发过程中发现的一个问题。对于 GHDL 以外的模拟器来说,这也是一个真正的问题。

因此,该包提供了类型转换函数来处理这个问题。要从 sfixed 或 ufixed 转换为 std_logic_vector 使用 to_slv 和 to_std_logic_vector:

  output <= to_slv(input);

要从 std_logic_vector 转换为 sfixed / ufixed 使用 to_sfixed/to_ufixed 的一种风格。有一个将索引作为参数,另一个将对象作为参数。

  signal a_sfixed : sfixed(0 downto -7) := x"00";
  signal a_slv    : std_logic_vector(7 downto 0) := x"00";

  a_sfixed <= to_sfixed(a_slv, 0, -7);
  . . . 
  a_sfixed <= to_sfixed(a_slv, a_sfixed);

是的,您可以使用类型转换(也称为强制转换)代替上述方法进行赋值,但是,如果您随后想在表达式中使用转换后的值,结果的范围将不正确,因为它由输入范围决定。

  signal a_sfixed : sfixed(0 downto -7) := x"00";
  signal a_slv    : std_logic_vector(7 downto 0) := x"00";
  signal y_sfixed : sfixed(1 downto -7) := x"00";

  y_sfixed <= a_sfixed + to_sfixed(a_slv, 0, -7);

固定包转换函数不是OP报告错误的解决方案,请参阅下面的函数转换为std_ulogic_vector的帖子。请注意 'result' 是一个 std_ulogic_vector 并且是通过执行操作数 'arg' 的类型转换获得的,与 OP 完全相同(除了 OP 使用 std_logic_vector)。固定点包将产生与 OP 报告的错误相同的错误。

  -- Conversion functions.  These are needed for synthesis where typically
  -- the only input and output type is a std_logic_vector.
  function to_sulv (
    arg : UNRESOLVED_ufixed)            -- fixed point vector
    return STD_ULOGIC_VECTOR is
    variable result : STD_ULOGIC_VECTOR (arg'length-1 downto 0);
  begin
    if arg'length < 1 then
      return NSLV;
    end if;
    result := STD_ULOGIC_VECTOR (arg);
    return result;
  end function to_sulv;

KJ

我发现这个 post 在 GHDL 0.35(mcode,windows)中使用 David Bishop 的 fixed_pkg_c(FPHDL,在 github)面临同样的错误。

注意,虽然这里的答案看起来是正确的;为了让 GHDL 编译和模拟,我必须在 fixed_pkg_c 中添加以下内容:

function to_sulv (
  arg : UNRESOLVED_sfixed)            -- fixed point vector
  return STD_ULOGIC_VECTOR is
  variable result : STD_ULOGIC_VECTOR (arg'length-1 downto 0);

  -- This was added
  subtype result_type is STD_ULOGIC_VECTOR (arg'length-1 downto 0);
  begin
  if arg'length < 1 then
    return NSLV;
  end if;
  --  originally: result := STD_ULOGIC_VECTOR (arg)
  result := result_type (arg);
  return result;
end function to_sulv;

需要对 ufixed 类型的 to_sulv 函数进行相同的更改。

不知道为什么之前的'type conversion'使用STD_ULOGIC_VECTOR没有效果,我也没有多想这个

如果其他人发现了这一点,请更新原始 fixed_pkg_c 文件在其原始实现中是否有效。