Skip to content
LIBRARY
Analog.Semiconductors.Tests.NPNSwitching.md

Analog.Semiconductors.Tests.NPNSwitching ​

Saturated switching test for NPN, with use_advanced_continuation = true.

A 10 MHz square wave drives the base through 1 kΩ, overdriving the device well into saturation each half-cycle (Bf * I_B = 12 mA against a 5 mA collector-limited current). This exercises the parts of the charge model the DC benches never move:

  • the diffusion capacitances C_DE/C_DC — storage delay on the falling base drive is set by Taur, visible as the collector holding low after the base drive is removed;

  • the depletion capacitances through der(V_BE)/der(V_BC), swinging with the junctions on every edge;

  • the advanced continuation branch of C_jC/C_jE, which starts the linear continuation at phi - Z instead of zero bias — the branch that carries the fractional-power domain guard, compiled and integrated here.

rc.v tracks the collector current: square-ish with rounded storage-delayed edges.

Because use_advanced_continuation = true is not an MSL setting, this test has no MSL cross-validation — only a snapshot. Every other BJT test runs on pure defaults, which do reproduce MSL.

Usage ​

ElectricalComponents.Analog.Semiconductors.Tests.NPNSwitching()

Behavior ​

Source ​

dyad
"""
Saturated switching test for NPN, with `use_advanced_continuation = true`.

A 10 MHz square wave drives the base through 1 kΩ, overdriving the device
well into saturation each half-cycle (`Bf * I_B` = 12 mA against a 5 mA
collector-limited current). This exercises the parts of the charge model the
DC benches never move:

  * the diffusion capacitances `C_DE`/`C_DC` — storage delay on the falling
    base drive is set by `Taur`, visible as the collector holding low after
    the base drive is removed;
  * the depletion capacitances through `der(V_BE)`/`der(V_BC)`, swinging with
    the junctions on every edge;
  * the **advanced continuation** branch of `C_jC`/`C_jE`, which starts the
    linear continuation at `phi - Z` instead of zero bias — the branch that
    carries the fractional-power domain guard, compiled and integrated here.

`rc.v` tracks the collector current: square-ish with rounded storage-delayed
edges.

Because `use_advanced_continuation = true` is not an MSL setting, this test has no MSL
cross-validation — only a snapshot. Every other BJT test runs on pure defaults, which do
reproduce MSL.
"""
test component NPNSwitching
  "Supply rail level (5 V)"
  supply_lvl = BlockComponents.Sources.Constant(k = 5) {
    "Dyad": {"placement": {"diagram": {"x1": 20, "x2": 120, "y1": 220, "y2": 320}}}
  }
  "Collector supply"
  supply = ElectricalComponents.Analog.Sources.VoltageSource() {
    "Dyad": {"placement": {"diagram": {"x1": 155, "x2": 255, "y1": 335, "y2": 435}}}
  }
  "Base drive: 0 to 1 V square wave at 10 MHz"
  bias_sig = BlockComponents.Sources.Square(amplitude = 0.5, offset = 0.5, frequency = 1e7) {
    "Dyad": {"placement": {"diagram": {"x1": 150, "x2": 250, "y1": 120, "y2": 220}}}
  }
  "Base drive source"
  bias = ElectricalComponents.Analog.Sources.VoltageSource() {
    "Dyad": {"placement": {"diagram": {"x1": 285, "x2": 385, "y1": 235, "y2": 335}}}
  }
  "Base series resistance (1 kΩ); sets the overdrive"
  rb = ElectricalComponents.Analog.Basic.Resistor(R = 1000) {
    "Dyad": {"placement": {"diagram": {"x1": 415, "x2": 515, "y1": 130, "y2": 230}}}
  }
  "Collector load resistor (1 kΩ)"
  rc = ElectricalComponents.Analog.Basic.Resistor(R = 1000) {
    "Dyad": {"placement": {"diagram": {"x1": 285, "x2": 385, "y1": 20, "y2": 120}}}
  }
  "Transistor under test, advanced junction-capacitance continuation"
  q = ElectricalComponents.Analog.Semiconductors.NPN(use_advanced_continuation = true) {
    "Dyad": {"placement": {"diagram": {"x1": 545, "x2": 645, "y1": 130, "y2": 230}}}
  }
  "Ground reference"
  ground = ElectricalComponents.Analog.Basic.Ground() {
    "Dyad": {"placement": {"diagram": {"x1": 415, "x2": 515, "y1": 340, "y2": 440}}}
  }
