Synthesis Only

J

Jonathan Ross

I'm trying to work around a bug in iSim where types with the
enum_encoding attribute set such that they're one-hot encoded gives
different results than in synthesis - essentially there's an off-by-
one error in this case in the simulation for initialization. I've
informed Xilinx, though the person handling the webcase seemed quite
uninterested and so I have little faith it'll be fixed any time soon.
I'm having trouble coming up with an acceptable work around. Take the
following example:

PROCESS( CLK )
TYPE TestType IS ( A, B, C );
ATTRIBUTE enum_encoding : string;
ATTRIBUTE enum_encoding OF TestType : TYPE IS "100 010 001";
VARIABLE Test : TestType := A;
BEGIN
...
END PROCESS;

XST results in Test having an initial value of A, and in iSim the
initial value is B (if I had assigned B, XST would use B, and iSim
would use C).

The only way I've found to work around this is to use a function as
follows:

FUNCTION KludgeInit
RETURN TestType IS
VARIABLE IsSynth : BOOLEAN := TRUE;
BEGIN
-- pragma synthesis_off
IsSynth := FALSE;
-- pragma synthesis_on
IF IsSynth THEN
RETURN B;
ELSE
RETURN A;
END IF;
END KludgeInit;

Of course, TestType must be declared B, A, C - there's no way to get
at the first item in the list due to the error (using the last item
causes iSim to crash.)

This is horrific. Is there no way for me to disable enum_encoding
entirely during simulation? Is there nothing like:

-- pragma simulation_off
....
-- pragma simulation_on
 
K

KJ

I'm trying to work around a bug in iSim where types with the
enum_encoding attribute set such that they're one-hot encoded gives
different results than in synthesis - essentially there's an off-by-
one error in this case in the simulation for initialization.

Just noting here that simulation doesn't give a hoot about the
enum_encoding attributes.
I've
informed Xilinx, though the person handling the webcase seemed quite
uninterested and so I have little faith it'll be fixed any time soon.
I'm having trouble coming up with an acceptable work around. Take the
following example:

PROCESS( CLK )
    TYPE TestType IS ( A, B, C );
    ATTRIBUTE enum_encoding : string;
    ATTRIBUTE enum_encoding OF TestType : TYPE IS "100 010 001";
    VARIABLE Test : TestType := A;
BEGIN
   ...
END PROCESS;

XST results in Test having an initial value of A,

This is correct...
and in iSim the
initial value is B

A few possibilities come to mine:
- iSim may be wrong
- You've missed a synthesis warning/note that said something to the
effect that the encoding of Test is not the same as what you've put
into the 'enum_encoding' attribute.
- It could be that you're misinterpreting which nodes are which.
Presumably 'Test' gets synthesized as actual signals Test(2-0), so
when you say "100" for 'A', is Test(2) = '1' or is Test(0)? How do
you know this to be true? Check the synthesis notes for confirmation.
- From your snippet, one can't tell if Test will result in flops or
not. If they are not the outputs of flip flops, then 'Test' might get
combined with other combinatorial logic in your design but still get
assigned the name 'Test' and you're interpreting that node to be the
same thing as listed in your source code. Assign an output signal of
the top level of the design to 'Test' and see what really pops out.
This is horrific. Is there no way for me to disable enum_encoding
entirely during simulation? Is there nothing like:

-- pragma simulation_off
...
-- pragma simulation_on

Any time you try to make simulation different from synthesis you're
starting down a bad path. The likely cause is probably listed above.
Peruse the synthesis warnings, make 'Test' temporarily be an output of
the design if you have to in order to debug and trudge forward.

Kevin Jennings
 
J

Jonathan Ross

Just noting here that simulation doesn't give a hoot about the
enum_encoding attributes.












This is correct...


A few possibilities come to mine:
- iSim may be wrong
- You've missed a synthesis warning/note that said something to the
effect that the encoding of Test is not the same as what you've put
into the 'enum_encoding' attribute.
- It could be that you're misinterpreting which nodes are which.
Presumably 'Test' gets synthesized as actual signals Test(2-0), so
when you say "100" for 'A', is Test(2) = '1' or is Test(0)?  How do
you know this to be true?  Check the synthesis notes for confirmation.
- From your snippet, one can't tell if Test will result in flops or
not.  If they are not the outputs of flip flops, then 'Test' might get
combined with other combinatorial logic in your design but still get
assigned the name 'Test' and you're interpreting that node to be the
same thing as listed in your source code.  Assign an output signal of
the top level of the design to 'Test' and see what really pops out.





