vhdl - 如何从常量设置 case 语句中的分支?错误: choice must be locally static expression

标签 vhdl ghdl

Verilog 允许将 case 语句的分支定义为不同文件中的常量。示例:

`define COND1 3'b001
`define COND2 3'b010
`define COND3 3'b100

module xyz(input wire [2:0] select, output reg value);
    always @* 
    case(select)
    `COND1: value = 1'b0;
    `COND2: value = 1'b1;
    `COND3: value = 1'b0;
    default: value = 1'b0;
endmodule

我怎样才能在 VHDL 中做同样的事情?我希望在包中定义 case 的常量,并将这些常量拉入当前体系结构,并使用这些常量定义 case 语句的分支。工作示例:

library ieee;
use ieee.std_logic_1164.all;

entity stuff is
   port(
       sel1: in std_logic_vector(2 downto 0);
       val1:  out std_logic
   );
end entity;

architecture rtl of stuff is
    constant COND1 : std_logic_vector(2 downto 0) := "001";
    constant COND2 : std_logic_vector(2 downto 0) := "010";
    constant COND3 : std_logic_vector(2 downto 0) := "100";
begin

    process(sel1) 
    begin 
        case sel1 is
        when COND1 => val1 <= '0';
        when COND2 => val1 <= '1';
        when COND3 => val1 <= '0';
        when others => val1 <= '0';
        end case;
    end process;

end architecture;

哪个工作正常...

但是,当我在 VHDL 代码中尝试它时,我收到一个奇怪的错误:

..\simtools\ghdl\bin\ghdl.exe -a stuff2.vhdl
stuff2.vhdl:40:18: choice must be locally static expression   
stuff2.vhdl:41:18: choice must be locally static expression
stuff2.vhdl:42:18: choice must be locally static expression

这是给出此错误的代码:

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

entity stuff is

    generic(
        CW : integer := 3
    );
    port(    
        sel1 : in    std_logic_vector(CW-1 downto 0);
        val1 : out   std_logic
    );

end entity;

architecture rtl of stuff is

    function n(n_value:integer; n_width:integer) 
        return std_logic_vector is
    begin
        return std_logic_vector(to_unsigned(n_value, n_width));
    end function;

    constant CMD1 : std_logic_vector(2 downto 0) := n(0, 3);
    constant CMD2 : std_logic_vector(2 downto 0) := n(1, 3);
    constant CMD3 : std_logic_vector(2 downto 0) := n(2, 3);
    constant CMD4 : std_logic_vector(2 downto 0) := n(3, 3);
    constant CMD5 : std_logic_vector(2 downto 0) := n(4, 3);

    signal sel2 : std_logic_vector(2 downto 0);

begin

    sel2 <= sel1(2 downto 0);

    process(sel2)
    begin
        case sel2 is
            when CMD1   => val1 <= '0';     
            when CMD2   => val1 <= '1';     
            when CMD3   => val1 <= '0';     
            when others => val1 <= '0';     
        end case;
    end process;

end architecture;

最佳答案

Kevin Kruse 的答案取决于 -2008:

9.4.2 本地静态初选

An expression is said to be locally static if and only if every operator in the expression denotes an implicitly defined operator or an operator defined in one of the packages STD_LOGIC_1164, NUMERIC_BIT, NUMERIC_STD, NUMERIC_BIT_UNSIGNED, or NUMERIC_STD_UNSIGNED in library IEEE, and if every primary in the expression is a locally static primary, where a locally static primary is defined to be one of the following:

...
e) A function call whose function name denotes an implicitly defined operation or an operation defined in one of the packages STD_LOGIC_1164, NUMERIC_BIT, NUMERIC_STD, NUMERIC_BIT_UNSIGNED, or NUMERIC_STD_UNSIGNED in library IEEE and whose actual parameters are each locally static expressions

截至 ghdl-0.36 尚未实现。否则,Kevin 的答案对于完全符合 -2008 的本地静态初选似乎有效。

在早期版本中,由于函数 n 或 to_unsigned 的返回值,常量值表达式不是局部静态的。

参见 -2002 或更早版本 7.4.2 全局静态初选 (9.4.3 - 2008) “i) 函数调用,其函数名称表示纯函数,其实际参数均为全局静态表达式”,其中每个局部静态表达式为也是全局静态的。

-2008 更改在 IEEE 包中添加了不允许更改其函数声明或功能的调用函数,允许将它们视为本地静态,并受包源的版权许可条款控制。

对于 -2008 或更早版本标准的不兼容实现,可以定义 CMD1 - 4 的数值并将 sel(2 downto 0) 转换为本地静态整数子类型值:

architecture rtl of stuff is
    constant CMD1:  natural range 0 to 7 := 0;  -- "000"
    constant CMD2:  natural range 0 to 7 := 1;  -- "001"
    constant CMD3:  natural range 0 to 7 := 2;  -- "010"
    constant CMD4:  natural range 0 to 7 := 3;  -- "011"
    constant CMD5:  natural range 0 to 7 := 4;  -- "100"
    signal sel2:    natural range 0 to 7;  -- locally static subtype
begin
    sel2 <= to_integer(unsigned(sel1(2 downto 0)));

    process (sel2)
    begin
        case sel2 is
            when CMD1   => val1 <= '0';
            when CMD2   => val1 <= '1';
            when CMD3   => val1 <= '0';
            when others => val1 <= '0';
        end case;
    end process;
end architecture;

但是问题的第一个 VHDL 示例最接近地实现了 Verilog 代码片段。

要使用固定切片来启用 sel1 的全局静态范围进行解码,需要声明 sel2 来为 case 表达式提供本地静态子类型:

architecture equiv_w_generic_sel1 of stuff is
    constant COND1:  std_logic_vector (2 downto 0) := "000";
    constant COND2:  std_logic_vector (2 downto 0) := "001";
    constant COND3:  std_logic_vector (2 downto 0) := "010";
    signal sel2:     std_logic_vector (2 downto 0);
begin

    sel2 <= sel1(sel2'range);  -- locally static subtype

    process (sel2)
    begin
        case sel2 is
            when COND1  => val1 <= '0';
            when COND2  => val1 <= '1';
            when COND3  => val1 <= '0';
            when others => val1 <= '0';
        end case;
    end process;
end architecture;

您不会通过使用非本地静态函数调用来重新定义问题变得更加困难,并且也不需要 use 子句来提供包 numeric_std 声明的可见性。请注意,COND1、COND2 和 COND3 常量与 Verilog 代码片段一样具有本地静态值表达式。

以上两种架构都可以在指定或不指定 ghdl 的 --std=08 的情况下进行分析。


请注意,问题中显示的 ghdl 命令行未指定 VHDL 修订版,并且 ghdl 默认为 --std=93c 的等效项,它提供宽松的合规性匹配 Modelsim 对标准 -1993 修订版的实现。

关于vhdl - 如何从常量设置 case 语句中的分支?错误: choice must be locally static expression,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55953234/

相关文章:

vhdl - 如何在VHDL中将两个16位STD_LOGIC_VECTOR和一个进位添加到17位?

vhdl - ghdl 详述包中的实体

vhdl - 此设计包含一个或多个与 Spartan6 架构直接不兼容的寄存器/锁存器

arrays - 如何在 VHDL 中初始化长度为 1 的数组

c++ - Doxygen:使用 C++ 和 VHDL 的项目的无缝文档

windows - ghdl 不生成二进制文件 (windows)

c - 计算错误 C uint64_t

compiler-errors - GHDL编译问题

c++ - ghdl 缺少 util.misc_conv_pkg ubuntu 14.04