Search code examples
vhdlquartus

How to instantiate multiple components with variable size ports in vhdl?


I want to retiteratively elaborate a couple of components using for generate statements, these components have variable size ports and I don't have an idea of how assign these variable size ports to signals.

I'm using a package with this declaration:

library ieee;
use ieee.std_logic_1164.all;

PACKAGE Arrays_package IS
    type Generic_ARRAY_type is array (integer range <>) of std_logic_vector;
END Arrays_package;

The components are Pre_pre_buffer_conv and Pre_buffer_conv in the code below.

How I can to declare the signal xdataout_preprebuffer?

library ieee;
use ieee.std_logic_1164.all;
use work.Arrays_package.all;

entity Naive_RNC_problem is

    generic(
                no_col_imag     : integer := 28;
                no_bits         : integer := 9; 
                no_bits_fraction : natural := 8;
                no_col_filt     : integer := 3 
    );  

    port 
    (
    CLOCK_50   : in std_logic;
    KEY        : in std_logic_vector(3 downto 0);
    SW         : in std_logic_vector(17 downto 0);

    xdataout_pre_buffer_conv : out Generic_ARRAY_type(no_col_filt*no_col_filt-1 downto 0)((no_bits-1) downto 0)

    );

end entity;

architecture rtl of Naive_RNC_problem is

component Image_ROM IS
    PORT
    (
        address     : IN STD_LOGIC_VECTOR (9 DOWNTO 0);
        clock       : IN STD_LOGIC  := '1';
        q       : OUT STD_LOGIC_VECTOR (8 DOWNTO 0)
    );
END component;

component generic_mask_nxn_v2 is
    generic(
                no_col_imag     : integer := 28;
                no_col_filt     : integer := 3;
                stride          : integer := 1;
                no_bits         : integer := 10 
    );  

    Port (
            -- ENTRADAS ------------------------
                iclk, irst    : in std_logic;
                ien               : in std_logic;
                idatain           : in std_logic_vector (no_bits-1 downto 0);
                index         : in integer;
                iindex_ctrl   : in std_logic_vector(7 downto 0);
            -- SALIDAS -------------------------
               odataout   : out Generic_ARRAY_type(no_col_filt-1 downto 0)((no_col_filt*no_bits-1) downto 0) ;
                omasken     : out std_logic

          );
end component;

component Pre_pre_buffer_conv is
    generic 
    (
        no_col_filt     : integer := 3;
        no_bits         : integer := 10 
    );

    port 
    (           
    -- ENTRADAS ------------------------
        iclk, irst    : in std_logic;
        ien               : in std_logic;
        index         : in integer;
        iindex_ctrl   : in std_logic_vector(7 downto 0);
        idatain           : in  Generic_ARRAY_type(no_col_filt-1 downto 0)(no_col_filt*no_bits-1 downto 0);
    -- SALIDAS -------------------------
        odataout          : out Generic_ARRAY_type(no_col_filt-1 downto 0)(no_col_filt*no_bits-1 downto 0)  
    );
end component;

component Pre_buffer_conv is
    generic 
    (
        no_col_filt     : integer := 3;
        no_bits         : integer := 9 
    );

    port 
    (           
    -- ENTRADAS ------------------------
        iclk, irst    : in std_logic;
        ien               : in std_logic;
        idatain           : in Generic_ARRAY_type(no_col_filt-1 downto 0)(no_col_filt*no_bits-1 downto 0);
        isel_row         : in std_logic_vector(3 downto 0);
        isel_col         : in std_logic_vector(3 downto 0);
    -- SALIDAS -------------------------
        odataout          : out std_logic_vector (no_bits-1 downto 0)
    );
end component;

component Top_Control_prepre_buffer is
    port (-- ENTRADAS -----------
            iclk, ireset     : in std_logic;

            iStart          : in std_logic;
            imasken_conv    : in std_logic;
            ifin_convolvers   : in std_logic;
            ifin_interfaz_Conv_pool : in std_logic;

            -- SALIDAS -----------------------
            oidle           : out std_logic;
            orst            : out std_logic;
            oen_line_buffer_conv : out std_logic;
            odir_imagen     : out std_logic_Vector(15 downto 0);
            ocarga_prepre_buffer     : out std_logic;
            ocarga_pre_buffer_conv   : out std_logic;
            oind_pre_buffers_conv : out std_logic_Vector(15 downto 0);
            oStart_convolver         : out std_logic;
            oinicia_interfaz_Conv_pool : out std_logic
    );      
