Goto page Previous 1, 2
Jonathan Bromley
Guest
Wed Jan 20, 2010 9:42 am
On Tue, 19 Jan 2010 18:14:19 -0800 (PST), sharp_at_cadence.com wrote:
Quote:
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.
Quote:
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.
Quote:
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.
Quote:
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
Jonathan Bromley
Guest
Wed Jan 20, 2010 9:59 am
On Tue, 19 Jan 2010 22:31:03 -0600, Cary R. wrote:
Quote:
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
Cary R.
Guest
Wed Jan 20, 2010 8:52 pm
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
Quote:
= 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.
Jonathan Bromley
Guest
Thu Jan 21, 2010 12:34 pm
On Wed, 20 Jan 2010 11:52:37 -0800, Cary R. wrote:
Quote:
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.
Quote:
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...
Quote:
always @(in) begin
out <= #t_udef 1'bx;
stable_in <= #t_udef 1'b0;
end
Fine so far.
Quote:
always @(negedge stable_in) stable_in <= 1'b1;
Very ingenious!
Quote:
buf #(t_def-t_udef,0) (stable, stable_in);
Even more ingenious!! I wish I'd thought of that...
Quote:
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.
Quote:
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
Cary R.
Guest
Thu Jan 21, 2010 6:18 pm
Jonathan Bromley wrote:
Quote:
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.
Quote:
Better still, it's a five-star posting - thanks! - because
it has so many good and unusual ideas...
You are welcome.
Quote:
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
Goto page Previous 1, 2