FPGARelated.com
Forums

Verilog: Simulating Transport Delays on Bidirectional Tristate Lines

Started by Kevin Neilson February 16, 2007
When I started to write this, I wanted to ask how to model a 
bidirectional wire with transport delays but I've come up with a 
solution that works for my SDRAM sim so I'll post it here.  I've done a 
fairly exhaustive search, and have found many instances of others posing 
this question, but no other definitive answers.  Mr. Bromley, in a 
recent post, showed me how to model transport (not inertial) delays on 
unidirectional lines.  I was initially able to, using two "wires" at the 
endpoints and a "reg" in the middle, simulate a tranport delay that 
worked in either direction, but the problem I kept encountering was 
this:  the signal got "reflected" at the receiving end of the path and 
retransmitted, bouncing back and forth forever like a photon in a 
mirrored box.

The Verilog "tran" primitive is not useful because it never incurs a 
delay across its two I/Os.

I finally found a way to prevent the reflections that has the limitation 
described below.  To model a bidirectional wire, just instantiate the 
module below, and the 'a' and 'b' ports correspond to the values at each 
end of a bidirectional wire with delay.  The delay values are reals so 
that they can be changed during the sim; therefore you must 'force' them 
using the method described below.  The delays can model PCB copper 
delays only, or, for RTL sims, can incorporate input/output pad delays, 
in which case the delays may be different in each direction.  Here is 
the model:

/*****************************************************************
  * module triwire:  bidirectional wire bus model with delay
  *
  * This module models the two ends of a bidirectional bus with
  * transport (not inertial) delays in each direction.  The
  * bus has a width of WIDTH and the delays are as follows:
  *   a->b has a delay of Ta_b (in `timescale units)
  *   b->a has a delay of Tb_a (in `timescale units)
  * The two delays will typically be the same.  This model
  * overcomes the problem of "echoes" at the receiving end of the
  * wire by ensuring that data is only transmitted down the wire
  * when the received data is Z.  That means that there may be
  * collisions resulting in X at the local end, but X's are not
  * transmitted to the other end, which is a limitation of the
  * model.  Another compromise made in the interest of simulation
  * speed is that the bus is not treated as individual wires, so
  * a Z on any single wire may prevent data from being transmitted
  * on other wires.
  *
  * The delays are reals so that they may vary throughout the
  * course of a simulation.  To change the delay, use the Verilog
  * force command.  Here is an example instantiation template:
  *
  real Ta_b=1, Tb_a=1;
  always@(Ta_b) force triwire.Ta_b = Ta_b;
  always@(Tb_a) force triwire.Tb_a = Tb_a;
  triwire #(.WIDTH(WIDTH)) triwire (.a(a),.b(b));

  * Kevin Neilson, Xilinx, 2007
  *****************************************************************/
module triwire #(parameter WIDTH=8) (inout [WIDTH-1:0] a, b);
   real             Ta_b=1, Tb_a=1;
   reg  [WIDTH-1:0] a_dly = 'bz, b_dly = 'bz;
always@(a) a_dly <= #(Ta_b) b_dly==={WIDTH{1'bz}} ? a : 'bz;
always@(b) b_dly <= #(Tb_a) a_dly==={WIDTH{1'bz}} ? b : 'bz;
   assign b = a_dly, a = b_dly;
endmodule