end component;

--=======================================================
--  Signal  declarations
--=======================================================

signal xRST            : std_logic;
signal xrst_ctrl       : std_logic;
signal xStart          : std_logic;
signal xclk_50 : std_logic;
signal xaddress_memoria_MNIST_ROM, xaddress_MNIST_PORTA: STD_LOGIC_VECTOR (9 DOWNTO 0);
signal xdataout_MNIST_ROM    : STD_LOGIC_VECTOR (8 DOWNTO 0);
signal xaddress_memoria_MNIST_ctrl : STD_LOGIC_VECTOR (15 DOWNTO 0);
signal  xrst_buffer_conv      :  std_logic;
signal  xdatain_buffer  :  std_logic_vector (no_bits-1 downto 0);
signal   xdataout_buffer  : Generic_ARRAY_type(no_col_filt-1 downto 0)((no_col_filt*no_bits-1) downto 0) ;      
signal  xmasken_buffer    :  std_logic;
signal   xen_line_buffer_conv   : std_logic;        
signal xcarga_prepre_buffer : std_logic;
signal xsel_row_pre_buffer : std_logic_vector(3 downto 0);
signal xsel_col_pre_buffer : std_logic_vector(3 downto 0); 
signal xstart_fill_buffers_conv : std_logic;
signal xcarga_pre_buffer_conv : std_logic;
signal xind_pre_buffers_conv_ctrl : std_logic_vector(15 downto 0);
signal xind_pre_buffers_conv : std_logic_vector(7 downto 0);
signal xrst_contol_prepre_buffer : std_logic;
signal xfin_convolver, xfin_Interfaz_conv_pool : std_logic;

    --  how to declare this signal? ---------------------------
type my_type1 is array (no_col_filt-1 downto 0) of std_logic_vector((no_col_filt*no_bits-1) downto 0);
type my_type2 is array(no_col_filt*no_col_filt-1 downto 0) of my_type1;
signal xdataout_preprebuffer : my_type2;
    ----
--=======================================================
--  Structural coding
--=======================================================


begin

xRST <= not KEY(0);
xStart <= not KEY(1);

-- RELOJES ===============================================

    xclk_50 <= CLOCK_50;

-- MEMORIA IMAGEN MNIST ===============================================

    MemoriaROM_MNIST : Image_ROM port map (xaddress_memoria_MNIST_ROM, xclk_50, xdataout_MNIST_ROM);

    xaddress_memoria_MNIST_ROM <= xaddress_memoria_MNIST_Ctrl(9 downto 0); 


-- Line Buffer convolucion ==============================================

    Buffer_mask : generic_mask_nxn_v2 generic map ( no_col_imag => no_col_imag,
                                                              no_col_filt => no_col_filt,
                                                              stride      => 1,
                                                              no_bits     => no_bits
                                                                )

                                            port map (-- ENTRADAS ------------------------
                                                         xclk_50, xrst_buffer_conv,
                                                         xen_line_buffer_conv, xdatain_buffer,  
                                                         0,
                                                         (others => '0'), 
                                                        -- SALIDAS -------------------------
                                                         xdataout_buffer, -- this is a variable size port (no problem here)
                                                         xmasken_buffer 
                                                            );

    xrst_buffer_conv <=  xRST or xrst_ctrl ;--(not xRST) or
    xdatain_buffer <= xdataout_MNIST_ROM;

    -- Control Prepre Buffer convolucion ==============================================

    Prepre_buffer_ctrl : Top_Control_prepre_buffer port map (-- ENTRADAS -----------------------
                                                                xclk_50, xrst_contol_prepre_buffer, 
                                                                xStart,
                                                                xmasken_buffer,
                                                                xfin_convolver,
                                                                xfin_Interfaz_conv_pool, 
                                                              -- SALIDAS -----------------------
                                                              open, xrst_ctrl, 
                                                              xen_line_buffer_conv, 
                                                              xaddress_memoria_MNIST_ctrl,                                                        
                                                              xcarga_prepre_buffer, xcarga_pre_buffer_conv, xind_pre_buffers_conv_ctrl,
                                                              open,
                                                              open

                                                                );
    xrst_contol_prepre_buffer <= xRST;
    xfin_convolver <= '1';  
    xfin_Interfaz_conv_pool <= '1';

