How to fork multiple forever blocks with for loop

Hi,
I want to fork multiple forever blocks using for loop. what is the best way!!
not sure if the solutions I’m trying below would work.
Thanks in advance.


//required output
fork //fork 3 forever blocks
  forever begin
    wait(xyz[0] == 1);
    //code for loop0
  end
  forever begin
    wait(xyz[1] == 1);
    //code for loop1
  end
  forever begin
    wait(xyz[2] == 1);
    //code for loop2
  end
join

//solution im thinking
//***********want to wait till three forever blocks join**************
for(int i=0; i<3; i++) begin
  fork
    automatic int j = i;
    forever begin
      wait(xyz[j] == 1);
      //code inside task written below but explicitly written here
    end
  join
end
    
//alternate trial - ideally I think both solutions give the same result
//just thinking forever might cause hang to the code above. So moved it into the task
for(int i=0; i<3; i++) begin
  fork
    automatic int j = i;
    myLoop(j); //task
  join
end    
    
task myLoop(int i);
  forever begin
    wait(xyz[i] == 1);
    @(posedge m_vif.uclk);
    if(!Flag[i]) begin
      wait_time[i] = getWaitTime();
      Flag[i] = 1;
    end
    memclk_cycle[i] += 1;
    if (memclk_cycle[i] == wait_time[i]) begin
      Flag[i] = 0;	
      memclk_cycle[i] = 0;
      xyz[i] = 0;
    end
  end
endtask

In reply to NaveenReddy:

Your solution and alternate have no fork statements. And without knowing what kind code you intent to put in the loop, it will be hard to give a best recommendation.

In reply to dave_59:

Hi Dave, thanks for pointing out the missing fork join. I have updated my code and the code i would be placing inside forever block.

In reply to NaveenReddy:

There really is no difference in terms of potential to hang if you put the code in a task or not.

It’s up to you to decide if using the task makes your code more readable. If this is a method of a class, putting it in a task makes it easier t override.

BTW, I recommend that you keep things synchronized by only using a clock edge and not using wait statements. Use

    @(posedge m_vif.uclk iff xyz[i] == 1)

In reply to dave_59:

Thanks Dave for the suggestion.

will the fork waits for all the three forever loops to join?

Also, in some post I read you suggesting to use it like below #1
what would be the best way to use #1 or #2 ?


// #1
forever @(posedge m_vif.uclk iff xyz[i] == 1) begin
  //code
end

//#2 
forever begin
  @(posedge m_vif.uclk iff xyz[i] == 1);
    //code
    // Question: is this way #2 correct or should the code be embedded in begin end blocks ?
  
end

In reply to NaveenReddy:

You need to use fork/join*_none*. I missed that.

You can put endless number of begin/ed blocks around a single statement. I prefer to use the minimum required, but sometimes it can make the code more readable. For example

if (cond)
  statement1;
  statement2;
statement3;

It’s not clear that only statement1 is part of the if conditional. Better to write

if (cond) begin
  statement1;
end
  statement2;
statement3;

In reply to NaveenReddy:

In reply to dave_59:
Thanks Dave for the suggestion.
will the fork waits for all the three forever loops to join?
Also, in some post I read you suggesting to use it like below #1
what would be the best way to use #1 or #2 ?


// #1
forever @(posedge m_vif.uclk iff xyz[i] == 1) begin
//code
end
//#2 
forever begin
@(posedge m_vif.uclk iff xyz[i] == 1);
//code
// Question: is this way #2 correct or should the code be embedded in begin end blocks ?
end

Dave pardon me for bugging more on this thread.
if I want the iff condition to be applied to all the below lines
will the #2 method i wrote below works?


//#1 is straight forward since the code will be embedded in begin end blocks
//#2 but in this, the iff condition is terminated by ; and the following statements are not
// enclosed in begin end blocks. so, in that case, how would the code behave?
forever begin
  @(posedge m_vif.uclk iff xyz[i] == 1);  //no begin end block here. so i believe this would only be applied to the immediate if condition here. Please correct me if I'm wrong
    if(!Flag[i]) begin
      wait_time[i] = getWaitTime();
      Flag[i] = 1;
    end
    memclk_cycle[i] += 1;
    if (memclk_cycle[i] == wait_time[i]) begin
      Flag[i] = 0;	
      memclk_cycle[i] = 0;
      xyz[i] = 0;
    end
end

In reply to NaveenReddy:

I think i found the answer to the question in this thread.
https://verificationacademy.com/forums/systemverilog/what-difference-between-posedge-clk-begin-end…-and-posedge-clk

Thanks