// 'L2E.vams' - Verilog-AMS connection rules file.
// last revised:  2/06/03 (ronv)
//
// REVISION HISTORY:
// Created:  3/13/02 ronv
// Updated:  4/17/02 ronv - merged features from L2E & Bidir.
// Updated:  6/20/02 ronv - fixed initialization & X issues.
// Updated:  8/30/02 ronv - removed optional output cap
// Updated: 10/22/02 ronv - updated from @cross to @above format, limit vtol
// Updated: 10/30/02 ronv - improved initialization
// Updated:  2/06/03 ronv - updated init to Z rather than X; added hysteresis
//
//============================================================================
// L2E (Din, Aout)
// - Logic-to-Electrical connect module.
//
// DESCRIPTION:
//  Reasonably comprehensive logic-to-electrical conversion routine.
//  This cell actually performs a bidirectional conversion, as the connect
//  module includes the writeback of the equivalent analog voltage level to 
//  the digital input.  Consequently, if connecting a digital "Z" to a driven
//  analog wire, the analog signal will be applied to the digital input.
//  This same cell is used as the "Bidir.v" cell, just by changing the pins
//  to be bidirectional rather than defined as logic in, electrical out.
//
//  Includes X & Z state conversion to analog signals, including separate 
//  output resistances for Lo, Hi, X, and Z, and backconversion to logic
//  levels based on actual analog voltage:  X & Z propagates only when the
//  output voltage falls between the thresholds.  If analog effects (large
//  capacitor or small resistor) cause a hi or lo input to stay between the
//  thresholds for more than txdel seconds, then the backconversion value
//  will be changed to X.  When the logic pin reads a Z, it will respond 
//  just like the electrical-to-logic conversion routine.  When logic pin
//  reads an X, it will immediately writeback the X value.
//
//  All voltage levels (vhi,vlo,vx,vz,vthi,vtlo,vtol) are assigned reasonable
//  default values based on the supply voltage parameter, vsup.  Proper
//  ordering is enforced by parameter range statements.
//
//  Rise time parameters include tr, tf, and tx for transitions to low, high
//  and X, respectively, and tz for transitions to/from Z.  All default to 
//  tr if unspecified.  Note that no td parameter is available:  the output
//  is supposed to be another view of the input, not a delayed version of it.
//  Note that these are 0 to 100% risetime values for the analog voltages.
//  If there is no analog load, the resulting digital driver signal's delay
//  will be typically 2/3 of tr and tf (depending on the threshold voltage
//  values specified).
//
//  Transitions between Lo, Hi, and X levels will shift the voltage linearly
//  through the entire risetime period.  The output resistance is always
//  shifted logarithmically, so that sqrt(R1*R2) falls at the midpoint of the 
//  transition.  When going to/from Z, however, the voltage transition to/from
//  vz is shifted to the upper half of the impedance transition to minimize
//  its impact (so the change to/from the vz mid-voltage level occurs only at
//  the highest impedance end of the resistance shift).
//
//  If all the drives to a node are high-impedance, the logical level fed back
//  will be dependent on the voltage at the analog node (low, high, or X).
//  This cell will not drive the logic to a Z level:  If noone has driven the
//  signal, and it has floated to the center, the proper feedback should be X,
//  since we don't know how the logic would be interpreted at that point. 
//
//  At time zero, this cell will treat digital X or analog in-between as a
//  high impedance Z state, so that initialization procedures can more easily
//  override it (otherwise a temporary unknown condition can result in a
//  forced X state, overriding other signals that would have resolved it).
//
// Example transitions - Given Din signal and no analog load:
//
//  Din  00000000.111111111111111111.ZZZZZZZZZZZZZZZZZZZ.000000000000000
//  Dout 0000000000000.111111111111111111111111111.XXXXXXX.0000000000000
//      .             .                           .       .             
//      .             .  .---vhi--------. |-txdel-|       .             
//      .      vthi___ .'.          .  __`.               .             
//      .            .'  .          .      `.____vz_____. .             
// Vout .          .'    .          .       .           .`.---vtlo      
//      .__vlo___.'      .          .       .           .  `.______vlo__
//      .        .       .          .       .           .       .       
//      .        .       .          .       .____rz_____.       .       
//      .        .       .          .     .'.           .`.     .       
// ln(Rout)      .       .          .   .'  .           .  `.   .       
//      .        .       .          . .'    .           .    `. .       
//      .__rlo_____.....-----rhi-----'      .           .      `.__rlo__
//               |--tr---|          |--tz---|           |--tz---|       
//
// LIMITATIONS:
//  Analog drive is not dependent on the actual strengths of logic signals --
//  this is only a 4-level model (H,L,X,Z).
//
//  For more information on which connect module to select, please refer to:
//    .../tools/affirma_ams/etc/connect_lib/README
//

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

