Re: Fwd: Verilog Races in Combinatorial Logic

From: James A. Markevitch (jam@magic.com)
Date: Thu Sep 21 2000 - 08:19:45 PDT


The point is not that your example was pathological, but that it assumed
a single-threaded programming environment, rather than a multi-threaded one,
which Verilog is.

Your example, using the always blocks, would be a dangerous programming
practice in any multi-threaded environment. And as I indicated in my
earlier email, always blocks are considered to be separate threads.

In any other multi-threaded language, I would do the equivalent of the
following:

    always @(posedge clk) begin
        reg tmp;

        a = ...
        b = ...
        c = ...
        tmp = a & b & c;
        cucu = tmp;
    end

    always @(posedge clk) begin
        reg tmp;

        tmp = d | e | f;
        dudu = tmp;
    end

Most multi-threaded environments would *not* make changes to ensure that
the variable "tmp" is race-free. The environment would not be able to know
which variables you want shared between threads and which you don't.
Generally, you need to identify such variables and/or explicitly indicate
a critical region of code (via locks, for example).

A high-quality tool, however, might emit a warning for variables which are
assigned in multiple threads.

Perhaps the standard should include a clear warning to the effect that:
DON'T ASSIGN VARIABLES IN MULTIPLE INITIAL OR ALWAYS BLOCKS UNLESS YOU
HAVE CLEARLY CONSIDERED THE IMPLICATIONS OR RACE CONDITIONS; IF YOU DON'T
NEED TO, DON'T DO IT.

James Markevitch

> I believe I have given an example of a common programming practice which all beh
> avioral Verilog coders will use. No one has ever
> feared to use such a structure. It is forbidden for us to cause such code to be
> "broken".
> It is not a pathological example.
>
> (I think that multi-thread environments of regular programming languages take sp
> ecial precautions,
> such as variable aliasing, to ensure that such problems will not occur.)
>
> Similarly, I can make an example using always constructs and temporary variables
> , which most normal programmers will always assume
> to be problem-free.
>
> always @(posedge clk) begin
> a = ...
> b = ...
> c = ...
> tmp = a & b & c ;
> cucu = tmp ;
> end
>
> always @(posedge clk) begin
> tmp = d | e | f ;
> dudu = tmp ;
> end
>
> (Remember, I am writing behavioral code, not a hardware description, and certain
> ly not intended for synthesis.)
>
> The key intuitive assumption, which I believe it is forbidden for us to break if
> Verilog is to flourish, is that within a given
> procedural block without any delays or event controls, a variable will retain it
> s value from line to line, assuming also that the
> procedural block does not trigger any additional process which can feed back to
> change the value of such a variable.
>
> In the example above, for example, I will assume that "tmp" will retain its valu
> e between its assignment and its usage, because the
> procedural block does not trigger any event which can change its value.
>
> On the other hand, if I have "assign b = func(c) ;", then I cannot assume that b
> will retain its value between its assignment and
> its usage because I have violated the conditions I stated.
>
> Shalom



This archive was generated by hypermail 2.1.4 : Mon Jul 08 2002 - 12:54:13 PDT and
sponsored by Boyd Technology, Inc.