0
\$\begingroup\$

In VHDL we can constrain the length of an std_logic_vector in port map as follows:

entity fdct_coeff_rom is
  generic (
    data_len : integer range 1 to 8
  );
  port (
    i_clk    : in std_logic;
    i_rst_n  : in std_logic;
    i_data   : in std_logic_vector(data_len-1 downto 0);
    i_we     : in std_logic;
    i_re     : in std_logic;
    o_data   : out std_logic_vector(data_len-1 downto 0)
  );

I have an array of std_logic_vectors in the port map. The ports are 8 std_logic_vectors, the length of which can change. Now I am not sure how to use generic to change the length of each std_logic_vector. Is this possible?

entity fdct_coeff_rom is
  generic (
    data_len : integer range 1 to 8
  );
  port (
    i_clk    : in std_logic;
    i_rst_n  : in std_logic;
    i_data   : in data_arr_t; -- 8 std_logic_vector, each data_len-1 downto 0
    i_we     : in std_logic;
    i_re     : in std_logic;
    o_data   : out data_arr_t  -- 8 std_logic_vector, each data_len-1 downto 0
  );

The data_arry_t is defined in a package as an array of std_logic_vector. I am not sure how I can specify the size of the std_logic_vector using a generic such that, each instance of the module has a different length of the std_logic_vector.

Please note that the module I am dealing with is complex, the example in this question is just to illustrate what I am trying to do.

Now, if this is not at all possible in VHDL, can this be done in SystemVerilog?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

VHDL 2008 allows all dimensions to be unconstrained when a type is defined. So, first create a package with the type:

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

package my_pkg is
  type slv_array_t is array(natural range <>) of std_logic_vector;
end package;

Now define the entity:

-- use VHDL-2008

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

library work;
use work.my_pkg.all;

entity my_entity is
  generic(
    N : natural := 8;
    WW : natural := 16
  );
  port (
    i_clk   : in std_logic;
    i_data  : in slv_array_t(0 to N-1)(WW-1 downto 0);
    o_data  : out slv_array_t(0 to N-1)(WW-1 downto 0)
  );
end entity;

architecture rtl of my_entity is

begin

  process(i_clk)
  begin
    if rising_edge(i_clk) then
      o_data <= i_data;
    end if;
  end process;

end architecture;

Take note of how the 2D array is being constrained in both dimensions, inner and outer.

i_data  : in slv_array_t(0 to N-1)(WW-1 downto 0);
o_data  : out slv_array_t(0 to N-1)(WW-1 downto 0)

This must be compiled with VHDL-2008 enabled. This will synthesize in Intel Quartus Prime, Xilinx Vivado and also Microsemi Libero SoC as long as the VHDL-2008 setting is specifie.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ In my_pkg composite array type slv_array_t has a single index, it's not a multidimensional array type while it's element type happens to be a composite array type with a single index. An object of type slv_array_t is not a 2D array. An indexed name specifies a specific element, a slice name a range of elements. A multidimensional (2D) array type can't be sliced. You can have an indexed name whose prefix is an indexed name and designates an element of a std_logic_vector and is a subelement of a slv_array_t. See Std 1076-2008 5.3.2 Array types and 8. Names. \$\endgroup\$ Commented Aug 12, 2022 at 20:27
  • 1
    \$\begingroup\$ I do not understand what you said, is there an example of what you are referring to? \$\endgroup\$
    – quantum231
    Commented Aug 13, 2022 at 13:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.