Verilog implementation notes

Traditionally, a circuit simulator consists of a program that processes and analyses circuits, together with a collection of device model implementations. The various Verilog standards provide a language to describe circuits, which we refer to as the “structural subset” of Verilog. The “behavioural modelling” subset provides a flexible standard for device modelling.

Gnucap is organised as a simulator program, which implements parsing and interpretation of the “structural subset”, whereas the “behavioural subset” is covered by another tool “modelgen-verilog”. Using modelgen-verilog (and gcc) we turn behavioural models into device plugins for use in the simulator with implementation notes here. The following sections relate to the structural subset, and its implementation on the simulator side implementation on the simulator side.

module

A module in a Verilog netlist is a collection of components similar to a SPICE subcircuit. Like paramsets, modules are declared at top level only. A module is an object inherited from BASE_SUBCKT, a COMPONENT that permits subdevices. Type resolution and elaboration is different to SPICE. Verilog has no “subtypes”: each subdevice refers to a COMPONENT by type name and has parameters and ports. The type name is resolved after read-in, and held by a stub device. Prototypes matching the type, port and parameter names of the stub are collected as candidates in precalc_first.

Once a candidate COMPONENT has undergone precalc_first, “is_valid()” indicates whether the candidate is the correct one. During expand, a cloned instance of the stub turns into a singleton subcircuit holding the valid candidate.

This singleton subcircuit is then deflated into just the candidate instance by the parent module at the end of expand.

According the the Verilog standard, only paramset, a special COMPONENT type permits overloading. In Gnucap Verilog mode a type name used in a device instance refers to all the prototypes by that name, regardless of their origin. Possible origins are device plugins and module or paramset statements loaded or parsed at any time before circuit expansion takes place. In spice mode, .subckt and .model commands provide a similar mechanism to create prototypes.

Hierarchical system parameters

(The implementation lags behind a bit as of May 2025, this is the normative behaviour, to be expected with the next snapshot.)

All devices have hierarchical system parameters (HSP). HSPs are propagated to subdevices following the standard rules from LRM table 9.29. For example, an $mfactor parameter specified in a module instance consitutes a multiplicative factor in the effective mfactor values of the devices underneath. In the module scope, hierarchical system parameters can be accessed by name, with or without trailing parentheses. The value returned is the effective hierarchical value.

module c();
  parameter p;
endmodule
module a();
  b #(.$xposition(3)) myb();
endmodule
module b();
  c #(.p($xposition()), .$xposition(17)) myc();
endmodule

a #(.$xposition(5)) mya();

Here, the value of p in a.b.c is 8, the effecive $xposition of a.b.

System parameters unknown to the simulator are ignored, but stored and passed on, akin to attributes.

Beyond the standard, Gnucap supports the following hierarchical system parameters. The purpose is to overrides simulator options that are usually global in traditional simulators.

Hierarchical temperature

The $temperature parameter sets the effective environmental temperature (in Kelvin) in a device instance. The $dtemp parameter controls the temperature difference relative to the enclosing device. Examples

resistor #(.$temperature(17.)) r0(p, n); // runs at 17 Kelvin
resistor #(.$dtemp(17.)) r1(p, n); // runs at 17 Kelvin above environment temperature
module m(p, n);
  resistor #(.$dtemp(42.)) r2(p, n); // mm.r2 runs at 45.K.
endmodule
m #(.$temperature(3.) mm(p,n);

Integration method

The $method HSP is string typed and selects the integration method. Methods are trap, euler, gear. Conflicts are resolved as usual, more local method wins over more global, 'only' wins over non-'only'.

capacitor #(.$method("euler")) c0(p, n);  // uses euler method (unless overridden)
module m(p, n);
  capacitor #(.$method("euler")) c0(p, n);  // mm.c0 uses trap method.
  capacitor #(.$method("euleronly")) c1(p, n);  // uses euler method.
endmodule
m #(.$method("traponly")) mm(p,n);
m #(.$method("trap")) mmm(p,n); // mmm.c0 uses euler method.

paramset

A paramset is a COMPONENT with a named reference to another of an underlying type and a set of parameters, similar to a one-device subcircuit. The type name is resolved during precalc_first and is supposedly unique. It is currently assumed to be available when parsing the paramset. Port names are inherited from this prototype and available after precalc_first.

The prototype name in a paramset declaration (used in the simulator) resolves to the first component found in its scope. Next, the device_dispatcher is queried. This is where dynamically loaded plugins may provide models. Note that the dispatcher replaces existing entries when installing the same name again, hence the last one loaded wins.

When gnucap-modelgen reads in a paramset, a module definition must be available by the prototype name, i.e. further up within the compilation unit. The standard requires a unique name. If it is not unique, the system will pick the latest one, and should issue a warning.

example

paramset res resistor
  parameter R;
 .r(R)
endparamset

Paramsets are declared at top level only, and ready before instances are elaborated when the containing modules are expanded.

The standard allows multiple paramset declarations with the same label (type name). In Gnucap, type resolution is implemented equally for all COMPONENTS.

During elaboration, paramset instances are flattened. An instance R1, as in

module main();
  res #(.R(r0)) R1(a, b);
endmodule

Is transformed into

resistor #(.r(r0)) R1(.p(a), .n(b));

after “paramset res” has been identified as the only valid, matching prototype. If there are multiple candidates, such as an additional

paramset res resistor
  parameter r;
 .r(r)
endparamset
gnucap/manual/tech/verilog.txt · Last modified: 2025/05/11 14:35 by felixs
 
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Run by Debian Driven by DokuWiki