David Belohrad
David Belohrad

Reputation: 468

In SystemVerilog testbench generator class - how to generate infinitely long data stream

In all the SystemVerilog test benches I could find on the internet the generator class always generates a fixed amount of samples and sends them to the mailbox. Driver reads the mailbox and generates an appropriate sequence by manipulating interface signals

One such generator, taken from [1] (chapter 1.3, paragraph 4) and reduced to essentials, is for example this:

    class generator;
      rand transaction trans;
      mailbox gen2driv;
      int  repeat_count; 
     
      function new(mailbox gen2driv);
        this.gen2driv = gen2driv;
      endfunction
       
      task main();
        repeat(repeat_count) begin
          trans = new();
          if( !trans.randomize() ) $fatal("Gen:: trans randomization failed");
          gen2driv.put(trans);
        end
      endtask
       
    endclass

This one generates repeat_count samples and sends them to the mailbox.

There are however situations, where user wants to generate infinite stream of data, because the testbench simulation is not terminated by a lack of input data, but rather by validation of a condition which happens somewhere in the future, at unknown time.

Extending the above example to replace repeat(repeat_count) begin by forever begin won't work. The simulator freezes in the loop as it tries to put infinite amount of samples to the mailbox. As the execution of main task is a blocking action, driver's signal generator never get executed, and the entire simulation stalls.

So my question is: How to define correctly a generator class, which can send infinite stream of data?

I'm looking for a behaviour similar to pythonic yield and generator function. This however requires some communication between driver and generator. So such generator model is probably not very suitable for SV?

[1] https://verificationguide.com/systemverilog-examples/systemverilog-testbench-example-01

Upvotes: 0

Views: 1025

Answers (2)

Greg
Greg

Reputation: 19112

Somewhere in your main task you can add a wait statement such as wait(gen2driv.num()<pause_threshold);. This will block the generator from adding more transaction until the driver has a chance to consume it.

task main();
  forever begin
    wait(gen2driv.num()<pause_threshold);
    trans = new();
    if( !trans.randomize() ) $fatal("Gen:: trans randomization failed");
    gen2driv.put(trans);
  end
endtask

Upvotes: 0

dave_59
dave_59

Reputation: 42748

What you are asking for is exactly how the UVM sequence/driver mechanism works. The generator does not do any randomization until the driver is ready and asks for an item to drive.

But you can get close to what the UVM does simply by constructing your mailbox with a bound of 1. Then the put(trans) in the main loop blocks until after the driver has performed a get(). Then there will always be one transaction in the mailbox waiting for the next drive cycle.

Upvotes: 2

Related Questions