relations
  "Drive starts high mid-square-wave; junctions discharged, collector at the rail"
  initial q.V_BE = 0
  initial q.V_CS = 5
  connect(supply_lvl.y, supply.V) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 205, "y": 270}], "E": 2}], "path": {}}}
  connect(bias_sig.y, bias.V) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 335, "y": 170}], "E": 2}], "path": {}}}
  connect(supply.p, rc.p) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 140, "y": 385}, {"x": 140, "y": 70}], "E": 2}],
      "path": {}
    }
  }
  connect(rc.n, q.c) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 595, "y": 70}], "E": 2}], "path": {}}}
  connect(bias.p, rb.p) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 270, "y": 285}, {"x": 270, "y": 180}], "E": 2}],
      "path": {}
    }
  }
  connect(rb.n, q.b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "path": {}}}
  connect(q.e, q.s, supply.n, bias.n, ground.g) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [{"x": 595, "y": 245}, {"x": 660, "y": 245}, {"x": 660, "y": 180}],
          "E": 2
        },
        {
          "S": 2,
          "M": [{"x": 670, "y": 180}, {"x": 670, "y": 490}, {"x": 270, "y": 490}],
          "E": -1
        },
        {"S": -1, "M": [], "E": 3},
        {"S": -1, "M": [{"x": 400, "y": 385}], "E": -2},
        {"S": -2, "M": [], "E": 4},
        {"S": -2, "M": [{"x": 465, "y": 285}], "E": 5}
      ],
      "junctions": [{"x": 270, "y": 385}, {"x": 400, "y": 285}],
      "path": {}
    }
  }
metadata {
  "Dyad": {
    "tests": {
      "case1": {
        "stop": 5e-7,
        "abstol": 1e-10,
        "reltol": 1e-8,
        "rtol": {"q.V_BE": 0.00001, "rc.v": 0.00001},
        "expect": {"signals": ["q.V_BE", "rc.v"]}
      }
    }
  }
}
end
Flattened Source
dyad
"""
Saturated switching test for NPN, with `use_advanced_continuation = true`.

A 10 MHz square wave drives the base through 1 kΩ, overdriving the device
well into saturation each half-cycle (`Bf * I_B` = 12 mA against a 5 mA
collector-limited current). This exercises the parts of the charge model the
DC benches never move:

  * the diffusion capacitances `C_DE`/`C_DC` — storage delay on the falling
    base drive is set by `Taur`, visible as the collector holding low after
    the base drive is removed;
  * the depletion capacitances through `der(V_BE)`/`der(V_BC)`, swinging with
    the junctions on every edge;
  * the **advanced continuation** branch of `C_jC`/`C_jE`, which starts the
    linear continuation at `phi - Z` instead of zero bias — the branch that
    carries the fractional-power domain guard, compiled and integrated here.

`rc.v` tracks the collector current: square-ish with rounded storage-delayed
edges.

Because `use_advanced_continuation = true` is not an MSL setting, this test has no MSL
cross-validation — only a snapshot. Every other BJT test runs on pure defaults, which do
reproduce MSL.
"""
test component NPNSwitching
  "Supply rail level (5 V)"
  supply_lvl = BlockComponents.Sources.Constant(k = 5) {
    "Dyad": {"placement": {"diagram": {"x1": 20, "x2": 120, "y1": 220, "y2": 320}}}
  }
  "Collector supply"
  supply = ElectricalComponents.Analog.Sources.VoltageSource() {
    "Dyad": {"placement": {"diagram": {"x1": 155, "x2": 255, "y1": 335, "y2": 435}}}
  }
  "Base drive: 0 to 1 V square wave at 10 MHz"
  bias_sig = BlockComponents.Sources.Square(amplitude = 0.5, offset = 0.5, frequency = 1e7) {
    "Dyad": {"placement": {"diagram": {"x1": 150, "x2": 250, "y1": 120, "y2": 220}}}
  }
  "Base drive source"
  bias = ElectricalComponents.Analog.Sources.VoltageSource() {
    "Dyad": {"placement": {"diagram": {"x1": 285, "x2": 385, "y1": 235, "y2": 335}}}
  }
  "Base series resistance (1 kΩ); sets the overdrive"
  rb = ElectricalComponents.Analog.Basic.Resistor(R = 1000) {
    "Dyad": {"placement": {"diagram": {"x1": 415, "x2": 515, "y1": 130, "y2": 230}}}
  }
  "Collector load resistor (1 kΩ)"
  rc = ElectricalComponents.Analog.Basic.Resistor(R = 1000) {
    "Dyad": {"placement": {"diagram": {"x1": 285, "x2": 385, "y1": 20, "y2": 120}}}
  }
  "Transistor under test, advanced junction-capacitance continuation"
  q = ElectricalComponents.Analog.Semiconductors.NPN(use_advanced_continuation = true) {
    "Dyad": {"placement": {"diagram": {"x1": 545, "x2": 645, "y1": 130, "y2": 230}}}
  }
  "Ground reference"
  ground = ElectricalComponents.Analog.Basic.Ground() {
    "Dyad": {"placement": {"diagram": {"x1": 415, "x2": 515, "y1": 340, "y2": 440}}}
  }
