// Bidir_2.vams - Efficient bi-directional connection module
// last revised:  04/18/06, jhou
//
// REVISION HISTORY:
// Created:  1/18/04 jhou
// Updated:  1/25/06 jhou - changed default tr to 0.2n
//           4/18/06 jhou - map digital X/Z to analog 0 by default
//                          in the full fast connect modules

/****************************************************************************
Description:

This bi-directional connect module, Bidir_2, is designed for better simulation
performance while maintaining similar accuracy as that of Bidir. Bidir_2
has the following different properties compared to Bidir:

1, Analog voltages of vx/vz, mapped from digital X/Z, are defaulted to
   vlo (which is 0 by default) with output impedance rx/rz.
   When the digital input changes from any value to Z at time > 0,
   the analog output voltage does not change but only the output
   impedance changes to rz (which is high impedance by default).
   In contrast, Bidir maps digital Z/X to analog vsup/2 by default, which
   is a worst case analysis but does not cover all worst cases.

2, The output resistance upon digital X, rx, is default to 10 times the
   sum of output-low and output-high resistances, since the output
   resistance of a gate during transition is usually higher.

3, When digital input changes, both analog output voltage and resistance
   transition linearly. This usually improves the convergence of 
   simulation.

4, A 10% of rise/fall time tolerance is added on transition filters for
   better performance, but the time tolerance is applied only 
   when strictly following the rise/fall time would significantly
   reduce the simulation speed.

5, Bidir_2 applies driver-receiver segregation on all digital signal levels, 
   while in contrast Bidir immediately feeds forward X value from
   driver to receiver.

6, The optimized hysteresis setup between above functions maximizes the
   noise filtering capabilities and hence simulation speed. By default,
   the time tolerance in cross function is 1/4 of transition rise/fall
   time and voltage tolerance is 1/12 of voltage supply.

****************************************************************************/

`include "disciplines.vams"
`timescale 1ns / 100ps

//============================================================================
connectmodule Bidir_2 (Din, Aout);
  inout Din; \logic Din;                      // logic signal
  inout Aout; electrical Aout;                // electrical signal

// INSTANCE PARAMETERS:
 parameter real vsup=1.8          from (0:inf);      // nominal supply voltage
 parameter real vlo=0             from (-inf:vsup);  // logic low voltage
 parameter real vhi=vsup          from (vlo:vsup];   // logic high voltage
 parameter real vthi=vsup/1.5     from (vlo:vsup];   // upper threshold
 parameter real vtlo=vthi/2       from (vlo:vsup];   // lower threshold
 parameter real vx=vlo            from [vlo:vhi];    // X output voltage
 parameter real vz=vx             from [vlo:vhi];    // Z output voltage
 parameter real tr=0.2n           from (0:inf);  // risetime of analog output
 parameter real tf=tr             from (0:inf);  // falltime of analog output
 parameter real ttol_t=(tr+tf)/20 from (0:inf);  // time tol of transition
 parameter real tdelay=0          from [0:inf);  // delay time of analog output
 parameter real rhi=200           from (0:inf);      // output resistance
 parameter real rlo=rhi           from (0:inf);      // output resistance
 parameter real rz=10M            from (0:inf);      // output resistance
 parameter real rx=10*(rlo+rhi)   from (0:inf);      // output resistance
 parameter real txdel=4*tr     from (0:1m];     // time midrange til output X
 parameter real ttol_c=tr/4    from (0:1m];     // time tolerance of crossing
 parameter real vtol=vsup/12   from (0:(vthi-vtlo)/2]; // voltage tolerance
 parameter real vtlox=vtlo+vtol   from (vtlo:vthi);  // lo-to-x threshold point
 parameter real vthix=vthi-vtol   from [vtlox:vthi); // hi-to-x threshold point

// LOCAL VARIABLES:
 reg Dreg;                // register to write back logic
 real Vstate,Rout;        // output voltage & resistance states
 real rout;               // analog output resistance
 reg Xin;                 // flag if analog is in midrange
 real txdig;              // delay from midlevel to X in timescale units

//============================================================================
  initial begin
    txdig=txdel/1n;        // digital delay midlevel to X  (ASSUMES TIMESCALE)
    Dreg=(V(Aout)>vthi)? 1'b1 : (V(Aout)<vtlo)? 1'b0 : 1'bz;  // initial level
    Xin=0;                 // initially not in X delay region.
    Vstate=vz; Rout=rz;         // initially map digital default to vz/rz
  end
 always begin
   case(Din)
     1'b0:  begin  Vstate=vlo; Rout=rlo;    end
     1'b1:  begin  Vstate=vhi; Rout=rhi;    end
     1'bz:  begin  Rout=rz;  end
     default:  begin Vstate=vx; Rout=rx;  end
   endcase
   @(Din);
 end
 analog begin
  rout = transition(Rout,tdelay,tr,tf,ttol_t);     // rout shifts linearly also;
  @(initial_step) rout = rz;                  //Initially with no digital input;
  I(Aout) <+ (V(Aout)-transition(Vstate,tdelay,tr,tf,ttol_t))/rout;
 end

// Reflect actual levels on analog side back to digital side:
  always @(above(V(Aout)-vthi,ttol_c,vtol))
      begin Dreg=1; Xin=0; end                   // analog XtoH
  always @(above(vtlo-V(Aout),ttol_c,vtol))
      begin Dreg=0; Xin=0; end                   // analog XtoL
  always @(above(vthix-V(Aout),ttol_c,vtol))
      if (V(Aout)>vtlo && Dreg!==1'bx) Xin=1;    // analog HtoX
  always @(above(V(Aout)-vtlox,ttol_c,vtol))
      if (V(Aout)<vthi && Dreg!==1'bx) Xin=1;    // analog LtoX
// Wait for txdel before driving output to X:
  always @(posedge(Xin)) begin :GoToX            // input changed to X
    #(txdig)                                     // wait for X time delay
    if (V(Aout)>vtlo && V(Aout)<vthi) Dreg=1'bx; // goto X if still between
    else Xin=0;                                  // else clear the X flag
  end
  always @(negedge(Xin)) disable GoToX;          // cancel out-to-X on Xin=0
  assign  Din=Dreg;                              // assign register to output
endmodule
