Luis
Luis

Reputation: 17

How would I create a function to convert from an integer to std_logic vector in VHDL?

I am seeking help as I am learning this language construct.

Here is what I have:

function int_slv(val,width: integer) return std_logic_vector is
variable R: std_logic_vector(0 to width-1):=(others=>'0')
variable b:integer:= width;

begin 
   if (b>32) then
      b=32;
   else
      assert 2**bits >val report
      "value too big for std_logic_vector"
      severity warning
   end if;

for i in 0 to b-1 loop
 if val ((val/(2**i)) MOD 2 = 1) then
      R(i)='1';
 end if;
end loop;

return(R);
end int_slv;

Upvotes: 0

Views: 1606

Answers (2)

PlayDough
PlayDough

Reputation: 1138

As @user1155120 has already indicated, the VHDL-2008 package numeric_std_unsigned has a builtin to_stdlogicvector. And @user1155120 already pointed out the to_signed and to_unsigned in numeric_std are available as well.

So, to expand on the previous answer, you can do:

constant C : integer := -6817563;
constant C_VEC : std_logic_vector(31 downto 0) := std_logic_vector(to_signed(c, 32));

And this mechanism will accept the full range of integer. You can also use to_unsigned, but this is limited to the range of natural.

Upvotes: 0

user1155120
user1155120

Reputation:

In addition to 5 syntax errors, one wrong identifier and a modulo reduction expressions expressed as an element of an array as well as several sets of redundant parentheses, your modified code:

library ieee;
use ieee.std_logic_1164.all;

package int2bv_pkg is
    function int_slv (val, width: integer) return std_logic_vector;
end package;
package body int2bv_pkg is
    function int_slv (val, width: integer) return std_logic_vector is
        variable R: std_logic_vector(0 to width-1):=(others=>'0'); -- added ';'
        variable b:integer:= width;
    begin  
        if b > 32 then
            b := 32;   -- ":=" is used for  variable assignment 
        else
            assert 2 ** width > val report  -- width not bits
            "value too big for std_logic_vector"
            severity warning; -- missing semicolon at the end of assertion
        end if;

        for i in 0 to b - 1 loop
            if val/2 ** i MOD 2 = 1 then -- not val (...)
                R(i) := '1';  -- ":=" variable assign.
            end if;
        end loop;
        return R;  -- parentheses not needed
    end int_slv;
end package body int2bv_pkg;

analyzes (compiles). The exponentiation operator "**" is the highest priority, the division operators "/" and "mod" are the same priority and executed in the order they are found (left to right). It's likely worthwhile learning VHDL operator precedence.

You were using "=" for variable assignment when you should have been using ":=" in two places, you were missing two semicolons and were using the identifier bits (which isn't declared in your function) where apparently you meant width.

The modified example analyzes, and hasn't been tested absent a Minimal, Complete and Verifiable example in the question.

Note that a package body is a design unit as is a package declaration. There are various other places in other design units you can introduce a function body.

You could also note the 2 ** 31 is outside the guaranteed range of an integer in VHDL equal to 2147483648, while the INTEGER value range guaranteed to be from -2147483647 to +2147483647 at a minimum.

This implies that were ever you are using a value that derived from an expression equivalent to 2 ** 31 you can incur a range error during execution (either at elaboration or during simulation).

This pretty much says you need a VHDL implementation with a larger INTEGER value range or you need to rethink what you're doing.

As a matter of course there are integer to unsigned and integer to signed functions found in package numeric_std in library IEEE. The result of such can be type converted to std_logic_vector, and the source code can make great learning aids on how to wend through the limitations VHDL imposes. These to_signed or to_unsigned functions would be capable of dealing with the maximum value an INTEGER can hold and specify the length of the resulting array type while providing zero or sign filling for array lengths greater than the INTEGER's binary value. That utility extends to clipping using length as well.

VHDL -2008 package numeric_std_unsigned contains a function To_StdLogicVector that does what your int_slv function is intended to do although limited to a NATURAL range for the integer type input.

Upvotes: 1

Related Questions