Using array of std_logic_vector as a port type, with both ranges using a generic

后端 未结 2 1657
南笙
南笙 2020-12-28 11:11

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 i

2条回答
  •  时光说笑
    2020-12-28 11:40

    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;
    

    And it can be used like this:

    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;
    

    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.

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

    Edit: 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;
    

    And it can be used like this:

    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;
    

提交回复
热议问题