Verilator does a great job notifying you about any possible source of error in your Verilog code. However, it’s not really the best sight getting a screen full of assorted warnings and errors whenever you compile a code with Verilator that was just working perfectly on Icarus. I don’t like warnings so I shot them down one by one until Verilator had absolutely nothing to say. This blog explains a couple of tough warnings that I had to figure out on my own and the simple ones as well.

  • Message: %Error: mem_load.v:163: Unsupported tristate construct (not in propagation graph): COND
Sample code: always @(posedge clk_i) x <= (y)? 1'bz : m;

Solution: Verilator doesn’t allow you to create a tristate buffer using non blocking assignment. You must use blocking assignment in a combinational block.

  • Message: %Warning-REDEFMACRO: Redefining existing define: VERILATOR, with different value:

Solution: This one was a bit tough cause it doesn’t say where in the file is the macro being redefined. Turns out that Verilator defines by default this macro “VERILATOR” so you can straight away use it in your code without having to define. 

And here is some general reminders that will just trigger warnings:

  • Verilator doesn’t support delays
  • Verilator expects conditions to return one bit after evaluation so if you are putting an integer there better put it as (x==0)
  • Verilator expects RHS width to be equal to the LSH is assignment statements
  • Verilator expects non blocking assignments to appear in sequential blocks only and blocking assignments in combinational ones.

Actually those warnings are very useful to ensure that your code is well written and you can learn several deep concepts in Verilog if you investigate the reason behind each warning. Even though I am complaining I have to admit that those warnings are what motivated me to use Verilator to ensure my code is free of any language ambiguities.

And that’s all about Verilator, good luck shooting down your share of warnings!