stumped on syntax yet again!

S

Shannon

Ok, here is the relevant code snipits:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;

HWID : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0);
RAM_addr : OUT UNSIGNED(9 DOWNTO 0);

TYPE reg_type IS ARRAY (0 TO NUM_REGS-1) OF
STD_LOGIC_VECTOR(HWID'RANGE);
SIGNAL regs : reg_type;
SIGNAL data_in : STD_LOGIC_VECTOR(HWID'RANGE);

Line 156: RAM_addr <= UNSIGNED("00" & data_in);

and the error is:

Error (10327): VHDL error at xFace.vhd(156): can't determine
definition of operator ""&"" -- found 2 possible definitions
Error (10647): VHDL type inferencing error at xFace.vhd(156): type of
expression is ambiguous - "reg_type" or "std_logic_vector" are two
possible matches
Error (10411): VHDL Type Conversion error at xFace.vhd(156): can't
determine type of object or expression near text or symbol "UNSIGNED"

I have no idea why it thinks "reg_type" is a possible match. It seems
very clear that RAM_addr is unsigned, "00" is SLV, and data_in is
SLV. "&" can only have one possible meaning. I'm sure that I'm doing
something else wrong that you guys will point out in less than a
second! ;)

Shannon
 
M

Mike Treseler

Shannon said:
Line 156: RAM_addr <= UNSIGNED("00" & data_in);
and the error is:

Error (10327): VHDL error at xFace.vhd(156): can't determine
definition of operator ""&"" -- found 2 possible definitions
Error (10647): VHDL type inferencing error at xFace.vhd(156): type of
expression is ambiguous - "reg_type" or "std_logic_vector" are two
possible matches
Error (10411): VHDL Type Conversion error at xFace.vhd(156): can't
determine type of object or expression near text or symbol "UNSIGNED"

I have no idea why it thinks "reg_type" is a possible match.

Make arrays of subtypes, not base types.

The problem is inside the parens.
"00" is an anonymous type that could be an reg_type *element*.

STD_LOGIC_VECTOR(HWID'RANGE) is an anonymous subtype.

The LRM does not require the compiler to think further.
That's just the way it is.

Simplest fix is to declare and use subtypes for the
various STD_LOGIC_VECTOR widths.

-- Mike Treseler
 
S

Shannon

Make arrays of subtypes, not base types.

The problem is inside the parens.
"00" is an anonymous type that could be an reg_type *element*.

STD_LOGIC_VECTOR(HWID'RANGE) is an anonymous subtype.

The LRM does not require the compiler to think further.
That's just the way it is.

Simplest fix is to declare and use subtypes for the
various STD_LOGIC_VECTOR widths.

       -- Mike Treseler

Thanks for the help Mike. I guess I still don't understand. I tried
googling for "anonymous subtype" but I didn't find any helpful
information.

I tried declaring a subtype by doing:

subtype hwid_type IS STD_LOGIC_VECTOR(7 DOWNTO 0);

and then:

TYPE reg_type IS ARRAY (0 TO NUM_REGS-1) OF hwid_type;
SIGNAL data_in : hwid_type;

That didn't change anything so I'm obviously not understanding the
term "anonymous subtype". Any hints?

Shannon
 
M

Mike Treseler

Shannon said:
That didn't change anything so I'm obviously not understanding the
term "anonymous subtype". Any hints?

Line 156: RAM_addr <= UNSIGNED("00" & data_in);

RAM_addr <= my_address_subtype'("00" & data_in);
 
N

Nicolas Matringe

Mike Treseler a écrit :
RAM_addr <= my_address_subtype'("00" & data_in);

I recently had a similar problem (though I was only using SLVs) and
fixed it by pulling the litteral constant out of the cast :

RAM_addr <= "00" & unsigned(data_in);

In this case the context is clear : "00" must be unsigned to make the
assignment valid.
I still don't understand why the context is unclear when concatenating a
litteral constant and a std_logic_vector.

Nicolas
 
M

Mike Treseler

Nicolas said:
I recently had a similar problem (though I was only using SLVs) and
fixed it by pulling the litteral constant out of the cast :

RAM_addr <= "00" & unsigned(data_in);

Yes. Of course. That's the ticket.

I still don't understand why the context is unclear when concatenating a
literal constant and a std_logic_vector.

The parser is not saying that "00" won't '&' with data_in.
It's saying that it is possible that "00"
was *meant* to be an element of another type in scope.
Which would be a type error.
So it is a type error.
Hmmm.

-- Mike Treseler
 
S

Shannon

Yes. Of course. That's the ticket.


The parser is not saying that "00" won't '&' with data_in.
It's saying that it is possible that "00"
was *meant* to be an element of another type in scope.
Which would be a type error.
So it is a type error.
Hmmm.

     -- Mike Treseler

RAM_addr is of type UNSIGNED not 'my_address_subtype'
So I tried:

RAM_addr <= UNSIGNED(my_address_subtype'("00" & data_in));

but then I'm back to the original errors again.

Nicolas's solution worked although I still don't understand why my
original line is wrong.

Thanks all!

Shannon
 
S

Shannon

RAM_addr is of type UNSIGNED not 'my_address_subtype'
So I tried:

RAM_addr <= UNSIGNED(my_address_subtype'("00" & data_in));

but then I'm back to the original errors again.

Nicolas's solution worked although I still don't understand why my
original line is wrong.

Thanks all!

Shannon- Hide quoted text -

- Show quoted text -

If "00" is a vague type in this case why can't I cast it to make the
error go away? For example:

RAM_addr <= UNSIGNED(STD_LOGIC_VECTOR'("00") & data_in);

Shannon
 
M

Mike Treseler

Shannon said:
If "00" is a vague type in this case why can't I cast it to make the
error go away?

Declare it as a constant to give it a type.

That's good practice in any case.
I often declare zero constants for this:

RAM_addr <= my_adr_zero_c + data_in;

-- Mike Treseler
 
M

Martin Thompson

Shannon said:
If "00" is a vague type in this case why can't I cast it to make the
error go away? For example:

RAM_addr <= UNSIGNED(STD_LOGIC_VECTOR'("00") & data_in);

You should be able to, certainly I have in the past. Does it not work?

Cheers,
Martin
 
S

Shannon

You should be able to, certainly I have in the past.  Does it not work?

Cheers,
Martin

No, it doesn't work. It results in the same original errors. I'm
thinking it still doesn't work because in order to cast it as a SLV it
needs to know what it is casting it FROM. (i.e. it can't figure out
what "00" is in order to re-cast it.)

Shannon
 
M

Mike Treseler

Shannon said:
No, it doesn't work. It results in the same original errors. I'm
thinking it still doesn't work because in order to cast it as a SLV it
needs to know what it is casting it FROM. (i.e. it can't figure out
what "00" is in order to re-cast it.)

I think that's about right.
Note that these fussy rules only apply
when I fail to declare my own constants
and subtypes.

-- Mike Treseler
 
S

Shannon

Shannon














What tool is this?  It may be a bug.  Here is why I think so, maybe
someone can straighten out my thoughts:

You are wrong and the tool is correct in that the type of the expression,
"00" & data_in, can be either std_logic_vector or reg_type (concatenation
is implicitly defined for all array types).  For example, if NUM_REGS is
two, the following would be legal:
    regs        <= data_in & data_in ;

OTOH, the type conversion UNSIGNED can only convert arrays of std_logic
to type unsigned.  Since the type reg_type is not an array of std_logic,
it should not be a potential match to the overload resolution.

Perhaps one of our resident compiler people could comment?

I would say report it as a bug.

The work around Nicolas gave you:
   RAM_addr <= "00" & unsigned(data_in);

works because there is no other path the tool can consider for the &.

Cheers,
Jim- Hide quoted text -

- Show quoted text -

You don't have to convince me that it's a bug! hehehe But I always
want to understand WHY things are the way they are. The thing I
learned here was "scope". I had no idea it was using the concept of
scope to resolve ambiguous situations.

Personally I think type casting it as an SLV should have worked.

Shannon
 
J

James Unterburger

The compiler can't figure out which "&" operator to use.
The rules in 7.3.5 Type conversion prohibit the target type
from being used to figure out the expression type.

Every array type comes with 4 implicit "&" operators:
"&"[array,array RETURN array]
"&"[array,elem RETURN array]
"&"[elem,array RETURN array]
"&"[elem,elem RETURN array]

VHDL uses only the base type when doing operator overloading
(figuring out which operator to use). This includes using
only the base type of the "elem" in the above.

--========================================================================
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;

HWID : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0);
RAM_addr : OUT UNSIGNED(9 DOWNTO 0);

TYPE reg_type IS ARRAY (0 TO NUM_REGS-1) OF STD_LOGIC_VECTOR(HWID'RANGE);
SIGNAL regs : reg_type;
SIGNAL data_in : STD_LOGIC_VECTOR(HWID'RANGE);

Line 156: RAM_addr <= UNSIGNED("00" & data_in);
--========================================================================

Take the expression ("00" & data_in). Remember, we can't
use the enclosing type conversion target type UNSIGNED because
of the 7.3.5 rules. The type of data_in is clearly std_logic_vector.
Now we must figure out the type of "00" and which of these 8 to call:

In this testcase, 8 relevant "&" operators are visible.
1a) "&"[std_logic_vector,std_logic_vector RETURN std_logic_vector]
1b) "&"[std_logic_vector,std_ulogic RETURN std_logic_vector]
1c) "&"[std_ulogic,std_logic_vector RETURN std_logic_vector]
1d) "&"[std_ulogic,std_ulogic RETURN std_logic_vector]
2a) "&"[reg_type,reg_type RETURN reg_type]
2b) "&"[reg_type,std_logic_vector RETURN reg_type]
2c) "&"[std_logic_vector,reg_type RETURN reg_type]
2d) "&"[std_logic_vector,std_logic_vector RETURN reg_type]

