Search code examples
verilogvhdlsystem-verilog

Why would a simulation/synthesis mismatch occur with non-blocking initialization of signals?


In the VHDL world, it is common in a clocked process to initialize a signal to a default value and then override it later (via IF or CASE statements) as necessary. I want to use the same technique in Verilog, but have been told it could be problematic.

Consider this example code:

  always_ff @(posedge sys_ref_clk or negedge rst_n)
    if (~rst_n) begin
      mstate <= STATE1;
      mysig <= '0;
    end else begin
      mysig <= '0;
      case (mstate)
        STATE1 : begin
          if (go) begin
            mstate <= STATE2;
          end
        end
        STATE2 : begin
          mysig <= '1;
          mstate <= STATE3;
        end
        STATE3 : begin
          mstate <= STATE1;
        end
      endcase
    end

Here, I want STATE2 to cause mysig to become 1, and all other states cause mysig to become 0. I do not want to have to type mysig <= '0; in STATE1 and STATE3, so I just set a default and only override it in STATE2.

In VHDL, the above is a technique I used successfully for many years. But upon switching to Verilog and to a new linter, I get lint errors such as the following:

[211] OverridenAssignment error
/path/to/file/myfile.sv 14 5 Flipflop 'mysig' is assigned over the same signal in an always construct for sequential circuits (at line '6')

I believe this is an overzealous lint error, but I admittedly don't know Verilog as well as I know VHDL. When I asked the person in charge of our lint tool about it, I was told that in Verilog, this might be dangerous -- specifically because non-blocking assignments can lead to inefficient or incorrect hardware structures, especially when used for initialization -- also that non-blocking assignments may be interpreted differently between synthesis and simulation tools.

Is this really the case that the above initialization of mysig is dangerous Verilog? It simulates just fine. What other way could a synthesis tool interpret this besides the (obvious, IMO) way it was intended?


Solution

  • I don't see a problem with the posted code. "The last assignment wins" when referring to the behavior in a process is common to VHDL & Verilog. As long as you use nb assignments for synchronous processes, & blocking for combinational you should be fine. I have used the state machine style with the driver before the case statement, so that you don't need to specify a value in all states. Worked with no errors or warnings in Vivado.

    This issue has been written about, probably in more than one place. Stu Sutherland discusses this style and has a section titled "Pros & Cons of pre-case assignments before decision statements" in his 2017 book "RTL Modeling with SyntemVerilog for Simulation & Synthesis".

    Sutherland states "A disadvantage of this coding style is that in can be more difficult to see what is assigned to all the variables used by the procedure by looking at a specific case item branch. It is necessary to look at the pre-case assignment and the case item assignments to see all the values assigned. In a large, complex decoder, these assignments could be separated by many lines of code."

    I find the pre-case assignment overall easier to read, and harder to make a mistake. If I have to put the same foo = 1; in each arm of the case statement, tomorrow I will add a state and forget to put foo = 1; in for the new state, and now have something to debug. I will be lucky to find it myself tomorrow the same day I put the bug in.

    Verilog has an initial process block which may or may not be used for setting initial values depending on the synthesis tool and exactly what you are trying to do. Consult the synthesis guide for the particular family of part you are targeting for things like what it will do with initial blocks.

    For edgy constructs like assignments in an Verilog initial block (referring to synthesis) The problem could become one of Vendor portability. One vendor might support the construct where the other may not. So there is risk in coding using that style.