【问题标题】:VHDL equal operator: different behavior for std_logic and std_ulogicVHDL 相等运算符:std_logic 和 std_ulogic 的不同行为
【发布时间】:2013-07-23 23:48:35
【问题描述】:

我有两种设计:

library ieee;
use ieee.std_logic_1164.all;

entity eq_test1 is

  port (a,b : IN std_logic_vector (1 downto 0);
        o   : OUT std_logic); 
end eq_test1;

architecture strange_behavior of eq_test1 is
begin  
    P: process (a,b)
    begin
        if a = b then o <= '1';
        else o <= '0';
        end if;
    end process P;
end strange_behavior;

在 Modelsim 中强制 a 具有“00”而 b 具有“0L”表明 o 变为“0”。 所以L不被解释为0,“00”=“0L”是假的。好的。

但是当我采用相同的设计并添加时

use ieee.std_logic_unsigned.all;

到列表中,行为是不同的。 然后 "00" = "0L" 返回真,所以 L IS 与 0 相同(0 变为 '1')。 包括未签名的包,即使“0X”=“0Z”返回true。

谁能解释一下原因?

【问题讨论】:

  • L 为下拉,表示:通过电阻接地。如果你将它插入门,它将被中断为“0”(与verilog的“弱0”相同)。它需要无符号的原因是因为 VHDL 是强类型的,你需要一个特殊的函数来将 'L' 转换为 '0'
  • 您可以查看 std_logic_unsigned 包(通过 modelsim 轻松访问它 - 只需选择 ieee -> lib)并查看其中定义的哪些函数同意 '0' = 'L'
  • 好的,谢谢。我会。这可能有助于理解两个相等运算符之间的区别

标签: vhdl behavior modelsim


【解决方案1】:

添加use ieee.std_logic_unsigned.all;就像打开潘多拉的盒子 Synopsys 库。经过如下所示的深入研究,结论是 在这种情况下,std_logic_unsigned 包使值 '0' 和 'L' 相等 通过一张桌子。

当“=”运算符被重新定义为:

function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is
begin
    return   UNSIGNED(L) = UNSIGNED(R);
end;

然而这只是开始,因为 std_logic_unsigned 包括 use IEEE.std_logic_arith.all;,它定义了类型:

type UNSIGNED is array (NATURAL range <>) of STD_LOGIC;

“=”中UNSIGNED的比较从而导致调用std_logic_arith函数:

function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is
    -- synopsys subpgm_id 341
    constant length: INTEGER := max(L'length, R'length);
begin
    return bitwise_eql( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ),
            STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) );
end;

在这个函数中,CONV_UNSIGNED 很有趣:

