Multiple Clock Frequency generator module

Hi All ,

I have a requirement in my test setup to generate one clock with random frequency in range of (0 → 250 Mhz) and another clock with random frequency in range of(0 → 400 Mhz).
Any idea or implementation to generate such clock module that can be instantiated from tb top file , so that every time any test run it will run with the above random clocks.
Note : Test bench in in UVM

In reply to anant.sharma:
Guess you are looking for something like this. You can access the SysCon MP from any virtual interface pointer from the UVM parts.
The code may contain errors.


`timescale 1ps/1ps

interface clock_interface#(
    parameter                           NUM_OF_CLOCKS = 2
  )(
    output var logic                    clks [NUM_OF_CLOCKS-1:0]
  );

  /*  CONTROLS  */
  var bit                               clk_en [NUM_OF_CLOCKS-1:0];
  var int unsigned                      clk_period_in_ps [NUM_OF_CLOCKS-1:0];

  /*  MODPORTS  */
  modport syscon_mp(import setup_clock);

  /*  FUNCTIONS  */
  task automatic init_clock();
    foreach(clks[i]) begin
      clks[i]                           = 0;
      clk_period_in_ps[i]               = $urandom_range(250,40000);
      clock_driver(i);
    end
  endtask: init_clock

  task automatic setup_clock(
      int unsigned                      _clk_line,
      bit                               _clk_en,
      int unsigned                      _min_delay_in_ps,
      int unsigned                      _max_delay_in_ps
    );

    assert (_min_delay_in_ps <= _max_delay_in_ps && _min_delay_in_ps) begin
      clk_en[_clk_line]                 = _clk_en;
      clk_period_in_ps[_clk_line]       = $urandom_range(_min_delay_in_ps, _max_delay_in_ps);
    end
    else $error("Parameter error!");
  endtask: setup_clock

  task automatic clock_driver(int unsigned _clk_line);
    fork
      forever #(clk_period_in_ps[_clk_line] * 1ps) begin
        if (clk_en[_clk_line]) begin
          case (clks[_clk_line])
            0,1:     clks[_clk_line]    = !clks[_clk_line];
            default: clks[_clk_line]    = 0;
          endcase
        end
        else clks[_clk_line]            = 'z;
      end
    join_none
  endtask: clock_driver

  initial begin
    init_clock();
  end
endinterface: clock_interface


/*  verify the interface  */
module top();
  clock_interface #(3) clock_if_inst();

  initial begin
    clock_if_inst.setup_clock(0, 1, 250, -1); // 400 MHz or slower
    clock_if_inst.setup_clock(1, 1, 400, -1); // 250 MHz or slower
  end

  initial begin
    // uvm_config_db#(virtual clock_interface.syscon_mp)::set(null, "*", "syscon_mp", clock_if_inst.syscon_mp);
  end
endmodule: top

In reply to gvekony:

Thanks GVEKONY,

It seems that above code will generate the clocks will generate in range of 250ps or less clock duration, and same for other case .
But my requirement is to generate the above clocks in 250Mhz or less and 400Mhz or less.

Your solution seems to be based on clock duration not on frequency as i need .

For eg : If need to generate a clock of 250 Mhz , my clock duration should be 4ns.
But problem starts when number gets real type .
For eg: if i need 249 Mhz frequency clock , my clock duration should be 4.0160642570ns.

I hope that explains my problem.

In reply to anant.sharma:

You can genearte any random real data by converting it to an integer and re-converting to a real.

In reply to anant.sharma:

Yeah, the numbers aren’t really exact. :) Just wanted to give you a solution that you can tinker to your needs.

On the other hand you cannot really generate a clock, without setting the period or the half-period duration as far as I know. So if you need exact 249MHz, you should set your timescale to fs-s and the half period to 4016064/2. It won’t be perfect though.

By the way, if your design does not contain any timing or delay information, the exact clock frequency is largely irrelevant for the simulation.