In the items labeled with "2", the type "reg_type" really means
the anonymous base type of the constrained array subtype "reg_type".

From these 8 concatenation operators, we need to pick the 1 that
will work, else we have an ambiguity (error).

The right operand "data_in" type being std_logic_vector, there
remain 4 possible choices:

1a) "&"[std_logic_vector,std_logic_vector RETURN std_logic_vector]
1c) "&"[std_ulogic,std_logic_vector RETURN std_logic_vector]
2b) "&"[reg_type,std_logic_vector RETURN reg_type]
2d) "&"[std_logic_vector,std_logic_vector RETURN reg_type]

Looking at the left operand string literal "00" (which is necessarily
some 1-dim array type), we can further prune this down to 2 choices (and
know that "00" is std_logic_vector):

1a) "&"[std_logic_vector,std_logic_vector RETURN std_logic_vector]
2d) "&"[std_logic_vector,std_logic_vector RETURN reg_type]

We can't decide which one of these 2 "&" operators to call. Overloading
occurs on the base type, and we can't use the RETURN type at all
when we're in a type conversion expression. The number of elements
of the constrained array subtype "reg_type" is irrelevant, any
length error would occur separate and after the overload resolution
has occurred. Basically, we don't know if ("00" & data_in) means,
"make an even longer std_logic_vector value", or "make a 2-element array value
of type "reg_type" (which would be an error because every element
of such a value has to be the same length as the other, and has to be the
same length as the actual element subtype of the array); the 2-element
interpretation must be considered even if the "reg_type" doesn't
define exactly two elements, and regardless of the length of the
element subtype.

