SystemVerilog Namespaces provide a mechanism for sharing data, type, task, and function declarations amongst multiple SystemVerilog modules and interfaces. A Namespace is a formalism and limitation to SystemVerilog 3.0 and 3.1 $root declarations.
 Namespaces are explicitly named scopes appearing at the outer level of 
  the source text (at the same level as modules, primitives, interfaces, etc.).
  Types, variables, tasks, and functions may be declared within a namespace.
  Such declarations may be referenced within modules, macromodules, interfaces,
  and other namespaces by either import or hierarchical name.
     
|  namespace_declaration ::= { attribute_instance } namespace namespace_identifier { namespace_item } endnamespace [ : namespace_identifier ] namespace_item ::= net_declaration | data_declaration | task_declaration | function_declaration | dpi_import_export | namespace_import_declaration | class_declaration  | 
         
The namespace declaration creates a top-level region to contain declarations
  intended to be shared amongst one or more modules, macromodules, or interfaces.
  Items within namespaces are generally type definitions, tasks, and functions.
  It is also possible to populate namespaces with variables and nets. This
 may occasionally be useful for globals that aren't conveniently passed down
 through the hierarchy.
    
The following is an example of a namespace:
    
namespace ComplexPkg;
           typedef struct {
          float i, r;
      } Complex;
  
           function Complex add(input Complex a, b)
          add.r = a.r + b.r;
          add.i = a.i + b.i;
      endfunction
      function Complex mul(input Complex a, b)
          mul.r = (a.r * b.r) + (a.i * b.i);
          mul.i = (a.r * b.i) + (a.i * b.r);
      endfunction
  endnamespace : ComplexPkg
Certainly, one of the ways to utilize declarations made in namespaces,
is to reference them hierarchically:
ComplexPkg.Complex cout = ComplexPkg.mul(a, b);
Import Syntax
|  namespace_import_declaration ::= { attribute_instance } import namespace_import_item { , namespace_import_item } ; namespace_import_item ::= namespace_identifier . identifier | namespace_identifier . *  | 
         
The import statement provides direct visibility of symbols within namespaces.
It allows those symbols declared within namespaces to be visible within the
 current scope by its declared simple name. Two forms of the import statement
 are provided. The first form is an explicit import and allows control over
 precisely which  symbols are imported:
  
import ComplexPkg.Complex;
  import ComplexPkg.add;
  
The second form of import is a wildcard import and allows all symbols
defined within a namespace to be imported as a group:
  
import ComplexPkg.*;
Explicit imports are treated similarly to a declaration.
An explicit import is illegal if another symbol by the same name has already
 been declared or imported into the same scope. Similarly, after importing
 a symbol by a given name, it's illegal to then declare a symbol by that
same  name within the same scope.
  
Wildcard imports have somewhat different restrictions. All the symbols
 within a namespace implied by a wildcard import are candidates for import.
They in fact become imported only if there are no other symbols by the same
name declared or imported in the same scope. Similarly, their visibility
may be limited by a subsequent declaration of the same name in the same scope.
It is also possible for two symbols in two wildcard imports to "hide" each
other.
  
Import statements usually affect the scope in which they appear. The exception
 to this policy is when one or more import statements appears immediately
prior to a module or interface declaration. In these cases, the import statement(s)
 affect the subsequent module or interface scope. Thus:
  
import ComplexPkg.*;
  module cadder(input Complex a, b, output Complex z);
      assign z = add(a, b);
  endmodule