Question

I am writing a systemverilog module and I need to make sure that a certain macro is set to allow compilation to proceed.

I have tried the below, but it simply gives the syntax error "unexpected SYSTEM_IDENTIFIER" $fatal.

I know that does technically stop the compilation, but does anyone know of a more graceful solution?

* Correction, if the syntax in the `else branch is not correct, none of the branches will compile successfully.

`ifdef MACRO_0
// Some code
`elsif MACRO_1
// Some other code
`else
$fatal("MACRO_0 or MACRO_1 must be set for compilation");
`endif

As per recommendation, adding the below information to the question:

The code is in a module but not inside an initial or always statement. I am hoping to find a solution that will allow me to terminate the compilation i.e. elaboration of hdl. I am designing for FPGA implementation and I need to make sure that no other user of this code can reach the synthesis phase of a design flow without setting one of these macros.

Was it helpful?

Solution

$fatal is a run-time system call, not a compile-time fatal as mentioned by toolic. I don't think you can stop the compile unless you have a compile error. In your sample code you are getting close to what you want by hiding part of the code, but the compile does not terminate and you don't print the right message.

I am not aware of any standard Verilog/SystemVerilog construct for printing a customized message during the compile time. GCC for example, has #error for this purpose. However, some synthesis tools, like Synopsis Design Compiler do print the output of $display messages during elaboration time. The $display still needs to be inside an always block. If you also deliberately place an elaboration error when MACRO0 and MACRO1 are not defined, you may be able to terminate the synthesis.

For example, in the following, a dummy module is instantiated without defining its body:

`ifdef MACRO_0
// Some code
`elsif MACRO_1
// Some other code
`else
 logic a;
 always $display("MACRO_0 or MACRO_1 must be set for compilation");
 DEFINE_MACRO0_OR_MACRO1 dummy (.in(a));
`endif

this will generate the following elaboration message:

$display output: MACRO_0 or MACRO_1 must be set for compilation
...
Information: Building the design 'DEFINE_MACRO0_OR_MACRO1'. (HDL-193)
Warning: Cannot find the design 'DEFINE_MACRO0_OR_MACRO1' in the library 'WORK'. (LBR-1)
Warning: Unable to resolve reference 'DEFINE_MACRO0_OR_MACRO1' in 'TEST'. (LINK-5)
0

OTHER TIPS

$fatal is also an elaboration task added in IEEE Std 1800-2009 in section 20.10. See IEEE Std 1800-2012 § 20.11 Elaboration system tasks. It can be used inside an generate block. The follow should work if the simulator is *09+ complaint.

...
`else
//inferred generate block
if (0) $fatal(1,"MACRO_0 or MACRO_1 must be set for compilation");
`endif

I tried it out on edaplaygrond but it looks like ModelSim10.1d does not support it. In the mean time, like others have suggested, you can do the following:

...
`else
CAUSE_ELAB_ERR fatal("MACRO_0 or MACRO_1 must be set for compilation");
`endif

Using an initial terminates the simulation at time 0. It does not terminate the compilation.

module tb;

`ifdef MACRO_0
// Some code
`elsif MACRO_1
// Some other code
`else
initial $fatal(1, "MACRO_0 or MACRO_1 must be set for compilation");
`endif

endmodule

at least in VCS $fatal is a system task for runtime,not elab/compile

Error-[SE] Syntax error Following verilog source has syntax error : Using elaboration system tasks requires option -assert svaext "bla.sv", 10: token is ';' $fatal("MACRO_0 or MACRO_1 must be set for compilation");
^

adding the proper switch allows it to go through in compilation time. i don't know the FGPA compiled you are using, but maybe it has similar switch

I know this is an old thread, but since the question was asked, the support for elaboration system tasks has improved quite a bit. The original code should now work as intended on most tools (e.g. Cadence Xcelium, Synopsys VCS and Mentor Questasim).

It can also be noted that the problem probably can be better solved by module parameters:

if (!(PARAM_0 || PARAM_1))
  $fatal(1,"your error message");
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top