Electrical Linear Networks (ELN)
Modeling conservative continuous-time electrical circuits using the Electrical Linear Networks (ELN) model of computation.
Electrical Linear Networks (ELN)
The Electrical Linear Networks (ELN) model of computation brings traditional schematic-based circuit modeling into SystemC AMS. While LSF relies on abstract mathematical data flows, ELN is specifically designed for conservative continuous-time systems. This means the AMS solver automatically enforces Kirchhoff's Voltage and Current Laws (KVL/KCL) across the network.
If you are accustomed to SPICE netlists, ELN will look very familiar. You build your model by defining electrical nodes (nets) and connecting physical components (like resistors, capacitors, and voltage sources) between them.
Nodes, Terminals, and Primitives
The core difference between ELN and TDF/LSF is how components interact. In TDF, data flows directionally from an output port to an input port. In ELN, energy is exchanged conservatively across bidirectional terminals.
1. Nodes (sca_eln::sca_node)
A node represents a physical electrical connection point (a wire or net). The instantaneous voltage at a node is calculated dynamically by the ELN solver relative to a reference ground.
sca_eln::sca_node: A standard electrical net.sca_eln::sca_node_ref: The electrical ground (defined as exactly 0 Volts). Every ELN cluster must have at least one path to a reference node.
2. Terminals (sca_eln::sca_terminal)
ELN components use terminals rather than directional ports. Terminals bind to nodes. By convention, current flows through the terminal into the component, and the voltage drops across the component's positive (p) and negative (n) terminals.
3. Electrical Primitives
The sca_eln namespace provides standard passive electrical components. All of them are instantiated as standard members in an sc_module:
sca_eln::sca_r: Resistor.sca_eln::sca_c: Capacitor.sca_eln::sca_l: Inductor.sca_eln::sca_vsource/sca_eln::sca_isource: Independent voltage/current sources.
Converting to/from ELN
You cannot connect a discrete TDF signal directly to a resistor. Instead, you use TDF-to-ELN converter primitives:
sca_eln::sca_tdf::sca_vsource: Acts as an ideal voltage source in the ELN domain, where the instantaneous voltage is driven by the sampled TDF input signal.sca_eln::sca_tdf::sca_vsink: Acts as an ideal voltmeter that reads the voltage drop across two ELN nodes and outputs it as a discrete-time TDF signal.
Complete Example: An RLC Low-Pass Filter
The following complete, compilable example demonstrates how to construct a classic Resistor-Inductor-Capacitor (RLC) filter. We will drive the filter with a TDF step-signal and read the continuous-time voltage response of the capacitor back into the TDF domain.
#include <systemc>
#include <systemc-ams.h>
// 1. TDF Source: Generates a Step input at 1.0 seconds
SCA_TDF_MODULE(StepSource) {
sca_tdf::sca_out<double> out;
SCA_CTOR(StepSource) {}
void set_attributes() {
set_timestep(1.0, sc_core::SC_MS); // 1 ms discrete timestep
}
void processing() {
double t = get_time().to_seconds();
double val = (t >= 1.0) ? 5.0 : 0.0; // 0V to 5V Step
out.write(val);
}
};
// 2. The ELN RLC Circuit
SC_MODULE(RLC_Circuit) {
// Interface to the TDF world
sca_tdf::sca_in<double> in;
sca_tdf::sca_out<double> out;
// Electrical Nodes
sca_eln::sca_node n_src; // Node between Source and Resistor
sca_eln::sca_node n_rl; // Node between Resistor and Inductor
sca_eln::sca_node n_lc; // Node between Inductor and Capacitor
sca_eln::sca_node_ref gnd; // The electrical ground (0V)
// Converter Primitives
sca_eln::sca_tdf::sca_vsource tdf_v_src;
sca_eln::sca_tdf::sca_vsink tdf_v_snk;
// Electrical Primitives
sca_eln::sca_r resistor;
sca_eln::sca_l inductor;
sca_eln::sca_c capacitor;
SC_CTOR(RLC_Circuit)
: tdf_v_src("tdf_v_src", 1.0) // Scale = 1.0
, tdf_v_snk("tdf_v_snk", 1.0)
, resistor("resistor", 10.0) // R = 10 Ohms
, inductor("inductor", 0.1) // L = 100 mH
, capacitor("capacitor", 0.001) // C = 1000 uF
{
// 1. Drive the circuit using the TDF input
tdf_v_src.inp(in); // Bind to TDF discrete port
tdf_v_src.p(n_src); // Positive terminal to Source node
tdf_v_src.n(gnd); // Negative terminal to Ground
// 2. Resistor in series
resistor.p(n_src);
resistor.n(n_rl);
// 3. Inductor in series
inductor.p(n_rl);
inductor.n(n_lc);
// 4. Capacitor to ground
capacitor.p(n_lc);
capacitor.n(gnd);
// 5. Read the voltage across the capacitor (n_lc to ground)
tdf_v_snk.p(n_lc);
tdf_v_snk.n(gnd);
tdf_v_snk.outp(out); // Bind to TDF discrete port
}
};
int sc_main(int argc, char* argv[]) {
// Signals
sca_tdf::sca_signal<double> sig_step("sig_step");
sca_tdf::sca_signal<double> sig_response("sig_response");
// Instantiate Modules
StepSource src("src");
src.out(sig_step);
RLC_Circuit rlc("rlc");
rlc.in(sig_step);
rlc.out(sig_response);
// Setup Tracing
sca_util::sca_trace_file* tf = sca_util::sca_create_vcd_trace_file("eln_rlc_wave");
sca_util::sca_trace(tf, sig_step, "Input_Step_Voltage");
sca_util::sca_trace(tf, sig_response, "Capacitor_Voltage_Response");
// You can also trace internal ELN nodes directly!
sca_util::sca_trace(tf, rlc.n_rl, "Node_RL_Voltage");
// Start Simulation
sc_core::sc_start(3.0, sc_core::SC_SEC);
sca_util::sca_close_vcd_trace_file(tf);
return 0;
}How the ELN Solver Works
During the elaboration phase, the SystemC AMS kernel identifies all connected ELN primitives (the converters, resistor, inductor, and capacitor) and groups them into an ELN cluster. It automatically formulates a continuous-time matrix of differential equations based on KVL and KCL.
During the simulation, whenever the discrete TDF solver injects a new voltage value via tdf_v_src, the ELN Linear Solver mathematically integrates the continuous-time response of the RLC circuit across that timestep, tracking the energy stored in the inductor and capacitor. It then provides the precise resulting voltage at node n_lc back to the discrete TDF domain via tdf_v_snk. This complex analog numerical integration happens entirely under the hood.
Comments and Corrections