modeling of the propagation delay between two inout ports

J

Jim

Guest
Does anybody have an example of modeling the propgation delay of a wire that
connects two inout ports?

Thanks,
Jim
 
Interassignment delay can be used for modeling only. ie

input b;
output a;

a <= #6 b;
 
I thought this was going to be easy, but the model I tried (shown
below) did not work as expected on the two simulators that I have
access to.

I have shown the simple 4-bit connector model using two tran switches
and an internal net with declared #5 delay.

I added a testbench below the model and showed what I thought would be
the expected outputs, but the two simulators that I ran gave different
results and neither matched the expected values that I have inserted as
comments into the stimlus strem.

Perhaps we could get someone to try this example with the old
Verilog-XL simulator and post the results for comparison?

Regards - Cliff (example below)

`timescale 1ns/1ns
module connector (pa1, pb1);
inout [3:0] pa1, pb1;
wire [3:0] #5 n1;

tran c1a[3:0] (pa1, n1); tran c1b[3:0] (n1, pb1);
endmodule

module tb;
reg [3:0] a1_reg, b1_reg;
wire [3:0] a1, b1;

connector u1 (.pa1(a1), .pb1(b1));

assign a1 = a1_reg;
assign b1 = b1_reg;

initial begin
$timeformat(-9,0,"ns", 10);
$monitor("%t: a1_reg=%b a1=%b n1=%b b1=%b b1_reg=%b",
$stime, a1_reg, a1, u1.n1, b1, b1_reg);
end

//----------------------------------------------------------------
// NOTE: There are two drivers on a1 (assign a1_reg & inout pa1)
// NOTE: There are two drivers on b1 (assign b1_reg & inout pb1)
// Expected results shown in comments
//----------------------------------------------------------------
initial begin
drive_a2b(4'hF);
// ---> <--- #5 ---> <---
// 0ns: a1_reg=1111 a1=1111 n1=zzzz b1=zzzz b1_reg=zzzz
// 5ns: a1_reg=1111 a1=1111 n1=1111 b1=1111 b1_reg=zzzz
#10 drive_off;
// ---> <--- #5 ---> <---
// 10ns: a1_reg=zzzz a1=zzzz n1=1111 b1=zzzz b1_reg=zzzz
// 15ns: a1_reg=zzzz a1=zzzz n1=zzzz b1=zzzz b1_reg=zzzz
#10 drive_b2a(4'hC);
// ---> <--- #5 ---> <---
// 20ns: a1_reg=zzzz a1=zzzz n1=zzzz b1=1100 b1_reg=1100
// 25ns: a1_reg=zzzz a1=1100 n1=1100 b1=1100 b1_reg=1100
#10 drive_off;
// ---> <--- #5 ---> <---
// 30ns: a1_reg=zzzz a1=zzzz n1=1100 b1=zzzz b1_reg=zzzz
// 35ns: a1_reg=zzzz a1=zzzz n1=zzzz b1=zzzz b1_reg=zzzz
#10 drive_a2b(4'hE);
// ---> <--- #5 ---> <---
// 40ns: a1_reg=1110 a1=1110 n1=zzzz b1=zzzz b1_reg=zzzz
// 45ns: a1_reg=1110 a1=1110 n1=1110 b1=1110 b1_reg=zzzz
#10 drive_b2a(4'h7);
// ---> <--- #5 ---> <---
// 50ns: a1_reg=zzzz a1=1110 n1=1110 b1=0111 b1_reg=0111
// 55ns: a1_reg=zzzz a1=0111 n1=0111 b1=0111 b1_reg=0111
#10 drive_a2b(4'h0);
// ---> <--- #5 ---> <---
// 60ns: a1_reg=0000 a1=0000 n1=0111 b1=0111 b1_reg=zzzz
#2 drive_a2b(4'h6);
// ---> <--- #5 ---> <---
// 62ns: a1_reg=0110 a1=0110 n1=0111 b1=0111 b1_reg=zzzz
// 65ns: a1_reg=0110 a1=0110 n1=0110 b1=0110 b1_reg=zzzz
#10 drive_b2a(4'hF);
// ---> <--- #5 ---> <---
// 72ns: a1_reg=zzzz a1=0110 n1=0110 b1=1111 b1_reg=1111
#3 drive_b2a(4'h9);
// ---> <--- #5 ---> <---
// 75ns: a1_reg=zzzz a1=0110 n1=0110 b1=1001 b1_reg=1001
// 80ns: a1_reg=zzzz a1=1001 n1=1001 b1=1001 b1_reg=1001
#10 $finish;
// ** Note: $finish
// Time: 85 ns
end


task drive_a2b;
input [3:0] aval;
begin
a1_reg = aval;
b1_reg = 4'bz;
end
endtask

task drive_b2a;
input [3:0] bval;
begin
a1_reg = 4'bz;
b1_reg = bval;
end
endtask

task drive_off;
begin
a1_reg = 4'bz;
b1_reg = 4'bz;
end
endtask
endmodule
 
That's not what he asked. Your example was unidirectional. If you take
30 seconds and search this newgroup
(groups.google.com/group/comp.lang.verilog), you will see that this
question has come up many times. The answer seems to be that the only
way involves sdf annotation.

Does anyone know if there is anything recent (Verilog 2000, 2001,
System Verilog) that addresses this?

David
 
I don't think some of the expected values in your testbench are
correct. You can't turn off one driver and turn on the other right away
if there is a 5ns propagation delay, otherwise you will get X's.

For propagation delays between two bidir ports, I found it makes life a
lot easier if you have access to the internal driver enable signals
(luckily for verilog, you can bring any signals out for simulation
without having to add ports for them). Here is what I would do using
the same tb with minor modifications. You just need to hook up the
enable signals to the pa_en and pb_en ports.

HTH,
Jim

`timescale 1ns/1ps
module connector (pa_en, pa1, pb_en, pb1);
inout [3:0] pa1, pb1;
input pa_en, pb_en;

