使用std_logic_vector数组作为端口类型,两个范围都使用泛型

Ale*_*amo 4 vhdl

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

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;
Run Code Online (Sandbox Code Playgroud)

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

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

array(natural range <>, natural range <>) of std_logic在包中定义类型工作 - 如在端口定义中没有给出错误 - 但实际使用它,如果它的定义方式似乎相当笨重.

是否有一些理智的方式来使用它?是否有一些简单的方法将N个单独的std_logic_vectors映射到这样定义的端口,同样对于实际的输出逻辑?

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

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

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

Ale*_*amo 7

这适用于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;
Run Code Online (Sandbox Code Playgroud)

它可以像这样使用:

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;
Run Code Online (Sandbox Code Playgroud)

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

不幸的是,我不知道如果没有带VHDL93的2d数组,是否有任何方法可以做任何类似的事情.

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

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;
Run Code Online (Sandbox Code Playgroud)

它可以像这样使用:

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;
Run Code Online (Sandbox Code Playgroud)


Pae*_*els 2

是的,这是可能的。

您对二维数组的尝试是好的,因为嵌套的一维数组需要内部维度的固定大小。因此,处理这样的二维数组的方法是编写一些函数和过程,将二维数组转换为嵌套的一维向量。

我在这里回答了一个类似的问题:
-在进程之外填充二维数组中的一行(VHDL)
-创建一个通用数组,其元素在 VHDL 中的宽度不断增加

这是我的矢量包

下面是 FIFO 接口多路复用器的示例,该多路复用器的数据宽度和输入计数都是可变的。它使用循环仲裁器来选择输入。

实体“PoC.bus.Stream.Mux”:

-- EMACS settings: -*-  tab-width: 2; indent-tabs-mode: t -*-
-- vim: tabstop=2:shiftwidth=2:noexpandtab
-- kate: tab-width 2; replace-tabs off; indent-width 2;
-- 
-- ============================================================================
-- Authors:           Patrick Lehmann
-- 
-- License:
-- ============================================================================
-- Copyright 2007-2015 Technische Universitaet Dresden - Germany
--                     Chair for VLSI-Design, Diagnostics and Architecture
-- 
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
-- 
--    http://www.apache.org/licenses/LICENSE-2.0
-- 
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- ============================================================================

library IEEE;
use     IEEE.STD_LOGIC_1164.all;
use     IEEE.NUMERIC_STD.all;

library PoC;
use     PoC.config.all;
use     PoC.utils.all;
use     PoC.vectors.all;


entity Stream_Mux is
  generic (
    PORTS            : POSITIVE                  := 2;
    DATA_BITS        : POSITIVE                  := 8;
    META_BITS        : NATURAL                   := 8;
    META_REV_BITS    : NATURAL                   := 2
  );                 
  port (             
    Clock            : IN  STD_LOGIC;
    Reset            : IN  STD_LOGIC;
    -- IN Ports      
    In_Valid         : IN  STD_LOGIC_VECTOR(PORTS - 1 downto 0);
    In_Data          : IN  T_SLM(PORTS - 1 downto 0, DATA_BITS - 1 downto 0);
    In_Meta          : IN  T_SLM(PORTS - 1 downto 0, META_BITS - 1 downto 0);
    In_Meta_rev      : OUT T_SLM(PORTS - 1 downto 0, META_REV_BITS - 1 downto 0);
    In_SOF           : IN  STD_LOGIC_VECTOR(PORTS - 1 downto 0);
    In_EOF           : IN  STD_LOGIC_VECTOR(PORTS - 1 downto 0);
    In_Ack           : OUT STD_LOGIC_VECTOR(PORTS - 1 downto 0);
    -- OUT Port      
    Out_Valid        : OUT STD_LOGIC;
    Out_Data         : OUT STD_LOGIC_VECTOR(DATA_BITS - 1 downto 0);
    Out_Meta         : OUT STD_LOGIC_VECTOR(META_BITS - 1 downto 0);
    Out_Meta_rev     : IN  STD_LOGIC_VECTOR(META_REV_BITS - 1 downto 0);
    Out_SOF          : OUT STD_LOGIC;
    Out_EOF          : OUT STD_LOGIC;
    Out_Ack          : IN  STD_LOGIC
  );
end;

