Implement LDO DUT model

Temperature-dependent LDO voltage regulator model with:
- Output voltage tempco (ppm/°C)
- Quiescent current tempco
- Dropout voltage temperature dependence
- Power dissipation calculation (Vin-Vout)*Iload + Vin*Iq
- Dropout detection

Implements DUTModel protocol for physics engine integration.
This commit is contained in:
2025-03-06 21:24:17 +00:00
parent f45f5a2a19
commit 762d7181e3
2 changed files with 224 additions and 0 deletions

View File

@@ -3,3 +3,8 @@
Provides thermal and electrical models for various device types
including LDO regulators, op-amps, and other components.
"""
from py_dvt_ate.simulation.physics.models.base import DUTModel
from py_dvt_ate.simulation.physics.models.ldo import LDOModel, LDOParameters
__all__ = ["DUTModel", "LDOModel", "LDOParameters"]

View File

@@ -0,0 +1,219 @@
"""LDO (Low Dropout Regulator) DUT model.
Implements temperature-dependent electrical behaviour for an LDO voltage
regulator, including output voltage tempco, quiescent current variation,
and power dissipation calculations.
"""
from dataclasses import dataclass
@dataclass(frozen=True)
class LDOParameters:
"""Configuration parameters for an LDO model.
All temperature coefficients are referenced to 25°C.
Attributes:
nominal_output_voltage: Nominal output voltage at 25°C in volts.
tempco_ppm_per_c: Output voltage temperature coefficient in ppm/°C.
quiescent_current_a: Quiescent current at 25°C in amps.
quiescent_current_tempco: Quiescent current temperature coefficient (1/°C).
dropout_voltage: Dropout voltage at 25°C in volts.
max_output_current: Maximum output current in amps.
"""
nominal_output_voltage: float = 3.3
tempco_ppm_per_c: float = 50.0
quiescent_current_a: float = 50e-6 # 50 µA
quiescent_current_tempco: float = 0.003 # 0.3%/°C
dropout_voltage: float = 0.3
max_output_current: float = 0.5
# Reference temperature for all calculations
REFERENCE_TEMPERATURE_C = 25.0
class LDOModel:
"""Temperature-dependent LDO voltage regulator model.
Models the electrical behaviour of a linear voltage regulator with:
- Output voltage that varies with temperature (tempco in ppm/°C)
- Quiescent current that varies with temperature
- Dropout voltage that increases with temperature
- Power dissipation from (Vin - Vout) × Iload + Vin × Iq
This class implements the DUTModel protocol.
"""
def __init__(
self,
params: LDOParameters | None = None,
input_voltage: float = 5.0,
load_current: float = 0.0,
) -> None:
"""Initialise the LDO model.
Args:
params: LDO parameters. Uses defaults if None.
input_voltage: Initial input voltage in volts.
load_current: Initial load current in amps.
"""
self._params = params or LDOParameters()
self._input_voltage = input_voltage
self._load_current = load_current
@property
def params(self) -> LDOParameters:
"""Get the LDO parameters."""
return self._params
@property
def input_voltage(self) -> float:
"""Get the current input voltage."""
return self._input_voltage
@input_voltage.setter
def input_voltage(self, value: float) -> None:
"""Set the input voltage."""
self._input_voltage = value
@property
def load_current(self) -> float:
"""Get the current load current."""
return self._load_current
@load_current.setter
def load_current(self, value: float) -> None:
"""Set the load current."""
self._load_current = value
def calculate_output_voltage(self, junction_temperature: float) -> float:
"""Calculate the output voltage at the given junction temperature.
Implements: V_out(T) = V_nom × (1 + TC_vout × (T - 25) × 1e-6)
The output voltage is clamped to not exceed (Vin - Vdropout) when
the regulator is in dropout.
Args:
junction_temperature: DUT junction temperature in degrees Celsius.
Returns:
Output voltage in volts.
"""
delta_t = junction_temperature - REFERENCE_TEMPERATURE_C
tempco_factor = 1.0 + self._params.tempco_ppm_per_c * delta_t * 1e-6
ideal_vout = self._params.nominal_output_voltage * tempco_factor
# Calculate dropout voltage at temperature
v_dropout = self._calculate_dropout_voltage(junction_temperature)
# Clamp output to not exceed (Vin - Vdropout)
max_vout = max(0.0, self._input_voltage - v_dropout)
return min(ideal_vout, max_vout)
def calculate_quiescent_current(self, junction_temperature: float) -> float:
"""Calculate the quiescent current at the given junction temperature.
Implements: I_q(T) = I_q_25 × (1 + TC_iq × (T - 25))
Args:
junction_temperature: DUT junction temperature in degrees Celsius.
Returns:
Quiescent current in amps.
"""
delta_t = junction_temperature - REFERENCE_TEMPERATURE_C
tempco_factor = 1.0 + self._params.quiescent_current_tempco * delta_t
return self._params.quiescent_current_a * tempco_factor
def calculate_power_dissipation(
self,
input_voltage: float,
load_current: float,
junction_temperature: float,
) -> float:
"""Calculate the power dissipation for given operating conditions.
Implements: P_diss = (V_in - V_out) × I_load + V_in × I_q
The power dissipation comes from:
- Voltage drop across the pass element times load current
- Quiescent current times input voltage
Args:
input_voltage: Input voltage in volts.
load_current: Load current in amps.
junction_temperature: DUT junction temperature in degrees Celsius.
Returns:
Power dissipation in watts.
"""
# Temporarily set input voltage for output voltage calculation
original_vin = self._input_voltage
self._input_voltage = input_voltage
try:
v_out = self.calculate_output_voltage(junction_temperature)
i_q = self.calculate_quiescent_current(junction_temperature)
# Power in pass element
p_pass = (input_voltage - v_out) * load_current
# Power from quiescent current
p_quiescent = input_voltage * i_q
return p_pass + p_quiescent
finally:
self._input_voltage = original_vin
def _calculate_dropout_voltage(self, junction_temperature: float) -> float:
"""Calculate the dropout voltage at the given temperature.
Implements: V_do(T) = V_do_25 × (T_K / 300)^1.5
where T_K is the temperature in Kelvin.
Dropout voltage increases with temperature due to increased
resistance of the pass element.
Args:
junction_temperature: Junction temperature in degrees Celsius.
Returns:
Dropout voltage in volts.
"""
# Convert to Kelvin
t_kelvin = junction_temperature + 273.15
# Temperature ratio (reference is approximately 300K ≈ 27°C)
temp_ratio = t_kelvin / 300.0
return self._params.dropout_voltage * (temp_ratio**1.5)
def is_in_dropout(self, junction_temperature: float) -> bool:
"""Check if the LDO is in dropout at current operating point.
The LDO is in dropout when the input voltage minus dropout voltage
is less than the nominal output voltage.
Args:
junction_temperature: Junction temperature in degrees Celsius.
Returns:
True if in dropout, False otherwise.
"""
v_dropout = self._calculate_dropout_voltage(junction_temperature)
headroom = self._input_voltage - v_dropout
# Get the ideal (temperature-adjusted) output voltage
delta_t = junction_temperature - REFERENCE_TEMPERATURE_C
tempco_factor = 1.0 + self._params.tempco_ppm_per_c * delta_t * 1e-6
ideal_vout = self._params.nominal_output_voltage * tempco_factor
return headroom < ideal_vout