9
\$\begingroup\$

I have a parameterised module in verilog, where the parameters are a clock rate and refresh rate, which is used to calculate how many cycles of inactivity are inserted between instances of a repeating operation. However, it is very easy to set parameters that cannot be attained (because the operation takes a non-trivial length of time, so the repeat would have to occur before it had completed), and at the moment the design does not give any feedback on this.

I was wondering if there was some way I could trigger an error during synthesis (or compilation prior to simulation) if the conditions cannot be met (i.e. if one localparam is less than another)? Some equivalent of the popular C/C++ compile-time-assert hack, perhaps.

\$\endgroup\$
10
\$\begingroup\$

I'm sure there is some way to bind in a C/C++ compile time callback. However, as long as your supports generate blocks (introduced in IEEE Std 1364-2001), then you can do something like the following:

generate
if (CONDITION > MAX_ALLOWED /* your condition check */ ) begin
    illegal_parameter_condition_triggered_will_instantiate_an non_existing_module();
end
endgenerate

If the condition is true, then the compiler will give an error because there is a request for something that doesn't exist. If the condition is false, then the operation is skipped. The only requirement is the code for the illegal condition follows legal Verilog syntax and the illegal condition will never accidentally become valid (hence the long and verbose non-existing module name).

If your simulator and synthesis tools support IEEE Std 1800-2009 (SystemVerilog revision released in 2009) or newer revision, then you can use $error() and give a more meaningful message to go with the error. I'm not sure if any venders has implemented this feature yet. It should become the preferred method once most venders implemented, therefore I will give an example:

generate
if (CONDITION > MAX_ALLOWED /* your condition check */ ) begin
    $error("%m ** Illegal Condition ** CONDITION(%d) > MAX_ALLOWED(%d)", CONDITION, MAX_ALLOWED);
end
endgenerate
\$\endgroup\$
1
\$\begingroup\$

You could do something like this:

module test();

  parameter VALUE=16;

  // VALUE should be between 16 and 64
  wire [64:16] range_for_value;
  assign range_for_value[VALUE] = 1'b0;

endmodule

Tools may treat this slightly differently, but if VALUE is not within the expected range it really should be an error since the bit index for the assign statement will be out of bounds of range_for_value.

\$\endgroup\$
1
\$\begingroup\$

Is it really true that there is nothing like "assert" in Verilog? This is pretty basic stuff!

If your tools support mixed language, you could add a module that is just a VHDL entity with the necessary ports or generics and the obvious ASSERT statement. For compile or elaboration time determinable conditions, this will work equally well in sim or synthesis (at least with XST or Synplicity).

entity CheckSize is
   generic (depth : natural := 16);
   port (data : std_logic_vector);
end CheckSize;

architecture empty of CheckSize is
begin
   Assert depth * data'length <= 256 Report "Size too large!" 
      severity Failure;
end empty;

None of the answers so far are really satisfactory except perhaps the "System Verilog 2009" $error() one but this is probably the easiest across the widest range of tools.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.