Error "procedural assignment to a non-register result is not permitted"

Helyx picture Helyx · Jul 17, 2015 · Viewed 23.4k times · Source

I'm getting the error

[Synth 8-2576] procedural assignment to a non-register result is not permitted ["lpm_mult.v":29]

What am i doing wrong?

module lpm_mult (
    dataa, datab,     // multiplicand,multiplier
    sum,              // partial sum 
    clock,            // pipeline clock
    clken,            // clock enable
    aclr,             // asynch clear
    result            // product
);

input  clock;
input  clken;
input  aclr;
input  [31:0] dataa;
input  [31:0] datab;
input  [63:0] sum;
output [63:0] result;

always @ (clken or posedge clock) begin
    if (1==clken) begin
        assign result = dataa * datab;
    end
end

endmodule

Answer

Greg picture Greg · Jul 17, 2015

There are more issues then then giving error message. As others have already pointed out result should be defined as output reg [63:0] result;

The other issues will not generate a compiling error; they are generating incorrect behavior and are unsynthesizable. With the code:

always @ (clken or posedge clock) begin
    if (1==clken) begin
        assign result = dataa * datab;
    end
end
  • clken is asynchronous trigger; it should not be in the sensitivity list.
  • An assign statement inside the always block is call a procedural continuous assignment. Once the assignment is triggered, it will be continuously and immediately updated on any change to dataa or datab (ignoring the conditions of clken and clock).

    • Note: IEEE is considering depreciating procedural continuous assignment, so in the future it will likely become illegal syntax. IEEE Std 1800-2012 C.4.2 Procedural assign and deassign statements:

      The procedural assign and deassign statements can be a source of design errors and can be an impediment to tool implementation. The procedural assign and deassign statements do not provide a capability that cannot be done by another method that avoids these problems. Therefore, the procedural assign and deassign statements are on a deprecation list. In other words, a future revision of IEEE Std 1800 might not require support for these statements. This current standard still requires tools to support the procedural assign and deassign statements. However, users are strongly encouraged to migrate their code to use one of the alternate methods of procedural or continuous assignments.

      Regular continuous assignments (assign outside of procedural block) will remain as legal legal syntax.
      Verilog and SystemVerilog were officially merged by IEEE with IEEE Std 1800-2009.

  • Synchronous logic should use non-blocking (<=) assignments. It is legal syntax to blocking (=) assignments in synchronous logic blocks, but is it not recommenced. Using blocking assignments in synchronous logic blocks may cause race conditions in the simulator resulting in behavioral mismatch between RTL and synthesized circuit.

    • Note: assign statements must use blocking assignments (non-blocking is illegal syntax).

Your code should look something line the following to compile and behave correctly in simulation:

...
output reg [63:0] result;

always @ (posedge clock) begin
    if (clken==1) begin
        result <= dataa * datab;
    end
end