首页 > 解决方案 > 当我为函数提供它所期望的子类型参数的父级时会发生什么?

问题描述

在试图从 numeric_std 包中找出 shift_right 函数的细节时,我注意到 count 参数属于 NATURAL 子类型:

function shift_right(ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is
begin
  if (ARG'length<1) then return NAU; end if;
  return UNSIGNED(XSRL(STD_LOGIC_VECTOR(ARG),COUNT));
  end;

但是,在调用该函数时,我还可以提供一个 INTEGER,与 NATURAL 相比,它可以容纳一个负数。

调用成功编译的代码示例:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity ExampleCode is
    port 
    (
        clk    : in std_logic;
        input  : in signed(15 downto 0);
        shift  : in signed(3 downto 0);
        output : out signed(15 downto 0)
    );
end entity;

architecture rtl of ExampleCode is

begin

    ProcessExample : process(clk)
    begin
        if (rising_edge(clk)) then
            output <= shift_right(input, to_integer(shift));
        end if;
    end process;

 end rtl;

numeric_std 包显示,如果您使用带有带符号参数的 to_integer,它将返回一个整数:

  function TO_INTEGER ( ARG: SIGNED) return INTEGER;

我的问题是;

标签: vhdl

解决方案


另一个答案非常详细,但我认为当您的具体问题可以更简洁地回答时,这有点像兔子洞。我从您可能使用的真实工具中实际发生的情况的角度回答了问题,而不是试图重新解释语言标准。

a 的一个重要特征是与父类型subtype之间存在自动“转换” + 。下面的示例通过枚举类型清楚地显示了这一点。将父类型参数传递给期望子类型的函数时,将调用相同的自动转换。

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity e is
end;

architecture a of e is

  type r is (A, B, C, D);
  subtype rs is r range A to C;

  signal x1 : r := B;
  signal x2 : r := D;
  signal xs : rs;

begin

  process
  begin
    xs <= x1; -- Fine.
    wait for 1 ns;
    xs <= x2; -- Run-time error, "Value 3 is out of range 0 to 2".
    wait;
  end process;

end;

VHDL 是否总是允许将子类型的父级作为函数的参数提供?

从上面看,是的,确实如此,但是在许多工具中,如果自动类型转换不能成功,你会得到一个错误,因为在示例中的第二个赋值中显然不能成功。请注意,如果x2constant,则工具可能会确定无法进行转换,然后引发编译时错误。

这同样适用于naturaland integer; 因为natural被定义为subtype natural is integer range 0 to integer'highnatural在某种意义上一个integer,所以只要整数不在自然范围之外,自动“转换”就简单而合理。

当它确实允许父类型时,它如何解决子类型的强加约束?

无论是否标准化,特定工具都可能以多种方式实现这一点,因此您可能会看到使用不同工具的超出范围的父类型值的不同行为。

例如,当我尝试使用 ModelSim 时,它的转换似乎integer只是natural简单地复制了该值,这意味着如果移位量整数不是常数(至少对于 10.7e 版本)shift_right,该工具中的负值将令人惊讶地工作)。

显然,依赖特定行为是不明智的,但不管行为如何,使用子类型可以为您提供比仅在整个设计中使用基类型更多的保护。


+这不是 VHDL 中的真正转换,但如果您使用过几乎任何其他语言,这就是您倾向于引用它的方式。


推荐阅读