Any time you try to make simulation different from synthesis you're
starting down a bad path.  The likely cause is probably listed above.
Peruse the synthesis warnings, make 'Test' temporarily be an output of
the design if you have to in order to debug and trudge forward.

Kevin Jennings

There was no warning. It's a highly repeatable issue. It probably went
undiscovered because it doesn't occur if you set a value during reset
- only if you initialize a value.

The workaround we finally came up with was to use a function to
produce a one-hot encoding for the string argument of enum_encoding.
When it doesn't detect simulation it produces a binary encoding
instead.
 
K

KJ

There was no warning. It's a highly repeatable issue. It probably went
undiscovered because it doesn't occur if you set a value during reset
- only if you initialize a value.

The only place you should ever consider using an initial value is in
the shift register that synchronizes an external reset signal to a
clock. You shouldn't use initial values anywhere else. You likely
have no control over when the clock starts up relative to the design
coming alive which means you have no way of guaranteeing setup/hold
times are met on that very first clock cycle. That's why you should
always design in an explicit reset...and why you found that it 'works'
for you when you do that.
The workaround we finally came up with was to use a function to
produce a one-hot encoding for the string argument of enum_encoding.
When it doesn't detect simulation it produces a binary encoding
instead.

When you have the solution and found that it works (i.e. using an
explicit reset) then why would you even consider a workaround?

As I mentioned before, any time you try to make simulation different
from synthesis you're starting down a bad path. That bad path will
end up biting you in the rear eventually if you continue to follow it.

KJ
 
J

Jonathan Ross

The only place you should ever consider using an initial value is in
the shift register that synchronizes an external reset signal to a
clock.  You shouldn't use initial values anywhere else.  You likely
have no control over when the clock starts up relative to the design
coming alive which means you have no way of guaranteeing setup/hold
times are met on that very first clock cycle.  That's why you should
always design in an explicit reset...and why you found that it 'works'
for you when you do that.


When you have the solution and found that it works (i.e. using an
explicit reset) then why would you even consider a workaround?

As I mentioned before, any time you try to make simulation different
from synthesis you're starting down a bad path.  That bad path will
end up biting you in the rear eventually if you continue to follow it.

KJ