relations
  "Drive starts high mid-square-wave; junctions discharged, collector at the rail"
  initial q.V_BE = 0
  initial q.V_CS = 5
  connect(supply_lvl.y, supply.V) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 205, "y": 270}], "E": 2}], "path": {}}}
  connect(bias_sig.y, bias.V) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 335, "y": 170}], "E": 2}], "path": {}}}
  connect(supply.p, rc.p) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 140, "y": 385}, {"x": 140, "y": 70}], "E": 2}],
      "path": {}
    }
  }
  connect(rc.n, q.c) {"Dyad": {"edges": [{"S": 1, "M": [{"x": 595, "y": 70}], "E": 2}], "path": {}}}
  connect(bias.p, rb.p) {
    "Dyad": {
      "edges": [{"S": 1, "M": [{"x": 270, "y": 285}, {"x": 270, "y": 180}], "E": 2}],
      "path": {}
    }
  }
  connect(rb.n, q.b) {"Dyad": {"edges": [{"S": 1, "M": [], "E": 2}], "path": {}}}
  connect(q.e, q.s, supply.n, bias.n, ground.g) {
    "Dyad": {
      "edges": [
        {
          "S": 1,
          "M": [{"x": 595, "y": 245}, {"x": 660, "y": 245}, {"x": 660, "y": 180}],
          "E": 2
        },
        {
          "S": 2,
          "M": [{"x": 670, "y": 180}, {"x": 670, "y": 490}, {"x": 270, "y": 490}],
          "E": -1
        },
        {"S": -1, "M": [], "E": 3},
        {"S": -1, "M": [{"x": 400, "y": 385}], "E": -2},
        {"S": -2, "M": [], "E": 4},
        {"S": -2, "M": [{"x": 465, "y": 285}], "E": 5}
      ],
      "junctions": [{"x": 270, "y": 385}, {"x": 400, "y": 285}],
      "path": {}
    }
  }
metadata {
  "Dyad": {
    "tests": {
      "case1": {
        "stop": 5e-7,
        "abstol": 1e-10,
        "reltol": 1e-8,
        "rtol": {"q.V_BE": 0.00001, "rc.v": 0.00001},
        "expect": {"signals": ["q.V_BE", "rc.v"]}
      }
    }
  }
}
end


Test Cases ​

Test Case case1 ​

julia
plt

julia
plt