Help with timing modeling please

J

Jonathan Bromley

Guest
hi folks,

as you know, I've been messing with Verilog for quite a
while now, but there's still some stuff I don't know,
so perhaps someone here can help.

I want to model an uncertain signal transition. My
source signal (let's say S) makes a clean transition
from 0 to 1, or the other way, at some time T. I
want an output (let's say Y) to follow this signal,
but with both a delay and an uncertainty - so it
should go to X at time T+Tmin, and then to 1 at
time T+Tmax. Rise and fall behaviour should be
symmetrical.

In VHDL I can trivially do this by using inertial
delay:

Y <= 'X' after Tmin, S after Tmax;

In Verilog I can get nearly there...

always @S begin
Y <= #Tmin 1'bx;
Y <= #Tmax S;
end

but that isn't quite right; suppose, for example,
that S goes from 0 to 1 at time T, and then goes
back to 0 again just before T+Tmax - I'll get Y
going to 1 at T+Tmax, and then back to X again...
it's wrong because Verilog <= delays are transport
rather than inertial.

I can think of various ways to do this, but all of
them cost a few lines of code. I strongly suspect
that there is some super-neat way to do it using
specify blocks or somesuch; can anyone save me a
lot of LRM-rummaging by telling me the trick?

thanks in advance
--
Jonathan Bromley
 
On Jan 17, 12:12 pm, Jonathan Bromley <s...@oxfordbromley.plus.com>
wrote:
hi folks,

as you know, I've been messing with Verilog for quite a
while now, but there's still some stuff I don't know,
so perhaps someone here can help.

I want to model an uncertain signal transition.  My
source signal (let's say S) makes a clean transition
from 0 to 1, or the other way, at some time T.  I
want an output (let's say Y) to follow this signal,
but with both a delay and an uncertainty - so it
should go to X at time T+Tmin, and then to 1 at
time T+Tmax.  Rise and fall behaviour should be
symmetrical.

In VHDL I can trivially do this by using inertial
delay:

  Y <= 'X' after Tmin, S after Tmax;

In Verilog I can get nearly there...

  always @S begin
    Y <= #Tmin 1'bx;
    Y <= #Tmax S;
  end

but that isn't quite right; suppose, for example,
that S goes from 0 to 1 at time T, and then goes
back to 0 again just before T+Tmax - I'll get Y
going to 1 at T+Tmax, and then back to X again...
it's wrong because Verilog <= delays are transport
rather than inertial.

I can think of various ways to do this, but all of
them cost a few lines of code.  I strongly suspect
that there is some super-neat way to do it using
specify blocks or somesuch; can anyone save me a
lot of LRM-rummaging by telling me the trick?

thanks in advance
--
Jonathan Bromley


Hello Jonathan,

Verilog has both inertial and transport delays. Delays put on the RHS
of the assignment are transport delays. Put the delay on the LHS, and
it will be an inertial delay.

Here is a random paper that has a bit more detail on modeling delays:

http://www.sunburst-design.com/papers/CummingsHDLCON1999_BehavioralDelays_Rev1_1.pdf

Regards,

John McCaskill
www.FasterTechnology.com
 
On Sun, 17 Jan 2010 13:29:55 -0800 (PST), John McCaskill wrote:

Verilog has both inertial and transport delays. Delays put on the RHS
of the assignment are transport delays. Put the delay on the LHS, and
it will be an inertial delay.
Sorry John, that's only half the story!

First, whilst you're completely right that inertial delay
is available, it doesn't solve my problem because I can't use it
to model more than one different delay for a given assignment.

Second, someone reading your post without the necessary
background might easily get the wrong idea, I fear.
Intra-assignment procedural delays are indeed transport delays;
this...

initial begin
...
a <= #5 b;

is very, very similar to VHDL's

a <= transport b after 5 ns;

Contrariwise, the blocking form is fairly useless:

initial begin
...
a = #5 b;

is simply equivalent to (Verilog)
some_temporary = b;
#5 a = some_temporary;

In procedural code, delays used as a prefix are neither inertial
nor transport; they're simple procedural stall that makes your
code hang for some simulation time while the rest of your model
gets on with other stuff:

...
do_some_stuff;
#10 // twiddle thumbs for 10 time units
do_other_stuff;

And in any kind of continuous assignment, the delay is inertial:

assign #4 target_wire = expression; // inertial delay

Here is a random paper that has a bit more detail on modeling delays:
Cliff's a great guy and that paper is fine, but he's an RTL
guy to the core of his being and my question was about
behavioural modelling for simulation only.

I *think* there's some stuff I can do with the pulse rejection
machinery, but that's the part I don't know.... trying to map
the VHDL on to Verilog, my problem is that you can't do inertial
delay in Verilog procedural code at all.

I have a different solution, but it's too clumsy for comfort.
--
Jonathan Bromley
 
Hi Jonathan

Is this close enough? If the input changes before T_min, you'll still
see a change to 1'bx at the output, though. Not sure how VHDL behaves
in this case.

module buffer;

reg S;
wire Y;

time T_min = 7.5;
time T_max = 10;

always @S
begin
#T_min;
force Y = 1'bx;
#(T_max - T_min);
release Y;
end

assign #(T_max) Y = S;

initial
begin
#13;

// uncritical
S = 1;
#30;
S = 0;
#30;

// input change during uncertainty
S = 1;
#8;
S = 0;
#8;

// input change before uncertainty
S = 1;
#5;
S = 0;
#30;
end
endmodule

Take care
--
Marcus Harnisch
Consultant

DOULOS - Developing Design Know-how
VHDL * SystemC * Verilog * SystemVerilog * e * PSL * Perl * Tcl/Tk
ARM Approved Training Centre (ATC)

Doulos Ltd., Central European Office, Garbsener Landstr. 10, 30419 Hannover
Tel: +49 (0)511 2771340 mailto: marcus.harnisch@doulos.com
Fax: +49 (0)511 2771349 Web: http://www.doulos.com

This e-mail and any attachments are confidential and Doulos Ltd. reserves
all rights of privilege in respect thereof. It is intended for the use of
the addressee only. If you are not the intended recipient please delete it
from your system, any use, disclosure, or copying of this document is
unauthorised. The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
On Mon, 18 Jan 2010 03:41:41 +0100, Marcus Harnisch
<marcus.harnisch@doulos.com> wrote:

Hi Jonathan

Is this close enough? If the input changes before T_min, you'll still
see a change to 1'bx at the output, though. Not sure how VHDL behaves
in this case.
VHDL will wipe out existing scheduled actions, and re-schedule
according to the inertial assignment, for each execution of the
signal assignment. So the end of 'X' gets pushed out to Tmax
after the last transition on S.

module buffer;
[snip]

I fear it has the same problem as some of my earlier efforts:
procedural delays in the "always @S" block mean that certain
transitions on S can be missed. I *think* this is more robust,
but I had to do a lot of futzing around to be confident that
I wouldn't get races or lockups. Not so much longer than
yours, if you take out the error checks :)

module bufX
#(parameter Tmax = 1, Tmin = 0)
(input in, output reg out);

reg transition;
initial begin
if ((Tmax < Tmin) || (Tmax < 0) || (Tmin < 0)) begin
$display("FATAL: bufX %m: Tmax = %0d, Tmin = %0d",
Tmax, Tmin);
$stop;
$finish(1);
end
transition = 1;
fork
forever @(in) begin
if (transition) begin
disable delay;
wait(!transition);
end
out <= #Tmin 1'bx;
transition = 1;
end
forever begin
wait(transition);
begin : delay
#Tmax out <= in;
end
transition = 0;
end
join
end
endmodule
 
On Mon, 18 Jan 2010 09:46:09 +0100, Jonathan Bromley wrote:

<stuff>

ps - forgot to sign off, and to ask how life is
treating you!
--
Jonathan Bromley
 
On Jan 17, 1:12 pm, Jonathan Bromley <s...@oxfordbromley.plus.com>
wrote:
hi folks,

as you know, I've been messing with Verilog for quite a
while now, but there's still some stuff I don't know,
so perhaps someone here can help.

I want to model an uncertain signal transition.  My
source signal (let's say S) makes a clean transition
from 0 to 1, or the other way, at some time T.  I
want an output (let's say Y) to follow this signal,
but with both a delay and an uncertainty - so it
should go to X at time T+Tmin, and then to 1 at
time T+Tmax.  Rise and fall behaviour should be
symmetrical.

In VHDL I can trivially do this by using inertial
delay:

  Y <= 'X' after Tmin, S after Tmax;

In Verilog I can get nearly there...

  always @S begin
    Y <= #Tmin 1'bx;
    Y <= #Tmax S;
  end

but that isn't quite right; suppose, for example,
that S goes from 0 to 1 at time T, and then goes
back to 0 again just before T+Tmax - I'll get Y
going to 1 at T+Tmax, and then back to X again...
it's wrong because Verilog <= delays are transport
rather than inertial.

I can think of various ways to do this, but all of
them cost a few lines of code.  I strongly suspect
that there is some super-neat way to do it using
specify blocks or somesuch; can anyone save me a
lot of LRM-rummaging by telling me the trick?

thanks in advance
--
Jonathan Bromley
Maybe not as pretty, but you could use a number
of assignments to get your transport delays:

wire Y_min, Y_max;
assign Y_min = #Tmin S;
assign Y_max = #Tmax S;
always @ (Y_min or Y_max)
if (Y_min != Y_max) Y = Y_min;
else Y = 1'bX;

Just a thought,
Gabor
 
On Mon, 18 Jan 2010 08:50:07 -0800 (PST), gabor wrote:

wire Y_min, Y_max;
assign Y_min = #Tmin S;
assign Y_max = #Tmax S;
always @ (Y_min or Y_max)
  if (Y_min != Y_max) Y = Y_min;
  else Y = 1'bX;

Got that backwards! should be if (Y_min == Y_max) . . .
If this works, it's very neat indeed because you can
use wire resolution to get the "X if different":

assign Y = #Tmin S;
assign Y = #Tmax S;

Unfortunately it's not quite right. If S thrashes around
with pulse widths shorter than Tmin, you can yet Y appearing
to settle at any of 0, 1 or X depending on the exact timing
of the pulses; this isn't quite what I wanted.

However, it's a very useful approximation for some of the
simpler cases, and I think it will do the trick in the
component model I'm trying to create just now. Thanks!
--
Jonathan Bromley
 
On Jan 18, 9:08 am, gabor <ga...@alacron.com> wrote:
On Jan 17, 1:12 pm, Jonathan Bromley <s...@oxfordbromley.plus.com
wrote:



hi folks,

as you know, I've been messing with Verilog for quite a
while now, but there's still some stuff I don't know,
so perhaps someone here can help.

I want to model an uncertain signal transition.  My
source signal (let's say S) makes a clean transition
from 0 to 1, or the other way, at some time T.  I
want an output (let's say Y) to follow this signal,
but with both a delay and an uncertainty - so it
should go to X at time T+Tmin, and then to 1 at
time T+Tmax.  Rise and fall behaviour should be
symmetrical.

In VHDL I can trivially do this by using inertial
delay:

  Y <= 'X' after Tmin, S after Tmax;

In Verilog I can get nearly there...

  always @S begin
    Y <= #Tmin 1'bx;
    Y <= #Tmax S;
  end

but that isn't quite right; suppose, for example,
that S goes from 0 to 1 at time T, and then goes
back to 0 again just before T+Tmax - I'll get Y
going to 1 at T+Tmax, and then back to X again...
it's wrong because Verilog <= delays are transport
rather than inertial.

I can think of various ways to do this, but all of
them cost a few lines of code.  I strongly suspect
that there is some super-neat way to do it using
specify blocks or somesuch; can anyone save me a
lot of LRM-rummaging by telling me the trick?

thanks in advance
--
Jonathan Bromley

Maybe not as pretty, but you could use a number
of assignments to get your transport delays:

wire Y_min, Y_max;
assign Y_min = #Tmin S;
assign Y_max = #Tmax S;
always @ (Y_min or Y_max)
  if (Y_min != Y_max) Y = Y_min;
  else Y = 1'bX;

Just a thought,
Gabor
Got that backwards! should be if (Y_min == Y_max) . . .
 
Jonathan Bromley wrote:
If this works, it's very neat indeed because you can
use wire resolution to get the "X if different":

assign Y = #Tmin S;
assign Y = #Tmax S;

Unfortunately it's not quite right. If S thrashes around
with pulse widths shorter than Tmin, you can yet Y appearing
to settle at any of 0, 1 or X depending on the exact timing
of the pulses; this isn't quite what I wanted.

However, it's a very useful approximation for some of the
simpler cases, and I think it will do the trick in the
component model I'm trying to create just now. Thanks!
This document seems to go through most of the things that you referred to.

http://ce.sharif.edu/courses/84-85/1/ce223/resources/root/Slides/10-Verilog%20Timing%20and%20Delays.ppt

Can you simplify your needs to 0->1, 1->0, 0->z, z->1, 1->z and z->0
with a specific delay time for each transition type? If so look at page
33 of the document.

This a section on state dependent timings.

I hope this is useful. Andy
 
Jonathan Bromley <jonathan.bromley@MYCOMPANY.com> writes:

ps - forgot to sign off, and to ask how life is
treating you!
Better than you -- keeping me awake with riddles when I should really
catch some sleep ;-)

Did you mention SystemVerilog in this thread? This solution looks
pretty close to the VHDL version, at least in my not-that-exhaustive
testbench:

module buffer_sv(input S, output Y);

parameter
T_min = 8,
T_max = 10;

always begin
@S;
forever
begin
// schedule x unless another change to S occurs
fork
begin
#T_min;
force Y = 1'bx;
#(T_max - T_min);
release Y;
@S;
end
@S;
join_any
disable fork;
end // forever begin
end

assign #(T_max) Y = S;
endmodule

Regards
--
Marcus Harnisch
Consultant

DOULOS - Developing Design Know-how
VHDL * SystemC * Verilog * SystemVerilog * e * PSL * Perl * Tcl/Tk
ARM Approved Training Centre (ATC)

Doulos Ltd., Central European Office, Garbsener Landstr. 10, 30419 Hannover
Tel: +49 (0)511 2771340 mailto: marcus.harnisch@doulos.com
Fax: +49 (0)511 2771349 Web: http://www.doulos.com

This e-mail and any attachments are confidential and Doulos Ltd. reserves
all rights of privilege in respect thereof. It is intended for the use of
the addressee only. If you are not the intended recipient please delete it
from your system, any use, disclosure, or copying of this document is
unauthorised. The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
Do you mean something like this

module uncertain(output wire out, input wire in)
parameter t_udef = 0, // The change to 'bx delay
t_def = 0; // The cahnge to defined delay
wire udef_window; // The uncertian window of operation
wire def_window; // The defined window of operation

initial if (t_udef > t_def) begi
$display("Configuration failure t_udef (%d) is greater than t_def (%d)."
t_udef, t_def)
$finish
en

buf #(t_udef, t_def) (udef_window, in)
buf #(t_def, t_udef) (def_window, in)

assign out = (uc_window & 1'bx) | def_window
endmodule

---
frmsrcurl: http://compgroups.net/comp.lang.verilog/Help-with-timing-modeling-please
 
On Jan 17, 1:12 pm, Jonathan Bromley <s...@oxfordbromley.plus.com>
wrote:

Nonblocking assignment delays are pure transport, i.e. none of the
assignments get descheduled by later assignments. Continuous
assignment and gate delays are pure inertial, i.e. only one event can
be scheduled at a time, and scheduling a new value will deschedule the
previous value.

What I assume you want is what I would call "normal" transport
scheduling. Multiple events can be scheduled as long as the ones
scheduled later are for a time after the ones scheduled earlier. When
an event is scheduled, any old events that would occur after it are
descheduled. So if a pulse width goes negative, the pulse disappears,
rather than having its edges occur in reverse order.

I believe that you can get this with path delays in specify blocks. I
don't know how much of this is part of the Verilog standard and how
much was specific to Verilog-XL (and replicated in NC-Verilog and
presumably some other simulators). I believe that these give you what
I would call transport delays, but with extra control over pulse
filtering. Instead of just filtering pulses that go negative, they
can filter pulses narrower than a given percentage of the delay. By
default I think that percentage is 100%, so it still looks like
inertial delay. If it is set to 0%, it would be transport delay.
This may be controlled by tool options, which is why I suspect it
might not be covered by the standard.

I think there are other controls that will allow narrow pulses to turn
to X for the runt pulse duration, instead of going away (though I
think it has to be implemented by some different mechanism of turning
to a special error state that is then treated as X, to get around some
absurd patent on the basic idea).
 
For the assign version isn't i

assign #T_min out = in
assign #T_max out = in

I don't recognize the other syntax as being valid.

---
frmsrcurl: http://compgroups.net/comp.lang.verilog/Help-with-timing-modeling-please
 
I thought about this a bit more on the drive home. Let the simulator do the resolution just like was suggested for the assign statements

buf #t_min (out, in)
buf #t_max (out, in)

Should give you exactly what you want.

---
frmsrcurl: http://compgroups.net/comp.lang.verilog/Help-with-timing-modeling-please
 
On Tue, 19 Jan 2010 18:14:19 -0800 (PST), sharp@cadence.com wrote:

Nonblocking assignment delays are pure transport, i.e. none of the
assignments get descheduled by later assignments.
Right, and you can't reliably rescind them with disable.
It would be possible to do some SystemVerilog voodoo with
spawned processes to allow scheduling a future event and
then reliably rescinding it, but that is a nasty example
of using a sledgehammer to crack a nut.

Continuous
assignment and gate delays are pure inertial, i.e. only one event can
be scheduled at a time, and scheduling a new value will deschedule the
previous value.
Indeed so.

What I assume you want is what I would call "normal" transport
scheduling. Multiple events can be scheduled as long as the ones
scheduled later are for a time after the ones scheduled earlier. When
an event is scheduled, any old events that would occur after it are
descheduled. So if a pulse width goes negative, the pulse disappears,
rather than having its edges occur in reverse order.
No, the effect I want is precisely what VHDL inertial delay gives
me: I want to be able to schedule multiple events (preferably in
a single hit, but that's not essential) and...
- deschedule any existing events that are later than the
earliest of the new events;
- scan backwards through existing scheduled events, starting from
the time of the earliest new event; as soon as you find an
event that would drive the target to a value different from
the earliest new event, deschedule it and all earlier events.
This arrangement gives what I want: runt pulses cause the output
to go to X at time Tmin after the first edge of the pulse, and
reach the settled value at Tmax after the last edge of the
pulse. And similarly for any train of pulses with edge-to-edge
times shorter than Tmax. I probably ought to ignore completely
any really short pulses (say, less than some percentage of Tmin)
but I haven't tried to address that yet.

I believe that you can get this with path delays in specify
blocks [...]

Right. As already mentioned, that's not my home territory
but it looks as though I need to start finding out about it!

Thanks.
--
Jonathan Bromley
 
On Tue, 19 Jan 2010 22:31:03 -0600, Cary R. wrote:

For the assign version isn't it

assign #T_min out = in;
assign #T_max out = in;

I don't recognize the other syntax as being valid.
Yes, you're right. It's an easy mistake to make.
I copied from gabor's post and carelessly
duplicated his slip-up. I'm pretty sure that
both of us know the right way to do it!

Unfortunately the resolved-assign thing doesn't
quite fit the bill. To see why, try this:

module test;
reg S;
wire Y;
assign #2 Y = S; // Tmin = 2
assign #10 Y = S; // Tmax = 10

initial begin
S = 0; #20;
// A long pulse behaves just as I want:
S = 1; #20 S = 0; #20;
// A short pulse also does the right thing:
S = 1; #5 S = 0; #20;
// A pulse shorter than Tmin is completely lost;
// not quite what I wanted, but sensible enough:
S = 1; #1 S = 0; #20;
// But here's the unacceptable case:
repeat (6) #5 S = ~S; #20;
end
endmodule

Given a train of short pulses (Tmin < Tpulse < Tmax), note
how the output goes X/0/X/0/X/0 when I need it to stay at X
for the entire duration of the pulse train - the input is
out-of-spec, so the output should be a steady X until Tmax
after the last edge of the pulse train.

Now, having said all of that, it is likely that the
two-assign (or, equivalently, two-buffer) solution will
do the job for most of the modeling I care about, and it's
a useful trick to have in the toolkit. But it really
doesn't match the convenience of VHDL's
Y <= 'X' after Tmin, S after Tmax;
which gives me precisely the effect I seek.

At some point I'll do battle with specify blocks and path
delays, and I'll post any solution I come up with.

Thanks to all for the interesting input.
--
Jonathan Bromley
 
OK, what you are asking for isn't really a straight inertial delay. I am
not fluent in VHDL so this is a guess, but I think this works like you
expect.

module uncertain(output reg out, input wire in);
parameter t_udef = 0, // The change to 'bx delay.
t_def = 0; // The change to defined delay.

wire stable;
reg stable_in;

initial if (t_udef > t_def || t_udef < 0) begin
$display("Configuration failure t_udef(%d) must be <= t_def(%d) and
= 0.",
t_udef, t_def);
$finish;
end

always @(in) begin
out <= #t_udef 1'bx;
stable_in <= #t_udef 1'b0;
end
always @(negedge stable_in) stable_in <= 1'b1;

buf #(t_def-t_udef,0) (stable, stable_in);

always @(posedge stable) out <= in;

endmodule

My interpretation of the VHLD command is that the after actually acts
like a transport delay, but the difference between the two are inertial
in nature. What I modeled sets the output to 1'bx t_min after any edge
and sets it to the input t_max after the edge if no other edges have
occurred.
 
On Wed, 20 Jan 2010 11:52:37 -0800, Cary R. wrote:

OK, what you are asking for isn't really a straight inertial delay.
Perhaps not; I'm not especially worried about the words (inertial
delay is a pretty silly name anyway) - it's the functionality
I care about.

I think this works like you expect.
[snip]
I think so. I also think it's neater (and probably more efficient)
than the version with fork and disable that I posted earlier.

Better still, it's a five-star posting - thanks! - because
it has so many good and unusual ideas...

always @(in) begin
out <= #t_udef 1'bx;
stable_in <= #t_udef 1'b0;
end
Fine so far.

always @(negedge stable_in) stable_in <= 1'b1;
Very ingenious!

buf #(t_def-t_udef,0) (stable, stable_in);
Even more ingenious!! I wish I'd thought of that...

always @(posedge stable) out <= in;
Right, so this postpones (posedge stable) until (in) has
been stable for t_def. Lovely. All previous transport
assignments to X have already matured by this time.

Just one minor query: why do you favour the 'buf'
primitive over continuous assignment to a wire? If
I understand correctly, your buf could have equally
well been replaced by

assign #(t_def-t_udef, 0) stable = stable_in;

which I find somewhat easier to read.

My interpretation of the VHDL command is that
the after actually acts like a transport delay,
but the difference between the two are inertial
in nature.
Like I said, I'm not too worried about the verbiage
here. I think the description I gave in an earlier
post was accurate; whether that's "inertial" or
"transport" or some hybrid doesn't really bother me.

Many thanks for the fascinating ideas and tricks!
--
Jonathan Bromley
 
Jonathan Bromley wrote:

Perhaps not; I'm not especially worried about the words (inertial
delay is a pretty silly name anyway)
I think about it as follows:

You need a pulse big enough to overcome the elements inertia for an
inertial delay.

Better still, it's a five-star posting - thanks! - because
it has so many good and unusual ideas...
You are welcome.

Just one minor query: why do you favour the 'buf'
primitive over continuous assignment to a wire? If
I understand correctly, your buf could have equally
well been replaced by

assign #(t_def-t_udef, 0) stable = stable_in;

which I find somewhat easier to read.
That's because you have an RTL background ;-). Thought seriously, either
works just fine. One real reason to use the buf is that it makes it very
clear this is a model not something to be synthesized. I also enjoy
trowing a curve ball every once and a while. Feel lucky I couldn't
figure out a reason to use a two output buffer!

Cary
 

Welcome to EDABoard.com

Sponsor

Back
Top