-2

I am following the testbench example at this link:

http://www.verificationguide.com/p/systemverilog-testbench-example-00.html

I have two questions regarding fork-join statements. The test environment has the following tasks for initiating the test:

task test();
  fork
  gen.main();
  driv.main();
  join_any
endtask

task post_test();
  wait(gen.ended.triggered);
  wait(gen.repeat_count == driv.no_transactions);
endtask

task run;
  pre_test();
  test();
  post_test();
  $finish;
endtask

My first question is why do we wait for the generator event to be triggered in the post_test() task? why not instead do a regular fork-join which, as far as I understand, will wait for both threads to finish before continuing.

I read another Stack Overflow question (System Verilog fork join - Not actually parallel?) that said these threads are not actually executed in parallel in the CPU sense, but only in the simulation sense.

My second question is what are the point of fork-joins if they are not actually executed in parallel. There would be no performance benefit, so why not follow a sequential algorithm like:

while true:
  Create new input
  Feed input to module
  Check output

To me this seems much simpler than the testbench example.

Thanks for your help!

tnugent97
  • 17
  • 2
  • The example you are following is so poorly written I can't begin to explain why things are done the way they are. I would never use `event`s and triggered methods. They are basically avoiding a race condition that should never have been there in the first place. Also - don't use unparameterized mailboxes, and don't use program blocks – dave_59 Feb 21 '18 at 19:37

1 Answers1

0

without having the code for gen and driv, it is difficult to say. However, most likely both driv and gen are communicating with each other in some manner, i.e. gen produces data which driv consumes and drive something else.

If gen and driv are written in as gen input/cousume input fashion, than your loop would make sense, however, most likely they generate and consume data based on some events and cannot be easily split in such functions easily. Something like the following is usually much cleaner.

gen:
    while() begin
       wait(some event);
       generateData;
       prepareForTheNextEvent;
    end

driv: 
    while() begin
       wait(gen ready);
       driveData;
   end

so, for the above reason you cannot run them sequentially. They must run in parallel. For all programming purposes they are running in parallel. In more details they run in the same single thread, but verilog schedules their execution based on events generated in simulation. So, you need fork.

As for the join_any, I think, that the test in your case is supposed to finish when either of the threads is done. However the driver has also to finish all outstanding jobs before it can exit. Therefore there are those wait statements in the posttest task.

Serge
  • 11,616
  • 3
  • 18
  • 28