ModelSim vs Aldec -- odd difference

A

Andy Peters

I'm evaluating Aldec Active-HDL v8.2, and it stumbles on the following
function:

function TimeToClocks (
timer : time;
clkper : time)
return natural is
variable division : natural;
variable remainder : time;
begin
division := timer / clkper;
remainder := timer rem clkper;

-- always round UP if the remainder is not zero.
if remainder /= (0 FS) then
division := division + 1;
end if;

division := division - 1;
return division;
end function TimeToClocks;

The compiler, set to analyzer to VDHL-2002, throws three errors, all
from the remainder assignment:

# Error: COMP96_0077: consts.vhdl : (765, 22): Assignment target
incompatible with right side. Expected type 'TIME'.
# Error: COMP96_0071: consts.vhdl : (765, 22): Operator "rem" is not
defined for such operands.
# Error: COMP96_0104: consts.vhdl : (765, 22): Undefined type of
expression.

What's odd is that ModelSim, similarly set to use the 2002 standard,
accepts the code without complaint. What's odder still is that if I
change remainder's type to natural. ModelSim throws the following
error:

# ** Error: consts.vhdl(765): Target type std.standard.natural in
variable assignment is different from expression type
std.standard.time.

and Active-HDL doesn't even try:

# Error: COMP96_0071: consts.vhdl : (765, 22): Operator "rem" is not
defined for such operands.

So my assumption was that dividing time by time would give me a
unitless result.

I can accept that dividing time by time would be bad, but why does
ModelSim accept it?

I suppose casting to natural would be a reasonable solution.

-a
 
S

sleeman

I'm evaluating Aldec Active-HDL v8.2, and it stumbles on the following
function:

   function TimeToClocks (
        timer  : time;
        clkper : time)
        return natural is
        variable division  : natural;
        variable remainder : time;
    begin
        division  := timer / clkper;
        remainder := timer rem clkper;

        -- always round UP if the remainder is not zero.
        if remainder /= (0 FS) then
            division := division + 1;
        end if;

        division := division - 1;
        return division;
    end function TimeToClocks;

The compiler, set to analyzer to VDHL-2002, throws three errors, all
from the remainder assignment:

# Error: COMP96_0077: consts.vhdl : (765, 22): Assignment target
incompatible with right side. Expected type 'TIME'.
# Error: COMP96_0071: consts.vhdl : (765, 22): Operator "rem" is not
defined for such operands.
# Error: COMP96_0104: consts.vhdl : (765, 22): Undefined type of
expression.

What's odd is that ModelSim, similarly set to use the 2002 standard,
accepts the code without complaint. What's odder still is that if I
change remainder's type to natural. ModelSim throws the following
error:

# ** Error: consts.vhdl(765): Target type std.standard.natural in
variable assignment is different from expression type
std.standard.time.

and Active-HDL doesn't even try:

# Error: COMP96_0071: consts.vhdl : (765, 22): Operator "rem" is not
defined for such operands.

So my assumption was that dividing time by time would give me a
unitless result.

I can accept that dividing time by time would be bad, but why does
ModelSim accept it?

I suppose casting to natural would be a reasonable solution.

-a

It looks like the LRM doesn't define an implicit "rem" for physical
types in the same way it defines "/" (which takes two of the same
equivalent types and produces a universal integer, which can then be
converted to whatever integer type you need). I'm not entirely sure
why it doesn't define it, since a physical type value denotes an
integer decorated with the physical type's primary unit, which ought
to be sufficient to construct a well-defined "rem" operator.

Defining "remainder" as a natural in your code is (I think)
irrelevant, since "rem" on the RHS isn't defined to begin with - it
just produced different messages.

- Kenn
 
A

Andy Peters

Why should it be bad? it yields a unitless result; it is perfectly valid to use
in e.g. a prescaler or clock divider.