There are at least 2 ways to make this work:

This effectively tells the expression of the type conversion
to UNSIGNED that "you are of type std_logic_vector", eliminating
choice 2d from the list:
RAM_addr <= UNSIGNED(std_logic_vector'("00" & data_in));

This converts data_in to UNSIGNED, bringing into play the 4 "&"
operators for type UNSIGNED, changing the interpretation of "00"
so that it's of type UNSIGNED, and chosing the
"&"[unsigned,unsigned RETURN unsigned] concatenation operator:
RAM_addr <= "00" & UNSIGNED(data_in);
 
R

Rob Dekker

Shannon said:
Ok, here is the relevant code snipits:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;

HWID : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0);
RAM_addr : OUT UNSIGNED(9 DOWNTO 0);

TYPE reg_type IS ARRAY (0 TO NUM_REGS-1) OF
STD_LOGIC_VECTOR(HWID'RANGE);
SIGNAL regs : reg_type;
SIGNAL data_in : STD_LOGIC_VECTOR(HWID'RANGE);

Line 156: RAM_addr <= UNSIGNED("00" & data_in);

and the error is:

Error (10327): VHDL error at xFace.vhd(156): can't determine
definition of operator ""&"" -- found 2 possible definitions
Error (10647): VHDL type inferencing error at xFace.vhd(156): type of
expression is ambiguous - "reg_type" or "std_logic_vector" are two
possible matches
Error (10411): VHDL Type Conversion error at xFace.vhd(156): can't
determine type of object or expression near text or symbol "UNSIGNED"

I have no idea why it thinks "reg_type" is a possible match. It seems
very clear that RAM_addr is unsigned, "00" is SLV, and data_in is
SLV. "&" can only have one possible meaning. I'm sure that I'm doing
something else wrong that you guys will point out in less than a
second! ;)

Shannon

Hi Shannon,

This is not a bug. As others tried to explain to you, the expression ("00" & data_in) could mean an array of 10 elements of
std_logic, or it could mean an array of 2 elements of std_logic_vector. In the first case, the result type is 'std_logic_vector', in
the second case it can be type 'reg_type'.

The tool cannot know which one you mean because the expression is used as an operand to the type conversion (to type 'UNSIGNED'),
and LRM 7.3.5 states explicitly : "The type of the operand of a type conversion must be determinable independent of the context (in
particular, independent of the target type)."

