2

Is it possible to create an array whose elements have increasing width. For example lets say X is an array that has 10 elements;

X(0) is std_logic_vector(3 downto 0)
X(1) is std_logic_vector(4 downto 0)
...
X(9) is std_logic_vector(12 downto 0)

0

2 Answers 2

3

There is no solution to solve your question, as you requested, but additionally to Morten's answer I'll try to provide another work around solutions.

I'll use your example: X is an array of 10 elements each with increasing length from 4 to 13.

My solution puts all the vectors into one 1-dimensional vector and eases the access to the bits with functions. The following lines try to present how the bits are organized.

--bit 84              bit 19      bit 13       bit 8       bit 4       bit 0
[X(9)(12..0)]...[X(4)(7..0)][X(3)(6..0)][X(2)(5..0)][X(1)(4..0)][X(0)(3..0)]

Step-by-Step:

  1. Create a vector of INTEGERs(T_INTVEC) or more constrained a vector of NATURALs (T_NATVEC).

    type T_NATVEC is array (NATURAL range <>) of NATURAL;
    
  2. Create a instance of this type and fill it with your array lengths.

    constant MY_BITS : T_NATVEC := (
      0 => 4,
      1 => 5,
      [...]
      9 => 13
    );
    

    Or use a function to calculate it:

    function generateVectorLengths return T_NATVEC is
      constant Count        : NATURAL              := 10;
      constant Startlength  : NATURAL              := 4;
      variable Result : T_NATVEC(0 to Count - 1);
    begin
      for i in 0 to Count - 1 loop
        Result(i) := StartLength + i;
      end loop;
      return Result;
    end function;
    
    constant MY_BITS : T_NATVEC := generateVectorLengths;
    
  3. Create some helper function to:

    • sum all vector lengths

      function isum(vec : T_NATVEC) return NATURAL is
        variable Result : NATURAL := 0;
      begin
        for i in vec'range loop
          Result := Result + vec(i);
        end loop;
        return Result;
      end function;
      
    • get the upper bound of an embedded vector

      function low(VectorBits : T_POSVEC; index : NATURAL) return NATURAL is
        variable pos : NATURAL := 0;
      begin
        for i in VectorBits'low to index - 1 loop
          pos := pos + VectorBits(i);
        end loop;
        return pos;
      end function;
      
    • get the lower bound of an embedded vector

      function high(VectorBits : T_POSVEC; index : NATURAL) return NATURAL is
        variable pos : NATURAL := 0;
      begin
        for i in lenvec'low to index loop
          pos := pos + VectorBits(i);
        end loop;
        return pos - 1;
      end function;
      
    • get an entire embedded vector

      function getSubvector(vector : STD_LOGIC_VECTOR; VectorBits : T_POSVEC; index : NATURAL) return STD_LOGIC_VECTOR is
      begin
        return vector(high(VectorBit, index) downto low(VectorBit, index));
      end function;
      
    • assign a sub vector to the big vector

       procedure assignSubVector(signal slm : out T_SLM; slv : STD_LOGIC_VECTOR; constant VectorBits : T_POSVEC; constant index : NATURAL) is
       begin
          for i in slv'range loop
            slm(high(VectorBit, index) downto low(VectorBit, index)) <= slv;
          end loop;
       end procedure;
      
  4. So now you can use this functions to create an 1-dimensional vector like this:

    signal Vector_1 : STD_LOGIC_VECTOR(isum(MY_BITS) - 1 downto 0)  := (others => 'Z');
    -- initialize this vector with 'Z'; this is needed for simulation!
    
  5. And you can use this vector with high and low function or with the forlast helper function (see function getSubvector).

    signal Vector_X3 : STD_LOGIC_VECTOR(MY_BITS(3) - 1 downto 0);
    ...
    Vector_X3 <= getSubvector(My_Vector, MY_BITS, 3);
    
  6. Finally, you can use assignSubVector to assign vectors to the big one:

    signal Vector_X4 : STD_LOGIC_VECTOR(MY_BITS(4) - 1 downto 0);
    ...
    assignSubvector(My_Vector, Vector_X4, MY_BITS, 4);
    

If you find these bit moving and twisting function for vectors and matrixes interesting, here is the complete file :).

Sign up to request clarification or add additional context in comments.

3 Comments

Nice framework, but quite some additional weight one has to carry around. Does your solution cause any problems with synthesis?
There is more :) We are working on a release on github. These functions are fully tested for simulation as well as synthesis and for different toolchains (quartus, xst, vivado, questasim,ghdl). All functions are just wiring descriptions.
Yes, you have nice general purpose package. That what I meant. But I will implement some spesific form consists of 1 or 2 functions.
2

No, all elements in an VHDL array are the same, thus will have same width (length) if the elements are std_logic_vector.

But in synthesis, if you declare the elements with maximum required length, and then simply don't use the upper bits on some of the elements, then any decent synthesis tool will reduce the actual size in the implementation.

If your question is related to simulation only, then you can declare an array of access types (pointers) to std_logic_vector, and the std_logic_vectors pointed to can then have different length.

2 Comments

Yes, I know that option. But I don't like "you never used that signal I trimmed for you" type warnings. I mean if there is a solution to make it with procedure or something like that.
A procedure/function wouldn't help you - ultimately, you'd need a signal/whatever to assign your data to, and there's no way to have a two-dimensional array where one of the dimensions varies within the array.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.