Vhdl 当比较std_逻辑与“X”时,如何获得模拟警告?

Vhdl 当比较std_逻辑与“X”时,如何获得模拟警告?,vhdl,Vhdl,为了在模拟中捕获更多的bug,获得警告是一种优势 如果在=比较中使用带“X”的std_逻辑 当使用ieee.std_logic_1164包时,std_logic compare功能 =不警告任何操作数中的“X”。因此,“如果”分支在 当sl_i为“1”时,采用下面的代码,但采用else分支 当sl_i为“0”、“X”等之一时: ??这样的重新定义是否符合VHDL标准,是否可行 一般来说,使用这些工具 正如Jim Lewis在提到 使用时,重写implicit=通常不适用于工具 VHDL-2003

为了在模拟中捕获更多的bug,获得警告是一种优势 如果在=比较中使用带“X”的std_逻辑

当使用ieee.std_logic_1164包时,std_logic compare功能 =不警告任何操作数中的“X”。因此,“如果”分支在 当sl_i为“1”时,采用下面的代码,但采用else分支 当sl_i为“0”、“X”等之一时:

??这样的重新定义是否符合VHDL标准,是否可行 一般来说,使用这些工具

正如Jim Lewis在提到 使用时,重写implicit=通常不适用于工具 VHDL-2003。VHDL-2008应该可以解决这个问题

请注意,上述问题和建议是根据David Koontz编辑的
前面的评论。

这个场景有两个问题

没有明确的std_逻辑_1164.=定义。所有类型都隐式声明了相等运算符和不相等运算符

IEEE标准1076-1993第3节类型,第2段:

…类型的操作集包括显式声明的 具有该类型的参数或结果的子程序。剩下的 类型的操作是基本操作和预定义的 操作员见7.2。这些操作都是隐式声明的 紧跟在类型声明之后的给定类型声明,以及 在下一个显式声明(如果有)之前

扩展名称应为ieee.std_logic_1164.=

表达式中的关系运算符是作为运算符符号给出的,因此没有包含左右参数的扩展名。对您声明的相等运算符函数的函数调用可以是扩展名

只要包声明中声明的=运算符未在包体的其他位置使用,就可以在包体之前使用上下文子句:

library ieee;
use ieee.std_logic_1164."=";

此外,还严格定义了相等运算符

IEEE标准1076-1993,7.2.2关系运算符,第4段:

。。。相同类型的两个标量值相等当且仅当值相同时

因此,没有任何等式会因为它们是元值而返回FALSE。重新定义“平等”的含义是违法的

是的,我知道有一个工具可以让你分析这个或其他接近的东西,但是当使用操作符时它会失败。即使它起作用,它也不会便携,同时仍然是非法的、不道德的,而且可能对腰围有害

这段代码在ghdl中崩溃,它试图避免使用-fexplicit标志人为更改重载运算符的优先级,这与-2008标准不兼容:

library ieee;
use ieee.std_logic_1164.std_logic;
use ieee.std_logic_1164.to_x01;
use ieee.std_logic_1164.is_x;

package std_logic_warning is
  function "="(l, r : std_logic) return boolean;
end package;

package body std_logic_warning is

    use ieee.std_logic_1164."=";

    function "="(l, r : std_logic) return boolean is
    begin
    if is_x(l) or is_x(r) then
      report "std_logic_warning.""="": metavalue detected, returning FALSE"
        severity WARNING;
      return FALSE;
    end if;
    return l = r; -- std_logic_1164."="(l, r);
    end function;

end package body;

library ieee;
use ieee.std_logic_1164.std_ulogic;
use ieee.std_logic_1164.std_logic;
-- use ieee.std_logic_1164.all;

use work.std_logic_warning.all;
entity warning_test is
end entity;

architecture foo of warning_test is
    signal a: std_logic;
    signal b: std_logic;
begin

UNLABELLED:
    process
    begin
        wait for 1 ns;
        a <= 'X';
        wait for 1 ns;
        b <= '1';
        wait for 1 ns;
        a <= '0';
        wait for 1 ns;
        b <= '0';
        wait;
    end process;