architecture rtl OF Stream_Mux is
  attribute KEEP               : BOOLEAN;
  attribute FSM_ENCODING       : STRING;

  subtype T_CHANNEL_INDEX is NATURAL range 0 to PORTS - 1;

  type T_STATE is (ST_IDLE, ST_DATAFLOW);

  signal State                 : T_STATE          := ST_IDLE;
  signal NextState             : T_STATE;

  signal FSM_Dataflow_en       : STD_LOGIC;

  signal RequestVector         : STD_LOGIC_VECTOR(PORTS - 1 downto 0);
  signal RequestWithSelf       : STD_LOGIC;
  signal RequestWithoutSelf    : STD_LOGIC;

  signal RequestLeft           : UNSIGNED(PORTS - 1 downto 0);
  signal SelectLeft            : UNSIGNED(PORTS - 1 downto 0);
  signal SelectRight           : UNSIGNED(PORTS - 1 downto 0);

  signal ChannelPointer_en     : STD_LOGIC;
  signal ChannelPointer        : STD_LOGIC_VECTOR(PORTS - 1 downto 0);
  signal ChannelPointer_d      : STD_LOGIC_VECTOR(PORTS - 1 downto 0)     := to_slv(2 ** (PORTS - 1), PORTS);
  signal ChannelPointer_nxt    : STD_LOGIC_VECTOR(PORTS - 1 downto 0);
  signal ChannelPointer_bin    : UNSIGNED(log2ceilnz(PORTS) - 1 downto 0);

  signal idx                   : T_CHANNEL_INDEX;

  signal Out_EOF_i             : STD_LOGIC;

begin
  RequestVector       <= In_Valid AND In_SOF;
  RequestWithSelf     <= slv_or(RequestVector);
  RequestWithoutSelf  <= slv_or(RequestVector AND NOT ChannelPointer_d);

  process(Clock)
  begin
    if rising_edge(Clock) then
      if (Reset = '1') then
        State        <= ST_IDLE;
      else
        State        <= NextState;
      end if;
    end if;
  end process;

  process(State, RequestWithSelf, RequestWithoutSelf, Out_Ack, Out_EOF_i, ChannelPointer_d, ChannelPointer_nxt)
  begin
    NextState                 <= State;

    FSM_Dataflow_en           <= '0';

    ChannelPointer_en         <= '0';
    ChannelPointer            <= ChannelPointer_d;

    case State is
      when ST_IDLE =>
        if (RequestWithSelf = '1') then
          ChannelPointer_en    <= '1';

          NextState            <= ST_DATAFLOW;
        end if;

      when ST_DATAFLOW =>
        FSM_Dataflow_en        <= '1';

        if ((Out_Ack   AND Out_EOF_i) = '1') then
          if (RequestWithoutSelf = '0') then
            NextState          <= ST_IDLE;
          else
            ChannelPointer_en  <= '1';
          end if;
        end if;
    end case;
  end process;

  process(Clock)
  begin
    if rising_edge(Clock) then
      if (Reset = '1') then
        ChannelPointer_d    <= to_slv(2 ** (PORTS - 1), PORTS);
      elsif (ChannelPointer_en = '1') then
        ChannelPointer_d    <= ChannelPointer_nxt;
      end if;
    end if;
  end process;

  RequestLeft         <= (NOT ((unsigned(ChannelPointer_d) - 1) OR unsigned(ChannelPointer_d))) AND unsigned(RequestVector);
  SelectLeft          <= (unsigned(NOT RequestLeft) + 1)    AND RequestLeft;
  SelectRight         <= (unsigned(NOT RequestVector) + 1)  AND unsigned(RequestVector);
  ChannelPointer_nxt  <= std_logic_vector(ite((RequestLeft = (RequestLeft'range => '0')), SelectRight, SelectLeft));

  ChannelPointer_bin  <= onehot2bin(ChannelPointer);
  idx                 <= to_integer(ChannelPointer_bin);

  Out_Data            <= get_row(In_Data, idx);
  Out_Meta            <= get_row(In_Meta, idx);

  Out_SOF             <= In_SOF(to_integer(ChannelPointer_bin));
  Out_EOF_i           <= In_EOF(to_integer(ChannelPointer_bin));
  Out_Valid           <= In_Valid(to_integer(ChannelPointer_bin)) and FSM_Dataflow_en;
  Out_EOF             <= Out_EOF_i;

  In_Ack              <= (In_Ack  'range => (Out_Ack   and FSM_Dataflow_en)) AND ChannelPointer;

  genMetaReverse_0 : if (META_REV_BITS = 0) generate
    In_Meta_rev    <= (others => (others => '0'));
  end generate;
  genMetaReverse_1 : if (META_REV_BITS > 0) generate
    signal Temp_Meta_rev : T_SLM(PORTS - 1 downto 0, META_REV_BITS - 1 downto 0)    := (others => (others => 'Z'));
  begin
    genAssign : for i in 0 to PORTS - 1 generate
      signal row  : STD_LOGIC_VECTOR(META_REV_BITS - 1 downto 0);
    begin
      row    <= Out_Meta_rev AND (row'range => ChannelPointer(I));
      assign_row(Temp_Meta_rev, row, i);
    end generate;
    In_Meta_rev    <= Temp_Meta_rev;
  end generate;
end architecture;
Run Code Online (Sandbox Code Playgroud)