[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: gEDA-user: Icarus/NC mismatch -- who's right?
Ah yes... some instrumentation (below) demonstrated it. Thanks!
module junk;
   reg [3:0] pi, ci, fill;
   reg [31:0] my_word;
   reg [31:0] fifo [0:7];
   initial begin
      // Put some data in a fifo.
      fifo[0] = 1;
      fifo[1] = 2;
      fifo[2] = 3;
      fifo[3] = 4;
      fifo[4] = 5;
      fifo[5] = 6;
      fifo[6] = 7;
      fifo[7] = 8;
      // Initialize Producer Index and Consumer Index
      pi <= 4;
      ci <= 0;
      $display("%m : initial done.");
   end
   // Compute FIFO fill level
   always @(pi or ci) begin
      $display("%m : level evaluation.");
      fill = (pi - ci);
      $display("%m : fill updated to %0d",fill);
   end
   // Drain FIFO whenever not empty
   always @(fill) begin
      $display("%m : drain evaluation.");
      while (fill > 0) begin
	 $display("%m : fill seen as %0d",fill);
	
	 read_word(my_word);
	 $display("%m : got word 0x%h\n",my_word);
      end
   end
   task read_word;
      output [31:0] word;
      begin
	 $display("%m : entering task.");
	
	 word = fifo[ci[2:0]];
	 ci <= ci + 1;
	 @(ci);
	 $display("%m : leaving task.");
	
      end
   endtask // read_word
endmodule
Gave me this:
junk : initial done.
junk : level evaluation.
junk : fill updated to 4
junk : drain evaluation.
junk : fill seen as 4
junk.read_word : entering task.
junk.read_word : leaving task.
junk : got word 0x00000001
junk : fill seen as 4
junk.read_word : entering task.
junk : level evaluation.
junk : fill updated to 3
junk.read_word : leaving task.
junk : got word 0x00000002
junk : fill seen as 3
junk.read_word : entering task.
junk : level evaluation.
junk : fill updated to 2
junk.read_word : leaving task.
junk : got word 0x00000003
junk : fill seen as 2
junk.read_word : entering task.
junk : level evaluation.
junk : fill updated to 1
junk.read_word : leaving task.
junk : got word 0x00000004
junk : fill seen as 1
junk.read_word : entering task.
junk : level evaluation.
junk : fill updated to 0
junk.read_word : leaving task.
junk : got word 0x00000005
junk : level evaluation.
junk : fill updated to 15
junk : drain evaluation.
junk : fill seen as 15
junk.read_word : entering task.
junk.read_word : leaving task.
junk : got word 0x00000006
junk : fill seen as 15
junk.read_word : entering task.
junk : level evaluation.
junk : fill updated to 14
junk.read_word : leaving task.
Evan Lavelle wrote:
Mark Schellhorn wrote:
Who's right? It kind of looks like the read_word() task fails to wait 
for @(ci) before leaving???
They're both right - you've got a race between your fill calculation and 
the inner read/display loop. for your code to work, the '@(ci)' timing 
control must lead immediately to a new fill level calculation, but 
there's no guarantee of this in Verilog. For Icarus, when the first 
@(ci) is hit, the drain process is rescheduled; for subsequent @(ci)'s, 
the fill level process is scheduled. This means that you go around the 
inner loop 5 times in Icarus (but presumably 4 times in NC-Verilog). 
After 5 iterations the FIFO has underflowed, so you carry on for ever 
(since regs are unsigned).
Evan