vhdl - 如何在 VHDL 中实例化通用设计的参数化版本?

标签 vhdl

我正在尝试理解 VHDL 中的泛型编程,并且我已经编写了一些简单的代码来实现这一点。我的目标是能够编写通用设计(通用的意思是未指定实体的输入/输出大小等特定事物),然后在顶级模块中实例化它并在实例化时指定设计约束。这样,我可以根据用户的需要编写一个设计来满足许多不同的参数约束。否则,我需要为每个文件编写一个单独的设计,每个文件只进行少量修改。这种灵 active 的一个明显用例是创建库。

这两个文件说明了我要实现的目标:

-- array_adder.vhd
-- 
-- Computes and outputs the pointwise addition of two arrays.
library ieee;
use ieee.numeric_std.all;

package array_adder_pkg is
    generic (array_size     : integer;
             precision_size : integer
    );
    type array_type is array (0 to array_size-1) of signed(precision_size-1 downto 0);

    component array_adder is
        port (a   : in  array_type;
              b   : in  array_type;
              c   : out array_type
        );
    end component;
end package;
-----main code:-----------------------------------------------------------------
library ieee;
use ieee.numeric_std.all;
--------------------------------------------------------------------------------
entity array_adder is
    port (a : in  array_type;
          b : in  array_type;
          c : out array_type
    );
end entity;
--------------------------------------------------------------------------------
architecture fpga of array_adder is
begin
    comp: for i in 0 to array_size-1 generate
        c(i) <= a(i) + b(i);
    end generate;
end architecture;

-- top_level.vhd
--------------------------------------------------------------------------------
package small_pkg is new work.array_adder_pkg
    generic map (array_size     => 3,
                 precision_size => 5
    );
package large_pkg is new work.array_adder_pkg
    generic map (array_size     => 15,
                 precision_size => 9
    );
use work.small_pkg.all;
use work.large_pkg.all;

library ieee;
use ieee.numeric_std.all;
--------------------------------------------------------------------------------
entity top_level is
end entity;
--------------------------------------------------------------------------------
architecture fpga of top_level is
    signal small_ina : work.small_pkg.array_type :=
                (to_signed(1, work.small_pkg.precision_size),
                 to_signed(2, work.small_pkg.precision_size),
                 to_signed(3, work.small_pkg.precision_size));
    signal small_inb : work.small_pkg.array_type :=
                (to_signed(4, work.small_pkg.precision_size),
                 to_signed(5, work.small_pkg.precision_size),
                 to_signed(6, work.small_pkg.precision_size));
    signal small_out : work.small_pkg.array_type;

    signal large_ina : work.large_pkg.array_type :=
                (to_signed(100, work.large_pkg.precision_size),
                 to_signed(110, work.large_pkg.precision_size),
                 to_signed(120, work.large_pkg.precision_size));
    signal large_inb : work.large_pkg.array_type :=
                (to_signed(50, work.large_pkg.precision_size),
                 to_signed(30, work.large_pkg.precision_size),
                 to_signed(80, work.large_pkg.precision_size));
    signal large_out : work.large_pkg.array_type;
begin
    small_array_adder: work.small_pkg.array_adder
        port map (a => small_ina,
                  b => small_inb,
                  c => small_out);

    large_array_adder: work.large_pkg.array_adder
        port map (a => large_ina,
                  b => large_inb,
                  c => large_out);
end architecture;

第一组无法编译,因为 array_adder 不知道 array_type 是什么。在 ModelSim 10.4b 中,我得到 (vcom-1136) Unknown identifier "array_type"。 这并不奇怪,因为我从未实例化过 array_adder_pkg

所以,我尝试在 array_adder.vhd 中实例化一个默认包,这大部分是相同的,但我将包含它以使其完整。 top_level.vhd 保持不变。

-- array_adder2.vhd
-- 
-- Computes and outputs the pointwise addition of two arrays.
library ieee;
use ieee.numeric_std.all;

package array_adder_pkg is
    generic (array_size     : integer;
             precision_size : integer
    );
    type array_type is array (0 to array_size-1) of signed(precision_size-1 downto 0);

    component array_adder is
        port (a   : in  array_type;
              b   : in  array_type;
              c   : out array_type
        );
    end component;
end package;
-----main code:-----------------------------------------------------------------
package default_array_adder_pkg is new work.array_adder_pkg
    generic map (array_size     => 3,
                 precision_size => 7
    );
use work.default_array_adder_pkg.all;

library ieee;
use ieee.numeric_std.all;
--------------------------------------------------------------------------------
entity array_adder is
    port (a : in  array_type;
          b : in  array_type;
          c : out array_type
    );
end entity;
--------------------------------------------------------------------------------
architecture fpga of array_adder is
begin
    comp: for i in 0 to array_size-1 generate
        c(i) <= a(i) + b(i);
    end generate;
end architecture;

现在两个文件都可以编译,但是当我尝试在 ModelSim 中模拟 top_level.vhd 时,我得到错误 Fatal: (vsim-3714) At array depth 1, array lengths do not match .左边是 15(0 到 14)。右边是 3(0 到 2)。 这似乎表明 ModelSim 在实例化大小与默认大小不同时遇到了问题。为了进一步测试这一点,我在 top_level.vhd 中删除了第二个包实例化和所有与之关联的代码(即所有 large_pkg 内容和与之关联的组件实例化)。这次我将为您省去大部分冗余代码。同样,这会按预期进行编译,但是当我尝试模拟它时,我得到了 Fatal: (vsim-3807) Types do not match between component and entity for port "a".

我真正能让它工作的唯一方法是在顶层设计中使用默认包并放弃两个不同大小的实例化,但这违背了通用设计的要点,因为我需要编写一个单独的设计每组参数规范的文件。

