// 'L2E_ss.vams' - Verilog-AMS connection module.
// last revised:  3/02/05 (nalin)
//
// REVISION HISTORY:
// Created:  3/13/02 ronv
// Updated:  4/17/02 ronv - copied from L2E.
// Updated:  6/20/02 ronv - fixed initialization & X issues.
// Updated:  9/03/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
// Updated: 11/18/03 ricks - modified for Supply Sensitivity use
// Updated: 12/31/03 ronv - merged: update for DC Z processing
// Updated:  1/30/04 ronv - scaling to simplify & correct Vss sensitivities 
// Updated:  3/02/05 nalin - changed vdd and vss to \vdd!  and \vss!  
//
//============================================================================
// L2E_ss (Din, Aout)
// - Logic-to-Electrical connect module with supply sensitivity.
//
// 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.
//
//  For this supply sensitive version of the model, the fixed levels have
//  been replaced by scale factors which map voltage levels of 0=\vss!  to
//  1=\vdd! .  Default thresholds are therefore vthi=0.67 and vtlo=0.33 etc.
//
//  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_ss (Din, Aout);
  input Din; \logic Din;                      // input logic
  output Aout; electrical Aout;               // output electrical

// Supply Sensitivity attributes
  electrical (* integer supplySensitivity = "cds_globals.\\vdd! " ; *) \vdd! ;
  electrical (* integer groundSensitivity = "cds_globals.\\vss! " ; *) \vss! ;
  
// INSTANCE PARAMETERS:
  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 ttol=tr/4;                   // time tolerance of crossing
// scaled input/output levels/thresholds (0 maps to Vref, 1 maps to Vsup):
  parameter real vlo=0 from [0:1);            // frac. output low level
  parameter real vhi=1 from (vlo:1];          // frac. output high level
  parameter real vthi=vhi/1.5 from (vlo:vhi); // frac. for high tresh (def=2/3)
  parameter real vtlo=vthi/2 from (vlo:vthi); // frac. for low tresh (def=1/3)
  parameter real vx=(vthi+vtlo)/2 from (vtlo:vthi); // frac for X state voltage
  parameter real vz=(vthi+vtlo)/2 from (vlo:vhi);   // frac for Z state voltage
  parameter real vtol=(vthi-vtlo)/10 from (0:(vthi-vtlo)/4]; // frac. for vtol

// LOCAL VARIABLES:
  reg Dreg;                // register to writeback logic
  reg Dold;                // register for keeping previous state of Din
  real Kin,Kout;           // input & output relative to supply range
  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=(Kin>vthi)? 1'b1 : (Kin<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
         Kout=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
         Kout=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
         Kout=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
           Kout=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
           Kout=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) begin            // get new state appropriately at DC:
      if (Din===1'bz) Dreg=(Kin>vthi)? 1'b1 : (Kin<vtlo)? 1'b0 : 1'bz;
      else if (Din!==1'bx) Dreg=Din;
    end
    Dold=Din;                         // keep old value of Din
    @(Din);                           // repeat when Din changes.
  end

  analog begin    
// Relative input level (maps input to range of 0=vref, 1=vsup):
     Kin = V(Aout,\vss! )/max(V(\vdd! ,\vss! ),1m);
// Output resistance shifts on log scale over its rise time:
     Rout = exp(transition(Rlog,0,TrR,TrR));
// Output voltage shifts linearly over rise time, scales with supply:
     Vout = V(\vdd! ,\vss! )*transition(Kout,TdV,TrV,TrV);
     I(Aout) <+ (V(Aout,\vss! )-Vout)/Rout;
//+// Output drive from proper supply could use this format:
//+     if (Vout<V(Aout,\vss! ))  I(Aout,\vss! ) <+ (V(Aout,\vss! )-Vout)/Rout;
//+     else                   I(\vdd! ,Aout) <+ (Vout-V(Aout,\vss! ))/Rout;
  end
  
// Reflect actual levels on analog side back to digital side:
  always @(above(Kin-vthi,ttol,vtol))
      begin Dreg=1; Xin=0; end                   // analog XtoH
  always @(above(vtlo-Kin,ttol,vtol))
      begin Dreg=0; Xin=0; end                   // analog XtoL
  always @(above(vthix-Kin,ttol,vtol))
      if (Kin>vtlo && Dreg!==1'bx) Xin=1;        // analog HtoX
  always @(above(Kin-vtlox,ttol,vtol))
      if (Kin<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 (Kin>0 && Kin<1) 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
