Why is there an apostrophe before a parenthesis in this VHDL function? - syntax

I'm new to coding test benches and so there is a lot of new syntax for me to learn. I'm stuck on trying to understand what the apostrophe after "string" is indicating.
It doesn't appear to be an attribute from here. Also, I've never seen a parenthesis after an apostrophe in VHDL.
procedure Shrink_line(L : inout LINE; pos : in integer)
is
variable old_L : LINE := L;
begin
if pos > 1 then
L := new string'(old_L(pos to old_L'high));
Deallocate(old_L);
end if;
end;

It's a qualified expression.
IEEE Std 1076-2008, 9.3.5 Qualified expressions:
A qualified expression is a basic operation (see 5.1) that is used to explicitly state the type, and possibly the subtype, of an operand that is an expression or an aggregate."
qualified_expression ::=
type_mark ' ( expression )
| type_mark ' aggregate
This qualified expression states both the type and the subtype for the allocator (9.3.7 Allocators) assigned to L in the procedure.
The operand of the qualified expression is the expression old_L(pos to old_L'high).
It's not an aggregate, it doesn't use named association to distinguish it from a parenthesized expression having a single choice (9.3.3 Aggregates).
Because you're not using a reference covering expressions you may not be aware what this allocator can do. Creating an MCVE:
use std.textio.all;
entity foo is
end entity;
architecture fum of foo is
procedure Shrink_line(L : inout LINE; pos : in integer)
is
variable old_L : LINE := L;
begin
if pos > 1 then
L := new string'(old_L(pos to old_L'high));
Deallocate(old_L);
end if;
end;
begin
process
variable L: LINE;
begin
write (L, string'("...shrinking violet"));
Shrink_line(L, 14);
writeline(OUTPUT,L);
wait;
end process;
end architecture;
Running this code in a simulation provides an output:
ghdl -a foo.vhdl
ghdl -e foo
ghdl -r foo
violet
The output comes from the writeline to OUTPUT (which is the File STD_OUTPUT (stdout in POSIX parlance).
9.3.7 Allocators, para 2:
The type of the object created by an allocator is the base type of the type mark given in either the subtype indication or the qualified expression. For an allocator with a subtype indication, the initial value of the created object is the same as the default initial value for an explicitly declared variable of the designated subtype. For an allocator with a qualified expression, this expression defines the initial value of the created object.
Creating the new allocator with a subtype constraint from the old allocator copied the string from the old allocator starting at position pos.
One other thing to note is that a string left bound is 1 by default. Shrink_line counted on that.

Related

How to write new line to file in VHDL?

I would like to separate my data with new line character in an output file, but the following codes result in error "can't resolve overload for procedure call":
write(out_line, "\n");
write(out_line, "");
write(out_line, '');
An example code how I want to use it:
ENTITY writer IS
PORT ( clk : IN STD_LOGIC := '0'; start : IN STD_LOGIC := '0');
END ENTITY;
ARCHITECTURE arch OF writer IS
SIGNAL vect : STD_LOGIC_VECTOR (2 downto 0) := "000";
TYPE state_type IS (init, write_file);
SIGNAL state : state_type := init;
BEGIN
PROCESS (clk, start)
FILE out_file : text;
VARIABLE out_line : line;
BEGIN
IF rising_edge(clk) THEN
CASE state IS
WHEN init =>
IF start = '1' THEN
state <= write_file;
ELSE
state <= init;
END IF;
WHEN write_file =>
state => init;
FOR i IN 0 TO 10 LOOP
write(out_line, vect);
writeline(out_file, out_line);
-- write(out_line, "\n"); <--
-- write(out_line, ""); <--
-- write(out_line, ''); <-- None of these work
writeline(out_file, out_line);
END LOOP;
END CASE;
END IF;
END PROCESS;
END ARCHITECTURE;
So I would like to know, is it possible in VHDL? If yes, how?
The following will consistently give you a single blank line:
write(out_line, string'(""));
writeline(out_file, out_line);
I suspect what #Dani posted may be tool dependent. For example while on one popular simulator, the following produces one line feed:
write(out_line, LF);
writeline(out_file, out_line);
However when I add a space after the LF, I get two lines:
write(out_line, LF & ' ');
writeline(out_file, out_line);
Creating a minimal, complete and verifiable example from the question's incomplete sample code:
library ieee; -- ADDED
use ieee.std_logic_1164.all; -- ADDED
use std.textio.all; -- ADDED
-- use ieee.std_logic_textio.all; -- ADDED for revisions earlier than -2008
ENTITY writer IS
-- PORT ( clk : IN STD_LOGIC := '0'; start : IN STD_LOGIC := '0');
END ENTITY;
ARCHITECTURE arch OF writer IS
SIGNAL vect : STD_LOGIC_VECTOR (2 downto 0) := "000";
-- TYPE state_type IS (init, write_file);
-- SIGNAL state : state_type := init;
BEGIN
PROCESS -- (clk, start)
FILE out_file : text;
VARIABLE out_line : line;
BEGIN
file_open(out_file, "some_file", WRITE_MODE); -- ADDED
-- IF rising_edge(clk) THEN
-- CASE state IS
-- WHEN init =>
-- IF start = '1' THEN
-- state <= write_file;
-- ELSE
-- state <= init;
-- END IF;
-- WHEN write_file =>
-- state => init;
FOR i IN 0 TO 10 LOOP
write(out_line, vect);
writeline(out_file, out_line);
-- write(out_line, "\n"); <--
-- write(out_line, ""); <--
-- write(out_line, ''); <-- None of these work
writeline(out_file, out_line);
END LOOP;
-- END CASE;
-- END IF;
wait; -- ADDED
END PROCESS;
END ARCHITECTURE;
demonstrates a way to get a blank line in the output:
some_file contents:
000
000
000
000
000
000
000
000
000
000
000
The second writeline procedure call produces an empty line without an intervening write procedure call.
Why is seen in IEEE Std 1076-2008 16.4 Package TEXTIO:
Procedures READLINE, WRITELINE, and TEE declared in package TEXTIO read and write entire lines of a file of type TEXT. Procedure READLINE causes the next line to be read from the file and returns as the value of parameter L an access value that designates an object representing that line. If parameter L contains a non-null access value at the start of the call, the procedure may deallocate the object designated by that value. The representation of the line does not contain the representation of the end of the line. It is an error if the file specified in a call to READLINE is not open or, if open, the file has an access mode other than read-only (see 5.5.2). Procedures WRITELINE and TEE each cause the current line designated by parameter L to be written to the file and returns with the value of parameter L designating a null string. Procedure TEE additionally causes the current line to be written to the file OUTPUT. If parameter L contains a null access value at the start of the call, then a null string is written to the file or files. If parameter L contains a non-null access value at the start of the call, the procedures may deallocate the object designated by that value. It is an error if the file specified in a call to WRITELINE or TEE is not open or, if open, the file has an access mode other than write-only.
The language does not define the representation of the end of a line. An implementation shall allow all possible values of types CHARACTER and STRING to be written to a file. However, as an implementation is permitted to use certain values of types CHARACTER and STRING as line delimiters, it might not be possible to read these values from a TEXT file.
A line feed (LF) format effector occurring as an element of a string written to a file of type TEXT, either using procedure WRITELINE or TEE, or using the WRITE operation implicitly defined for the type TEXT, is interpreted by the implementation as signifying the end of a line. The implementation shall transform the LF into the implementation-defined representation of the end of a line.
...
For each WRITE, OWRITE, and HWRITE procedure, after data is appended to the string value designated by the parameter L, L designates the entire line. The procedure may modify the value of the object designated by the parameter L at the start of the call or may deallocate the object.
If deallocation occurs out_line will have a value of null after a writeline call and a null string is written in the immediately following writeline call which also provides an end of line.
If the object value accessed by out_line is a null array (having no elements, 5.3.2.2 Index constraints and discrete ranges, a null string) the immediately following writeline call will result in an end of line being written to the file.
In essence your code example already contains one of these methods for writing a blank line, which depends on whether deallocation is used conditionally (may).
Variants of allocate() and free() can be relatively expensive in terms of execution time and when the size of the allocated object and it's element size is known a smaller 'allocated' object can be written to the same object space saving simulation time. The simulation kernel representation of an array object can have bounds separate from the array value, deallocation and re-allocation can be reserved for when the object size is larger than the previously allocated size or an explicit deallocate call occurs.
There's also a requirement that an implementation translate an LF character to an end of line in a write to a file. This is the other mechanism that allows you to write an LF character as the last or only character to a line and get a following blank line.
You could also explicitly write a null string to out_line
write(out_line, string'(""));
prior to the second writeline call. The qualified expression provides the type of the string literal unlike the attempt commented out in the original question where the type of the string literal can't be determined. See 9.3.2 Literals "... The type of a string or bit string literal shall be determinable solely from the context in which the literal appears, excluding the literal itself but using the fact that the type of the literal shall be a one-dimensional array of a character type. ...". The procedure write would be ambiguous in this context, failing overload resolution (12.5 The context of overload resolution).
Finally after a lot of searching and trying I found that the following code works:
write(out_line, lf);
writeline(out_file, out_line);
I found that write(out_line, cr); does the same thing, and write(out_line, nul); adds ' ' character between the outputs.

Error: Libero SoC 11.9 VHDL compile "A homograph of hread is already declared in the region"

I am a novice at VHDL. Im getting the following compile errors:
A homograph of hread is already in the region
A homograph of hread is already in the region
A homograph of hwrite is already in the region
The location of the errors appear as if Libero
compilation is not telling the difference between Std_ULogic_Vector and Std_Logic_Vector. Any insight is helpful.
Slyswine
--pragma translate_off
library Std;
use Std.Standard.all;
use Std.TextIO.all;
library ieee;
use ieee.std_logic_1164.all;
--pragma translate_on
package StdIO is
--pragma translate_off
procedure HRead(
variable L: inout Line;
variable VALUE: out Std_ULogic_Vector;
variable GOOD: out Boolean);
procedure HRead(
variable L: inout Line;
variable VALUE: out Std_ULogic_Vector);
procedure HRead(
variable L: inout Line;
variable VALUE: out bit_vector);
procedure HRead( -- "Error occurs on this line"
variable L: inout Line;
variable VALUE: out Std_Logic_Vector;
variable GOOD: out Boolean);
procedure HRead( -- "and this line"
variable L: inout Line;
variable VALUE: out Std_Logic_Vector);
procedure HWrite(
variable L: inout Line;
constant VALUE: in Std_ULogic_Vector;
constant JUSTIFIED: in SIDE := RIGHT;
constant FIELD: in WIDTH := 0);
procedure HWrite( -- "and this line"
variable L: inout Line;
constant VALUE: in Std_Logic_Vector;
constant JUSTIFIED: in SIDE := RIGHT;
constant FIELD: in WIDTH := 0);
procedure Write(
variable L: inout Line;
constant VALUE: in Std_ULogic;
constant JUSTIFIED: in SIDE := RIGHT;
constant FIELD: in WIDTH := 0);
--pragma translate_on
end package StdIO;
The TL;DR answer
All of these subprogram declarations are already covered in package std_logic_1164 for an IEEE Std 1076-2008 revision compliant tool. Also in n -2008 STD_LOGIC_VECTOR is a subtype of STD_ULOGIC_VECTOR, meaning the base type (STD_ULOGIC_VECTOR) is the same and they errors are homographs (which aren't allowed here in the same declarative region).
When using -2008 package StdIO (it's declaration shown here) isn't needed unless there are behavioral differences in a subprogram specification.
The package declaration would analyze correctly in a tool compliant to an earlier revision of the VHDL standard because STD_LOGIC_VECTOR is declared as a separate type in package std_logic_1164.
The long answer
The Errors
12.3 Visibility
... Each of two declarations is said to be a homograph of the other if and only if both declarations have the same designator, and they denote different named entities, and either overloading is allowed for at most one of the two, or overloading is allowed for both declarations and they have the same parameter and result type profile (see 4.5.1).
4.5 Subprogram overloading
4.5.1 General
Two formal parameter lists are said to have the same parameter type profile if and only if they have the same number of parameters, and if at each parameter position the corresponding parameters have the same base type. Two subprograms are said to have the same parameter and result type profile if and only if both have the same parameter type profile, and if either both are functions with the same result base type or neither of the two is a function.
procedure HRead(
variable L: inout Line;
variable VALUE: out Std_ULogic_Vector;
variable GOOD: out Boolean);
and
procedure HRead( -- "Error occurs on this line"
variable L: inout Line;
variable VALUE: out Std_Logic_Vector;
variable GOOD: out Boolean);
are being considered homographs as are
procedure HRead(
variable L: inout Line;
variable VALUE: out Std_ULogic_Vector);
and
procedure HRead( -- "and this line"
variable L: inout Line;
variable VALUE: out Std_Logic_Vector);
As well as
procedure HWrite(
variable L: inout Line;
constant VALUE: in Std_ULogic_Vector;
constant JUSTIFIED: in SIDE := RIGHT;
constant FIELD: in WIDTH := 0);
and
procedure HWrite( -- "and this line"
variable L: inout Line;
constant VALUE: in Std_Logic_Vector;
constant JUSTIFIED: in SIDE := RIGHT;
constant FIELD: in WIDTH := 0);
12.3 Visibility
...
Two declarations that occur immediately within the same declarative region, other than the declarative region of a block implied by a component instantiation or the declarative region of a generic-mapped package or subprogram equivalent to a package instance or a subprogram instance, shall not be homographs, unless exactly one of them is the implicit declaration of a predefined operation or is an implicit alias of such an implicit declaration. In such cases, a predefined operation or alias thereof is always hidden by the other homograph. Where hidden in this manner, an implicit declaration is hidden within the entire scope of the other declaration (regardless of which declaration occurs first); the implicit declaration is visible neither by selection nor directly. For a declarative region of a block implied by a component instantiation or the declarative region of a generic-mapped package or subprogram equivalent to a package instance or a subprogram instance, the rules of this paragraph are applied to the corresponding entity declaration, component declaration, uninstantiated package declaration, or uninstantiated subprogram declaration, as appropriate.
...
To avoid a rathole HREAD and HWRITE are explicitly declared in package std_logic_1164 (-2008) and
procedure HRead(
variable L: inout Line;
variable VALUE: out Std_ULogic_Vector;
variable GOOD: out Boolean);
procedure HRead(
variable L: inout Line;
variable VALUE: out Std_ULogic_Vector);
procedure HWrite(
variable L: inout Line;
constant VALUE: in Std_ULogic_Vector;
constant JUSTIFIED: in SIDE := RIGHT;
constant FIELD: in WIDTH := 0);
are legal overloads of the procedures declared in -2008 package std_logic_1164. (These are the declarations for which following illegal homographs are found. They aren't implicitly declared or aliases. These declarations are not found in earlier revision versions of package std_logic_1164. The implication is none of these declarations may be necessary in the OP's package StdIO.)
And these are errors:
1.3 Structure and terminology of this standard
1.3.1 General
In this document, the word shall is used to indicate a mandatory requirement. The word should is used to indicate a recommendation. The word may is used to indicate a permissible action. The word can is used for statements of possibility and capability.
1.3.3 Semantic description
The meaning and restrictions of a particular construct are described with a set of narrative rules immediately following the syntactic productions. In these rules, an italicized term indicates the definition of that term, and identifiers appearing entirely in uppercase letters refer to definitions in package STANDARD (see 16.3).
The following terms are used in these semantic descriptions with the following meanings:
erroneous: The condition described represents an ill-formed description; however, implementations are not required to detect and report this condition. Conditions are deemed erroneous only when it is impossible in general to detect the condition during the processing of the language.
error: The condition described represents an ill-formed description; implementations are required to detect the condition and report an error to the user of the tool.
illegal: A synonym for “error.”
legal: The condition described represents a well-formed description.
The homograph subprogram declarations produce errors, not meeting a semantic requirement that is mandatory (the use of shall in 12.3 above).
Why they're homographs is based on the use of IEEE Std 1076-2008 compliant VHDL tool where in IEEE package std_logic_1164 STD_LOGIC_VECTOR is a subtype of STD_ULOGIC_VECTOR:
subtype STD_LOGIC_VECTOR is (resolved) STD_ULOGIC_VECTOR;
Note for homograph procedure declarations the interface objects of the form:
6.5.2 Interface object declarations
interface_constant_declaration ::=
[ constant ] identifier_list : [ in ] subtype_indication [ := static_expression ]
interface_variable_declaration ::=
[ variable ] identifier_list : [ mode ] subtype_indication [ := static_expression ]
whose subtype indication type marks:
6.3 Subtype declarations
subtype_indication ::=
[ resolution_indication ] type_mark [ constraint ]
..
type_mark ::=
type_name
| subtype_name
have the same base type:
6.3 Subtype declarations
...
A type mark denotes a type or a subtype. If a type mark is the name of a type, the type mark denotes this type and also the corresponding unconstrained subtype. The base type of a type mark is, by definition, the base type of the type or subtype denoted by the type mark.
...
have the same parameter type profile (4.5.1), and the procedure declarations are homographs.
4.5 Subprogram overloading
4.5.1 General
...
A given subprogram designator can be used to designate multiple subprograms. The subprogram designator is then said to be overloaded; the designated subprograms are also said to be overloaded and to overload each other. If two subprograms overload each other, one of them can hide the other only if both subprograms have the same parameter and result type profile.
A call to an overloaded subprogram is ambiguous (and therefore is an error) if the name of the subprogram, the number of parameter associations, the types and order of the actual parameters, the names of the formal parameters (if named associations are used), and the result type (for functions) are not sufficient to identify exactly one (overloaded) subprogram.
Solutions
First you could use a tool compatible with an earlier revision of the VHDL standard. Prior to -2008 the std_ulogic_vector and std_logic_vector were two separate types.
Second you could delete the 'duplicate' declarations with std_logic_vector parameters and presumably any matching subprogram specifications in the package body while using -2008 compliant design specifications and tools. Potentially none of this package (as seen from it's declaration) is needed with -2008 unless there is some behavior found for any of it's subprogram specifications not provided in -2008 package std_logic_1164. If there's no differentiation in behavior the package StdIO isn't needed whatsoever, all it's procedures are declared in -2008 package std_logic_1164. (You may get a glimmer of why STD_LOGIC_VECTOR is a subtype of STD_ULOGIC_VECTOR in -2008, it reduces the number of subprogram declarations and specifications drammatically.)
Resources
The source for the -2008 package bodies as well as earlier package bodies can be found here if not made available in your tool implementation. (Respectively 1076-2008_downloads.zip and 1076.2-1996_downloads.zip). For purposes of these errors only the declarations for STD_LOGIC_VECTOR in package std_logic_1164 need be considered (1076-2008_downloads/1076-2008_machine-readable/ieee/std_logic_1164.vhdl and 1076.2-1996_downloads/std_logic_1164.vhdl).
Other items
You don't need the library clause for std nor the use clause for std.standard in the context clause of package StdIO.
See IEEE Std 1076-2008:
13.2 Design libraries.
...
Every design unit except a context declaration and package STANDARD is assumed to contain the following implicit context items as part of its context clause:
library STD, WORK; use STD.STANDARD.all;

Initialize dynamic VHDL array

--in the package
type t_array is array (natural range <>) of std_logic_vector (7 downto 0);
type p_array is access t_array;
--in my testbench
variable my_array : p_array := null;
begin
my_array := new t_array(0 to 19);
my_array := ( X"00",X"00",X"00",X"00",X"FF",
X"FF",X"FF",X"FF",X"00",X"00",
X"FF",X"FF",X"FF",X"FF",X"FF",
X"FF",X"FF",X"FF",X"FF",X"FF" );
Error: Target type util_lib.tb_pkg.p_array in variable assignment is different from expression type util_lib.tb_pkg.t_array.
How can I compactly assign all the elements of the array?
(1). Dereference your poincough access type.
my_array.all := (...);
(2) Initialise it from a function
begin
my_array := new_array(20);
The gory details of initialising it can be buried in the function, which could calculate the values algorithmically, copy them from a constant array, or even read the contents from file.
constant initialiser : t_array := (...);
function new_array(length : natural range initialiser'range) return t_array is
variable temp : p_array := new t_array(0 to length - 1);
begin
-- either this
for i in temp'range loop
temp(i) := initialiser(i);
end loop;
-- or simply this
temp.all := initialiser(temp'range);
return temp;
end new_array;
(note the constraint on arguments to new_array : that ensures it won't create an array larger than the initialiser.)
If you like one step, you can also do:
--in my testbench
variable my_array : p_array := null;
begin
my_array := new t_array'( X"00",X"00",X"00",X"00",X"FF",
X"FF",X"FF",X"FF",X"00",X"00",
X"FF",X"FF",X"FF",X"FF",X"FF",
X"FF",X"FF",X"FF",X"FF",X"FF" );
You can also to do this in an initialization:
--in my testbench
variable my_array : p_array := new t_array'(
X"00",X"00",X"00",X"00",X"FF",
X"FF",X"FF",X"FF",X"00",X"00",
X"FF",X"FF",X"FF",X"FF",X"FF",
X"FF",X"FF",X"FF",X"FF",X"FF" );
begin
Your error message:
Error: Target type util_lib.tb_pkg.p_array in variable assignment is different from expression type util_lib.tb_pkg.t_array.
tells us the subtype of the target doesn't match the right hand expression.
That can be cured several ways:
library ieee;
use ieee.std_logic_1164.all;
package initialize is
--in the package
type t_array is array (natural range <>) of std_logic_vector (7 downto 0);
type p_array is access t_array;
end package;
library ieee;
use ieee.std_logic_1164.all;
use work.initialize.all;
entity testbench is
end entity;
architecture fum of testbench is
begin
process
--in my testbench
variable my_array : p_array := null;
begin
my_array := new t_array(0 to 19);
my_array (my_array'range) := (
X"00",X"00",X"00",X"00",X"FF",
X"FF",X"FF",X"FF",X"00",X"00",
X"FF",X"FF",X"FF",X"FF",X"FF",
X"FF",X"FF",X"FF",X"FF",X"FF" );
wait;
end process;
end architecture;
here using a slice name with the range provided by my_array'range.
Without the range the target name is interpreted as an access type name. As a slice name with a discrete range the target name denotes the value of the object type denotes:
IEEE Std 1076-2008 8. Names 8.1 General Paragraph 3 - 4:
Certain forms of name (indexed and selected names, slice names, and attribute names) include a prefix that is a name or a function call. If the prefix of a name is a function call, then the name denotes an element, a slice, or an attribute, either of the result of the function call, or (if the result is an access value) of the object designated by the result. Function calls are defined in 9.3.4.
A prefix is said to be appropriate for a type in either of the following cases:
— The type of the prefix is the type considered.
— The type of the prefix is an access type whose designated type is the type considered.
Here it helps to understand designate is a synonym for denote used to describe the relationship between a value of an access type and the object it references.
paragraph 5:
The evaluation of a name determines the named entity denoted by the name. The evaluation of a name that has a prefix includes the evaluation of the prefix, that is, of the corresponding name or function call. If the type of the prefix is an access type, the evaluation of the prefix includes the determination of the object designated by the corresponding access value. In such a case, it is an error if the value of the prefix is a null access value. It is an error if, after all type analysis (including overload resolution), the name is ambiguous.
In this case you can use a slice name that encompasses the entire array.
You can use a selected name for the access type object designates:
architecture fie of testbench is
begin
process
variable my_array : p_array := null;
begin
my_array := new t_array(0 to 19);
my_array.all := ( X"00",X"00",X"00",X"00",X"FF",
X"FF",X"FF",X"FF",X"00",X"00",
X"FF",X"FF",X"FF",X"FF",X"FF",
X"FF",X"FF",X"FF",X"FF",X"FF" );
wait;
end process;
end architecture;
8.3 Selected names paragraph 5:
For a selected name that is used to denote the object designated by an access value, the suffix shall be the reserved word all. The prefix shall belong to an access type.
Using these methods distinguishes between assignment to an object of an access type (which isn't the type of the composite in the right hand expression) and the allocated object designated by the object of the access type.

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;
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.
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.

No function declarations for operator + error in VHDL

In this piece of code I get this error for the line with +
function func (bv1 : in bit_vector; bv2 : in integer) return bit_vector is
variable temp : natural := 2**bv2;
variable result : bit_vector(1 to 32);
begin
report "asd" & natural'image(temp);
result <= bv1 + temp; // this line causes the error
return result;
end func;
The error is :
No function declarations for operator +
How can I solve this? I also get a similar error for "=" as well.
Don't use bit_vectors (or std_logic_vectors, really) for anything you want to do arithmetic on.
Use the ieee.numeric_std library and then declare your signals (or whatever) to be of type signed ot unsigned depending on what type of vector you want. (Or of course, you can just use integers and the subtypes of that)
It's because you try to add a natural to a bit_vector which does not work because they are of different types. So you'll have to use a converter, e.g. as shown here within one of the functions. The other method is to stick to all the same types, but that isn't always possible.
Some initial problems with the code are that VHDL comments markup is --, not
//, and assign to result variable must use :=, since <= is for assign
to signal.
Then, the reason for the error:
No function declarations for operator +
is that VHDL is a strong typed language, so it is not possible just to add a
natural type and a bit_vector type, as attempted in result <= bv1 + temp.
Instead you need to use the package numeric_bit_unsigned, and for example
convert temp to bit_vector using function to_bitvector before adding.
Resulting code can then be:
library ieee;
use ieee.numeric_bit_unsigned.all;
...
function func (bv1 : in bit_vector; bv2 : in integer) return bit_vector is
variable temp : natural := 2**bv2;
variable result : bit_vector(1 to 32);
begin
report "asd" & natural'image(temp);
result := bv1 + to_bitvector(temp, result'length); -- this line causes the error
return result;
end func;
You should check that the length is enough to handle the required values.
However, instead of using bit_vector type, you may consider the
std_logic_vector (depending on the design), since the std_logic_vector has
additional values that may reveal design problem in simulation.

Resources