Re: udp scheduling semantics

From: Stephen Williams (steve@icarus.com)
Date: Mon Sep 15 2003 - 18:57:51 PDT

  • Next message: Brad.Pierce@synopsys.com: "errata/283: PROPOSAL - Syntax 2-1: 'dx, 'dz"

    Steven Sharp wrote:

    > They may be seeing a UDP output change that is delayed until after
    > some other events, and assuming that it must be on the NBA queue.
    > But it is hard to tell whether the change happened just before the
    > NBA queue, or at the beginning of the NBA queue.

    OK, by your reasoning, the attached sample has a race in it.
    To wit, the "ce" which is registered by a sequential primitive
    may get to another thread or device that is activated by the
    same clock but uses the "ce" as an enable.

    In Icarus Verilog, it turns out that all the clocked devices
    are activated at once, and subsequent events are enqueued in
    FIFO order within an activation queue, so in my simulator there
    is no race for this example.

    But a simulator that processes all propagation events, including
    the output of the sequential primitive, before it processes any
    activated behavioral threads, might turn on the "ce" before the
    thread that reads it is scheduled. The "out" value would then
    activate one clock too early. The same device, modeled with a
    non-blocking assignment, is free of races.

    I can contrive slightly more complicated examples that have
    races (assuming "active" scheduling) even with purely FIFO
    schedulers, but the ideas in my head put combinational logic
    on one clock input.

    These are exactly the sorts of complaints I hear from users,
    and why I've heard of some writing udps out of their libraries.

    -- 
    Steve Williams                "The woods are lovely, dark and deep.
    steve at icarus.com           But I have promises to keep,
    http://www.icarus.com         and lines to code before I sleep,
    http://www.picturel.com       And lines to code before I sleep."
    

    primitive FF(Q, C, D);
       output Q;
       input D, C;
       reg Q;
       initial Q = 0;

       table
          // C D Q Q+
          (01) 0 : ? : 0 ;
          (01) 1 : ? : 1 ;
          (0?) 1 : 1 : 1 ;
          (0?) 0 : 0 : 0 ;
          (?0) ? : ? : - ;
          ? (??) : ? : - ;
       endtable

    endprimitive // FF

    module top;

       reg clk;
       always begin
          #5 clk = 0;
          #5 clk = 1;
       end

       reg [1:0] count = 0;
       always @(posedge clk) count <= count + 1;

       // ce is a delayed count[1]. It is common to use a delayed
       // enable to match pipeline delays.
       wire ce;
       FF delay_by_1 (ce, clk, count[1]);

       // This is a trivial thread that uses the delayed ce. The
       // out value should take a 1 value on the clk *after* the
       // ce goes active, and fall on the clk after ce goes inactive.
       // This is normal synchronous logic pipelining.
       reg out = 0;
       always @(posedge clk)
         if (ce)
           out <= 1'b1;
         else
           out <= 1'bz;

       // If the ce update is scheduled before the "out" thread is
       // executed (FIFO order is not guaranteed) then the out value
       // will change one clk too soon.

       initial begin
          $monitor("clk=%b, count=%b, ce=%b, out=%b", clk, count, ce, out);
          #83 $finish;
       end

    endmodule // top



    This archive was generated by hypermail 2.1.4 : Mon Sep 15 2003 - 18:09:32 PDT and
    sponsored by Boyd Technology, Inc.