We tend to use a lot of initial values and have never had trouble with
them in hardware - only in simulation (due to the off-by-one error). I
see what you're saying, though either the Xilinx tools or board must
be compensating for it or I'd expect we'd have been bitten by it by
now (we've been doing this for a long time and never seen an issue).
We use initial values instead of reset whenever there's no harm
running the process during RESET with the hope of shortening logic
paths.

That said, you're right. I'm now deeply worried we've been getting
lucky. Does anyone know about this in detail? We use Virtex-6 chips
and we've been doing our initial development on the ML605 board from
Xilinx. Are we going to have a catastrophic failure when we move to
our production board?
 
R

rickman

We tend to use a lot of initial values and have never had trouble with
them in hardware - only in simulation (due to the off-by-one error). I
see what you're saying, though either the Xilinx tools or board must
be compensating for it or I'd expect we'd have been bitten by it by
now (we've been doing this for a long time and never seen an issue).
We use initial values instead of reset whenever there's no harm
running the process during RESET with the hope of shortening logic
paths.

That said, you're right. I'm now deeply worried we've been getting
lucky. Does anyone know about this in detail? We use Virtex-6 chips
and we've been doing our initial development on the ML605 board from
Xilinx. Are we going to have a catastrophic failure when we move to
our production board?

I'm not clear on what your reset concept is. It used to be that the
tools did not use initializations in synthesis. I believe now that
many of them do. The values used in the initialization is imposed on
registers coming out of configuration and if the GSR is connected
externally, this will give the same result. Check with your synthesis
vendor to find out if initialization is supported. However...

The issue with using GSR is not asserting it, but removing it. The
GSR path is slow and if your clock is running and any clock enables
are asserted different registers are released at different clock
cycles than others. This can result in state machines ending up in
invalid states, counters at wrong initial counts, etc. In essence,
your synchronous logic is out of sync!

There are many ways to deal with this. Often various parts of the
design will do nothing until some condition enables them. These parts
don't need to be changed unless there is a way they can be enabled
when GSR is released. If any parts of the design need to be held in
reset and released on the same clock cycle, then you need a sync reset
on those portions. You can do this on a section by section basis so
that you don't have one sync reset driving the entire design. Or you
can use one common sync reset to the entire design which will most
likely be replicated anyway. But this should be coded as a sync
reset, not an async reset.

Rick
 
J

Jonathan Ross

I'm not clear on what your reset concept is.  It used to be that the
tools did not use initializations in synthesis.  I believe now that
many of them do.  The values used in the initialization is imposed on
registers coming out of configuration and if the GSR is connected
externally, this will give the same result.  Check with your synthesis
vendor to find out if initialization is supported.  However...

The issue with using GSR is not asserting it, but removing it.  The
GSR path is slow and if your clock is running and any clock enables
are asserted different registers are released at different clock
cycles than others.  This can result in state machines ending up in
invalid states, counters at wrong initial counts, etc.  In essence,
your synchronous logic is out of sync!

There are many ways to deal with this.  Often various parts of the
design will do nothing until some condition enables them.  These parts
don't need to be changed unless there is a way they can be enabled
when GSR is released.  If any parts of the design need to be held in
reset and released on the same clock cycle, then you need a sync reset
on those portions.  You can do this on a section by section basis so
that you don't have one sync reset driving the entire design.  Or you
can use one common sync reset to the entire design which will most
likely be replicated anyway.  But this should be coded as a sync
reset, not an async reset.

Rick

I found the following post:
http://forums.xilinx.com/t5/Virtex-...ration-and-GSR/m-p/98892/highlight/true#M7728

All of our state machines have either no reset logic (purely
initialized) or synchronous reset logic, so it sounds like we're safe.
 
R

rickman

I found the following post:http://forums.xilinx.com/t5/Virtex-Family-FPGAs/Virtex-5-and-Virtex-6...

All of our state machines have either no reset logic (purely
initialized) or synchronous reset logic, so it sounds like we're safe.

Do you know if the initialized machines are init the way you want? I
don't depend on init values to set my GSR state...

BTW, if you think using init values somehow gets you around the GSR
problem, you don't understand what I am saying. If the init values
are used for synthesis, then they are used to set the GSR behavior of
the registers. You then have to deal with how the register comes out
of reset.

Are you using an external reset of any kind? Is that the sync reset?
If so, how do you activate the GSR reset for the rest of the chip?

Rick
 
K

KJ

I found the following post:http://forums.xilinx.com/t5/Virtex-Family-FPGAs/Virtex-5-and-Virtex-6...

All of our state machines have either no reset logic (purely
initialized) or synchronous reset logic, so it sounds like we're safe.

I'm not seeing how you think you're safe if you have synchronous logic
that depends only on initial values. The issue is not whether or not
the initial values get loaded, but how the transition from
configuration to user mode with a running clock happens and whether it
occurs at a time which violates a setup or hold time requirement.

Any flop that is part of a feedback path (such as state machines or
counters) are candidates for problems; any flop that is not part of a
feedback (such as a synchronizer or delay) will not be a problem.

Having said that, the odds of seeing such a failure might also be
rather slim since configuration generally happens only once per power
cycle. So, yes you are getting lucky, but you're also not in a high
probability of failure situation. Still, good design practice
generally dictactes that you should not rely on initial values for two
reasons:
- Potential timing issues at end of configuration as just discussed
- No way to have the design recover from any unusual situation without
cycling power

Kevin Jennings
 
R

rickman

I'm not seeing how you think you're safe if you have synchronous logic
that depends only on initial values.  The issue is not whether or not
the initial values get loaded, but how the transition from
configuration to user mode with a running clock happens and whether it
occurs at a time which violates a setup or hold time requirement.

Any flop that is part of a feedback path (such as state machines or
counters) are candidates for problems; any flop that is not part of a
feedback (such as a synchronizer or delay) will not be a problem.

Having said that, the odds of seeing such a failure might also be
rather slim since  configuration generally happens only once per power
cycle.  So, yes you are getting lucky, but you're also not in a high
probability of failure situation.  Still, good design practice
generally dictactes that you should not rely on initial values for two
reasons:
- Potential timing issues at end of configuration as just discussed
- No way to have the design recover from any unusual situation without
cycling power


Depending on initial states does not require a power cycle. Most, if
not all FPGAs can be reloaded by asserting a pin, often called PRGM or
something similar. Otherwise I agree with you.

Rick
 
K

KJ

Depending on initial states does not require a power cycle.  Most, if
not all FPGAs can be reloaded by asserting a pin, often called PRGM or
something similar.  Otherwise I agree with you.

Rick

You're right, I thought of that too soon after clicking on 'Send'.

KJ
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top