0

我打算将许多 if 语句汇总为一个(在 VHDL 中),例如:

从这个工作片段

if config = "0001" and counter = 40 then
    res <= '1';
elsif config = "0010" and counter = 52 then
    res <= '1';
else
    res <= '0';
end if;

到这个不工作的片段

if config = "0001" and counter = 40 or config = "0010" and counter = 52 then
    res <= '1';
else
    res <= '0';
end if;

Vivado 告诉我“'或'附近有问题”,但我没有看到。

这在硬件实现上会更好(更健壮)吗?

谢谢

4

2 回答 2

3

提供一个最小的、完整的和可验证的例子,例如:

library ieee;
use ieee.std_logic_1164.all;

entity unworking_snippet is
end entity;

architecture snippet of unworking_snippet is
    signal config:  bit_vector (3 downto 0) := "0001";
    signal counter: integer range 0 to 52 := 40;
    signal res:  std_logic;
begin

    process  (config, counter)
    begin

        if config = "0001" and counter = 40 or config = "0010" and counter = 52 then
            res <= '1';
        else
            res <= '0';
        end if;
    end process;
end architecture;

这将产生一条指向您的 if 语句的错误消息。例如,ghdl 指向 if 语句中的两个错误:

ghdl -a unworking_snippet.vhdl
unworking_snippet.vhdl:16:45:error: only one type of logical operators may be used to combine relation
unworking_snippet.vhdl:16:64:error: only one type of logical operators may be used to combine relation
ghdl:error: compilation error

其中第 16 行包含 if 语句条件,字符 45 是 'o' in or,字符 64 是 second 中的 'a' and

这些被硬编码到 VHDL 的表达式解析中,在 IEEE Std 1076-2008 9 中的 Baccus Naur 形式 (BNF) 中描述。表达式,9.1 一般:

An expression is a formula that defines the computation of a value.
expression ::=
      condition_operator primary
    | logical_expression

logical_expression ::=
      relation { and relation }
    | relation { or relation }
    | relation { xor relation 
    | relation [ nand relation ]
    | relation [ nor relation ]
    | relation { xnor relation }

relation ::=
    shift_expression [ relational_operator shift_expression ]

shift_expression ::=
    simple_expression [ shift_operator simple_expression ]

simple_expression ::=
    [ sign ] term { adding_operator term }

term ::=  
    factor { multiplying_operator factor }

factor ::=
      primary [ ** primary ]  
    | abs primary
    | not primary
    | logical_operator primary  

primary ::=  
      name
    | literal
    | aggregate
    | function_call
    | qualified_expression
    | type_conversion
    | allocator
    | ( expression )

您可以在其中手动解析 if 语句条件,将两个不同的逻辑运算符作为另一个逻辑运算符中的关系的唯一方法是,如果主运算符包含在括号中:

        if (config = "0001" and counter = 40) or (config = "0010" and counter = 52) then

通过BNF的路径是relation => shift_expression => simple_expression => term => logical_operator primary, primary => (expression)。这发生在操作员的双方or

替换更新的 if 语句条件允许 MCVe 成功分析(编译)。

虽然具有编程背景的人通常会引入多余的括号,但同一表达式中的不同逻辑运算符需要括号(config = "0001" and counter = 40 or config = "0010" and counter = 52在原始的“不工作”片段中)。

因为它是 BNF 中的语法分析要求,所以模拟和合成后功能之间没有区别。

VHDL 以相同的优先级处理逻辑运算符:

9.2 运算符

9.2.1 概述

表达式中可以使用的运算符定义如下。每个算子都属于一类算子,所有的算子都具有相同的优先级;运算符的类别按优先级递增的顺序列出。

...
逻辑运算符 ::=| | 南德| 也不| 异或| 异或

关系运算符 ::= = | /= | < | <= | > | >= | ?= | ?/= | ?< | ?<= | ?> | ?>=
...

较高优先级的运算符在较低优先级的运算符之前与其操作数相关联。在语言允许一系列运算符的情况下,具有相同优先级的运算符按文本顺序从左到右与其操作数相关联。运算符的优先级是固定的,用户不能更改,但可以使用括号来控制运算符和操作数的关联。

通常,表达式中的操作数在与运算符相关联之前进行求值。然而,对于某些操作,当且仅当左侧操作数具有特定值时,才评估右侧操作数。这些操作称为短路操作。为 BIT 和 BOOLEAN 类型的操作数定义的二进制逻辑运算 and, or, nand, and nor 都是短路运算;此外,这些是唯一的短路操作。

这里的语言不允许基于逻辑运算符之间缺乏优先级的运算符序列。

9.1 第 3 和 4 段

每个主节点都有一个值和一个类型。唯一允许作为主要名称的名称是产生值的属性和表示对象或值的名称。在名称表示对象而不是文件类型或受保护类型的对象的情况下,主要的值是对象的值。在名称表示文件对象或受保护类型的对象的情况下,主要的值是名称表示的实体。

表达式的类型仅取决于其操作数的类型和应用的运算符;对于重载的操作数或运算符,操作数类型的确定或重载运算符的标识取决于上下文(见 12.5)。对于每个预定义的运算符,操作数和结果类型在以下子条款中给出。

下面的子条款是 9.2,关系运算符产生的表达式类型是 BOOLEAN 类型(9.2.3 关系运算符)。

需要括号的 BNF 限制避免了重复评估整个表达式以确定它的树结构而不在 George Boole 的代数上叠加逻辑运算符优先级的复杂性,注意表达式也可以产生任意类型的值。表达式的大小或复杂性没有限制,括号表示子树。

于 2019-07-30T03:13:10.983 回答
1

您必须像这样放置括号:

if (config = "0001" and counter = 40) or (config = "0010" and counter = 52) then
    res <= '1';
else
    res <= '0';
end if;

在硬件实现上,我认为这两个代码很可能会推断出相同的组件,或者差异可以忽略不计。

于 2019-07-29T21:06:51.480 回答