1
votes

I have a verilog header file enclosed within include guards. It contains some functions which i use to define local parameters within other rtl files. This include file gets referenced within modules description (module (port instantiation) `include.... (body) endmodule). I always thought when verilog compiled each module the scope of that inclusion would be local to that module and it would only enforce the guard within the module. I've been compiling all the modules in the project now and it seems like the second time the inclusion is referenced in another module the guard is still on. Is this something to do with how preprocessor behaves for systemverilog?

3

3 Answers

2
votes

Verilog has sticky semantics for the files it compiles. It means that if you have several files on the command line, macros defined in one file remain defined in other file as well.

a.v

`include "h.vh"
`define A_V 1

b.v

`include "h.vh"
...
assign A = `A_V;

So, macro A_V is available in file b.v if you compile them in the following order: a.v, b.v.

As a result, if h.vh uses guard macros, it will only be parsed as included in a.v and will be guarded in b.v and not parsed.

Now suppose that you contain definitions of parameters of functions in h.vh:

`ifndef H_VH
`defien H_VH
paremeter I = 10;
`endif

and it gets include in the module body:

a.v

module A;
`include "h.vh"
assign A = I;
endmodule

b.v

module B;
`include "h.vh"
assign B = I;
endmodule

Now, when the file gets included inside module A first, the parameter is now defined inside module A. But the macro H_VH is also defined. The include file will not be parsed the second time in the 'b.v' file. So, inclusion it inside the module will not expand to the parameter definition and compilation fails, because there is no I available.

Guard macros in verilog are useful if the file is included in the global scope, outside the modules. They create a lot of issues, if included inside scopes. The rule o thumb is to use them for globally included headers and never use them if the header is include in a scope. Never ever mix global and scope inclusions.

And yes, as everyone already mentioned, in system verilog you'd better use packages for this. In regular verilog you have no other choice for scoping common declarations.

1
votes

When you say guard, I'm assuming you mean something like:

`ifndef MY_GUARD
`define MY_GUARD
// ... definitions for parameters, functions, etc. ...
`endif // MY_GUARD

`ifdef, `ifndef, `define, and other related ` operations are dependent on compile order. Macro definitions exist in the global space from moment they are defined until they are undefined. In the example above, once MY_GUARD is defined any `ifndef MY_GUARD will evaluate to false until it is undefined (`undef MY_GUARD).

If you want to include the same file in multiple modules, then remove the guards.


Since you are using SystemVerilog. Consider putting the common code in a package then import it to each module.

1
votes

You don't really need compile guards in SystemVerilog. With the proper use of packages, your compile scripts should compile everything in the proper order. The only exception might be for including text macros.

Tools have several use models for compiling files and how compilation units are formed. If you have

compile file1 file2

In the single file compilation mode, this is the same as if you entered

compile file1
compile file2

In this mode, all compiler directives do not carry over from one file to the next. And the orfer of compilation does not matter except that a package must be compiled before it can be imported.

In the multiple file compile mode, any `defines in file1 carry over to file2. So the order of the files matter.