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.