MONITOR:
    process (a,b)
    begin
        assert a = b 
            report "a = b " & "( " & std_logic'image(a)
                             & "=" & std_logic'image(b) & " )"
                severity NOTE;
    end process;

end architecture;
这也避免了将Modelsim或ghdl重载规则规避-fexplicit用作ghdl中的命令行参数

不幸的是,这说明VHDL比其他任何东西都复杂

一位熟人指出函数调用中存在递归,因此我通过更改函数名和断言条件表达式证明了这一点

ghdl-a test.vhdl ghdl-e警告测试 ghdl-r警告测试 test.vhdl:16:7:@0ms:report警告:std_logic_警告。=:检测到元值,返回FALSE test.vhdl:56:9:@0ms:assertion注释:a=b'U'='U' test.vhdl:16:7:@1ns:report警告:std_logic_警告=:检测到元值,返回FALSE test.vhdl:56:9:@1ns:assertion注释:a=b'X'=U' test.vhdl:16:7:@2ns:report警告:std_logic_警告。=:检测到元值,返回FALSE test.vhdl:56:9:@2ns:assertion注释:a=b'X'='1' test.vhdl:56:9:@3ns:assertion注释:a=b'0'='1'

递归围绕函数返回表达式=

注释掉包体中的use子句将产生:

-- use ieee.std_logic_1164."=";
ghdl-a test.vhdl test.vhdl:20:14:运算符没有函数声明= ghdl:编译错误

这说明use条款是必要的,这是预期的:

IEEE标准1076-1993第3节类型,第2段:

…类型的操作集包括显式声明的 具有该类型的参数或结果的子程序。剩下的 类型的操作是基本操作和预定义的 操作员见7.2。这些操作都是隐式声明的 紧跟在类型声明之后的给定类型声明,以及 在下一个显式声明(如果有)之前

那么,这个问题是否解决得过多?不,是能见度

10.5过载解决方案的背景:

重载是为名称、子程序和枚举定义的 文字

对于重载实体,重载解析确定实际的 表示标识符或字符文字的出现具有 每当可见性规则确定多个 本事件发生地的含义是可接受的;超载 分辨率同样决定了实际的平均值 事故的发生 操作员或基本操作参见第3节的介绍

我们首先要确定function=的两个声明是否都可见

10.4使用条款,第3段:

use子句中的每个选定名称标识一个或多个声明 这将有可能变得直接可见。如果 所选名称是简单名称、字符文字或运算符符号, 然后,所选名称仅标识该名称的声明 中包含的简单名称、字符文字或运算符符号 由所选名称的前缀表示的包或库

10.4使用条款,第4段:

对于每个use子句,都有一个称为 使用条款的范围。此区域在使用后立即开始 条款如果use子句是某个声明性语句的声明性项 区域,子句的范围扩展到声明语句的末尾 区域如果use子句出现在设计的上下文子句中 单位,use子句的范围扩展到 与设计单元关联的声明性区域。使用范围 子句还可以扩展到配置声明中请参见 10.2

关于这里,我们注意到这个use子句在包体中,它的作用不会扩展到其他任何地方。我们还知道,声明的函数最初也是直接可见的,即不是通过从包声明中进行选择

10.4使用条款,第5段:

以确定哪些声明在 给定的按用途子句,考虑声明集 由其范围包含此位置的所有use子句标识。任何 此集合中的声明是可能可见的声明。A. 潜在可见的声明实际上是直接可见的 以下两种情况除外:

a。如果出现以下情况,则可能可见的声明不会直接可见: 所考虑的位置在同形异义词的直接范围内 宣言

b。具有相同标识符的潜在可见声明包括 不直接可见,除非它们中的每一个都是枚举 文字说明或子程序的声明,由 子程序声明或隐式声明

在包声明中有一个同形词,即函数声明

附录B术语表:

