How to set branch in case statement from a constant? ERROR: choice must be locally static expression
How to set branch in case statement from a constant? ERROR: choice must be locally static expression
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;
您对函数 n
的使用使得常量的值不是局部静态的。
如果您将 n(0, 3)
替换为 std_logic_vector(to_unsigned(0, 3))
,它将起作用。或者,正如您已经展示的那样,将其替换为 "000"
.
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 开始尚未实现。否则凯文的答案似乎对完全符合 -2008 的本地静态初选有效。
在早期版本中,由于函数 n 或 to_unsigned 的 return 值,常量值表达式不是局部静态的。
请参阅 -2002 或更早版本 7.4.2 全局静态初选 (9.4.3 - 2008) "i) A function call whose function name denotes a pure function and whose actual parameters are each globally static expressions" 其中每个局部静态表达式也是全局静态的。
-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 修订版的实现。
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;
您对函数 n
的使用使得常量的值不是局部静态的。
如果您将 n(0, 3)
替换为 std_logic_vector(to_unsigned(0, 3))
,它将起作用。或者,正如您已经展示的那样,将其替换为 "000"
.
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 开始尚未实现。否则凯文的答案似乎对完全符合 -2008 的本地静态初选有效。
在早期版本中,由于函数 n 或 to_unsigned 的 return 值,常量值表达式不是局部静态的。
请参阅 -2002 或更早版本 7.4.2 全局静态初选 (9.4.3 - 2008) "i) A function call whose function name denotes a pure function and whose actual parameters are each globally static expressions" 其中每个局部静态表达式也是全局静态的。
-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 修订版的实现。