issue when using #delay to cause drift between clocks

M

masoodtahir

Guest
I have a clock named "clk" with clock period of 200ps(50%duty cycle).
I want to introduce a drift of 1ps every clock cycle. Please look at
this short piece of verilog code which I thought would do this. In the
simulation, I see that for the first 100 cycles, the positive edges of
clk and delayed_clk keep moving apart from each other by 1ps, 2ps,
3ps....all the way to 100ps, which is what I intended the code to do.
Then at 101th clock, the delayed_clk remains asserted for the next 100
cycles. Then at cycle#200, the edges of clk and delayed_clk align
again, and the process is repeated.

Any idea what I am missing here? I expected that the rising edges of
clk and delayed_clk would be 101ps apart in cycle # 101, then 102ps
apart in cycle#102, all the way to 199ps apart in cycle#199 and then
align again in cycle#200. Any idea how to do this?

wire delayed_clk;
integer acc_driftdelay=0; // accumulate drift delay
always @(posedge clk)
begin
if (acc_driftdelay ==200)
acc_driftdelay = 0;
else
acc_driftdelay = acc_driftdelay + 1;
end
assign #acc_driftdelay delayed_clk = clk;
 
On May 18, 12:44 am, masoodtahir <masoodta...@hotmail.com> wrote:
I have a clock named "clk" with clock period of 200ps(50%duty cycle).
I want to introduce a drift of 1ps every clock cycle. Please look at
this short piece of verilog code which I thought would do this. In the
simulation, I see that for the first 100 cycles, the positive edges of
clk and delayed_clk keep moving apart from each other by 1ps, 2ps,
3ps....all the way to 100ps, which is what I intended the code to do.
Then at 101th clock, the delayed_clk remains asserted for the next 100
cycles. Then at cycle#200, the edges of clk and delayed_clk align
again, and the process is repeated.

Any idea what I am missing here? I expected that the rising edges of
clk and delayed_clk would be 101ps apart in cycle # 101, then 102ps
apart in cycle#102, all the way to 199ps apart in cycle#199 and then
align again in cycle#200. Any idea how to do this?

wire delayed_clk;
integer acc_driftdelay=0; // accumulate drift delay
always @(posedge clk)
begin
if (acc_driftdelay ==200)
acc_driftdelay = 0;
else
acc_driftdelay = acc_driftdelay + 1;
end
assign #acc_driftdelay delayed_clk = clk;

I think you're trying to implement a transport delay with
a continuous assignment. When your #delay exceeds the
pulse width of clk, the continuous assignment is re-applied
before the delay elapses. In this case the previously scheduled
update of delayed_clk is superseded by the new event.
This means that the delayed_clk never gets updated until
the #delay is once again below the pulse width of clk.
 
masoodtahir wrote:
Any idea what I am missing here? I expected that the rising edges of
clk and delayed_clk would be 101ps apart in cycle # 101, then 102ps
apart in cycle#102, all the way to 199ps apart in cycle#199 and then
align again in cycle#200. Any idea how to do this?
Propagation delays in Verilog are what are called "inertial" delays.
They will not pass a pulse narrower than the delay. There is some
physical justification for this in the way that gate delays actually
work, but it also simplifies simulators because they only have to
track one scheduled event on a net at a time.

So as soon as the delay becomes greater than 100ps, you cannot pass
the 100ps high and low pulses that make up your clock. It holds at
the last value that got through, an inertia-like effect.

There are only a few ways of getting non-inertial delays in Verilog.
Path delays given in specify blocks can provide what are called
"transport" delays, which are closer to what you would expect for a
delay line or series of multiple gates. They still cannot just pass
the waveform delayed, because the rising and falling delays may be
different. This can shrink pulse widths, and pulses that go to
negative widths will disappear. Path delays will also deliberately
filter pulses that are narrower than a given amount, so that users can
deliberately tailor them to match device behavior.

Non-blocking assignment intra-assignment delays are what are sometimes
called "pure transport" delays. The events are always passed through
with the specified delays. If pulse widths become negative, the edges
come out in reverse order, which can be surprising.

Possible workarounds include breaking your delay up into several delay
elements in series, or re-writing your continuous assignment as a
combinational always block that uses nonblocking assignments.

Note that you may see some unexpected results when you try to set the
delay back to 0, since you have multiple edges scheduled from
different times to come out at the same time, or in a different order
than they were scheduled in.
 

Welcome to EDABoard.com

Sponsor

Back
Top