// This is -*- Verilog-A -*-

// ============================================================================
//
// (c) Copyright 2005, All Rights Reserved, Philips Electronics N.V.
//
//
// Version: August 22, 2005
//
// ============================================================================

// Spice primitives
// Verilog-AMS LRM 2.0 Annex E "SPICE compatibility"

`include "disciplines.vams"
`include "constants.vams"

`ifdef VPULSE_VA
`else
`define VPULSE_VA 1

/**
 * @brief pulse waveform voltage source.
 *
 * @param dc		DC voltage level in [V].
 * @param mag		AC small-signal source magnitude in [V].
 * @param phase		AC small-signal source phase in [rad].
 * @param val0		pulse waveform initial value in [V].
 * @param val1		pulse waveform second value in [V].
 * @param td		pulse delay time in [s].
 * @param rise		pulse rise time in [s].
 * @param fall		pulse fall time in [s].
 * @param width		pulse width in [s].
 * @param period	pulse period in [s] or 0 if not periodic.
 */

module Vpulse (p, n);
inout p, n;
electrical p, n;
parameter dc = 0.0;
parameter mag = 1.0;
parameter phase = 0.0;
parameter val0 = 0.0;
parameter val1 = 0.0;
parameter td = 0.0 from [0:inf);
parameter rise = 0.0 from [0:inf);
parameter fall = 0.0 from [0:inf);
parameter width = 0.0 from [0:inf);
parameter period = 0.0 from [0:inf);

real dc_val, expr;

analog begin

  @(initial_step) begin
  
    if ((period > 0) && (td + rise + width + fall > period)) begin
      $strobe("ERROR: period of %m is too small for given waveform.");
      $finish;
    end
  
    // If the DC value is not given, we make it equal to the val0 value,
    // so the DC solution is continuous with any subsequent transient.
    // We assume the DC value not given if it is 0, and val0 is not 0.
    if ((dc == 0.0) && (val0 != 0.0))
      dc_val = val0;
    else
      dc_val = dc;

  end

  V(p, n) <+ ac_stim("ac", mag, phase);
  
  if (analysis("dc","ic","static"))

    V(p, n) <+ dc_val;

  else if (analysis("tran")) begin

    @(timer(0, period))
      expr = val1;

    @(timer(width, period))
      expr = val0;

    V(p, n) <+ transition(expr, td, rise, width, fall);

  end

end

endmodule // Vpulse

`endif
