circuitRF Reference Guide

Compiled Verilog-A Models

Running a compact model you supply — a published physics-based transistor model, or one you wrote — from Verilog-A source or from a compiled artefact, with no kit and nothing to install inside circuitRF.

What this component is for

1 2 3 VerilogA 1 2 3 VerilogA
VerilogA

The VerilogA component runs a compact model you supply. It needs no kit, no manifest and nothing installed into circuitRF — you point it at a file and place it.

That is the path to take when the device you need is a published physics-based compact model. Those are distributed as Verilog-A source: a few thousand lines of analog equations, a manual, and one or more fitted parameter sets. What this page buys you is the whole of that route — source in, a placed five-terminal device out, running DC, S-parameters and harmonic balance like any other component.

Two file types, one component

The File parameter takes either Verilog-A source (.va, .vams) or an already-compiled model (.osdi). Source is compiled once, by the compiler on your machine, and reused. If you already have a compiled artefact, point at it and no compiler is involved at all.

The compiler, and why it is yours

circuitRF does not contain a Verilog-A compiler and never will. The established compilers for this model format are GPL-3.0; circuitRF is MIT, and bundling or linking one would change that. So circuitRF does what a build system does with a C compiler: it runs a compiler you installed, as a separate program, and loads the file that comes out. Nothing is linked and nothing is redistributed.

Install one of your choosing, then either put it on PATH — in which case there is nothing to configure — or name it explicitly:

Settings ▸ Security & Permissions ▸ Verilog-A Compiler

Leave the box blank to use whatever is on PATH. Fill it in when you have more than one, or when yours lives somewhere PATH does not reach. A compiler you name wins over PATH — that is the whole point of naming one.

Blank also looks in the places a compiler is usually installed — ~/.local/bin, /opt/homebrew/bin and /usr/local/bin — because an application started from the Finder or a desktop launcher does not inherit the PATH your terminal has. So a compiler you can run by typing its name is found here too, without your having to name it. Press Test and circuitRF will run it and report what it says it is, which is the fastest way to confirm the setting before you need it.

For a headless run — a script, CI, a batch job — set CRF_VERILOGA_COMPILER to the compiler's path. It outranks PATH and leaves nobody's settings file touched.

If no compiler can be found, circuitRF says so at the moment you choose the file, names what to install and where to point it, and changes nothing else. The .osdi route keeps working.

A worked example, end to end

This is the whole path for a model you have just downloaded. It assumes only that you have the model's source and one of its parameter sets — which is what a model family actually ships.

  1. Put the source where you want it. Keep the family's own folder layout intact: models of this size `include parameter and macro files beside the source, and circuitRF passes the source's own directory to the compiler as an include path so those resolve exactly as they do when you build by hand.
  2. Place a VerilogA component. It is in the palette under Devices — search for "Verilog-A", "OSDI" or "compact model".
  3. Set File. Click Browse… beside the File row and choose the .va. circuitRF compiles it — once, taking a few seconds for a model of this size — and then reads it. The parameter editor tells you underneath which compiler ran, where the artefact was written, and whether anything was actually rebuilt; on every later visit it will say the source has not changed.

    If the compiler refuses, you get its own diagnostics, verbatim: file, line and column, exactly as it printed them. That is deliberate — the line number is the whole value of a compiler error, and a paraphrase would be worse than the error.

  4. Check Model. A file usually declares one module and circuitRF fills this in for you. When it declares several, the row becomes a picker — choose the one you want.
  5. Check Pins. circuitRF fills this in from the model's own terminal count and then locks it, because the model has stated it. See below for the one case where you deliberately set it lower.
  6. Load the parameter set — Load Parameters… at the foot of the parameter editor. See below.
  7. Wire it and run. From here it is an ordinary nonlinear component. Attach a DC analysis to sweep a bias point, S-parameters to get small-signal behaviour about that point, and harmonic balance for large-signal power, gain and efficiency. Everything in Simulations applies unchanged, and so does harmonicaRF — a compiled model is a valid DUT there too.
Start at DC

Run a DC sweep before anything else. A compact model that is mis-parameterised, or whose thermal terminal is wired the wrong way, shows it as a bias point that will not converge — and that is far easier to read at DC than in the middle of a harmonic-balance sweep.

Terminals, Pins, and the thermal one

The symbol is a plain box, deliberately. circuitRF does not know what your model is — it could be a transistor, a diode or a whole subcircuit — so drawing a transistor glyph would assert something the file has not said.

The leads are named by the model. Once circuitRF has read the file, each lead is labelled with the model's own name for that terminal — d, g, s, b, dt — rather than 1..5. On a five-terminal part with five identical leads, numbers are the single largest source of mis-wiring, and the model has already told circuitRF which is which. A lead the model does not name falls back to its number, on its own; you may see a mix.

The thermal terminal

Many physics-based models expose a thermal terminal: a node whose "voltage" is a temperature and whose "current" is a power. You have two honest choices, and circuitRF supports both.

