Meta

Dave RichDave Rich is Verification Technologist at Mentor Graphics and is one of the authors of Mentor’s Advanced Verification Methodology cookbook. He began his career as a design and verification engineer in 1981 at Data General. In 1987, he joined Gateway Design Automation as one of the first application engineers to support Verilog-XL. At Gateway, he helped design many of the early features of the Verilog Hardware Description Language (HDL), and after Cadence acquired Gateway, helped prepare the Language Reference Manual (LRM) that would eventually be donated to the newly formed Open Verilog International. In 1995, he joined another Verilog simulation company, Frontline Design Automation as an AE manager and later as a Product Manager after it was acquired by Avant!. In 1998, he joined Ambit Design and worked as a consulting engineer for both synthesis and simulation products after it was acquired by Cadence. In 2000, he joined Co-Design Automation as Director of Application Engineering where the Superlog HDL was being developed that eventually became the basis of the Accellera SystemVerilog 3.0 standard. Co-Design Automation was acquired by Synopsys in 2002. Dave began work on numerous technical committees within Accellera and later the IEEE P1800 working group, where he continues today. « Less

Dave RichDave Rich is Verification Technologist at Mentor Graphics and is one of the authors of Mentor’s Advanced Verification Methodology cookbook. He began his career as a design and verification engineer in 1981 at Data General. In 1987, he joined Gateway Design Automation as one of the first … More »

SystemVerilog: The finer details of $root versus $unit

Believe me – I tried to make this shorter. It’s difficult for me to explain things without a historical perspective.

Verilog was invented to be an interpreted language. Verilog-XL was (and still is) an interpretive engine with single compilation unit use model. In an interpreted engine, all of the source code is parsed and loaded into memory. This means you have to specify all the source files of a design, including the source files of any required libraries, within a single command line before simulating.

VCS (Verilog Compiled Simulator) continued this single compilation use model even though it compiled the code into a machine object saved on disk. Later, it introduced an incremental compile feature that only compiled certain files that needed it, but you still had to specify all the source files on the command line. This is not the same as separate compilation available in most software programming languages where source code can be converted into machine code independently.

Tools such as NCsim and Modelsim introduced the concept of separate compilation, loosely based on the work library concept from VHDL. This is relatively easy to do in Verilog because module definitions are self contained. However, parameter overrides and hierarchical references limit the amount of machine code you can generate. The elaboration step does a lot of this work. It turns out that module instantiation syntax is easy to recognize, so the compiler does not need to see the definition of module that is being instantiating beforehand.

Superlog, the predecessor to SystemVerilog, was also invented as an interpreted language. It introduced the concept of $root as a global scope that allowed any kind of declaration (data types classes, variables) along with module definitions nested in that global scope. Any uninstantiated module becomes implicitly instantiated in $root. That’s fine for a single compilation unit, but you can no longer separately compile modules because they now may have dependencies on declarations outside their scope. For example

class C;
endclass
module top;
C c_h;
endmodule

There’s no problem if this is compiled as a single file, but if module top were to be compiled separately from the class C definition, it wouldn’t know what the identifier C was supposed to represent, and wouldn’t be able to parse the file.

So the IEEE committee borrowed the concept of packages from VHDL and standardized the concept of a compilation unit. A package allows you to compile definitions in a separate step and import those definitions into another compilation step. Packages create separate namespaces for those definitions as wall as imposing compilation order dependencies.

A compilation unit formalizes a scope that represents what is visible in a compilation step – called $unit in SystemVerilog. If you have a design that is compiled as a single compilation unit, there is really no conceptual difference between $unit and $root. However, once you have a design with multiple compilation units, then $unit represents the top level of each compilation unit, and there is nothing in $root except for the implicitly instantiated module instances. The only time you need to use $root or $unit is when a local name in the current scope hides a name in a higher level scope. For example