How to avoid pulse swallowing?

J

Jan Stuyt

Guest
Hello Verilog community,

Does anyone know how to program a transport delay, rather than the default inertial delay?

Here is the problem:


--------------------------------------------------------------------------------

`timescale 1ns / 1ps

module problem;
reg a;
wire b;

initial
begin
a = 1'b0;
#5 a = 1'b1; // pulse just one time unit wide
#6 a = 1'b0;
#10 a = 1'b1;
#15 $finish;
end

assign #2 b = a; // intend to delay the pulse by 2 time units

initial $monitor($time,,a,b); // the pulse on b is gone!
endmodule

--------------------------------------------------------------------------------


Because the width of the pulse on signal a is less than the distributed delay in the assignment to b,
the default Verilog behaviour is cancel the pulse altogether. In VHDL you can add the qualifier
"transport" in the assignment:

b <= transport a after 2 ns;

which neatly shifts the 1ns pulse by 2ns.

Question: How do I get this behaviour in Verilog?

Note: I use Verilog-XL, NcVerilog or ncvlog/ncelab/ncsim; I want consistent behaviour in all simulators.
 
Part 1.
You are misunderstanding what # delays in procedural blocks do. The
first #5 delays evaluation and the assignment, it does not mean ( at
time 5 ). So what you think is a 1 NS pulse, because you have a #5
followed by a #6 is actually a 6ns pulse. and the output changes at
time #11.

Part 2.
Get yourself an IEEE 1364 standard. See section 6.1.3 Assigment -
Delays.

Paragraph 2:

In situations where a right-hand side operand changes before a previous
change has had time to propogate to the left-hand side, then the
following steps are taken :
....
b) if the RHS value differes from the value currently scheduled to
propogate to the left-hand side, then the currently scheduled
propogation is descheduled.


Now there are some other ways of handling it. Most of which involve
registers and non-blocking assignments, that won't get cancelled:

For instance :

reg b;
always @(a)
b <= #2 a ;

This will cause b to always mimic the last value in every time slice of
a, only 2 ns later. It also does it at Non-blocking assignment time,
which means, if you have a clock that is sampling this value at the
same time, it will see the old value.

-Art
 
Distributed delays (i.e. the delays on continuous assignments or gate
primitives) are always inertial in Verilog.

Non-blocking assignments provide "pure transport" delays. This may
give you what you need for your purposes. However, unlike VHDL
transport delays, they won't swallow pulses even if the effective pulse
width goes negative. In other words, if you schedule the leading edge
of a pulse, and then schedule the trailing edge to happen before the
leading edge, you will get the trailing edge value and then the leading
edge value. However, as long as you are only using a single
propagation delay, this won't be a problem.

Verilog also provides path delays from port to port, using "specify"
blocks. With these, you can control the pulse-filtering behavior. The
default is 100% filtering, which is equivalent to inertial delay. If
you set it to 0% filtering, you will get transport delay. Or you can
set it to something in between, to filter pulses with widths up to a
given percentage of the propagation delay. However, I wouldn't
recommend trying to learn about Verilog's more advanced timing features
unless you are prepared for a lot of extra effort.
 

Welcome to EDABoard.com

Sponsor

Back
Top