Overloading function in subprogram, but I it has "already been defined" - vhdl

I'm trying to compile my subprogram pack and I get this error:
** Error: C:/Users/kmgrytte/Downloads/subprog_pck.vhd(16): (vcom-1295) Function "parity" has already been defined in this region.
** =====> Prior declaration of "parity" is at C:/Users/kmgrytte/Downloads/subprog_pck.vhd(12).
** Error: C:/Users/kmgrytte/Downloads/subprog_pck.vhd(20): VHDL Compiler exiting
Oveloading like this worked in my main program and I can't find any good examples of overloading in subprograms online.
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;
package subprog_pck is
procedure parity;
procedure parity(
in1 : in std_logic_vector(15 downto 0);
in2 : in std_logic_vector(15 downto 0);
par : out std_logic);
function parity return std_logic;
function parity(
indata : in std_logic_vector(15 downto 0)) return std_logic;
impure function parity return std_logic;
impure function parity(
indata : in unsigned(15 downto 0)) return std_logic;
end package subprog_pck;
package body subprog_pck is
procedure parity(
in1 : in std_logic_vector(15 downto 0);
in2 : in std_logic_vector(15 downto 0);
par : out std_logic) is
begin
variable parity1, parity2 : std_logic:=0;
if (rst_n = '0') then
parity1 := '0';
parity2 := '0';
par <= '0';
elsif rising_edge(mclk) then
parity1 := '0';
for i in in1'range loop
if in1(i) = '1' then
parity1 := not parity1;
end if;
end loop;
parity2 := '0';
for j in in2'range loop
parity2 := parity2 xor in2(j);
end loop;
par <= parity1 xor parity2;
end if;
end parity;
function parity(indata : in std_logic_vector(15 downto 0)) return std_logic is
variable parity_var : std_logic := '0';
begin
for i in indata'range loop
if (indata(i) = '1') then
parity_var := not parity_var;
end if;
end loop;
return parity_var;
end function parity;
function parity(indata : in unsigned(15 downto 0))
return std_logic is
variable parity_var : std_logic := '0';
begin
for j in indata'range loop
parity_var := parity_var xor indata(j);
end loop;
return parity_var;
end function parity;
end package body subprog_pck;

Function overloading only occurs when you have the same function name with a different parameter list. Using impure does not overload another function. So you have two version of parity that takes no inputs and outputs a std_logic. Hence the compile error.
You also didn't provide a this version of parity in the package body.

