Simulation hangs when using fork_join_none inside forever

Hi All,

My objective is to use two thread inside fork join_none; one thread will drive reset related stimulus and other when there is no reset.
could any one point one where i am doing mistake and what is the solution?

`timescale 1ns/1ps

interface fjn_intf(input bit clk,rst);
  logic [7:0] data;
  logic [3:0] addr;
endinterface


class my_driver;

  // virtual inteface handle
  virtual fjn_intf vif;
  
  //new constructor
  function new (input virtual fjn_intf vif);
    this.vif = vif;
  endfunction

  // run_t method
  task run_t();
    
    forever
      begin
      fork
        begin: RESET_THREAD
          @(negedge vif.rst);
          vif.data <= 'b1;
          vif.addr <= 'b0;
        end

        begin: NORMAL_OP
          wait(vif.rst == 1'b1);
          @(posedge vif.clk);
          vif.data <= $urandom_range(39,51);
          vif.addr <= $urandom;
        end
      join_none
    end

  endtask:run_t
endclass

module fork_joinnone_forever;
  //local declared  clock and reset
  logic clk,rst;

  //instantiate interface and pass the clk,rst
   fjn_intf intf(clk,rst);

  // driver class handle;
  my_driver drvh;

   initial
      begin
       drvh = new(intf);
       drvh.run_t;
     end


  initial
    begin
      clk <= 1'b0;
      $dumpvars;
      $dumpfile("fork_joinnone.vcd");
      #30 $finish;
    end

    initial
       begin
          repeat(50)
            begin
              #0.25ns clk = ~clk;
            end
       end

      initial
        begin
         rst <= 1'b1;
         repeat(3) @(negedge clk)
           rst <= 1'b0;
         repeat(2) @(posedge clk)
          rst <= 1'b1;
        end  
endmodule

The logic inside the forever loop is flawed.

Let us trace this logic.

  1. the forever starts
  2. fork… starts two threads
  3. While both threads are waiting for some events the join_none is
    encountered. Execution continues.
  4. Goes back to step 1 above and two more threads are created.

In summary this simulation will create infinite threads in no time
and the simulation hangs.

In reply to VLSI_ENTHU:

Please use code tags making your code easier to read. I have added them for you.

You have a forever loop with no delay, which means the time cannot advance. You proably want to use join_any instead of join_none.

task run_t();
 
    forever
      begin
      fork
        begin: RESET_THREAD
          @(negedge vif.rst);
          vif.data <= 'b1;
          vif.addr <= 'b0;
        end
 
        forever begin: NORMAL_OP
         @(posedge vif.clk iff vif.rst == 1'b1);
          vif.data <= $urandom_range(39,51);
          vif.addr <= $urandom;
        end
      join_any
      // can only get here on reset.
      disable fork;
    end
 
  endtask:run_t

In reply to dave_59:

Hi Dave,

Thanks for your response and Your suggested solution works.

But i need your help to understand the fork -join_none behavior.I am using @(posedge vif.rst) or @(posedge vif.clk) in RESET and NORMAL_OP thread,so can’t they be considered as timing control event? they definitely introduce some delay as waiting for an event is involved.
So Simulation hangs because of 1) simulation is not getting advanced OR 2) infinite number of threads spawned at zero time which occupied entire CPU Memory and got stuck?

Thanks.

In reply to VLSI_ENTHU:

The @(posedge clk) timing controls are in the threads that have been forked, not the thread containing the forever loop. The forever loop just repeated forks off threads without every giving them a chance to execute.