Creating a generic array whose elements have increasing width in VHDL

后端 未结 2 1059
情深已故
情深已故 2020-12-21 12:37

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)

相关标签:
2条回答
  • 2020-12-21 12:45

    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.

    0 讨论(0)
  • 2020-12-21 12:48

    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 :).

    0 讨论(0)
提交回复
热议问题