-- Pre pre Buffer convolucion ===========================================

    pre_pre_buffers_conV : for i in 0 to (no_col_filt*no_col_filt-1) generate
        pre_pre_buffer_conV_cmp : Pre_pre_buffer_conv generic map (no_col_filt => no_col_filt,
                                                                            no_bits     => no_bits 
                                                                            )
                                                                     port map (-- ENTRADAS -----------------------
                                                                        xclk_50, xrst_buffer_conv,
                                                                        xcarga_prepre_buffer,
                                                                        i,
                                                                        xind_pre_buffers_conv,
                                                                        xdataout_buffer, -- this is a variable size port (no problem here)
                                                                        -- SALIDAS -----------------------
                                                                        xdataout_preprebuffer(i) -- this is a variable size port (ERROR HERE)
                                                                  );            

    end generate;


-- Pre Buffer convolucion ==============================================

    pre_buffers_conV : for i in 0 to (no_col_filt*no_col_filt-1) generate
        pre_buffer_conV_cmp : Pre_buffer_conv generic map (no_col_filt => no_col_filt,
                                                                            no_bits     => no_bits 
                                                                            )
                                                          port map (-- ENTRADAS -----------------------
                                                                        xclk_50, xrst_buffer_conv,
                                                                        xcarga_pre_buffer_conv,
                                                                        xdataout_preprebuffer(i),  -- this is a variable size port (ERROR HERE)
                                                                        xsel_row_pre_buffer,
                                                                        xsel_col_pre_buffer,
                                                                        -- SALIDAS -----------------------
                                                                        xdataout_pre_buffer_conv(i)  
                                                                  );    
    end generate;   

   xind_pre_buffers_conv <= xind_pre_buffers_conv_ctrl(7 downto 0); 
    xsel_row_pre_buffer <= (others => '0');
    xsel_col_pre_buffer <= (others => '0');     


end rtl;

The errors thrown by analysis & elaboration stage were:

Error (10381): VHDL Type Mismatch error at Naive_RNC_problem.vhd(228): indexed name returns a value whose type does not match "Generic_ARRAY_type", the type of the target expression

Error: Quartus Prime Analysis & Elaboration was unsuccessful. 1 error, 0 warnings

I believe that the signal xdataout_preprebuffer has to be declared as 2d array signal, but I don't know how to accomplish that.


Solution

  • Two changes.

    An added type in the package:

    library ieee;
    use ieee.std_logic_1164.all;
    
    package arrays_package is
        type generic_array_type is array (integer range <>) of std_logic_vector;
        type generic_array_of_generic_type is   -- ADDED type
                                array (integer range <>) of generic_array_type;
    end package arrays_package;
    

    and the signal declaration:

    signal xdataout_preprebuffer:   generic_array_of_generic_type  -- type mark
                                -- index subtype:
                                        (no_col_filt * no_bits - 1 downto 0) 
                                -- element constraint (generic_array_type):
                                    -- index subtype:
                                        (no_col_filt - 1 downto 0)
                                    --  element index constraint (std_logic_vector):
                                        (no_col_filt * no_bits - 1 downto 0);
    

    After which your code will analyze (elaboration and simulation requires the entities to which all those components are bound during elaboration. With entity declarations and dummy architecture bodies for your components your code elaborates and simulates (showing associations and assignments don't have bounds errors).

    The added type uses the -2008 unbounded array definition as does the original (See IEEE Std 1076-2008 5.3.2 Array types, 5.3.2.1 General, 5.3.2.2 Index constraints and discrete ranges, 6.3 Subtype declarations).

    What we have is an unbound one-dimensional array type (generic_array_of_generic_type) whose element type (unbounded one-dimensional type generic_array_type) has it's own element unbounded one-dimensional array type (std_logic_vector). The index constraints for the unbounded array types are provided during object declaration.