There are additional errors in your package which is missing a library clause (library ieee;) in the context clause. The procedure parity has a variable declaration after begin, your initial values for parity1 and parity2 are 0 (a numeric literal), there's no declaration for rst_n or mclk, par in par <= ... is not a signal, there's no body for procedure parity or function parity with no parameters.
IEEE Std 1076-2008
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.
(There's no implicit declaration here and no predefined operation, emphasis added.)
Also in 12.3
... 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
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.
You have more than one of these errors. vcom quit after the first one. The order in which errors are found are left to vagaries of the VHDL tool implementation applying semantic rules (other tools might find other errors first, explaining how the errors in the first paragraph above were found).
Modelsim has a verror tool providing more explanation:
vcom Message # 1295:
Two declarations that occur immediately within the same declarative
region must not be homographs, unless exactly one of them is the
declaration of a predefined operation.
Each of two declarations is said to be a homograph of the other if both
declarations have the same identifier, operator symbol, or character
literal, and if overloading is allowed for at most one of the two.
If overloading is allowed for both declarations, then each of the two is
a homograph of the other if they have the same identifier, operator
symbol, or character literal, as well as the same parameter and result
type profile (see 3.1.1). Overloading is defined only for subprograms
(including those those whose designator is an operator symbol) and
enumeration literals (including character literals).
[DOC: IEEE Std 1076-1993 VHDL LRM - 10.3 Visibility]
(These references are from the -1993 revision of the standard.)

Related

What happens when I provide a function with the parent of the subtype argument it's expecting?

While trying to figure out the specifics of the shift_right function from the numeric_std package I noticed that the count argument is of the subtype NATURAL:
function shift_right(ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is
begin
if (ARG'length<1) then return NAU; end if;
return UNSIGNED(XSRL(STD_LOGIC_VECTOR(ARG),COUNT));
end;
However when calling the function I can also provide an INTEGER which in contrast to NATURAL can hold a negative number.
Example of calling code that succesfully compiles:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ExampleCode is
port
(
clk : in std_logic;
input : in signed(15 downto 0);
shift : in signed(3 downto 0);
output : out signed(15 downto 0)
);
end entity;
architecture rtl of ExampleCode is
begin
ProcessExample : process(clk)
begin
if (rising_edge(clk)) then
output <= shift_right(input, to_integer(shift));
end if;
end process;
end rtl;
The numeric_std package shows that if you use to_integer with a signed argument that it returns an integer:
function TO_INTEGER ( ARG: SIGNED) return INTEGER;
My questions are;
Does VHDL always allow parents of subtypes to be provided as arguments to functions?
When it does allow a parent type, how does it resolve the imposed constraints of the subtype?
The other answer is very detailed, but I think goes down a bit of a rabbit hole, when your specific questions can be answered more succinctly. I have answered from a perspecitve of what will practically happen in a real tool that you might use, as opposed to trying to re-interpret the language standard.
An important feature of a subtype is that there is automatic 'conversion'+ to and from the parent type. The example below clearly shows this with an enumerated type. The same automatic conversion would be invoked when passing a parent-type parameter to a function that expects the sub-type.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity e is
end;
architecture a of e is
type r is (A, B, C, D);
subtype rs is r range A to C;
signal x1 : r := B;
signal x2 : r := D;
signal xs : rs;
begin
process
begin
xs <= x1; -- Fine.
wait for 1 ns;
xs <= x2; -- Run-time error, "Value 3 is out of range 0 to 2".
wait;
end process;
end;
Does VHDL always allow parents of subtypes to be provided as arguments to functions?
From the above, yes, it does, but in many tools, you will get an error if the automatic type conversion cannot succeed, as it obviously cannot in the second assignment in the example. Note that if x2 was a constant, a tool could work out that the conversion is not going to be possible, and thrown up a compile-time error then instead.
The same applies with natural and integer; since natural is defined as subtype natural is integer range 0 to integer'high, natural in a sense is an integer, so automatic 'conversion' is simple and reasonable as long as the integer is not outside the natural's range.
When it does allow a parent type, how does it resolve the imposed constraints of the subtype?
Whether standardised or not, a particular tool might implement this in a variety of ways, so you might see different behavior for out-of-range parent-typed values with different tools.
For example, when I tried with ModelSim, it appears that its conversion from integer to natural simply copies the value, meaning that shift_right will surprisingly work with a negative value in that tool, if the shift amount integer is not a constant (at least for version 10.7e).
Obviously it is not sensible to rely on a particular behavior, but regardless of behavior, using a sub type can offer you more protection than just using base types throughout a design.
+ It's not really conversion in VHDL, but if you've used pretty much any other language, this is how you will tend to refer to it.

Custom Type as VHDL 2008 Generic

I want to create a custom type in my generic section of my entity using VHDL-2008. However I get an error immediately in Modelsim with this code. The error is:
** Error: C:/Projects/source/My_Mux.vhd(35): near "is": expecting ';' or ')'
Note that Line 35 is the type t_Array below:
entity My_Mux is
generic (
g_MUX_INPUTS : integer := 2;
type t_Array is array (0 to g_MUX_INPUTS-1) of std_logic_vector(7 downto 0)
);
port (
i_Select : in std_logic_vector(1 downto 0);
i_Mux_Data : in t_Array;
o_Data : out std_logic_vector(7 downto 0)
);
end entity My_Mux;
architecture RTL of My_Mux is
begin
o_Data <= i_Mux_Data(0) when i_Select = "00" else i_Mux_Data(1);
end architecture RTL;
I looked into creating a special function that I define in my generic portion of my code. But that requires that I overload the function in the instantiating module, which I really did not want to have to do, it seems needlessly complicated. If I could create a custom type in the generic it would solve my problem. Possible using VHDL-2008?
How would you expect to have type compatibility between the formal and actual if they declaration of a type were actually made in a generic declaration?
Each declaration in VHDL is unique, not by name but by declaration occurrence. What declaration the name references depends on scope and visibility. Both (all) places a name is used have to be able to reach the same declaration.
How a generic type is declared is found in IEEE Std 1076-2008 6.5.3 Interface type declarations:
An interface type declaration declares an interface type that appears as a generic of a design entity, a component, a block, a package, or a subprogram.
interface_type_declaration ::=
interface_incomplete_type_declaration
interface_incomplete_type_declaration ::= type identifier
An interface type provides a means for the environment to determine a type to be used for objects in a particular portion of a description. The set of values and applicable operations for an interface type may be determined by an associated subtype in the environment. The manner in which such associations are made is described in 6.5.7.
And the important thing to note is that is an incomplete type declaration, where the actual specifies a preexisting type with a subtype constraint (6.5.6.2):
The subtype denoted by a generic type is specified by the corresponding actual in a generic association list. It is an error if no such actual is specified for a given formal generic type (either because the formal generic is unassociated or because the actual is open).
Because that association is with a previously declared type there is little difference with doing the same thing the -1993 way:
library ieee;
use ieee.std_logic_1164.all;
package my_package is
type my_array is array (natural range <>) of std_logic_vector(7 downto 0);
end package;
library ieee;
use ieee.std_logic_1164.all;
use work.my_package.all;
entity My_Mux is
generic (
g_MUX_INPUTS: integer := 2
--type t_Array is array (0 to g_MUX_INPUTS-1) of
-- std_logic_vector(7 downto 0)
);
port (
i_Select: in std_logic_vector(1 downto 0);
-- i_Mux_Data: in t_Array;
i_Mux_Data: in my_array (0 to g_MUX_INPUTS - 1);
o_Data : out std_logic_vector(7 downto 0)
);
end entity My_Mux;
architecture RTL of My_Mux is
begin
o_Data <= i_Mux_Data(0) when i_Select = "00" else i_Mux_Data(1);
end architecture RTL;
There's an added package that has a type declaration my_array which is an unbound (partially constrained) multidimensional array type.
This allows the use of the package my_package to specify the type of the actual:
library ieee;
use ieee.std_logic_1164.all;
use work.my_package.all;
entity my_mux_tb is
end entity;
architecture foo of my_mux_tb is
constant MUX_INPUTS: natural := 2;
signal i_Select: std_logic_vector (1 downto 0);
signal i_Mux_Data: my_array (0 to MUX_INPUTS -1);
signal o_Data: std_logic_vector(7 downto 0);
begin
DUT:
entity work.My_mux
generic map (
g_MUX_INPUTS => MUX_INPUTS
)
port map (
i_Select => i_Select,
i_Mux_Data => i_Mux_Data,
o_Data => o_Data
);
end architecture;
The two examples above analyzed in order, elaborate and the testbench simulates (while doing nothing particular interesting besides telling us the subtype constraint is passed on the port actual).
The custom type would be required to be accessible to both the component or entity instantiation and the place the port actual is declared.
Using a generic type would allow you to remove the my_package use clause from the my_mux context clause, relying on the actual association instead.
You can also bind the type at elaboration time without switching the package (or relying on package instantiation in -2008 with it's own generics).

VHDL Parametric case

I've some problem with my synthesis tool. I'm writing a module and I'm tryng to make it parametric and scalable. In my design I've a FSM and some counters. The counters have a parametric width ( they are function of the width of the datapath ). The problem is that I'm using that counter to drive a case statements. The synthesizer gives me back this error :
2049990 ERROR - (VHDL-1544) array type case expression must be of a locally static subtype
I've also tried to use subtype, but it doesnt work. The declaration is :
constant LENGTH_COUNTER_WORD : integer := integer(ceil(log2(real(WIDTH_DATA/WIDTH_WORD))));
subtype type_counter_word is std_logic_vector( LENGTH_COUNTER_WORD - 1 downto 0);
signal counter_word : std_logic_vector( LENGTH_COUNTER_WORD - 1 downto 0);
The case :
case type_counter_word'(counter_word) is
when (others => '1') =>
do_stuff();
when others =>
do_other_stuff();
end case;
I cannot switch to VHDL-2008. I've read I can use variable, but I'd like to find a different solution, if it exists. I cannot imagine there isn't any way to give parameters to synthesizer before the synthesis.
This is fixed in VHDL-2008. You can only work around it in earlier standards by using cascaded if statements (with the attendant priority logic). Variables don't make a difference when determining if choices are locally static.
I'm not sure how complicated your do_stuff() and do_other_stuff() operations are, but if you are just doing simple signal assignments, you could look into the and_reduce() function in the ieee.std_logic_misc library.
As an example:
output <= '1' when and_reduce(type_counter_word'(counter_word)) = '1' else '0';
Otherwise, as Kevin's answer suggests, a process block using if statements might be your best option.
About the time of Kevin's good enough answer, I had written this to demonstrate:
library ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.all;
entity counterword is
generic (
WIDTH_DATA: positive := 16;
WIDTH_WORD: positive := 8
);
end entity;
architecture foo of counterword is
constant LENGTH_COUNTER_WORD : integer :=
integer(ceil(log2(real(WIDTH_DATA/WIDTH_WORD))));
subtype type_counter_word is
std_logic_vector( LENGTH_COUNTER_WORD - 1 downto 0);
signal counter_word : std_logic_vector( LENGTH_COUNTER_WORD - 1 downto 0);
procedure do_stuff is
begin
end;
procedure do_other_stuff is
begin
end;
begin
UNLABELLED:
process (counter_word)
begin
-- case type_counter_word'(counter_word) is
-- when (others => '1') =>
-- do_stuff;
-- when others =>
-- do_other_stuff;
-- end case;
if counter_word = type_counter_word'(others => '1') then
do_stuff;
else
do_other_stuff;
end if;
end process;
end architecture;
Note because type_counter_word is a subtype you can provide the subtype constraints in a qualified expression for the aggregate:
if counter_word = type_counter_word'(others => '1') then
From 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.
This example analyzes, elaborates and simulates while doing nothing in particular. It'll call the sequential procedure statement do_other_stuff, which does nothing.
(For do_stuff and do_other stuff, empty interface lists aren't allowed).

VHDL operator argument type mismatch

I have a very simple operator problem in VHDL. I try to compare some inputs with logical operators but get an error message...
entity test is
port (
paddr : in std_logic_vector(15 downto 0);
psel : in std_logic;
penable : in std_logic;
pwrite : in std_logic
);
end entity test;
signal wrfifo_full : std_logic;
process (paddr, psel, penable, pwrite, wrfifo_full) is
begin
if (((paddr(8 downto 2) = "1000000")) and (psel and penable) and (pwrite and not(wrfifo_full))) then
dt_fifo_wr_i <= '1';
else
dt_fifo_wr_i <= '0';
end if;
end process;
Unfortuantely, I get then the following error message:
if (((paddr(8 downto 2) = "1000000")) and (psel and penable) and
(pwrite and not(wrfifo_full))) then
| ncvhdl_p: *E,OPTYMM (hdl/vhdl/test.vhd,523|43): operator argument type mismatch
87[4.3.3.2] 93[4.3.2.2] [7.2]
Anyway sees the problem?
Cheers
psel, penable, pwrite and wrfifo_full are all std_logic.
In vhdl, to write the test they way you have, they would need to be boolean.
Instead write the code so that you are comparing their values to 1 or zero.
(paddr(8 downto 2) = "1000000" and
psel = '1' and penable ='1' and
pwrite = '1' and wrfifo_full = '0')
As George said, you have to currently convert all your std logics to booleans.
In VHDL-2008 however, there is a new conditional operator (??) which is applied implicitly to statements such as yours, which means they will work as you hoped. You'll have to enable VHDL-2008 support on you compiler (or whinge at your supplier to get with the times :)
This book is a good read on all the new bits that VHDL2008 gives us:
VHDL-2008 Just the new stuff
Section 4.4 covers the conditional operator

VHDL - Problem with std_logic_vector

i'm coding a 4-bit binary adder with accumulator:
library ieee;
use ieee.std_logic_1164.all;
entity binadder is
port(n,clk,sh:in bit;
x,y:inout std_logic_vector(3 downto 0);
co:inout bit;
done:out bit);
end binadder;
architecture binadder of binadder is
signal state: integer range 0 to 3;
signal sum,cin:bit;
begin
sum<= (x(0) xor y(0)) xor cin;
co<= (x(0) and y(0)) or (y(0) and cin) or (x(0) and cin);
process
begin
wait until clk='0';
case state is
when 0=>
if(n='1') then
state<=1;
end if;
when 1|2|3=>
if(sh='1') then
x<= sum & x(3 downto 1);
y<= y(0) & y(3 downto 1);
cin<=co;
end if;
if(state=3) then
state<=0;
end if;
end case;
end process;
done<='1' when state=3 else '0';
end binadder;
The output :
-- Compiling architecture binadder of binadder
** Error: C:/Modeltech_pe_edu_6.5a/examples/binadder.vhdl(15):
No feasible entries for infix operator
"xor".
** Error: C:/Modeltech_pe_edu_6.5a/examples/binadder.vhdl(15):
Type error resolving infix expression
"xor" as type std.standard.bit.
** Error: C:/Modeltech_pe_edu_6.5a/examples/binadder.vhdl(16):
No feasible entries for infix operator
"and".
** Error: C:/Modeltech_pe_edu_6.5a/examples/binadder.vhdl(16):
Bad expression in right operand of
infix expression "or".
** Error: C:/Modeltech_pe_edu_6.5a/examples/binadder.vhdl(16):
No feasible entries for infix operator
"and".
** Error: C:/Modeltech_pe_edu_6.5a/examples/binadder.vhdl(16):
Bad expression in left operand of
infix expression "or".
** Error: C:/Modeltech_pe_edu_6.5a/examples/binadder.vhdl(16):
Bad expression in right operand of
infix expression "or".
** Error: C:/Modeltech_pe_edu_6.5a/examples/binadder.vhdl(16):
Type error resolving infix expression
"or" as type std.standard.bit.
** Error: C:/Modeltech_pe_edu_6.5a/examples/binadder.vhdl(28):
No feasible entries for infix operator
"&".
** Error: C:/Modeltech_pe_edu_6.5a/examples/binadder.vhdl(28):
Type error resolving infix expression
"&" as type
ieee.std_logic_1164.std_logic_vector.
** Error: C:/Modeltech_pe_edu_6.5a/examples/binadder.vhdl(39):
VHDL Compiler exiting
I believe i'm not handling std_logic_vector's correctly. Please tell me how? :(
One of the features of VHDL is that very little functionality is provided in the base language itself. Most of it is provided by using packages. The second line of your code is an example of this (use ieee.std_logic_1164.all). This means that you are using all of the std_logic_1164 package. See here for what this package defines.
When you write code, you generally want to store your signals in either std_logic or std_logic_vector. There are two reasons for this. The first is that a std_logic can also represent values other than '0' or '1'. It can also represent 'Z' or 'X' for example. The second is that the simulators (such as modelsim that you are using) are optimised to run faster with std_logic.
As a general convention, it is good practice to always make the inputs and outputs from your entity a std_logic or std_logic_vector.
The specific problem you are having is that you are using the type bit (which is one of the very few types defined in the VHDL standard) with xor.
The simplest solution is to change the co output in your entity to be of type std_logic and to change the declaration for sum and cin to be of type std_logic.
entity binadder is
port(n,clk,sh:in bit;
x,y:inout std_logic_vector(3 downto 0);
co:inout std_logic;
done:out bit);
end binadder;
signal sum,cin:std_logic;
A further comment is that it is generally bad practice to make your ports inout unless you have a very good reason to do so as this removes some of the strict type checking that is built into the language. The best solution is to create a signal within the entity itself and assign the signal directly to the output.
entity binadder is
port(n,clk,sh:in bit;
x,y:inout std_logic_vector(3 downto 0);
co:out std_logic;
done:out bit);
end binadder;
signal co_int:std_logic;
begin
co_int<= (x(0) and y(0)) or (y(0) and cin) or (x(0) and cin);
co <= co_int;
One final comment is that once the value of state is 1, how will it ever become 2 or 3?
Take a look into your logical-physical library mappings.
Check that the physical library actually has the packages dumped.
Make sure you are not using a different version of pre-compiled header with a different version of the simulator.
If nothing works, just make a local copy of ieee, compile the std_logic_1164 packages into it, move to work library and then compile your design. This has to work.

Resources