function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED is
    constant msb: INTEGER := min(ARG'length, SIZE) - 1;
    subtype rtype is UNSIGNED (SIZE-1 downto 0);
    variable new_bounds: UNSIGNED (ARG'length-1 downto 0);
    variable result: rtype;
    -- synopsys built_in SYN_ZERO_EXTEND
    -- synopsys subpgm_id 372
begin
    -- synopsys synthesis_off
    new_bounds := MAKE_BINARY(ARG);
    if (new_bounds(0) = 'X') then
        result := rtype'(others => 'X');
        return result;
    end if;
    result := rtype'(others => '0');
    result(msb downto 0) := new_bounds(msb downto 0);
    return result;
    -- synopsys synthesis_on
end;

现在我们已经接近了,因为上面的调用:

function MAKE_BINARY(A : UNSIGNED) return UNSIGNED is
    -- synopsys built_in SYN_FEED_THRU
    variable one_bit : STD_ULOGIC;
    variable result : UNSIGNED (A'range);
begin
    -- synopsys synthesis_off
        for i in A'range loop
            if (IS_X(A(i))) then
                assert false
                report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)."
                severity warning;
                result := (others => 'X');
                return result;
            end if;
            result(i) := tbl_BINARY(A(i));
        end loop;
        return result;
    -- synopsys synthesis_on
end;

在这里我们有'L'等于'0'的原因,因为tbl_BINARY 是一个常量,定义为:

type tbl_type is array (STD_ULOGIC) of STD_ULOGIC;
constant tbl_BINARY : tbl_type :=
    ('X', 'X', '0', '1', 'X', 'X', '0', '1', 'X');

要理解这种映射,与 STD_ULOGIC 中的值:

std_ulogic: ( 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-');

tbl_BINARY: ( 'X', 'X', '0', '1', 'X', 'X', '0', '1', 'X');

这表明通过 tbl_BINARY 转换后则等效组 是 ('U', 'X', 'Z', 'W', '-'), ('0', 'L') 和 ('1', 'H')。

最后的评论是,即使通过 std_logic_unsigned 包驻留 在一个名为“ieee”的库中,该包不是像 VHDL 这样的 IEEE 标准,而是一个 新思软件包。该软件包和其他相关的 Synopsys 软件包具有 已经存在了一段时间并被广泛使用。

但是,您可以考虑改用 IEEE 标准包 numeric_std。

【讨论】:

  • 你认为 std_logic_unsigned 有什么不好的地方?
  • std_logic_unsigned 是非标准的,因此设计人员可能会在最坏的情况下在他们的模拟器中使用一个版本的 std_logic_unsigned 包,在他们的综合工具中使用另一个版本,最坏的情况是模拟行为不是硬件(综合)行为。如果测试依赖于模拟,最坏的结果可能是您签署了一个在模拟中工作但在现实世界硬件中不工作的 ASIC。具有标准的想法应该是明确定义行为以避免此类差异。
  • “邪恶”:IEEE Std 1076-2008, 9.2.1 关系运算符,第 3 段,第 2 句 - “当且仅当对于左操作数存在右操作数的匹配元素,反之亦然,并且匹配元素的值相等,由元素类型的预定义相等运算符给出。”在这种情况下,复合意味着 std_logic_vector。请参阅第 2 段,第 1 句“等式和不等式运算符(= 和 /=)是为文件类型和受保护类型以外的所有类型定义的。” bitwise_eql 违反了“as given by”。
  • 现在你可以明白为什么 -2008 添加了匹配相等运算符 (?=),它给出了与 std_logic_unsigned "=" 相同的答案。第 3 段第 2 句自 -1987 年以来一直在标准中。
  • 我认为这一切“std_logic_unsigned”都是邪恶的,这取决于你做什么。如果您只是使用“STD_LOGIC_VECTOR”作为位向量(仅包含“0”和“1”元素),并且您只想进行无符号算术(而不是在同一实体/架构中),那么 std_logic_unsigned 非常方便(因为您不需要像使用 numeric_std 那样在“UNSIGNED”/“SIGNED”/“STD_LOGIC_VECTOR”之间进行类型转换。)如果您当然以更复杂的方式使用 STD_LOGIC_VECTOR,那么您就有麻烦了。但是你无论如何都会遇到麻烦,因为不清楚合成会做什么......
【解决方案2】:

查看std_logic_unsigned的定义。它替换了“=”的原始定义如下

function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is
begin
    return   UNSIGNED(L) = UNSIGNED(R);
end;

并且由于类型 UNSIGNED 是一个整数类型,它不知道字面量 'h' 和 'l',因此它被解析为一个整数值,因此 'l' 变为 '0',语义等价于未签名

【讨论】:

  • UNSIGNED类型不是整数类型,而是位数组,而是在某些算术运算中使用时可以解释为无符号值的位数组。因此,UNSIGNED 中的位仍然可以具有值为 STD_LOGIC 的位,例如“L”、“X”和“Z”,并且没有长度限制,例如整数类型为 31 位。
【解决方案3】:

简短的回答是std_logic_unsigned 以及它的预期替换numeric_std_unsigned,正确地将“H”和“L”处理为“1”和“0”。

“无符号”包将 std_logic_unsigned 视为无符号数值。以下是一些好处:

  • 正确处理“H”和“L”
  • 输入的数字处理,尤其是当它们大小不同时
  • 支持将 std_logic_vector 与整数混合 (Addr = 0) 而不是 (Addr = "0000")
  • 重载 >、>=、

在供应商(综合)实现 VHDL-2008 匹配关系运算符 ?= ?/= ?&gt; ?&gt;= ?&lt;?&lt;= 之前,我建议您使用这些软件包之一。当他们实现匹配关系时,我建议在新设计中使用它们。

有关 VHDL-2008 功能的更多信息,请参阅http://www.synthworks.com/blog/vhdl-standards/

【讨论】:

  • "直到供应商(综合)",或使用 FUNCTION To_X01Z ( s : std_logic_vector ) RETURN std_logic_vector;在 std_logic_1164 中,称为“强度剥离器”。
猜你喜欢
  • 2017-08-12
  • 2015-10-18
  • 1970-01-01
  • 2017-05-18
  • 2011-06-25
  • 1970-01-01
  • 1970-01-01
  • 2010-09-09
相关资源
最近更新 更多