modelsim doesn't like my increment w/wraparound

B

Ben Voigt

Guest
I'm getting this error:
Fatal: (vsim-3421) Value 125000 for inc_tick is out of range 0 to
124999.

From this code:
SUBTYPE tick_t IS NATURAL RANGE 0 TO 124999;
SIGNAL tick, inc_tick : tick_t;
SIGNAL tick_overflow : BOOLEAN;
tick_overflow <= (tick = tick_t'HIGH);
inc_tick <= tick_t'LOW WHEN tick_overflow ELSE tick + 1;

The expression tick+1 overflowed, but it can at most glitch (the other
path of the selected assignment is active) and the setup time for the
flip-flop shouldn't be an issue.

This synthesizes just fine, but fails under simulation. I can get it
to simulate using a process and sequential if statement, but that's
about five times more code than I have now (I need the overflow flag
for other logic).

Any ideas how to do this elegantly?
 
Ben Voigt wrote:
I'm getting this error:
Fatal: (vsim-3421) Value 125000 for inc_tick is out of range 0 to
124999.

Any ideas how to do this elegantly?
Include the overflow value in the subtype range.
This value is needed for simulation.

SUBTYPE tick_t IS NATURAL RANGE 0 TO 125000;

or maybe

SUBTYPE tick_t IS NATURAL RANGE 0 TO -1 + 2**17

Synthesis utilization will not be affected.

-- Mike Treselre
 
Ben Voigt wrote:

Yes, but... that changes the period of my counter and still breaks. I
can compare against tick_t'HIGH-1 instead, but that's a magic number
which I don't like.
Sometimes the range has to exceed the rollover value.

I eventually got rid of the inc_tick signal completely, since the
process doing tick <= inc_tick can use a IF directly with no glitching
(it's clocked, the value of tick_overflow has time to settle and the
problematic addition is never simulated).
That's even better.
 
On Jul 1, 5:19 pm, Mike Treseler <mtrese...@gmail.com> wrote:
Ben Voigt wrote:
I'm getting this error:
Fatal: (vsim-3421) Value 125000 for inc_tick is out of range 0 to
124999.
Any ideas how to do this elegantly?

Include the overflow value in the subtype range.
This value is needed for simulation.

 SUBTYPE tick_t IS NATURAL RANGE 0 TO 125000;
Yes, but... that changes the period of my counter and still breaks. I
can compare against tick_t'HIGH-1 instead, but that's a magic number
which I don't like.

I eventually got rid of the inc_tick signal completely, since the
process doing tick <= inc_tick can use a IF directly with no glitching
(it's clocked, the value of tick_overflow has time to settle and the
problematic addition is never simulated).

or maybe

 SUBTYPE tick_t IS NATURAL RANGE 0 TO -1 + 2**17

Synthesis utilization will not be affected.

      -- Mike Treselre
 
Ben Voigt wrote:
I'm getting this error:
Fatal: (vsim-3421) Value 125000 for inc_tick is out of range 0 to
124999.

From this code:
SUBTYPE tick_t IS NATURAL RANGE 0 TO 124999;
SIGNAL tick, inc_tick : tick_t;
SIGNAL tick_overflow : BOOLEAN;
tick_overflow <= (tick = tick_t'HIGH);
inc_tick <= tick_t'LOW WHEN tick_overflow ELSE tick + 1;

The expression tick+1 overflowed, but it can at most glitch (the other
path of the selected assignment is active) and the setup time for the
flip-flop shouldn't be an issue.

This synthesizes just fine, but fails under simulation. I can get it
to simulate using a process and sequential if statement, but that's
about five times more code than I have now (I need the overflow flag
for other logic).

Any ideas how to do this elegantly?
How about:
tick_overflow <= (tick = tick_t'HIGH);
inc_tick <= tick_t'LOW WHEN (tick = tick_t'HIGH) ELSE tick + 1;
?

Kind regards,

Pieter Hulshoff

PS: I hope this is inside a clocked process, otherwise you should get some
interesting synthesis results. :)
 
On 1 Jul., 23:04, Ben Voigt <richardvo...@gmail.com> wrote:
I'm getting this error:
Fatal: (vsim-3421) Value 125000 for inc_tick is out of range 0 to
124999.

From this code:
   SUBTYPE tick_t IS NATURAL RANGE 0 TO 124999;
   SIGNAL tick, inc_tick : tick_t;
   SIGNAL tick_overflow : BOOLEAN;
   tick_overflow <= (tick = tick_t'HIGH);
   inc_tick <= tick_t'LOW WHEN tick_overflow ELSE tick + 1;

The expression tick+1 overflowed, but it can at most glitch (the other
path of the selected assignment is active) and the setup time for the
flip-flop shouldn't be an issue.

This synthesizes just fine, but fails under simulation.  I can get it
to simulate using a process and sequential if statement, but that's
about five times more code than I have now (I need the overflow flag
for other logic).

Any ideas how to do this elegantly?
Hi,
if this is just a n error that happens on the delta-cycle level, it
has no real meaning, but is still annoying.
Likle others said it would be a good idea to expand the range of your
type by one.
Maybe like this:

SUBTYPE tick_t IS NATURAL RANGE 0 TO 125000;
SIGNAL tick, inc_tick : tick_t;
SIGNAL tick_overflow : BOOLEAN;
tick_overflow <= (tick = tick_t'HIGH-1); -- regard the -1 here.
your flag will come at the right time
inc_tick <= tick_t'LOW WHEN tick_overflow ELSE tick + 1;

Give it a try and if it works take a look at the delta-cycles of
signal inc_tick.
You probably will still find the value of 125000 there, but only for a
few delta cycles, then it should be overridden by 0.

Have a nice simulation
Eilert
 
On Wed, 1 Jul 2009 14:04:48 -0700 (PDT), Ben Voigt <richardvoigt@gmail.com>
wrote:

I'm getting this error:
Fatal: (vsim-3421) Value 125000 for inc_tick is out of range 0 to
124999.

From this code:
SUBTYPE tick_t IS NATURAL RANGE 0 TO 124999;
SIGNAL tick, inc_tick : tick_t;
SIGNAL tick_overflow : BOOLEAN;
tick_overflow <= (tick = tick_t'HIGH);
inc_tick <= tick_t'LOW WHEN tick_overflow ELSE tick + 1;

The expression tick+1 overflowed, but it can at most glitch (the other
path of the selected assignment is active) and the setup time for the
flip-flop shouldn't be an issue.

This synthesizes just fine, but fails under simulation. I can get it
to simulate using a process and sequential if statement, but that's
about five times more code than I have now (I need the overflow flag
for other logic).

Any ideas how to do this elegantly?
Looks like an order-of-evaluation thing; when tick becomes tick'high, it
propagates into both next_tick and tick_overflow. Therefore inc_tick WILL
overflow until tick_overflow propagates in the next delta cycle.

Obviously you meant

inc_tick <= tick_t'LOW WHEN tick = tick_t'HIGH ELSE tick + 1;

which, by avoiding the race, cannot raise the constraint error.
The trick is to do this without duplicating code which WILL get out of sync
during later updates.

function overflow (t:tick_t) return boolean is
begin
return tick = tick_t'HIGH;
end function overflow;

tick_overflow <= overflow(tick);
inc_tick <= tick_t'LOW WHEN overflow(tick) ELSE tick + 1;

is one answer.

- Brian
 
On Wed, 1 Jul 2009 14:04:48 -0700 (PDT), Ben Voigt wrote:


SUBTYPE tick_t IS NATURAL RANGE 0 TO 124999;
SIGNAL tick, inc_tick : tick_t;
SIGNAL tick_overflow : BOOLEAN;
tick_overflow <= (tick = tick_t'HIGH);
inc_tick <= tick_t'LOW WHEN tick_overflow ELSE tick + 1;

I can get it
to simulate using a process and sequential if statement, but that's
about five times more code than I have now
Hmmm... let's compare

tick_overflow <= (tick = tick_t'HIGH);
inc_tick <= tick_t'LOW WHEN tick_overflow ELSE tick + 1;

with this, which won't suffer the delta-glitches in simulation
and (I believe) reflects the same design intent:

process (tick) begin
if tick = tick_t'HIGH then
tick_overflow <= '1';
inc_tick <= tick_t'LOW;
else
tick_overflow <= '0';
inc_tick <= tick + 1;
end if;
end process;

OK, it's a few more _lines_, but it's not very much more code;
and I find it hugely more readable than the conditional
assignments, which look to me like someone trying to
use VHDL to describe a schematic.

Better still, roll the whole mess into a single clocked
process (your counter is clocked, right????), using a
variable that captures the next-count value and tests it
to generate a glitch-free, synchronous overflow output.
Add resets, mode controls etc. to taste:

-- utility function that everyone needs
function to_SL(flag: boolean) return std_logic is
begin
if flag then return '1'; else return '0'; end if;
end;

-- bounded counter with overflow indication
process (clock)
variable next_tick: tick_t;
begin
if rising_edge (clock) then

if tick = tick_t'HIGH then
next_tick := tick_t'LOW;
else
next_tick := tick + 1;
end if;

if count_enable = '1' then
tick <= next_tick;
tick_overflow <= to_SL(next_tick = tick_t'HIGH);
end if;

end if;
end process;
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
Jonathan's response illustrates another subtle issue: scope control.

From the OP example we cannot tell whether tick_overflow, inc_tick, or
tick itself is needed elsewhere, since they are all signals. Since we
don't see the actual update to tick (hopefully synchronous!), we can
assume that inc_tick is needed there, but where else?

By using variables, Jonathan has declared that next_tick (FKA
inc_tick) is only needed within that process, in which only the
signals tick and tick_overflow are used/exported. If it turns out that
tick itself is not really needed anywhere (just tick_overflow), then
tick could be a variable too, and we would then be able to work with
up or down counters, whichever might be more efficient in the target
architecture. Sometimes detecting a rollover on a down counter
requires less logic. By isolating tick from external access, it can be
changed/optimized without fear of breaking something else.

By deliberately controlling scope, you are telling future maintainers
(perhaps even yourself in a few weeks/months/years) important
information about the ripple effect of potential changes.

Block statements can be used for "local signals" to control scope as
well, if you prefer the delayed-update semantics of signal
assignments.

Andy
 
On Tue, 7 Jul 2009 07:17:21 -0700 (PDT), Andy wrote:

another subtle issue: scope control.
[...]
By isolating tick from external access, it can be
changed/optimized without fear of breaking something else.

By deliberately controlling scope, you are telling future maintainers
(perhaps even yourself in a few weeks/months/years) important
information about the ripple effect of potential changes.
Beautifully said, and I couldn't agree more. Is that
statement in the public domain so I can repeat it
frequently and openly? Especially when talking to
Verilog folk, for many of whom "scope control" means
the timebase knob ;-)

Block statements can be used for "local signals" to control scope as
well, if you prefer the delayed-update semantics of signal
assignments.
That's true, and it's something I all too often ignore.
One of my reasons for ignoring blocks is a vague
folk-memory that tool support for blocks is not as
good as it might be. Have you (or anyone) ever encountered
problems with VHDL block statements in real tools?

Thanks
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
On Tue, 7 Jul 2009 10:11:37 -0700 (PDT), sleeman wrote:

 Have you (or anyone) ever encountered
problems with VHDL block statements in real tools?

It would be ironic if it there were such problems, since blocks are
(during elaboration, per the LRM) the penultimate simplification of
the structural aspect the entire design. There's nothing "closer to
the metal" in terms of language semantics until the entire design is
turned into the simulator's "grist for the mill" : nets and processes.
You're right, of course. I don't even know where my
irrational avoidance of blocks originally came from -
probably just pig-headedness, or ignorance. They're
a rather useful way to localize type, signal and
subprogram declarations in a big architecture.

I think we would all be pretty cross if our
tools were to choke on

G: if TRUE generate
...
begin
...
end generate G;

and it's hard to find any difference between that and

G: BLOCK -- with no ports and no guard
...
begin
...
end block G;

Interestingly, our Golden Reference Guide still suggests
that blocks are not widely supported by synthesis tools.
Maybe it's time to review that statement.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
On Jul 7, 12:54 pm, Jonathan Bromley <jonathan.brom...@MYCOMPANY.com>
wrote:

That's true, and it's something I all too often ignore.
One of my reasons for ignoring blocks is a vague
folk-memory that tool support for blocks is not as
good as it might be.  Have you (or anyone) ever encountered
problems with VHDL block statements in real tools?
It would be ironic if it there were such problems, since blocks are
(during elaboration, per the LRM) the penultimate simplification of
the structural aspect the entire design. There's nothing "closer to
the metal" in terms of language semantics until the entire design is
turned into the simulator's "grist for the mill" : nets and processes.

- Kenn
 
Beautifully said, and I couldn't agree more.  Is that
statement in the public domain so I can repeat it
frequently and openly?  Especially when talking to
Verilog folk, for many of whom "scope control" means
the timebase knob ;-)
Repeat at will...

I've not used block statements very much, and not any that I recall in
synthesis; I tend to use variables/processes instead. To be fair, my
processes tend to be on the large side (too bad blocks can't be used
inside processes).

Andy
 

Welcome to EDABoard.com

Sponsor

Back
Top