{"id":1486,"date":"2010-07-13T00:21:07","date_gmt":"2010-07-13T07:21:07","guid":{"rendered":"https:\/\/blogs.mentor.com\/verificationhorizons\/?p=1486"},"modified":"2026-03-27T08:53:06","modified_gmt":"2026-03-27T12:53:06","slug":"package-import-versus-include","status":"publish","type":"post","link":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/2010\/07\/13\/package-import-versus-include\/","title":{"rendered":"SystemVerilog Coding Guidelines: Package import versus `include"},"content":{"rendered":"<p>Another frequently asked question: Should I import my classes from a <strong>package <\/strong>or `<strong>include<\/strong> them? To answer this properly, you need to know more about SystemVerilog\u2019s type system, especially the difference between its <a href=\"http:\/\/wiki.answers.com\/Q\/What_is_strong-typing_versus_weak-typing\" target=\"_blank\" rel=\"noopener\">strong and weak typing<\/a> systems.<\/p>\n<p>In programming languages, weak typing is characterized by implicit\u00a0 or ad-hoc conversions without explicit casting between values of different data types. Verilog\u2019s bit vectors, or integral types, represent these weak typing aspects by implicitly padding and truncating values to be the proper bit lengths \u2013 at least proper by Verilog standards. If you perform a bitwise AND of a 7-bit and 8-bit vector, Verilog implicitly zero pads an 8th bit to the 7-bit operand and returns an 8-bit result. In contrast using VHDL, you would have to explicitly state whether you wanted the 7-bit operand to be padded, or the 8-bit operand to be truncated so that you have an expression with operands of equal size.<\/p>\n<p>With a few exceptions, all other types in SystemVerilog follow <a title=\"Using Strong Types in Your SystemVerilog Design and Verification\" href=\"https:\/\/verificationacademy.com\/resources\/technical-papers\/using-strong-types-in-your-systemverilog-design-and-verification\" target=\"_blank\" rel=\"noopener\">strong typing<\/a> rules. Strong typing rules require explicit conversions or casts when assigning or expressing operands of unequal types. And understanding what SystemVerilog considers equivalent types is key to understanding the effect of importing a class from a package versus including it from a file.<\/p>\n<p>Inheritance aside, SystemVerilog uses the name of a type alone to determine type equivalence of a class. For example, suppose I have these two class definitions A and B below:<\/p>\n<table border=\"1\" width=\"400\" cellspacing=\"0\" cellpadding=\"2\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"200\"><code>class A;<br \/>\nint i;<br \/>\nendclass : A<\/code><\/td>\n<td valign=\"top\" width=\"200\"><code>class B;<br \/>\nint i;<br \/>\nendclass : B<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>SystemVerilog considers these two class definitions unequal types because they have different names, even though their contents, or class bodies, are identical. The name of a class includes more than just the simple names <strong>A<\/strong> and <strong>B<\/strong>; the names also include the scope where the definition is declared. When you declare a class in a package, the package name becomes a prefix to the class name:<\/p>\n<table border=\"1\" width=\"400\" cellspacing=\"0\" cellpadding=\"2\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"200\"><code>package P;<br \/>\nclass A;<br \/>\nint i;<br \/>\nendclass : A<br \/>\nA a1;<br \/>\nendpackage : P<\/code><\/td>\n<td valign=\"top\" width=\"200\"><code>package Q;<br \/>\nclass A;<br \/>\nint i;<br \/>\nendclass : A<br \/>\nA a1;<br \/>\nendpackage : Q<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Now there are two definitions of class A, one called <strong>P::A<\/strong> and the other called <strong>Q::A<\/strong>. And the variables <strong>P::a1<\/strong> and <strong>Q::a1<\/strong> are type incompatible referencing two different class A\u2019s. Re-writing the above example using an include file creates the same situation \u2013 two incompatible class definitions.<\/p>\n<table border=\"1\" width=\"400\" cellspacing=\"0\" cellpadding=\"2\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"132\">File A.sv<\/td>\n<td valign=\"top\" width=\"133\">File P.sv<\/td>\n<td valign=\"top\" width=\"133\">File Q.sv<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"132\"><code>class A;<br \/>\nint i;<br \/>\nendclass : A<\/code><\/td>\n<td valign=\"top\" width=\"133\"><code>package P;<br \/>\n`include \u201cA.sv\"<br \/>\nA a1;<br \/>\nendpackage : P<\/code><\/td>\n<td valign=\"top\" width=\"133\"><code>package Q;<br \/>\n`include \u201cA.sv\"<br \/>\nA a1;<br \/>\nendpackage : Q<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>After `<strong>includ<\/strong>ing class A into each package, you wind up with two definitions of class A. Using `<strong>include<\/strong> is just a shortcut for cut and pasting text in a file. Importing a name from a package does not duplicate text; it makes that name visible from another package without copying the definition.<\/p>\n<table border=\"1\" width=\"501\" cellspacing=\"0\" cellpadding=\"2\">\n<tbody>\n<tr>\n<td valign=\"top\" width=\"124\">File A.sv<\/td>\n<td valign=\"top\" width=\"125\">File P.sv<\/td>\n<td valign=\"top\" width=\"125\">File R.sv<\/td>\n<td valign=\"top\" width=\"125\">File S.sv<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\" width=\"124\"><code>class A;<br \/>\nint i;<br \/>\nendclass : A<\/code><\/td>\n<td valign=\"top\" width=\"125\"><code>package P;<br \/>\n`include \u201cA.sv\"<br \/>\nendpackage : P<\/code><\/td>\n<td valign=\"top\" width=\"125\"><code>package R;<br \/>\nimport P::A;<br \/>\nA a1;<br \/>\nendpackage : R<\/code><\/td>\n<td valign=\"top\" width=\"125\"><code>package S;<br \/>\nimport P::A;<br \/>\nA a1;<br \/>\nendpackage : S<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Class A is declared in package P, and <em>only<\/em> in package P. The variables <strong>R::a1<\/strong> and <strong>S::a1<\/strong> are type compatible because they are both of type <strong>P::A<\/strong>. The fact that class A was `<strong>include<\/strong>d from another file once it is expanded is no longer relevant once you consider the placement of the text from the file.<\/p>\n<p>When you get compiler errors claiming that two types are incompatible even though they appear to have the same name, make sure you consider the scope where the types are declared as part of the full name. Class names declared in a module are prefixed by the module instance name, so the same module instantiated multiple times will create unique class names, all incompatible types.<\/p>\n<p>For further information about packages, check out the June <a href=\"https:\/\/d1pe2sh79ppm3e.cloudfront.net\/volume6-issue2-verification-horizons-publication-lr.pdf\" target=\"_blank\" rel=\"noopener\">Verification Horizons<\/a> article entitled <em>\u201cUsing SystemVerilog Packages in Real Verification Projects\u201d.<\/em><\/p>\n<p>Dave Rich<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Another frequently asked question: Should I import my classes from a package or `include them? To answer this properly, you&#8230;<\/p>\n","protected":false},"author":71589,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spanish_translation":"","french_translation":"","german_translation":"","italian_translation":"","polish_translation":"","japanese_translation":"","chinese_translation":"","footnotes":""},"categories":[1],"tags":[533,751,819],"industry":[],"product":[205],"coauthors":[979],"class_list":["post-1486","post","type-post","status-publish","format-standard","hentry","category-news","tag-ieee-1800","tag-systemverilog","tag-verification","product-questa"],"_links":{"self":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/1486","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/users\/71589"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/comments?post=1486"}],"version-history":[{"count":3,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/1486\/revisions"}],"predecessor-version":[{"id":19231,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/posts\/1486\/revisions\/19231"}],"wp:attachment":[{"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/media?parent=1486"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/categories?post=1486"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/tags?post=1486"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/industry?post=1486"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/product?post=1486"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/verificationhorizons\/wp-json\/wp\/v2\/coauthors?post=1486"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}