Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
12 years ago

Verilog with ANSI-style regs, non-zero initial value is not synthesised correctly!

Hi,

We raised this with Altera and had it confirmed in Quartus V13, but the issue is not fixed in 13.sp1 so I thought I would raise awareness here in the hope it might save anyone else debugging time.

If you have a Verilog module with 'ANSI-style' port lists, any 'reg' output ports that are initialised in line to be non-zero will incorrectly initialise to zero after synthesis. Value of y also has to be modified, ie. not reducible to a constant expression.

module mux8 (
    output reg  y = 8'd4,
    input wire a,
    input wire  b,
    input wire clk);
...
    always @(posedge clk)
        y <= a ? y : y + 1;
endmodule

We debugged this from a hardware mismatch, and luckily, if you simulate the post-synthesis netlist with vendor part library you can spot the difference against the same module under HDL simulation!

Altera stated that in-line initialisation/default value is not a supported V2001 language feature, and added a feature request. We argued this should be a bug fix for the service pack cycle, since you get a simulation/synthesis mismatch with zero warnings. Tools should either synthesise correctly or fail! Modelsim etc. follows V2001 correctly.

The obvious workaround is to convert the port to a wire, then use an explicit assign from a register declared internally.

module mux8 (
    output wire  y,
    input wire a,
    input wire  b,
    input wire clk);
...
    reg  yreg = 8'd4;
    assign y = yreg;
...
    always @(posedge clk)
        yreg <= a ? yreg : yreg + 1;
endmodule

Happy debugging!

Chris

(Updated to indicate the process is clocked)

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    module mux8 (
        output reg  y = 8'd4,
        input wire a,
        input wire  b,
        input wire en);
    ...
        y <= a ? y : y + 1;
    endmodule

    The code example doesn't seem to make sense without an edge-sensitive always block.

    P.S.: The workaround must increment yreg instead of output variable y.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Yeah, I've updated to indicate it's clocked and driven yreg in the workaround. The example posted in the service request was somewhat more detailed. Thanks.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    This came up for me around a year ago. It took a while to track it down to being a Quartus problem since the simulations passed and there were no errors or warnings in Quartus. When I mentioned it to an field applications engineer (not a direct Altera FAE, rather a local distributor FAE who happens to cover Altera), the response was "well, don't write your code like that."

    --- Quote Start ---

    The obvious workaround is to convert the port to a wire, then use an explicit assign from a register declared internally.

    --- Quote End ---

    Personally, I go with initial statements because the meaning and intention are a little clearer to me. Initial statements are supported by Quartus.

    
    module mux8 (
        output reg  y,
        input wire a,
        input wire  b,
        input wire clk);
    ...
        initial begin
            y = 8'd4;
        end
        always @(posedge clk) y <= a ? y : y + 1;
    endmodule
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I'm sure everyone who's bitten by this learns the hard way. Probably cost us about 20 hours engineering time to go from malfunction all the way back through reproducing in post-synthesis then observing the difference vs. original HDL synthesis. Really is a nasty one to catch you out if you happen to drift a bit to much into the "new style" Verilog spec.