Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
14 years ago

VHDL integer causing RTL and Gate level simulation difference

I have a general question regarding the use of integers in VHDL.

If I have a lot of Array defined, we have to use integer as its index when accessing the arrays. However, when the index is converted from std_logic_vectors, it masked away the 'X' values, which masked my signal initiailization problem. Can anybody please let me know how to avoid this problem?

When running simulation, I have the following warning:

# ** Warning: NUMERIC_STD.TO_INTEGER: metavalue deteced, returning 0

The code example is below:

SIGNAL a : ARRAY (INTEGER 0 TO 15) of STD_LOGIC_VECTOR(5 DOWNTO 0);

SIGNAL b : STD_LOGIC_VECTOR(3 DOWNTO 0);

SIGNAL c : STD_LOGIC_VECTOR(5 DOWNTO 0);

c <= a(TO_INTEGER(UNSIGNED(b));

15 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Thanks very much for the reply.

    My problem is exactly 'B' gets an unknown value in the design. In RTL simulation, the good 'C' values corresponding to address 0 gets used; while in Gate level simulation, the unknown 'C' gets used.

    When there is tons of such logic in your design and we don't do reset our flops as a general principle, it is very hard to catch which one causes the problem in gate level simulation if it is not duplicate-able in RTL simulation.

    In general, we don't want to give an initial value to a variable since it is ignored by the synthesize tools.

    What we want is to have an exact RTL simulation to avoid debugging problem using gate level simulation.

    --- Quote End ---

    What this points to then is that you may need to be writing a better testbench. The signal 'c' eventually has some effect on the overall design and it being stuck at the value contained in a(0) should have caused some output to not be correct at some point...but it can only be determined to be incorrect if you take the time to write a testbench that generates stimulus sufficient to exercise the signals and that actually checks the outputs to verify that they are correct. The time it takes to write testbenches will pay off dividends over the entire lifecycle of the code as it changes over time.

    However, even when you do take that time things will get missed because it can take roughly as much time to write a testbench as it does to do the design. But it can also take just a small bit of time to get a testbench that covers a lot without much effort. The value judgment comes in as to where to draw the line about where you think you've tested this enough because there will never be an end to tests that you could've written. As you've already noticed running gate level simulations are painfully slow. Many experienced designers do not run them as a simple matter of course since there time is more effectively spent elsewhere.

    As I mentioned in the first post, one can sometimes also write self-checking right into the design itself. It's more limited then testbench testing but has the advantage of being usable in any testbench.

    Kevin Jennings
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    In general, we don't want to give an initial value to a variable since it is ignored by the synthesize tools.

    --- Quote End ---

    What makes you say that?

    FPGAs configure from bit-streams, and those bitstreams define the register states at power-on. Most devices power-up with registers set to 0, but if you initialize a signal to 1, the synthesis tool will use 'not gate pushback' to invert the input and output to the register, so as far as your logic is concerned, the register powers up to your initialized value of 1.

    Cheers,

    Dave
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks very much for the reply.

    My problem is exactly 'B' gets an unknown value in the design. In RTL simulation, the good 'C' values corresponding to address 0 gets used; while in Gate level simulation, the unknown 'C' gets used.

    When there is tons of such logic in your design and we don't do reset our flops as a general principle, it is very hard to catch which one causes the problem in gate level simulation if it is not duplicate-able in RTL simulation.

    In general, we don't want to give an initial value to a variable since it is ignored by the synthesize tools.

    What we want is to have an exact RTL simulation to avoid debugging problem using gate level simulation.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    I have a general question regarding the use of integers in VHDL.

    If I have a lot of Array defined, we have to use integer as its index when accessing the arrays. However, when the index is converted from std_logic_vectors, it masked away the 'X' values, which masked my signal initiailization problem. Can anybody please let me know how to avoid this problem?

    When running simulation, I have the following warning:

    # ** Warning: NUMERIC_STD.TO_INTEGER: metavalue deteced, returning 0

    --- Quote End ---

    Actually, the simulator didn't mask the problem, you ignored the reporting. As you can see from the message that you posted you ignored what was reported presumably since it was 'just' a warning. You can set the simulator to stop on warnings as well as errors.

    Having said that though, making use of the message that was reported can be problematic since at t=0 you can likely have a ton of such messages reporting similar warnings, so usually the better solution will be more task specific as mentioned below...

    --- Quote Start ---

    The code example is below:

    SIGNAL a : ARRAY (INTEGER 0 TO 15) of STD_LOGIC_VECTOR(5 DOWNTO 0);

    SIGNAL b : STD_LOGIC_VECTOR(3 DOWNTO 0);

    SIGNAL c : STD_LOGIC_VECTOR(5 DOWNTO 0);

    c <= a(TO_INTEGER(UNSIGNED(b));

    --- Quote End ---

    To be able to flag the problem you're seeing with this example you can create your own assertion. Let's say that you want to ignore problems at t=0 but otherwise report when 'b' has unknown values in them. The following assertion will do the trick:

    assert (t=0 ns) or (b = to_unsigned(to_integer(unsigned(b)), b'length))

    report "OOPS! Unknown value detected on 'b'" severity ERROR;

    This will create an error rather than a warning but it won't bother with things when t=0. One caveat though is that if the bits in b get set to an unknown value at t=0, and b never changes after that then the above assertion won't catch it either because it only does the check when there is a change on 'b'.

    Lastly, a way to work around it is to give b an initial value like this

    SIGNAL b : STD_LOGIC_VECTOR(3 DOWNTO 0) := (others => '0');

    The problem with this approach is that it might not reflect what the real hardware is doing for initializations in which case you've simply punted the problem downstream. Instead of being able to catch the problem in simulation, you now will think everything is good, but when you build the real hardware it is working differently.

    Kevin Jennings
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The problem is brought up with uninialized std_logic and derived types, that have a default value of 'U' in functional simulation and '0' in real hardware. Add '0' initializers to the definition of register signals or add an explicite reset initialization to achieve consistent simulation.