My understanding of "specify" is that it controls the propagation delay from input to output.
So ..
I expect the code below to show 'o' changing at 118 - ie 10 time units after 108 when 'b' changed but instead the 'b' change is incorporated at 115 which is 10 units after a changed.
>A T= 0 a 0 b 0 o x
>B T= 0 a 0 b 0 o x
O T= 10 a 0 b 0 o 0
>A T= 105 a 1 b 0 o 0
>B T= 108 a 1 b 1 o 0
O T= 115 a 1 b 1 o 2
I expected this ....
>A T= 0 a 0 b 0 o x
>B T= 0 a 0 b 0 o x
O T= 10 a 0 b 0 o 0
>A T= 105 a 1 b 0 o 0
>B T= 108 a 1 b 1 o 0
O T= 115 a 1 b 1 o 1
O T= 118 a 1 b 1 o 2
Have I misunderstood 'specify'?
See https://www.edaplayground.com/x/eBUY
module check(a,b,o);
output wire [1:0] o;
input [1:0] a,b;
specify
( a => o ) = 10;
( b => o ) = 10;
endspecify
assign o = a + b;
always @ (a)
$display (">A T=%4t a %2d b %2d o %2d ", $time, a, b, o);
always @ (b)
$display (">B T=%4t a %2d b %2d o %2d ", $time, a, b, o);
always @ (o)
$display (" O T=%4t a %2d b %2d o %2d ", $time, a, b, o);
endmodule
module test;
wire [1:0] o;
logic [1:0] a,b;
check t1(.a,.b,.o);
initial begin
a = 0;
b = 0;
end
initial begin
#105 a = 1;
end
initial begin
#108 b = 1; // I EXPECT o TO CHANGE AS 108+10 BUT IT CHANGES AT 115
end
endmodule
=========
Updated ...
Two alternatives that seem to work the way I expected See below and https://www.edaplayground.com/x/P7kB
module check(a,b,o);
output reg [1:0] o;
input [1:0] a,b;
// OPTION 1 - put the delays on the individual wires
wire #10 a_delayed = a;
wire #10 b_delayed = b;
assign o = a_delayed + b_delayed;
// OPTION 2
// Use non-blocking with RHS delay as per https://www-inst.eecs.berkeley.edu/~cs152/fa06/handouts/CummingsHDLCON1999_BehavioralDelays_Rev1_1.pdf
// always @*
// o <= #10 a + b;
always @ (a)
$display (">A T=%4t a %2d b %2d o %2d ", $time, a, b, o);
always @ (b)
$display (">B T=%4t a %2d b %2d o %2d ", $time, a, b, o);
always @ (o)
$display (" O T=%4t a %2d b %2d o %2d ", $time, a, b, o);
endmodule
Both option 1 nd 2 produce the same output ...
>A T= 0 a 0 b 0 o x
>B T= 0 a 0 b 0 o x
O T= 10 a 0 b 0 o 0
>A T= 105 a 1 b 0 o 0
>B T= 108 a 1 b 1 o 0
O T= 115 a 1 b 1 o 1
O T= 118 a 1 b 1 o 2
Is there a better way to get the individual input to output propagation delays to work?
BTW This quesiton is actually part of a more complictated usecase that this question was motivated by. I am creating a timed model of a 74HCT151 and wanted the timings to be accurate as I want to generate the settling glitches that the published timing implies.
Should I create a separate question for that?
Specify path delays come in two forms; Parallel connection a=>o
and Full connection a*>o
. A parallel connection is the same as writing a[0] => o[0]
and a[1] => o[1]
. There is no path from a[0] => o[1]
, same for b[0]=>o[1]
.
In your testcase, you are changing a[0]
and b[0]
, but o[1]
is changing, since there is no path, there is 0 delay. Also, the LRM section 30.7 says
Two consecutive scheduled transitions closer together in time than the module path delay are deemed a pulse. By default, pulses on a module path output are rejected.
That is why o
goes directly from 0
to 2
. You need use a Full connection.
BTW, I could not get Icarus Verilog on EDAPlayground to match your results or give me the correct results when changing =>
to *>
, but all the other simulators worked.
Your option 1 filters input glitches. If a
or b
have glitches less than 10 time units, those get filtered out. Your option 2 passes all output glitches through, even 0 delay glitches. If you want realistic pulse filtering, you must use specify
path delays with $PATHPULSE
and apparently iverilog does not implement correctly.