如何实例化一个采用通用包的组件?
How to instantiate a component that takes a generic package?
我有以下情况:我的 VHDL 设计中有模块 X 和 Y,可以根据大量参数进行定制。为此,我将这些参数作为泛型包含在 X 和 Y 的声明中。此外,X 必须在 Y 中实例化。
但是,由于这个参数列表非常大,我认为最好将它们全部封装在一个通用包中,这就是麻烦的开始。当我尝试使用通用包编译模块 X 时一切顺利。但是,当我尝试编译模块 Y(并在内部实例化模块 X)时,我找不到将 Y 中的顶级通用包映射到 X 模块的方法。
为了澄清,这是我的场景的 MWE:
包裹:
package generic_parameters is
Generic(
PARAM_A : natural;
PARAM_B : natural);
end package generic_parameters;
模块 X:
library ieee;
use ieee.std_logic_1164.all;
entity module_X is
generic(package p is new work.generic_parameters generic map (<>));
port(
A : in std_logic_vector(p.PARAM_A-1 downto 0);
B : out std_logic_vector(p.PARAM_A-1 downto 0));
end entity module_X;
architecture RTL of module_X is
begin
B <= not(A);
end architecture RTL;
模块 Y:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity module_Y is
generic(package p is new work.generic_parameters generic map (<>));
port(
A : in std_logic_vector(p.PARAM_A-1 downto 0);
B : out std_logic_vector(p.PARAM_A-1 downto 0));
end entity module_Y;
architecture RTL of module_Y is
begin
instance_X: entity work.module_X
generic map(p => p)
port map(
A => A,
B => B);
end architecture RTL;
我得到的两个错误是(ModelSim 2020.1,在文件 module_Y.vhd 中):
- 关联元素实际部分的错误表达 'p'。
- 接口包声明的实际参数'p'不是包实例化。
我想要完成的事情是不可能的吗?还有什么选择?
无法访问 Modelsim 或 EDA 游乐场,使用 ghd 分析了示例代码,它产生的错误类似于 Modelsim 附带描述实际问题的错误:
ghdl -a --std=08 mbrandalero.vhdl
mbrandalero.vhdl:14:35:error: no declaration for "param_a" in package interface "p"
mbrandalero.vhdl:15:36:error: no declaration for "param_a" in package interface "p"
mbrandalero.vhdl:18:14:error: entity 'module_x' was not analyzed
mbrandalero.vhdl:33:35:error: no declaration for "param_a" in package interface "p"
mbrandalero.vhdl:34:36:error: no declaration for "param_a" in package interface "p"
mbrandalero.vhdl:37:14:error: entity 'module_y' was not analyed
ghdl:error: compilation error
(设计单位将所有错误集中在一个文件中,端口信号声明取决于 Module_X
和 Module_Y
中的 PARAM_A
。)
可见性问题在 IEEE 标准 1076-2008 中指定:
4.7 包声明
Items declared immediately within a simple or a generic-mapped package declaration become visible by selection within a given design unit wherever the name of that package is visible in the given unit. Such items may also be made directly visible by an appropriate use clause (see 12.4). Items declared immediately within an uninstantiated package declaration cannot be made visible outside of the package.
这里的泛型是在一个未实例化的包中立即声明的,直到详细说明才实例化。实例化包的名称 (p
) 是可见的,但通用常量 (PARAM_A
和 PARAM_B
) 是可见的,直到在 Module_Y
中详细说明 instance_X
的组件实例化并且大概 entity work.Module_Y
在设计层次结构的较高位置。这包括使用选定名称的可见性。
很明显,通用实例化包不打算用于端口子句声明。
是否有将实例化包映射为通用包的替代方法?
是的。解决示例代码中出现的问题并注意到您正尝试在设计层次结构中向下使用相同的实例化包,您可以将包 p 实例化为主要设计单元并将该设计单元添加到各种上下文子句中(Module_X
, Module_Y
, 设计层次结构中的下一个更高级别):
package generic_parameters is
generic (PARAM_A: natural; PARAM_B: natural);
end package generic_parameters;
package p is new work.generic_parameters -- ADDED primary unit declaration
generic map (PARAM_A => 4, PARAM_B => 2);
library ieee;
use ieee.std_logic_1164.all;
use work.p.all; -- ADDED use clause
entity module_X is
-- generic (package p is new work.generic_parameters generic map (<>));
port (
A: in std_logic_vector(PARAM_A - 1 downto 0); -- WAS p.PARAM_A
B: out std_logic_vector(PARAM_A - 1 downto 0) -- WAS p.PARAM_A
);
end entity module_X;
architecture RTL of module_X is
begin
B <= not(A);
end architecture RTL;
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.numeric_std.all; -- NOT USED
use work.p.all; -- ADDED USE CLAUSE
entity module_Y is
-- generic (package p is new work.generic_parameters generic map (<>));
port (
A: in std_logic_vector(PARAM_A - 1 downto 0); -- WAS p.PARAM_A
B: out std_logic_vector(PARAM_A - 1 downto 0) -- WAS p.PARAM_A
);
end entity module_Y;
architecture RTL of module_Y is
begin
instance_X:
entity work.module_X
-- generic map (p => p)
port map (
A => A,
B => B
);
end architecture RTL;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.p.all;
entity module_y_tb is
end entity;
architecture foo of module_y_tb is
signal A: std_logic_vector (PARAM_A - 1 downto 0);
signal B: std_logic_vector (PARAM_A - 1 downto 0);
begin
UUT:
entity work.module_y
port map (
A => A,
B => B
);
STIMULUS:
process
begin
for i in 0 to 15 loop
A <= std_logic_vector (to_unsigned(i, A'LENGTH));
wait for 10 ns;
end loop;
wait;
end process;
end architecture;
由于没有理由在这里使用通用子句,它们被简单地注释掉了,包实例化是元素。
测试台产生:
使所有各种主要单元依赖于同一个分析库单元(包 p
)的唯一缺点是,如果这改变了所有具有分析顺序依赖性的设计单元,则需要重新分析。
有几种方法可以解决这个问题:
提供多个包,减少分析顺序依赖
使用记录类型的通用常量(在整个工具链支持的情况下)。在重新分析设计层次结构的整个受影响部分之前,可以添加要使用的 'spare' 元素。传递记录类型的泛型常量,降低泛型子句的文本复杂度
记录常量可以使用通过 textio 读取文件的非纯函数来定义其值。这发生在细化阶段,并得到综合和仿真供应商的广泛支持。
关于这些潜在解决方案的问题可以处理特定问题。上面显示的修改后的示例代码满足了这个问题的要求,不需要详细说明时间限制。所有包实例都将使用顶级包。
使用记录常量而不是实例化包
package generic_parameters is
generic (PARAM_A: natural; PARAM_B: natural);
type param_rec is record -- list of parameters
A: natural;
B: natural;
end record;
constant PARAM: param_rec := (PARAM_A, PARAM_B);
end package generic_parameters;
package p is new work.generic_parameters
generic map (PARAM_A => 4, PARAM_B => 2);
library ieee;
use ieee.std_logic_1164.all;
use work.p.all;
entity module_X is
generic (param: param_rec);
port (
A: in std_logic_vector(param.A - 1 downto 0);
B: out std_logic_vector(param.A - 1 downto 0)
);
end entity module_X;
architecture RTL of module_X is
begin
B <= not A;
end architecture RTL;
library ieee;
use ieee.std_logic_1164.all;
use work.p.all;
entity module_Y is
generic (param: param_rec);
port (
A: in std_logic_vector(param.A - 1 downto 0);
B: out std_logic_vector(param.A - 1 downto 0)
);
end entity module_Y;
architecture RTL of module_Y is
begin
instance_X:
entity work.module_X
generic map (param => param)
port map (
A => A,
B => B
);
end architecture RTL;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.p.all;
entity module_y_tb is -- TOP LEVEL of design hierarch
end entity;
architecture foo of module_y_tb is
signal A: std_logic_vector (PARAM_A - 1 downto 0);
signal B: std_logic_vector (PARAM_A - 1 downto 0);
constant tb_param: param_rec := (A => 4, B => 2);
begin
UUT:
entity work.module_y
generic map (param => param)
port map (
A => A,
B => B
);
STIMULUS:
process
begin
for i in 0 to 15 loop
A <= std_logic_vector (to_unsigned(i, A'LENGTH));
wait for 10 ns;
end loop;
wait;
end process;
end architecture;
这将允许在每个通用映射中进行替换,就像在详细说明过程中进行包实例化一样,但要遵守端口关联列表中形式和实际之间需要匹配元素的限制。
我有以下情况:我的 VHDL 设计中有模块 X 和 Y,可以根据大量参数进行定制。为此,我将这些参数作为泛型包含在 X 和 Y 的声明中。此外,X 必须在 Y 中实例化。
但是,由于这个参数列表非常大,我认为最好将它们全部封装在一个通用包中,这就是麻烦的开始。当我尝试使用通用包编译模块 X 时一切顺利。但是,当我尝试编译模块 Y(并在内部实例化模块 X)时,我找不到将 Y 中的顶级通用包映射到 X 模块的方法。
为了澄清,这是我的场景的 MWE:
包裹:
package generic_parameters is
Generic(
PARAM_A : natural;
PARAM_B : natural);
end package generic_parameters;
模块 X:
library ieee;
use ieee.std_logic_1164.all;
entity module_X is
generic(package p is new work.generic_parameters generic map (<>));
port(
A : in std_logic_vector(p.PARAM_A-1 downto 0);
B : out std_logic_vector(p.PARAM_A-1 downto 0));
end entity module_X;
architecture RTL of module_X is
begin
B <= not(A);
end architecture RTL;
模块 Y:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity module_Y is
generic(package p is new work.generic_parameters generic map (<>));
port(
A : in std_logic_vector(p.PARAM_A-1 downto 0);
B : out std_logic_vector(p.PARAM_A-1 downto 0));
end entity module_Y;
architecture RTL of module_Y is
begin
instance_X: entity work.module_X
generic map(p => p)
port map(
A => A,
B => B);
end architecture RTL;
我得到的两个错误是(ModelSim 2020.1,在文件 module_Y.vhd 中):
- 关联元素实际部分的错误表达 'p'。
- 接口包声明的实际参数'p'不是包实例化。
我想要完成的事情是不可能的吗?还有什么选择?
无法访问 Modelsim 或 EDA 游乐场,使用 ghd 分析了示例代码,它产生的错误类似于 Modelsim 附带描述实际问题的错误:
ghdl -a --std=08 mbrandalero.vhdl
mbrandalero.vhdl:14:35:error: no declaration for "param_a" in package interface "p"
mbrandalero.vhdl:15:36:error: no declaration for "param_a" in package interface "p"
mbrandalero.vhdl:18:14:error: entity 'module_x' was not analyzed
mbrandalero.vhdl:33:35:error: no declaration for "param_a" in package interface "p"
mbrandalero.vhdl:34:36:error: no declaration for "param_a" in package interface "p"
mbrandalero.vhdl:37:14:error: entity 'module_y' was not analyed
ghdl:error: compilation error
(设计单位将所有错误集中在一个文件中,端口信号声明取决于 Module_X
和 Module_Y
中的 PARAM_A
。)
可见性问题在 IEEE 标准 1076-2008 中指定:
4.7 包声明
Items declared immediately within a simple or a generic-mapped package declaration become visible by selection within a given design unit wherever the name of that package is visible in the given unit. Such items may also be made directly visible by an appropriate use clause (see 12.4). Items declared immediately within an uninstantiated package declaration cannot be made visible outside of the package.
这里的泛型是在一个未实例化的包中立即声明的,直到详细说明才实例化。实例化包的名称 (p
) 是可见的,但通用常量 (PARAM_A
和 PARAM_B
) 是可见的,直到在 Module_Y
中详细说明 instance_X
的组件实例化并且大概 entity work.Module_Y
在设计层次结构的较高位置。这包括使用选定名称的可见性。
很明显,通用实例化包不打算用于端口子句声明。
是否有将实例化包映射为通用包的替代方法?
是的。解决示例代码中出现的问题并注意到您正尝试在设计层次结构中向下使用相同的实例化包,您可以将包 p 实例化为主要设计单元并将该设计单元添加到各种上下文子句中(Module_X
, Module_Y
, 设计层次结构中的下一个更高级别):
package generic_parameters is
generic (PARAM_A: natural; PARAM_B: natural);
end package generic_parameters;
package p is new work.generic_parameters -- ADDED primary unit declaration
generic map (PARAM_A => 4, PARAM_B => 2);
library ieee;
use ieee.std_logic_1164.all;
use work.p.all; -- ADDED use clause
entity module_X is
-- generic (package p is new work.generic_parameters generic map (<>));
port (
A: in std_logic_vector(PARAM_A - 1 downto 0); -- WAS p.PARAM_A
B: out std_logic_vector(PARAM_A - 1 downto 0) -- WAS p.PARAM_A
);
end entity module_X;
architecture RTL of module_X is
begin
B <= not(A);
end architecture RTL;
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.numeric_std.all; -- NOT USED
use work.p.all; -- ADDED USE CLAUSE
entity module_Y is
-- generic (package p is new work.generic_parameters generic map (<>));
port (
A: in std_logic_vector(PARAM_A - 1 downto 0); -- WAS p.PARAM_A
B: out std_logic_vector(PARAM_A - 1 downto 0) -- WAS p.PARAM_A
);
end entity module_Y;
architecture RTL of module_Y is
begin
instance_X:
entity work.module_X
-- generic map (p => p)
port map (
A => A,
B => B
);
end architecture RTL;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.p.all;
entity module_y_tb is
end entity;
architecture foo of module_y_tb is
signal A: std_logic_vector (PARAM_A - 1 downto 0);
signal B: std_logic_vector (PARAM_A - 1 downto 0);
begin
UUT:
entity work.module_y
port map (
A => A,
B => B
);
STIMULUS:
process
begin
for i in 0 to 15 loop
A <= std_logic_vector (to_unsigned(i, A'LENGTH));
wait for 10 ns;
end loop;
wait;
end process;
end architecture;
由于没有理由在这里使用通用子句,它们被简单地注释掉了,包实例化是元素。
测试台产生:
使所有各种主要单元依赖于同一个分析库单元(包 p
)的唯一缺点是,如果这改变了所有具有分析顺序依赖性的设计单元,则需要重新分析。
有几种方法可以解决这个问题:
提供多个包,减少分析顺序依赖
使用记录类型的通用常量(在整个工具链支持的情况下)。在重新分析设计层次结构的整个受影响部分之前,可以添加要使用的 'spare' 元素。传递记录类型的泛型常量,降低泛型子句的文本复杂度
记录常量可以使用通过 textio 读取文件的非纯函数来定义其值。这发生在细化阶段,并得到综合和仿真供应商的广泛支持。
关于这些潜在解决方案的问题可以处理特定问题。上面显示的修改后的示例代码满足了这个问题的要求,不需要详细说明时间限制。所有包实例都将使用顶级包。
使用记录常量而不是实例化包
package generic_parameters is
generic (PARAM_A: natural; PARAM_B: natural);
type param_rec is record -- list of parameters
A: natural;
B: natural;
end record;
constant PARAM: param_rec := (PARAM_A, PARAM_B);
end package generic_parameters;
package p is new work.generic_parameters
generic map (PARAM_A => 4, PARAM_B => 2);
library ieee;
use ieee.std_logic_1164.all;
use work.p.all;
entity module_X is
generic (param: param_rec);
port (
A: in std_logic_vector(param.A - 1 downto 0);
B: out std_logic_vector(param.A - 1 downto 0)
);
end entity module_X;
architecture RTL of module_X is
begin
B <= not A;
end architecture RTL;
library ieee;
use ieee.std_logic_1164.all;
use work.p.all;
entity module_Y is
generic (param: param_rec);
port (
A: in std_logic_vector(param.A - 1 downto 0);
B: out std_logic_vector(param.A - 1 downto 0)
);
end entity module_Y;
architecture RTL of module_Y is
begin
instance_X:
entity work.module_X
generic map (param => param)
port map (
A => A,
B => B
);
end architecture RTL;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.p.all;
entity module_y_tb is -- TOP LEVEL of design hierarch
end entity;
architecture foo of module_y_tb is
signal A: std_logic_vector (PARAM_A - 1 downto 0);
signal B: std_logic_vector (PARAM_A - 1 downto 0);
constant tb_param: param_rec := (A => 4, B => 2);
begin
UUT:
entity work.module_y
generic map (param => param)
port map (
A => A,
B => B
);
STIMULUS:
process
begin
for i in 0 to 15 loop
A <= std_logic_vector (to_unsigned(i, A'LENGTH));
wait for 10 ns;
end loop;
wait;
end process;
end architecture;
这将允许在每个通用映射中进行替换,就像在详细说明过程中进行包实例化一样,但要遵守端口关联列表中形式和实际之间需要匹配元素的限制。