From: Stephen Williams (steve@icarus.com)
Date: Mon Sep 15 2003 - 18:57:51 PDT
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.