Simulation mismatch for a basic example (Verilog-XL vs Model

S

Scott

Guest
I know that Verilog spec suggests that any pulse which is less than the
propagation delay of a given module should be filtered by default (the
default 'inertial' mode filters, and transport mode passes the pulse
after the propagation delay). If it is exactly equal to the
propagation delay, I would assume that it is a valid pulse, and should
not be filtered.

I ran into a problem when trying to switch simulators on a very large
design. The rest of the team uses Verilog-XL, but I prefer ModelSim.
However, I couldn't get any cases from my testbench to pass under
modelsim. I tracked it down to a single-cycle unknown pulse, which
leaks from our custom D-flop. This 'X' values comes from a cmos
primitive whose p-cntrl and n-cntrl necessarily conflict for 1 cycle.
In Veriog-XL, the unknown pulse is filtered at the very next component.
In every other simulator I've tried, it's allowed to continue.
Consider the following simple example:

module testbench;
reg in;
wire out1, out2;
not (strong0, strong1) #(1,1) inv1 (out1, in);
not (strong0, strong1) #(1,1) inv2 (out2, out1);
initial begin
$monitor("%t: inv_in=%b - inv_out1=%b - inv_out2=%b",
$stime, in, out1, out2);
in = 1'b1;
#10 in = 1'bx;
#01 in = 1'b0;
#10 in = 1'bx;
#01 in = 1'b1;
#10 $finish;
end
endmodule

Output from Verilog-XL:
0: inv_in=1 - inv_out1=x - inv_out2=x
1: inv_in=1 - inv_out1=0 - inv_out2=x
2: inv_in=1 - inv_out1=0 - inv_out2=1
10: inv_in=x - inv_out1=0 - inv_out2=1
11: inv_in=0 - inv_out1=x - inv_out2=1
12: inv_in=0 - inv_out1=1 - inv_out2=0
21: inv_in=x - inv_out1=1 - inv_out2=0
22: inv_in=1 - inv_out1=x - inv_out2=0
23: inv_in=1 - inv_out1=0 - inv_out2=1

Output from ModelSim, Icarus, and any other simulator:
0: inv_in=1 - inv_out1=x - inv_out2=x
1: inv_in=1 - inv_out1=0 - inv_out2=x
2: inv_in=1 - inv_out1=0 - inv_out2=1
10: inv_in=x - inv_out1=0 - inv_out2=1
11: inv_in=0 - inv_out1=x - inv_out2=1
12: inv_in=0 - inv_out1=1 - inv_out2=x
13: inv_in=0 - inv_out1=1 - inv_out2=0
21: inv_in=x - inv_out1=1 - inv_out2=0
22: inv_in=1 - inv_out1=x - inv_out2=0
23: inv_in=1 - inv_out1=0 - inv_out2=x
24: inv_in=1 - inv_out1=0 - inv_out2=1

Does anyone know why this doesn't behave the same in Verilog-XL?

The next question, which is one we have to internally answer, is which
behavior do we want. I don't think I can convince the whole team to
switch away from Verilog-XL, even if it is behaving incorrectly. It'd
be nice if I had a way to tell ModelSim to behave the same as
Verilog-XL. Then I could at least have a smoother transition while we
incremently adjust our models.
 
Scott wrote:
I know that Verilog spec suggests that any pulse which is less than the
propagation delay of a given module should be filtered by default (the
default 'inertial' mode filters, and transport mode passes the pulse
after the propagation delay). If it is exactly equal to the
propagation delay, I would assume that it is a valid pulse, and should
not be filtered.
I believe that this is technically a race condition. You have multiple
events scheduled to happen at the same time. The output of the
primitive is scheduled to change at the same time that the input is
scheduled to change and cause the primitive to be evaluated again. If
the input is allowed to change first, and then the primitive is allowed
to evaluate and change the output, all before the output changes, the
pulse will be filtered. If the output is allowed to change before both
the input changes and the primitive is evaluated, then the pulse will
not be filtered.

This kind of event ordering is explicitly nondeterministic in the
language. Either behavior is valid.

Does anyone know why this doesn't behave the same in Verilog-XL?
It is all a matter of how the scheduling queues work, and the
evaluation order that results. For your original cmos example, things
get even more complex because there is the extra evaluation of the
multiple-driver resolution.

The next question, which is one we have to internally answer, is which
behavior do we want. I don't think I can convince the whole team to
switch away from Verilog-XL, even if it is behaving incorrectly. It'd
be nice if I had a way to tell ModelSim to behave the same as
Verilog-XL. Then I could at least have a smoother transition while we
incremently adjust our models.
I doubt that ModelSim would be able to match all the details of the
Verilog-XL scheduling and evaluation algorithms. You might be able to
get Verilog-XL to match ModelSim more closely for this situation by
turning off certain optimizations, but it would hurt simulation
performance.

You could try modifying the design to put some extra zero-delay
elements in one of the paths, to try to influence the evaluation order
in one simulator or the other. I suspect that it will be easier to
influence ModelSim's behavior this way. It isn't a good answer, but
you are dealing with undefined behavior.
 
sharp@cadence.com wrote:
I believe that this is technically a race condition. You have multiple
events scheduled to happen at the same time. The output of the
primitive is scheduled to change at the same time that the input is
scheduled to change and cause the primitive to be evaluated again. If
the input is allowed to change first, and then the primitive is allowed
to evaluate and change the output, all before the output changes, the
pulse will be filtered. If the output is allowed to change before both
the input changes and the primitive is evaluated, then the pulse will
not be filtered.

This kind of event ordering is explicitly nondeterministic in the
language. Either behavior is valid.
I think I (mostly) follow what you're saying here. But, if the the
scheduler is using a proper queue, shouldn't the evaluation of the
input at the current time not effect the output until the first cycle
after it's propagation delay? For example, time #10-12 bother me in
the Verilog-XL output:

10: inv_in=x - inv_out1=0 - inv_out2=1
11: inv_in=0 - inv_out1=x - inv_out2=1
12: inv_in=0 - inv_out1=1 - inv_out2=0

At time 11, the input to the first inverter goes from 'x' to 0, yet
inverter 1 is still 1 cycle behind this change... Even to time 12.
However, the second inverter, whose input is 'x' at time 11, goes
straight to '0' at time 12. As if it was immediately evaluating the
input at the current time, not the last scheduled input value. I do
think I agree with you that there is a race condition in the case of
'input pulse width'=='propagation delay'... But I'm still perplexed
why it seems to be treated differently by the first and second
component of this circuit.

You could try modifying the design to put some extra zero-delay
elements in one of the paths, to try to influence the evaluation order
in one simulator or the other. I suspect that it will be easier to
influence ModelSim's behavior this way. It isn't a good answer, but
you are dealing with undefined behavior.
I can see how the 'unknowns' would be filtered if I used a component
whose delay is greater than the pulse width (by at least 1 cycle) of
the unknown. Can you elaborate more on how extra zero-delay elements
would help?

I should mention that, for the most part, either behavior is fine.
Since the 'x' does eventually settle out in either simulator, it
doesn't really effect the operation of my circuit. The problem comes
about when this 'x' leaks into one of our oscillator models. It gets
stuck in a feedback path real fast and latches up the oscillator
output. I could get the designer to update the model for that, so that
I could have a design which is simulator-agnostic (and tolerant of
these glitches), but he is understandably hesitant to make a change
when it works just fine for him.
 
Scott wrote:
For example, time #10-12 bother me in
the Verilog-XL output:

10: inv_in=x - inv_out1=0 - inv_out2=1
11: inv_in=0 - inv_out1=x - inv_out2=1
12: inv_in=0 - inv_out1=1 - inv_out2=0

At time 11, the input to the first inverter goes from 'x' to 0, yet
inverter 1 is still 1 cycle behind this change... Even to time 12.
However, the second inverter, whose input is 'x' at time 11, goes
straight to '0' at time 12. As if it was immediately evaluating the
input at the current time, not the last scheduled input value. I do
think I agree with you that there is a race condition in the case of
'input pulse width'=='propagation delay'... But I'm still perplexed
why it seems to be treated differently by the first and second
component of this circuit.
I agree with you that the behavior of the second delay is perplexing,
and cannot be explained by the kind of race condition that allows the X
pulse to pass. This is not normal inertial delay behavior.

I have a vague memory of having run into something similar before, and
having it explained by someone familiar with the internals of
Verilog-XL. Here is what I recall of the explanation. This only
happens for primitives, which are evaluated by a special algorithm, for
speed. There is some kind of short-cut taken when scheduling an output
on a gate that already has an output transition scheduled. Instead of
descheduling the old transition, and scheduling the new one for a new
time, it simply changes the value in the old schedule to the new value.
This would cause the new value to come out at the time that the old
value would have come out. I would guess that this is faster to
simulate.

Playing around with command line options, it appears that the +noxl
option will turn off the gate acceleration algorithm in Verilog-XL.
Running the testcase with this option gives results more like what you
would expect. The X pulse comes out of the second inverter with a
delay of 1 from the first inverter output.

I would not expect your co-workers to be willing to slow down their
simulations by turning off gate accelleration, especially when the old
behavior has been working fine for them. Also, the results still do
not match what you wanted, because the X pulse is still passed.

I can see how the 'unknowns' would be filtered if I used a component
whose delay is greater than the pulse width (by at least 1 cycle) of
the unknown. Can you elaborate more on how extra zero-delay elements
would help?
The idea was to widen the pulse by the delay of a zero-delay element
(what VHDL calls a delta-cycle), to cause ModelSim to propagate it. If
the input changed a delta cycle later, the output might come out before
the input changed. Since ModelSim is a mixed language simulator, it
might be possible to control the delta cycle behavior the way you could
in VHDL. Then again, it might not.

Regardless, it might avoid the race condition, but it will not help you
get the unusual scheduling behavior of Verilog-XL discussed above.
 

Welcome to EDABoard.com

Sponsor

Back
Top