OTA (operational transconductance amplifier) code model as a
reference implementation that exercises the programmatic noise interface.
This commit is contained in:
parent
1ccf795b9b
commit
d5bfe3af4a
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
================================================================================
|
||||
|
||||
FILE ota/cfunc.mod
|
||||
|
||||
Public Domain
|
||||
|
||||
AUTHORS
|
||||
|
||||
20 Mar 2026 Seth Hillbrand
|
||||
|
||||
SUMMARY
|
||||
|
||||
This file contains the model-specific routines for the OTA
|
||||
(Operational Transconductance Amplifier) code model.
|
||||
|
||||
DC/TRAN: Vout as current = gm * (Vp - Vn)
|
||||
AC: Complex gain = gm
|
||||
NOISE: Programmatic noise with en, in_noise, enk, ink, incm, incmk.
|
||||
|
||||
Parameter naming follows LTSPICE convention for OTA compatibility.
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
void cm_ota(ARGS)
|
||||
{
|
||||
double gm_val = PARAM(gm);
|
||||
double rout = PARAM(rout);
|
||||
double rin = PARAM(rin);
|
||||
|
||||
Mif_Complex_t ac_gain;
|
||||
|
||||
if (ANALYSIS == NOISE) {
|
||||
/* Register noise sources on every call (N_OPEN and N_CALC).
|
||||
* During N_OPEN: registers and returns index.
|
||||
* During N_CALC: returns same sequential index. */
|
||||
int src_en_w = cm_noise_add_source("en_white", 1, 0, MIF_NOISE_CURRENT);
|
||||
int src_en_f = cm_noise_add_source("en_flicker", 1, 0, MIF_NOISE_CURRENT);
|
||||
int src_in_w = cm_noise_add_source("in_white", 0, 0, MIF_NOISE_CURRENT);
|
||||
int src_in_f = cm_noise_add_source("in_flicker", 0, 0, MIF_NOISE_CURRENT);
|
||||
|
||||
/* Common-mode current noise: independent sources from each input pin to ground */
|
||||
int src_icm_pw = cm_noise_add_source("incm_p_white", 0, 0, MIF_NOISE_CURRENT_POS);
|
||||
int src_icm_pf = cm_noise_add_source("incm_p_flicker", 0, 0, MIF_NOISE_CURRENT_POS);
|
||||
int src_icm_nw = cm_noise_add_source("incm_n_white", 0, 0, MIF_NOISE_CURRENT_NEG);
|
||||
int src_icm_nf = cm_noise_add_source("incm_n_flicker", 0, 0, MIF_NOISE_CURRENT_NEG);
|
||||
|
||||
if (!mif_private->noise->registering) {
|
||||
double en = PARAM(en);
|
||||
double in_n = PARAM(in_noise);
|
||||
double enk_val = PARAM(enk);
|
||||
double ink_val = PARAM(ink);
|
||||
double incm = PARAM(incm);
|
||||
double incmk_val = PARAM(incmk);
|
||||
double f = NOISE_FREQ;
|
||||
|
||||
/* en referred to output as current noise: (en * gm)^2 A^2/Hz */
|
||||
NOISE_DENSITY(src_en_w) = en * en * gm_val * gm_val;
|
||||
NOISE_DENSITY(src_en_f) = (enk_val > 0 && f > 0) ?
|
||||
en * en * gm_val * gm_val * enk_val / f : 0.0;
|
||||
|
||||
/* in as differential current noise at input: in^2 A^2/Hz */
|
||||
NOISE_DENSITY(src_in_w) = in_n * in_n;
|
||||
NOISE_DENSITY(src_in_f) = (ink_val > 0 && f > 0) ?
|
||||
in_n * in_n * ink_val / f : 0.0;
|
||||
|
||||
/* incm as current noise from each input pin to ground */
|
||||
NOISE_DENSITY(src_icm_pw) = incm * incm;
|
||||
NOISE_DENSITY(src_icm_pf) = (incmk_val > 0 && f > 0) ?
|
||||
incm * incm * incmk_val / f : 0.0;
|
||||
NOISE_DENSITY(src_icm_nw) = incm * incm;
|
||||
NOISE_DENSITY(src_icm_nf) = (incmk_val > 0 && f > 0) ?
|
||||
incm * incm * incmk_val / f : 0.0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (ANALYSIS != MIF_AC) {
|
||||
double v_in = INPUT(inp);
|
||||
double v_out = INPUT(out);
|
||||
|
||||
OUTPUT(out) = gm_val * v_in + v_out / rout;
|
||||
PARTIAL(out, inp) = gm_val;
|
||||
PARTIAL(out, out) = 1.0 / rout;
|
||||
|
||||
OUTPUT(inp) = v_in / rin;
|
||||
PARTIAL(inp, inp) = 1.0 / rin;
|
||||
}
|
||||
else {
|
||||
Mif_Complex_t ac_rout;
|
||||
Mif_Complex_t ac_rin;
|
||||
|
||||
ac_gain.real = gm_val;
|
||||
ac_gain.imag = 0.0;
|
||||
AC_GAIN(out, inp) = ac_gain;
|
||||
|
||||
ac_rout.real = 1.0 / rout;
|
||||
ac_rout.imag = 0.0;
|
||||
AC_GAIN(out, out) = ac_rout;
|
||||
|
||||
ac_rin.real = 1.0 / rin;
|
||||
ac_rin.imag = 0.0;
|
||||
AC_GAIN(inp, inp) = ac_rin;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
================================================================================
|
||||
Public Domain
|
||||
|
||||
SUMMARY
|
||||
|
||||
Interface specification for the OTA (Operational Transconductance Amplifier)
|
||||
code model. LTSPICE-compatible parameter naming convention.
|
||||
|
||||
Noise is implemented via the programmatic API (cm_noise_add_source /
|
||||
NOISE_DENSITY). Set noise_programmatic = TRUE to enable noise analysis.
|
||||
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
NAME_TABLE:
|
||||
|
||||
|
||||
C_Function_Name: cm_ota
|
||||
Spice_Model_Name: ota
|
||||
Description: "Operational Transconductance Amplifier with noise"
|
||||
|
||||
|
||||
PORT_TABLE:
|
||||
|
||||
|
||||
Port_Name: inp out
|
||||
Description: "input" "output"
|
||||
Direction: inout inout
|
||||
Default_Type: gd g
|
||||
Allowed_Types: [gd] [g]
|
||||
Vector: no no
|
||||
Vector_Bounds: - -
|
||||
Null_Allowed: no no
|
||||
|
||||
|
||||
PARAMETER_TABLE:
|
||||
|
||||
|
||||
Parameter_Name: gm rout
|
||||
Description: "transconductance" "output resistance"
|
||||
Data_Type: real real
|
||||
Default_Value: 1.0e-3 1.0e12
|
||||
Limits: [1e-15 -] [0 -]
|
||||
Vector: no no
|
||||
Vector_Bounds: - -
|
||||
Null_Allowed: yes yes
|
||||
|
||||
|
||||
PARAMETER_TABLE:
|
||||
|
||||
|
||||
Parameter_Name: rin
|
||||
Description: "input resistance"
|
||||
Data_Type: real
|
||||
Default_Value: 1.0e12
|
||||
Limits: [0 -]
|
||||
Vector: no
|
||||
Vector_Bounds: -
|
||||
Null_Allowed: yes
|
||||
|
||||
|
||||
PARAMETER_TABLE:
|
||||
|
||||
|
||||
Parameter_Name: en in_noise
|
||||
Description: "input voltage noise density V/rtHz" "input current noise density A/rtHz"
|
||||
Data_Type: real real
|
||||
Default_Value: 0.0 0.0
|
||||
Limits: [0 -] [0 -]
|
||||
Vector: no no
|
||||
Vector_Bounds: - -
|
||||
Null_Allowed: yes yes
|
||||
|
||||
|
||||
PARAMETER_TABLE:
|
||||
|
||||
|
||||
Parameter_Name: enk ink
|
||||
Description: "voltage noise 1/f corner Hz" "current noise 1/f corner Hz"
|
||||
Data_Type: real real
|
||||
Default_Value: 0.0 0.0
|
||||
Limits: [0 -] [0 -]
|
||||
Vector: no no
|
||||
Vector_Bounds: - -
|
||||
Null_Allowed: yes yes
|
||||
|
||||
|
||||
PARAMETER_TABLE:
|
||||
|
||||
|
||||
Parameter_Name: incm incmk
|
||||
Description: "CM current noise density A/rtHz" "CM current noise 1/f corner Hz"
|
||||
Data_Type: real real
|
||||
Default_Value: 0.0 0.0
|
||||
Limits: [0 -] [0 -]
|
||||
Vector: no no
|
||||
Vector_Bounds: - -
|
||||
Null_Allowed: yes yes
|
||||
|
||||
|
||||
PARAMETER_TABLE:
|
||||
|
||||
|
||||
Parameter_Name: noise_programmatic
|
||||
Description: "enable programmatic noise sources"
|
||||
Data_Type: boolean
|
||||
Default_Value: TRUE
|
||||
Limits: -
|
||||
Vector: no
|
||||
Vector_Bounds: -
|
||||
Null_Allowed: yes
|
||||
|
||||
|
||||
Loading…
Reference in New Issue