B.117同形词:两个声明的自反性质。如果两个声明都具有相同的标识符,并且两个声明中最多有一个允许重载,则这两个声明中的每一个都称为另一个声明的同形图。如果两个声明都允许重载,那么如果它们具有相同的标识符、运算符符号或字符文字,以及相同的参数和结果类型配置文件,则两个声明中的每一个都是另一个的同形图。§1.3.1,§10.3

B.119直接作用域:声明的一个属性,与声明立即发生的声明区域有关。声明的直接作用域从声明的开始一直延伸到声明区域的结束。§10.2

因此,问题围绕10.4,a中的直接范围。b告诉我们,如果两者都是子程序声明,那么它们在子程序体中都是可见的

然后我们开始讨论笔记:

1-这些规则保证直接作出的声明 use子句可见不能隐藏以其他方式直接可见的 声明

可能可见的use子句声明位于包声明中子程序声明的直接作用域中

如果不是:

10.5过载解决方案,第3段:

在这样一个地方,所有可见的声明都会被考虑。这个 仅当对事件有一种解释时,事件才合法 最内部完整上下文的每个组成部分;完整的上下文 是声明、规范或语句

不合法就是错误。我们会出错的

所以这里的寓意是VHDL可能很复杂,特别是当你试图玩它的时候。我试图做的事情导致了法律代码并没有达到预期的效果,并且直到运行时堆栈空间不足时才产生错误,这是一个第22条军规

显示的代码可以通过以下更改来运行:

删除包体中的use子句:

library ieee;
use ieee.std_logic_1164."=";
-使用ieee.std_logic_1164

还原equidev的返回语句:

return l = r; -- std_logic_1164."="(l, r);  
变成

    return std_logic_1164."="(l, r);  
再说一遍。纠正我的错误

这使得:

ghdl-标准逻辑警告.vhdl ghdl-e警告测试 ghdl-r警告测试 标准逻辑警告。vhdl:17:7:@0ms:报告警告:标准逻辑警告。=:检测到元值,返回FALSE 标准逻辑警告。vhdl:58:9:@0ms:asser 注意:a=b'U'='U' 标准逻辑警告。vhdl:17:7:@1ns:报告警告:标准逻辑警告。=:检测到元值,返回FALSE 标准逻辑警告。vhdl:58:9:@1ns:assertion注释:a=b'X'='U' std_logic_warning.vhdl:17:7:@2ns:报告警告:std_logic_warning.=:检测到元值,返回FALSE 标准逻辑警告。vhdl:58:9:@2ns:assertion注释:a=b'X'='1' 标准逻辑警告。vhdl:58:9:@3ns:assertion注释:a=b“0”='1'

这似乎是正确的结果,因为当在4 ns时将b分配给“0”时,不会触发函数或监视进程的断言测试

重述

是否可以替换std_逻辑的关系运算符=

是的,但它可能不实用。注意,除了=,所有使用的包std_logic_1164名称都有use子句。在-2008中,您可以声明上下文,您可以在其中一次性构造这样一个上下文子句并调用它。或者,您可以用use子句填充包声明

这个练习的全部目的是表明所采用的=的定义对元值无效,并且不符合标准。上述7.2.2第4段引用


正如Jim指出的,断言测试监视器可以取代重新定义=可能具有的任何有用性。

根据您使用的语言版本,您可能会遇到可移植性问题。我建议您使用VHDL-2008来避免这些问题,因为它消除了许多问题

在VHDL-2008之前,一些工具不允许显式运算符重载隐式运算符。在VHDL-2008之前,工具对ieee.std_logic_1164.std_logic的引用进行了不同的解释。有关讨论,请参见ISAC IR2058:。即使实现了IR2058,我的解释是is_x也不会包含在您对std_逻辑的引用中,因为只包含重载运算符,而不是所有函数-因此,如果这样做有效,它可能无法在工具之间移植

因此,我将使用VHDL-2008和以下代码。我将对ieee.std_logic_1164.=的引用替换为对ieee.numeric_std.std_match的引用,因为我不清楚一旦显式运算符被替换,您是否仍然可以引用隐式运算符-即使它是合法的,我希望这是一个附带案例,可能会破坏工具确保报告错误。使用std_match还有正确处理“L”或“H”的好处

