Menu ▾ ▴

#883 PSpice VSWITCH (XSPICE pswitch) gives impossible AC gain (~4.6e15) in a passive divider, ps/ltps mode

v1.0 (example)
open-accepted
5
4 hours ago
1 day ago
No

Summary
In PSpice compatibility mode (ps or ltps), a voltage-controlled switch defined with a PSpice VSWITCH model, which ngspice maps to the XSPICE pswitch code model, returns a physically impossible small-signal AC gain in a purely passive network. A switch biased mid-way between VOFF and VON feeding a 1 kOhm load should give a transfer of 0.5; ngspice reports about 4.6e15. LTspice gives 0.5 for the same circuit.

Version / platform
ngspice-47 release, built from ngspice-47.tar.gz (./configure --without-x --with-readline=no), Linux x86-64. Not yet re-tested against current git master.

Reproducer (two files in the same directory; .spiceinit contains set ngbehavior=ps)

v_switch_signal.cir:
Independent PSpice switch signal transfer
.include "v_switch_signal.lib"
VDR IN 0 DC .1 AC 1
XU IN OUT DEMO
.save all
.ac lin 3 .99 1.01
.meas ac m_re FIND vr(OUT) AT=1
.meas ac m_im FIND vi(OUT) AT=1
.end

v_switch_signal.lib:
.subckt DEMO IN OUT
VCTRL CTRL 0 .1
S1 IN OUT CTRL 0 MODE
.model MODE VSWITCH(RON=100 ROFF=10000 VON=.2 VOFF=0)
R1 OUT 0 1k
.ends DEMO

Run: ngspice -b v_switch_signal.cir

Expected
The control voltage (0.1 V) is half-way between VOFF (0 V) and VON (0.2 V), so the PSpice switch resistance is sqrt(RON*ROFF) = 1 kOhm, a 1k/1k divider: m_re = 0.5, m_im = 0. LTspice 26.1.1 gives m_re = 0.50000000025.

Actual
ngspice-47 in ps and ltps modes: m_re = 4.61169e15, m_im = 0. (Default and lt modes reject the deck.)

Notes

  • The expanded listing and loader tracing show the switch is the XSPICE pswitch code model, not aswitch.
  • In a local diagnostic build, making pswitch's AC (small-signal) partials consistent in sign and loading with its DC partials restored the expected 0.5 for this circuit. That points at the AC load of pswitch, but I haven't verified it as a complete fix.
  • Found while running vendor op-amp macromodels that use VSWITCH internally: their open-loop gain collapses in ngspice's AC analysis while LTspice gives the expected value.
2 Attachments

Discussion

  • Holger Vogt

    Holger Vogt - 10 hours ago
    • status: open --> open-accepted
    • assigned_to: Holger Vogt
     
  • Holger Vogt

    Holger Vogt - 10 hours ago

    Thanks for the report. Indeed the ac output is buggy.

    What has been your solution?

     
    • Praveen Sundar

      Praveen Sundar - 4 hours ago

      Thanks for confirming it @h_vogt. I've attached a patch against current master (a80f6e3e).

      The problem is in the AC branch of the pswitch code model. Its conductance entries use the opposite sign to the DC current Jacobian, and it never stamps the control port's input loading. While checking that, I also found that the derivative in the logarithmic transition region wasn't normalized by the control voltage span, and that the control derivative stays nonzero where the resistance is clamped. aswitch has the same sign error and the same clamping issue, so the patch fixes both models.

      To check it without relying on another simulator, I compared each AC result against a numerical derivative of the DC operating point (central differences at two step sizes) on 97 small test circuits. They cover both control directions, linear and log interpolation, the off, transition and on regions, input loading and clamping. 86 of them failed before the patch; all 97 pass after it. A three-switch amplifier with a DC gain of about 2.66e6 shows an AC gain of 0 before the patch and the matching value after.

      The patch adds an analog regression test to make check. It fails before the change and passes after. The full suite passes (59 tests), the existing CMC comparison results are unchanged, and the seven examples I tried behave the same.

      Here is a minimal case using pswitch directly, with no compatibility mode:

      Passive switch divider
      VDR IN 0 DC .1 AC 1
      VCTRL CTRL 0 DC .1
      A1 %gd(CTRL 0) %gd(IN OUT) MODE
      .model MODE pswitch(r_on=100 r_off=10000 cntl_on=.2 cntl_off=0)
      RL OUT 0 1k
      .ac lin 1 1 1
      .print ac vr(OUT)
      .end
      

      With the control at 0.1 V the switch sits at 1 kΩ, so the expected transfer is 0.5. Unpatched master gives 4.61e15; with the patch it gives 0.5.

      One separate thing came up while testing a larger op-amp macromodel. If the DC operating point fails and ngspice falls back to a transient-based operating point, a DC servo loop in the circuit can be left far from equilibrium, and the AC gain is then meaningless. This patch doesn't change that behavior. I mention it in case it's worth a separate ticket.

       

Log in to post a comment.