Blog

Thoughts on IC development, EDA, and hardware design languages.

SystemVerilog: bet you didn’t know you could…(Part 2)

Posted by: Trent McClements | Posted on: November 16th, 2014 | 3 Comments

Share on LinkedIn20Share on Facebook0Tweet about this on Twitter0Share on Google+0Email this to someone

…have multiple different global domains (well, almost)!

Welcome to the world of SystemVerilog compilation units — a deceptively simple concept. At first blush compilation units are like compile containers, or silos as I like to think of them, where a single file (single file compilation unit) or multiple files (multi-file compilation unit) can be compiled into. That seems pretty simple. The devil, however, is always in the details… First, the SystemVerilog LRM doesn’t completely specify how compilation units are to be implemented so different tools may behave in different ways. Add to that the complications of things like macro definitions, packages, etc. and things get really interesting… We’ll dive into that aspect in a later post. For today I just want to give an overview of just what the heck these compilation units things actually are!

At the 10000 foot level the idea behind compilation units was to provide a way to compile one or more SystemVerilog files into isolated scopes. The concept ports very well when thinking about compiling sub-blocks of a toplevel design or testbench that made use of the global declaration scope. You can contain the declaration scope of these sub-blocks into isolated silos when reusing them, which sounds great and can get you out of a bind when you have declaration collisions.

So, what can be in a compilation unit? Well, a compilation unit can contain anything that can be defined within a package (types, nets, variables, tasks, functions, sequences, properties and checkers) along with bind constructs. A bit confusingly, modules, interface, packages, programs and primitive constructs are visible in all compilation units but cannot be defined within them – these type of constructs are truly global (hence the “almost” in the title).

Now, let’s look at an example. Let’s say we have a module, “module0″, that references a wire, “common” and that wire is declared in the file containing the definition of “module0″ but external to module0′s definition:

wire [31:0] common;

module module0();
assign common = 32′hA5A5A5A5;

endmodule

We also have a second module, “module1″, that is defined in a second file and also references a wire named “common”, but that wire is not declared anywhere in the file containing “module1″:

module module1();
assign common = 32′hF0F0F0F0;

endmodule

What happens? Well, if these two modules are compiled into the same compilation unit (multi-file compilation unit mode) then they would both share the externally declared wire “common”. However, if they are compiled into different compilation units (single-file compilation unit mode) then “module0″ would indeed see the wire declaration of “common” and it would have a width of 32. But “module1″ would not and would create an implicitly declared wire “common” of width 1!

So, compilation units can be a bit tricky, even in the simple use case. In fact, once you understand the “gory details” of compilation units, you will probably see that using packages is a much cleaner and more robust strategy. But, of course, life is never that easy, and in some cases you really do need to use compilation units, perhaps due to a reuse subblock that played fast-and-loose with the declaration scope… So understanding of compilation units definitely needs to be a part of your HDL toolbox.

Stay tuned for the next installment(s) where we will add Veriog marcos to the mix, and see just how complex things can get….

4-Ways-to-Build-Best-in-Class

Share on LinkedIn20Share on Facebook0Tweet about this on Twitter0Share on Google+0Email this to someone

Comments (3)


  1. Tudor Timi - Reply
    November 19, 2014

    Hi Trent,

    It’s really good that you pointed this out, with the compilation units. Because of the opportunity for confusion, I’d guess that using a wire defined in the global scope (or anything for that matter) is best avoided.

    • Trent McClements - Reply
      November 19, 2014

      Yes, I personally try to avoid globals if at all possible — especially so when designing something targeted for reuse!

  2. Mohamed - Reply
    February 21, 2016

    Dude, right on there brertoh.

Leave a Comment