有没有其他我想念的方法?或者,这不是 VHDL 目前支持的东西吗?

最佳答案

您几乎完成了,但需要为包中的组件分配默认值。

然后 VHDL-2008 允许无约束数组,这可以在这里帮助您。

看这个例子:

library ieee;
use ieee.numeric_std.all;

package array_pkg is
    type signed_array is array (natural range <>) of signed;
end package;


use work.array_pkg.signed_array;

package array_adder_pkg is
    generic(
        array_size     : positive;
        precision_size : positive
    );

    subtype array_type is signed_array(0 to array_size-1)(precision_size-1 downto 0);

    component array_adder is
        generic(
            array_size     : positive := array_size;
            precision_size : positive := precision_size
        );
        port (
            a : in  signed_array(0 to array_size-1)(precision_size-1 downto 0);
            b : in  signed_array(0 to array_size-1)(precision_size-1 downto 0);
            c : out signed_array(0 to array_size-1)(precision_size-1 downto 0)
        );
    end component;
end package;


use work.array_pkg.signed_array;

entity array_adder is
    generic(
        array_size     : positive;
        precision_size : positive
    );
    port (
        a : in  signed_array(0 to array_size-1)(precision_size-1 downto 0);
        b : in  signed_array(0 to array_size-1)(precision_size-1 downto 0);
        c : out signed_array(0 to array_size-1)(precision_size-1 downto 0)
    );
end entity;

library ieee;

architecture fpga of array_adder is
    use ieee.numeric_std.all;
begin
    comp: for i in 0 to array_size-1 generate
        c(i) <= a(i) + b(i);
    end generate;
end architecture;


entity top_level is end entity;

package small_pkg is new work.array_adder_pkg
    generic map (array_size     => 3,
                 precision_size => 5
    );
package large_pkg is new work.array_adder_pkg
    generic map (array_size     => 3,
                 precision_size => 9
    );

library ieee;

architecture fpga of top_level is
    use ieee.numeric_std.all;

    signal small_ina : work.small_pkg.array_type :=
                (to_signed(1, work.small_pkg.precision_size),
                 to_signed(2, work.small_pkg.precision_size),
                 to_signed(3, work.small_pkg.precision_size));
    signal small_inb : work.small_pkg.array_type :=
                (to_signed(4, work.small_pkg.precision_size),
                 to_signed(5, work.small_pkg.precision_size),
                 to_signed(6, work.small_pkg.precision_size));
    signal small_out : work.small_pkg.array_type;

    signal large_ina : work.large_pkg.array_type :=
                (to_signed(100, work.large_pkg.precision_size),
                 to_signed(110, work.large_pkg.precision_size),
                 to_signed(120, work.large_pkg.precision_size));
    signal large_inb : work.large_pkg.array_type :=
                (to_signed(50, work.large_pkg.precision_size),
                 to_signed(30, work.large_pkg.precision_size),
                 to_signed(80, work.large_pkg.precision_size));
    signal large_out : work.large_pkg.array_type;
begin
    small_array_adder: work.small_pkg.array_adder
        port map (a => small_ina,
                  b => small_inb,
                  c => small_out);

    large_array_adder: work.large_pkg.array_adder
        port map (a => large_ina,
                  b => large_inb,
                  c => large_out);
end architecture;

编辑:我想补充一点,您还可以生成您的体系结构本地的专用包。这样它们就不会被编译到你的库中。示例:

entity top_level is end entity;

library ieee;

architecture fpga of top_level is
    use ieee.numeric_std.all;

    package small_pkg is new work.array_adder_pkg
        generic map (array_size     => 3,
                     precision_size => 5
        );
    package large_pkg is new work.array_adder_pkg
        generic map (array_size     => 3,
                     precision_size => 9
        );

    signal small_ina : small_pkg.array_type :=
                (to_signed(1, small_pkg.precision_size),
                 to_signed(2, small_pkg.precision_size),
                 to_signed(3, small_pkg.precision_size));
    signal small_inb : small_pkg.array_type :=
                (to_signed(4, small_pkg.precision_size),
                 to_signed(5, small_pkg.precision_size),
                 to_signed(6, small_pkg.precision_size));
    signal small_out : small_pkg.array_type;

    signal large_ina : large_pkg.array_type :=
                (to_signed(100, large_pkg.precision_size),
                 to_signed(110, large_pkg.precision_size),
                 to_signed(120, large_pkg.precision_size));
    signal large_inb : large_pkg.array_type :=
                (to_signed(50, large_pkg.precision_size),
                 to_signed(30, large_pkg.precision_size),
                 to_signed(80, large_pkg.precision_size));
    signal large_out : large_pkg.array_type;
begin
    small_array_adder: small_pkg.array_adder
        port map (a => small_ina,
                  b => small_inb,
                  c => small_out);

    large_array_adder: large_pkg.array_adder
        port map (a => large_ina,
                  b => large_inb,
                  c => large_out);
end architecture;

关于vhdl - 如何在 VHDL 中实例化通用设计的参数化版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50034305/

相关文章:

vhdl - VHDL中SLA算子的真实使用

ubuntu - 尝试在 Ubuntu 12.04LTS 上运行 Qsim 时出现 "bad option -readonly"错误

vhdl - 使用 VHDL 2008 通用类型功能创建伪动态类型

VHDL if 语句 - 文本附近的语法错误

VHDL : nested vs. 多个条件中的 If 语句

matlab - simulink中仿真和HDL代码生成的区别

vhdl - 在 VHDL 函数中生成随机值

process - VHDL中如何处理多个进程中的控制信号

来自不同进程的VHDL驱动信号

algorithm - 生成 nCk 个从 0 到 n-1 的数字组合