使用 std_logic_vector 数组作为端口类型,两个范围都使用泛型 [英] Using array of std_logic_vector as a port type, with both ranges using a generic

查看:29
本文介绍了使用 std_logic_vector 数组作为端口类型,两个范围都使用泛型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以创建一个实体,其端口是一个 std_logic_vectors 数组,数组的大小和 std_logic_vector 都来自泛型?IE.是否可以创建例如.一个总线多路复用器的总线宽度和总线数量都可以配置?

Is it possible to create an entity with a port that is an array of std_logic_vectors, with both the size of the array and the std_logic_vector coming from generics? Ie. is it possible to create eg. a bus multiplexer with both the bus width and bus count configurable?

entity bus_multiplexer is
        generic (bus_width : positive := 8;
                sel_width : positive := 2);
        port (  i : in array(integer range 2**sel_width - 1 downto 0) of std_logic_vector(bus_width - 1 downto 0);
                sel : in std_logic_vector(sel_width - 1 downto 0);
                o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer;

architecture dataflow of bus_multiplexer is
begin
        o <= i(to_integer(unsigned(sel)));
end dataflow;

上面的好像不行,因为数组类型需要单独定义.在端口之前定义类型也不起作用,因为它期望实体定义在它之后结束.在端口定义之后定义它不起作用,因为它会在此之前使用.在包中定义它不起作用,因为类型定义似乎不喜欢在基本类型"中有不受约束的范围.

The above doesn't seem to work because the array type needs to be defined separately. Defining the type before the port also does not work, as then it expects the entity definition to end after it. Defining it after the port definition doesn't work since it'd be used before that. Defining it in a package doesn't work because the type definition doesn't seem to like having an unconstrained range in the "base type".

是否可以在 VHDL-93 中以某种方式执行此操作?(VHDL-2008 怎么样?)

Is it possible to somehow do this in VHDL-93? (What about VHDL-2008?)

在包中将类型定义为 std_logic 的 array(natural range <>, natural range <>) 有效 - 就像在端口定义中一样不会给出错误 - 但是如果以这种方式定义,实际上使用它似乎很笨拙.

Defining the type as array(natural range <>, natural range <>) of std_logic in the package works - as in the port definition doesn't give an error - but actually using it if it's defined that way seems to be quite unwieldy.

有没有像这样使用它的一些理智的方法?是否有一些简单的方法可以将 N 个单独的 std_logic_vectors 映射到一个这样定义的端口,对于实际的输出逻辑也是如此?

Is there some sane way to use it like this? Is there some simple way to map N separate std_logic_vectors to a port defined like that, and likewise for the actual output logic?

我尝试了原始和 o <= i(to_integer(unsigned(sel)), bus_width - 1 downto 0),但都没有奏效.我知道我可以一次做一点,但我更喜欢更简单的东西.虽然逐位方法对于内部实现可能没问题,但我当然不想每次使用组件时都必须为端口映射这样做......

I tried the original and o <= i(to_integer(unsigned(sel)), bus_width - 1 downto 0), but neither worked. I know I could do it one bit at a time, but I'd prefer something simpler. And while the bit-by-bit -approach might be okay for the internal implementation, I certainly wouldn't want to have to do that for the port mapping every time I use the component...

是否有一些理智的(-ish)方法来做到这一点?

Is there some sane(-ish) way to do this?

(附录:我知道有一些类似的问题,但其中大多数都没有处理来自泛型的两个范围的情况,而是使用包中的类型定义来解决的.那个做了谈论两个通用维度显然不需要来自不同 std_logic_vectors 的输入,最终使用了std_logic 的二维数组"方法,这对我不起作用(至少没有进一步说明如何使用它而没有失去理智))

推荐答案

这适用于 VHDL2008:

This works with VHDL2008:

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

package bus_multiplexer_pkg is
        type bus_array is array(natural range <>) of std_logic_vector;
end package;

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

entity bus_multiplexer is
        generic (bus_width : positive := 8;
                sel_width : positive := 2);
        port (  i : in bus_array(2**sel_width - 1 downto 0)(bus_width - 1 downto 0);
                sel : in std_logic_vector(sel_width - 1 downto 0);
                o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer;

architecture dataflow of bus_multiplexer is
begin
        o <= i(to_integer(unsigned(sel)));
end dataflow;

它可以这样使用:

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

entity bus_multiplexer_4 is
        generic (bus_width : positive := 8);
        port (  bus0, bus1, bus2, bus3 : in std_logic_vector(bus_width - 1 downto 0);
                sel : in std_logic_vector(1 downto 0);
                o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer_4;

architecture structural of bus_multiplexer_4 is
        signal i : bus_array(3 downto 0)(bus_width - 1 downto 0);
begin
        i <= (0 => bus0, 1 => bus1, 2 => bus2, 3 => bus3);
        u: entity bus_multiplexer generic map (bus_width => bus_width, sel_width => 2) port map (i => i, sel => sel, o => o);
end;

但是,它不适用于 VHDL93,因为如问题所述,您不能在类型定义中不受约束地保留 std_logic_vector.

It doesn't work with VHDL93, however, because you can't leave the std_logic_vector unconstrained in the type definition, as stated in the question.

不幸的是,我不知道是否有任何方法可以在没有 VHDL93 的二维数组的情况下做类似的事情.

Unfortunately, I don't know if there's any way to do anything similar without 2d arrays with VHDL93.

Paebbels 的回答显示了如何使用 2d 数组在 VHDL93 中执行此操作,并使用自定义程序使其易于管理.由于他的例子很大,这里也有一个相同概念的最小例子:

Paebbels's answer shows how to do this in VHDL93 by using 2d arrays, with custom procedures to make it manageable. Since his example is quite big, here's also a minimal example of the same concept:

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

package bus_multiplexer_pkg is
        type bus_array is array(natural range <>, natural range <>) of std_logic;

        procedure slm_row_from_slv(signal slm : out bus_array; constant row : natural; signal slv : in std_logic_vector);
        procedure slv_from_slm_row(signal slv : out std_logic_vector; signal slm : in bus_array; constant row : natural);
end package;

package body bus_multiplexer_pkg is
        procedure slm_row_from_slv(signal slm : out bus_array; constant row : natural; signal slv : in std_logic_vector) is
        begin
                for i in slv'range loop
                        slm(row, i) <= slv(i);
                end loop;
        end procedure;

        procedure slv_from_slm_row(signal slv : out std_logic_vector; signal slm : in bus_array; constant row : natural) is
        begin
                for i in slv'range loop
                        slv(i) <= slm(row, i);
                end loop;
        end procedure;
end package body;

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

entity bus_multiplexer is
        generic (bus_width : positive := 8;
                sel_width : positive := 2);
        port (  i : in bus_array(2**sel_width - 1 downto 0, bus_width - 1 downto 0);
                sel : in std_logic_vector(sel_width - 1 downto 0);
                o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer;

architecture dataflow of bus_multiplexer is
begin
        slv_from_slm_row(o, i, to_integer(unsigned(sel)));
end dataflow;

它可以这样使用:

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

entity bus_multiplexer_4 is
        generic (bus_width : positive := 8);
        port (  bus0, bus1, bus2, bus3 : in std_logic_vector(bus_width - 1 downto 0);
                sel : in std_logic_vector(1 downto 0);
                o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer_4;

architecture structural of bus_multiplexer_4 is
        signal i : bus_array(3 downto 0, bus_width - 1 downto 0);
begin
        slm_row_from_slv(i, 0, bus0);
        slm_row_from_slv(i, 1, bus1);
        slm_row_from_slv(i, 2, bus2);
        slm_row_from_slv(i, 3, bus3);
        u: entity bus_multiplexer generic map (bus_width => bus_width, sel_width => 2) port map (i => i, sel => sel, o => o);
end;

这篇关于使用 std_logic_vector 数组作为端口类型,两个范围都使用泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