//============================================================================= // Description: IBIS macro library implemented in Verilog-A(MS) // Created: September 2005 by Arpad Muranyi (Intel Corporation) // // Revision history: // // 2005/10/10 - rev0.0 completed. // 2005/10/19 - Fixed IBIS_K to include the Scale parameter in the // calculation of M. // - Fixed IBIS_T equations. // 2005/10/21 - Fixed @(cross) logic in "Catch process" of all buffer models. // - Removed En_D from IBIS_OPENSINK and IBIS_OPENSOURCE. // - Fixed initial state in IBIS_IO_OPENSOURCE. // 2005/10/24 - Removed extra variables related to second pair of Vt tables. // from IBIS_OPENSINK, IBIS_IO_OPENSINK, IBIS_OPENSOURCE and // IBIS_IO_OPENSOURCE from Max_t, Min_t and Max_length equations. // 2005/10/26 - Corrected event triggered PWL sources so that they will only // start after the first event occurred on the input (and not // immediately at t=0). // 2005/10/27 - Changed @(cross ...) events to have 100ps and 100mV tolerances. // - Rearranged equations in controlled capacitor and inductor // modules to be nice to some simulators which cannot use probed // voltages and/or currents with ddt() together. // - Applied the same change to IBIS_K to make the module more // efficient by reducing the number of ddt() operators. // 2005/11/03 - Changed IBIS_TCVS_PWL and IBIS_TCCS_PWL sources to do HE. // - Changed the four event controlled PWL sources to have two // data tables with independent threshold voltages (one for // each triggering edge direction), and to do HE. // 2006/01/23 - Changed spelling of several variable names to match them // with the VHDL-A(MS) implementation. // - Made minor changes in the code to match with the VHDL-A(MS) // implementation. // 2006/02/06 - Changed the algorithm of "DIV" controlled sources to handle // div/0 situation more gently. // 2006/02/27 - Fixed a bug in the "FindCommonLength" and "CommonTime" // functions of IBIS buffer models. // - Added IV and Vt curve scaling capability to IBIS buffers // 2006/06/28 - Added port direction declarations. // - Fixed a typo in the "DIV" module's analog equations. // - Added "$discontinuity" statements to "DIV" and event // controlled PWL sources. // - Removed "\" character from some of the test bench files. // - Fixed event controlled PWL sources to initialize properly // for all possible combinations of input values. // - Fixed the input thresholds for buffers and event triggered // PWL sources to be more compatible with HSPICE's B-element // threshold levels. // - Updated "state machine" of buffers and event controlled PWL // sources to follow the same algorithm as in the VHDL-AMS // version. // - Added a warning to the IBIS_***_DIV elements. // 2007/02/20 - Mike LaBonte // - Added documentation for IBIS buffer modules. // - Changed some buffer "IO" terminals to "Pad", for consistency. //============================================================================= // ======================================== Module list === // // LIST OF MODULES: // // IBIS_R (p, n) // IBIS_VCR (p, n, ps, ns) // IBIS_CCR (p, n, ps, ns) // IBIS_C (p, n) // IBIS_VCC (p, n, ps, ns) // IBIS_CCC (p, n, ps, ns) // IBIS_L (p, n) // IBIS_VCL (p, n, ps, ns) // IBIS_CCL (p, n, ps, ns) // IBIS_K (p1, n1, p2, n2) // IBIS_V (p, n) // IBIS_VCVS (p, n, ps, ns) // IBIS_CCVS (p, n, ps, ns) // IBIS_VCVS_DELAY (p, n, ps, ns) // IBIS_CCVS_DELAY (p, n, ps, ns) // IBIS_VCVS_MIN (p, n, ps1, ns1, ps2, ns2) // IBIS_CCVS_MIN (p, n, ps1, ns1, ps2, ns2) // IBIS_VCVS_MAX (p, n, ps1, ns1, ps2, ns2) // IBIS_CCVS_MAX (p, n, ps1, ns1, ps2, ns2) // IBIS_VCVS_ABS (p, n, ps, ns) // IBIS_CCVS_ABS (p, n, ps, ns) // IBIS_VCVS_SUM (p, n, ps1, ns1, ps2, ns2) // IBIS_CCVS_SUM (p, n, ps1, ns1, ps2, ns2) // IBIS_VCVS_MULT (p, n, ps1, ns1, ps2, ns2) // IBIS_CCVS_MULT (p, n, ps1, ns1, ps2, ns2) // IBIS_VCVS_DIV (p, n, ps1, ns1, ps2, ns2) // IBIS_CCVS_DIV (p, n, ps1, ns1, ps2, ns2) // IBIS_VCVS_PWL (p, n, ps, ns) // IBIS_CCVS_PWL (p, n, ps, ns) // IBIS_TCVS_PWL (p, n) // IBIS_VECVS_PWL (p, n, ps, ns) // IBIS_CECVS_PWL (p, n, ps, ns) // IBIS_I (p, n) // IBIS_VCCS (p, n, ps, ns) // IBIS_CCCS (p, n, ps, ns) // IBIS_VCCS_DELAY (p, n, ps, ns) // IBIS_CCCS_DELAY (p, n, ps, ns) // IBIS_VCCS_MIN (p, n, ps1, ns1, ps2, ns2) // IBIS_CCCS_MIN (p, n, ps1, ns1, ps2, ns2) // IBIS_VCCS_MAX (p, n, ps1, ns1, ps2, ns2) // IBIS_CCCS_MAX (p, n, ps1, ns1, ps2, ns2) // IBIS_VCCS_ABS (p, n, ps, ns) // IBIS_CCCS_ABS (p, n, ps, ns) // IBIS_VCCS_SUM (p, n, ps1, ns1, ps2, ns2) // IBIS_CCCS_SUM (p, n, ps1, ns1, ps2, ns2) // IBIS_VCCS_MULT (p, n, ps1, ns1, ps2, ns2) // IBIS_CCCS_MULT (p, n, ps1, ns1, ps2, ns2) // IBIS_VCCS_DIV (p, n, ps1, ns1, ps2, ns2) // IBIS_CCCS_DIV (p, n, ps1, ns1, ps2, ns2) // IBIS_VCCS_PWL (p, n, ps, ns) // IBIS_CCCS_PWL (p, n, ps, ns) // IBIS_TCCS_PWL (p, n) // IBIS_VECCS_PWL (p, n, ps, ns) // IBIS_CECCS_PWL (p, n, ps, ns) // IBIS_T (n1, ref1, n2, ref2) // IBIS_INPUT (PC_ref, GC_ref, Pad, Rcv_D) // IBIS_OUTPUT (PU_ref, PD_ref, Pad, In_D, PC_ref, GC_ref) // IBIS_IO (PU_ref, PD_ref, Pad, In_D, En_D, Rcv_D, PC_ref, GC_ref) // IBIS_3STATE (PU_ref, PD_ref, Pad, In_D, En_D, PC_ref, GC_ref) // IBIS_OPENSINK (PU_ref, PD_ref, Pad, In_D, PC_ref, GC_ref) // IBIS_IO_OPENSINK (PU_ref, PD_ref, Pad, In_D, En_D, Rcv_D, PC_ref, GC_ref) // IBIS_OPENSOURCE (PU_ref, PD_ref, Pad, In_D, PC_ref, GC_ref) // IBIS_IO_OPENSOURCE (PU_ref, PD_ref, Pad, In_D, En_D, Rcv_D, PC_ref, GC_ref) // // ========================================================= //============================================================================= // // IBIS buffer types and keywords not implemented yet: // // Input_ECL, Output_ECL, I/O_ECL, 3-state_ECL, Terminator, // Series, and Series_switch. // // [R Series] - not necessary, it can be implemented by other elements // [L Series] - not necessary, it can be implemented by other elements // [Rl Series] - not necessary, it can be implemented by other elements // [C Series] - not necessary, it can be implemented by other elements // [Lc Series] - not necessary, it can be implemented by other elements // [Rc Series] - not necessary, it can be implemented by other elements // [Series Current] - not necessary, it can be implemented with VCCS_PWL // [Series MOSFET] - could be useful // [On], [Off] - TBD // // // IBIS_SPARAM - a building block using S-parameter data as input // //----------------------------------------------------------------------------- // Other ideas: // // Do we need a conductance model? // Do we need temperature coefficients in resistor (and conductance) models? // Do we need an ideal switch model? // // Frequency domain equations and/or sources? // // More than 2 element mutual inductor(s)? // More than 2 input adder, multiplier? // Other math functions (power, root, exp, log, etc...)? // Other math operators (derivative, integral, etc...)? // //----------------------------------------------------------------------------- // List of features not implemented yet from Don Telian's list: // // Equation-based sources (voltage, current, numeric) // AM: This cannot be done due to language limitations. Even // though string parameters do exist, they cannot be // interpreted as expression (i.e. converted to "code"). // However, it would be easy to write equation based source // statements in the templates directly assuming some // familiarity with the language. This could prevent or // make the substitution of native SPICE elements impossible, // though. // // B element with c_comp on/off and table scaling (static/dynamic) // - Hspice can't do c_comp or dynamic // AM: Both of these features can be added easily to the existing // *-AMS IBIS buffer implementations. Dynamic scaling would // require addition control ports, as discussed with the // controlled R, L, and C building blocks. We need to decide // how many and what type of control ports we want to add. // // Expressions in parameters // AM: Same answer as 1st entry above. // // Use of previously computed value (prev(x)) in equation // - Hspice can not // AM: Need to check into this how it can be done in *-AMS. // //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_R (p, n) // // DESCRIPTION: // A simple resistor. The resistance value is calculated: // // R = Rval * Scale // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // // PARAMETERS: // // Rval Resistance value // DEFAULT Rval = '1.0' // // Scale Scaling factor for calculating resistance value // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 clk_n clkp IBIS_R Rval=100 // // VAMS: IBIS_R #(.Rval(100)) R1 (clk_n, clk_p); // // ========================================================= module IBIS_R (p, n); inout p, n; electrical p, n; branch (p, n) Out; parameter real Rval = 1.0; parameter real Scale = 1.0; analog begin V(Out) <+ Scale * Rval * I(Out); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCR (p, n, ps, ns) // // DESCRIPTION: // A voltage-controlled resistor. The resistance value is // calculated: // // R = V(ps,ns) * Scale // // The sense terminals ps and ns draw no current. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps positive sense terminal for control voltage // ns negative sense terminal for control voltage // // PARAMETERS: // // Scale Scaling factor for calculating resistance value // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 clkn clkp vcrp vcrn IBIS_VCR Scale=50 // // VAMS: IBIS_VCR #(.Scale(50)) VCR1 (clkn, clk_p, vcrp, vcrn); // // ========================================================= module IBIS_VCR (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(Out) <+ Scale * V(In) * I(Out); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCR (p, n, ps, ns) // // DESCRIPTION: // A current-controlled resistor. The resistance value is // calculated: // // R = I(ps,ns) * Scale // // The sense terminals ps and ns behave as a short circuit. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps positive sense terminal for control current // ns negative sense terminal for control current // // PARAMETERS: // // Scale Scaling factor for calculating resistance value // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 clkn clkp ccrp ccrn IBIS_CCR Scale=200 // // VAMS: IBIS_CCR #(.Scale(200)) CCR1 (clkn, clk_p, ccrp, ccrn); // // ========================================================= module IBIS_CCR (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(In) <+ 0.0; V(Out) <+ Scale * I(In) * I(Out); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_C (p, n) // // DESCRIPTION: // A simple capacitor. The capacitance value is calculated: // // C = Cval * Scale // // TERMINALS: // // p positive capacitor terminal // n negative capacitor terminal // // PARAMETERS: // // Cval Capacitance value // DEFAULT Cval = '1.0' // // V0 Voltage value at time = zero // DEFAULT V0 = '0.0' // // Scale Scaling factor for calculating capacitance value // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 clk_n clkp IBIS_C Cval=4.5 Scale=1e-12 // // VAMS: IBIS_C #(.Cval(4.5),.Scale(1e-12))) C1 (clk_n, clk_p); // // ========================================================= module IBIS_C (p, n); inout p, n; electrical p, n; branch (p, n) Out; parameter real Cval = 1.0; parameter real V0 = 0.0; parameter real Scale = 1.0; analog begin if (analysis("static")) V(Out) <+ V0; else I(Out) <+ Scale * Cval * ddt(V(Out)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCC (p, n, ps, ns) // // DESCRIPTION: // A voltage-controlled capacitor. The capacitance value is // calculated: // // C = V(ps,ns) * Scale // // The sense terminals ps and ns draw no current. This is a // charge-conserving model. When the capacitance value // changes, a displacement current is produced from p to n to // adjust the stored charge so that the total charge level // observes the rule: // // Q = C * V(p,n) // // TERMINALS: // // p positive capacitor terminal // n negative capacitor terminal // ps positive sense terminal for control voltage // ns negative sense terminal for control voltage // // PARAMETERS: // // V0 Voltage at time = zero // DEFAULT V0 = '0.0' // // Scale Scaling factor for calculating capacitance value // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 clkn clkp vccp vccn IBIS_VCC Scale=1e-12 // // VAMS: IBIS_VCC #(.Scale(1e-12)) VCC1 (clkn, clk_p, vccp, vccn); // // ========================================================= module IBIS_VCC (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real V0 = 0.0; parameter real Scale = 1.0; // real dIn; // real dOut; analog begin // dIn = ddt(V(In)); // dOut = ddt(V(Out)); if (analysis("static")) V(Out) <+ V0; else // I(Out) <+ Scale * (V(Out)*dIn + V(In)*dOut); // Some tools cannot handle the syntax below. If that is the case, comment // out the following line and comment in all of the commented lines above. I(Out) <+ Scale * (V(Out)*ddt(V(In)) + V(In)*ddt(V(Out))); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCC (p, n, ps, ns) // // DESCRIPTION: // A current-controlled capacitor. The capacitance value is // calculated: // // C = I(ps,ns) * Scale // // The sense terminals ps and ns behave as a short circuit. // // This is a charge-conserving model. When the capacitance // value changes, a displacement current is produced from p // to n to adjust the stored charge so that the total charge // level observes the rule: // // Q = C * V(p,n) // // TERMINALS: // // p positive capacitor terminal // n negative capacitor terminal // ps positive sense terminal for control current // ns negative sense terminal for control current // // PARAMETERS: // // V0 Capacitor voltage at time zero // DEFAULT V0 = '0.0' // // Scale Scaling factor for calculating capacitance value // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 clkn clkp cccp cccn IBIS_CCC Scale=5e-12 // // VAMS: IBIS_CCC #(.Scale(5e-12)) CCC1 (clkn, clk_p, cccp, cccn); // // ========================================================= module IBIS_CCC (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real V0 = 0.0; parameter real Scale = 1.0; // real dIn; // real dOut; analog begin // dIn = ddt(I(In)); // dOut = ddt(V(Out)); V(In) <+ 0.0; if (analysis("static")) V(Out) <+ V0; else // I(Out) <+ Scale * (V(Out)*dIn + I(In)*dOut); // Some tools cannot handle the syntax below. If that is the case, comment // out the following line and comment in all of the commented lines above. I(Out) <+ Scale * (V(Out)*ddt(I(In)) + I(In)*ddt(V(Out))); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_L (p, n) // // DESCRIPTION: // A simple inductor. The inductance value is calculated: // // L = Lval * Scale // // TERMINALS: // // p positive inductor terminal // n negative inductor terminal // // PARAMETERS: // // Lval Inductance value // DEFAULT Lval = '1.0' // // I0 Inductance value // DEFAULT I0 = '0.0' // // Scale Scaling factor for calculating inductance value // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 clk_n clkp IBIS_L Lval=0.8 Scale=1e-9 // // VAMS: IBIS_L #(.Lval(0.8),.Scale(1e-9)) L1 (clk_n, clk_p); // // ========================================================= module IBIS_L (p, n); inout p, n; electrical p, n; branch (p, n) Out; parameter real Lval = 1.0; parameter real I0 = 0.0; parameter real Scale = 1.0; analog begin if (analysis("static")) I(Out) <+ I0; else V(Out) <+ Scale * Lval * ddt(I(Out)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCL (p, n, ps, ns) // // DESCRIPTION: // A voltage-controlled inductor. The inductance value is // calculated: // // L = V(ps,ns) * Scale // // The sense terminals ps and ns draw no current. This is a // flux-conserving model. When the inductance value changes, // the voltage-current relationship adjusts so that magnetic // flux is conserved in the equation: // // B = L * I(p,n) // // TERMINALS: // // p positive inductor terminal // n negative inductor terminal // ps positive sense terminal for control voltage // ns negative sense terminal for control voltage // // PARAMETERS: // // I0 Inductor current at time zero // DEFAULT I0 = '0.0' // // Scale Scaling factor for calculating inductance value // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 clkn clkp vclp vcln IBIS_VCL Scale=0.5e-9 // // VAMS: IBIS_VCL #(.Scale(0.5e-9)) VCL1 (clkn, clk_p, vclp, vcln); // // ========================================================= module IBIS_VCL (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real I0 = 0.0; parameter real Scale = 1.0; // real dIn; // real dOut; analog begin // dIn = ddt(V(In)); // dOut = ddt(I(Out)); if (analysis("static")) I(Out) <+ I0; else // V(Out) <+ Scale * (I(Out)*dIn + V(In)*dOut); // Some tools cannot handle the syntax below. If that is the case, comment // out the following line and comment in all of the commented lines above. V(Out) <+ Scale * (I(Out)*ddt(V(In)) + V(In)*ddt(I(Out))); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCL (p, n, ps, ns) // // DESCRIPTION: // A current-controlled inductor. The inductance value is // calculated: // // L = I(ps,ns) * Scale // // The sense terminals ps and ns draw no current. // // This is a flux-conserving model. When the inductance value // changes, the voltage-current relationship adjusts so that // magnetic flux is conserved in the equation: // // B = L * I(p,n) // // TERMINALS: // // p positive inductor terminal // n negative inductor terminal // ps positive sense terminal for control current // ns negative sense terminal for control current // // PARAMETERS: // // I0 Inductor current at time zero // DEFAULT I0 = '0.0' // // Scale Scaling factor for calculating inductance value // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 clkn clkp cclp ccln IBIS_CCL Scale=4e-9 // // VAMS: IBIS_CCL #(.Scale(4e-9)) CCL1 (clkn, clk_p, cclp, ccln); // // ========================================================= module IBIS_CCL (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real I0 = 0.0; parameter real Scale = 1.0; // real dIn; // real dOut; analog begin // dIn = ddt(I(In)); // dOut = ddt(I(Out)); V(In) <+ 0.0; if (analysis("static")) I(Out) <+ I0; else // V(Out) <+ Scale * (I(Out)*dIn + I(In)*dOut); // Some tools cannot handle the syntax below. If that is the case, comment // out the following line and comment in all of the commented lines above. V(Out) <+ Scale * (I(Out)*ddt(I(In)) + I(In)*ddt(I(Out))); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_K (p1, n1, p2, n2) // // DESCRIPTION: // A mutually-coupled inductor pair. The inductance values // are calculated: // // L_1 = Lval_1 * Scale // // L_2 = Lval_2 * Scale // // TERMINALS: // // p1 positive inductor 1 terminal // n1 negative inductor 1 terminal // p2 positive inductor 2 terminal // n2 negative inductor 2 terminal // // PARAMETERS: // // Lval_1 Inductance value for inductor 1 // DEFAULT Lval_1 = '1.0' // // Lval_2 Inductance value for inductor 2 // DEFAULT Lval_2 = '1.0' // // Kval Mutual coupling value // DEFAULT Kval = '0.0' // // I0_1 Inductance value at time zero for inductor 1 // DEFAULT I0_1 = '0.0' // // I0_2 Inductance value at time zero for inductor 2 // DEFAULT I0_2 = '0.0' // // Scale Scaling factor for calculating both inductance values // DEFAULT Scale = '1.0' // // M // DEFAULT M = 'Scale * Kval * sqrt(Lval_1 * Lval_2)' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 pad_n pad_p pin_n pin_p IBIS_K \ // + Lval_1=0.8 Lval_2=0.5 Kval=0.15 Scale=1e-9 // // VAMS: IBIS_K // #(.Lval_1(0.8),.Lval_2(0.5),.Kval(0.15),.Scale(1e-9)) \ // K1 (pad_n, pad_p, pin_n, pin_p); // // ========================================================= module IBIS_K (p1, n1, p2, n2); inout p1, n1, p2, n2; electrical p1, n1, p2, n2; branch (p1, n1) Out1; branch (p2, n2) Out2; parameter real Lval_1 = 1.0; parameter real Lval_2 = 1.0; parameter real Kval = 0.0; parameter real I0_1 = 0.0; parameter real I0_2 = 0.0; parameter real Scale = 1.0; // This should really be a "localparam" to prevent it from being // changed from the outside. parameter real M = Scale * Kval * sqrt(Lval_1 * Lval_2); // real dOut1; // real dOut2; analog begin // dOut1 = ddt(I(Out1)); // dOut2 = ddt(I(Out2)); if (analysis("static")) begin I(Out1) <+ I0_1; I(Out2) <+ I0_2; end else begin // V(Out1) <+ Scale * Lval_1 * dOut1 + M * dOut2; // V(Out2) <+ Scale * Lval_2 * dOut2 + M * dOut1; // Some tools cannot handle the syntax below. If that is the case, comment // out the following lines and comment in all of the commented lines above. V(Out1) <+ Scale * Lval_1 * ddt(I(Out1)) + M * ddt(I(Out2)); V(Out2) <+ Scale * Lval_2 * ddt(I(Out2)) + M * ddt(I(Out1)); end end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_V (p, n) // // DESCRIPTION: // A DC voltage source. Output voltage is calculated: // // V(p,n) = Vdc * Scale // // TERMINALS: // // p positive voltage source terminal // n negative voltage source terminal // // PARAMETERS: // // Vdc DC voltage value // DEFAULT Vdc = '1.0' // // Scale Scaling factor for calculating inductance value // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 vddq vss IBIS_V Vdc=3.3 // // VAMS: IBIS_V #(.Vdc(3.3)) V1 (vddq, vss); // // ========================================================= module IBIS_V (p, n); inout p, n; electrical p, n; branch (p, n) Out; parameter real Vdc = 1.0; parameter real Scale = 1.0; analog begin V(Out) <+ Scale * Vdc; end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCVS (p, n, ps, ns) // // DESCRIPTION: // A voltage-controlled voltage source. The output voltage // value is calculated: // // V(p,n) = V(ps,ns) * Scale // // The sense terminals ps and ns draw no current. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps positive sense terminal for control voltage // ns negative sense terminal for control voltage // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 clkn clkp vcrp vcrn IBIS_VCVS Scale=0.5 // // VAMS: IBIS_VCVS #(.Scale(0.5)) VCVS1 (clkn, clk_p, vcrp, vcrn); // // ========================================================= module IBIS_VCVS (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(Out) <+ Scale * V(In); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCVS (p, n, ps, ns) // // DESCRIPTION: // A current-controlled voltage source. The output voltage // value is calculated: // // V(p,n) = I(ps,ns) * Scale // // The sense terminals ps and ns behave as a short circuit. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps positive sense terminal for control current // ns negative sense terminal for control current // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 buf2in vss pad padi IBIS_CCVS Scale=100 // // VAMS: IBIS_CCVS #(.Scale(100)) CCVS1 (buf2in, vss, pad, padi); // // ========================================================= module IBIS_CCVS (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(In) <+ 0.0; V(Out) <+ Scale * I(In); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCVS_DELAY (p, n, ps, ns) // // DESCRIPTION: // A voltage-controlled voltage source with delay. All // changes at the sense terminals affect the output later in // time, using the specified delay. The voltage value is // calculated: // // V(p,n) = V(ps,ns) * Scale, delayed by TD // // The sense terminals ps and ns draw no current. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps positive sense terminal for control voltage // ns negative sense terminal for control voltage // // PARAMETERS: // // TD Time delay from control voltage change to output change // DEFAULT TD = '0.0' // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 buf2in vss pad padi IBIS_VCVS_DELAY TD=200p // // VAMS: IBIS_VCVS_DELAY #(.TD(200e-12)) \ // VCVS1 (buf2in, vss, pad, padi); // // ========================================================= module IBIS_VCVS_DELAY (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real TD = 0.0; parameter real Scale = 1.0; analog begin V(Out) <+ Scale * absdelay(V(In), TD); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCVS_DELAY (p, n, ps, ns) // // DESCRIPTION: // A current-controlled voltage source with delay. All // changes at the sense terminals affect the output later, // using the specified delay in seconds. The voltage value is // calculated: // // V(p,n) = I(ps,ns) * Scale // // The sense terminals ps and ns behave as a short circuit. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps positive sense terminal for control current // ns negative sense terminal for control current // // PARAMETERS: // // TD Time delay from control current change to output change // DEFAULT TD = '0.0' // // Scale Scaling factor for calculating voltage // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 buf2in vss pad padi IBIS_CCVS_DELAY Scale=100 TD=200p // // VAMS: IBIS_CCVS_DELAY #(.Scale(100),.TD(200e-12)) \ // CCVS1 (buf2in, vss, pad, padi); // // ========================================================= module IBIS_CCVS_DELAY (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real TD = 0.0; parameter real Scale = 1.0; analog begin V(In) <+ 0.0; V(Out) <+ Scale * absdelay(I(In), TD); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCVS_MIN (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A voltage-controlled voltage source for taking the lesser // of two control input voltages. The output voltage value is // calculated: // // V(p,n) = min( V(ps1,ns1) V(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 draw no current. The sense // terminals ps2 and ns2 draw no current. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps1 positive sense terminal for control voltage 1 // ns1 negative sense terminal for control voltage 1 // ps2 positive sense terminal for control voltage 2 // ns2 negative sense terminal for control voltage 2 // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 bufctl vss ctlmain vss boost vss IBIS_VCVS_MIN // // VAMS: IBIS_VCVS_MIN MIN1 (bufctl, vss, ctlmain, vss, boost, // vss); // // ========================================================= module IBIS_VCVS_MIN (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(Out) <+ Scale * min(V(In1), V(In2)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCVS_MIN (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A voltage-controlled voltage source for taking the lesser // of two control input voltages. The output voltage value is // calculated: // // V(p,n) = min( V(ps1,ns1) V(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 behave as a short circuit. // The sense terminals ps2 and ns2 behave as a short circuit. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps1 positive sense terminal for control current 1 // ns1 negative sense terminal for control current 1 // ps2 positive sense terminal for control current 2 // ns2 negative sense terminal for control current 2 // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 bufctl vss ctlmain ctlmaini boost boosti IBIS_CCVS_MIN // // VAMS: IBIS_CCVS_MIN MIN1 (bufctl, vss, ctlmain, vss, boost, // vss); // // ========================================================= module IBIS_CCVS_MIN (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(In1) <+ 0.0; V(In2) <+ 0.0; V(Out) <+ Scale * min(I(In1), I(In2)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCVS_MAX (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A voltage-controlled voltage source for taking the greater // of two control input voltages. The output voltage value is // calculated: // // V(p,n) = min( V(ps1,ns1) V(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 draw no current. The sense // terminals ps2 and ns2 draw no current. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps1 positive sense terminal for control voltage 1 // ns1 negative sense terminal for control voltage 1 // ps2 positive sense terminal for control voltage 2 // ns2 negative sense terminal for control voltage 2 // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 bufctl vss ctlmain vss boost vss IBIS_VCVS_MAX // // VAMS: IBIS_VCVS_MAX MAX1 (bufctl, vss, ctlmain, vss, boost, // vss); // // ========================================================= module IBIS_VCVS_MAX (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(Out) <+ Scale * max(V(In1), V(In2)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCVS_MAX (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A current-controlled voltage source for taking the greater // of two input currents. The output voltage value is // calculated: // // V(p,n) = max( I(ps1,ns1) I(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 draw no current. The sense // terminals ps2 and ns2 draw no current. // // TERMINALS: // // p positive voltage source terminal // n negative voltage source terminal // ps1 positive sense terminal for control current 1 // ns1 negative sense terminal for control current 1 // ps2 positive sense terminal for control current 2 // ns2 negative sense terminal for control current 2 // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_CCVS_MAX (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(In1) <+ 0.0; V(In2) <+ 0.0; V(Out) <+ Scale * max(I(In1), I(In2)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCVS_ABS (p, n, ps, ns) // // DESCRIPTION: // A voltage-controlled voltage source for taking the // absolute value of the control voltage. The output voltage // value is always positive, and is calculated: // // V(p,n) = abs( V(ps,ns) ) * Scale // // The sense terminals ps and ns draw no current. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps positive sense terminal for control voltage // ns negative sense terminal for control voltage // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_VCVS_ABS (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(Out) <+ Scale * abs(V(In)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCVS_ABS (p, n, ps, ns) // // DESCRIPTION: // A current-controlled voltage source for taking the // absolute value of the control current. The output voltage // value is always positive, and is calculated: // // V(p,n) = abs( I(ps,ns) ) * Scale // // The sense terminals ps and ns behave as a short circuit. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps positive sense terminal for control current // ns negative sense terminal for control current // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_CCVS_ABS (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(In) <+ 0.0; V(Out) <+ Scale * abs(I(In)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCVS_SUM (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A voltage-controlled voltage source for taking the sum of // two control input voltages. The output voltage value is // calculated: // // V(p,n) = ( V(ps1,ns1) + V(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 draw no current. The sense // terminals ps2 and ns2 draw no current. // // TERMINALS: // // p positive voltage source terminal // n negative voltage source terminal // ps1 positive sense terminal for control voltage 1 // ns1 negative sense terminal for control voltage 1 // ps2 positive sense terminal for control voltage 2 // ns2 negative sense terminal for control voltage 2 // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_VCVS_SUM (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(Out) <+ Scale * (V(In1) + V(In2)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCVS_SUM (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A current-controlled voltage source for taking the sum of // two control input voltages. The output voltage value is // calculated: // // V(p,n) = ( I(ps1,ns1) + I(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 behave as a short circuit. // The sense terminals ps2 and ns2 behave as a short circuit. // // TERMINALS: // // p positive voltage source terminal // n negative voltage source terminal // ps1 positive sense terminal for control current 1 // ns1 negative sense terminal for control current 1 // ps2 positive sense terminal for control current 2 // ns2 negative sense terminal for control current 2 // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_CCVS_SUM (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(In1) <+ 0.0; V(In2) <+ 0.0; V(Out) <+ Scale * (I(In1) + I(In2)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCVS_MULT (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A voltage-controlled voltage source for taking the product // of two control input voltages. The output voltage value is // calculated: // // V(p,n) = ( V(ps1,ns1) * V(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 draw no current. The sense // terminals ps2 and ns2 draw no current. // // TERMINALS: // // p positive voltage source terminal // n negative voltage source terminal // ps1 positive sense terminal for control voltage 1 // ns1 negative sense terminal for control voltage 1 // ps2 positive sense terminal for control voltage 2 // ns2 negative sense terminal for control voltage 2 // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_VCVS_MULT (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(Out) <+ Scale * V(In1) * V(In2); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCVS_MULT (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A current-controlled voltage source for taking the product // of two control input currents. The output voltage value is // calculated: // // V(p,n) = ( I(ps1,ns1) * I(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 behave as a short circuit. // The sense terminals ps2 and ns2 behave as a short circuit. // // TERMINALS: // // p positive voltage source terminal // n negative voltage source terminal // ps1 positive sense terminal for control current 1 // ns1 negative sense terminal for control current 1 // ps2 positive sense terminal for control current 2 // ns2 negative sense terminal for control current 2 // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_CCVS_MULT (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(In1) <+ 0.0; V(In2) <+ 0.0; V(Out) <+ Scale * I(In1) * I(In2); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCVS_DIV (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A voltage-controlled voltage source for taking the ratio // of two control input voltages. The output voltage value is // calculated: // // V(p,n) = ( V(ps1,ns1) / V(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 draw no current. The sense // terminals ps2 and ns2 draw no current. // // TERMINALS: // // p positive voltage source terminal // n negative voltage source terminal // ps1 positive sense terminal for control voltage 1 // ns1 negative sense terminal for control voltage 1 // ps2 positive sense terminal for control voltage 2 // ns2 negative sense terminal for control voltage 2 // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // ZeroLimit // DEFAULT ZeroLimit = '1.0e-3' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_VCVS_DIV (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; parameter real ZeroLimit = 1.0e-3; real AbsVin2; integer NearZero; analog begin AbsVin2 = abs(V(In2)); if (analysis("static")) begin if (AbsVin2 > ZeroLimit) begin NearZero = 0; end else begin NearZero = 1; $strobe("Warning: The divisor in module 'IBIS_VCVS_DIV' is less than or equal to the value defined in its parameter 'ZeroLimit = %e' at time = %e.", ZeroLimit, $abstime); end end @(cross(AbsVin2-ZeroLimit, 0, 100p, 100m)) begin if (AbsVin2 > ZeroLimit) begin NearZero = 0; end else begin NearZero = 1; $strobe("Warning: The divisor in module 'IBIS_VCVS_DIV' is less than or equal to the value defined in its parameter 'ZeroLimit = %e' at time = %e.", ZeroLimit, $abstime); end $discontinuity(1); end if (NearZero) begin V(Out) <+ Scale * V(In1) * V(In2) / pow(ZeroLimit,2); end else begin V(Out) <+ Scale * V(In1) / V(In2); end end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCVS_DIV (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A current-controlled voltage source for taking the ratio // of two control input currents. The output voltage value is // calculated: // // V(p,n) = ( I(ps1,ns1) / I(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 behave as a short circuit. // The sense terminals ps2 and ns2 behave as a short circuit. // // TERMINALS: // // p positive voltage source terminal // n negative voltage source terminal // ps1 positive sense terminal for control current 1 // ns1 negative sense terminal for control current 1 // ps2 positive sense terminal for control current 2 // ns2 negative sense terminal for control current 2 // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // ZeroLimit // DEFAULT ZeroLimit = '1.0e-3' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_CCVS_DIV (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; parameter real ZeroLimit = 1.0e-3; real AbsIin2; integer NearZero; analog begin AbsIin2 = abs(I(In2)); V(In1) <+ 0.0; V(In2) <+ 0.0; if (analysis("static")) begin if (AbsIin2 > ZeroLimit) begin NearZero = 0; end else begin NearZero = 1; $strobe("Warning: The divisor in module 'IBIS_CCVS_DIV' is less than or equal to the value defined in its parameter 'ZeroLimit = %e' at time = %e.", ZeroLimit, $abstime); end end @(cross(AbsIin2-ZeroLimit, 0, 100p, 100m)) begin if (AbsIin2 > ZeroLimit) begin NearZero = 0; end else begin NearZero = 1; $strobe("Warning: The divisor in module 'IBIS_CCVS_DIV' is less than or equal to the value defined in its parameter 'ZeroLimit = %e' at time = %e.", ZeroLimit, $abstime); end $discontinuity(1); end if (NearZero) begin V(Out) <+ Scale * I(In1) * I(In2) / pow(ZeroLimit,2); end else begin V(Out) <+ Scale * I(In1) / I(In2); end end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCVS_PWL (p, n, ps, ns) // // DESCRIPTION: // A voltage-controlled voltage source with non-linear // relationship between control voltage and output voltage, // described using a piecewise-linear table. // // Each voltage value in the array of X values is paired with // a Y array voltage value. The Length parameter must be set // to the number of elements in these arrays. // // The input control voltage determines a position in the X // array, and the corersponding Y array value is used for the // output voltage. Linear interpolation is used for control // voltage values that do not fall exactly on a particular X // array value. Points outside the X array range are // extrapolated using the slope of the nearest two points of // the PWL data. // // The sense terminals ps and ns draw no current. // // TERMINALS: // // p positive voltage source terminal // n negative voltage source terminal // ps positive sense terminal for control voltage // ns negative sense terminal for control voltage // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // Length Number of elements in the X and Y arrays // DEFAULT Length = '4' // // X[1:Length] Array of X axis values (input control voltage) // DEFAULT X[1:Length] = '{-5.00 0.00 5.00 10.00}' // // Y[1:Length] Array of Y axis values (output voltage) // DEFAULT Y[1:Length] = '{-0.10 0.00 0.10 0.10}' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_VCVS_PWL (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Scale = 1.0; //--------------------------------------------------------------------------- // Vectors of the PWL table //--------------------------------------------------------------------------- parameter integer Length = 4; parameter real X[1:Length] = {-5.00, 0.00, 5.00, 10.00}, Y[1:Length] = {-0.10, 0.00, 0.10, 0.10}; //--------------------------------------------------------------------------- analog begin V(Out) <+ Scale * $table_model(V(In), X, Y, "LL"); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCVS_PWL (p, n, ps, ns) // // DESCRIPTION: // A current-controlled voltage source with non-linear // relationship between control current and output voltage, // described using a piecewise-linear table. // // Each current value in the array of X values is paired with // a Y array voltage value. The Length parameter must be set // to the number of elements in these arrays. // // The input control current determines a position in the X // array, and the corersponding Y array value is used for the // output voltage. Linear interpolation is used for control // current values that do not fall exactly on a particular X // array value. Points outside the X array range are // extrapolated using the slope of the nearest two points of // the PWL data. // // The sense terminals ps and ns behave as a short circuit. // // TERMINALS: // // p positive voltage source terminal // n negative voltage source terminal // ps positive sense terminal for control current // ns negative sense terminal for control current // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // Length Number of elements in the X and Y arrays // DEFAULT Length = '4' // // X[1:Length] Array of X axis values (input control current) // DEFAULT X[1:Length] = '{-5.00 0.00 5.00 10.00}' // // Y[1:Length] Array of Y axis values (output voltage) // DEFAULT Y[1:Length] = '{-0.10 0.00 0.10 0.10}' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_CCVS_PWL (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Scale = 1.0; //--------------------------------------------------------------------------- // Vectors of the PWL table //--------------------------------------------------------------------------- parameter integer Length = 4; parameter real X[1:Length] = {-5.00, 0.00, 5.00, 10.00}, Y[1:Length] = {-0.10, 0.00, 0.10, 0.10}; //--------------------------------------------------------------------------- analog begin V(In) <+ 0.0; V(Out) <+ Scale * $table_model(I(In), X, Y, "LL"); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_TCVS_PWL (p, n) // // DESCRIPTION: // A time-controlled voltage source with non-linear // relationship between time and output voltage, described // using a piecewise-linear table. // // Each time value in the array of X values is paired with a // Y array votage value. The Length parameter must be set to // the number of elements in these arrays. // // The arrays describe the output voltage waveform. The first // X value in the array gives the time at wich the waveform // begins in the simulation. Linear interpolation is used for // time values that do not fall exactly on a particular X // array value. Points outside the time range are // extrapolated horizontally, ie., the Y value of nearest // point is used. // // TERMINALS: // // p positive voltage source terminal // n negative voltage source terminal // // PARAMETERS: // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // Length Number of elements in the X and Y arrays // DEFAULT Length = '4' // // X[1:Length] Array of X axis values (time) // DEFAULT X[1:Length] = '{0.50e-9 1.00e-9 2.00e-9 2.50e-9}' // // Y[1:Length] Array of Y axis values (output voltage) // DEFAULT Y[1:Length] = '{0.00 0.10 0.90 1.00}' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_TCVS_PWL (p, n); inout p, n; electrical p, n; branch (p, n) Out; parameter real Scale = 1.0; //--------------------------------------------------------------------------- // Vectors of the PWL table //--------------------------------------------------------------------------- parameter integer Length = 4; parameter real X[1:Length] = {0.50e-9, 1.00e-9, 2.00e-9, 2.50e-9}, Y[1:Length] = {0.00, 0.10, 0.90, 1.00}; //--------------------------------------------------------------------------- analog begin // This line does SE // V(Out) <+ Scale * $table_model($abstime, X, Y, "LL"); // This line does HE V(Out) <+ Scale * $table_model(min(max($abstime, X[1]), X[Length]), X, Y, "LL"); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VECVS_PWL (p, n, ps, ns) // // DESCRIPTION: // A voltage event-controlled voltage source producing // time-based piecewise-linear voltage waveforms in response // to trigger events. The control voltage triggers separate // rising and falling PWL waveforms to effect transitions // between high and low states. // // Each time value in the XR array is paired with a voltage // value in the YR array to describe a rising edge waveform. // Likewise for XF and YF arrays, which describe a falling // edge waveform. The Length_R and Length_F parameters must // be set to the number of elements in the *R and *F arrays, // respectively. // // When the control voltage rises above Vth_R the rising edge // waveform is output. Voltage then remains at the level of // the last point in the rising waveform table until a // falling edge transition is triggerd. When the control // voltage falls below Vth_F a falling edge waveform is // triggered, holding at the last voltage until the next // rising edge. // // In DC analysis the first point of the falling edge // waveform is output if the control voltage is above Vth_R, // and the first point of the rising edge waveform is output // if the control voltage is below Vth_F. If Vt_R is less // than or equal to Vth_F and the control voltage lies on or // between those values the high state voltage is output. If // Vth_R is greater than Vth_F and the control voltage lies // on or between those values, the average of the high and // low state voltages is output. // // TERMINALS: // // p positive voltage source terminal // n negative voltage source terminal // ps positive sense terminal for control voltage // ns negative sense terminal for control voltage // // PARAMETERS: // // Vth_R Threshold voltage to trigger a rising edge event // DEFAULT Vth_R = '0.0' // // Vth_F Threshold voltage to trigger a falling edge event // DEFAULT Vth_F = '0.0' // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // Length_R Number of elements in the XR and YR arrays // DEFAULT Length_R = '4' // // Length_F Number of elements in the XF and YF arrays // DEFAULT Length_F = '4' // // XR[1:Length_R] Array of rising edge X values (time) // DEFAULT XR[1:Length_R] = '{0.50e-9 1.00e-9 2.00e-9 2.50e-9}' // // YR[1:Length_R] Array of rising edge Y values (voltage) // DEFAULT YR[1:Length_R] = '{0.00 0.10 0.90 1.00}' // // XF[1:Length_F] Array of falling edge X values (time) // DEFAULT XF[1:Length_F] = '{0.50e-9 1.00e-9 2.00e-9 2.50e-9}' // // YF[1:Length_F] Array of falling edge Y values (voltage) // DEFAULT YF[1:Length_F] = '{1.00 0.90 0.10 0.00}' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_VECVS_PWL (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Vth_R = 0.0; parameter real Vth_F = 0.0; parameter real Scale = 1.0; //--------------------------------------------------------------------------- // Vectors of the PWL table //--------------------------------------------------------------------------- parameter integer Length_R = 4, Length_F = 4; parameter real XR[1:Length_R] = {0.50e-9, 1.00e-9, 2.00e-9, 2.50e-9}, YR[1:Length_R] = {0.00, 0.10, 0.90, 1.00}, XF[1:Length_F] = {0.50e-9, 1.00e-9, 2.00e-9, 2.50e-9}, YF[1:Length_F] = {1.00, 0.90, 0.10, 0.00}; //parameter integer // Length_R = 1, // These should really be the default values // Length_F = 1; // //parameter real // XR[1:Length_R] = {0.0}, // YR[1:Length_R] = {0.0}, // XF[1:Length_F] = {0.0}, // YF[1:Length_F] = {0.0}; //--------------------------------------------------------------------------- real T_event; integer EventState; analog begin if (analysis("static")) begin if (V(In) > Vth_R) // high state EventState = 1; else if (V(In) < Vth_F) // low state EventState = -1; else // unkown state EventState = 0; end @(cross(V(In)-Vth_R, 1, 100p, 100m)) begin // rising edge if (EventState == 0) begin EventState = 2; // unknown to high state change T_event = $abstime; end else if (EventState < 0) begin EventState = 3; // low to high state transition T_event = $abstime; end $discontinuity(1); end @(cross(V(In)-Vth_F, -1, 100p, 100m)) begin // falling edge if (EventState == 0) begin EventState = -2; // unknown to low state change T_event = $abstime; end else if (EventState > 0) begin EventState = -3; // high to low state transition T_event = $abstime; end $discontinuity(1); end case (EventState) -3 : V(Out) <+ Scale * $table_model(min(max($abstime-T_event, XF[1]), XF[Length_F]), XF, YF, "LL"); -2 : V(Out) <+ Scale * ($table_model(XR[1], XR, YR, "LL") + $table_model(min(max($abstime-T_event, XF[1]), XF[Length_F]), XF, YF, "LL")) / 2.0; -1 : V(Out) <+ Scale * $table_model(XR[1], XR, YR, "LL"); 1 : V(Out) <+ Scale * $table_model(XF[1], XF, YF, "LL"); 2 : V(Out) <+ Scale * ($table_model(XF[1], XF, YF, "LL") + $table_model(min(max($abstime-T_event, XR[1]), XR[Length_R]), XR, YR, "LL")) / 2.0; 3 : V(Out) <+ Scale * $table_model(min(max($abstime-T_event, XR[1]), XR[Length_R]), XR, YR, "LL"); default : begin // executes during DC operating point analysis if (V(In) > Vth_R) V(Out) <+ Scale * $table_model(XF[1], XF, YF, "LL"); else if (V(In) < Vth_F) V(Out) <+ Scale * $table_model(XR[1], XR, YR, "LL"); else V(Out) <+ Scale * ($table_model(XR[1], XR, YR, "LL") + $table_model(XF[1], XF, YF, "LL")) / 2.0; end endcase end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CECVS_PWL (p, n, ps, ns) // // DESCRIPTION: // A current event-controlled voltage source producing // time-based piecewise-linear voltage waveforms in response // to trigger events. The control current triggers separate // rising and falling PWL waveforms to effect transitions // between high and low states. // // Each time value in the XR array is paired with a voltage // value in the YR array to describe a rising edge waveform. // Likewise for XF and YF arrays, which describe a falling // edge waveform. The Length_R and Length_F parameters must // be set to the number of elements in the *R and *F arrays, // respectively. // // When the control current rises above Ith_R the rising edge // waveform is output. Voltage then remains at the level of // the last point in the rising waveform table until a // falling edge transition is triggerd. When the control // current falls below Ith_F a falling edge waveform is // triggered, holding at the last voltage until the next // rising edge. // // In DC analysis the first point of the falling edge // waveform is output if the control current is above Ith_R, // and the first point of the rising edge waveform is output // if the control current is below Ith_F. If It_R is less // than or equal to Ith_F and the control current lies on or // between those values the high state voltage is output. If // Ith_R is greater than Ith_F and the control current lies // on or between those values, the average of the high and // low state voltages is output. // // TERMINALS: // // p positive voltage source terminal // n negative voltage source terminal // ps positive sense terminal for control current // ns negative sense terminal for control current // // PARAMETERS: // // Ith_R Threshold current to trigger a rising edge event // DEFAULT Ith_R = '0.0' // // Ith_F Threshold current to trigger a falling edge event // DEFAULT Ith_F = '0.0' // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // Length_R Number of elements in the XR and YR arrays // DEFAULT Length_R = '4' // // Length_F Number of elements in the XF and YF arrays // DEFAULT Length_F = '4' // // XR[1:Length_R] Array of rising edge X values (time) // DEFAULT XR[1:Length_R] = '{0.50e-9 1.00e-9 2.00e-9 2.50e-9}' // // YR[1:Length_R] Array of rising edge Y values (current) // DEFAULT YR[1:Length_R] = '{0.00 0.10 0.90 1.00}' // // XF[1:Length_F] Array of falling edge X values (time) // DEFAULT XF[1:Length_F] = '{0.50e-9 1.00e-9 2.00e-9 2.50e-9}' // // YF[1:Length_F] Array of falling edge Y values (current) // DEFAULT YF[1:Length_F] = '{1.00 0.90 0.10 0.00}' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_CECVS_PWL (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Ith_R = 0.0; parameter real Ith_F = 0.0; parameter real Scale = 1.0; //--------------------------------------------------------------------------- // Vectors of the PWL table //--------------------------------------------------------------------------- parameter integer Length_R = 4, Length_F = 4; parameter real XR[1:Length_R] = {0.50e-9, 1.00e-9, 2.00e-9, 2.50e-9}, YR[1:Length_R] = {0.00, 0.10, 0.90, 1.00}, XF[1:Length_F] = {0.50e-9, 1.00e-9, 2.00e-9, 2.50e-9}, YF[1:Length_F] = {1.00, 0.90, 0.10, 0.00}; //parameter integer // Length_R = 1, // These should really be the default values // Length_F = 1; // //parameter real // XR[1:Length_R] = {0.0}, // YR[1:Length_R] = {0.0}, // XF[1:Length_F] = {0.0}, // YF[1:Length_F] = {0.0}; //--------------------------------------------------------------------------- real T_event; integer EventState; analog begin if (analysis("static")) begin if (I(In) > Ith_R) // high state EventState = 1; else if (I(In) < Ith_F) // low state EventState = -1; else // unkown state EventState = 0; end @(cross(I(In)-Ith_R, 1, 100p, 100m)) begin // rising edge if (EventState == 0) begin EventState = 2; // unknown to high state change T_event = $abstime; end else if (EventState < 0) begin EventState = 3; // low to high state transition T_event = $abstime; end $discontinuity(1); end @(cross(I(In)-Ith_F, -1, 100p, 100m)) begin // falling edge if (EventState == 0) begin EventState = -2; // unknown to low state change T_event = $abstime; end else if (EventState > 0) begin EventState = -3; // high to low state transition T_event = $abstime; end $discontinuity(1); end V(In) <+ 0.0; case (EventState) -3 : V(Out) <+ Scale * $table_model(min(max($abstime-T_event, XF[1]), XF[Length_F]), XF, YF, "LL"); -2 : V(Out) <+ Scale * ($table_model(XR[1], XR, YR, "LL") + $table_model(min(max($abstime-T_event, XF[1]), XF[Length_F]), XF, YF, "LL")) / 2.0; -1 : V(Out) <+ Scale * $table_model(XR[1], XR, YR, "LL"); 1 : V(Out) <+ Scale * $table_model(XF[1], XF, YF, "LL"); 2 : V(Out) <+ Scale * ($table_model(XF[1], XF, YF, "LL") + $table_model(min(max($abstime-T_event, XR[1]), XR[Length_R]), XR, YR, "LL")) / 2.0; 3 : V(Out) <+ Scale * $table_model(min(max($abstime-T_event, XR[1]), XR[Length_R]), XR, YR, "LL"); default : begin // executes during DC operating point analysis if (I(In) > Ith_R) V(Out) <+ Scale * $table_model(XF[1], XF, YF, "LL"); else if (I(In) < Ith_F) V(Out) <+ Scale * $table_model(XR[1], XR, YR, "LL"); else V(Out) <+ Scale * ($table_model(XR[1], XR, YR, "LL") + $table_model(XF[1], XF, YF, "LL")) / 2.0; end endcase end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_I (p, n) // // DESCRIPTION: // A DC current source. Output current is calculated: // // I(p,n) = Idc * Scale // // TERMINALS: // // p positive current source terminal // n negative current source terminal // // PARAMETERS: // // Idc DC current value // DEFAULT Idc = '1.0' // // Scale Scaling factor for calculating output voltage // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 pada vss IBIS_I Idc=0.025 // // VAMS: IBIS_I #(.Idc(0.025)) I1 (pada, vss); // // ========================================================= module IBIS_I (p, n); inout p, n; electrical p, n; branch (p, n) Out; parameter real Idc = 1.0; parameter real Scale = 1.0; analog begin I(Out) <+ Scale * Idc; end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCCS (p, n, ps, ns) // // DESCRIPTION: // A voltage-controlled current source. The output current // value is calculated: // // I(p,n) = I(ps,ns) * Scale // // The sense terminals ps and ns draw no current. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps positive sense terminal for control voltage // ns negative sense terminal for control voltage // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 pupwr pupwra vcp vss IBIS_VCCS Scale=0.05 // // VAMS: IBIS_VCCS #(.Scale(0.05)) VCCS1 (pupwr, pupwr, vcp, vss); // // ========================================================= module IBIS_VCCS (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Scale = 1.0; analog begin I(Out) <+ Scale * V(In); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCCS (p, n, ps, ns) // // DESCRIPTION: // A current-controlled current source. The output current // value is calculated: // // I(p,n) = I(ps,ns) * Scale // // The sense terminals ps and ns behave as a short circuit. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps positive sense terminal for control current // ns negative sense terminal for control current // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 buf2in vss pad padi IBIS_CCVS Scale=0.1 // // VAMS: IBIS_CCVS #(.Scale(0.1)) CCVS1 (buf2in, vss, pad, padi); // // ========================================================= module IBIS_CCCS (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(In) <+ 0.0; I(Out) <+ Scale * I(In); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCCS_DELAY (p, n, ps, ns) // // DESCRIPTION: // A voltage-controlled current source with delay. All // changes at the sense terminals affect the output later in // time, using the specified delay. The output current value // is calculated: // // I(p,n) = V(ps,ns) * Scale, delayed by TD // // The sense terminals ps and ns draw no current. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps positive sense terminal for control voltage // ns negative sense terminal for control voltage // // PARAMETERS: // // TD Time delay from control voltage change to output change // DEFAULT TD = '0.0' // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 buf2in vss pad padi IBIS_VCCS_DELAY TD=200p // // VAMS: IBIS_VCCS_DELAY #(.TD(200e-12)) \ // VCCS1 (buf2in, vss, pad, padi); // // ========================================================= module IBIS_VCCS_DELAY (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real TD = 0.0; parameter real Scale = 1.0; analog begin I(Out) <+ Scale * absdelay(V(In), TD); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCCS_DELAY (p, n, ps, ns) // // DESCRIPTION: // A current-controlled current source with delay. All // changes at the sense terminals affect the output later, // using the specified delay in seconds. The current value is // calculated: // // I(p,n) = I(ps,ns) * Scale // // The sense terminals ps and ns behave as a short circuit. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps positive sense terminal for control current // ns negative sense terminal for control current // // PARAMETERS: // // TD Time delay from control current change to output change // DEFAULT TD = '0.0' // // Scale Scaling factor for calculating current // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 buf2in vss pad padi IBIS_CCVS_DELAY Scale=100 TD=200p // // VAMS: IBIS_CCVS_DELAY #(.Scale(100),.TD(200e-12)) \ // CCVS1 (buf2in, vss, pad, padi); // // ========================================================= module IBIS_CCCS_DELAY (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real TD = 0.0; parameter real Scale = 1.0; analog begin V(In) <+ 0.0; I(Out) <+ Scale * absdelay(I(In), TD); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCCS_MIN (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A voltage-controlled current source for taking the lesser // of two control input voltages. The output current value is // calculated: // // I(p,n) = min( V(ps1,ns1) V(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 draw no current. The sense // terminals ps2 and ns2 draw no current. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps1 positive sense terminal for control voltage 1 // ns1 negative sense terminal for control voltage 1 // ps2 positive sense terminal for control voltage 2 // ns2 negative sense terminal for control voltage 2 // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 bufctl vss ctlmain vss boost vss IBIS_VCCS_MIN // // VAMS: IBIS_VCCS_MIN MIN1 (bufctl, vss, ctlmain, vss, boost, // vss); // // ========================================================= module IBIS_VCCS_MIN (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; analog begin I(Out) <+ Scale * min(V(In1), V(In2)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCCS_MIN (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A voltage-controlled current source for taking the lesser // of two control input voltages. The output current value is // calculated: // // I(p,n) = min( V(ps1,ns1) V(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 behave as a short circuit. // The sense terminals ps2 and ns2 behave as a short circuit. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps1 positive sense terminal for control current 1 // ns1 negative sense terminal for control current 1 // ps2 positive sense terminal for control current 2 // ns2 negative sense terminal for control current 2 // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 bufctl vss ctlmain ctlmaini boost boosti IBIS_CCVS_MIN // // VAMS: IBIS_CCVS_MIN MIN1 (bufctl, vss, ctlmain, vss, boost, // vss); // // ========================================================= module IBIS_CCCS_MIN (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(In1) <+ 0.0; V(In2) <+ 0.0; I(Out) <+ Scale * min(I(In1), I(In2)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCCS_MAX (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A voltage-controlled current source for taking the greater // of two control input voltages. The output current value is // calculated: // // I(p,n) = min( V(ps1,ns1) V(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 draw no current. The sense // terminals ps2 and ns2 draw no current. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps1 positive sense terminal for control voltage 1 // ns1 negative sense terminal for control voltage 1 // ps2 positive sense terminal for control voltage 2 // ns2 negative sense terminal for control voltage 2 // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // SPICE: X1 bufctl vss ctlmain vss boost vss IBIS_VCCS_MAX // // VAMS: IBIS_VCCS_MAX MAX1 (bufctl, vss, ctlmain, vss, boost, // vss); // // ========================================================= module IBIS_VCCS_MAX (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; analog begin I(Out) <+ Scale * max(V(In1), V(In2)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCCS_MAX (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A current-controlled current source for taking the greater // of two input currents. The output current value is // calculated: // // V(p,n) = max( I(ps1,ns1) I(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 draw no current. The sense // terminals ps2 and ns2 draw no current. // // TERMINALS: // // p positive current source terminal // n negative current source terminal // ps1 positive sense terminal for control current 1 // ns1 negative sense terminal for control current 1 // ps2 positive sense terminal for control current 2 // ns2 negative sense terminal for control current 2 // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_CCCS_MAX (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(In1) <+ 0.0; V(In2) <+ 0.0; I(Out) <+ Scale * max(I(In1), I(In2)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCCS_ABS (p, n, ps, ns) // // DESCRIPTION: // A voltage-controlled current source for taking the // absolute value of the control voltage. The output current // value is always positive, and is calculated: // // V(p,n) = abs( V(ps,ns) ) * Scale // // The sense terminals ps and ns draw no current. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps positive sense terminal for control voltage // ns negative sense terminal for control voltage // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_VCCS_ABS (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Scale = 1.0; analog begin I(Out) <+ Scale * abs(V(In)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCCS_ABS (p, n, ps, ns) // // DESCRIPTION: // A current-controlled current source for taking the // absolute value of the control current. The output current // value is always positive, and is calculated: // // V(p,n) = abs( I(ps,ns) ) * Scale // // The sense terminals ps and ns behave as a short circuit. // // TERMINALS: // // p positive resistor terminal // n negative resistor terminal // ps positive sense terminal for control current // ns negative sense terminal for control current // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_CCCS_ABS (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(In) <+ 0.0; I(Out) <+ Scale * abs(I(In)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCCS_SUM (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A voltage-controlled current source for taking the sum of // two control input voltages. The output current value is // calculated: // // V(p,n) = ( V(ps1,ns1) + V(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 draw no current. The sense // terminals ps2 and ns2 draw no current. // // TERMINALS: // // p positive current source terminal // n negative current source terminal // ps1 positive sense terminal for control voltage 1 // ns1 negative sense terminal for control voltage 1 // ps2 positive sense terminal for control voltage 2 // ns2 negative sense terminal for control voltage 2 // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_VCCS_SUM (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; analog begin I(Out) <+ Scale * (V(In1) + V(In2)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCCS_SUM (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A current-controlled current source for taking the sum of // two control input voltages. The output current value is // calculated: // // V(p,n) = ( I(ps1,ns1) + I(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 behave as a short circuit. // The sense terminals ps2 and ns2 behave as a short circuit. // // TERMINALS: // // p positive current source terminal // n negative current source terminal // ps1 positive sense terminal for control current 1 // ns1 negative sense terminal for control current 1 // ps2 positive sense terminal for control current 2 // ns2 negative sense terminal for control current 2 // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_CCCS_SUM (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(In1) <+ 0.0; V(In2) <+ 0.0; I(Out) <+ Scale * (I(In1) + I(In2)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCCS_MULT (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A voltage-controlled current source for taking the product // of two control input voltages. The output current value is // calculated: // // V(p,n) = ( V(ps1,ns1) * V(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 draw no current. The sense // terminals ps2 and ns2 draw no current. // // TERMINALS: // // p positive current source terminal // n negative current source terminal // ps1 positive sense terminal for control voltage 1 // ns1 negative sense terminal for control voltage 1 // ps2 positive sense terminal for control voltage 2 // ns2 negative sense terminal for control voltage 2 // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_VCCS_MULT (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; analog begin I(Out) <+ Scale * V(In1) * V(In2); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCCS_MULT (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A current-controlled current source for taking the product // of two control input currents. The output current value is // calculated: // // V(p,n) = ( I(ps1,ns1) * I(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 behave as a short circuit. // The sense terminals ps2 and ns2 behave as a short circuit. // // TERMINALS: // // p positive current source terminal // n negative current source terminal // ps1 positive sense terminal for control current 1 // ns1 negative sense terminal for control current 1 // ps2 positive sense terminal for control current 2 // ns2 negative sense terminal for control current 2 // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_CCCS_MULT (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; analog begin V(In1) <+ 0.0; V(In2) <+ 0.0; I(Out) <+ Scale * I(In1) * I(In2); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCCS_DIV (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A voltage-controlled current source for taking the ratio // of two control input voltages. The output current value is // calculated: // // V(p,n) = ( V(ps1,ns1) / V(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 draw no current. The sense // terminals ps2 and ns2 draw no current. // // TERMINALS: // // p positive current source terminal // n negative current source terminal // ps1 positive sense terminal for control voltage 1 // ns1 negative sense terminal for control voltage 1 // ps2 positive sense terminal for control voltage 2 // ns2 negative sense terminal for control voltage 2 // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // ZeroLimit // DEFAULT ZeroLimit = '1.0e-3' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_VCCS_DIV (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; parameter real ZeroLimit = 1.0e-3; real AbsVin2; integer NearZero; analog begin AbsVin2 = abs(V(In2)); if (analysis("static")) begin if (AbsVin2 > ZeroLimit) begin NearZero = 0; end else begin NearZero = 1; $strobe("Warning: The divisor in module 'IBIS_VCCS_DIV' is less than or equal to the value defined in its parameter 'ZeroLimit = %e' at time = %e.", ZeroLimit, $abstime); end end @(cross(AbsVin2-ZeroLimit, 0, 100p, 100m)) begin if (AbsVin2 > ZeroLimit) begin NearZero = 0; end else begin NearZero = 1; $strobe("Warning: The divisor in module 'IBIS_VCCS_DIV' is less than or equal to the value defined in its parameter 'ZeroLimit = %e' at time = %e.", ZeroLimit, $abstime); end $discontinuity(1); end if (NearZero) begin I(Out) <+ Scale * V(In1) * V(In2) / pow(ZeroLimit,2); end else begin I(Out) <+ Scale * V(In1) / V(In2); end end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCCS_DIV (p, n, ps1, ns1, ps2, ns2) // // DESCRIPTION: // A current-controlled current source for taking the ratio // of two control input currents. The output current value is // calculated: // // V(p,n) = ( I(ps1,ns1) / I(ps2,ns2) ) * Scale // // The sense terminals ps1 and ns1 behave as a short circuit. // The sense terminals ps2 and ns2 behave as a short circuit. // // TERMINALS: // // p positive current source terminal // n negative current source terminal // ps1 positive sense terminal for control current 1 // ns1 negative sense terminal for control current 1 // ps2 positive sense terminal for control current 2 // ns2 negative sense terminal for control current 2 // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // ZeroLimit // DEFAULT ZeroLimit = '1.0e-3' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_CCCS_DIV (p, n, ps1, ns1, ps2, ns2); input ps1, ns1, ps2, ns2; electrical ps1, ns1, ps2, ns2; inout p, n; electrical p, n; branch (ps1, ns1) In1; branch (ps2, ns2) In2; branch (p, n) Out; parameter real Scale = 1.0; parameter real ZeroLimit = 1.0e-3; real AbsIin2; integer NearZero; analog begin AbsIin2 = abs(I(In2)); V(In1) <+ 0.0; V(In2) <+ 0.0; if (analysis("static")) begin if (AbsIin2 > ZeroLimit) begin NearZero = 0; end else begin NearZero = 1; $strobe("Warning: The divisor in module 'IBIS_CCCS_DIV' is less than or equal to the value defined in its parameter 'ZeroLimit = %e' at time = %e.", ZeroLimit, $abstime); end end @(cross(AbsIin2-ZeroLimit, 0, 100p, 100m)) begin if (AbsIin2 > ZeroLimit) begin NearZero = 0; end else begin NearZero = 1; $strobe("Warning: The divisor in module 'IBIS_CCCS_DIV' is less than or equal to the value defined in its parameter 'ZeroLimit = %e' at time = %e.", ZeroLimit, $abstime); end $discontinuity(1); end if (NearZero) begin I(Out) <+ Scale * I(In1) * I(In2) / pow(ZeroLimit,2); end else begin I(Out) <+ Scale * I(In1) / I(In2); end end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VCCS_PWL (p, n, ps, ns) // // DESCRIPTION: // A voltage-controlled current source with non-linear // relationship between control voltage and output current, // described using a piecewise-linear table. // // Each voltage value in the array of X values is paired with // a Y array current value. The Length parameter must be set // to the number of elements in these arrays. // // The input control voltage determines a position in the X // array, and the corersponding Y array value is used for the // output current. Linear interpolation is used for control // voltage values that do not fall exactly on a particular X // array value. Points outside the X array range are // extrapolated using the slope of the nearest two points of // the PWL data. // // The sense terminals ps and ns draw no current. // // TERMINALS: // // p positive current source terminal // n negative current source terminal // ps positive sense terminal for control voltage // ns negative sense terminal for control voltage // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // Length Number of elements in the X and Y arrays // DEFAULT Length = '4' // // X[1:Length] Array of X axis values (input control voltage) // DEFAULT X[1:Length] = '{-5.00 0.00 5.00 10.00}' // // Y[1:Length] Array of Y axis values (output current) // DEFAULT Y[1:Length] = '{-0.10 0.00 0.10 0.10}' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_VCCS_PWL (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Scale = 1.0; //--------------------------------------------------------------------------- // Vectors of the PWL table //--------------------------------------------------------------------------- parameter integer Length = 4; parameter real X[1:Length] = {-5.00, 0.00, 5.00, 10.00}, Y[1:Length] = {-0.10, 0.00, 0.10, 0.10}; //--------------------------------------------------------------------------- analog begin I(Out) <+ Scale * $table_model(V(In), X, Y, "LL"); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CCCS_PWL (p, n, ps, ns) // // DESCRIPTION: // A current-controlled current source with non-linear // relationship between control current and output current, // described using a piecewise-linear table. // // Each current value in the array of X values is paired with // a Y array current value. The Length parameter must be set // to the number of elements in these arrays. // // The input control current determines a position in the X // array, and the corersponding Y array value is used for the // output current. Linear interpolation is used for control // current values that do not fall exactly on a particular X // array value. Points outside the X array range are // extrapolated using the slope of the nearest two points of // the PWL data. // // The sense terminals ps and ns behave as a short circuit. // // TERMINALS: // // p positive current source terminal // n negative current source terminal // ps positive sense terminal for control current // ns negative sense terminal for control current // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // Length Number of elements in the X and Y arrays // DEFAULT Length = '4' // // X[1:Length] Array of X axis values (input control current) // DEFAULT X[1:Length] = '{-5.00 0.00 5.00 10.00}' // // Y[1:Length] Array of Y axis values (output current) // DEFAULT Y[1:Length] = '{-0.10 0.00 0.10 0.10}' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_CCCS_PWL (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Scale = 1.0; //--------------------------------------------------------------------------- // Vectors of the PWL table //--------------------------------------------------------------------------- parameter integer Length = 4; parameter real X[1:Length] = {-5.00, 0.00, 5.00, 10.00}, Y[1:Length] = {-0.10, 0.00, 0.10, 0.10}; //--------------------------------------------------------------------------- analog begin V(In) <+ 0.0; I(Out) <+ Scale * $table_model(I(In), X, Y, "LL"); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_TCCS_PWL (p, n) // // DESCRIPTION: // A time-controlled current source with non-linear // relationship between time and output current, described // using a piecewise-linear table. // // Each time value in the array of X values is paired with a // Y array votage value. The Length parameter must be set to // the number of elements in these arrays. // // The arrays describe the output current waveform. The first // X value in the array gives the time at wich the waveform // begins in the simulation. Linear interpolation is used for // time values that do not fall exactly on a particular X // array value. Points outside the time range are // extrapolated horizontally, ie., the Y value of nearest // point is used. // // TERMINALS: // // p positive current source terminal // n negative current source terminal // // PARAMETERS: // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // Length Number of elements in the X and Y arrays // DEFAULT Length = '4' // // X[1:Length] Array of X axis values (time) // DEFAULT X[1:Length] = '{0.50e-9 1.00e-9 2.00e-9 2.50e-9}' // // Y[1:Length] Array of Y axis values (output current) // DEFAULT Y[1:Length] = '{0.00 0.10 0.90 1.00}' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_TCCS_PWL (p, n); inout p, n; electrical p, n; branch (p, n) Out; parameter real Scale = 1.0; //--------------------------------------------------------------------------- // Vectors of the PWL table //--------------------------------------------------------------------------- parameter integer Length = 4; parameter real X[1:Length] = {0.50e-9, 1.00e-9, 2.00e-9, 2.50e-9}, Y[1:Length] = {0.00, 0.10, 0.90, 1.00}; //--------------------------------------------------------------------------- analog begin // This line does SE // I(Out) <+ Scale * $table_model($abstime, X, Y, "LL"); // This line does HE I(Out) <+ Scale * $table_model(min(max($abstime, X[1]), X[Length]), X, Y, "LL"); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_VECCS_PWL (p, n, ps, ns) // // DESCRIPTION: // A voltage event-controlled current source producing // time-based piecewise-linear current waveforms in response // to trigger events. The control voltage triggers separate // rising and falling PWL waveforms to effect transitions // between high and low states. // // Each time value in the XR array is paired with a current // value in the YR array to describe a rising edge waveform. // Likewise for XF and YF arrays, which describe a falling // edge waveform. The Length_R and Length_F parameters must // be set to the number of elements in the *R and *F arrays, // respectively. // // When the control voltage rises above Vth_R the rising edge // waveform is output. Voltage then remains at the level of // the last point in the rising waveform table until a // falling edge transition is triggerd. When the control // voltage falls below Vth_F a falling edge waveform is // triggered, holding at the last current until the next // rising edge. // // In DC analysis the first point of the falling edge // waveform is output if the control voltage is above Vth_R, // and the first point of the rising edge waveform is output // if the control voltage is below Vth_F. If Vt_R is less // than or equal to Vth_F and the control voltage lies on or // between those values the high state current is output. If // Vth_R is greater than Vth_F and the control voltage lies // on or between those values, the average of the high and // low state currents is output. // // TERMINALS: // // p positive current source terminal // n negative current source terminal // ps positive sense terminal for control voltage // ns negative sense terminal for control voltage // // PARAMETERS: // // Vth_R Threshold voltage to trigger a rising edge event // DEFAULT Vth_R = '0.0' // // Vth_F Threshold voltage to trigger a falling edge event // DEFAULT Vth_F = '0.0' // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // Length_R Number of elements in the XR and YR arrays // DEFAULT Length_R = '4' // // Length_F Number of elements in the XF and YF arrays // DEFAULT Length_F = '4' // // XR[1:Length_R] Array of rising edge X values (time) // DEFAULT XR[1:Length_R] = '{0.50e-9 1.00e-9 2.00e-9 2.50e-9}' // // YR[1:Length_R] Array of rising edge Y values (current) // DEFAULT YR[1:Length_R] = '{0.00 0.10 0.90 1.00}' // // XF[1:Length_F] Array of falling edge X values (time) // DEFAULT XF[1:Length_F] = '{0.50e-9 1.00e-9 2.00e-9 2.50e-9}' // // YF[1:Length_F] Array of falling edge Y values (current) // DEFAULT YF[1:Length_F] = '{1.00 0.90 0.10 0.00}' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_VECCS_PWL (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Vth_R = 0.0; parameter real Vth_F = 0.0; parameter real Scale = 1.0; //--------------------------------------------------------------------------- // Vectors of the PWL table //--------------------------------------------------------------------------- parameter integer Length_R = 4, Length_F = 4; parameter real XR[1:Length_R] = {0.50e-9, 1.00e-9, 2.00e-9, 2.50e-9}, YR[1:Length_R] = {0.00, 0.10, 0.90, 1.00}, XF[1:Length_F] = {0.50e-9, 1.00e-9, 2.00e-9, 2.50e-9}, YF[1:Length_F] = {1.00, 0.90, 0.10, 0.00}; //parameter integer // Length_R = 1, // These should really be the default values // Length_F = 1; // //parameter real // XR[1:Length_R] = {0.0}, // YR[1:Length_R] = {0.0}, // XF[1:Length_F] = {0.0}, // YF[1:Length_F] = {0.0}; //--------------------------------------------------------------------------- real T_event; integer EventState; analog begin if (analysis("static")) begin if (V(In) > Vth_R) // high state EventState = 1; else if (V(In) < Vth_F) // low state EventState = -1; else // unkown state EventState = 0; end @(cross(V(In)-Vth_R, 1, 100p, 100m)) begin // rising edge if (EventState == 0) begin EventState = 2; // unknown to high state change T_event = $abstime; end else if (EventState < 0) begin EventState = 3; // low to high state transition T_event = $abstime; end $discontinuity(1); end @(cross(V(In)-Vth_F, -1, 100p, 100m)) begin // falling edge if (EventState == 0) begin EventState = -2; // unknown to low state change T_event = $abstime; end else if (EventState > 0) begin EventState = -3; // high to low state transition T_event = $abstime; end $discontinuity(1); end case (EventState) -3 : I(Out) <+ Scale * $table_model(min(max($abstime-T_event, XF[1]), XF[Length_F]), XF, YF, "LL"); -2 : I(Out) <+ Scale * ($table_model(XR[1], XR, YR, "LL") + $table_model(min(max($abstime-T_event, XF[1]), XF[Length_F]), XF, YF, "LL")) / 2.0; -1 : I(Out) <+ Scale * $table_model(XR[1], XR, YR, "LL"); 1 : I(Out) <+ Scale * $table_model(XF[1], XF, YF, "LL"); 2 : I(Out) <+ Scale * ($table_model(XF[1], XF, YF, "LL") + $table_model(min(max($abstime-T_event, XR[1]), XR[Length_R]), XR, YR, "LL")) / 2.0; 3 : I(Out) <+ Scale * $table_model(min(max($abstime-T_event, XR[1]), XR[Length_R]), XR, YR, "LL"); default : begin // executes during DC operating point analysis if (V(In) > Vth_R) I(Out) <+ Scale * $table_model(XF[1], XF, YF, "LL"); else if (V(In) < Vth_F) I(Out) <+ Scale * $table_model(XR[1], XR, YR, "LL"); else I(Out) <+ Scale * ($table_model(XR[1], XR, YR, "LL") + $table_model(XF[1], XF, YF, "LL")) / 2.0; end endcase end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_CECCS_PWL (p, n, ps, ns) // // DESCRIPTION: // A current event-controlled current source producing // time-based piecewise-linear current waveforms in response // to trigger events. The control current triggers separate // rising and falling PWL waveforms to effect transitions // between high and low states. // // Each time value in the XR array is paired with a current // value in the YR array to describe a rising edge waveform. // Likewise for XF and YF arrays, which describe a falling // edge waveform. The Length_R and Length_F parameters must // be set to the number of elements in the *R and *F arrays, // respectively. // // When the control current rises above Ith_R the rising edge // waveform is output. Voltage then remains at the level of // the last point in the rising waveform table until a // falling edge transition is triggerd. When the control // current falls below Ith_F a falling edge waveform is // triggered, holding at the last current until the next // rising edge. // // In DC analysis the first point of the falling edge // waveform is output if the control current is above Ith_R, // and the first point of the rising edge waveform is output // if the control current is below Ith_F. If It_R is less // than or equal to Ith_F and the control current lies on or // between those values the high state current is output. If // Ith_R is greater than Ith_F and the control current lies // on or between those values, the average of the high and // low state currents is output. // // TERMINALS: // // p positive current source terminal // n negative current source terminal // ps positive sense terminal for control current // ns negative sense terminal for control current // // PARAMETERS: // // Ith_R Threshold current to trigger a rising edge event // DEFAULT Ith_R = '0.0' // // Ith_F Threshold current to trigger a falling edge event // DEFAULT Ith_F = '0.0' // // Scale Scaling factor for calculating output current // DEFAULT Scale = '1.0' // // Length_R Number of elements in the XR and YR arrays // DEFAULT Length_R = '4' // // Length_F Number of elements in the XF and YF arrays // DEFAULT Length_F = '4' // // XR[1:Length_R] Array of rising edge X values (time) // DEFAULT XR[1:Length_R] = '{0.50e-9 1.00e-9 2.00e-9 2.50e-9}' // // YR[1:Length_R] Array of rising edge Y values (current) // DEFAULT YR[1:Length_R] = '{0.00 0.10 0.90 1.00}' // // XF[1:Length_F] Array of falling edge X values (time) // DEFAULT XF[1:Length_F] = '{0.50e-9 1.00e-9 2.00e-9 2.50e-9}' // // YF[1:Length_F] Array of falling edge Y values (current) // DEFAULT YF[1:Length_F] = '{1.00 0.90 0.10 0.00}' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_CECCS_PWL (p, n, ps, ns); input ps, ns; electrical ps, ns; inout p, n; electrical p, n; branch (ps, ns) In; branch (p, n) Out; parameter real Ith_R = 0.0; parameter real Ith_F = 0.0; parameter real Scale = 1.0; //--------------------------------------------------------------------------- // Vectors of the PWL table //--------------------------------------------------------------------------- parameter integer Length_R = 4, Length_F = 4; parameter real XR[1:Length_R] = {0.50e-9, 1.00e-9, 2.00e-9, 2.50e-9}, YR[1:Length_R] = {0.00, 0.10, 0.90, 1.00}, XF[1:Length_F] = {0.50e-9, 1.00e-9, 2.00e-9, 2.50e-9}, YF[1:Length_F] = {1.00, 0.90, 0.10, 0.00}; //parameter integer // Length_R = 1, // These should really be the default values // Length_F = 1; // //parameter real // XR[1:Length_R] = {0.0}, // YR[1:Length_R] = {0.0}, // XF[1:Length_F] = {0.0}, // YF[1:Length_F] = {0.0}; //--------------------------------------------------------------------------- real T_event; integer EventState; analog begin if (analysis("static")) begin if (I(In) > Ith_R) // high state EventState = 1; else if (I(In) < Ith_F) // low state EventState = -1; else // unkown state EventState = 0; end @(cross(I(In)-Ith_R, 1, 100p, 100m)) begin // rising edge if (EventState == 0) begin EventState = 2; // unknown to high state change T_event = $abstime; end else if (EventState < 0) begin EventState = 3; // low to high state transition T_event = $abstime; end $discontinuity(1); end @(cross(I(In)-Ith_F, -1, 100p, 100m)) begin // falling edge if (EventState == 0) begin EventState = -2; // unknown to low state change T_event = $abstime; end else if (EventState > 0) begin EventState = -3; // high to low state transition T_event = $abstime; end $discontinuity(1); end V(In) <+ 0.0; case (EventState) -3 : I(Out) <+ Scale * $table_model(min(max($abstime-T_event, XF[1]), XF[Length_F]), XF, YF, "LL"); -2 : I(Out) <+ Scale * ($table_model(XR[1], XR, YR, "LL") + $table_model(min(max($abstime-T_event, XF[1]), XF[Length_F]), XF, YF, "LL")) / 2.0; -1 : I(Out) <+ Scale * $table_model(XR[1], XR, YR, "LL"); 1 : I(Out) <+ Scale * $table_model(XF[1], XF, YF, "LL"); 2 : I(Out) <+ Scale * ($table_model(XF[1], XF, YF, "LL") + $table_model(min(max($abstime-T_event, XR[1]), XR[Length_R]), XR, YR, "LL")) / 2.0; 3 : I(Out) <+ Scale * $table_model(min(max($abstime-T_event, XR[1]), XR[Length_R]), XR, YR, "LL"); default : begin // executes during DC operating point analysis if (I(In) > Ith_R) I(Out) <+ Scale * $table_model(XF[1], XF, YF, "LL"); else if (I(In) < Ith_F) I(Out) <+ Scale * $table_model(XR[1], XR, YR, "LL"); else I(Out) <+ Scale * ($table_model(XR[1], XR, YR, "LL") + $table_model(XF[1], XF, YF, "LL")) / 2.0; end endcase end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_T (n1, ref1, n2, ref2) // // DESCRIPTION: // A lossless transmission line. // // TERMINALS: // // n1 Signal terminal for end 1 // ref1 Reference terminal for end 1 // n2 Signal terminal for end 2 // ref2 Reference terminal for end 2 // // PARAMETERS: // // Z0 Transmission line impedance in ohms // DEFAULT Z0 = '50.0' // // TD Time delay in seconds // DEFAULT TD = '1.0e-9' // // // INSTANCE CALL EXAMPLES: // // ========================================================= module IBIS_T (n1, ref1, n2, ref2); inout n1, ref1, n2, ref2; electrical n1, ref1, n2, ref2; branch (n1, ref1) End1; branch (n2, ref2) End2; parameter real Z0 = 50.0; parameter real TD = 1.0e-9; real i12; // Current wave traveling from End1 to End2 real i21; // Current wave traveling from End2 to End1 analog begin i12 = I(End1) + absdelay(i21, TD); i21 = I(End2) + absdelay(i12, TD); V(End1) <+ Z0 * (2*i12 - I(End1)); V(End2) <+ Z0 * (2*i21 - I(End2)); end endmodule //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_INPUT (PC_ref, GC_ref, Pad, Rcv_D) // // DESCRIPTION: // An IBIS Input buffer. The effects modeled are: // - Clamp I/V curves // - Die capacitance seen at the Pad terminal, with distribution // to separate power/ground terminal per IBIS 4.1. // - Threshold based received logic detection. // // The voltage at the Pad terminal is monitored and // a corresponding output voltage is produced at the Rcv_D // terminal. The Vinl and Vinh parameters are used as voltage // thresholds for controlling the core-level output data // at the Rcv_D terminal. When the Pad voltage is above // Vinh the Rcv_D voltage is 1.0. When the Pad voltage is // below Vinl the Rcv_D voltage is 0.0. When the Pad voltage // is in the middle region the Rcv_D voltage is 0.5. // // Clamp currents can be experimentally scaled using the // kI_pc and kI_gc parameters. These are not IBIS parameters. // // This IBIS implementation is unable to read IBIS files // directly. Therefore it will be necessary to extract // appropriate parameters from IBIS models to pass to // this model as HDL parameters. IBIS tables are passed // as arrays, with the array lengths given as separate // parameters. The default parameter values in this model // provide a functional example that does not necessarily // model any known "real" buffer. Comments below describe // where to find values in the IBIS file. // // Note that while IBIS contains typical, minimum, and // maximum values for most parameters, this buffer model // implementation accepts only a single value for each // parameter. It will be necessary to maintain seperate // parameter sets for each "corner". // // TERMINALS: // // PC_ref Power clamp reference voltage supply // GC_ref Ground clamp reference voltage supply // Pad Pad terminal providing input to and output from buffer // Rcv_D Received data from buffer to core logic // // PARAMETERS: // // C_comp Component die capacitance in farads // Extract IBIS C_comp to get this value. // DEFAULT C_comp = '5.0p' // // kC_comp_pc Fraction of C_comp referenced to PC_ref terminal // Extract IBIS C_comp_power_clamp to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pc = '0.25' // // kC_comp_gc Fraction of C_comp referenced to GC_ref terminal // Extract IBIS C_comp_ground_clamp to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_gc = '0.25' // // Vinh Minimum threshold voltage for a logic high to be received // Extract IBIS Vinh to get this value. // DEFAULT Vinh = '2.0' // // Vinl Maximum threshold voltage for a logic low to be received // Extract IBIS Vinl to get this value. // DEFAULT Vinl = '0.8' // // Vpc_ref Power clamp reference supply voltage // Extract IBIS [POWER Clamp Reference] to get this value. // Use [Voltage Range] if no [POWER Clamp Reference] // DEFAULT Vpc_ref = '5.0' // // Vgc_ref Ground clamp reference supply voltage // Extract IBIS [GND Clamp Reference] to get this value. // Use 0 if no [GND Clamp Reference] // DEFAULT Vgc_ref = '0.0' // // IVpc_length Number of elements in the Ipc_data and Vpc_data arrays // Count the number of IBIS [Power clamp] entries to get // this value. // DEFAULT IVpc_length = '4' // // IVgc_length Number of elements in the Igc_data and Vgc_data arrays // Count the number of IBIS [GND clamp] entries to get // this value. // DEFAULT IVgc_length = '4' // // Ipc_data[1:IVpc_length] Array of current values for power clamp I/V // Extract the IBIS [Power clamp] current column to get this. // DEFAULT Ipc_data[1:IVpc_length] = '{ 0.08 0.00 0.00 0.00}' // // Vpc_data[1:IVpc_length] Array of voltage values for power clamp I/V // Extract the IBIS [Power clamp] voltage column to get this. // DEFAULT Vpc_data[1:IVpc_length] = '{-5.00 -1.00 5.00 10.00}' // // Igc_data[1:IVgc_length] Array of current values for ground clamp I/V // Extract the IBIS [GND clamp] current column to get this. // DEFAULT Igc_data[1:IVgc_length] = '{-0.08 0.00 0.00 0.00}' // // Vgc_data[1:IVgc_length] Array of voltage values for ground clamp I/V // Extract the IBIS [GND clamp] voltage column to get this. // DEFAULT Vgc_data[1:IVgc_length] = '{-5.00 -1.00 5.00 10.00}' // // kI_pc Scaling factor for power clamp current values. // Not an IBIS parameter; set to desired simulation resolution. // DEFAULT kI_pc = '1.0' // // kI_gc Scaling factor for ground clamp current values. // Not an IBIS parameter; set to desired simulation resolution. // DEFAULT kI_gc = '1.0' // // // INSTANCE CALL EXAMPLES: // // VAMS: // IBIS_INPUT #( // .C_comp(1.2e-12), .Vinh(2.0), .Vinl(0.8), // .Vpc_ref(5.0, .Vgc_ref(0.0), // .IVpc_length(4), .I_pc({ 0.08, 0.00, 0.00, 0.00}), // .V_pc({-5.00, -1.00, 5.00, 10.00}), // .IVgc_length(4), .I_gc({-0.10, 0.00, 0.10, 0.20}), // .V_gc({-5.00, 0.00, 5.00, 10.00}), // B1 (B1_pc, B1_gc, B1_pad, B1_a); // // ========================================================= module IBIS_INPUT (PC_ref, GC_ref, Pad, Rcv_D); output Rcv_D; electrical Rcv_D; inout Pad, PC_ref, GC_ref; electrical Pad, PC_ref, GC_ref; branch (PC_ref, Pad) pc; // branches driven in model branch (Pad, GC_ref) gc; parameter real //--------------------------------------------------------------------------- // IBIS parameters //--------------------------------------------------------------------------- C_comp = 5.0p, // Default C_comp value kC_comp_pc = 0.50, // C_comp splitting coefficients kC_comp_gc = 0.50, Vinh = 2.0, // Default Vinh value Vinl = 0.8; // Default Vinl value //--------------------------------------------------------------------------- // Vectors of the IV curve tables //--------------------------------------------------------------------------- parameter integer IVpc_length = 4, IVgc_length = 4; parameter real Ipc_data[1:IVpc_length] = { 0.08, 0.00, 0.00, 0.00}, Vpc_data[1:IVpc_length] = {-5.00, -1.00, 5.00, 10.00}, Igc_data[1:IVgc_length] = {-0.08, 0.00, 0.00, 0.00}, Vgc_data[1:IVgc_length] = {-5.00, -1.00, 5.00, 10.00}, //--------------------------------------------------------------------------- // Non-IBIS parameters //--------------------------------------------------------------------------- kI_pc = 1.0, // PC current scaling kI_gc = 1.0; // GC current scaling //=========================================================================== analog begin //========================================================================= // This section contains the analog expressions which calculate // the clamping currents from the IV curves and C_comp capacitors. //------------------------------------------------------------------------- I(pc) <+ -kI_pc * $table_model(V(pc), Vpc_data, Ipc_data, "LL") + kC_comp_pc*C_comp*ddt(V(pc)); I(gc) <+ kI_gc * $table_model(V(gc), Vgc_data, Igc_data, "LL") + kC_comp_gc*C_comp*ddt(V(gc)); //------------------------------------------------------------------------- // A simple receiver logic //------------------------------------------------------------------------- if (V(gc) > Vinh) V(Rcv_D) <+ 1.0; else if (V(gc) < Vinl) V(Rcv_D) <+ 0.0; else V(Rcv_D) <+ 0.5; //------------------------------------------------------------------------- end endmodule // IBIS_INPUT //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_OUTPUT (PU_ref, PD_ref, Pad, In_D, PC_ref, GC_ref) // // DESCRIPTION: // An IBIS Output buffer. The effects modeled are: // - Pullup, pulldown, and clamp I/V curves with IBIS 2.1 // waveform-based pullup/pulldown turn-on/off timing. // - Die capacitance seen at the Pad terminal, with distribution // to separate power/ground terminal per IBIS 4.1. // // The Vth_R and Vth_F parameters control how the In_D // terminal behaves. By default these are set to 0.8V // and 0.2V, respectively. The In_D terminal is // triggered to the high state when voltage rises above // Vth_R and to the low state when voltage falls below Vth_F. // // The Pad terminal is driven by either the // Pullup or Pulldown I/V table, depending on the low/high // state of the In_D terminal. State changes at the In_D // terminal trigger controlled transitions to the other // I/V table, using the waveform and test fixture parameters // to guide the transition. // // Clamp, Pullup, and Pulldown currents can be experimentally // scaled using the kI_pc, kI_gc, kI_pu, and kI_pd parameters. // These are not IBIS parameters. // // This IBIS implementation is unable to read IBIS files // directly. Therefore it will be necessary to extract // appropriate parameters from IBIS models to pass to // this model as HDL parameters. IBIS tables are passed // as arrays, with the array lengths given as separate // parameters. The default parameter values in this model // provide a functional example that does not necessarily // model any known "real" buffer. Comments below describe // where to find values in the IBIS file. // // Note that while IBIS contains typical, minimum, and // maximum values for most parameters, this buffer model // implementation accepts only a single value for each // parameter. It will be necessary to maintain seperate // parameter sets for each "corner". // // TERMINALS: // // PU_ref Pullup reference voltage supply // PD_ref Pulldown reference voltage supply // Pad Pad terminal providing input to and output from buffer // In_D Core data signal controlling buffer output // En_D Core signal controlling buffer enable state // PC_ref Power clamp reference voltage supply // GC_ref Ground clamp reference voltage supply // // PARAMETERS: // // C_comp Component die capacitance in farads // Extract IBIS C_comp to get this value. // DEFAULT C_comp = '5.0p' // // kC_comp_pc Fraction of C_comp referenced to PC_ref terminal // Extract IBIS C_comp_power_clamp to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pc = '0.25' // // kC_comp_pu Fraction of C_comp referenced to PU_ref terminal // Extract IBIS C_comp_pullup to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pu = '0.25' // // kC_comp_pd Fraction of C_comp referenced to PD_ref terminal // Extract IBIS C_comp_pulldown to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pd = '0.25' // // kC_comp_gc Fraction of C_comp referenced to GC_ref terminal // Extract IBIS C_comp_ground_clamp to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_gc = '0.25' // // Vinh Minimum threshold voltage for a logic high to be received // Extract IBIS Vinh to get this value. // DEFAULT Vinh = '2.0' // // Vinl Maximum threshold voltage for a logic low to be received // Extract IBIS Vinl to get this value. // DEFAULT Vinl = '0.8' // // Vpc_ref Power clamp reference supply voltage // Extract IBIS [POWER Clamp Reference] to get this value. // Use [Voltage Range] if no [POWER Clamp Reference] // DEFAULT Vpc_ref = '5.0' // // Vpu_ref Pullup reference supply voltage // Extract IBIS [Pullup Reference] to get this value. // Use [Voltage Range] if no [Pullup Reference] // DEFAULT Vpu_ref = '5.0' // // Vpd_ref Pulldown reference supply voltage // Extract IBIS [Pulldown Reference] to get this value. // Use 0 if no [Pulldown Reference] // DEFAULT Vpd_ref = '0.0' // // Vgc_ref Ground clamp reference supply voltage // Extract IBIS [GND Clamp Reference] to get this value. // Use 0 if no [GND Clamp Reference] // DEFAULT Vgc_ref = '0.0' // // IVpc_length Number of elements in the Ipc_data and Vpc_data arrays // Count the number of IBIS [Power clamp] entries to get // this value. // DEFAULT IVpc_length = '4' // // IVpu_length Number of elements in the Ipu_data and Vpu_data arrays // Count the number of IBIS [Pullup] entries to get // this value. // DEFAULT IVpu_length = '4' // // IVpd_length Number of elements in the Ipd_data and Vpd_data arrays // Count the number of IBIS [Pulldown] entries to get // this value. // DEFAULT IVpd_length = '4' // // IVgc_length Number of elements in the Igc_data and Vgc_data arrays // Count the number of IBIS [GND clamp] entries to get // this value. // DEFAULT IVgc_length = '4' // // Ipc_data[1:IVpc_length] Array of current values for power clamp I/V // Extract the IBIS [Power clamp] current column to get this. // DEFAULT Ipc_data[1:IVpc_length] = '{ 0.08 0.00 0.00 0.00}' // // Vpc_data[1:IVpc_length] Array of voltage values for power clamp I/V // Extract the IBIS [Power clamp] voltage column to get this. // DEFAULT Vpc_data[1:IVpc_length] = '{-5.00 -1.00 5.00 10.00}' // // Ipu_data[1:IVpu_length] Array of current values for pullup I/V // Extract the IBIS [Pullup] current column to get this. // DEFAULT Ipu_data[1:IVpu_length] = '{-0.08 0.00 0.00 0.00}' // // Vpu_data[1:IVpu_length] Array of voltage values for pullup I/V // Extract the IBIS [Pullup] voltage column to get this. // DEFAULT Vpu_data[1:IVpu_length] = '{-5.00 -1.00 5.00 10.00}' // // Ipd_data[1:IVpd_length] Array of current values for pulldown I/V // Extract the IBIS [Pulldown] current column to get this. // DEFAULT Ipd_data[1:IVpd_length] = '{ 0.08 0.00 0.00 0.00}' // // Vpd_data[1:IVpd_length] Array of voltage values for pulldown I/V // Extract the IBIS [Pulldown] voltage column to get this. // DEFAULT Vpd_data[1:IVpd_length] = '{-5.00 -1.00 5.00 10.00}' // // Igc_data[1:IVgc_length] Array of current values for ground clamp I/V // Extract the IBIS [GND clamp] current column to get this. // DEFAULT Igc_data[1:IVgc_length] = '{-0.08 0.00 0.00 0.00}' // // Vgc_data[1:IVgc_length] Array of voltage values for ground clamp I/V // Extract the IBIS [GND clamp] voltage column to get this. // DEFAULT Vgc_data[1:IVgc_length] = '{-5.00 -1.00 5.00 10.00}' // // VTr1_length Number of elements in the Tr1 and Vr1 arrays // Count the number of entries in the IBIS [Rising Waveform] // with V_fixture = 0 to get this value. // DEFAULT VTr1_length = '4' // // VTr2_length Number of elements in the Tr2 and Vr2 arrays // Count the number of entries in the IBIS [Rising Waveform] // with the higher V_fixture to get this value. // DEFAULT VTr2_length = '4' // // VTf1_length Number of elements in the Tf1 and Vf1 arrays // Count the number of entries in the IBIS [Falling Waveform] // with the higher V_fixture to get this value. // DEFAULT VTf1_length = '4' // // VTf2_length Number of elements in the Tf2 and Vf2 arrays // Count the number of entries in the IBIS [Falling Waveform] // with the lower V_fixture to get this value. // DEFAULT VTf2_length = '4' // // Vr1_data[1:VTr1_length] // Extract the voltage column from the IBIS [Rising Waveform] // with the higher V_fixture to get this value. // DEFAULT Vr1_data[1:VTr1_length] = '{0.00 0.00 2.50 2.50}' // // Tr1_data[1:VTr1_length] // Extract the time column from the IBIS [Rising Waveform] // with the higher the lower V_fixture to get this value. // DEFAULT Tr1_data[1:VTr1_length] = '{0.00 1.00e-9 2.00e-9 3.00e-9}' // // Vr2_data[1:VTr2_length] // Extract the voltage column from the IBIS [Rising Waveform] // with the higher V_fixture to get this value. // DEFAULT Vr2_data[1:VTr2_length] = '{2.50 2.50 5.00 5.00}' // // Tr2_data[1:VTr2_length] // Extract the time column from the IBIS [Rising Waveform] // with the higher V_fixture to get this value. // DEFAULT Tr2_data[1:VTr2_length] = '{0.00 0.50e-9 0.80e-9 3.00e-9}' // // Vf1_data[1:VTf1_length] // Extract the voltage column from the IBIS [Falling Waveform] // with the lower V_fixture to get this value. // DEFAULT Vf1_data[1:VTf1_length] = '{5.00 5.00 2.50 2.50}' // // Tf1_data[1:VTf1_length] // Extract the time column from the IBIS [Falling Waveform] // with the lower V_fixture to get this value. // DEFAULT Tf1_data[1:VTf1_length] = '{0.00 1.00e-9 2.00e-9 3.00e-9}' // // Vf2_data[1:VTf2_length] // Extract the voltage column from the IBIS [Falling Waveform] // with the higher the higher V_fixture to get this value. // DEFAULT Vf2_data[1:VTf2_length] = '{2.50 2.50 0.00 0.00}' // // Tf2_data[1:VTf2_length] // Extract the time column from the IBIS [Falling Waveform] // with the higher the higher V_fixture to get this value. // DEFAULT Tf2_data[1:VTf2_length] = '{0.00 0.50e-9 0.80e-9 3.00e-9}' // // Vfx_r1 V_fixture value for Rising Waveform 1 // Extract the lower V_fixture value from the IBIS // [Rising Waveform] set. // DEFAULT Vfx_r1 = '0.0' // // Vfx_r2 V_fixture value for Rising Waveform 2 // Extract the higher V_fixture value from the IBIS // [Rising Waveform] set. // DEFAULT Vfx_r2 = '5.0' // // Vfx_f1 V_fixture value for Falling Waveform 1 // Extract the higher V_fixture value from the IBIS // [Falling Waveform] set. // DEFAULT Vfx_f1 = '5.0' // // Vfx_f2 V_fixture value for Falling Waveform 2 // Extract the lower V_fixture value from the IBIS // [Falling Waveform] set. // DEFAULT Vfx_f2 = '0.0' // // Rfx_r1 R_fixture value for Rising Waveform 1 // Extract the R_fixture value from the IBIS // [Rising Waveform] with lower V_fixture. // DEFAULT Rfx_r1 = '50.0 from (0:inf)' // // Rfx_r2 R_fixture value for Rising Waveform 2 // Extract the R_fixture value from the IBIS // [Rising Waveform] with higher V_fixture. // DEFAULT Rfx_r2 = '50.0 from (0:inf)' // // Rfx_f1 R_fixture value for Falling Waveform 1 // Extract the R_fixture value from the IBIS // [Falling Waveform] with higher V_fixture. // DEFAULT Rfx_f1 = '50.0 from (0:inf)' // // Rfx_f2 R_fixture value for Falling Waveform2 // Extract the R_fixture value from the IBIS // [Falling Waveform] with lower V_fixture. // DEFAULT Rfx_f2 = '50.0 from (0:inf)' // // kI_pc Scaling factor for power clamp current values. // DEFAULT kI_pc = '1.0' // // kI_pu Scaling factor for pullup clamp current values. // DEFAULT kI_pu = '1.0' // // kI_pd Scaling factor for pulldown current values. // DEFAULT kI_pd = '1.0' // // kI_gc Scaling factor for ground clamp current values. // DEFAULT kI_gc = '1.0' // // kt_rise Scaling factor for [Rising waveform] time values. // DEFAULT kt_rise = '1.0 from (0:inf)' // // kt_fall Scaling factor for [Falling waveform] time values. // DEFAULT kt_fall = '1.0 from (0:inf)' // // Vth_R Input threshold for rising edges // Not an IBIS parameter; signals at the In_D and En_D // terminals will be considered to be in the high state // when the voltage is above this value. // DEFAULT Vth_R = '0.8' // // Vth_F Input threshold for falling edges // Not an IBIS parameter; signals at the In_D and En_D // terminals will be considered to be in the low state // when the voltage is below this value. // DEFAULT Vth_F = '0.2' // // Max_dt Maximum dt between simulated time points // Not an IBIS parameter; set to desired simulation resolution. // DEFAULT Max_dt = '1.0e-12 from (0:inf)' // // // INSTANCE CALL EXAMPLES: // // VAMS: // IBIS_OUTPUT #( // .C_comp(1.2e-12), // .Vpc_ref(5.0, .Vpu_ref(5.0), .Vpd_ref(0.0), .Vgc_ref(0.0), // .IVpc_length(4), .I_pc({ 0.08, 0.00, 0.00, 0.00}), // .V_pc({-5.00, -1.00, 5.00, 10.00}), // .IVpu_length(4), .I_pu({ 0.10, 0.00, -0.10, -0.20}), // .V_pu({-5.00, 0.00, 5.00, 10.00}), // .IVpd_length(4), .I_pd({-0.10, 0.00, 0.10, 0.20}), // .V_pd({-5.00, 0.00, 5.00, 10.00}), // .IVgc_length(4), .I_gc({-0.10, 0.00, 0.10, 0.20}), // .V_gc({-5.00, 0.00, 5.00, 10.00}), // .VTr1_length(4), .Vr1({0.00, 0.00, 1.66, 1.66}), // .Tr1({0.00, 1.00e-9, 2.00e-9, 3.00e-9}), // .VTr2_length(6), .Vr2({1.66, 1.66, 2.50, 2.50, 3.33, 3.33}), // .Tr2({0.00, 0.50e-9, 0.80e-9, 1.00e-9, 2.0e-9, 3.00e-9}), // .VTf1_length(6), .Vf1({3.33, 3.33, 2.50, 2.50, 1.66, 1.66}), // .Tf1({0.00, 0.50e-9, 0.80e-9, 1.00e-9, 2.00e-9, 3.00e-9}), // .VTf2_length(4), .Vf2({1.66, 1.66, 0.00, 0.00}), // .Tf2({0.00, 0.50e-9, 0.80e-9, 3.00e-9}) ) // B1 (B1_pu, B1_pd, B1_pad, B1_in, B1_pc, B1_gc); // // ========================================================= module IBIS_OUTPUT (PU_ref, PD_ref, Pad, In_D, PC_ref, GC_ref); input In_D; electrical In_D; inout Pad, PC_ref, PU_ref, PD_ref, GC_ref; electrical Pad, PC_ref, PU_ref, PD_ref, GC_ref; branch (PC_ref, Pad) pc; // branches driven in model branch (PU_ref, Pad) pu; branch (Pad, PD_ref) pd; branch (Pad, GC_ref) gc; parameter real //--------------------------------------------------------------------------- // IBIS parameters //--------------------------------------------------------------------------- C_comp = 5.0p, // Default C_comp value kC_comp_pc = 0.25, // C_comp splitting coefficients kC_comp_pu = 0.25, kC_comp_pd = 0.25, kC_comp_gc = 0.25, Vpc_ref = 5.0, // Power clamp reference voltage Vpu_ref = 5.0, // Pullup reference voltage Vpd_ref = 0.0, // Pulldown reference voltage Vgc_ref = 0.0; // Ground clamp reference voltage //--------------------------------------------------------------------------- // Vectors of the IV curve tables //--------------------------------------------------------------------------- parameter integer IVpc_length = 4, IVpu_length = 4, IVpd_length = 4, IVgc_length = 4; parameter real Ipc_data[1:IVpc_length] = { 0.08, 0.00, 0.00, 0.00}, Vpc_data[1:IVpc_length] = {-5.00, -1.00, 5.00, 10.00}, Ipu_data[1:IVpu_length] = { 0.10, 0.00, -0.10, -0.20}, Vpu_data[1:IVpu_length] = {-5.00, 0.00, 5.00, 10.00}, Ipd_data[1:IVpd_length] = {-0.10, 0.00, 0.10, 0.20}, Vpd_data[1:IVpd_length] = {-5.00, 0.00, 5.00, 10.00}, Igc_data[1:IVgc_length] = {-0.08, 0.00, 0.00, 0.00}, Vgc_data[1:IVgc_length] = {-5.00, -1.00, 5.00, 10.00}; //--------------------------------------------------------------------------- // Vectors of the Vt curve tables //--------------------------------------------------------------------------- parameter integer VTr1_length = 4, VTr2_length = 4, VTf1_length = 4, VTf2_length = 4; parameter real Vr1_data[1:VTr1_length] = {0.00, 0.00, 2.50, 2.50}, Tr1_data[1:VTr1_length] = {0.00, 1.00e-9, 2.00e-9, 3.00e-9}, Vr2_data[1:VTr2_length] = {2.50, 2.50, 5.00, 5.00}, Tr2_data[1:VTr2_length] = {0.00, 0.50e-9, 0.80e-9, 3.00e-9}, Vf1_data[1:VTf1_length] = {5.00, 5.00, 2.50, 2.50}, Tf1_data[1:VTf1_length] = {0.00, 1.00e-9, 2.00e-9, 3.00e-9}, Vf2_data[1:VTf2_length] = {2.50, 2.50, 0.00, 0.00}, Tf2_data[1:VTf2_length] = {0.00, 0.50e-9, 0.80e-9, 3.00e-9}; //--------------------------------------------------------------------------- parameter real Vfx_r1 = 0.0, // V_fixture values Vfx_r2 = 5.0, Vfx_f1 = 5.0, Vfx_f2 = 0.0, Rfx_r1 = 50.0 from (0:inf), // R_fixture values Rfx_r2 = 50.0 from (0:inf), Rfx_f1 = 50.0 from (0:inf), Rfx_f2 = 50.0 from (0:inf), //--------------------------------------------------------------------------- // Non-IBIS parameters //--------------------------------------------------------------------------- kI_pc = 1.0, // PC current scaling kI_pu = 1.0, // PU current scaling kI_pd = 1.0, // PD current scaling kI_gc = 1.0, // GC current scaling kt_rise = 1.0 from (0:inf), // Rising waveform time scaling kt_fall = 1.0 from (0:inf), // Falling waveform time scaling //--------------------------------------------------------------------------- Max_dt = 1.0e-12 from (0:inf), // Maximum dt between time points Vth_R = 0.8, // Input threshold for rising edges Vth_F = 0.2, // Input threshold for falling edges DC_threshold = (Vth_R+Vth_F)/2.0; // Input threshold during DC analysis //--------------------------------------------------------------------------- // Internal variables //--------------------------------------------------------------------------- // Calculate maximum array length for common time and K_*** tables // and declare the arrays //--------------------------------------------------------------------------- parameter real Max_t = max(kt_rise*max(Tr1_data[VTr1_length], Tr2_data[VTr2_length]), kt_fall*max(Tf1_data[VTf1_length], Tf2_data[VTf2_length])); parameter real Min_t = min(kt_rise*min(Tr1_data[1], Tr2_data[1]), kt_fall*min(Tf1_data[1], Tf2_data[1])); parameter integer Max_length = ceil((Max_t-Min_t)/Max_dt) + VTr1_length + VTr2_length + VTf1_length + VTf2_length; real Tcm[1:Max_length]; // Common time axis array real Kr1[1:Max_length]; // Scaling coefficient arrays real Kr2[1:Max_length]; real Kf1[1:Max_length]; real Kf2[1:Max_length]; integer PU_State; // Logic state variables integer PD_State; real Tpu_event; // Variables to store event time real Tpd_event; real kpu; // Output current scaling coefficients real kpd; //--------------------------------------------------------------------------- // variables used in Common_time / Common_wfm / Kcoef "function" //--------------------------------------------------------------------------- integer i; integer Common_length; integer Index_r1; integer Index_r2; integer Index_f1; integer Index_f2; integer New_index_r1; integer New_index_r2; integer New_index_f1; integer New_index_f2; real Old_t; real New_t; real Last_t; real Additional_pts; real New_dt; real Tr1_vec[1:VTr1_length]; // Vectors for scaled time real Tr2_vec[1:VTr2_length]; real Tf1_vec[1:VTf1_length]; real Tf2_vec[1:VTf2_length]; real Vr1_common[1:3]; // Need 3 elements in order to do derivatives real Vr2_common[1:3]; real Vf1_common[1:3]; real Vf2_common[1:3]; real dVwfm_r1; real dVwfm_r2; real dVwfm_f1; real dVwfm_f2; real Iout1; real Iout2; real Ipd1; real Ipd2; real Ipu1; real Ipu2; real Igc1; real Igc2; real Ipc1; real Ipc2; real Term1; real Term2; real Den; //=========================================================================== analog begin @(initial_step) begin //======================================================================= // Scale the time axis of the Vt tables //======================================================================= for (i = 1; i <= VTr1_length; i = i + 1) begin Tr1_vec[i] = kt_rise*Tr1_data[i]; end for (i = 1; i <= VTr2_length; i = i + 1) begin Tr2_vec[i] = kt_rise*Tr2_data[i]; end for (i = 1; i <= VTf1_length; i = i + 1) begin Tf1_vec[i] = kt_fall*Tf1_data[i]; end for (i = 1; i <= VTf2_length; i = i + 1) begin Tf2_vec[i] = kt_fall*Tf2_data[i]; end //======================================================================= // This "function" makes a common time axis for all Vt curves and // calculates the corresponding voltage points with linear interpolation // and/or linear extrapolation if necessary. After that it converts the // Vt curves to K coefficients which will be used in the analog equations // to scale the IV curves. The K coefficients are stored in arrays. //----------------------------------------------------------------------- // Initialize variables //----------------------------------------------------------------------- Common_length = 1; Index_r1 = 1; Index_r2 = 1; Index_f1 = 1; Index_f2 = 1; New_index_r1 = VTr1_length; New_index_r2 = VTr2_length; New_index_f1 = VTf1_length; New_index_f2 = VTf2_length; //----------------------------------------------------------------------- // Put the earliest time value of all given time vectors into "Old_t" //----------------------------------------------------------------------- Old_t = min(Tr1_vec[1], Tr2_vec[1]); Old_t = min(Old_t, Tf1_vec[1]); Old_t = min(Old_t, Tf2_vec[1]); //----------------------------------------------------------------------- // Put the latest time value of all given time vectors into "New_t" //----------------------------------------------------------------------- Last_t = max(Tr1_vec[VTr1_length], Tr2_vec[VTr2_length]); Last_t = max(Last_t, Tf1_vec[VTf1_length]); Last_t = max(Last_t, Tf2_vec[VTf2_length]); New_t = Last_t; //----------------------------------------------------------------------- // Loop until latest time value is reached in each given time vector //----------------------------------------------------------------------- while (Old_t < New_t) begin //--------------------------------------------------------------------- // Save the time value from Old_t in Tcm // and increment Common_length counter //--------------------------------------------------------------------- Tcm[Common_length] = Old_t; Common_length = Common_length + 1; //--------------------------------------------------------------------- // Find which given time vector(s) have the lowest time value and // advance their temporary indexes //--------------------------------------------------------------------- if (Tr1_vec[Index_r1] <= Old_t) New_index_r1 = Index_r1 + 1; if (Tr2_vec[Index_r2] <= Old_t) New_index_r2 = Index_r2 + 1; if (Tf1_vec[Index_f1] <= Old_t) New_index_f1 = Index_f1 + 1; if (Tf2_vec[Index_f2] <= Old_t) New_index_f2 = Index_f2 + 1; //--------------------------------------------------------------------- // Find the lowest value at the new indexes in the given vector(s) // and update indexes for next iteration //--------------------------------------------------------------------- if (New_index_r1 <= VTr1_length) begin if (Tr1_vec[New_index_r1] < New_t) New_t = Tr1_vec[New_index_r1]; Index_r1 = New_index_r1; end if (New_index_r2 <= VTr2_length) begin if (Tr2_vec[New_index_r2] < New_t) New_t = Tr2_vec[New_index_r2]; Index_r2 = New_index_r2; end if (New_index_f1 <= VTf1_length) begin if (Tf1_vec[New_index_f1] < New_t) New_t = Tf1_vec[New_index_f1]; Index_f1 = New_index_f1; end if (New_index_f2 <= VTf2_length) begin if (Tf2_vec[New_index_f2] < New_t) New_t = Tf2_vec[New_index_f2]; Index_f2 = New_index_f2; end //--------------------------------------------------------------------- // Add points if dt is larger than Max_dt //--------------------------------------------------------------------- if ((New_t-Old_t) > Max_dt) begin Additional_pts = ceil((New_t-Old_t)/Max_dt); New_dt = (New_t-Old_t) / Additional_pts; for (i = 1; i < Additional_pts; i = i + 1) begin //$strobe("\ndif = %e\tAdd = %d\tCL = %d\t T = %e\tNew_dt = ", (New_t-Old_t), Additional_pts, Common_length, Tcm[Common_length-1]+New_dt, New_dt); Tcm[Common_length] = Tcm[Common_length-1] + New_dt; Common_length = Common_length + 1; end end //--------------------------------------------------------------------- // Update variables for next iteration //--------------------------------------------------------------------- Old_t = New_t; New_t = Last_t; //--------------------------------------------------------------------- end // while loop //$strobe("\nCommon length: %d", Common_length); Tcm[Common_length] = Last_t; //======================================================================= //======================================================================= // Calculate the scaling coefficients for each time point along Tcm //----------------------------------------------------------------------- // Store the first voltage point in the common waveform variables //----------------------------------------------------------------------- Vr1_common[2] = $table_model(Tcm[1], Tr1_vec, Vr1_data, "LL"); Vr2_common[2] = $table_model(Tcm[1], Tr2_vec, Vr2_data, "LL"); Vf1_common[2] = $table_model(Tcm[1], Tf1_vec, Vf1_data, "LL"); Vf2_common[2] = $table_model(Tcm[1], Tf2_vec, Vf2_data, "LL"); for (i = 1; i <= Common_length; i = i + 1) begin //----------------------------------------------------------------------- // Store the next point (for the derivative calculations) //----------------------------------------------------------------------- if (i < Common_length) begin Vr1_common[3] = $table_model(Tcm[i+1], Tr1_vec, Vr1_data, "LL"); Vr2_common[3] = $table_model(Tcm[i+1], Tr2_vec, Vr2_data, "LL"); Vf1_common[3] = $table_model(Tcm[i+1], Tf1_vec, Vf1_data, "LL"); Vf2_common[3] = $table_model(Tcm[i+1], Tf2_vec, Vf2_data, "LL"); end //$strobe("\nTcom = %e\tR1 = %e\tR2 = %e\tF1 = %e\tF2 = %e", Tcm[i], Vr1_common[2], Vr2_common[2], Vf1_common[2], Vf2_common[2]); //--------------------------------------------------------------------- // Calculate the derivative of each waveform for C_comp compensation //--------------------------------------------------------------------- if ((i <= 1) || (i >= Common_length)) begin dVwfm_r1 = 0.0; // Force the end point derivatives to zero dVwfm_r2 = 0.0; dVwfm_f1 = 0.0; dVwfm_f2 = 0.0; end else begin dVwfm_r1 = ((Vr1_common[2] - Vr1_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vr1_common[3] - Vr1_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; dVwfm_r2 = ((Vr2_common[2] - Vr2_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vr2_common[3] - Vr2_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; dVwfm_f1 = ((Vf1_common[2] - Vf1_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vf1_common[3] - Vf1_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; dVwfm_f2 = ((Vf2_common[2] - Vf2_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vf2_common[3] - Vf2_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; end //$strobe("dR1 = %e\tdR2 = %e\tdF1 = %e\tdF2 = %e", dVwfm_r1, dVwfm_r2, dVwfm_f1, dVwfm_f2); //--------------------------------------------------------------------- // Calculate intermediate variables and the Kr1 Kr2 coefficients //--------------------------------------------------------------------- Iout1 = ((Vr1_common[2] - Vfx_r1) / Rfx_r1) + C_comp * dVwfm_r1; Iout2 = ((Vr2_common[2] - Vfx_r2) / Rfx_r2) + C_comp * dVwfm_r2; Ipc1 = -1.0 * $table_model(Vpc_ref - Vr1_common[2], Vpc_data, Ipc_data, "LL"); Ipc2 = -1.0 * $table_model(Vpc_ref - Vr2_common[2], Vpc_data, Ipc_data, "LL"); Ipu1 = -1.0 * $table_model(Vpu_ref - Vr1_common[2], Vpu_data, Ipu_data, "LL"); Ipu2 = -1.0 * $table_model(Vpu_ref - Vr2_common[2], Vpu_data, Ipu_data, "LL"); Ipd1 = $table_model(Vr1_common[2] - Vpd_ref, Vpd_data, Ipd_data, "LL"); Ipd2 = $table_model(Vr2_common[2] - Vpd_ref, Vpd_data, Ipd_data, "LL"); Igc1 = $table_model(Vr1_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); Igc2 = $table_model(Vr2_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); Term1 = Iout1 + Igc1 - Ipc1; Term2 = Ipc2 - Igc2 - Iout2; Den = (Ipu1 * Ipd2) - (Ipd1 * Ipu2); // Since these are rising waveforms // Kr1 == Kpu_on and Kr2 == Kpd_off Kr1[i] = (Ipd2*Term1 + Ipd1*Term2) / Den; Kr2[i] = (Ipu2*Term1 + Ipu1*Term2) / Den; //--------------------------------------------------------------------- // Calculate intermediate variables and the Kf1 Kf2 coefficients //--------------------------------------------------------------------- Iout1 = ((Vf1_common[2] - Vfx_f1) / Rfx_f1) + C_comp * dVwfm_f1; Iout2 = ((Vf2_common[2] - Vfx_f2) / Rfx_f2) + C_comp * dVwfm_f2; Ipc1 = -1.0 * $table_model(Vpc_ref - Vf1_common[2], Vpc_data, Ipc_data, "LL"); Ipc2 = -1.0 * $table_model(Vpc_ref - Vf2_common[2], Vpc_data, Ipc_data, "LL"); Ipu1 = -1.0 * $table_model(Vpu_ref - Vf1_common[2], Vpu_data, Ipu_data, "LL"); Ipu2 = -1.0 * $table_model(Vpu_ref - Vf2_common[2], Vpu_data, Ipu_data, "LL"); Ipd1 = $table_model(Vf1_common[2] - Vpd_ref, Vpd_data, Ipd_data, "LL"); Ipd2 = $table_model(Vf2_common[2] - Vpd_ref, Vpd_data, Ipd_data, "LL"); Igc1 = $table_model(Vf1_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); Igc2 = $table_model(Vf2_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); Term1 = Iout1 + Igc1 - Ipc1; Term2 = Ipc2 - Igc2 - Iout2; Den = (Ipu1 * Ipd2) - (Ipd1 * Ipu2); // Since these are falling waveforms // Kf1 == Kpd_on and Kf2 == Kpu_off Kf1[i] = (Ipu2*Term1 + Ipu1*Term2) / Den; Kf2[i] = (Ipd2*Term1 + Ipd1*Term2) / Den; //$strobe("\nTcom = %e\tKr1 = %e\tKr2 = %e\tKf1 = %e\tKf2 = %e", Tcm[i], Kr1[i], Kr2[i], Kf1[i], Kf2[i]); //--------------------------------------------------------------------- // Shift points by one index for next iteration (for C_comp compensation) //--------------------------------------------------------------------- Vr1_common[1] = Vr1_common[2]; Vr2_common[1] = Vr2_common[2]; Vf1_common[1] = Vf1_common[2]; Vf2_common[1] = Vf2_common[2]; Vr1_common[2] = Vr1_common[3]; Vr2_common[2] = Vr2_common[3]; Vf1_common[2] = Vf1_common[3]; Vf2_common[2] = Vf2_common[3]; end // for loop //----------------------------------------------------------------------- // Fill the unused portion of the arrays with reasonable values // to prevent any misbehaving later with $table_model //======================================================================= for (i = Common_length + 1; i <= Max_length; i = i + 1) begin Tcm[i] = Tcm[i-1] + Max_dt; Kr1[i] = Kr1[Common_length]; Kr2[i] = Kr2[Common_length]; Kf1[i] = Kf1[Common_length]; Kf2[i] = Kf2[Common_length]; end // for loop //----------------------------------------------------------------------- // End of Common_time / Common_wfm / Kcoef "function" //======================================================================= //======================================================================= // Initialize logic state variables and kpu, kpd scaling coefficients //----------------------------------------------------------------------- if (V(In_D) > DC_threshold) begin // high state PU_State = 1; PD_State = -1; end else begin // low state PU_State = -1; PD_State = 1; end if (PU_State == 1) begin // Initialization of kpu, kpd. kpu = Kr1[Common_length]; // Start with the end of the end else begin // Vt curves for those which kpu = Kf2[Common_length]; // are fully on initially. end if (PD_State == 1) begin kpd = Kf1[Common_length]; end else begin kpd = Kr2[Common_length]; end //======================================================================= end // @(initial_step) //========================================================================= // Threshold_crossing: process to detect threshold crossings in In_D //------------------------------------------------------------------------- @(cross(V(In_D)-DC_threshold, 0, 100p, 100m) or cross(V(In_D)-Vth_R, 0, 100p, 100m) or cross(V(In_D)-Vth_F, 0, 100p, 100m)) begin if ((PU_State > 0) & (PD_State < 0)) begin // curent state is high if (V(In_D) < Vth_F) begin // go to low state PU_State = -2; PD_State = 2; Tpu_event = $abstime; Tpd_event = $abstime; end end else if ((PU_State < 0) & (PD_State > 0)) begin // curent state is low if (V(In_D) > Vth_R) begin // go to high state PU_State = 2; PD_State = -2; Tpu_event = $abstime; Tpd_event = $abstime; end end $discontinuity(1); //$strobe("Time = %e\tPU_State = %d\tPD_State = %d\tTpu_event = %e\tTpd_event = %e", $abstime, PU_State, PD_State, Tpu_event, Tpd_event); //========================================================================= end // of Threshold_crossing //========================================================================= // This section contains the simultaneous analog equations to find the // appropriate scaling coefficients according to the state the buffer. //------------------------------------------------------------------------- case (PU_State) -2 : begin // PU is turning off kpu = $table_model($abstime - Tpu_event, Tcm, Kf2, "LL"); //$strobe("Time = %e\tPU_State = -2", $abstime); end -1 : begin // PU is off kpu = Kr1[1]; // 1st point in PU_on table //$strobe("Time = %e\tPU_State = -1", $abstime); end 1 : begin // PU is on kpu = Kf2[1]; // 1st point in PU_off table //$strobe("Time = %e\tPU_State = 1", $abstime); end 2 : begin // PU is tuning on kpu = $table_model($abstime - Tpu_event, Tcm, Kr1, "LL"); //$strobe("Time = %e\tPU_State = 2", $abstime); end default : begin // before any process assignments are available kpu = 0.0; //$strobe("Time = %e\tPU_State = DEFAULT", $abstime); end endcase case (PD_State) -2 : begin // PD is turning off kpd = $table_model($abstime - Tpd_event, Tcm, Kr2, "LL"); //$strobe("Time = %e\tPD_State = -2", $abstime); end -1 : begin // PD is off kpd = Kf1[1]; // 1st point in PD_on table //$strobe("Time = %e\tPD_State = -1", $abstime); end 1 : begin // PD is on kpd = Kr2[1]; // 1st point in PD_off table //$strobe("Time = %e\tPD_State = 1", $abstime); end 2 : begin // PD is tuning on kpd = $table_model($abstime - Tpd_event, Tcm, Kf1, "LL"); //$strobe("Time = %e\tPD_State = 2", $abstime); end default : begin // before any process assignments are available kpd = 0.0; //$strobe("Time = %e\tPD_State = DEFAULT", $abstime); end endcase //========================================================================= // This section contains the analog expressions which calculate // the output currents of the IV curves and C_comp capacitors. //------------------------------------------------------------------------- I(pc) <+ -kI_pc * $table_model(V(pc), Vpc_data, Ipc_data, "LL") + kC_comp_pc*C_comp*ddt(V(pc)); I(pu) <+ -kI_pu * kpu * $table_model(V(pu), Vpu_data, Ipu_data, "LL") + kC_comp_pu*C_comp*ddt(V(pu)); I(pd) <+ kI_pd * kpd * $table_model(V(pd), Vpd_data, Ipd_data, "LL") + kC_comp_pd*C_comp*ddt(V(pd)); I(gc) <+ kI_gc * $table_model(V(gc), Vgc_data, Igc_data, "LL") + kC_comp_gc*C_comp*ddt(V(gc)); //------------------------------------------------------------------------- end endmodule // IBIS_OUTPUT //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_IO (PU_ref, PD_ref, Pad, In_D, En_D, Rcv_D, PC_ref, GC_ref) // // DESCRIPTION: // An IBIS I/O buffer. The effects modeled are: // - Pullup, pulldown, and clamp I/V curves with IBIS 2.1 // waveform-based pullup/pulldown turn-on/off timing. // - Die capacitance seen at the Pad terminal, with distribution // to separate power/ground terminal per IBIS 4.1. // - Threshold based received logic detection. // // The Vth_R and Vth_F parameters control how the In_D and // En_D terminals behave. By default these are set to 0.8V // and 0.2V, respectively. The In_D and En_D terminals are // triggered to the high state when voltage rises above // Vth_R and to the low state when voltage falls below Vth_F. // For DC analyses the DC_threshold parameter is used, since // the hysteresis implemented using Vth_R and Vth_F is not useful // in DC analysis. This defaults to the mid-point between // Vth_R and Vth_F. // // When En_D is low the Pad terminal goes to high impedance. // The voltage at the Pad terminal is monitored and // a corresponding output voltage is produced at the Rcv_D // terminal. The Vinl and Vinh parameters are used as voltage // thresholds for controlling the core-level output data // at the Rcv_D terminal. When the Pad voltage is above // Vinh the Rcv_D voltage is 1.0. When the Pad voltage is // below Vinl the Rcv_D voltage is 0.0. When the Pad voltage // is in the middle region the Rcv_D voltage is 0.5. // // When En_D is high the Pad terminal is driven by either the // Pullup or Pulldown I/V table, depending on the low/high // state of the In_D terminal. State changes at the In_D // terminal trigger controlled transitions to the other // I/V table, using the waveform and test fixture parameters // to guide the transition. // // Clamp, Pullup, and Pulldown currents can be experimentally // scaled using the kI_pc, kI_gc, kI_pu, and kI_pd parameters. // These are not IBIS parameters. // // This IBIS implementation is unable to read IBIS files // directly. Therefore it will be necessary to extract // appropriate parameters from IBIS models to pass to // this model as HDL parameters. IBIS tables are passed // as arrays, with the array lengths given as separate // parameters. The default parameter values in this model // provide a functional example that does not necessarily // model any known "real" buffer. Comments below describe // where to find values in the IBIS file. // // Note that while IBIS contains typical, minimum, and // maximum values for most parameters, this buffer model // implementation accepts only a single value for each // parameter. It will be necessary to maintain seperate // parameter sets for each "corner". // // TERMINALS: // // PU_ref Pullup reference voltage supply // PD_ref Pulldown reference voltage supply // Pad Pad terminal providing input to and output from buffer // In_D Core data signal controlling buffer output // En_D Core signal controlling buffer enable state // Rcv_D Received data from buffer to core logic // PC_ref Power clamp reference voltage supply // GC_ref Ground clamp reference voltage supply // // PARAMETERS: // // C_comp Component die capacitance in farads // Extract IBIS C_comp to get this value. // DEFAULT C_comp = '5.0p' // // kC_comp_pc Fraction of C_comp referenced to PC_ref terminal // Extract IBIS C_comp_power_clamp to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pc = '0.25' // // kC_comp_pu Fraction of C_comp referenced to PU_ref terminal // Extract IBIS C_comp_pullup to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pu = '0.25' // // kC_comp_pd Fraction of C_comp referenced to PD_ref terminal // Extract IBIS C_comp_pulldown to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pd = '0.25' // // kC_comp_gc Fraction of C_comp referenced to GC_ref terminal // Extract IBIS C_comp_ground_clamp to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_gc = '0.25' // // Vinh Minimum threshold voltage for a logic high to be received // Extract IBIS Vinh to get this value. // DEFAULT Vinh = '2.0' // // Vinl Maximum threshold voltage for a logic low to be received // Extract IBIS Vinl to get this value. // DEFAULT Vinl = '0.8' // // Vpc_ref Power clamp reference supply voltage // Extract IBIS [POWER Clamp Reference] to get this value. // Use [Voltage Range] if no [POWER Clamp Reference] // DEFAULT Vpc_ref = '5.0' // // Vpu_ref Pullup reference supply voltage // Extract IBIS [Pullup Reference] to get this value. // Use [Voltage Range] if no [Pullup Reference] // DEFAULT Vpu_ref = '5.0' // // Vpd_ref Pulldown reference supply voltage // Extract IBIS [Pulldown Reference] to get this value. // Use 0 if no [Pulldown Reference] // DEFAULT Vpd_ref = '0.0' // // Vgc_ref Ground clamp reference supply voltage // Extract IBIS [GND Clamp Reference] to get this value. // Use 0 if no [GND Clamp Reference] // DEFAULT Vgc_ref = '0.0' // // IVpc_length Number of elements in the Ipc_data and Vpc_data arrays // Count the number of IBIS [Power clamp] entries to get // this value. // DEFAULT IVpc_length = '4' // // IVpu_length Number of elements in the Ipu_data and Vpu_data arrays // Count the number of IBIS [Pullup] entries to get // this value. // DEFAULT IVpu_length = '4' // // IVpd_length Number of elements in the Ipd_data and Vpd_data arrays // Count the number of IBIS [Pulldown] entries to get // this value. // DEFAULT IVpd_length = '4' // // IVgc_length Number of elements in the Igc_data and Vgc_data arrays // Count the number of IBIS [GND clamp] entries to get // this value. // DEFAULT IVgc_length = '4' // // Ipc_data[1:IVpc_length] Array of current values for power clamp I/V // Extract the IBIS [Power clamp] current column to get this. // DEFAULT Ipc_data[1:IVpc_length] = '{ 0.08 0.00 0.00 0.00}' // // Vpc_data[1:IVpc_length] Array of voltage values for power clamp I/V // Extract the IBIS [Power clamp] voltage column to get this. // DEFAULT Vpc_data[1:IVpc_length] = '{-5.00 -1.00 5.00 10.00}' // // Ipu_data[1:IVpu_length] Array of current values for pullup I/V // Extract the IBIS [Pullup] current column to get this. // DEFAULT Ipu_data[1:IVpu_length] = '{-0.08 0.00 0.00 0.00}' // // Vpu_data[1:IVpu_length] Array of voltage values for pullup I/V // Extract the IBIS [Pullup] voltage column to get this. // DEFAULT Vpu_data[1:IVpu_length] = '{-5.00 -1.00 5.00 10.00}' // // Ipd_data[1:IVpd_length] Array of current values for pulldown I/V // Extract the IBIS [Pulldown] current column to get this. // DEFAULT Ipd_data[1:IVpd_length] = '{ 0.08 0.00 0.00 0.00}' // // Vpd_data[1:IVpd_length] Array of voltage values for pulldown I/V // Extract the IBIS [Pulldown] voltage column to get this. // DEFAULT Vpd_data[1:IVpd_length] = '{-5.00 -1.00 5.00 10.00}' // // Igc_data[1:IVgc_length] Array of current values for ground clamp I/V // Extract the IBIS [GND clamp] current column to get this. // DEFAULT Igc_data[1:IVgc_length] = '{-0.08 0.00 0.00 0.00}' // // Vgc_data[1:IVgc_length] Array of voltage values for ground clamp I/V // Extract the IBIS [GND clamp] voltage column to get this. // DEFAULT Vgc_data[1:IVgc_length] = '{-5.00 -1.00 5.00 10.00}' // // VTr1_length Number of elements in the Tr1 and Vr1 arrays // Count the number of entries in the IBIS [Rising Waveform] // with V_fixture = 0 to get this value. // DEFAULT VTr1_length = '4' // // VTr2_length Number of elements in the Tr2 and Vr2 arrays // Count the number of entries in the IBIS [Rising Waveform] // with the higher V_fixture to get this value. // DEFAULT VTr2_length = '4' // // VTf1_length Number of elements in the Tf1 and Vf1 arrays // Count the number of entries in the IBIS [Falling Waveform] // with the higher V_fixture to get this value. // DEFAULT VTf1_length = '4' // // VTf2_length Number of elements in the Tf2 and Vf2 arrays // Count the number of entries in the IBIS [Falling Waveform] // with the lower V_fixture to get this value. // DEFAULT VTf2_length = '4' // // Vr1_data[1:VTr1_length] // Extract the voltage column from the IBIS [Rising Waveform] // with the higher V_fixture to get this value. // DEFAULT Vr1_data[1:VTr1_length] = '{0.00 0.00 2.50 2.50}' // // Tr1_data[1:VTr1_length] // Extract the time column from the IBIS [Rising Waveform] // with the higher the lower V_fixture to get this value. // DEFAULT Tr1_data[1:VTr1_length] = '{0.00 1.00e-9 2.00e-9 3.00e-9}' // // Vr2_data[1:VTr2_length] // Extract the voltage column from the IBIS [Rising Waveform] // with the higher V_fixture to get this value. // DEFAULT Vr2_data[1:VTr2_length] = '{2.50 2.50 5.00 5.00}' // // Tr2_data[1:VTr2_length] // Extract the time column from the IBIS [Rising Waveform] // with the higher V_fixture to get this value. // DEFAULT Tr2_data[1:VTr2_length] = '{0.00 0.50e-9 0.80e-9 3.00e-9}' // // Vf1_data[1:VTf1_length] // Extract the voltage column from the IBIS [Falling Waveform] // with the lower V_fixture to get this value. // DEFAULT Vf1_data[1:VTf1_length] = '{5.00 5.00 2.50 2.50}' // // Tf1_data[1:VTf1_length] // Extract the time column from the IBIS [Falling Waveform] // with the lower V_fixture to get this value. // DEFAULT Tf1_data[1:VTf1_length] = '{0.00 1.00e-9 2.00e-9 3.00e-9}' // // Vf2_data[1:VTf2_length] // Extract the voltage column from the IBIS [Falling Waveform] // with the higher the higher V_fixture to get this value. // DEFAULT Vf2_data[1:VTf2_length] = '{2.50 2.50 0.00 0.00}' // // Tf2_data[1:VTf2_length] // Extract the time column from the IBIS [Falling Waveform] // with the higher the higher V_fixture to get this value. // DEFAULT Tf2_data[1:VTf2_length] = '{0.00 0.50e-9 0.80e-9 3.00e-9}' // // Vfx_r1 V_fixture value for Rising Waveform 1 // Extract the lower V_fixture value from the IBIS // [Rising Waveform] set. // DEFAULT Vfx_r1 = '0.0' // // Vfx_r2 V_fixture value for Rising Waveform 2 // Extract the higher V_fixture value from the IBIS // [Rising Waveform] set. // DEFAULT Vfx_r2 = '5.0' // // Vfx_f1 V_fixture value for Falling Waveform 1 // Extract the higher V_fixture value from the IBIS // [Falling Waveform] set. // DEFAULT Vfx_f1 = '5.0' // // Vfx_f2 V_fixture value for Falling Waveform 2 // Extract the lower V_fixture value from the IBIS // [Falling Waveform] set. // DEFAULT Vfx_f2 = '0.0' // // Rfx_r1 R_fixture value for Rising Waveform 1 // Extract the R_fixture value from the IBIS // [Rising Waveform] with lower V_fixture. // DEFAULT Rfx_r1 = '50.0 from (0:inf)' // // Rfx_r2 R_fixture value for Rising Waveform 2 // Extract the R_fixture value from the IBIS // [Rising Waveform] with higher V_fixture. // DEFAULT Rfx_r2 = '50.0 from (0:inf)' // // Rfx_f1 R_fixture value for Falling Waveform 1 // Extract the R_fixture value from the IBIS // [Falling Waveform] with higher V_fixture. // DEFAULT Rfx_f1 = '50.0 from (0:inf)' // // Rfx_f2 R_fixture value for Falling Waveform2 // Extract the R_fixture value from the IBIS // [Falling Waveform] with lower V_fixture. // DEFAULT Rfx_f2 = '50.0 from (0:inf)' // // Vth_R Input threshold for rising edges // Not an IBIS parameter; signals at the In_D and En_D // terminals will be considered to be in the high state // when the voltage is above this value. // DEFAULT Vth_R = '0.8' // // Vth_F Input threshold for falling edges // Not an IBIS parameter; signals at the In_D and En_D // terminals will be considered to be in the low state // when the voltage is below this value. // DEFAULT Vth_F = '0.2' // // Max_dt Maximum delta time between simulated time points // Not an IBIS parameter; set to desired simulation resolution. // DEFAULT Max_dt = '1.0e-12 from (0:inf)' // // kI_pc Scaling factor for power clamp current values. // DEFAULT kI_pc = '1.0' // // kI_pu Scaling factor for pullup clamp current values. // DEFAULT kI_pu = '1.0' // // kI_pd Scaling factor for pulldown current values. // DEFAULT kI_pd = '1.0' // // kI_gc Scaling factor for ground clamp current values. // DEFAULT kI_gc = '1.0' // // kt_rise Scaling factor for [Rising waveform] time values. // DEFAULT kt_rise = '1.0 from (0:inf)' // // kt_fall Scaling factor for [Falling waveform] time values. // DEFAULT kt_fall = '1.0 from (0:inf)' // // DC_threshold Input threshold during DC analysis // DEFAULT DC_threshold = '(Vth_R+Vth_F)/2.0' // // // INSTANCE CALL EXAMPLES: // // VAMS: // IBIS_IO #( // .C_comp(1.2e-12), .Vinh(2.0), .Vinl(0.8), // .Vpc_ref(5.0, .Vpu_ref(5.0), .Vpd_ref(0.0), .Vgc_ref(0.0), // .IVpc_length(4), .I_pc({ 0.08, 0.00, 0.00, 0.00}), // .V_pc({-5.00, -1.00, 5.00, 10.00}), // .IVpu_length(4), .I_pu({ 0.10, 0.00, -0.10, -0.20}), // .V_pu({-5.00, 0.00, 5.00, 10.00}), // .IVpd_length(4), .I_pd({-0.10, 0.00, 0.10, 0.20}), // .V_pd({-5.00, 0.00, 5.00, 10.00}), // .IVgc_length(4), .I_gc({-0.10, 0.00, 0.10, 0.20}), // .V_gc({-5.00, 0.00, 5.00, 10.00}), // .VTr1_length(4), .Vr1({0.00, 0.00, 1.66, 1.66}), // .Tr1({0.00, 1.00e-9, 2.00e-9, 3.00e-9}), // .VTr2_length(6), .Vr2({1.66, 1.66, 2.50, 2.50, 3.33, 3.33}), // .Tr2({0.00, 0.50e-9, 0.80e-9, 1.00e-9, 2.0e-9, 3.00e-9}), // .VTf1_length(6), .Vf1({3.33, 3.33, 2.50, 2.50, 1.66, 1.66}), // .Tf1({0.00, 0.50e-9, 0.80e-9, 1.00e-9, 2.00e-9, 3.00e-9}), // .VTf2_length(4), .Vf2({1.66, 1.66, 0.00, 0.00}), // .Tf2({0.00, 0.50e-9, 0.80e-9, 3.00e-9}) ) // B1 (B1_pu, B1_pd, B1_pad, B1_in, B1_en, B1_a, B1_pc, B1_gc); // // ========================================================= module IBIS_IO (PU_ref, PD_ref, Pad, In_D, En_D, Rcv_D, PC_ref, GC_ref); input In_D, En_D; electrical In_D, En_D; output Rcv_D; electrical Rcv_D; inout Pad, PC_ref, PU_ref, PD_ref, GC_ref; electrical Pad, PC_ref, PU_ref, PD_ref, GC_ref; branch (PC_ref, Pad) pc; // branches driven in model branch (PU_ref, Pad) pu; branch (Pad, PD_ref) pd; branch (Pad, GC_ref) gc; parameter real //--------------------------------------------------------------------------- // IBIS parameters //--------------------------------------------------------------------------- C_comp = 5.0p, // Default C_comp value kC_comp_pc = 0.25, // C_comp splitting coefficients kC_comp_pu = 0.25, kC_comp_pd = 0.25, kC_comp_gc = 0.25, Vinh = 2.0, // Default Vinh value Vinl = 0.8, // Default Vinl value Vpc_ref = 5.0, // Power clamp reference voltage Vpu_ref = 5.0, // Pullup reference voltage Vpd_ref = 0.0, // Pulldown reference voltage Vgc_ref = 0.0; // Ground clamp reference voltage //--------------------------------------------------------------------------- // Vectors of the IV curve tables //--------------------------------------------------------------------------- parameter integer IVpc_length = 4, IVpu_length = 4, IVpd_length = 4, IVgc_length = 4; parameter real Ipc_data[1:IVpc_length] = { 0.08, 0.00, 0.00, 0.00}, Vpc_data[1:IVpc_length] = {-5.00, -1.00, 5.00, 10.00}, Ipu_data[1:IVpu_length] = { 0.10, 0.00, -0.10, -0.20}, Vpu_data[1:IVpu_length] = {-5.00, 0.00, 5.00, 10.00}, Ipd_data[1:IVpd_length] = {-0.10, 0.00, 0.10, 0.20}, Vpd_data[1:IVpd_length] = {-5.00, 0.00, 5.00, 10.00}, Igc_data[1:IVgc_length] = {-0.08, 0.00, 0.00, 0.00}, Vgc_data[1:IVgc_length] = {-5.00, -1.00, 5.00, 10.00}; //--------------------------------------------------------------------------- // Vectors of the Vt curve tables //--------------------------------------------------------------------------- parameter integer VTr1_length = 4, VTr2_length = 4, VTf1_length = 4, VTf2_length = 4; parameter real Vr1_data[1:VTr1_length] = {0.00, 0.00, 2.50, 2.50}, Tr1_data[1:VTr1_length] = {0.00, 1.00e-9, 2.00e-9, 3.00e-9}, Vr2_data[1:VTr2_length] = {2.50, 2.50, 5.00, 5.00}, Tr2_data[1:VTr2_length] = {0.00, 0.50e-9, 0.80e-9, 3.00e-9}, Vf1_data[1:VTf1_length] = {5.00, 5.00, 2.50, 2.50}, Tf1_data[1:VTf1_length] = {0.00, 1.00e-9, 2.00e-9, 3.00e-9}, Vf2_data[1:VTf2_length] = {2.50, 2.50, 0.00, 0.00}, Tf2_data[1:VTf2_length] = {0.00, 0.50e-9, 0.80e-9, 3.00e-9}; //--------------------------------------------------------------------------- parameter real Vfx_r1 = 0.0, // V_fixture values Vfx_r2 = 5.0, Vfx_f1 = 5.0, Vfx_f2 = 0.0, Rfx_r1 = 50.0 from (0:inf), // R_fixture values Rfx_r2 = 50.0 from (0:inf), Rfx_f1 = 50.0 from (0:inf), Rfx_f2 = 50.0 from (0:inf), //--------------------------------------------------------------------------- // Non-IBIS parameters //--------------------------------------------------------------------------- kI_pc = 1.0, // PC current scaling kI_pu = 1.0, // PU current scaling kI_pd = 1.0, // PD current scaling kI_gc = 1.0, // GC current scaling kt_rise = 1.0 from (0:inf), // Rising waveform time scaling kt_fall = 1.0 from (0:inf), // Falling waveform time scaling //--------------------------------------------------------------------------- Max_dt = 1.0e-12 from (0:inf), // Maximum dt between time points Vth_R = 0.8, // Input threshold for rising edges Vth_F = 0.2, // Input threshold for falling edges DC_threshold = (Vth_R+Vth_F)/2.0; // Input threshold during DC analysis //--------------------------------------------------------------------------- // Internal variables //--------------------------------------------------------------------------- // Calculate maximum array length for common time and K_*** tables // and declare the arrays //--------------------------------------------------------------------------- parameter real Max_t = max(kt_rise*max(Tr1_data[VTr1_length], Tr2_data[VTr2_length]), kt_fall*max(Tf1_data[VTf1_length], Tf2_data[VTf2_length])); parameter real Min_t = min(kt_rise*min(Tr1_data[1], Tr2_data[1]), kt_fall*min(Tf1_data[1], Tf2_data[1])); parameter integer Max_length = ceil((Max_t-Min_t)/Max_dt) + VTr1_length + VTr2_length + VTf1_length + VTf2_length; real Tcm[1:Max_length]; // Common time axis array real Kr1[1:Max_length]; // Scaling coefficient arrays real Kr2[1:Max_length]; real Kf1[1:Max_length]; real Kf2[1:Max_length]; integer PU_State; // Logic state variables integer PD_State; real Tpu_event; // Variables to store event time real Tpd_event; real kpu; // Output current scaling coefficients real kpd; //--------------------------------------------------------------------------- // variables used in Common_time / Common_wfm / Kcoef "function" //--------------------------------------------------------------------------- integer i; integer Common_length; integer Index_r1; integer Index_r2; integer Index_f1; integer Index_f2; integer New_index_r1; integer New_index_r2; integer New_index_f1; integer New_index_f2; real Old_t; real New_t; real Last_t; real Additional_pts; real New_dt; real Tr1_vec[1:VTr1_length]; // Vectors for scaled time real Tr2_vec[1:VTr2_length]; real Tf1_vec[1:VTf1_length]; real Tf2_vec[1:VTf2_length]; real Vr1_common[1:3]; // Need 3 elements in order to do derivatives real Vr2_common[1:3]; real Vf1_common[1:3]; real Vf2_common[1:3]; real dVwfm_r1; real dVwfm_r2; real dVwfm_f1; real dVwfm_f2; real Iout1; real Iout2; real Ipd1; real Ipd2; real Ipu1; real Ipu2; real Igc1; real Igc2; real Ipc1; real Ipc2; real Term1; real Term2; real Den; //=========================================================================== analog begin @(initial_step) begin //======================================================================= // Scale the time axis of the Vt tables //======================================================================= for (i = 1; i <= VTr1_length; i = i + 1) begin Tr1_vec[i] = kt_rise*Tr1_data[i]; end for (i = 1; i <= VTr2_length; i = i + 1) begin Tr2_vec[i] = kt_rise*Tr2_data[i]; end for (i = 1; i <= VTf1_length; i = i + 1) begin Tf1_vec[i] = kt_fall*Tf1_data[i]; end for (i = 1; i <= VTf2_length; i = i + 1) begin Tf2_vec[i] = kt_fall*Tf2_data[i]; end //======================================================================= // This "function" makes a common time axis for all Vt curves and // calculates the corresponding voltage points with linear interpolation // and/or linear extrapolation if necessary. After that it converts the // Vt curves to K coefficients which will be used in the analog equations // to scale the IV curves. The K coefficients are stored in arrays. //----------------------------------------------------------------------- // Initialize variables //----------------------------------------------------------------------- Common_length = 1; Index_r1 = 1; Index_r2 = 1; Index_f1 = 1; Index_f2 = 1; New_index_r1 = VTr1_length; New_index_r2 = VTr2_length; New_index_f1 = VTf1_length; New_index_f2 = VTf2_length; //----------------------------------------------------------------------- // Put the earliest time value of all given time vectors into "Old_t" //----------------------------------------------------------------------- Old_t = min(Tr1_vec[1], Tr2_vec[1]); Old_t = min(Old_t, Tf1_vec[1]); Old_t = min(Old_t, Tf2_vec[1]); //----------------------------------------------------------------------- // Put the latest time value of all given time vectors into "New_t" //----------------------------------------------------------------------- Last_t = max(Tr1_vec[VTr1_length], Tr2_vec[VTr2_length]); Last_t = max(Last_t, Tf1_vec[VTf1_length]); Last_t = max(Last_t, Tf2_vec[VTf2_length]); New_t = Last_t; //----------------------------------------------------------------------- // Loop until latest time value is reached in each given time vector //----------------------------------------------------------------------- while (Old_t < New_t) begin //--------------------------------------------------------------------- // Save the time value from Old_t in Tcm // and increment Common_length counter //--------------------------------------------------------------------- Tcm[Common_length] = Old_t; Common_length = Common_length + 1; //--------------------------------------------------------------------- // Find which given time vector(s) have the lowest time value and // advance their temporary indexes //--------------------------------------------------------------------- if (Tr1_vec[Index_r1] <= Old_t) New_index_r1 = Index_r1 + 1; if (Tr2_vec[Index_r2] <= Old_t) New_index_r2 = Index_r2 + 1; if (Tf1_vec[Index_f1] <= Old_t) New_index_f1 = Index_f1 + 1; if (Tf2_vec[Index_f2] <= Old_t) New_index_f2 = Index_f2 + 1; //--------------------------------------------------------------------- // Find the lowest value at the new indexes in the given vector(s) // and update indexes for next iteration //--------------------------------------------------------------------- if (New_index_r1 <= VTr1_length) begin if (Tr1_vec[New_index_r1] < New_t) New_t = Tr1_vec[New_index_r1]; Index_r1 = New_index_r1; end if (New_index_r2 <= VTr2_length) begin if (Tr2_vec[New_index_r2] < New_t) New_t = Tr2_vec[New_index_r2]; Index_r2 = New_index_r2; end if (New_index_f1 <= VTf1_length) begin if (Tf1_vec[New_index_f1] < New_t) New_t = Tf1_vec[New_index_f1]; Index_f1 = New_index_f1; end if (New_index_f2 <= VTf2_length) begin if (Tf2_vec[New_index_f2] < New_t) New_t = Tf2_vec[New_index_f2]; Index_f2 = New_index_f2; end //--------------------------------------------------------------------- // Add points if dt is larger than Max_dt //--------------------------------------------------------------------- if ((New_t-Old_t) > Max_dt) begin Additional_pts = ceil((New_t-Old_t)/Max_dt); New_dt = (New_t-Old_t) / Additional_pts; for (i = 1; i < Additional_pts; i = i + 1) begin //$strobe("\ndif = %e\tAdd = %d\tCL = %d\t T = %e\tNew_dt = ", (New_t-Old_t), Additional_pts, Common_length, Tcm[Common_length-1]+New_dt, New_dt); Tcm[Common_length] = Tcm[Common_length-1] + New_dt; Common_length = Common_length + 1; end end //--------------------------------------------------------------------- // Update variables for next iteration //--------------------------------------------------------------------- Old_t = New_t; New_t = Last_t; //--------------------------------------------------------------------- end // while loop //$strobe("\nCommon length: %d", Common_length); Tcm[Common_length] = Last_t; //======================================================================= //======================================================================= // Calculate the scaling coefficients for each time point along Tcm //----------------------------------------------------------------------- // Store the first voltage point in the common waveform variables //----------------------------------------------------------------------- Vr1_common[2] = $table_model(Tcm[1], Tr1_vec, Vr1_data, "LL"); Vr2_common[2] = $table_model(Tcm[1], Tr2_vec, Vr2_data, "LL"); Vf1_common[2] = $table_model(Tcm[1], Tf1_vec, Vf1_data, "LL"); Vf2_common[2] = $table_model(Tcm[1], Tf2_vec, Vf2_data, "LL"); for (i = 1; i <= Common_length; i = i + 1) begin //----------------------------------------------------------------------- // Store the next point (for the derivative calculations) //----------------------------------------------------------------------- if (i < Common_length) begin Vr1_common[3] = $table_model(Tcm[i+1], Tr1_vec, Vr1_data, "LL"); Vr2_common[3] = $table_model(Tcm[i+1], Tr2_vec, Vr2_data, "LL"); Vf1_common[3] = $table_model(Tcm[i+1], Tf1_vec, Vf1_data, "LL"); Vf2_common[3] = $table_model(Tcm[i+1], Tf2_vec, Vf2_data, "LL"); end //$strobe("\nTcom = %e\tR1 = %e\tR2 = %e\tF1 = %e\tF2 = %e", Tcm[i], Vr1_common[2], Vr2_common[2], Vf1_common[2], Vf2_common[2]); //--------------------------------------------------------------------- // Calculate the derivative of each waveform for C_comp compensation //--------------------------------------------------------------------- if ((i <= 1) || (i >= Common_length)) begin dVwfm_r1 = 0.0; // Force the end point derivatives to zero dVwfm_r2 = 0.0; dVwfm_f1 = 0.0; dVwfm_f2 = 0.0; end else begin dVwfm_r1 = ((Vr1_common[2] - Vr1_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vr1_common[3] - Vr1_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; dVwfm_r2 = ((Vr2_common[2] - Vr2_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vr2_common[3] - Vr2_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; dVwfm_f1 = ((Vf1_common[2] - Vf1_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vf1_common[3] - Vf1_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; dVwfm_f2 = ((Vf2_common[2] - Vf2_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vf2_common[3] - Vf2_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; end //$strobe("dR1 = %e\tdR2 = %e\tdF1 = %e\tdF2 = %e", dVwfm_r1, dVwfm_r2, dVwfm_f1, dVwfm_f2); //--------------------------------------------------------------------- // Calculate intermediate variables and the Kr1 Kr2 coefficients //--------------------------------------------------------------------- Iout1 = ((Vr1_common[2] - Vfx_r1) / Rfx_r1) + C_comp * dVwfm_r1; Iout2 = ((Vr2_common[2] - Vfx_r2) / Rfx_r2) + C_comp * dVwfm_r2; Ipc1 = -1.0 * $table_model(Vpc_ref - Vr1_common[2], Vpc_data, Ipc_data, "LL"); Ipc2 = -1.0 * $table_model(Vpc_ref - Vr2_common[2], Vpc_data, Ipc_data, "LL"); Ipu1 = -1.0 * $table_model(Vpu_ref - Vr1_common[2], Vpu_data, Ipu_data, "LL"); Ipu2 = -1.0 * $table_model(Vpu_ref - Vr2_common[2], Vpu_data, Ipu_data, "LL"); Ipd1 = $table_model(Vr1_common[2] - Vpd_ref, Vpd_data, Ipd_data, "LL"); Ipd2 = $table_model(Vr2_common[2] - Vpd_ref, Vpd_data, Ipd_data, "LL"); Igc1 = $table_model(Vr1_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); Igc2 = $table_model(Vr2_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); Term1 = Iout1 + Igc1 - Ipc1; Term2 = Ipc2 - Igc2 - Iout2; Den = (Ipu1 * Ipd2) - (Ipd1 * Ipu2); // Since these are rising waveforms // Kr1 == Kpu_on and Kr2 == Kpd_off Kr1[i] = (Ipd2*Term1 + Ipd1*Term2) / Den; Kr2[i] = (Ipu2*Term1 + Ipu1*Term2) / Den; //--------------------------------------------------------------------- // Calculate intermediate variables and the Kf1 Kf2 coefficients //--------------------------------------------------------------------- Iout1 = ((Vf1_common[2] - Vfx_f1) / Rfx_f1) + C_comp * dVwfm_f1; Iout2 = ((Vf2_common[2] - Vfx_f2) / Rfx_f2) + C_comp * dVwfm_f2; Ipc1 = -1.0 * $table_model(Vpc_ref - Vf1_common[2], Vpc_data, Ipc_data, "LL"); Ipc2 = -1.0 * $table_model(Vpc_ref - Vf2_common[2], Vpc_data, Ipc_data, "LL"); Ipu1 = -1.0 * $table_model(Vpu_ref - Vf1_common[2], Vpu_data, Ipu_data, "LL"); Ipu2 = -1.0 * $table_model(Vpu_ref - Vf2_common[2], Vpu_data, Ipu_data, "LL"); Ipd1 = $table_model(Vf1_common[2] - Vpd_ref, Vpd_data, Ipd_data, "LL"); Ipd2 = $table_model(Vf2_common[2] - Vpd_ref, Vpd_data, Ipd_data, "LL"); Igc1 = $table_model(Vf1_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); Igc2 = $table_model(Vf2_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); Term1 = Iout1 + Igc1 - Ipc1; Term2 = Ipc2 - Igc2 - Iout2; Den = (Ipu1 * Ipd2) - (Ipd1 * Ipu2); // Since these are falling waveforms // Kf1 == Kpd_on and Kf2 == Kpu_off Kf1[i] = (Ipu2*Term1 + Ipu1*Term2) / Den; Kf2[i] = (Ipd2*Term1 + Ipd1*Term2) / Den; //$strobe("\nTcom = %e\tKr1 = %e\tKr2 = %e\tKf1 = %e\tKf2 = %e", Tcm[i], Kr1[i], Kr2[i], Kf1[i], Kf2[i]); //--------------------------------------------------------------------- // Shift points by one index for next iteration (for C_comp compensation) //--------------------------------------------------------------------- Vr1_common[1] = Vr1_common[2]; Vr2_common[1] = Vr2_common[2]; Vf1_common[1] = Vf1_common[2]; Vf2_common[1] = Vf2_common[2]; Vr1_common[2] = Vr1_common[3]; Vr2_common[2] = Vr2_common[3]; Vf1_common[2] = Vf1_common[3]; Vf2_common[2] = Vf2_common[3]; end // for loop //----------------------------------------------------------------------- // Fill the unused portion of the arrays with reasonable values // to prevent any misbehaving later with $table_model //======================================================================= for (i = Common_length + 1; i <= Max_length; i = i + 1) begin Tcm[i] = Tcm[i-1] + Max_dt; Kr1[i] = Kr1[Common_length]; Kr2[i] = Kr2[Common_length]; Kf1[i] = Kf1[Common_length]; Kf2[i] = Kf2[Common_length]; end // for loop //----------------------------------------------------------------------- // End of Common_time / Common_wfm / Kcoef "function" //======================================================================= //======================================================================= // Initialize logic state variables and kpu, kpd scaling coefficients //----------------------------------------------------------------------- if ((V(En_D) > DC_threshold) & (V(In_D) > DC_threshold)) begin // high state PU_State = 1; PD_State = -1; end else if ((V(En_D) > DC_threshold) & (V(In_D) <= DC_threshold)) begin // low state PU_State = -1; PD_State = 1; end else begin // 3-state PU_State = -1; PD_State = -1; end if (PU_State == 1) begin // Initialization of kpu, kpd. kpu = Kr1[Common_length]; // Start with the end of the end else begin // Vt curves for those which kpu = Kf2[Common_length]; // are fully on initially. end if (PD_State == 1) begin kpd = Kf1[Common_length]; end else begin kpd = Kr2[Common_length]; end //======================================================================= end // @(initial_step) //========================================================================= // Threshold_crossing: process to detect threshold crossings in In_D, En_D //------------------------------------------------------------------------- @(cross(V(In_D)-DC_threshold, 0, 100p, 100m) or cross(V(In_D)-Vth_R, 0, 100p, 100m) or cross(V(In_D)-Vth_F, 0, 100p, 100m) or cross(V(En_D)-Vth_R, 0, 100p, 100m) or cross(V(En_D)-Vth_F, 0, 100p, 100m)) begin if ((PU_State < 0) & (PD_State < 0)) begin // curent state is 3-state if ((V(En_D) > Vth_R) & (V(In_D) > DC_threshold)) begin // go to high state PU_State = 2; PD_State = -1; Tpu_event = $abstime; end else if ((V(En_D) > Vth_R) & (V(In_D) <= DC_threshold)) begin // go to low state PU_State = -1; PD_State = 2; Tpd_event = $abstime; end end else if ((PU_State > 0) & (PD_State < 0)) begin // curent state is high if ((V(En_D) > Vth_R) & (V(In_D) < Vth_F)) begin // go to low state PU_State = -2; PD_State = 2; Tpu_event = $abstime; Tpd_event = $abstime; end else if (V(En_D) < Vth_F) begin // go to 3-state PU_State = -2; PD_State = -1; Tpu_event = $abstime; end end else if ((PU_State < 0) & (PD_State > 0)) begin // curent state is low if ((V(En_D) > Vth_R) & (V(In_D) > Vth_R)) begin // go to high state PU_State = 2; PD_State = -2; Tpu_event = $abstime; Tpd_event = $abstime; end else if (V(En_D) < Vth_F) begin // go to 3-state PU_State = -1; PD_State = -2; Tpd_event = $abstime; end end $discontinuity(1); //$strobe("Time = %e\tPU_State = %d\tPD_State = %d\tTpu_event = %e\tTpd_event = %e", $abstime, PU_State, PD_State, Tpu_event, Tpd_event); //========================================================================= end // of Threshold_crossing //========================================================================= // This section contains the simultaneous analog equations to find the // appropriate scaling coefficients according to the state the buffer. //------------------------------------------------------------------------- case (PU_State) -2 : begin // PU is turning off kpu = $table_model($abstime - Tpu_event, Tcm, Kf2, "LL"); //$strobe("Time = %e\tPU_State = -2", $abstime); end -1 : begin // PU is off kpu = Kr1[1]; // 1st point in PU_on table //$strobe("Time = %e\tPU_State = -1", $abstime); end 1 : begin // PU is on kpu = Kf2[1]; // 1st point in PU_off table //$strobe("Time = %e\tPU_State = 1", $abstime); end 2 : begin // PU is tuning on kpu = $table_model($abstime - Tpu_event, Tcm, Kr1, "LL"); //$strobe("Time = %e\tPU_State = 2", $abstime); end default : begin // before any process assignments are available kpu = 0.0; //$strobe("Time = %e\tPU_State = DEFAULT", $abstime); end endcase case (PD_State) -2 : begin // PD is turning off kpd = $table_model($abstime - Tpd_event, Tcm, Kr2, "LL"); //$strobe("Time = %e\tPD_State = -2", $abstime); end -1 : begin // PD is off kpd = Kf1[1]; // 1st point in PD_on table //$strobe("Time = %e\tPD_State = -1", $abstime); end 1 : begin // PD is on kpd = Kr2[1]; // 1st point in PD_off table //$strobe("Time = %e\tPD_State = 1", $abstime); end 2 : begin // PD is tuning on kpd = $table_model($abstime - Tpd_event, Tcm, Kf1, "LL"); //$strobe("Time = %e\tPD_State = 2", $abstime); end default : begin // before any process assignments are available kpd = 0.0; //$strobe("Time = %e\tPD_State = DEFAULT", $abstime); end endcase //========================================================================= // This section contains the analog expressions which calculate // the output currents of the IV curves and C_comp capacitors. //------------------------------------------------------------------------- I(pc) <+ -kI_pc * $table_model(V(pc), Vpc_data, Ipc_data, "LL") + kC_comp_pc*C_comp*ddt(V(pc)); I(pu) <+ -kI_pu * kpu * $table_model(V(pu), Vpu_data, Ipu_data, "LL") + kC_comp_pu*C_comp*ddt(V(pu)); I(pd) <+ kI_pd * kpd * $table_model(V(pd), Vpd_data, Ipd_data, "LL") + kC_comp_pd*C_comp*ddt(V(pd)); I(gc) <+ kI_gc * $table_model(V(gc), Vgc_data, Igc_data, "LL") + kC_comp_gc*C_comp*ddt(V(gc)); //------------------------------------------------------------------------- // A simple receiver logic //------------------------------------------------------------------------- if (V(pd) > Vinh) V(Rcv_D) <+ 1.0; else if (V(pd) < Vinl) V(Rcv_D) <+ 0.0; else V(Rcv_D) <+ 0.5; //------------------------------------------------------------------------- end endmodule // IBIS_IO //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_3STATE (PU_ref, PD_ref, Pad, In_D, En_D, PC_ref, GC_ref) // // DESCRIPTION: // An IBIS tri-stateable Output buffer. The effects modeled are: // - Pullup, pulldown, and clamp I/V curves with IBIS 2.1 // waveform-based pullup/pulldown turn-on/off timing. // - Die capacitance seen at the Pad terminal, with distribution // to separate power/ground terminal per IBIS 4.1. // // The Vth_R and Vth_F parameters control how the In_D and // En_D terminals behave. By default these are set to 0.8V // and 0.2V, respectively. The In_D and En_D terminals are // triggered to the high state when voltage rises above // Vth_R and to the low state when voltage falls below Vth_F. // For DC analyses the DC_threshold parameter is used, since // the hysteresis implemented using Vth_R and Vth_F is not useful // in DC analysis. This defaults to the mid-point between // Vth_R and Vth_F. // // When En_D is low the Pad terminal goes to high impedance. // // Clamp, Pullup, and Pulldown currents can be experimentally // scaled using the kI_pc, kI_gc, kI_pu, and kI_pd parameters. // These are not IBIS parameters. // // This IBIS implementation is unable to read IBIS files // directly. Therefore it will be necessary to extract // appropriate parameters from IBIS models to pass to // this model as HDL parameters. IBIS tables are passed // as arrays, with the array lengths given as separate // parameters. The default parameter values in this model // provide a functional example that does not necessarily // model any known "real" buffer. Comments below describe // where to find values in the IBIS file. // // Note that while IBIS contains typical, minimum, and // maximum values for most parameters, this buffer model // implementation accepts only a single value for each // parameter. It will be necessary to maintain seperate // parameter sets for each "corner". // // TERMINALS: // // PU_ref Pullup reference voltage supply // PD_ref Pulldown reference voltage supply // Pad Pad terminal providing input to and output from buffer // In_D Core data signal controlling buffer output // En_D Core signal controlling buffer enable state // PC_ref Power clamp reference voltage supply // GC_ref Ground clamp reference voltage supply // // PARAMETERS: // // C_comp Component die capacitance in farads // Extract IBIS C_comp to get this value. // DEFAULT C_comp = '5.0p' // // kC_comp_pc Fraction of C_comp referenced to PC_ref terminal // Extract IBIS C_comp_power_clamp to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pc = '0.25' // // kC_comp_pu Fraction of C_comp referenced to PU_ref terminal // Extract IBIS C_comp_pullup to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pu = '0.25' // // kC_comp_pd Fraction of C_comp referenced to PD_ref terminal // Extract IBIS C_comp_pulldown to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pd = '0.25' // // kC_comp_gc Fraction of C_comp referenced to GC_ref terminal // Extract IBIS C_comp_ground_clamp to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_gc = '0.25' // // Vpc_ref Power clamp reference supply voltage // Extract IBIS [POWER Clamp Reference] to get this value. // Use [Voltage Range] if no [POWER Clamp Reference] // DEFAULT Vpc_ref = '5.0' // // Vpu_ref Pullup reference supply voltage // Extract IBIS [Pullup Reference] to get this value. // Use [Voltage Range] if no [Pullup Reference] // DEFAULT Vpu_ref = '5.0' // // Vpd_ref Pulldown reference supply voltage // Extract IBIS [Pulldown Reference] to get this value. // Use 0 if no [Pulldown Reference] // DEFAULT Vpd_ref = '0.0' // // Vgc_ref Ground clamp reference supply voltage // Extract IBIS [GND Clamp Reference] to get this value. // Use 0 if no [GND Clamp Reference] // DEFAULT Vgc_ref = '0.0' // // IVpc_length Number of elements in the Ipc_data and Vpc_data arrays // Count the number of IBIS [Power clamp] entries to get // this value. // DEFAULT IVpc_length = '4' // // IVpu_length Number of elements in the Ipu_data and Vpu_data arrays // Count the number of IBIS [Pullup] entries to get // this value. // DEFAULT IVpu_length = '4' // // IVpd_length Number of elements in the Ipd_data and Vpd_data arrays // Count the number of IBIS [Pulldown] entries to get // this value. // DEFAULT IVpd_length = '4' // // IVgc_length Number of elements in the Igc_data and Vgc_data arrays // Count the number of IBIS [GND clamp] entries to get // this value. // DEFAULT IVgc_length = '4' // // Ipc_data[1:IVpc_length] Array of current values for power clamp I/V // Extract the IBIS [Power clamp] current column to get this. // DEFAULT Ipc_data[1:IVpc_length] = '{ 0.08 0.00 0.00 0.00}' // // Vpc_data[1:IVpc_length] Array of voltage values for power clamp I/V // Extract the IBIS [Power clamp] voltage column to get this. // DEFAULT Vpc_data[1:IVpc_length] = '{-5.00 -1.00 5.00 10.00}' // // Ipu_data[1:IVpu_length] Array of current values for pullup I/V // Extract the IBIS [Pullup] current column to get this. // DEFAULT Ipu_data[1:IVpu_length] = '{-0.08 0.00 0.00 0.00}' // // Vpu_data[1:IVpu_length] Array of voltage values for pullup I/V // Extract the IBIS [Pullup] voltage column to get this. // DEFAULT Vpu_data[1:IVpu_length] = '{-5.00 -1.00 5.00 10.00}' // // Ipd_data[1:IVpd_length] Array of current values for pulldown I/V // Extract the IBIS [Pulldown] current column to get this. // DEFAULT Ipd_data[1:IVpd_length] = '{ 0.08 0.00 0.00 0.00}' // // Vpd_data[1:IVpd_length] Array of voltage values for pulldown I/V // Extract the IBIS [Pulldown] voltage column to get this. // DEFAULT Vpd_data[1:IVpd_length] = '{-5.00 -1.00 5.00 10.00}' // // Igc_data[1:IVgc_length] Array of current values for ground clamp I/V // Extract the IBIS [GND clamp] current column to get this. // DEFAULT Igc_data[1:IVgc_length] = '{-0.08 0.00 0.00 0.00}' // // Vgc_data[1:IVgc_length] Array of voltage values for ground clamp I/V // Extract the IBIS [GND clamp] voltage column to get this. // DEFAULT Vgc_data[1:IVgc_length] = '{-5.00 -1.00 5.00 10.00}' // // VTr1_length Number of elements in the Tr1 and Vr1 arrays // Count the number of entries in the IBIS [Rising Waveform] // with V_fixture = 0 to get this value. // DEFAULT VTr1_length = '4' // // VTr2_length Number of elements in the Tr2 and Vr2 arrays // Count the number of entries in the IBIS [Rising Waveform] // with the higher V_fixture to get this value. // DEFAULT VTr2_length = '4' // // VTf1_length Number of elements in the Tf1 and Vf1 arrays // Count the number of entries in the IBIS [Falling Waveform] // with the higher V_fixture to get this value. // DEFAULT VTf1_length = '4' // // VTf2_length Number of elements in the Tf2 and Vf2 arrays // Count the number of entries in the IBIS [Falling Waveform] // with the lower V_fixture to get this value. // DEFAULT VTf2_length = '4' // // Vr1_data[1:VTr1_length] // Extract the voltage column from the IBIS [Rising Waveform] // with the higher V_fixture to get this value. // DEFAULT Vr1_data[1:VTr1_length] = '{0.00 0.00 2.50 2.50}' // // Tr1_data[1:VTr1_length] // Extract the time column from the IBIS [Rising Waveform] // with the higher the lower V_fixture to get this value. // DEFAULT Tr1_data[1:VTr1_length] = '{0.00 1.00e-9 2.00e-9 3.00e-9}' // // Vr2_data[1:VTr2_length] // Extract the voltage column from the IBIS [Rising Waveform] // with the higher V_fixture to get this value. // DEFAULT Vr2_data[1:VTr2_length] = '{2.50 2.50 5.00 5.00}' // // Tr2_data[1:VTr2_length] // Extract the time column from the IBIS [Rising Waveform] // with the higher V_fixture to get this value. // DEFAULT Tr2_data[1:VTr2_length] = '{0.00 0.50e-9 0.80e-9 3.00e-9}' // // Vf1_data[1:VTf1_length] // Extract the voltage column from the IBIS [Falling Waveform] // with the lower V_fixture to get this value. // DEFAULT Vf1_data[1:VTf1_length] = '{5.00 5.00 2.50 2.50}' // // Tf1_data[1:VTf1_length] // Extract the time column from the IBIS [Falling Waveform] // with the lower V_fixture to get this value. // DEFAULT Tf1_data[1:VTf1_length] = '{0.00 1.00e-9 2.00e-9 3.00e-9}' // // Vf2_data[1:VTf2_length] // Extract the voltage column from the IBIS [Falling Waveform] // with the higher the higher V_fixture to get this value. // DEFAULT Vf2_data[1:VTf2_length] = '{2.50 2.50 0.00 0.00}' // // Tf2_data[1:VTf2_length] // Extract the time column from the IBIS [Falling Waveform] // with the higher the higher V_fixture to get this value. // DEFAULT Tf2_data[1:VTf2_length] = '{0.00 0.50e-9 0.80e-9 3.00e-9}' // // Vfx_r1 V_fixture value for Rising Waveform 1 // Extract the lower V_fixture value from the IBIS // [Rising Waveform] set. // DEFAULT Vfx_r1 = '0.0' // // Vfx_r2 V_fixture value for Rising Waveform 2 // Extract the higher V_fixture value from the IBIS // [Rising Waveform] set. // DEFAULT Vfx_r2 = '5.0' // // Vfx_f1 V_fixture value for Falling Waveform 1 // Extract the higher V_fixture value from the IBIS // [Falling Waveform] set. // DEFAULT Vfx_f1 = '5.0' // // Vfx_f2 V_fixture value for Falling Waveform 2 // Extract the lower V_fixture value from the IBIS // [Falling Waveform] set. // DEFAULT Vfx_f2 = '0.0' // // Rfx_r1 R_fixture value for Rising Waveform 1 // Extract the R_fixture value from the IBIS // [Rising Waveform] with lower V_fixture. // DEFAULT Rfx_r1 = '50.0 from (0:inf)' // // Rfx_r2 R_fixture value for Rising Waveform 2 // Extract the R_fixture value from the IBIS // [Rising Waveform] with higher V_fixture. // DEFAULT Rfx_r2 = '50.0 from (0:inf)' // // Rfx_f1 R_fixture value for Falling Waveform 1 // Extract the R_fixture value from the IBIS // [Falling Waveform] with higher V_fixture. // DEFAULT Rfx_f1 = '50.0 from (0:inf)' // // Rfx_f2 R_fixture value for Falling Waveform2 // Extract the R_fixture value from the IBIS // [Falling Waveform] with lower V_fixture. // DEFAULT Rfx_f2 = '50.0 from (0:inf)' // // kI_pc Scaling factor for power clamp current values. // DEFAULT kI_pc = '1.0' // // kI_pu Scaling factor for pullup clamp current values. // DEFAULT kI_pu = '1.0' // // kI_pd Scaling factor for pulldown current values. // DEFAULT kI_pd = '1.0' // // kI_gc Scaling factor for ground clamp current values. // DEFAULT kI_gc = '1.0' // // kt_rise Scaling factor for [Rising waveform] time values. // DEFAULT kt_rise = '1.0 from (0:inf)' // // kt_fall Scaling factor for [Falling waveform] time values. // DEFAULT kt_fall = '1.0 from (0:inf)' // // Vth_R Input threshold for rising edges // Not an IBIS parameter; signals at the In_D and En_D // terminals will be considered to be in the high state // when the voltage is above this value. // DEFAULT Vth_R = '0.8' // // Vth_F Input threshold for falling edges // Not an IBIS parameter; signals at the In_D and En_D // terminals will be considered to be in the low state // when the voltage is below this value. // DEFAULT Vth_F = '0.2' // // Max_dt Maximum dt between simulated time points // Not an IBIS parameter; set to desired simulation resolution. // DEFAULT Max_dt = '1.0e-12 from (0:inf)' // // // INSTANCE CALL EXAMPLES: // // VAMS: // IBIS_3STATE #( // .C_comp(1.2e-12), // .Vpc_ref(5.0, .Vpu_ref(5.0), .Vpd_ref(0.0), .Vgc_ref(0.0), // .IVpc_length(4), .I_pc({ 0.08, 0.00, 0.00, 0.00}), // .V_pc({-5.00, -1.00, 5.00, 10.00}), // .IVpu_length(4), .I_pu({ 0.10, 0.00, -0.10, -0.20}), // .V_pu({-5.00, 0.00, 5.00, 10.00}), // .IVpd_length(4), .I_pd({-0.10, 0.00, 0.10, 0.20}), // .V_pd({-5.00, 0.00, 5.00, 10.00}), // .IVgc_length(4), .I_gc({-0.10, 0.00, 0.10, 0.20}), // .V_gc({-5.00, 0.00, 5.00, 10.00}), // .VTr1_length(4), .Vr1({0.00, 0.00, 1.66, 1.66}), // .Tr1({0.00, 1.00e-9, 2.00e-9, 3.00e-9}), // .VTr2_length(6), .Vr2({1.66, 1.66, 2.50, 2.50, 3.33, 3.33}), // .Tr2({0.00, 0.50e-9, 0.80e-9, 1.00e-9, 2.0e-9, 3.00e-9}), // .VTf1_length(6), .Vf1({3.33, 3.33, 2.50, 2.50, 1.66, 1.66}), // .Tf1({0.00, 0.50e-9, 0.80e-9, 1.00e-9, 2.00e-9, 3.00e-9}), // .VTf2_length(4), .Vf2({1.66, 1.66, 0.00, 0.00}), // .Tf2({0.00, 0.50e-9, 0.80e-9, 3.00e-9}) ) // B1 (B1_pu, B1_pd, B1_pad, B1_in, B1_pc, B1_gc); // // ========================================================= module IBIS_3STATE (PU_ref, PD_ref, Pad, In_D, En_D, PC_ref, GC_ref); input In_D, En_D; electrical In_D, En_D; inout Pad, PC_ref, PU_ref, PD_ref, GC_ref; electrical Pad, PC_ref, PU_ref, PD_ref, GC_ref; branch (PC_ref, Pad) pc; // branches driven in model branch (PU_ref, Pad) pu; branch (Pad, PD_ref) pd; branch (Pad, GC_ref) gc; parameter real //--------------------------------------------------------------------------- // IBIS parameters //--------------------------------------------------------------------------- C_comp = 5.0p, // Default C_comp value kC_comp_pc = 0.25, // C_comp splitting coefficients kC_comp_pu = 0.25, kC_comp_pd = 0.25, kC_comp_gc = 0.25, Vpc_ref = 5.0, // Power clamp reference voltage Vpu_ref = 5.0, // Pullup reference voltage Vpd_ref = 0.0, // Pulldown reference voltage Vgc_ref = 0.0; // Ground clamp reference voltage //--------------------------------------------------------------------------- // Vectors of the IV curve tables //--------------------------------------------------------------------------- parameter integer IVpc_length = 4, IVpu_length = 4, IVpd_length = 4, IVgc_length = 4; parameter real Ipc_data[1:IVpc_length] = { 0.08, 0.00, 0.00, 0.00}, Vpc_data[1:IVpc_length] = {-5.00, -1.00, 5.00, 10.00}, Ipu_data[1:IVpu_length] = { 0.10, 0.00, -0.10, -0.20}, Vpu_data[1:IVpu_length] = {-5.00, 0.00, 5.00, 10.00}, Ipd_data[1:IVpd_length] = {-0.10, 0.00, 0.10, 0.20}, Vpd_data[1:IVpd_length] = {-5.00, 0.00, 5.00, 10.00}, Igc_data[1:IVgc_length] = {-0.08, 0.00, 0.00, 0.00}, Vgc_data[1:IVgc_length] = {-5.00, -1.00, 5.00, 10.00}; //--------------------------------------------------------------------------- // Vectors of the Vt curve tables //--------------------------------------------------------------------------- parameter integer VTr1_length = 4, VTr2_length = 4, VTf1_length = 4, VTf2_length = 4; parameter real Vr1_data[1:VTr1_length] = {0.00, 0.00, 2.50, 2.50}, Tr1_data[1:VTr1_length] = {0.00, 1.00e-9, 2.00e-9, 3.00e-9}, Vr2_data[1:VTr2_length] = {2.50, 2.50, 5.00, 5.00}, Tr2_data[1:VTr2_length] = {0.00, 0.50e-9, 0.80e-9, 3.00e-9}, Vf1_data[1:VTf1_length] = {5.00, 5.00, 2.50, 2.50}, Tf1_data[1:VTf1_length] = {0.00, 1.00e-9, 2.00e-9, 3.00e-9}, Vf2_data[1:VTf2_length] = {2.50, 2.50, 0.00, 0.00}, Tf2_data[1:VTf2_length] = {0.00, 0.50e-9, 0.80e-9, 3.00e-9}; //--------------------------------------------------------------------------- parameter real Vfx_r1 = 0.0, // V_fixture values Vfx_r2 = 5.0, Vfx_f1 = 5.0, Vfx_f2 = 0.0, Rfx_r1 = 50.0 from (0:inf), // R_fixture values Rfx_r2 = 50.0 from (0:inf), Rfx_f1 = 50.0 from (0:inf), Rfx_f2 = 50.0 from (0:inf), //--------------------------------------------------------------------------- // Non-IBIS parameters //--------------------------------------------------------------------------- kI_pc = 1.0, // PC current scaling kI_pu = 1.0, // PU current scaling kI_pd = 1.0, // PD current scaling kI_gc = 1.0, // GC current scaling kt_rise = 1.0 from (0:inf), // Rising waveform time scaling kt_fall = 1.0 from (0:inf), // Falling waveform time scaling //--------------------------------------------------------------------------- Max_dt = 1.0e-12 from (0:inf), // Maximum dt between time points Vth_R = 0.8, // Input threshold for rising edges Vth_F = 0.2, // Input threshold for falling edges DC_threshold = (Vth_R+Vth_F)/2.0; // Input threshold during DC analysis //--------------------------------------------------------------------------- // Internal variables //--------------------------------------------------------------------------- // Calculate maximum array length for common time and K_*** tables // and declare the arrays //--------------------------------------------------------------------------- parameter real Max_t = max(kt_rise*max(Tr1_data[VTr1_length], Tr2_data[VTr2_length]), kt_fall*max(Tf1_data[VTf1_length], Tf2_data[VTf2_length])); parameter real Min_t = min(kt_rise*min(Tr1_data[1], Tr2_data[1]), kt_fall*min(Tf1_data[1], Tf2_data[1])); parameter integer Max_length = ceil((Max_t-Min_t)/Max_dt) + VTr1_length + VTr2_length + VTf1_length + VTf2_length; real Tcm[1:Max_length]; // Common time axis array real Kr1[1:Max_length]; // Scaling coefficient arrays real Kr2[1:Max_length]; real Kf1[1:Max_length]; real Kf2[1:Max_length]; integer PU_State; // Logic state variables integer PD_State; real Tpu_event; // Variables to store event time real Tpd_event; real kpu; // Output current scaling coefficients real kpd; //--------------------------------------------------------------------------- // variables used in Common_time / Common_wfm / Kcoef "function" //--------------------------------------------------------------------------- integer i; integer Common_length; integer Index_r1; integer Index_r2; integer Index_f1; integer Index_f2; integer New_index_r1; integer New_index_r2; integer New_index_f1; integer New_index_f2; real Old_t; real New_t; real Last_t; real Additional_pts; real New_dt; real Tr1_vec[1:VTr1_length]; // Vectors for scaled time real Tr2_vec[1:VTr2_length]; real Tf1_vec[1:VTf1_length]; real Tf2_vec[1:VTf2_length]; real Vr1_common[1:3]; // Need 3 elements in order to do derivatives real Vr2_common[1:3]; real Vf1_common[1:3]; real Vf2_common[1:3]; real dVwfm_r1; real dVwfm_r2; real dVwfm_f1; real dVwfm_f2; real Iout1; real Iout2; real Ipd1; real Ipd2; real Ipu1; real Ipu2; real Igc1; real Igc2; real Ipc1; real Ipc2; real Term1; real Term2; real Den; //=========================================================================== analog begin @(initial_step) begin //======================================================================= // Scale the time axis of the Vt tables //======================================================================= for (i = 1; i <= VTr1_length; i = i + 1) begin Tr1_vec[i] = kt_rise*Tr1_data[i]; end for (i = 1; i <= VTr2_length; i = i + 1) begin Tr2_vec[i] = kt_rise*Tr2_data[i]; end for (i = 1; i <= VTf1_length; i = i + 1) begin Tf1_vec[i] = kt_fall*Tf1_data[i]; end for (i = 1; i <= VTf2_length; i = i + 1) begin Tf2_vec[i] = kt_fall*Tf2_data[i]; end //======================================================================= // This "function" makes a common time axis for all Vt curves and // calculates the corresponding voltage points with linear interpolation // and/or linear extrapolation if necessary. After that it converts the // Vt curves to K coefficients which will be used in the analog equations // to scale the IV curves. The K coefficients are stored in arrays. //----------------------------------------------------------------------- // Initialize variables //----------------------------------------------------------------------- Common_length = 1; Index_r1 = 1; Index_r2 = 1; Index_f1 = 1; Index_f2 = 1; New_index_r1 = VTr1_length; New_index_r2 = VTr2_length; New_index_f1 = VTf1_length; New_index_f2 = VTf2_length; //----------------------------------------------------------------------- // Put the earliest time value of all given time vectors into "Old_t" //----------------------------------------------------------------------- Old_t = min(Tr1_vec[1], Tr2_vec[1]); Old_t = min(Old_t, Tf1_vec[1]); Old_t = min(Old_t, Tf2_vec[1]); //----------------------------------------------------------------------- // Put the latest time value of all given time vectors into "New_t" //----------------------------------------------------------------------- Last_t = max(Tr1_vec[VTr1_length], Tr2_vec[VTr2_length]); Last_t = max(Last_t, Tf1_vec[VTf1_length]); Last_t = max(Last_t, Tf2_vec[VTf2_length]); New_t = Last_t; //----------------------------------------------------------------------- // Loop until latest time value is reached in each given time vector //----------------------------------------------------------------------- while (Old_t < New_t) begin //--------------------------------------------------------------------- // Save the time value from Old_t in Tcm // and increment Common_length counter //--------------------------------------------------------------------- Tcm[Common_length] = Old_t; Common_length = Common_length + 1; //--------------------------------------------------------------------- // Find which given time vector(s) have the lowest time value and // advance their temporary indexes //--------------------------------------------------------------------- if (Tr1_vec[Index_r1] <= Old_t) New_index_r1 = Index_r1 + 1; if (Tr2_vec[Index_r2] <= Old_t) New_index_r2 = Index_r2 + 1; if (Tf1_vec[Index_f1] <= Old_t) New_index_f1 = Index_f1 + 1; if (Tf2_vec[Index_f2] <= Old_t) New_index_f2 = Index_f2 + 1; //--------------------------------------------------------------------- // Find the lowest value at the new indexes in the given vector(s) // and update indexes for next iteration //--------------------------------------------------------------------- if (New_index_r1 <= VTr1_length) begin if (Tr1_vec[New_index_r1] < New_t) New_t = Tr1_vec[New_index_r1]; Index_r1 = New_index_r1; end if (New_index_r2 <= VTr2_length) begin if (Tr2_vec[New_index_r2] < New_t) New_t = Tr2_vec[New_index_r2]; Index_r2 = New_index_r2; end if (New_index_f1 <= VTf1_length) begin if (Tf1_vec[New_index_f1] < New_t) New_t = Tf1_vec[New_index_f1]; Index_f1 = New_index_f1; end if (New_index_f2 <= VTf2_length) begin if (Tf2_vec[New_index_f2] < New_t) New_t = Tf2_vec[New_index_f2]; Index_f2 = New_index_f2; end //--------------------------------------------------------------------- // Add points if dt is larger than Max_dt //--------------------------------------------------------------------- if ((New_t-Old_t) > Max_dt) begin Additional_pts = ceil((New_t-Old_t)/Max_dt); New_dt = (New_t-Old_t) / Additional_pts; for (i = 1; i < Additional_pts; i = i + 1) begin //$strobe("\ndif = %e\tAdd = %d\tCL = %d\t T = %e\tNew_dt = ", (New_t-Old_t), Additional_pts, Common_length, Tcm[Common_length-1]+New_dt, New_dt); Tcm[Common_length] = Tcm[Common_length-1] + New_dt; Common_length = Common_length + 1; end end //--------------------------------------------------------------------- // Update variables for next iteration //--------------------------------------------------------------------- Old_t = New_t; New_t = Last_t; //--------------------------------------------------------------------- end // while loop //$strobe("\nCommon length: %d", Common_length); Tcm[Common_length] = Last_t; //======================================================================= //======================================================================= // Calculate the scaling coefficients for each time point along Tcm //----------------------------------------------------------------------- // Store the first voltage point in the common waveform variables //----------------------------------------------------------------------- Vr1_common[2] = $table_model(Tcm[1], Tr1_vec, Vr1_data, "LL"); Vr2_common[2] = $table_model(Tcm[1], Tr2_vec, Vr2_data, "LL"); Vf1_common[2] = $table_model(Tcm[1], Tf1_vec, Vf1_data, "LL"); Vf2_common[2] = $table_model(Tcm[1], Tf2_vec, Vf2_data, "LL"); for (i = 1; i <= Common_length; i = i + 1) begin //----------------------------------------------------------------------- // Store the next point (for the derivative calculations) //----------------------------------------------------------------------- if (i < Common_length) begin Vr1_common[3] = $table_model(Tcm[i+1], Tr1_vec, Vr1_data, "LL"); Vr2_common[3] = $table_model(Tcm[i+1], Tr2_vec, Vr2_data, "LL"); Vf1_common[3] = $table_model(Tcm[i+1], Tf1_vec, Vf1_data, "LL"); Vf2_common[3] = $table_model(Tcm[i+1], Tf2_vec, Vf2_data, "LL"); end //$strobe("\nTcom = %e\tR1 = %e\tR2 = %e\tF1 = %e\tF2 = %e", Tcm[i], Vr1_common[2], Vr2_common[2], Vf1_common[2], Vf2_common[2]); //--------------------------------------------------------------------- // Calculate the derivative of each waveform for C_comp compensation //--------------------------------------------------------------------- if ((i <= 1) || (i >= Common_length)) begin dVwfm_r1 = 0.0; // Force the end point derivatives to zero dVwfm_r2 = 0.0; dVwfm_f1 = 0.0; dVwfm_f2 = 0.0; end else begin dVwfm_r1 = ((Vr1_common[2] - Vr1_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vr1_common[3] - Vr1_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; dVwfm_r2 = ((Vr2_common[2] - Vr2_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vr2_common[3] - Vr2_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; dVwfm_f1 = ((Vf1_common[2] - Vf1_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vf1_common[3] - Vf1_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; dVwfm_f2 = ((Vf2_common[2] - Vf2_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vf2_common[3] - Vf2_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; end //$strobe("dR1 = %e\tdR2 = %e\tdF1 = %e\tdF2 = %e", dVwfm_r1, dVwfm_r2, dVwfm_f1, dVwfm_f2); //--------------------------------------------------------------------- // Calculate intermediate variables and the Kr1 Kr2 coefficients //--------------------------------------------------------------------- Iout1 = ((Vr1_common[2] - Vfx_r1) / Rfx_r1) + C_comp * dVwfm_r1; Iout2 = ((Vr2_common[2] - Vfx_r2) / Rfx_r2) + C_comp * dVwfm_r2; Ipc1 = -1.0 * $table_model(Vpc_ref - Vr1_common[2], Vpc_data, Ipc_data, "LL"); Ipc2 = -1.0 * $table_model(Vpc_ref - Vr2_common[2], Vpc_data, Ipc_data, "LL"); Ipu1 = -1.0 * $table_model(Vpu_ref - Vr1_common[2], Vpu_data, Ipu_data, "LL"); Ipu2 = -1.0 * $table_model(Vpu_ref - Vr2_common[2], Vpu_data, Ipu_data, "LL"); Ipd1 = $table_model(Vr1_common[2] - Vpd_ref, Vpd_data, Ipd_data, "LL"); Ipd2 = $table_model(Vr2_common[2] - Vpd_ref, Vpd_data, Ipd_data, "LL"); Igc1 = $table_model(Vr1_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); Igc2 = $table_model(Vr2_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); Term1 = Iout1 + Igc1 - Ipc1; Term2 = Ipc2 - Igc2 - Iout2; Den = (Ipu1 * Ipd2) - (Ipd1 * Ipu2); // Since these are rising waveforms // Kr1 == Kpu_on and Kr2 == Kpd_off Kr1[i] = (Ipd2*Term1 + Ipd1*Term2) / Den; Kr2[i] = (Ipu2*Term1 + Ipu1*Term2) / Den; //--------------------------------------------------------------------- // Calculate intermediate variables and the Kf1 Kf2 coefficients //--------------------------------------------------------------------- Iout1 = ((Vf1_common[2] - Vfx_f1) / Rfx_f1) + C_comp * dVwfm_f1; Iout2 = ((Vf2_common[2] - Vfx_f2) / Rfx_f2) + C_comp * dVwfm_f2; Ipc1 = -1.0 * $table_model(Vpc_ref - Vf1_common[2], Vpc_data, Ipc_data, "LL"); Ipc2 = -1.0 * $table_model(Vpc_ref - Vf2_common[2], Vpc_data, Ipc_data, "LL"); Ipu1 = -1.0 * $table_model(Vpu_ref - Vf1_common[2], Vpu_data, Ipu_data, "LL"); Ipu2 = -1.0 * $table_model(Vpu_ref - Vf2_common[2], Vpu_data, Ipu_data, "LL"); Ipd1 = $table_model(Vf1_common[2] - Vpd_ref, Vpd_data, Ipd_data, "LL"); Ipd2 = $table_model(Vf2_common[2] - Vpd_ref, Vpd_data, Ipd_data, "LL"); Igc1 = $table_model(Vf1_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); Igc2 = $table_model(Vf2_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); Term1 = Iout1 + Igc1 - Ipc1; Term2 = Ipc2 - Igc2 - Iout2; Den = (Ipu1 * Ipd2) - (Ipd1 * Ipu2); // Since these are falling waveforms // Kf1 == Kpd_on and Kf2 == Kpu_off Kf1[i] = (Ipu2*Term1 + Ipu1*Term2) / Den; Kf2[i] = (Ipd2*Term1 + Ipd1*Term2) / Den; //$strobe("\nTcom = %e\tKr1 = %e\tKr2 = %e\tKf1 = %e\tKf2 = %e", Tcm[i], Kr1[i], Kr2[i], Kf1[i], Kf2[i]); //--------------------------------------------------------------------- // Shift points by one index for next iteration (for C_comp compensation) //--------------------------------------------------------------------- Vr1_common[1] = Vr1_common[2]; Vr2_common[1] = Vr2_common[2]; Vf1_common[1] = Vf1_common[2]; Vf2_common[1] = Vf2_common[2]; Vr1_common[2] = Vr1_common[3]; Vr2_common[2] = Vr2_common[3]; Vf1_common[2] = Vf1_common[3]; Vf2_common[2] = Vf2_common[3]; end // for loop //----------------------------------------------------------------------- // Fill the unused portion of the arrays with reasonable values // to prevent any misbehaving later with $table_model //======================================================================= for (i = Common_length + 1; i <= Max_length; i = i + 1) begin Tcm[i] = Tcm[i-1] + Max_dt; Kr1[i] = Kr1[Common_length]; Kr2[i] = Kr2[Common_length]; Kf1[i] = Kf1[Common_length]; Kf2[i] = Kf2[Common_length]; end // for loop //----------------------------------------------------------------------- // End of Common_time / Common_wfm / Kcoef "function" //======================================================================= //======================================================================= // Initialize logic state variables and kpu, kpd scaling coefficients //----------------------------------------------------------------------- if ((V(En_D) > DC_threshold) & (V(In_D) > DC_threshold)) begin // high state PU_State = 1; PD_State = -1; end else if ((V(En_D) > DC_threshold) & (V(In_D) <= DC_threshold)) begin // low state PU_State = -1; PD_State = 1; end else begin // 3-state PU_State = -1; PD_State = -1; end if (PU_State == 1) begin // Initialization of kpu, kpd. kpu = Kr1[Common_length]; // Start with the end of the end else begin // Vt curves for those which kpu = Kf2[Common_length]; // are fully on initially. end if (PD_State == 1) begin kpd = Kf1[Common_length]; end else begin kpd = Kr2[Common_length]; end //======================================================================= end // @(initial_step) //========================================================================= // Threshold_crossing: process to detect threshold crossings in In_D, En_D //------------------------------------------------------------------------- @(cross(V(In_D)-DC_threshold, 0, 100p, 100m) or cross(V(In_D)-Vth_R, 0, 100p, 100m) or cross(V(In_D)-Vth_F, 0, 100p, 100m) or cross(V(En_D)-Vth_R, 0, 100p, 100m) or cross(V(En_D)-Vth_F, 0, 100p, 100m)) begin if ((PU_State < 0) & (PD_State < 0)) begin // curent state is 3-state if ((V(En_D) > Vth_R) & (V(In_D) > DC_threshold)) begin // go to high state PU_State = 2; PD_State = -1; Tpu_event = $abstime; end else if ((V(En_D) > Vth_R) & (V(In_D) <= DC_threshold)) begin // go to low state PU_State = -1; PD_State = 2; Tpd_event = $abstime; end end else if ((PU_State > 0) & (PD_State < 0)) begin // curent state is high if ((V(En_D) > Vth_R) & (V(In_D) < Vth_F)) begin // go to low state PU_State = -2; PD_State = 2; Tpu_event = $abstime; Tpd_event = $abstime; end else if (V(En_D) < Vth_F) begin // go to 3-state PU_State = -2; PD_State = -1; Tpu_event = $abstime; end end else if ((PU_State < 0) & (PD_State > 0)) begin // curent state is low if ((V(En_D) > Vth_R) & (V(In_D) > Vth_R)) begin // go to high state PU_State = 2; PD_State = -2; Tpu_event = $abstime; Tpd_event = $abstime; end else if (V(En_D) < Vth_F) begin // go to 3-state PU_State = -1; PD_State = -2; Tpd_event = $abstime; end end $discontinuity(1); //$strobe("Time = %e\tPU_State = %d\tPD_State = %d\tTpu_event = %e\tTpd_event = %e", $abstime, PU_State, PD_State, Tpu_event, Tpd_event); //========================================================================= end // of Threshold_crossing //========================================================================= // This section contains the simultaneous analog equations to find the // appropriate scaling coefficients according to the state the buffer. //------------------------------------------------------------------------- case (PU_State) -2 : begin // PU is turning off kpu = $table_model($abstime - Tpu_event, Tcm, Kf2, "LL"); //$strobe("Time = %e\tPU_State = -2", $abstime); end -1 : begin // PU is off kpu = Kr1[1]; // 1st point in PU_on table //$strobe("Time = %e\tPU_State = -1", $abstime); end 1 : begin // PU is on kpu = Kf2[1]; // 1st point in PU_off table //$strobe("Time = %e\tPU_State = 1", $abstime); end 2 : begin // PU is tuning on kpu = $table_model($abstime - Tpu_event, Tcm, Kr1, "LL"); //$strobe("Time = %e\tPU_State = 2", $abstime); end default : begin // before any process assignments are available kpu = 0.0; //$strobe("Time = %e\tPU_State = DEFAULT", $abstime); end endcase case (PD_State) -2 : begin // PD is turning off kpd = $table_model($abstime - Tpd_event, Tcm, Kr2, "LL"); //$strobe("Time = %e\tPD_State = -2", $abstime); end -1 : begin // PD is off kpd = Kf1[1]; // 1st point in PD_on table //$strobe("Time = %e\tPD_State = -1", $abstime); end 1 : begin // PD is on kpd = Kr2[1]; // 1st point in PD_off table //$strobe("Time = %e\tPD_State = 1", $abstime); end 2 : begin // PD is tuning on kpd = $table_model($abstime - Tpd_event, Tcm, Kf1, "LL"); //$strobe("Time = %e\tPD_State = 2", $abstime); end default : begin // before any process assignments are available kpd = 0.0; //$strobe("Time = %e\tPD_State = DEFAULT", $abstime); end endcase //========================================================================= // This section contains the analog expressions which calculate // the output currents of the IV curves and C_comp capacitors. //------------------------------------------------------------------------- I(pc) <+ -kI_pc * $table_model(V(pc), Vpc_data, Ipc_data, "LL") + kC_comp_pc*C_comp*ddt(V(pc)); I(pu) <+ -kI_pu * kpu * $table_model(V(pu), Vpu_data, Ipu_data, "LL") + kC_comp_pu*C_comp*ddt(V(pu)); I(pd) <+ kI_pd * kpd * $table_model(V(pd), Vpd_data, Ipd_data, "LL") + kC_comp_pd*C_comp*ddt(V(pd)); I(gc) <+ kI_gc * $table_model(V(gc), Vgc_data, Igc_data, "LL") + kC_comp_gc*C_comp*ddt(V(gc)); //------------------------------------------------------------------------- end endmodule // IBIS_3STATE //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_OPENSINK (PU_ref, PD_ref, Pad, In_D, PC_ref, GC_ref) // // DESCRIPTION: // An IBIS open-sink output buffer, with no pullup I/V. // The effects modeled are: // - Pulldown and clamp I/V curves with IBIS 2.1 // waveform-based pulldown turn-on/off timing. // - Die capacitance seen at the Pad terminal, with distribution // to separate power/ground terminal per IBIS 4.1. // This can distribute current to the PU_ref terminal // even though there is no pullup I/V. // // The Vth_R and Vth_F parameters control how the In_D // terminal behaves. By default these are set to 0.8V // and 0.2V, respectively. The In_D terminal is // triggered to the high state when voltage rises above // Vth_R and to the low state when voltage falls below Vth_F. // // The Pad terminal is driven by the // Pulldown I/V table, depending on the low/high // state of the In_D terminal. State changes at the In_D // terminal trigger controlled on/off transitions for the // I/V table, using the waveform and test fixture parameters // to guide the transition. // // Only one waveform pair is supported by this model instead // of the usual two pairs for push-pull buffers. The V_fixture // values should be at the power voltage. // // Clamp and Pulldown currents can be experimentally // scaled using the kI_pc, kI_gc, and kI_pd parameters. // These are not IBIS parameters. // // This IBIS implementation is unable to read IBIS files // directly. Therefore it will be necessary to extract // appropriate parameters from IBIS models to pass to // this model as HDL parameters. IBIS tables are passed // as arrays, with the array lengths given as separate // parameters. The default parameter values in this model // provide a functional example that does not necessarily // model any known "real" buffer. Comments below describe // where to find values in the IBIS file. // // Note that while IBIS contains typical, minimum, and // maximum values for most parameters, this buffer model // implementation accepts only a single value for each // parameter. It will be necessary to maintain seperate // parameter sets for each "corner". // // TERMINALS: // // PU_ref Pullup reference voltage supply // PD_ref Pulldown reference voltage supply // Pad Pad terminal providing input to and output from buffer // In_D Core data signal controlling buffer output // En_D Core signal controlling buffer enable state // PC_ref Power clamp reference voltage supply // GC_ref Ground clamp reference voltage supply // // PARAMETERS: // // C_comp Component die capacitance in farads // Extract IBIS C_comp to get this value. // DEFAULT C_comp = '5.0p' // // kC_comp_pc Fraction of C_comp referenced to PC_ref terminal // Extract IBIS C_comp_power_clamp to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pc = '0.25' // // kC_comp_pu Fraction of C_comp referenced to PU_ref terminal // Extract IBIS C_comp_pullup to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pu = '0.25' // // kC_comp_pd Fraction of C_comp referenced to PD_ref terminal // Extract IBIS C_comp_pulldown to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pd = '0.25' // // kC_comp_gc Fraction of C_comp referenced to GC_ref terminal // Extract IBIS C_comp_ground_clamp to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_gc = '0.25' // // Vinh Minimum threshold voltage for a logic high to be received // Extract IBIS Vinh to get this value. // DEFAULT Vinh = '2.0' // // Vinl Maximum threshold voltage for a logic low to be received // Extract IBIS Vinl to get this value. // DEFAULT Vinl = '0.8' // // Vpc_ref Power clamp reference supply voltage // Extract IBIS [POWER Clamp Reference] to get this value. // Use [Voltage Range] if no [POWER Clamp Reference] // DEFAULT Vpc_ref = '5.0' // // Vpu_ref Pullup reference supply voltage // Extract IBIS [Pullup Reference] to get this value. // Use [Voltage Range] if no [Pullup Reference] // DEFAULT Vpu_ref = '5.0' // // Vpd_ref Pulldown reference supply voltage // Extract IBIS [Pulldown Reference] to get this value. // Use 0 if no [Pulldown Reference] // DEFAULT Vpd_ref = '0.0' // // Vgc_ref Ground clamp reference supply voltage // Extract IBIS [GND Clamp Reference] to get this value. // Use 0 if no [GND Clamp Reference] // DEFAULT Vgc_ref = '0.0' // // IVpc_length Number of elements in the Ipc_data and Vpc_data arrays // Count the number of IBIS [Power clamp] entries to get // this value. // DEFAULT IVpc_length = '4' // // IVpd_length Number of elements in the Ipd_data and Vpd_data arrays // Count the number of IBIS [Pulldown] entries to get // this value. // DEFAULT IVpd_length = '4' // // IVgc_length Number of elements in the Igc_data and Vgc_data arrays // Count the number of IBIS [GND clamp] entries to get // this value. // DEFAULT IVgc_length = '4' // // Ipc_data[1:IVpc_length] Array of current values for power clamp I/V // Extract the IBIS [Power clamp] current column to get this. // DEFAULT Ipc_data[1:IVpc_length] = '{ 0.08 0.00 0.00 0.00}' // // Vpc_data[1:IVpc_length] Array of voltage values for power clamp I/V // Extract the IBIS [Power clamp] voltage column to get this. // DEFAULT Vpc_data[1:IVpc_length] = '{-5.00 -1.00 5.00 10.00}' // // Ipd_data[1:IVpd_length] Array of current values for pulldown I/V // Extract the IBIS [Pulldown] current column to get this. // DEFAULT Ipd_data[1:IVpd_length] = '{ 0.08 0.00 0.00 0.00}' // // Vpd_data[1:IVpd_length] Array of voltage values for pulldown I/V // Extract the IBIS [Pulldown] voltage column to get this. // DEFAULT Vpd_data[1:IVpd_length] = '{-5.00 -1.00 5.00 10.00}' // // Igc_data[1:IVgc_length] Array of current values for ground clamp I/V // Extract the IBIS [GND clamp] current column to get this. // DEFAULT Igc_data[1:IVgc_length] = '{-0.08 0.00 0.00 0.00}' // // Vgc_data[1:IVgc_length] Array of voltage values for ground clamp I/V // Extract the IBIS [GND clamp] voltage column to get this. // DEFAULT Vgc_data[1:IVgc_length] = '{-5.00 -1.00 5.00 10.00}' // // VTr1_length Number of elements in the Tr1 and Vr1 arrays // Count the number of entries in the IBIS [Rising Waveform] // with V_fixture = 0 to get this value. // DEFAULT VTr1_length = '4' // // VTf1_length Number of elements in the Tf1 and Vf1 arrays // Count the number of entries in the IBIS [Falling Waveform] // with the higher V_fixture to get this value. // DEFAULT VTf1_length = '4' // // Vr1_data[1:VTr1_length] // Extract the voltage column from the IBIS [Rising Waveform] // with the higher V_fixture to get this value. // DEFAULT Vr1_data[1:VTr1_length] = '{0.00 0.00 2.50 2.50}' // // Tr1_data[1:VTr1_length] // Extract the time column from the IBIS [Rising Waveform] // with the higher the lower V_fixture to get this value. // DEFAULT Tr1_data[1:VTr1_length] = '{0.00 1.00e-9 2.00e-9 3.00e-9}' // // Vf1_data[1:VTf1_length] // Extract the voltage column from the IBIS [Falling Waveform] // with the lower V_fixture to get this value. // DEFAULT Vf1_data[1:VTf1_length] = '{5.00 5.00 2.50 2.50}' // // Tf1_data[1:VTf1_length] // Extract the time column from the IBIS [Falling Waveform] // with the lower V_fixture to get this value. // DEFAULT Tf1_data[1:VTf1_length] = '{0.00 1.00e-9 2.00e-9 3.00e-9}' // // Vfx_r1 V_fixture value for Rising Waveform 1 // Extract the higher V_fixture value from the IBIS // [Rising Waveform] set. // DEFAULT Vfx_r1 = '0.0' // // Vfx_f1 V_fixture value for Falling Waveform 1 // Extract the higher V_fixture value from the IBIS // [Falling Waveform] set. // DEFAULT Vfx_f1 = '5.0' // // Rfx_r1 R_fixture value for Rising Waveform 1 // Extract the R_fixture value from the IBIS // [Rising Waveform] with higher V_fixture. // DEFAULT Rfx_r1 = '50.0 from (0:inf)' // // Rfx_f1 R_fixture value for Falling Waveform 1 // Extract the R_fixture value from the IBIS // [Falling Waveform] with higher V_fixture. // DEFAULT Rfx_f1 = '50.0 from (0:inf)' // // kI_pc Scaling factor for power clamp current values. // DEFAULT kI_pc = '1.0' // // kI_pd Scaling factor for pulldown current values. // DEFAULT kI_pd = '1.0' // // kI_gc Scaling factor for ground clamp current values. // DEFAULT kI_gc = '1.0' // // kt_rise Scaling factor for [Rising waveform] time values. // DEFAULT kt_rise = '1.0 from (0:inf)' // // kt_fall Scaling factor for [Falling waveform] time values. // DEFAULT kt_fall = '1.0 from (0:inf)' // // Vth_R Input threshold for rising edges // Not an IBIS parameter; signals at the In_D and En_D // terminals will be considered to be in the high state // when the voltage is above this value. // DEFAULT Vth_R = '0.8' // // Vth_F Input threshold for falling edges // Not an IBIS parameter; signals at the In_D and En_D // terminals will be considered to be in the low state // when the voltage is below this value. // DEFAULT Vth_F = '0.2' // // Max_dt Maximum dt between simulated time points // Not an IBIS parameter; set to desired simulation resolution. // DEFAULT Max_dt = '1.0e-12 from (0:inf)' // // // INSTANCE CALL EXAMPLES: // // VAMS: // IBIS_OPENSINK #( // .C_comp(1.2e-12), // .Vpc_ref(5.0, .Vpu_ref(5.0), .Vpd_ref(0.0), .Vgc_ref(0.0), // .IVpc_length(4), .I_pc({ 0.08, 0.00, 0.00, 0.00}), // .V_pc({-5.00, -1.00, 5.00, 10.00}), // .IVpd_length(4), .I_pd({-0.10, 0.00, 0.10, 0.20}), // .V_pd({-5.00, 0.00, 5.00, 10.00}), // .IVgc_length(4), .I_gc({-0.10, 0.00, 0.10, 0.20}), // .V_gc({-5.00, 0.00, 5.00, 10.00}), // .VTr1_length(4), .Vr1({0.00, 0.00, 1.66, 1.66}), // .Tr1({0.00, 1.00e-9, 2.00e-9, 3.00e-9}), // .VTf1_length(6), .Vf1({3.33, 3.33, 2.50, 2.50, 1.66, 1.66}), // .Tf1({0.00, 0.50e-9, 0.80e-9, 1.00e-9, 2.00e-9, 3.00e-9}), // B1 (B1_pu, B1_pd, B1_pad, B1_in, B1_pc, B1_gc); // // ========================================================= module IBIS_OPENSINK (PU_ref, PD_ref, Pad, In_D, PC_ref, GC_ref); input In_D; electrical In_D; inout Pad, PC_ref, PU_ref, PD_ref, GC_ref; electrical Pad, PC_ref, PU_ref, PD_ref, GC_ref; branch (PC_ref, Pad) pc; // branches driven in model branch (PU_ref, Pad) pu; branch (Pad, PD_ref) pd; branch (Pad, GC_ref) gc; parameter real //--------------------------------------------------------------------------- // IBIS parameters //--------------------------------------------------------------------------- C_comp = 5.0p, // Default C_comp value kC_comp_pc = 0.25, // C_comp splitting coefficients kC_comp_pu = 0.25, kC_comp_pd = 0.25, kC_comp_gc = 0.25, Vpc_ref = 5.0, // Power clamp reference voltage Vpd_ref = 0.0, // Pulldown reference voltage Vgc_ref = 0.0; // Ground clamp reference voltage //--------------------------------------------------------------------------- // Vectors of the IV curve tables //--------------------------------------------------------------------------- parameter integer IVpc_length = 4, IVpd_length = 4, IVgc_length = 4; parameter real Ipc_data[1:IVpc_length] = { 0.08, 0.00, 0.00, 0.00}, Vpc_data[1:IVpc_length] = {-5.00, -1.00, 5.00, 10.00}, Ipd_data[1:IVpd_length] = {-0.10, 0.00, 0.10, 0.20}, Vpd_data[1:IVpd_length] = {-5.00, 0.00, 5.00, 10.00}, Igc_data[1:IVgc_length] = {-0.08, 0.00, 0.00, 0.00}, Vgc_data[1:IVgc_length] = {-5.00, -1.00, 5.00, 10.00}; //--------------------------------------------------------------------------- // Vectors of the Vt curve tables //--------------------------------------------------------------------------- parameter integer VTr1_length = 4, VTf1_length = 4; parameter real Vr1_data[1:VTr1_length] = {2.50, 2.50, 5.00, 5.00}, Tr1_data[1:VTr1_length] = {0.00, 0.50e-9, 0.80e-9, 3.00e-9}, Vf1_data[1:VTf1_length] = {5.00, 5.00, 2.50, 2.50}, Tf1_data[1:VTf1_length] = {0.00, 1.00e-9, 2.00e-9, 3.00e-9}; //--------------------------------------------------------------------------- parameter real Vfx_r1 = 5.0, // V_fixture values Vfx_f1 = 5.0, Rfx_r1 = 50.0 from (0:inf), // R_fixture values Rfx_f1 = 50.0 from (0:inf), //--------------------------------------------------------------------------- // Non-IBIS parameters //--------------------------------------------------------------------------- kI_pc = 1.0, // PC current scaling kI_pd = 1.0, // PD current scaling kI_gc = 1.0, // GC current scaling kt_rise = 1.0 from (0:inf), // Rising waveform time scaling kt_fall = 1.0 from (0:inf), // Falling waveform time scaling //--------------------------------------------------------------------------- Max_dt = 1.0e-12 from (0:inf), // Maximum dt between time points Vth_R = 0.8, // Input threshold for rising edges Vth_F = 0.2, // Input threshold for falling edges DC_threshold = (Vth_R+Vth_F)/2.0; // Input threshold during DC analysis //--------------------------------------------------------------------------- // Internal variables //--------------------------------------------------------------------------- // Calculate maximum array length for common time and K_*** tables // and declare the arrays //--------------------------------------------------------------------------- parameter real Max_t = max(kt_rise*Tr1_data[VTr1_length], kt_fall*Tf1_data[VTf1_length]); parameter real Min_t = min(kt_rise*Tr1_data[1], kt_fall*Tf1_data[1]); parameter integer Max_length = ceil((Max_t-Min_t)/Max_dt) + VTr1_length + VTf1_length; real Tcm[1:Max_length]; // Common time axis array real Kr1[1:Max_length]; // Scaling coefficient arrays real Kf1[1:Max_length]; integer PD_State; // Logic state variables real Tpd_event; // Variables to store event time real kpd; // Output current scaling coefficients //--------------------------------------------------------------------------- // variables used in Common_time / Common_wfm / Kcoef "function" //--------------------------------------------------------------------------- integer i; integer Common_length; integer Index_r1; integer Index_f1; integer New_index_r1; integer New_index_f1; real Old_t; real New_t; real Last_t; real Additional_pts; real New_dt; real Tr1_vec[1:VTr1_length]; // Vectors for scaled time real Tf1_vec[1:VTf1_length]; real Vr1_common[1:3]; // Need 3 elements in order to do derivatives real Vf1_common[1:3]; real dVwfm_r1; real dVwfm_f1; real Iout1; real Ipd1; real Igc1; real Ipc1; //=========================================================================== analog begin @(initial_step) begin //======================================================================= // Scale the time axis of the Vt tables //======================================================================= for (i = 1; i <= VTr1_length; i = i + 1) begin Tr1_vec[i] = kt_rise*Tr1_data[i]; end for (i = 1; i <= VTf1_length; i = i + 1) begin Tf1_vec[i] = kt_fall*Tf1_data[i]; end //======================================================================= // This "function" makes a common time axis for all Vt curves and // calculates the corresponding voltage points with linear interpolation // and/or linear extrapolation if necessary. After that it converts the // Vt curves to K coefficients which will be used in the analog equations // to scale the IV curves. The K coefficients are stored in arrays. //----------------------------------------------------------------------- // Initialize variables //----------------------------------------------------------------------- Common_length = 1; Index_r1 = 1; Index_f1 = 1; New_index_r1 = VTr1_length; New_index_f1 = VTf1_length; //----------------------------------------------------------------------- // Put the earliest time value of all given time vectors into "Old_t" //----------------------------------------------------------------------- Old_t = min(Tr1_vec[1], Tf1_vec[1]); //----------------------------------------------------------------------- // Put the latest time value of all given time vectors into "New_t" //----------------------------------------------------------------------- Last_t = max(Tr1_vec[VTr1_length], Tf1_vec[VTf1_length]); New_t = Last_t; //----------------------------------------------------------------------- // Loop until latest time value is reached in each given time vector //----------------------------------------------------------------------- while (Old_t < New_t) begin //--------------------------------------------------------------------- // Save the time value from Old_t in Tcm // and increment Common_length counter //--------------------------------------------------------------------- Tcm[Common_length] = Old_t; Common_length = Common_length + 1; //--------------------------------------------------------------------- // Find which given time vector(s) have the lowest time value and // advance their temporary indexes //--------------------------------------------------------------------- if (Tr1_vec[Index_r1] <= Old_t) New_index_r1 = Index_r1 + 1; if (Tf1_vec[Index_f1] <= Old_t) New_index_f1 = Index_f1 + 1; //--------------------------------------------------------------------- // Find the lowest value at the new indexes in the given vector(s) // and update indexes for next iteration //--------------------------------------------------------------------- if (New_index_r1 <= VTr1_length) begin if (Tr1_vec[New_index_r1] < New_t) New_t = Tr1_vec[New_index_r1]; Index_r1 = New_index_r1; end if (New_index_f1 <= VTf1_length) begin if (Tf1_vec[New_index_f1] < New_t) New_t = Tf1_vec[New_index_f1]; Index_f1 = New_index_f1; end //--------------------------------------------------------------------- // Add points if dt is larger than Max_dt //--------------------------------------------------------------------- if ((New_t-Old_t) > Max_dt) begin Additional_pts = ceil((New_t-Old_t)/Max_dt); New_dt = (New_t-Old_t) / Additional_pts; for (i = 1; i < Additional_pts; i = i + 1) begin //$strobe("\ndif = %e\tAdd = %d\tCL = %d\t T = %e\tNew_dt = ", (New_t-Old_t), Additional_pts, Common_length, Tcm[Common_length-1]+New_dt, New_dt); Tcm[Common_length] = Tcm[Common_length-1] + New_dt; Common_length = Common_length + 1; end end //--------------------------------------------------------------------- // Update variables for next iteration //--------------------------------------------------------------------- Old_t = New_t; New_t = Last_t; //--------------------------------------------------------------------- end // while loop //$strobe("\nCommon length: %d", Common_length); Tcm[Common_length] = Last_t; //======================================================================= //======================================================================= // Calculate the scaling coefficients for each time point along Tcm //----------------------------------------------------------------------- // Store the first voltage point in the common waveform variables //----------------------------------------------------------------------- Vr1_common[2] = $table_model(Tcm[1], Tr1_vec, Vr1_data, "LL"); Vf1_common[2] = $table_model(Tcm[1], Tf1_vec, Vf1_data, "LL"); for (i = 1; i <= Common_length; i = i + 1) begin //----------------------------------------------------------------------- // Store the next point (for the derivative calculations) //----------------------------------------------------------------------- if (i < Common_length) begin Vr1_common[3] = $table_model(Tcm[i+1], Tr1_vec, Vr1_data, "LL"); Vf1_common[3] = $table_model(Tcm[i+1], Tf1_vec, Vf1_data, "LL"); end //$strobe("\nTcom = %e\tR1 = %e\tF1 = %e", Tcm[i], Vr1_common[2], Vf1_common[2]); //--------------------------------------------------------------------- // Calculate the derivative of each waveform for C_comp compensation //--------------------------------------------------------------------- if ((i <= 1) || (i >= Common_length)) begin dVwfm_r1 = 0.0; // Force the end point derivatives to zero dVwfm_f1 = 0.0; end else begin dVwfm_r1 = ((Vr1_common[2] - Vr1_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vr1_common[3] - Vr1_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; dVwfm_f1 = ((Vf1_common[2] - Vf1_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vf1_common[3] - Vf1_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; end //$strobe("dR1 = %e\tdF1 = %e", dVwfm_r1, dVwfm_f1); //--------------------------------------------------------------------- // Calculate intermediate variables and the Kr1 coefficients //--------------------------------------------------------------------- Iout1 = ((Vr1_common[2] - Vfx_r1) / Rfx_r1) + C_comp * dVwfm_r1; Ipc1 = -1.0 * $table_model(Vpc_ref - Vr1_common[2], Vpc_data, Ipc_data, "LL"); Ipd1 = $table_model(Vr1_common[2] - Vpd_ref, Vpd_data, Ipd_data, "LL"); Igc1 = $table_model(Vr1_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); // Since these is a rising waveform Kr1 == Kpd_off if (Ipd1 == 0) Kr1[i] = 0.0; else Kr1[i] = (Ipc1 - Igc1 - Iout1) / Ipd1; //--------------------------------------------------------------------- // Calculate intermediate variables and the Kf1 coefficients //--------------------------------------------------------------------- Iout1 = ((Vf1_common[2] - Vfx_f1) / Rfx_f1) + C_comp * dVwfm_f1; Ipc1 = -1.0 * $table_model(Vpc_ref - Vf1_common[2], Vpc_data, Ipc_data, "LL"); Ipd1 = $table_model(Vf1_common[2] - Vpd_ref, Vpd_data, Ipd_data, "LL"); Igc1 = $table_model(Vf1_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); // Since these is a falling waveform Kf1 == Kpd_on if (Ipd1 == 0) Kf1[i] = 0.0; else Kf1[i] = (Ipc1 - Igc1 - Iout1) / Ipd1; //$strobe("\nTcom = %e\tKr1 = %e\tKf1 = %e", Tcm[i], Kr1[i], Kf1[i]); //--------------------------------------------------------------------- // Shift points by one index for next iteration (for C_comp compensation) //--------------------------------------------------------------------- Vr1_common[1] = Vr1_common[2]; Vf1_common[1] = Vf1_common[2]; Vr1_common[2] = Vr1_common[3]; Vf1_common[2] = Vf1_common[3]; end // for loop //----------------------------------------------------------------------- // Fill the unused portion of the arrays with reasonable values // to prevent any misbehaving later with $table_model //======================================================================= for (i = Common_length + 1; i <= Max_length; i = i + 1) begin Tcm[i] = Tcm[i-1] + Max_dt; Kr1[i] = Kr1[Common_length]; Kf1[i] = Kf1[Common_length]; end // for loop //----------------------------------------------------------------------- // End of Common_time / Common_wfm / Kcoef "function" //======================================================================= //======================================================================= // Initialize logic state variables and kpu, kpd scaling coefficients //----------------------------------------------------------------------- if (V(In_D) > DC_threshold) begin // high state PD_State = -1; end else begin // low state PD_State = 1; end if (PD_State == 1) begin // Initialization of kpd. kpd = Kf1[Common_length]; // Start with the end of the end else begin // Vt curves for those which kpd = Kr1[Common_length]; // are fully on initially. end //======================================================================= end // @(initial_step) //========================================================================= // Threshold_crossing: process to detect threshold crossings in In_D //------------------------------------------------------------------------- @(cross(V(In_D)-DC_threshold, 0, 100p, 100m) or cross(V(In_D)-Vth_R, 0, 100p, 100m) or cross(V(In_D)-Vth_F, 0, 100p, 100m)) begin if (PD_State < 0) begin // curent state is high if (V(In_D) < Vth_F) begin // go to low state PD_State = 2; Tpd_event = $abstime; end end else if (PD_State > 0) begin // curent state is low if (V(In_D) > Vth_R) begin // go to high state PD_State = -2; Tpd_event = $abstime; end end $discontinuity(1); //$strobe("Time = %e\tPD_State = %d\tTpd_event = %e", $abstime, PD_State, Tpd_event); //========================================================================= end // of Threshold_crossing //========================================================================= // This section contains the simultaneous analog equations to find the // appropriate scaling coefficients according to the state the buffer. //------------------------------------------------------------------------- case (PD_State) -2 : begin // PD is turning off kpd = $table_model($abstime - Tpd_event, Tcm, Kr1, "LL"); //$strobe("Time = %e\tPD_State = -2", $abstime); end -1 : begin // PD is off kpd = Kf1[1]; // 1st point in PD_on table //$strobe("Time = %e\tPD_State = -1", $abstime); end 1 : begin // PD is on kpd = Kr1[1]; // 1st point in PD_off table //$strobe("Time = %e\tPD_State = 1", $abstime); end 2 : begin // PD is tuning on kpd = $table_model($abstime - Tpd_event, Tcm, Kf1, "LL"); //$strobe("Time = %e\tPD_State = 2", $abstime); end default : begin // before any process assignments are available kpd = 0.0; //$strobe("Time = %e\tPD_State = DEFAULT", $abstime); end endcase //========================================================================= // This section contains the analog expressions which calculate // the output currents of the IV curves and C_comp capacitors. //------------------------------------------------------------------------- I(pc) <+ -kI_pc * $table_model(V(pc), Vpc_data, Ipc_data, "LL") + kC_comp_pc*C_comp*ddt(V(pc)); I(pu) <+ kC_comp_pu*C_comp*ddt(V(pu)); I(pd) <+ kI_pd * kpd * $table_model(V(pd), Vpd_data, Ipd_data, "LL") + kC_comp_pd*C_comp*ddt(V(pd)); I(gc) <+ kI_gc * $table_model(V(gc), Vgc_data, Igc_data, "LL") + kC_comp_gc*C_comp*ddt(V(gc)); //------------------------------------------------------------------------- end endmodule // IBIS_OPENSINK //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_IO_OPENSINK (PU_ref, PD_ref, Pad, In_D, En_D, Rcv_D, PC_ref, GC_ref) // // DESCRIPTION: // An IBIS open-sink I/O buffer, with no pullup I/V. // The effects modeled are: // - Pulldown and clamp I/V curves with IBIS 2.1 // waveform-based pullup/pulldown turn-on/off timing. // - Die capacitance seen at the Pad terminal, with distribution // to separate power/ground terminal per IBIS 4.1. // This can distribute current to the PU_ref terminal // even though there is no pullup I/V. // - Threshold based received logic detection. // // The Vth_R and Vth_F parameters control how the In_D and // En_D terminals behave. By default these are set to 0.8V // and 0.2V, respectively. The In_D and En_D terminals are // triggered to the high state when voltage rises above // Vth_R and to the low state when voltage falls below Vth_F. // For DC analyses the DC_threshold parameter is used, since // the hysteresis implemented using Vth_R and Vth_F is not useful // in DC analysis. This defaults to the mid-point between // Vth_R and Vth_F. // // The Pad terminal is driven by the // Pulldown I/V table, depending on the low/high // state of the In_D terminal. State changes at the In_D // terminal trigger controlled on/off transitions of the // I/V table, using the waveform and test fixture parameters // to guide the transition. // // Only one waveform pair is supported by this model instead // of the usual two pairs for push-pull buffers. The V_fixture // values should be at the power voltage. // // Clamp and Pulldown currents can be experimentally // scaled using the kI_pc, kI_gc, and kI_pd parameters. // These are not IBIS parameters. // // This IBIS implementation is unable to read IBIS files // directly. Therefore it will be necessary to extract // appropriate parameters from IBIS models to pass to // this model as HDL parameters. IBIS tables are passed // as arrays, with the array lengths given as separate // parameters. The default parameter values in this model // provide a functional example that does not necessarily // model any known "real" buffer. Comments below describe // where to find values in the IBIS file. // // Note that while IBIS contains typical, minimum, and // maximum values for most parameters, this buffer model // implementation accepts only a single value for each // parameter. It will be necessary to maintain seperate // parameter sets for each "corner". // // TERMINALS: // // PU_ref Pullup reference voltage supply // PD_ref Pulldown reference voltage supply // Pad Pad terminal providing input to and output from buffer // In_D Core data signal controlling buffer output // En_D Core signal controlling buffer enable state // Rcv_D Received data from buffer to core logic // PC_ref Power clamp reference voltage supply // GC_ref Ground clamp reference voltage supply // // PARAMETERS: // // C_comp Component die capacitance in farads // Extract IBIS C_comp to get this value. // DEFAULT C_comp = '5.0p' // // kC_comp_pc Fraction of C_comp referenced to PC_ref terminal // Extract IBIS C_comp_power_clamp to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pc = '0.25' // // kC_comp_pu Fraction of C_comp referenced to PU_ref terminal // Extract IBIS C_comp_pullup to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pu = '0.25' // // kC_comp_pd Fraction of C_comp referenced to PD_ref terminal // Extract IBIS C_comp_pulldown to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pd = '0.25' // // kC_comp_gc Fraction of C_comp referenced to GC_ref terminal // Extract IBIS C_comp_ground_clamp to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_gc = '0.25' // // Vinh Minimum threshold voltage for a logic high to be received // Extract IBIS Vinh to get this value. // DEFAULT Vinh = '2.0' // // Vinl Maximum threshold voltage for a logic low to be received // Extract IBIS Vinl to get this value. // DEFAULT Vinl = '0.8' // // Vpc_ref Power clamp reference supply voltage // Extract IBIS [POWER Clamp Reference] to get this value. // Use [Voltage Range] if no [POWER Clamp Reference] // DEFAULT Vpc_ref = '5.0' // // Vpu_ref Pullup reference supply voltage // Extract IBIS [Pullup Reference] to get this value. // Use [Voltage Range] if no [Pullup Reference] // DEFAULT Vpu_ref = '5.0' // // Vpd_ref Pulldown reference supply voltage // Extract IBIS [Pulldown Reference] to get this value. // Use 0 if no [Pulldown Reference] // DEFAULT Vpd_ref = '0.0' // // Vgc_ref Ground clamp reference supply voltage // Extract IBIS [GND Clamp Reference] to get this value. // Use 0 if no [GND Clamp Reference] // DEFAULT Vgc_ref = '0.0' // // IVpc_length Number of elements in the Ipc_data and Vpc_data arrays // Count the number of IBIS [Power clamp] entries to get // this value. // DEFAULT IVpc_length = '4' // // IVpd_length Number of elements in the Ipd_data and Vpd_data arrays // Count the number of IBIS [Pulldown] entries to get // this value. // DEFAULT IVpd_length = '4' // // IVgc_length Number of elements in the Igc_data and Vgc_data arrays // Count the number of IBIS [GND clamp] entries to get // this value. // DEFAULT IVgc_length = '4' // // Ipc_data[1:IVpc_length] Array of current values for power clamp I/V // Extract the IBIS [Power clamp] current column to get this. // DEFAULT Ipc_data[1:IVpc_length] = '{ 0.08 0.00 0.00 0.00}' // // Vpc_data[1:IVpc_length] Array of voltage values for power clamp I/V // Extract the IBIS [Power clamp] voltage column to get this. // DEFAULT Vpc_data[1:IVpc_length] = '{-5.00 -1.00 5.00 10.00}' // // Ipd_data[1:IVpd_length] Array of current values for pulldown I/V // Extract the IBIS [Pulldown] current column to get this. // DEFAULT Ipd_data[1:IVpd_length] = '{ 0.08 0.00 0.00 0.00}' // // Vpd_data[1:IVpd_length] Array of voltage values for pulldown I/V // Extract the IBIS [Pulldown] voltage column to get this. // DEFAULT Vpd_data[1:IVpd_length] = '{-5.00 -1.00 5.00 10.00}' // // Igc_data[1:IVgc_length] Array of current values for ground clamp I/V // Extract the IBIS [GND clamp] current column to get this. // DEFAULT Igc_data[1:IVgc_length] = '{-0.08 0.00 0.00 0.00}' // // Vgc_data[1:IVgc_length] Array of voltage values for ground clamp I/V // Extract the IBIS [GND clamp] voltage column to get this. // DEFAULT Vgc_data[1:IVgc_length] = '{-5.00 -1.00 5.00 10.00}' // // VTr1_length Number of elements in the Tr1 and Vr1 arrays // Count the number of entries in the IBIS [Rising Waveform] // with the higher V_fixture to get this value. // DEFAULT VTr1_length = '4' // // VTf1_length Number of elements in the Tf1 and Vf1 arrays // Count the number of entries in the IBIS [Falling Waveform] // with the higher V_fixture to get this value. // DEFAULT VTf1_length = '4' // // Vr1_data[1:VTr1_length] // Extract the voltage column from the IBIS [Rising Waveform] // with the higher V_fixture to get this value. // DEFAULT Vr1_data[1:VTr1_length] = '{0.00 0.00 2.50 2.50}' // // Tr1_data[1:VTr1_length] // Extract the time column from the IBIS [Rising Waveform] // with the higher the lower V_fixture to get this value. // DEFAULT Tr1_data[1:VTr1_length] = '{0.00 1.00e-9 2.00e-9 3.00e-9}' // // Vf1_data[1:VTf1_length] // Extract the voltage column from the IBIS [Falling Waveform] // with the higher V_fixture to get this value. // DEFAULT Vf1_data[1:VTf1_length] = '{5.00 5.00 2.50 2.50}' // // Tf1_data[1:VTf1_length] // Extract the time column from the IBIS [Falling Waveform] // with the higher V_fixture to get this value. // DEFAULT Tf1_data[1:VTf1_length] = '{0.00 1.00e-9 2.00e-9 3.00e-9}' // // Vfx_r1 V_fixture value for Rising Waveform 1 // Extract the higher V_fixture value from the IBIS // [Rising Waveform] set. // DEFAULT Vfx_r1 = '0.0' // // Vfx_f1 V_fixture value for Falling Waveform 1 // Extract the higher V_fixture value from the IBIS // [Falling Waveform] set. // DEFAULT Vfx_f1 = '5.0' // // Rfx_r1 R_fixture value for Rising Waveform 1 // Extract the R_fixture value from the IBIS // [Rising Waveform] with higher V_fixture. // DEFAULT Rfx_r1 = '50.0 from (0:inf)' // // Rfx_f1 R_fixture value for Falling Waveform 1 // Extract the R_fixture value from the IBIS // [Falling Waveform] with higher V_fixture. // DEFAULT Rfx_f1 = '50.0 from (0:inf)' // // Vth_R Input threshold for rising edges // Not an IBIS parameter; signals at the In_D and En_D // terminals will be considered to be in the high state // when the voltage is above this value. // DEFAULT Vth_R = '0.8' // // Vth_F Input threshold for falling edges // Not an IBIS parameter; signals at the In_D and En_D // terminals will be considered to be in the low state // when the voltage is below this value. // DEFAULT Vth_F = '0.2' // // Max_dt Maximum delta time between simulated time points // Not an IBIS parameter; set to desired simulation resolution. // DEFAULT Max_dt = '1.0e-12 from (0:inf)' // // kI_pc Scaling factor for power clamp current values. // DEFAULT kI_pc = '1.0' // // kI_pd Scaling factor for pulldown current values. // DEFAULT kI_pd = '1.0' // // kI_gc Scaling factor for ground clamp current values. // DEFAULT kI_gc = '1.0' // // kt_rise Scaling factor for [Rising waveform] time values. // DEFAULT kt_rise = '1.0 from (0:inf)' // // kt_fall Scaling factor for [Falling waveform] time values. // DEFAULT kt_fall = '1.0 from (0:inf)' // // DC_threshold Input threshold during DC analysis // DEFAULT DC_threshold = '(Vth_R+Vth_F)/2.0' // // // INSTANCE CALL EXAMPLES: // // VAMS: // IBIS_IO_OPENSINK #( // .C_comp(1.2e-12), .Vinh(2.0), .Vinl(0.8), // .Vpc_ref(5.0, .Vpu_ref(5.0), .Vpd_ref(0.0), .Vgc_ref(0.0), // .IVpc_length(4), .I_pc({ 0.08, 0.00, 0.00, 0.00}), // .V_pc({-5.00, -1.00, 5.00, 10.00}), // .IVpd_length(4), .I_pd({-0.10, 0.00, 0.10, 0.20}), // .V_pd({-5.00, 0.00, 5.00, 10.00}), // .IVgc_length(4), .I_gc({-0.10, 0.00, 0.10, 0.20}), // .V_gc({-5.00, 0.00, 5.00, 10.00}), // .VTr1_length(4), .Vr1({0.00, 0.00, 1.66, 1.66}), // .Tr1({0.00, 1.00e-9, 2.00e-9, 3.00e-9}), // .VTf1_length(6), .Vf1({3.33, 3.33, 2.50, 2.50, 1.66, 1.66}), // .Tf1({0.00, 0.50e-9, 0.80e-9, 1.00e-9, 2.00e-9, 3.00e-9}), // B1 (B1_pu, B1_pd, B1_pad, B1_in, B1_en, B1_a, B1_pc, B1_gc); // // ========================================================= module IBIS_IO_OPENSINK (PU_ref, PD_ref, Pad, In_D, En_D, Rcv_D, PC_ref, GC_ref); input In_D, En_D; electrical In_D, En_D; output Rcv_D; electrical Rcv_D; inout Pad, PC_ref, PU_ref, PD_ref, GC_ref; electrical Pad, PC_ref, PU_ref, PD_ref, GC_ref; branch (PC_ref, Pad) pc; // branches driven in model branch (PU_ref, Pad) pu; branch (Pad, PD_ref) pd; branch (Pad, GC_ref) gc; parameter real //--------------------------------------------------------------------------- // IBIS parameters //--------------------------------------------------------------------------- C_comp = 5.0p, // Default C_comp value kC_comp_pc = 0.25, // C_comp splitting coefficients kC_comp_pu = 0.25, kC_comp_pd = 0.25, kC_comp_gc = 0.25, Vinh = 2.0, // Default Vinh value Vinl = 0.8, // Default Vinl value Vpc_ref = 5.0, // Power clamp reference voltage Vpd_ref = 0.0, // Pulldown reference voltage Vgc_ref = 0.0; // Ground clamp reference voltage //--------------------------------------------------------------------------- // Vectors of the IV curve tables //--------------------------------------------------------------------------- parameter integer IVpc_length = 4, IVpd_length = 4, IVgc_length = 4; parameter real Ipc_data[1:IVpc_length] = { 0.08, 0.00, 0.00, 0.00}, Vpc_data[1:IVpc_length] = {-5.00, -1.00, 5.00, 10.00}, Ipd_data[1:IVpd_length] = {-0.10, 0.00, 0.10, 0.20}, Vpd_data[1:IVpd_length] = {-5.00, 0.00, 5.00, 10.00}, Igc_data[1:IVgc_length] = {-0.08, 0.00, 0.00, 0.00}, Vgc_data[1:IVgc_length] = {-5.00, -1.00, 5.00, 10.00}; //--------------------------------------------------------------------------- // Vectors of the Vt curve tables //--------------------------------------------------------------------------- parameter integer VTr1_length = 4, VTf1_length = 4; parameter real Vr1_data[1:VTr1_length] = {2.50, 2.50, 5.00, 5.00}, Tr1_data[1:VTr1_length] = {0.00, 0.50e-9, 0.80e-9, 3.00e-9}, Vf1_data[1:VTf1_length] = {5.00, 5.00, 2.50, 2.50}, Tf1_data[1:VTf1_length] = {0.00, 1.00e-9, 2.00e-9, 3.00e-9}; //--------------------------------------------------------------------------- parameter real Vfx_r1 = 5.0, // V_fixture values Vfx_f1 = 5.0, Rfx_r1 = 50.0 from (0:inf), // R_fixture values Rfx_f1 = 50.0 from (0:inf), //--------------------------------------------------------------------------- // Non-IBIS parameters //--------------------------------------------------------------------------- kI_pc = 1.0, // PC current scaling kI_pd = 1.0, // PD current scaling kI_gc = 1.0, // GC current scaling kt_rise = 1.0 from (0:inf), // Rising waveform time scaling kt_fall = 1.0 from (0:inf), // Falling waveform time scaling //--------------------------------------------------------------------------- Max_dt = 1.0e-12 from (0:inf), // Maximum dt between time points Vth_R = 0.8, // Input threshold for rising edges Vth_F = 0.2, // Input threshold for falling edges DC_threshold = (Vth_R+Vth_F)/2.0; // Input threshold during DC analysis //--------------------------------------------------------------------------- // Internal variables //--------------------------------------------------------------------------- // Calculate maximum array length for common time and K_*** tables // and declare the arrays //--------------------------------------------------------------------------- parameter real Max_t = max(kt_rise*Tr1_data[VTr1_length], kt_fall*Tf1_data[VTf1_length]); parameter real Min_t = min(kt_rise*Tr1_data[1], kt_fall*Tf1_data[1]); parameter integer Max_length = ceil((Max_t-Min_t)/Max_dt) + VTr1_length + VTf1_length; real Tcm[1:Max_length]; // Common time axis array real Kr1[1:Max_length]; // Scaling coefficient arrays real Kf1[1:Max_length]; integer PU_State; // Logic state variables integer PD_State; real Tpd_event; // Variables to store event time real kpd; // Output current scaling coefficients //--------------------------------------------------------------------------- // variables used in Common_time / Common_wfm / Kcoef "function" //--------------------------------------------------------------------------- integer i; integer Common_length; integer Index_r1; integer Index_f1; integer New_index_r1; integer New_index_f1; real Old_t; real New_t; real Last_t; real Additional_pts; real New_dt; real Tr1_vec[1:VTr1_length]; // Vectors for scaled time real Tf1_vec[1:VTf1_length]; real Vr1_common[1:3]; // Need 3 elements in order to do derivatives real Vf1_common[1:3]; real dVwfm_r1; real dVwfm_f1; real Iout1; real Ipd1; real Igc1; real Ipc1; //=========================================================================== analog begin @(initial_step) begin //======================================================================= // Scale the time axis of the Vt tables //======================================================================= for (i = 1; i <= VTr1_length; i = i + 1) begin Tr1_vec[i] = kt_rise*Tr1_data[i]; end for (i = 1; i <= VTf1_length; i = i + 1) begin Tf1_vec[i] = kt_fall*Tf1_data[i]; end //======================================================================= // This "function" makes a common time axis for all Vt curves and // calculates the corresponding voltage points with linear interpolation // and/or linear extrapolation if necessary. After that it converts the // Vt curves to K coefficients which will be used in the analog equations // to scale the IV curves. The K coefficients are stored in arrays. //----------------------------------------------------------------------- // Initialize variables //----------------------------------------------------------------------- Common_length = 1; Index_r1 = 1; Index_f1 = 1; New_index_r1 = VTr1_length; New_index_f1 = VTf1_length; //----------------------------------------------------------------------- // Put the earliest time value of all given time vectors into "Old_t" //----------------------------------------------------------------------- Old_t = min(Tr1_vec[1], Tf1_vec[1]); //----------------------------------------------------------------------- // Put the latest time value of all given time vectors into "New_t" //----------------------------------------------------------------------- Last_t = max(Tr1_vec[VTr1_length], Tf1_vec[VTf1_length]); New_t = Last_t; //----------------------------------------------------------------------- // Loop until latest time value is reached in each given time vector //----------------------------------------------------------------------- while (Old_t < New_t) begin //--------------------------------------------------------------------- // Save the time value from Old_t in Tcm // and increment Common_length counter //--------------------------------------------------------------------- Tcm[Common_length] = Old_t; Common_length = Common_length + 1; //--------------------------------------------------------------------- // Find which given time vector(s) have the lowest time value and // advance their temporary indexes //--------------------------------------------------------------------- if (Tr1_vec[Index_r1] <= Old_t) New_index_r1 = Index_r1 + 1; if (Tf1_vec[Index_f1] <= Old_t) New_index_f1 = Index_f1 + 1; //--------------------------------------------------------------------- // Find the lowest value at the new indexes in the given vector(s) // and update indexes for next iteration //--------------------------------------------------------------------- if (New_index_r1 <= VTr1_length) begin if (Tr1_vec[New_index_r1] < New_t) New_t = Tr1_vec[New_index_r1]; Index_r1 = New_index_r1; end if (New_index_f1 <= VTf1_length) begin if (Tf1_vec[New_index_f1] < New_t) New_t = Tf1_vec[New_index_f1]; Index_f1 = New_index_f1; end //--------------------------------------------------------------------- // Add points if dt is larger than Max_dt //--------------------------------------------------------------------- if ((New_t-Old_t) > Max_dt) begin Additional_pts = ceil((New_t-Old_t)/Max_dt); New_dt = (New_t-Old_t) / Additional_pts; for (i = 1; i < Additional_pts; i = i + 1) begin //$strobe("\ndif = %e\tAdd = %d\tCL = %d\t T = %e\tNew_dt = ", (New_t-Old_t), Additional_pts, Common_length, Tcm[Common_length-1]+New_dt, New_dt); Tcm[Common_length] = Tcm[Common_length-1] + New_dt; Common_length = Common_length + 1; end end //--------------------------------------------------------------------- // Update variables for next iteration //--------------------------------------------------------------------- Old_t = New_t; New_t = Last_t; //--------------------------------------------------------------------- end // while loop //$strobe("\nCommon length: %d", Common_length); Tcm[Common_length] = Last_t; //======================================================================= //======================================================================= // Calculate the scaling coefficients for each time point along Tcm //----------------------------------------------------------------------- // Store the first voltage point in the common waveform variables //----------------------------------------------------------------------- Vr1_common[2] = $table_model(Tcm[1], Tr1_vec, Vr1_data, "LL"); Vf1_common[2] = $table_model(Tcm[1], Tf1_vec, Vf1_data, "LL"); for (i = 1; i <= Common_length; i = i + 1) begin //----------------------------------------------------------------------- // Store the next point (for the derivative calculations) //----------------------------------------------------------------------- if (i < Common_length) begin Vr1_common[3] = $table_model(Tcm[i+1], Tr1_vec, Vr1_data, "LL"); Vf1_common[3] = $table_model(Tcm[i+1], Tf1_vec, Vf1_data, "LL"); end //$strobe("\nTcom = %e\tR1 = %e\tF1 = %e", Tcm[i], Vr1_common[2], Vf1_common[2]); //--------------------------------------------------------------------- // Calculate the derivative of each waveform for C_comp compensation //--------------------------------------------------------------------- if ((i <= 1) || (i >= Common_length)) begin dVwfm_r1 = 0.0; // Force the end point derivatives to zero dVwfm_f1 = 0.0; end else begin dVwfm_r1 = ((Vr1_common[2] - Vr1_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vr1_common[3] - Vr1_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; dVwfm_f1 = ((Vf1_common[2] - Vf1_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vf1_common[3] - Vf1_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; end //$strobe("dR1 = %e\tdF1 = %e", dVwfm_r1, dVwfm_f1); //--------------------------------------------------------------------- // Calculate intermediate variables and the Kr1 coefficients //--------------------------------------------------------------------- Iout1 = ((Vr1_common[2] - Vfx_r1) / Rfx_r1) + C_comp * dVwfm_r1; Ipc1 = -1.0 * $table_model(Vpc_ref - Vr1_common[2], Vpc_data, Ipc_data, "LL"); Ipd1 = $table_model(Vr1_common[2] - Vpd_ref, Vpd_data, Ipd_data, "LL"); Igc1 = $table_model(Vr1_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); // Since these is a rising waveform Kr1 == Kpd_off if (Ipd1 == 0) Kr1[i] = 0.0; else Kr1[i] = (Ipc1 - Igc1 - Iout1) / Ipd1; //--------------------------------------------------------------------- // Calculate intermediate variables and the Kf1 coefficients //--------------------------------------------------------------------- Iout1 = ((Vf1_common[2] - Vfx_f1) / Rfx_f1) + C_comp * dVwfm_f1; Ipc1 = -1.0 * $table_model(Vpc_ref - Vf1_common[2], Vpc_data, Ipc_data, "LL"); Ipd1 = $table_model(Vf1_common[2] - Vpd_ref, Vpd_data, Ipd_data, "LL"); Igc1 = $table_model(Vf1_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); // Since these is a falling waveform Kf1 == Kpd_on if (Ipd1 == 0) Kf1[i] = 0.0; else Kf1[i] = (Ipc1 - Igc1 - Iout1) / Ipd1; //$strobe("\nTcom = %e\tKr1 = %e\tKf1 = %e", Tcm[i], Kr1[i], Kf1[i]); //--------------------------------------------------------------------- // Shift points by one index for next iteration (for C_comp compensation) //--------------------------------------------------------------------- Vr1_common[1] = Vr1_common[2]; Vf1_common[1] = Vf1_common[2]; Vr1_common[2] = Vr1_common[3]; Vf1_common[2] = Vf1_common[3]; end // for loop //----------------------------------------------------------------------- // Fill the unused portion of the arrays with reasonable values // to prevent any misbehaving later with $table_model //======================================================================= for (i = Common_length + 1; i <= Max_length; i = i + 1) begin Tcm[i] = Tcm[i-1] + Max_dt; Kr1[i] = Kr1[Common_length]; Kf1[i] = Kf1[Common_length]; end // for loop //----------------------------------------------------------------------- // End of Common_time / Common_wfm / Kcoef "function" //======================================================================= //======================================================================= // Initialize logic state variables and kpu, kpd scaling coefficients //----------------------------------------------------------------------- if ((V(En_D) > DC_threshold) & (V(In_D) > DC_threshold)) begin // high state PU_State = 1; PD_State = -1; end else if ((V(En_D) > DC_threshold) & (V(In_D) <= DC_threshold)) begin // low state PU_State = -1; PD_State = 1; end else begin // 3-state PU_State = -1; PD_State = -1; end if (PD_State == 1) begin // Initialization of kpd. kpd = Kf1[Common_length]; // Start with the end of the end else begin // Vt curves for those which kpd = Kr1[Common_length]; // are fully on initially. end //======================================================================= end // @(initial_step) //========================================================================= // Threshold_crossing: process to detect threshold crossings in In_D, En_D //------------------------------------------------------------------------- @(cross(V(In_D)-DC_threshold, 0, 100p, 100m) or cross(V(In_D)-Vth_R, 0, 100p, 100m) or cross(V(In_D)-Vth_F, 0, 100p, 100m) or cross(V(En_D)-Vth_R, 0, 100p, 100m) or cross(V(En_D)-Vth_F, 0, 100p, 100m)) begin if ((PU_State < 0) & (PD_State < 0)) begin // curent state is 3-state if ((V(En_D) > Vth_R) & (V(In_D) > DC_threshold)) begin // go to high state PU_State = 2; PD_State = -1; end else if ((V(En_D) > Vth_R) & (V(In_D) <= DC_threshold)) begin // go to low state PU_State = -1; PD_State = 2; Tpd_event = $abstime; end end else if ((PU_State > 0) & (PD_State < 0)) begin // curent state is high if ((V(En_D) > Vth_R) & (V(In_D) < Vth_F)) begin // go to low state PU_State = -2; PD_State = 2; Tpd_event = $abstime; end else if (V(En_D) < Vth_F) begin // go to 3-state PU_State = -2; PD_State = -1; end end else if ((PU_State < 0) & (PD_State > 0)) begin // curent state is low if ((V(En_D) > Vth_R) & (V(In_D) > Vth_R)) begin // go to high state PU_State = 2; PD_State = -2; Tpd_event = $abstime; end else if (V(En_D) < Vth_F) begin // go to 3-state PU_State = -1; PD_State = -2; Tpd_event = $abstime; end end $discontinuity(1); //$strobe("Time = %e\tPU_State = %d\tPD_State = %d\tTpd_event = %e", $abstime, PU_State, PD_State, Tpd_event); //========================================================================= end // of Threshold_crossing //========================================================================= // This section contains the simultaneous analog equations to find the // appropriate scaling coefficients according to the state the buffer. //------------------------------------------------------------------------- case (PD_State) -2 : begin // PD is turning off kpd = $table_model($abstime - Tpd_event, Tcm, Kr1, "LL"); //$strobe("Time = %e\tPD_State = -2", $abstime); end -1 : begin // PD is off kpd = Kf1[1]; // 1st point in PD_on table //$strobe("Time = %e\tPD_State = -1", $abstime); end 1 : begin // PD is on kpd = Kr1[1]; // 1st point in PD_off table //$strobe("Time = %e\tPD_State = 1", $abstime); end 2 : begin // PD is tuning on kpd = $table_model($abstime - Tpd_event, Tcm, Kf1, "LL"); //$strobe("Time = %e\tPD_State = 2", $abstime); end default : begin // before any process assignments are available kpd = 0.0; //$strobe("Time = %e\tPD_State = DEFAULT", $abstime); end endcase //========================================================================= // This section contains the analog expressions which calculate // the output currents of the IV curves and C_comp capacitors. //------------------------------------------------------------------------- I(pc) <+ -kI_pc * $table_model(V(pc), Vpc_data, Ipc_data, "LL") + kC_comp_pc*C_comp*ddt(V(pc)); I(pu) <+ kC_comp_pu*C_comp*ddt(V(pu)); I(pd) <+ kI_pd * kpd * $table_model(V(pd), Vpd_data, Ipd_data, "LL") + kC_comp_pd*C_comp*ddt(V(pd)); I(gc) <+ kI_gc * $table_model(V(gc), Vgc_data, Igc_data, "LL") + kC_comp_gc*C_comp*ddt(V(gc)); //------------------------------------------------------------------------- // A simple receiver logic //------------------------------------------------------------------------- if (V(pd) > Vinh) V(Rcv_D) <+ 1.0; else if (V(pd) < Vinl) V(Rcv_D) <+ 0.0; else V(Rcv_D) <+ 0.5; //------------------------------------------------------------------------- end endmodule // IBIS_IO_OPENSINK //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_OPENSOURCE (PU_ref, PD_ref, Pad, In_D, PC_ref, GC_ref) // // DESCRIPTION: // An IBIS open-source buffer, with no pulldown I/V. // The effects modeled are: // - Pulldown and clamp I/V curves with IBIS 2.1 // waveform-based pullup turn-on/off timing. // - Die capacitance seen at the Pad terminal, with distribution // to separate power/ground terminal per IBIS 4.1. // // The Vth_R and Vth_F parameters control how the In_D // terminal behaves. By default these are set to 0.8V // and 0.2V, respectively. The In_D terminal is // triggered to the high state when voltage rises above // Vth_R and to the low state when voltage falls below Vth_F. // // The Pad terminal is driven by the // Pullup I/V table, depending on the low/high // state of the In_D terminal. State changes at the In_D // terminal trigger controlled on/off transitions of the // I/V table, using the waveform and test fixture parameters // to guide the transition. // // Clamp and Pullup currents can be experimentally // scaled using the kI_pc, kI_gc, and kI_pu parameters. // These are not IBIS parameters. // // This IBIS implementation is unable to read IBIS files // directly. Therefore it will be necessary to extract // appropriate parameters from IBIS models to pass to // this model as HDL parameters. IBIS tables are passed // as arrays, with the array lengths given as separate // parameters. The default parameter values in this model // provide a functional example that does not necessarily // model any known "real" buffer. Comments below describe // where to find values in the IBIS file. // // Note that while IBIS contains typical, minimum, and // maximum values for most parameters, this buffer model // implementation accepts only a single value for each // parameter. It will be necessary to maintain seperate // parameter sets for each "corner". // // TERMINALS: // // PU_ref Pullup reference voltage supply // PD_ref Pulldown reference voltage supply // Pad Pad terminal providing input to and output from buffer // In_D Core data signal controlling buffer output // En_D Core signal controlling buffer enable state // PC_ref Power clamp reference voltage supply // GC_ref Ground clamp reference voltage supply // // PARAMETERS: // // C_comp Component die capacitance in farads // Extract IBIS C_comp to get this value. // DEFAULT C_comp = '5.0p' // // kC_comp_pc Fraction of C_comp referenced to PC_ref terminal // Extract IBIS C_comp_power_clamp to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pc = '0.25' // // kC_comp_pu Fraction of C_comp referenced to PU_ref terminal // Extract IBIS C_comp_pullup to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pu = '0.25' // // kC_comp_pd Fraction of C_comp referenced to PD_ref terminal // Extract IBIS C_comp_pulldown to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pd = '0.25' // // kC_comp_gc Fraction of C_comp referenced to GC_ref terminal // Extract IBIS C_comp_ground_clamp to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_gc = '0.25' // // Vinh Minimum threshold voltage for a logic high to be received // Extract IBIS Vinh to get this value. // DEFAULT Vinh = '2.0' // // Vinl Maximum threshold voltage for a logic low to be received // Extract IBIS Vinl to get this value. // DEFAULT Vinl = '0.8' // // Vpc_ref Power clamp reference supply voltage // Extract IBIS [POWER Clamp Reference] to get this value. // Use [Voltage Range] if no [POWER Clamp Reference] // DEFAULT Vpc_ref = '5.0' // // Vpu_ref Pullup reference supply voltage // Extract IBIS [Pullup Reference] to get this value. // Use [Voltage Range] if no [Pullup Reference] // DEFAULT Vpu_ref = '5.0' // // Vpd_ref Pulldown reference supply voltage // Extract IBIS [Pulldown Reference] to get this value. // Use 0 if no [Pulldown Reference] // DEFAULT Vpd_ref = '0.0' // // Vgc_ref Ground clamp reference supply voltage // Extract IBIS [GND Clamp Reference] to get this value. // Use 0 if no [GND Clamp Reference] // DEFAULT Vgc_ref = '0.0' // // IVpc_length Number of elements in the Ipc_data and Vpc_data arrays // Count the number of IBIS [Power clamp] entries to get // this value. // DEFAULT IVpc_length = '4' // // IVpu_length Number of elements in the Ipu_data and Vpu_data arrays // Count the number of IBIS [Pullup] entries to get // this value. // DEFAULT IVpu_length = '4' // // IVgc_length Number of elements in the Igc_data and Vgc_data arrays // Count the number of IBIS [GND clamp] entries to get // this value. // DEFAULT IVgc_length = '4' // // Ipc_data[1:IVpc_length] Array of current values for power clamp I/V // Extract the IBIS [Power clamp] current column to get this. // DEFAULT Ipc_data[1:IVpc_length] = '{ 0.08 0.00 0.00 0.00}' // // Vpc_data[1:IVpc_length] Array of voltage values for power clamp I/V // Extract the IBIS [Power clamp] voltage column to get this. // DEFAULT Vpc_data[1:IVpc_length] = '{-5.00 -1.00 5.00 10.00}' // // Ipu_data[1:IVpu_length] Array of current values for pullup I/V // Extract the IBIS [Pullup] current column to get this. // DEFAULT Ipu_data[1:IVpu_length] = '{-0.08 0.00 0.00 0.00}' // // Vpu_data[1:IVpu_length] Array of voltage values for pullup I/V // Extract the IBIS [Pullup] voltage column to get this. // DEFAULT Vpu_data[1:IVpu_length] = '{-5.00 -1.00 5.00 10.00}' // // Igc_data[1:IVgc_length] Array of current values for ground clamp I/V // Extract the IBIS [GND clamp] current column to get this. // DEFAULT Igc_data[1:IVgc_length] = '{-0.08 0.00 0.00 0.00}' // // Vgc_data[1:IVgc_length] Array of voltage values for ground clamp I/V // Extract the IBIS [GND clamp] voltage column to get this. // DEFAULT Vgc_data[1:IVgc_length] = '{-5.00 -1.00 5.00 10.00}' // // VTr1_length Number of elements in the Tr1 and Vr1 arrays // Count the number of entries in the IBIS [Rising Waveform] // with lower V_fixture to get this value. // DEFAULT VTr1_length = '4' // // VTf1_length Number of elements in the Tf1 and Vf1 arrays // Count the number of entries in the IBIS [Falling Waveform] // with lower V_fixture to get this value. // DEFAULT VTf1_length = '4' // // Vr1_data[1:VTr1_length] // Extract the voltage column from the IBIS [Rising Waveform] // with the lower V_fixture to get this value. // DEFAULT Vr1_data[1:VTr1_length] = '{0.00 0.00 2.50 2.50}' // // Tr1_data[1:VTr1_length] // Extract the time column from the IBIS [Rising Waveform] // with the lower the lower V_fixture to get this value. // DEFAULT Tr1_data[1:VTr1_length] = '{0.00 1.00e-9 2.00e-9 3.00e-9}' // // Vf1_data[1:VTf1_length] // Extract the voltage column from the IBIS [Falling Waveform] // with the lower V_fixture to get this value. // DEFAULT Vf1_data[1:VTf1_length] = '{5.00 5.00 2.50 2.50}' // // Tf1_data[1:VTf1_length] // Extract the time column from the IBIS [Falling Waveform] // with the lower V_fixture to get this value. // DEFAULT Tf1_data[1:VTf1_length] = '{0.00 1.00e-9 2.00e-9 3.00e-9}' // // Vfx_r1 V_fixture value for Rising Waveform 1 // Extract the lower V_fixture value from the IBIS // [Rising Waveform] set. // DEFAULT Vfx_r1 = '0.0' // // Vfx_f1 V_fixture value for Falling Waveform 1 // Extract the lower V_fixture value from the IBIS // [Falling Waveform] set. // DEFAULT Vfx_f1 = '5.0' // // Rfx_r1 R_fixture value for Rising Waveform 1 // Extract the R_fixture value from the IBIS // [Rising Waveform] with lower V_fixture. // DEFAULT Rfx_r1 = '50.0 from (0:inf)' // // Rfx_f1 R_fixture value for Falling Waveform 1 // Extract the R_fixture value from the IBIS // [Falling Waveform] with lower V_fixture. // DEFAULT Rfx_f1 = '50.0 from (0:inf)' // // Vth_R Input threshold for rising edges // Not an IBIS parameter; signals at the In_D and En_D // terminals will be considered to be in the high state // when the voltage is above this value. // DEFAULT Vth_R = '0.8' // // Vth_F Input threshold for falling edges // Not an IBIS parameter; signals at the In_D and En_D // terminals will be considered to be in the low state // when the voltage is below this value. // DEFAULT Vth_F = '0.2' // // Max_dt Maximum dt between simulated time points // Not an IBIS parameter; set to desired simulation resolution. // DEFAULT Max_dt = '1.0e-12 from (0:inf)' // // // INSTANCE CALL EXAMPLES: // // VAMS: // IBIS_OPENSOURCE #( // .C_comp(1.2e-12), // .Vpc_ref(5.0, .Vpu_ref(5.0), .Vpd_ref(0.0), .Vgc_ref(0.0), // .IVpc_length(4), .I_pc({ 0.08, 0.00, 0.00, 0.00}), // .V_pc({-5.00, -1.00, 5.00, 10.00}), // .IVpu_length(4), .I_pu({ 0.10, 0.00, -0.10, -0.20}), // .V_pu({-5.00, 0.00, 5.00, 10.00}), // .IVgc_length(4), .I_gc({-0.10, 0.00, 0.10, 0.20}), // .V_gc({-5.00, 0.00, 5.00, 10.00}), // .VTr1_length(4), .Vr1({0.00, 0.00, 1.66, 1.66}), // .Tr1({0.00, 1.00e-9, 2.00e-9, 3.00e-9}), // .VTf1_length(6), .Vf1({3.33, 3.33, 2.50, 2.50, 1.66, 1.66}), // .Tf1({0.00, 0.50e-9, 0.80e-9, 1.00e-9, 2.00e-9, 3.00e-9}), // B1 (B1_pu, B1_pd, B1_pad, B1_in, B1_pc, B1_gc); // // ========================================================= module IBIS_OPENSOURCE (PU_ref, PD_ref, Pad, In_D, PC_ref, GC_ref); input In_D; electrical In_D; inout Pad, PC_ref, PU_ref, PD_ref, GC_ref; electrical Pad, PC_ref, PU_ref, PD_ref, GC_ref; branch (PC_ref, Pad) pc; // branches driven in model branch (PU_ref, Pad) pu; branch (Pad, PD_ref) pd; branch (Pad, GC_ref) gc; parameter real //--------------------------------------------------------------------------- // IBIS parameters //--------------------------------------------------------------------------- C_comp = 5.0p, // Default C_comp value kC_comp_pc = 0.25, // C_comp splitting coefficients kC_comp_pu = 0.25, kC_comp_pd = 0.25, kC_comp_gc = 0.25, Vpc_ref = 5.0, // Power clamp reference voltage Vpu_ref = 5.0, // Pullup reference voltage Vgc_ref = 0.0; // Ground clamp reference voltage //--------------------------------------------------------------------------- // Vectors of the IV curve tables //--------------------------------------------------------------------------- parameter integer IVpc_length = 4, IVpu_length = 4, IVgc_length = 4; parameter real Ipc_data[1:IVpc_length] = { 0.08, 0.00, 0.00, 0.00}, Vpc_data[1:IVpc_length] = {-5.00, -1.00, 5.00, 10.00}, Ipu_data[1:IVpu_length] = { 0.10, 0.00, -0.10, -0.20}, Vpu_data[1:IVpu_length] = {-5.00, 0.00, 5.00, 10.00}, Igc_data[1:IVgc_length] = {-0.08, 0.00, 0.00, 0.00}, Vgc_data[1:IVgc_length] = {-5.00, -1.00, 5.00, 10.00}; //--------------------------------------------------------------------------- // Vectors of the Vt curve tables //--------------------------------------------------------------------------- parameter integer VTr1_length = 4, VTf1_length = 4; parameter real Vr1_data[1:VTr1_length] = {0.00, 0.00, 2.50, 2.50}, Tr1_data[1:VTr1_length] = {0.00, 1.00e-9, 2.00e-9, 3.00e-9}, Vf1_data[1:VTf1_length] = {2.50, 2.50, 0.00, 0.00}, Tf1_data[1:VTf1_length] = {0.00, 0.50e-9, 0.80e-9, 3.00e-9}; //--------------------------------------------------------------------------- parameter real Vfx_r1 = 0.0, // V_fixture values Vfx_f1 = 0.0, Rfx_r1 = 50.0 from (0:inf), // R_fixture values Rfx_f1 = 50.0 from (0:inf), //--------------------------------------------------------------------------- // Non-IBIS parameters //--------------------------------------------------------------------------- kI_pc = 1.0, // PC current scaling kI_pu = 1.0, // PU current scaling kI_gc = 1.0, // GC current scaling kt_rise = 1.0 from (0:inf), // Rising waveform time scaling kt_fall = 1.0 from (0:inf), // Falling waveform time scaling //--------------------------------------------------------------------------- Max_dt = 1.0e-12 from (0:inf), // Maximum dt between time points Vth_R = 0.8, // Input threshold for rising edges Vth_F = 0.2, // Input threshold for falling edges DC_threshold = (Vth_R+Vth_F)/2.0; // Input threshold during DC analysis //--------------------------------------------------------------------------- // Internal variables //--------------------------------------------------------------------------- // Calculate maximum array length for common time and K_*** tables // and declare the arrays //--------------------------------------------------------------------------- parameter real Max_t = max(kt_rise*Tr1_data[VTr1_length], kt_fall*Tf1_data[VTf1_length]); parameter real Min_t = min(kt_rise*Tr1_data[1], kt_fall*Tf1_data[1]); parameter integer Max_length = ceil((Max_t-Min_t)/Max_dt) + VTr1_length + VTf1_length; real Tcm[1:Max_length]; // Common time axis array real Kr1[1:Max_length]; // Scaling coefficient arrays real Kf1[1:Max_length]; integer PU_State; // Logic state variables real Tpu_event; // Variables to store event time real kpu; // Output current scaling coefficients //--------------------------------------------------------------------------- // variables used in Common_time / Common_wfm / Kcoef "function" //--------------------------------------------------------------------------- integer i; integer Common_length; integer Index_r1; integer Index_f1; integer New_index_r1; integer New_index_f1; real Old_t; real New_t; real Last_t; real Additional_pts; real New_dt; real Tr1_vec[1:VTr1_length]; // Vectors for scaled time real Tf1_vec[1:VTf1_length]; real Vr1_common[1:3]; // Need 3 elements in order to do derivatives real Vf1_common[1:3]; real dVwfm_r1; real dVwfm_f1; real Iout1; real Ipu1; real Igc1; real Ipc1; //=========================================================================== analog begin @(initial_step) begin //======================================================================= // Scale the time axis of the Vt tables //======================================================================= for (i = 1; i <= VTr1_length; i = i + 1) begin Tr1_vec[i] = kt_rise*Tr1_data[i]; end for (i = 1; i <= VTf1_length; i = i + 1) begin Tf1_vec[i] = kt_fall*Tf1_data[i]; end //======================================================================= // This "function" makes a common time axis for all Vt curves and // calculates the corresponding voltage points with linear interpolation // and/or linear extrapolation if necessary. After that it converts the // Vt curves to K coefficients which will be used in the analog equations // to scale the IV curves. The K coefficients are stored in arrays. //----------------------------------------------------------------------- // Initialize variables //----------------------------------------------------------------------- Common_length = 1; Index_r1 = 1; Index_f1 = 1; New_index_r1 = VTr1_length; New_index_f1 = VTf1_length; //----------------------------------------------------------------------- // Put the earliest time value of all given time vectors into "Old_t" //----------------------------------------------------------------------- Old_t = min(Tr1_vec[1], Tf1_vec[1]); //----------------------------------------------------------------------- // Put the latest time value of all given time vectors into "New_t" //----------------------------------------------------------------------- Last_t = max(Tr1_vec[VTr1_length], Tf1_vec[VTf1_length]); New_t = Last_t; //----------------------------------------------------------------------- // Loop until latest time value is reached in each given time vector //----------------------------------------------------------------------- while (Old_t < New_t) begin //--------------------------------------------------------------------- // Save the time value from Old_t in Tcm // and increment Common_length counter //--------------------------------------------------------------------- Tcm[Common_length] = Old_t; Common_length = Common_length + 1; //--------------------------------------------------------------------- // Find which given time vector(s) have the lowest time value and // advance their temporary indexes //--------------------------------------------------------------------- if (Tr1_vec[Index_r1] <= Old_t) New_index_r1 = Index_r1 + 1; if (Tf1_vec[Index_f1] <= Old_t) New_index_f1 = Index_f1 + 1; //--------------------------------------------------------------------- // Find the lowest value at the new indexes in the given vector(s) // and update indexes for next iteration //--------------------------------------------------------------------- if (New_index_r1 <= VTr1_length) begin if (Tr1_vec[New_index_r1] < New_t) New_t = Tr1_vec[New_index_r1]; Index_r1 = New_index_r1; end if (New_index_f1 <= VTf1_length) begin if (Tf1_vec[New_index_f1] < New_t) New_t = Tf1_vec[New_index_f1]; Index_f1 = New_index_f1; end //--------------------------------------------------------------------- // Add points if dt is larger than Max_dt //--------------------------------------------------------------------- if ((New_t-Old_t) > Max_dt) begin Additional_pts = ceil((New_t-Old_t)/Max_dt); New_dt = (New_t-Old_t) / Additional_pts; for (i = 1; i < Additional_pts; i = i + 1) begin //$strobe("\ndif = %e\tAdd = %d\tCL = %d\t T = %e\tNew_dt = ", (New_t-Old_t), Additional_pts, Common_length, Tcm[Common_length-1]+New_dt, New_dt); Tcm[Common_length] = Tcm[Common_length-1] + New_dt; Common_length = Common_length + 1; end end //--------------------------------------------------------------------- // Update variables for next iteration //--------------------------------------------------------------------- Old_t = New_t; New_t = Last_t; //--------------------------------------------------------------------- end // while loop //$strobe("\nCommon length: %d", Common_length); Tcm[Common_length] = Last_t; //======================================================================= //======================================================================= // Calculate the scaling coefficients for each time point along Tcm //----------------------------------------------------------------------- // Store the first voltage point in the common waveform variables //----------------------------------------------------------------------- Vr1_common[2] = $table_model(Tcm[1], Tr1_vec, Vr1_data, "LL"); Vf1_common[2] = $table_model(Tcm[1], Tf1_vec, Vf1_data, "LL"); for (i = 1; i <= Common_length; i = i + 1) begin //----------------------------------------------------------------------- // Store the next point (for the derivative calculations) //----------------------------------------------------------------------- if (i < Common_length) begin Vr1_common[3] = $table_model(Tcm[i+1], Tr1_vec, Vr1_data, "LL"); Vf1_common[3] = $table_model(Tcm[i+1], Tf1_vec, Vf1_data, "LL"); end //$strobe("\nTcom = %e\tR1 = %e\tF1 = %e", Tcm[i], Vr1_common[2], Vf1_common[2]); //--------------------------------------------------------------------- // Calculate the derivative of each waveform for C_comp compensation //--------------------------------------------------------------------- if ((i <= 1) || (i >= Common_length)) begin dVwfm_r1 = 0.0; // Force the end point derivatives to zero dVwfm_f1 = 0.0; end else begin dVwfm_r1 = ((Vr1_common[2] - Vr1_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vr1_common[3] - Vr1_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; dVwfm_f1 = ((Vf1_common[2] - Vf1_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vf1_common[3] - Vf1_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; end //$strobe("dR1 = %e\tdF1 = %e", dVwfm_r1, dVwfm_f1); //--------------------------------------------------------------------- // Calculate intermediate variables and the Kr1 coefficients //--------------------------------------------------------------------- Iout1 = ((Vr1_common[2] - Vfx_r1) / Rfx_r1) + C_comp * dVwfm_r1; Ipc1 = -1.0 * $table_model(Vpc_ref - Vr1_common[2], Vpc_data, Ipc_data, "LL"); Ipu1 = $table_model(Vpu_ref - Vr1_common[2], Vpu_data, Ipu_data, "LL"); Igc1 = $table_model(Vr1_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); // Since these is a rising waveform Kr1 == Kpu_on if (Ipu1 == 0) Kr1[i] = 0.0; else Kr1[i] = (Ipc1 - Igc1 - Iout1) / Ipu1; //--------------------------------------------------------------------- // Calculate intermediate variables and the Kf1 coefficients //--------------------------------------------------------------------- Iout1 = ((Vf1_common[2] - Vfx_f1) / Rfx_f1) + C_comp * dVwfm_f1; Ipc1 = -1.0 * $table_model(Vpc_ref - Vf1_common[2], Vpc_data, Ipc_data, "LL"); Ipu1 = $table_model(Vpu_ref - Vf1_common[2], Vpu_data, Ipu_data, "LL"); Igc1 = $table_model(Vf1_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); // Since these is a falling waveform Kf1 == Kpu_off if (Ipu1 == 0) Kf1[i] = 0.0; else Kf1[i] = (Ipc1 - Igc1 - Iout1) / Ipu1; //$strobe("\nTcom = %e\tKr1 = %e\tKf1 = %e", Tcm[i], Kr1[i], Kf1[i]); //--------------------------------------------------------------------- // Shift points by one index for next iteration (for C_comp compensation) //--------------------------------------------------------------------- Vr1_common[1] = Vr1_common[2]; Vf1_common[1] = Vf1_common[2]; Vr1_common[2] = Vr1_common[3]; Vf1_common[2] = Vf1_common[3]; end // for loop //----------------------------------------------------------------------- // Fill the unused portion of the arrays with reasonable values // to prevent any misbehaving later with $table_model //======================================================================= for (i = Common_length + 1; i <= Max_length; i = i + 1) begin Tcm[i] = Tcm[i-1] + Max_dt; Kr1[i] = Kr1[Common_length]; Kf1[i] = Kf1[Common_length]; end // for loop //----------------------------------------------------------------------- // End of Common_time / Common_wfm / Kcoef "function" //======================================================================= //======================================================================= // Initialize logic state variables and kpu, kpd scaling coefficients //----------------------------------------------------------------------- if (V(In_D) > DC_threshold) begin // high state PU_State = 1; end else begin // low state PU_State = -1; end if (PU_State == 1) begin // Initialization of kpu. kpu = Kr1[Common_length]; // Start with the end of the end else begin // Vt curves for those which kpu = Kf1[Common_length]; // are fully on initially. end //======================================================================= end // @(initial_step) //========================================================================= // Threshold_crossing: process to detect threshold crossings in In_D //------------------------------------------------------------------------- @(cross(V(In_D)-DC_threshold, 0, 100p, 100m) or cross(V(In_D)-Vth_R, 0, 100p, 100m) or cross(V(In_D)-Vth_F, 0, 100p, 100m)) begin if (PU_State > 0) begin // curent state is high if (V(In_D) < Vth_F) begin // go to low state PU_State = -2; Tpu_event = $abstime; end end else if (PU_State < 0) begin // curent state is low if (V(In_D) > Vth_R) begin // go to high state PU_State = 2; Tpu_event = $abstime; end end $discontinuity(1); //$strobe("Time = %e\tPU_State = %d\tTpu_event = %e", $abstime, PU_State, Tpu_event); //========================================================================= end // of Threshold_crossing //========================================================================= // This section contains the simultaneous analog equations to find the // appropriate scaling coefficients according to the state the buffer. //------------------------------------------------------------------------- case (PU_State) -2 : begin // PU is turning off kpu = $table_model($abstime - Tpu_event, Tcm, Kf1, "LL"); //$strobe("Time = %e\tPU_State = -2", $abstime); end -1 : begin // PU is off kpu = Kr1[1]; // 1st point in PU_on table //$strobe("Time = %e\tPU_State = -1", $abstime); end 1 : begin // PU is on kpu = Kf1[1]; // 1st point in PU_off table //$strobe("Time = %e\tPU_State = 1", $abstime); end 2 : begin // PU is tuning on kpu = $table_model($abstime - Tpu_event, Tcm, Kr1, "LL"); //$strobe("Time = %e\tPU_State = 2", $abstime); end default : begin // before any process assignments are available kpu = 0.0; //$strobe("Time = %e\tPU_State = DEFAULT", $abstime); end endcase //========================================================================= // This section contains the analog expressions which calculate // the output currents of the IV curves and C_comp capacitors. //------------------------------------------------------------------------- I(pc) <+ -kI_pc * $table_model(V(pc), Vpc_data, Ipc_data, "LL") + kC_comp_pc*C_comp*ddt(V(pc)); I(pu) <+ -kI_pu * kpu * $table_model(V(pu), Vpu_data, Ipu_data, "LL") + kC_comp_pu*C_comp*ddt(V(pu)); I(pd) <+ kC_comp_pd*C_comp*ddt(V(pd)); I(gc) <+ kI_gc * $table_model(V(gc), Vgc_data, Igc_data, "LL") + kC_comp_gc*C_comp*ddt(V(gc)); //------------------------------------------------------------------------- end endmodule // IBIS_OPENSOURCE //============================================================================= //============================================================================= // =========================================moduledoc====== // // MODULE: IBIS_IO_OPENSOURCE (PU_ref, PD_ref, Pad, In_D, En_D, Rcv_D, PC_ref, GC_ref) // // DESCRIPTION: // An IBIS open-source I/O buffer, with no pulldown I/V. // The effects modeled are: // - Pullup and clamp I/V curves with IBIS 2.1 // waveform-based pullup turn-on/off timing. // - Die capacitance seen at the Pad terminal, with distribution // to separate power/ground terminal per IBIS 4.1. // - Threshold based received logic detection. // // The Vth_R and Vth_F parameters control how the In_D and // En_D terminals behave. By default these are set to 0.8V // and 0.2V, respectively. The In_D and En_D terminals are // triggered to the high state when voltage rises above // Vth_R and to the low state when voltage falls below Vth_F. // For DC analyses the DC_threshold parameter is used, since // the hysteresis implemented using Vth_R and Vth_F is not useful // in DC analysis. This defaults to the mid-point between // Vth_R and Vth_F. // // The Pad terminal is driven by the // Pullup I/V table, depending on the low/high // state of the In_D terminal. State changes at the In_D // terminal trigger controlled on/off transitions of the // I/V table, using the waveform and test fixture parameters // to guide the transition. // // Clamp and Pullup currents can be experimentally // scaled using the kI_pc, kI_gc, and kI_pu parameters. // These are not IBIS parameters. // // This IBIS implementation is unable to read IBIS files // directly. Therefore it will be necessary to extract // appropriate parameters from IBIS models to pass to // this model as HDL parameters. IBIS tables are passed // as arrays, with the array lengths given as separate // parameters. The default parameter values in this model // provide a functional example that does not necessarily // model any known "real" buffer. Comments below describe // where to find values in the IBIS file. // // Note that while IBIS contains typical, minimum, and // maximum values for most parameters, this buffer model // implementation accepts only a single value for each // parameter. It will be necessary to maintain seperate // parameter sets for each "corner". // // TERMINALS: // // PU_ref Pullup reference voltage supply // PD_ref Pulldown reference voltage supply // Pad Pad terminal providing input to and output from buffer // In_D Core data signal controlling buffer output // En_D Core signal controlling buffer enable state // Rcv_D Received data from buffer to core logic // PC_ref Power clamp reference voltage supply // GC_ref Ground clamp reference voltage supply // // PARAMETERS: // // C_comp Component die capacitance in farads // Extract IBIS C_comp to get this value. // DEFAULT C_comp = '5.0p' // // kC_comp_pc Fraction of C_comp referenced to PC_ref terminal // Extract IBIS C_comp_power_clamp to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pc = '0.25' // // kC_comp_pu Fraction of C_comp referenced to PU_ref terminal // Extract IBIS C_comp_pullup to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pu = '0.25' // // kC_comp_pd Fraction of C_comp referenced to PD_ref terminal // Extract IBIS C_comp_pulldown to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_pd = '0.25' // // kC_comp_gc Fraction of C_comp referenced to GC_ref terminal // Extract IBIS C_comp_ground_clamp to get this value. // The sum of all kC_comp_* values should be 1.0. // DEFAULT k_C_comp_gc = '0.25' // // Vinh Minimum threshold voltage for a logic high to be received // Extract IBIS Vinh to get this value. // DEFAULT Vinh = '2.0' // // Vinl Maximum threshold voltage for a logic low to be received // Extract IBIS Vinl to get this value. // DEFAULT Vinl = '0.8' // // Vpc_ref Power clamp reference supply voltage // Extract IBIS [POWER Clamp Reference] to get this value. // Use [Voltage Range] if no [POWER Clamp Reference] // DEFAULT Vpc_ref = '5.0' // // Vpu_ref Pullup reference supply voltage // Extract IBIS [Pullup Reference] to get this value. // Use [Voltage Range] if no [Pullup Reference] // DEFAULT Vpu_ref = '5.0' // // Vpd_ref Pulldown reference supply voltage // Extract IBIS [Pulldown Reference] to get this value. // Use 0 if no [Pulldown Reference] // DEFAULT Vpd_ref = '0.0' // // Vgc_ref Ground clamp reference supply voltage // Extract IBIS [GND Clamp Reference] to get this value. // Use 0 if no [GND Clamp Reference] // DEFAULT Vgc_ref = '0.0' // // IVpc_length Number of elements in the Ipc_data and Vpc_data arrays // Count the number of IBIS [Power clamp] entries to get // this value. // DEFAULT IVpc_length = '4' // // IVpu_length Number of elements in the Ipu_data and Vpu_data arrays // Count the number of IBIS [Pullup] entries to get // this value. // DEFAULT IVpu_length = '4' // // IVpd_length Number of elements in the Ipd_data and Vpd_data arrays // Count the number of IBIS [Pulldown] entries to get // this value. // DEFAULT IVpd_length = '4' // // IVgc_length Number of elements in the Igc_data and Vgc_data arrays // Count the number of IBIS [GND clamp] entries to get // this value. // DEFAULT IVgc_length = '4' // // Ipc_data[1:IVpc_length] Array of current values for power clamp I/V // Extract the IBIS [Power clamp] current column to get this. // DEFAULT Ipc_data[1:IVpc_length] = '{ 0.08 0.00 0.00 0.00}' // // Vpc_data[1:IVpc_length] Array of voltage values for power clamp I/V // Extract the IBIS [Power clamp] voltage column to get this. // DEFAULT Vpc_data[1:IVpc_length] = '{-5.00 -1.00 5.00 10.00}' // // Ipu_data[1:IVpu_length] Array of current values for pullup I/V // Extract the IBIS [Pullup] current column to get this. // DEFAULT Ipu_data[1:IVpu_length] = '{-0.08 0.00 0.00 0.00}' // // Vpu_data[1:IVpu_length] Array of voltage values for pullup I/V // Extract the IBIS [Pullup] voltage column to get this. // DEFAULT Vpu_data[1:IVpu_length] = '{-5.00 -1.00 5.00 10.00}' // // Igc_data[1:IVgc_length] Array of current values for ground clamp I/V // Extract the IBIS [GND clamp] current column to get this. // DEFAULT Igc_data[1:IVgc_length] = '{-0.08 0.00 0.00 0.00}' // // Vgc_data[1:IVgc_length] Array of voltage values for ground clamp I/V // Extract the IBIS [GND clamp] voltage column to get this. // DEFAULT Vgc_data[1:IVgc_length] = '{-5.00 -1.00 5.00 10.00}' // // VTr1_length Number of elements in the Tr1 and Vr1 arrays // Count the number of entries in the IBIS [Rising Waveform] // with V_fixture = 0 to get this value. // DEFAULT VTr1_length = '4' // // VTf1_length Number of elements in the Tf1 and Vf1 arrays // Count the number of entries in the IBIS [Falling Waveform] // with the lower V_fixture to get this value. // DEFAULT VTf1_length = '4' // // Vr1_data[1:VTr1_length] // Extract the voltage column from the IBIS [Rising Waveform] // with the lower V_fixture to get this value. // DEFAULT Vr1_data[1:VTr1_length] = '{0.00 0.00 2.50 2.50}' // // Tr1_data[1:VTr1_length] // Extract the time column from the IBIS [Rising Waveform] // with the lower the lower V_fixture to get this value. // DEFAULT Tr1_data[1:VTr1_length] = '{0.00 1.00e-9 2.00e-9 3.00e-9}' // // Vf1_data[1:VTf1_length] // Extract the voltage column from the IBIS [Falling Waveform] // with the lower V_fixture to get this value. // DEFAULT Vf1_data[1:VTf1_length] = '{5.00 5.00 2.50 2.50}' // // Tf1_data[1:VTf1_length] // Extract the time column from the IBIS [Falling Waveform] // with the lower V_fixture to get this value. // DEFAULT Tf1_data[1:VTf1_length] = '{0.00 1.00e-9 2.00e-9 3.00e-9}' // // Vfx_r1 V_fixture value for Rising Waveform 1 // Extract the lower V_fixture value from the IBIS // [Rising Waveform] set. // DEFAULT Vfx_r1 = '0.0' // // Vfx_f1 V_fixture value for Falling Waveform 1 // Extract the lower V_fixture value from the IBIS // [Falling Waveform] set. // DEFAULT Vfx_f1 = '5.0' // // Rfx_r1 R_fixture value for Rising Waveform 1 // Extract the R_fixture value from the IBIS // [Rising Waveform] with lower V_fixture. // DEFAULT Rfx_r1 = '50.0 from (0:inf)' // // Rfx_f1 R_fixture value for Falling Waveform 1 // Extract the R_fixture value from the IBIS // [Falling Waveform] with lower V_fixture. // DEFAULT Rfx_f1 = '50.0 from (0:inf)' // // Vth_R Input threshold for rising edges // Not an IBIS parameter; signals at the In_D and En_D // terminals will be considered to be in the high state // when the voltage is above this value. // DEFAULT Vth_R = '0.8' // // Vth_F Input threshold for falling edges // Not an IBIS parameter; signals at the In_D and En_D // terminals will be considered to be in the low state // when the voltage is below this value. // DEFAULT Vth_F = '0.2' // // Max_dt Maximum delta time between simulated time points // Not an IBIS parameter; set to desired simulation resolution. // DEFAULT Max_dt = '1.0e-12 from (0:inf)' // // kI_pc Scaling factor for power clamp current values. // DEFAULT kI_pc = '1.0' // // kI_pu Scaling factor for pullup clamp current values. // DEFAULT kI_pu = '1.0' // // kI_gc Scaling factor for ground clamp current values. // DEFAULT kI_gc = '1.0' // // kt_rise Scaling factor for [Rising waveform] time values. // DEFAULT kt_rise = '1.0 from (0:inf)' // // kt_fall Scaling factor for [Falling waveform] time values. // DEFAULT kt_fall = '1.0 from (0:inf)' // // DC_threshold Input threshold during DC analysis // DEFAULT DC_threshold = '(Vth_R+Vth_F)/2.0' // // // INSTANCE CALL EXAMPLES: // // VAMS: // IBIS_IO_OPENSOURCE #( // .C_comp(1.2e-12), .Vinh(2.0), .Vinl(0.8), // .Vpc_ref(5.0, .Vpu_ref(5.0), .Vpd_ref(0.0), .Vgc_ref(0.0), // .IVpc_length(4), .I_pc({ 0.08, 0.00, 0.00, 0.00}), // .V_pc({-5.00, -1.00, 5.00, 10.00}), // .IVpu_length(4), .I_pu({ 0.10, 0.00, -0.10, -0.20}), // .V_pu({-5.00, 0.00, 5.00, 10.00}), // .IVgc_length(4), .I_gc({-0.10, 0.00, 0.10, 0.20}), // .V_gc({-5.00, 0.00, 5.00, 10.00}), // .VTr1_length(4), .Vr1({0.00, 0.00, 1.66, 1.66}), // .Tr1({0.00, 1.00e-9, 2.00e-9, 3.00e-9}), // .VTf1_length(6), .Vf1({3.33, 3.33, 2.50, 2.50, 1.66, 1.66}), // .Tf1({0.00, 0.50e-9, 0.80e-9, 1.00e-9, 2.00e-9, 3.00e-9}), // B1 (B1_pu, B1_pd, B1_pad, B1_in, B1_en, B1_a, B1_pc, B1_gc); // // ========================================================= module IBIS_IO_OPENSOURCE (PU_ref, PD_ref, Pad, In_D, En_D, Rcv_D, PC_ref, GC_ref); input In_D, En_D; electrical In_D, En_D; output Rcv_D; electrical Rcv_D; inout Pad, PC_ref, PU_ref, PD_ref, GC_ref; electrical Pad, PC_ref, PU_ref, PD_ref, GC_ref; branch (PC_ref, Pad) pc; // branches driven in model branch (PU_ref, Pad) pu; branch (Pad, PD_ref) pd; branch (Pad, GC_ref) gc; parameter real //--------------------------------------------------------------------------- // IBIS parameters //--------------------------------------------------------------------------- C_comp = 5.0p, // Default C_comp value kC_comp_pc = 0.25, // C_comp splitting coefficients kC_comp_pu = 0.25, kC_comp_pd = 0.25, kC_comp_gc = 0.25, Vinh = 2.0, // Default Vinh value Vinl = 0.8, // Default Vinl value Vpc_ref = 5.0, // Power clamp reference voltage Vpu_ref = 5.0, // Pullup reference voltage Vgc_ref = 0.0; // Ground clamp reference voltage //--------------------------------------------------------------------------- // Vectors of the IV curve tables //--------------------------------------------------------------------------- parameter integer IVpc_length = 4, IVpu_length = 4, IVgc_length = 4; parameter real Ipc_data[1:IVpc_length] = { 0.08, 0.00, 0.00, 0.00}, Vpc_data[1:IVpc_length] = {-5.00, -1.00, 5.00, 10.00}, Ipu_data[1:IVpu_length] = { 0.10, 0.00, -0.10, -0.20}, Vpu_data[1:IVpu_length] = {-5.00, 0.00, 5.00, 10.00}, Igc_data[1:IVgc_length] = {-0.08, 0.00, 0.00, 0.00}, Vgc_data[1:IVgc_length] = {-5.00, -1.00, 5.00, 10.00}; //--------------------------------------------------------------------------- // Vectors of the Vt curve tables //--------------------------------------------------------------------------- parameter integer VTr1_length = 4, VTf1_length = 4; parameter real Vr1_data[1:VTr1_length] = {0.00, 0.00, 2.50, 2.50}, Tr1_data[1:VTr1_length] = {0.00, 1.00e-9, 2.00e-9, 3.00e-9}, Vf1_data[1:VTf1_length] = {2.50, 2.50, 0.00, 0.00}, Tf1_data[1:VTf1_length] = {0.00, 0.50e-9, 0.80e-9, 3.00e-9}; //--------------------------------------------------------------------------- parameter real Vfx_r1 = 0.0, // V_fixture values Vfx_f1 = 0.0, Rfx_r1 = 50.0 from (0:inf), // R_fixture values Rfx_f1 = 50.0 from (0:inf), //--------------------------------------------------------------------------- // Non-IBIS parameters //--------------------------------------------------------------------------- kI_pc = 1.0, // PC current scaling kI_pu = 1.0, // PU current scaling kI_gc = 1.0, // GC current scaling kt_rise = 1.0 from (0:inf), // Rising waveform time scaling kt_fall = 1.0 from (0:inf), // Falling waveform time scaling //--------------------------------------------------------------------------- Max_dt = 1.0e-12 from (0:inf), // Maximum dt between time points Vth_R = 0.8, // Input threshold for rising edges Vth_F = 0.2, // Input threshold for falling edges DC_threshold = (Vth_R+Vth_F)/2.0; // Input threshold during DC analysis //--------------------------------------------------------------------------- // Internal variables //--------------------------------------------------------------------------- // Calculate maximum array length for common time and K_*** tables // and declare the arrays //--------------------------------------------------------------------------- parameter real Max_t = max(kt_rise*Tr1_data[VTr1_length], kt_fall*Tf1_data[VTf1_length]); parameter real Min_t = min(kt_rise*Tr1_data[1], kt_fall*Tf1_data[1]); parameter integer Max_length = ceil((Max_t-Min_t)/Max_dt) + VTr1_length + VTf1_length; real Tcm[1:Max_length]; // Common time axis array real Kr1[1:Max_length]; // Scaling coefficient arrays real Kf1[1:Max_length]; integer PU_State; // Logic state variables integer PD_State; real Tpu_event; // Variables to store event time real kpu; // Output current scaling coefficients //--------------------------------------------------------------------------- // variables used in Common_time / Common_wfm / Kcoef "function" //--------------------------------------------------------------------------- integer i; integer Common_length; integer Index_r1; integer Index_f1; integer New_index_r1; integer New_index_f1; real Old_t; real New_t; real Last_t; real Additional_pts; real New_dt; real Tr1_vec[1:VTr1_length]; // Vectors for scaled time real Tf1_vec[1:VTf1_length]; real Vr1_common[1:3]; // Need 3 elements in order to do derivatives real Vf1_common[1:3]; real dVwfm_r1; real dVwfm_f1; real Iout1; real Ipu1; real Igc1; real Ipc1; //=========================================================================== analog begin @(initial_step) begin //======================================================================= // Scale the time axis of the Vt tables //======================================================================= for (i = 1; i <= VTr1_length; i = i + 1) begin Tr1_vec[i] = kt_rise*Tr1_data[i]; end for (i = 1; i <= VTf1_length; i = i + 1) begin Tf1_vec[i] = kt_fall*Tf1_data[i]; end //======================================================================= // This "function" makes a common time axis for all Vt curves and // calculates the corresponding voltage points with linear interpolation // and/or linear extrapolation if necessary. After that it converts the // Vt curves to K coefficients which will be used in the analog equations // to scale the IV curves. The K coefficients are stored in arrays. //----------------------------------------------------------------------- // Initialize variables //----------------------------------------------------------------------- Common_length = 1; Index_r1 = 1; Index_f1 = 1; New_index_r1 = VTr1_length; New_index_f1 = VTf1_length; //----------------------------------------------------------------------- // Put the earliest time value of all given time vectors into "Old_t" //----------------------------------------------------------------------- Old_t = min(Tr1_vec[1], Tf1_vec[1]); //----------------------------------------------------------------------- // Put the latest time value of all given time vectors into "New_t" //----------------------------------------------------------------------- Last_t = max(Tr1_vec[VTr1_length], Tf1_vec[VTf1_length]); New_t = Last_t; //----------------------------------------------------------------------- // Loop until latest time value is reached in each given time vector //----------------------------------------------------------------------- while (Old_t < New_t) begin //--------------------------------------------------------------------- // Save the time value from Old_t in Tcm // and increment Common_length counter //--------------------------------------------------------------------- Tcm[Common_length] = Old_t; Common_length = Common_length + 1; //--------------------------------------------------------------------- // Find which given time vector(s) have the lowest time value and // advance their temporary indexes //--------------------------------------------------------------------- if (Tr1_vec[Index_r1] <= Old_t) New_index_r1 = Index_r1 + 1; if (Tf1_vec[Index_f1] <= Old_t) New_index_f1 = Index_f1 + 1; //--------------------------------------------------------------------- // Find the lowest value at the new indexes in the given vector(s) // and update indexes for next iteration //--------------------------------------------------------------------- if (New_index_r1 <= VTr1_length) begin if (Tr1_vec[New_index_r1] < New_t) New_t = Tr1_vec[New_index_r1]; Index_r1 = New_index_r1; end if (New_index_f1 <= VTf1_length) begin if (Tf1_vec[New_index_f1] < New_t) New_t = Tf1_vec[New_index_f1]; Index_f1 = New_index_f1; end //--------------------------------------------------------------------- // Add points if dt is larger than Max_dt //--------------------------------------------------------------------- if ((New_t-Old_t) > Max_dt) begin Additional_pts = ceil((New_t-Old_t)/Max_dt); New_dt = (New_t-Old_t) / Additional_pts; for (i = 1; i < Additional_pts; i = i + 1) begin //$strobe("\ndif = %e\tAdd = %d\tCL = %d\t T = %e\tNew_dt = ", (New_t-Old_t), Additional_pts, Common_length, Tcm[Common_length-1]+New_dt, New_dt); Tcm[Common_length] = Tcm[Common_length-1] + New_dt; Common_length = Common_length + 1; end end //--------------------------------------------------------------------- // Update variables for next iteration //--------------------------------------------------------------------- Old_t = New_t; New_t = Last_t; //--------------------------------------------------------------------- end // while loop //$strobe("\nCommon length: %d", Common_length); Tcm[Common_length] = Last_t; //======================================================================= //======================================================================= // Calculate the scaling coefficients for each time point along Tcm //----------------------------------------------------------------------- // Store the first voltage point in the common waveform variables //----------------------------------------------------------------------- Vr1_common[2] = $table_model(Tcm[1], Tr1_vec, Vr1_data, "LL"); Vf1_common[2] = $table_model(Tcm[1], Tf1_vec, Vf1_data, "LL"); for (i = 1; i <= Common_length; i = i + 1) begin //----------------------------------------------------------------------- // Store the next point (for the derivative calculations) //----------------------------------------------------------------------- if (i < Common_length) begin Vr1_common[3] = $table_model(Tcm[i+1], Tr1_vec, Vr1_data, "LL"); Vf1_common[3] = $table_model(Tcm[i+1], Tf1_vec, Vf1_data, "LL"); end //$strobe("\nTcom = %e\tR1 = %e\tF1 = %e", Tcm[i], Vr1_common[2], Vf1_common[2]); //--------------------------------------------------------------------- // Calculate the derivative of each waveform for C_comp compensation //--------------------------------------------------------------------- if ((i <= 1) || (i >= Common_length)) begin dVwfm_r1 = 0.0; // Force the end point derivatives to zero dVwfm_f1 = 0.0; end else begin dVwfm_r1 = ((Vr1_common[2] - Vr1_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vr1_common[3] - Vr1_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; dVwfm_f1 = ((Vf1_common[2] - Vf1_common[1]) / (Tcm[i] - Tcm[i-1]) + (Vf1_common[3] - Vf1_common[2]) / (Tcm[i+1] - Tcm[i])) / 2.0; end //$strobe("dR1 = %e\tdF1 = %e", dVwfm_r1, dVwfm_f1); //--------------------------------------------------------------------- // Calculate intermediate variables and the Kr1 coefficients //--------------------------------------------------------------------- Iout1 = ((Vr1_common[2] - Vfx_r1) / Rfx_r1) + C_comp * dVwfm_r1; Ipc1 = -1.0 * $table_model(Vpc_ref - Vr1_common[2], Vpc_data, Ipc_data, "LL"); Ipu1 = $table_model(Vpu_ref - Vr1_common[2], Vpu_data, Ipu_data, "LL"); Igc1 = $table_model(Vr1_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); // Since these is a rising waveform Kr1 == Kpu_on if (Ipu1 == 0) Kr1[i] = 0.0; else Kr1[i] = (Ipc1 - Igc1 - Iout1) / Ipu1; //--------------------------------------------------------------------- // Calculate intermediate variables and the Kf1 coefficients //--------------------------------------------------------------------- Iout1 = ((Vf1_common[2] - Vfx_f1) / Rfx_f1) + C_comp * dVwfm_f1; Ipc1 = -1.0 * $table_model(Vpc_ref - Vf1_common[2], Vpc_data, Ipc_data, "LL"); Ipu1 = $table_model(Vpu_ref - Vf1_common[2], Vpu_data, Ipu_data, "LL"); Igc1 = $table_model(Vf1_common[2] - Vgc_ref, Vgc_data, Igc_data, "LL"); // Since these is a falling waveform Kf1 == Kpu_off if (Ipu1 == 0) Kf1[i] = 0.0; else Kf1[i] = (Ipc1 - Igc1 - Iout1) / Ipu1; //$strobe("\nTcom = %e\tKr1 = %e\tKf1 = %e", Tcm[i], Kr1[i], Kf1[i]); //--------------------------------------------------------------------- // Shift points by one index for next iteration (for C_comp compensation) //--------------------------------------------------------------------- Vr1_common[1] = Vr1_common[2]; Vf1_common[1] = Vf1_common[2]; Vr1_common[2] = Vr1_common[3]; Vf1_common[2] = Vf1_common[3]; end // for loop //----------------------------------------------------------------------- // Fill the unused portion of the arrays with reasonable values // to prevent any misbehaving later with $table_model //======================================================================= for (i = Common_length + 1; i <= Max_length; i = i + 1) begin Tcm[i] = Tcm[i-1] + Max_dt; Kr1[i] = Kr1[Common_length]; Kf1[i] = Kf1[Common_length]; end // for loop //----------------------------------------------------------------------- // End of Common_time / Common_wfm / Kcoef "function" //======================================================================= //======================================================================= // Initialize logic state variables and kpu, kpd scaling coefficients //----------------------------------------------------------------------- if ((V(En_D) > DC_threshold) & (V(In_D) > DC_threshold)) begin // high state PU_State = 1; PD_State = -1; end else if ((V(En_D) > DC_threshold) & (V(In_D) <= DC_threshold)) begin // low state PU_State = -1; PD_State = 1; end else begin // 3-state PU_State = -1; PD_State = -1; end if (PU_State == 1) begin // Initialization of kpu, kpd. kpu = Kr1[Common_length]; // Start with the end of the end else begin // Vt curves for those which kpu = Kf1[Common_length]; // are fully on initially. end //======================================================================= end // @(initial_step) //========================================================================= // Threshold_crossing: process to detect threshold crossings in In_D, En_D //------------------------------------------------------------------------- @(cross(V(In_D)-DC_threshold, 0, 100p, 100m) or cross(V(In_D)-Vth_R, 0, 100p, 100m) or cross(V(In_D)-Vth_F, 0, 100p, 100m) or cross(V(En_D)-Vth_R, 0, 100p, 100m) or cross(V(En_D)-Vth_F, 0, 100p, 100m)) begin if ((PU_State < 0) & (PD_State < 0)) begin // curent state is 3-state if ((V(En_D) > Vth_R) & (V(In_D) > DC_threshold)) begin // go to high state PU_State = 2; PD_State = -1; Tpu_event = $abstime; end else if ((V(En_D) > Vth_R) & (V(In_D) <= DC_threshold)) begin // go to low state PU_State = -1; PD_State = 2; end end else if ((PU_State > 0) & (PD_State < 0)) begin // curent state is high if ((V(En_D) > Vth_R) & (V(In_D) < Vth_F)) begin // go to low state PU_State = -2; PD_State = 2; Tpu_event = $abstime; end else if (V(En_D) < Vth_F) begin // go to 3-state PU_State = -2; PD_State = -1; Tpu_event = $abstime; end end else if ((PU_State < 0) & (PD_State > 0)) begin // curent state is low if ((V(En_D) > Vth_R) & (V(In_D) > Vth_R)) begin // go to high state PU_State = 2; PD_State = -2; Tpu_event = $abstime; end else if (V(En_D) < Vth_F) begin // go to 3-state PU_State = -1; PD_State = -2; end end $discontinuity(1); //$strobe("Time = %e\tPU_State = %d\tPD_State = %d\tTpu_event = %e", $abstime, PU_State, PD_State, Tpu_event); //========================================================================= end // of Threshold_crossing //========================================================================= // This section contains the simultaneous analog equations to find the // appropriate scaling coefficients according to the state the buffer. //------------------------------------------------------------------------- case (PU_State) -2 : begin // PU is turning off kpu = $table_model($abstime - Tpu_event, Tcm, Kf1, "LL"); //$strobe("Time = %e\tPU_State = -2", $abstime); end -1 : begin // PU is off kpu = Kr1[1]; // 1st point in PU_on table //$strobe("Time = %e\tPU_State = -1", $abstime); end 1 : begin // PU is on kpu = Kf1[1]; // 1st point in PU_off table //$strobe("Time = %e\tPU_State = 1", $abstime); end 2 : begin // PU is tuning on kpu = $table_model($abstime - Tpu_event, Tcm, Kr1, "LL"); //$strobe("Time = %e\tPU_State = 2", $abstime); end default : begin // before any process assignments are available kpu = 0.0; //$strobe("Time = %e\tPU_State = DEFAULT", $abstime); end endcase //========================================================================= // This section contains the analog expressions which calculate // the output currents of the IV curves and C_comp capacitors. //------------------------------------------------------------------------- I(pc) <+ -kI_pc * $table_model(V(pc), Vpc_data, Ipc_data, "LL") + kC_comp_pc*C_comp*ddt(V(pc)); I(pu) <+ -kI_pu * kpu * $table_model(V(pu), Vpu_data, Ipu_data, "LL") + kC_comp_pu*C_comp*ddt(V(pu)); I(pd) <+ kC_comp_pd*C_comp*ddt(V(pd)); I(gc) <+ kI_gc * $table_model(V(gc), Vgc_data, Igc_data, "LL") + kC_comp_gc*C_comp*ddt(V(gc)); //------------------------------------------------------------------------- // A simple receiver logic //------------------------------------------------------------------------- if (V(pd) > Vinh) V(Rcv_D) <+ 1.0; else if (V(pd) < Vinl) V(Rcv_D) <+ 0.0; else V(Rcv_D) <+ 0.5; //------------------------------------------------------------------------- end endmodule // IBIS_IO_OPENSOURCE //============================================================================= //=============================================================================