library ieee;
use ieee.std_logic_1164.all;

package std_logic_warning is
  function "="(l, r : std_logic) return boolean;
end package;

package body std_logic_warning is

  function "="(l, r : std_logic) return boolean is
  begin
    assert not (is_x(l) or is_x(r))
      report "std_logic_warning.""="": metavalue detected"
      severity WARNING;
    return ieee.numeric_std.std_match(l, r);
  end function;

end package body;
如果您不喜欢std_match的行为,您可以使用std_match作为模板来创建功能,但是,我不建议这样做,因为合成工具可能不喜欢它

虽然您可以使用modified=,但作为一个反建议,X有两个来源,外部来自其他设计,内部来自未初始化的寄存器。我不担心未初始化的寄存器,因为我对重置非常严格。因此,在核心级别,我可能会根据我对其他人或测试台的信心,直接在核心输入上使用assert语句

assert not is_x(core_input_1) 
  report "meta value detected on core_input_1" severity ERROR ; 

谢谢我已经更新了建议以解决您的问题。任何意见都非常感谢。感谢额外的更新;我已经删除了std_logic_原始包,并使用std_logic_1164扩展名进行访问。使用ieee.std_logic_1164;使ModelSim崩溃,因此不是那种方法。我让ghdl也崩溃了。我怀疑这与一个合格的函数和一个隐式定义的函数有关,它们可能在后处理或格式上有所不同。正如Jim在他的回答中间接指出的,这是由于在实现中没有遵守标准,指定使用哪个=或其他操作符。分析、阐述和模拟你的函数的目的是为了证明“U”=“U”符合LRM对“equal”的定义,你的函数不符合该定义。谢谢,非常有用。std_匹配将是一个很好的替代品,但您是说合成工具可能不支持它吗?否则,可以通过额外的包“std_logic_original”访问原始std_逻辑运算符。对于外部协议和内部RAM,使用额外代码进行显式“X”检查可能会非常麻烦。其思想是可以将use.std_logic_warning.all添加到已经编写的代码中,以便快速添加“X”检查。我认为,如果VHDL语言支持这样的东西,将提高模拟测试质量。合成工具应该很好地支持std_匹配。我关心的是用你写的行为来代替它。不太确定about=behavior,但是如果用对应包中实际存在的代码替换rising_EdgeLk或+之类的东西,就不能保证它会产生您想要的结果。这是因为std_logic_1164和numeric_std中的内容不是合成的,而是具有已知行为的已知包。一些工具使用带有含义和属性的pragmas注释将合成工具指向实现
奇怪的是,该语言已经对类型为ieee.numeric\u std.unsigned的=执行了此操作。因此,如果您使用无符号的数字\u std\u,对于std\u logic\u vector,它已经得到支持。std_ulogic没有类似的重载。语言中的implicit=for std_逻辑不能更改,因为有些东西需要测试“X”。不确定是否有合适的位置来重载隐式行为。我还研究了?=的行为,它确实正确地通过了X,但是??不检查元数据,这可能会产生警告。在测试台代码中,我看到=必须能够在没有警告的情况下与“X”进行比较。对于可综合设计的模块,我假设,=compare中的“X”很可能表示设计者希望进一步研究的内容,并且可能会使用一些保护表达式,从而受益于VHDL短路评估。
    return std_logic_1164."="(l, r);  
library ieee;
use ieee.std_logic_1164.all;

package std_logic_warning is
  function "="(l, r : std_logic) return boolean;
end package;

package body std_logic_warning is

  function "="(l, r : std_logic) return boolean is
  begin
    assert not (is_x(l) or is_x(r))
      report "std_logic_warning.""="": metavalue detected"
      severity WARNING;
    return ieee.numeric_std.std_match(l, r);
  end function;

end package body;
assert not is_x(core_input_1) 
  report "meta value detected on core_input_1" severity ERROR ;