So either type 'reg_type' or type 'std_logic_vector' could match here.

How to fix this ?
Work with EITHER 'std_logic_vector' OR with 'unsigned'. Convert between the two as little as you can. That will also make it clear
what the representation of the data is in the signals. If you have to convert, do it with a plain conversion (no expression in the
argument).

So, two solutions :
(1) Change 'data_in' to be an 'unsigned'. Then use normal assignment :

RAM_addr <= "00" & data_in;

(2) If you want to keep 'data_in' the same (type std_logic_vector), then concert it by itself :

RAM_addr <= "00" & UNSIGNED(data_in);

Either way should work (no ambiguity).

Rob
 
M

Martin Thompson

Shannon said:
No, it doesn't work. It results in the same original errors. I'm
thinking it still doesn't work because in order to cast it as a SLV it
needs to know what it is casting it FROM. (i.e. it can't figure out
what "00" is in order to re-cast it.)

OK, so I missed James' detailed message, which had the second paren
in the right place (ie two parens after data_in, not one after
"00")... sorry about that!

Cheers,
Martin
 
S

Shannon

OK, so I missed James' detailed message, which had the second paren
in the right place (ie two parens after data_in, not one after
"00")... sorry about that!

Cheers,
Martin

--
(e-mail address removed)
TRW Conekt - Consultancy in Engineering, Knowledge and Technologyhttp://www.conekt.net/electronics.html- Hide quoted text -

- Show quoted text -

Great stuff! Thanks for the detailed explaination. This group is a
wonderful resource.

I think I followed James's explaination but I have one remaining
question.

If I (properly) used a subtype to declare my array:

subtype hwid_type IS STD_LOGIC_VECTOR(7 DOWNTO 0);
TYPE reg_type IS ARRAY (0 TO NUM_REGS-1) OF hwid_type;
SIGNAL data_in : hwid_type;