//============================================================================
connectmodule L2E (Din, Aout);
  input Din; \logic Din;                      // input logic
  output Aout; electrical Aout;               // output electrical
  
// INSTANCE PARAMETERS:
  parameter real vsup=1.8 from (0:inf);       // nominal supply voltage
  parameter real vlo=0;                       // output voltage levels
  parameter real vhi=vsup from (vlo:vsup];    //
  parameter real vthi=vhi/1.5 from (vlo:vhi); // upper threshold (def Vhi*2/3)
  parameter real vtlo=vthi/2 from (vlo:vthi); // lower threshold (def Vhi*1/3)
  parameter real vx=(vthi+vtlo)/2 from (vtlo:vthi); // X output voltage
  parameter real vz=(vthi+vtlo)/2 from (vlo:vhi);   // Z output voltage
  parameter real tr=0.2n from (0:1m);         // risetime (L/X to Hi)
  parameter real tf=tr from (0:1m);           // falltime (H/X to Lo)
  parameter real tx=tr from (0:1m);           // time to unknown (L/H/Z to X)
  parameter real tz=tr from (0:1m);           // impedance risetime to/from Z
  parameter real txdel=4*tr;                  // analog-midrange to output X
  parameter real rlo=200 from (0:1M);         // low state output resistance
  parameter real rhi=rlo from (0:1M);         // high state output resistance
  parameter real rx=(rlo+rhi)/10 from (0:1M); // X state output resistance
  parameter real rz=10M from (rhi:1T];        // Z state output resistance 
  parameter real vtol=vsup/100 from (0:(vthi-vtlo)/4]; // voltage tolerance
  parameter real ttol=tr/4;                   // time tolerance of crossing

// LOCAL VARIABLES:
  reg Dreg;                // register to writeback logic
  reg Dold;                // register for keeping previous state of Din
  real Vout,Rout;          // output voltage & resistance
  reg Xin;                 // flag if analog is midrange
  real Rlog;               // natural log of output resistance value
  real txdig;              // delay midlevel to X in timescale units
  real TdV,TrV,TrR;        // delays & risetime for voltage & resistance
  real vtlox,vthix;        // thresholds for transition to X state

//============================================================================
  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.
    vtlox=vtlo+2*vtol;     // lo-to-x threshold point
    vthix=vthi-2*vtol;     // hi-to-x threshold point
  end
  always begin  
    case (Din)                        // Lookup of V,R,T values for new state
      1'b1:  begin                    // to HIGH
         Vout=vhi;  Rlog=ln(rhi);  TdV=0;
         if (Dold!==1'bz)  begin TrV=tr;   TrR=tr; end   // Lo/X to Hi
         else              begin TrV=tz/2; TrR=tz; end   // Z to high
      end
      1'b0: begin                     // to LOW
         Vout=vlo;  Rlog=ln(rlo);  TdV=0;
         if (Dold!==1'bz)  begin TrV=tf;   TrR=tf; end   // Hi/X to Lo
         else              begin TrV=tz/2; TrR=tz; end   // Z to low
      end
      1'bz:  begin                    // to HIGH IMPEDANCE
         Vout=vz;  Rlog=ln(rz);  TdV=tz/2;
         TrV=tz/2; TrR=tz;                               // Hi/Lo/X to Z
      end
      default:  begin                 // to UNKNOWN
         if ($abstime>0) begin        // normal X level
           Vout=vx;  Rlog=ln(rx);  TdV=0;
           TrV=tx;  TrR=tx;                              // Hi/Lo/Z to X
           Dreg=1'bx;                 // logic X occurs immediately
         end
         else begin                   // @T=0, define as Z rather than X
           Vout=vz;  Rlog=ln(rz);  TdV=0;
           TrV=tz/2;  TrR=tz;                            // Z to Hi/Lo
           Dreg=1'bz;                 // logic Z level
         end
      end
    endcase
    if ($abstime==0 && Din!==1'bx) Dreg=Din;   // Initial DC uses Dreg=Din
    Dold=Din;                         // keep old value of Din
    @(Din);                           // repeat when Din changes.
  end

  analog begin                 // Apply Vout,Rout to output with transitions:
     Rout = exp(transition(Rlog,0,TrR,TrR));       // Rout shifts on log scale
     I(Aout) <+ (V(Aout)-transition(Vout,TdV,TrV,TrV))/Rout; // linear Vout chg
  end
  
// Reflect actual levels on analog side back to digital side:
  always @(above(V(Aout)-vthi,ttol,vtol))
      begin Dreg=1; Xin=0; end                   // analog XtoH
  always @(above(vtlo-V(Aout),ttol,vtol))
      begin Dreg=0; Xin=0; end                   // analog XtoL
  always @(above(vthix-V(Aout),ttol,vtol))
      if (V(Aout)>vtlo && Dreg!==1'bx) Xin=1;    // analog HtoX
  always @(above(V(Aout)-vtlox,ttol,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