What you drawWhat the model doesWhen to use it
Pins = the model's full count, thermal terminal wired Reads the temperature you impose on that node You are building the thermal network yourself — a resistance and capacitance from that node to an ambient source that sets the baseplate temperature.
Pins = one less, thermal terminal omitted Sees that the terminal is unconnected and grounds it internally The ordinary case. The model handles its own self-heating and you draw a four-pin part.
circuitRF tells the model how many terminals you connected; that is what the model's own $port_connected reads.

When you set Pins one below the model's count and the omitted terminal is thermal, the parameter editor says so — that a thermal terminal is deliberately left off and the model is handling its own self-heating. It is not a warning. It is there because a symbol with one lead fewer than the model declares otherwise reads as a mistake, and "fixing" it is the one thing you must not do:

Never leave a thermal terminal drawn but unwired

A thermal node with a pin on it and no thermal network attached is a floating node with no DC solution. It does not fail quickly or clearly — it spends the whole continuation budget and then reports a residual. Either omit the pin (and let the model ground it) or attach a real thermal network. There is no third option.

Loading a fitted parameter set

A fitted parameter set for a model of this size is 50 to 200 numbers. Both of the ways to get them in are at the foot of the parameter editor:

Load Parameters… reads sets written as Verilog-A parameter declarations, which is the form these families actually ship:

parameter real vxo   = 1.3e7;    // saturation velocity
parameter real beta  = 1.8;
parameter integer nf = 4;

Comments are ignored (including one containing a semicolon), from […] and exclude ranges are ignored, and both 1.3e7 and engineering notation like 2.4p are read as written. The whole load is one undo step.

Two behaviours worth knowing:

Absent means "the model's default"

circuitRF only writes the parameters your set actually assigns. A parameter that is not on the component is not sent to the model at all, which already means use your own default. That is why the whole declared list is never materialised as rows: freezing today's defaults into the design would mean recompiling with a changed default silently had no effect.

Reading back what the model computed

A compact model computes far more than the currents it hands the solver. Transconductances, junction capacitances, an overdrive voltage, a junction temperature — a physics-based model declares tens of them, and they are the numbers a designer actually reasons about. Verilog-A calls them operating point variables; circuitRF reads them back after every solve and publishes them as a result cube named OP.

They are never parameters. A parameter is something you tell the model; an operating-point variable is something it tells you, and it does not appear in the parameter editor for the same reason a voltmeter has no dial.

What you get, and where

At a DC operating point each one is a number, on a labelled axis whose entries are <instance>.<name> — X1.gm, X1.cgs, X1.tj. Wrapped in a parametric sweep it becomes a curve per quantity, one point per bias, in the Data Display's signal list beside V and I.

At a harmonic-balance point each one is a waveform, because that is what it is: a transconductance at 30 dBm of drive swings between pinch-off and full channel once per RF cycle, and no single number describes it. So OP there is a spectrum on the same harmonic axis V and I use — harmonic 0 is the cycle average, which is what "gm at this drive" usually means, and the higher entries say how hard the quantity is being swung.

In a measurement, name one through the analysis it came from:

measure gm_mS = DC1.OP("X1.gm") * 1000
measure gm_avg = HB1.OP("X1.gm", 0)

A name the model does not declare is refused, by name, with the available ones listed — it is never quietly dropped.

Turning it off per device

The parameter editor's Report operating-point variables checkbox is on by default. A model declaring forty quantities, on a design holding a dozen such devices, swept over a few hundred bias points, is a result carrying thousands of names — so turn it off on the devices you are not studying. Off costs nothing at all: the device is not asked, so neither the round trip nor the cube happens.

Two kinds of quantity are declared and not plotted. A model may declare an op-var as an integer or as a string. An integer arrives as an ordinary number. A string cannot: a result cube holds numbers of one kind, and there is nowhere in one to put a word. Such a quantity is still reported as declared, so you can see that it exists; it simply never appears in OP.

When circuitRF rebuilds, and where the artefact goes

A simulation of an unedited model compiles nothing. The compiled artefact is cached, and the cache key is:

Change any of those and you pay exactly one recompile. Change none of them and the compiler is not asked to build anything, however many times you run.

Artefacts are written to circuitRF's own per-user cache — not beside your source. A model family is often installed as a read-only tree, and writing build output into someone else's delivery is wrong even where it would succeed. The parameter editor names the exact path each time it reads the file, so a rebuild you were not expecting is visible rather than mysterious.

What is not supported

NetTerminal
11
22

The nets of an instance line, in this order. How many there are is set by Pins; the table shows Pins = 2.

NameDefaultUnitOn schematicMeaning
File——shownThe model to load: a compiled model (.osdi), or Verilog-A source (.va, .vams) which circuitRF builds once with the compiler installed on this machine and reuses until the source changes. Choosing one fills in Model and Pins below.
Model———Which device type inside that file to place. A file usually declares one, and then this can be left blank; when it declares several, pick the one you want.
Pins2——How many terminals the symbol draws. It is the model's own terminal count, filled in from the file — change it only if you are drawing before choosing one.
OpVarstrue——Whether this instance publishes the operating-point variables its model computes — transconductances, capacitances, node temperatures. On by default; turn it off on devices you are not studying to keep a swept result small.