Then wouldn't "reg_type" resolve down to SLV and thereby remove the
ambiguity? To refer back to James's list we would have:


1a) "&"[std_logic_vector,std_logic_vector RETURN std_logic_vector]
2d) "&"[std_logic_vector,std_logic_vector RETURN reg_type]

but reg_type is really a subtype of SLV. So in fact 1a and 2d would
be equivalent.

(I know I'm wrong. I'm just looking for that last little bit of
understanding)

Shannon
 
J

James Unterburger

Sorry, "reg_type" is not "really a subtype of SLV", it is a subtype
of a distinct type (an anonymous array type) whose element subtype
is the constrained array subtype "hwid_type".
The element *type* is still "std_logic_vector" however, and
overloading occurs using only base types, never subtypes.
OK, so I missed James' detailed message, which had the second paren
in the right place (ie two parens after data_in, not one after
"00")... sorry about that!

Cheers,
Martin

--
(e-mail address removed)
TRW Conekt - Consultancy in Engineering, Knowledge and Technologyhttp://www.conekt.net/electronics.html- Hide quoted text -

- Show quoted text -


Great stuff! Thanks for the detailed explaination. This group is a
wonderful resource.

I think I followed James's explaination but I have one remaining
question.

If I (properly) used a subtype to declare my array:

subtype hwid_type IS STD_LOGIC_VECTOR(7 DOWNTO 0);
TYPE reg_type IS ARRAY (0 TO NUM_REGS-1) OF hwid_type;
SIGNAL data_in : hwid_type;

Then wouldn't "reg_type" resolve down to SLV and thereby remove the
ambiguity? To refer back to James's list we would have:


1a) "&"[std_logic_vector,std_logic_vector RETURN std_logic_vector]
2d) "&"[std_logic_vector,std_logic_vector RETURN reg_type]

but reg_type is really a subtype of SLV. So in fact 1a and 2d would
be equivalent.

(I know I'm wrong. I'm just looking for that last little bit of
understanding)

Shannon
 
R

rickman

Sorry, "reg_type" is not "really a subtype of SLV", it is a subtype
of a distinct type (an anonymous array type) whose element subtype
is the constrained array subtype "hwid_type".
The element *type* is still "std_logic_vector" however, and
overloading occurs using only base types, never subtypes.

Given that statement, how do I apply this when working with
constrained integers...

I have a function to perform a "shift" operation on an integer,

function sllint (x, sh : natural) return natural is
begin
return x*(2**sh);
end sllint;

I am using it with a constrained integer,

SIGNAL Addr : NibbInt;

where

subtype NibbInt is Integer range 0 to 2**4-1;

usage,

Addr <= sllint(Addr, CTPDATAWDTH) + to_nat(Scfg_Din);

where Scfg_Din is an SLV (1 downto 0) and CTPDATAWDTH is an integer
constant of 2.

I am not clear on what happens when I shift the value of Addr left by
2 and significant bits extend beyond the defined range. I thought
about defining an overloaded operator for shifting NibbInt which would
use the mod operator, but you say the subtype won't be used for
overloading. So it would just use the sllint operator defined for
integer anyway.

I don't want to have to pass into the function the range of the
parameter. The usage of the function just gets too messy. I guess I
could use an sllnib operator, but I would prefer not to have to pre-
select the function and the compiler select it as an overloaded
function.

How am I looking at this wrong? Shouldn't I be able to do this?

Rick
 
M

Mike Treseler

rickman said:
function sllint (x, sh : natural) return natural is
begin
return x*(2**sh);
end sllint;
I am not clear on what happens when I shift the value of Addr left by
2 and significant bits extend beyond the defined range.

The function, as written, will return x*(2**sh)
up to the natural range. It knows nothing about
any other range unless you add a parameter
to to function.

I would use numeric_std.unsigned and the shift_left
function, and to_integer(my_uns, my_len) as needed.

-- Mike Treseler
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top