reg [3:0] pa1_int, pb1_int;

// transport delays for small pulses
always @(*) begin
pa1_int <= #5 (pa_en & pb_en) ? 4'bxxxx : (pb_en ? pb1 :
4'bzzzz);
pb1_int <= #5 (pa_en & pb_en) ? 4'bxxxx : (pa_en ? pa1 :
4'bzzzz);
end

assign pa1 = pa1_int;
assign pb1 = pb1_int;
endmodule

module tb;
reg [3:0] a1_reg, b1_reg;
reg a1_en, b1_en;
wire [3:0] a1, b1;

connector u1 (.pa_en(a1_en), .pa1(a1), .pb_en(b1_en), .pb1(b1));

assign a1 = a1_reg;
assign b1 = b1_reg;

initial begin
$timeformat(-9,0,"ns", 10);
$monitor("%t: a1_reg=%b a1=%b b1=%b b1_reg=%b",
$stime, a1_reg, a1, b1, b1_reg);
end

//----------------------------------------------------------------
// NOTE: There are two drivers on a1 (assign a1_reg & inout pa1)
// NOTE: There are two drivers on b1 (assign b1_reg & inout pb1)
// Expected results shown in comments
//----------------------------------------------------------------
initial begin
drive_off;

#10 drive_a2b(4'hF);
#7 drive_off;

#5 drive_b2a(4'hC);

#5 drive_off;

#5 drive_a2b(4'hE);
#10 drive_off;

#5 drive_b2a(4'h7);
#10 drive_off;

#5 drive_a2b(4'h0);
#10 drive_off;

#5 drive_a2b(4'h6);

#2 drive_off;
#10 drive_b2a(4'hF);
#10 drive_off;

#5 drive_b2a(4'h9);
end

task drive_a2b;
input [3:0] aval;
begin
a1_reg = aval;
b1_reg = 4'bz;
a1_en = 1;
b1_en = 0;
end
endtask

task drive_b2a;
input [3:0] bval;
begin
a1_reg = 4'bz;
b1_reg = bval;
a1_en = 0;
b1_en = 1;
end
endtask

task drive_off;
begin
a1_reg = 4'bz;
b1_reg = 4'bz;
a1_en = 0;
b1_en = 0;
end
endtask
endmodule
 
The output from Verilog-XL is:

0ns: a1_reg=1111 a1=1111 n1=xxxx b1=1111 b1_reg=zzzz
5ns: a1_reg=1111 a1=1111 n1=1111 b1=1111 b1_reg=zzzz
10ns: a1_reg=zzzz a1=zzzz n1=1111 b1=zzzz b1_reg=zzzz
15ns: a1_reg=zzzz a1=zzzz n1=zzzz b1=zzzz b1_reg=zzzz
20ns: a1_reg=zzzz a1=1100 n1=zzzz b1=1100 b1_reg=1100
25ns: a1_reg=zzzz a1=1100 n1=1100 b1=1100 b1_reg=1100
30ns: a1_reg=zzzz a1=zzzz n1=1100 b1=zzzz b1_reg=zzzz
35ns: a1_reg=zzzz a1=zzzz n1=zzzz b1=zzzz b1_reg=zzzz
40ns: a1_reg=1110 a1=1110 n1=zzzz b1=1110 b1_reg=zzzz
45ns: a1_reg=1110 a1=1110 n1=1110 b1=1110 b1_reg=zzzz
50ns: a1_reg=zzzz a1=0111 n1=1110 b1=0111 b1_reg=0111
55ns: a1_reg=zzzz a1=0111 n1=0111 b1=0111 b1_reg=0111
60ns: a1_reg=0000 a1=0000 n1=0111 b1=0000 b1_reg=zzzz
62ns: a1_reg=0110 a1=0110 n1=0111 b1=0110 b1_reg=zzzz
65ns: a1_reg=0110 a1=0110 n1=0110 b1=0110 b1_reg=zzzz
72ns: a1_reg=zzzz a1=1111 n1=0110 b1=1111 b1_reg=1111
75ns: a1_reg=zzzz a1=1001 n1=0110 b1=1001 b1_reg=1001
77ns: a1_reg=zzzz a1=1001 n1=1111 b1=1001 b1_reg=1001
80ns: a1_reg=zzzz a1=1001 n1=1001 b1=1001 b1_reg=1001
L68 "bidi.v": $finish at simulation time 85ns

NC-Verilog gets the same results.

These results differ from your expectations. I looked at the first
couple of differences to see why. The first one is that n1 starts at
X, while you assumed it would start at Z. But n1 has a 5ns delay, so
it takes that long for the input value of Z to propagate to it. Until
then it is at the initial X value. This is a minor point.

The next difference is more significant. You assumed that when a1_reg
went to Z, a1 would immediately go to Z. This is based on thinking of
the original goal of a "directional" delay. But what you have written
is not directional. The delay on n1 holds the old value of n1 for 5ns
and drives that onto b1. But it also drives that old value on a1, so
a1 will hold value for 5ns also. There is nothing directional about
that delay. It is more like a lumped capacitor holding the value
than a delay line.

I didn't look at any further differences, but assume that they are due
to similar issues.
 

Welcome to EDABoard.com

Sponsor

Back
Top