That was my original thought: time divided by time is unitless, so the
whole thing should just work.
The remainder is of the original type, of course (e.g. a fraction of a second).
So all compilers should reject "rem" in this context with natural result, as
they do.

OK, that is what I was missing.
No. (That way leads to C :)
Noooooooooo!!

A more reasonable solution would be to supply the missing function.

Which I shall do, by stealing your code below :)
If so, that does look like an omission to me. It's interesting (but not so
unusual) that Modelsim does more than the standard requires.

Ashenden (2nd edition, p39) tells us that the definition of the
physical type time is implementation-defined. And I suppose that
ModelSim's implementation differs from Aldec's.
I would define the missing function as

function rem (a,b:time) return time is
variable temp: natural := a/b;
begin
   return a - temp*b;
end function rem;

I don't expect you can fix the syntax by
function "rem" ... in the same way function "/" ...
allows overloading the / operator, so you are probably stuck with
calling it as
remainder := rem(timer, clkper);

I don't mind calling it as a function -- I just want it to work!

Thanks,
-a
 
A

Andy Peters

After a quick test -- "rem" of course is a keyword and both ModelSim
and Aldec throw an "expecting string or identifier" error. Changing
the name of the function to something like rem_time works.

-a
 
S

sleeman

After a quick test -- "rem" of course is a keyword and both ModelSim
and Aldec throw an "expecting string or identifier" error. Changing
the name of the function to something like rem_time works.

-a

It is legal to overload a function in this way, but you need to use
quotes around the identifier, e.g.

function "rem" (a,b: time)
....
end "rem"

- Kenn
 
A

Andy Peters

It is legal to overload a function in this way, but you need to use
quotes around the identifier, e.g.

function "rem" (a,b: time)
...
end "rem"

 - Kenn

Yep, that works! This is one of the dustier corners of VHDL.

-a
 
A

Andy Peters

It is legal to overload a function in this way, but you need to use
quotes around the identifier, e.g.

function "rem" (a,b: time)
...
end "rem"

 - Kenn

Ah, well, XST throws an unhappy error:
ERROR:Xst:781 - "E:/Projects/foo/bar.vhdl" line 284: Type definition
is not authorized : 'PhysicalType'.

The error wasn't actually in the "rem" function. Rather, it was thrown
when the parser hit a constant definition in the declarative part of
an architecture:

constant INITDELAY : natural := TimeToClocks(INITDELAY_TIME,
CLKPER);

where both INITDELAY_TIME and CLKPER are in time units.

That will teach me to be clever.

-a
 
A

Andy Peters

Better, teach XST to be clever.

It would be useful to boil this down to the simplest example that works (prints
a sensible message) in Modelsim and errors in XST, and submit it as a webcase.

First line support may just want to sell you a workaround, so persist until they
actually acknowledge it's a bug (or missing feature), raise a CR (change
request) and inform you of the CR number.

Xilinx do usually fix things, eventually.

Meanwhile we do the best we can with broken tools.

It's an error because XST simply doesn't support physical types,
period, even if said physical type is only used as part of an equation
that sets an integer constant. Which is why it SHOULD be supported, at
least for that use, and yes, I will open a Web Case and demand a
change request.

-a
 
J

JimLewis

Andy,
Caution with overloading either "rem" and "mod" since the are
overloaded in VHDL-2008. Which may explain why it works in one
simulator and not another.

If you do not want to use VHDL-2008 just yet, you might give your
function a different name.

Cheers,
Jim
 
A

Andy Peters

Andy,
Caution with overloading either "rem" and "mod" since the are
overloaded in VHDL-2008.  Which may explain why it works in one
simulator and not another.

If you do not want to use VHDL-2008 just yet, you might give your
function a different name.

No 2008 here, yet, as XST doesn't support it. As for the overloading,
aren't most operators overloaded? If my overloaded function has a
different signature (different arguments) from the standard, then
isn't the elaborator supposed to sort this all out?

-a
 

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

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top