Electronic – Initialize variable used in always_ff block

fpgasimulationsystem-verilog

I have a bunch of (System) Verilog code that uses initialization statements. This is code for an Altera FPGA. I test the code using automated testbenches in the version of modelsim that ships with quartus, and it all works fine. However, I have been trying to move some of our test benches to the cadence simulator, and it is complaining. A simple example of code that fails is this:

reg [15:0] counter = 0;

always_ff @(posedge clk) begin
    counter = counter + 1'b1;
    display("counter: %4X", counter);
end

This give an error in the cadence simulator that it is not allowed for counter to have multiple drivers because it is used in an always_ff block.

Is this error correct? Two tools say that code is OK, and one fails. The rules I have found for always_ff state that "a variable assigned in an always_ff, always_comb, or always_latch may not be assigned in by any other process". This makes sense, but it seems strange that the initial value would be considered a process, and in any case would make those language features mutually incompatible.

So is there a correct way to use initializers along side system verilog new style always_* processes? Does this behavior depend on the version of the system verilog standard such that I might be able to tell my tools which one to use? Or are my choices to use explicit reset lines only, or stick to old style always blocks?

Best Answer

I see that Cadence and Synopsys both produce an error for this code. I also see that Mentor and Aldec both allow driving initialized variables in always_ff blocks. This suggests that the correct behavior is not properly defined in the LRM.

Relying on power-up values for FPGA designs is perfectly viable. Altera's recommended coding guideline is to use always @(posedge clock), so I would suggest that you do this as a workaround. Alternatively you can use a different simulator.

Cadence's behavior arguably makes sense for ASIC designs, where you can't rely on initialization of registers. Adding an initialization value for a variable by mistake could hide missing reset bugs in simulation.

Related Topic