In Part 1 we only translated a simple resistor. Let's look at a more complicated model, a diode with a junction capacitance that varies with voltage. Here is the model in VHDL-A, keywords in bold:

**library** IEEE, Disciplines;**use** Disciplines.electrical_system.**all**;**use** IEEE.math_real.**all**;**entity** diode_cap **is**

**generic** (

i0: REAL := 0.0; -- amps

tau: REAL := 0.0; -- seconds

c0: REAL := 0.0; -- farads

vj: REAL := 0.0); -- volts

**port** (**terminal** a, k: electrical);**end entity** diode_cap;**architecture** simple **of** diode_cap **is**

**quantity** vdiode **across** idiode, icap **through** a **to** k;

**quantity** qcap: charge;

**constant** vt: REAL := 0.0258; -- thermal voltage at Tj = 300K in volts**begin**

idiode == i0 * (exp(vdiode / vt) - 1.0);

qcap == tau * idiode - 2.0 * c0 * sqrt(vj**2 - vj * vdiode);

icap == qcap’dot;**end architecture** simple;

It is similar in structure to the resistor example in part 1, but there are three new ideas added:

First, the implicit parallel connection of the two current branches idiode and icap that you can see in the line:

**quantity** vdiode **across** idiode, icap **through** a **to** k;

Second, the usage of the "tick dot" notation to apply the time derivative method onto qcap in the line:

icap == qcap’dot;

Third, charge is a data type in VHDL-A's electrical nature.

My translation to Verilog-A is:

**`include** "disciplines.vams"

**module** diode_cap(a, k);

**parameter real** i0=0.0; // amps

**parameter real** tau=0.0; // seconds

**parameter real** c0=0.0; // farads

**parameter real** vj=0.0; // volts

**real** qcap;

**inout** a, k;

**electrical** a, k;

**branch** (a, k) diode, cap;

**analog begin**

I(diode) <+ i0 * (limexp(V(a,k) / **$vt**(300)) - 1.0);

qcap = tau * I(diode) - 2.0 * c0 * sqrt(vj**2 - vj * V(a,k));

I(cap) <+ ddt(qcap);** end****endmodule**

Notable differences compared to part 1 and to the VHDL version are:

First, that** branch **is an explicit keyword in Verilog-A. Here we declare two named branches diode and cap both of which are between nets a and k, which renders them in a parallel (aka shunt) configuration. You can apply the access functions V() and I() to named branches so V(a,k) is the same as V(cap) and V(diode) in our case. (By the way, to connect branches in series instead of parallel, you would declare an internal node, say electrical i; , and write something like branch (a, i) rs, (i, k) diode; )

Second, that the time derivative is a function ddt() not a method. If the capacitance had been a constant c, you could have used I(cap) <+ c * ddt(V(cap));

Third, I used a real to represent charge. There is a Charge nature in the standard include file disciplines.vams Verilog-A but it's not useful in this context. The variable qcap is internal to the model, so we omit the parameter keyword, because we don't want to expose it in the model's parameter list. Because qcap is an ordinary variable, we cannot use the <+ contribution operator: we must use the assignment operator = . For this reason, the order of the statements is important. The qcap assignment must be placed before the contribution statement that uses the result. This is a subtle but important difference between Verilog and VHDL and it is worth your time to ponder it. For a discussion, see page 58 of "The Designer's Guide to Verilog-AMS" by Kundert and Zinke.

Note that I chose to highlight one of the built-in system functions $vt()** **for the thermal voltage rather than defining a constant. You can use an explicit temperature like $vt(300) or the simulator temperature by writing $vt($temperature). If you omit the parentheses and argument, simply $vt, it is equivalent to $vt($temperature). By the way, the temperature is in kelvin, so be sure not to accidentally set it to zero! Zero kelvin is non-physical obviously, and besides that it can trigger horrible math library exceptions like divide by zero or zero to the power zero.

Note also that I chose to use limexp() instead of exp(). limexp is short for exponential with limiting. It limits how fast the return value can change from call to call. It often improves simulator convergence versus its cousin, the more usual exp().

In Part 5, I turn to a slightly different topic, namely verification.