2

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 中做同样的事情?我想在一个包中定义我的案例常量,并将这些常量拉入当前架构并使用这些常量来定义案例语句的分支。工作示例:

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;
4

2 回答 2

2

Kevin Kruse 的回答取决于 -2008:

9.4.2 局部静态原色

当且仅当表达式中的每个运算符都表示隐式定义的运算符或在库 IEEE 中的包 STD_LOGIC_1164、NUMERIC_BIT、NUMERIC_STD、NUMERIC_BIT_UNSIGNED 或 NUMERIC_STD_UNSIGNED 之一中定义的运算符,并且如果在该表达式是一个本地静态主,其中一个本地静态主被定义为以下之一:

...
e) 函数调用,其函数名称表示隐式定义的操作或在库 IEEE 中的包 STD_LOGIC_1164、NUMERIC_BIT、NUMERIC_STD、NUMERIC_BIT_UNSIGNED 或 NUMERIC_STD_UNSIGNED 之一中定义的操作,其实际参数是每个本地静态表达式

截至 ghdl-0.36 尚未实施。否则,凯文的答案似乎对完全符合 -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;

您没有通过使用非本地静态函数调用将问题重新定义为更难,并且也不需要使用子句来为包 numeric_std 声明提供可见性。请注意 COND1、COND2 和 COND3 常量具有本地静态值表达式,Verilog 片段也是如此。

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


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

于 2019-05-02T18:09:57.090 回答
0

您对该函数的使用n使常量的值不是本地静态的。

如果你n(0, 3)用它代替std_logic_vector(to_unsigned(0, 3))它会工作。或者,正如您已经展示的那样,将其替换为"000".

于 2019-05-02T14:27:40.177 回答