Use the output of a module inside a class (including task (generator)

Hello all,

i’m trying to use a sine wave generatot module outputs as inputs in a task (inside class env) to serve as a stimulus for my design:

task run_phase(uvm_phase phase);
    phase.raise_objection(this);
    `uvm_info("LABEL", "Started run phase.", UVM_HIGH);
    
    begin
    
      int reset_n = 0'h0;
      @(m_if.cb);
      m_if.cb.Ain <= sine;// the output of the module
      m_if.cb.reset_n <= reset_n;
      repeat(2) @(m_if.cb);
      
    end
    `uvm_info("LABEL", "Finished run phase.", UVM_HIGH);
    phase.drop_objection(this);
  endtask: run_phase

i’m thinking to use a class like this:

  class my_env extends uvm_component;
...
sv_ams_sine_voltage_gen#(-1.0, +1.0, 1.0E6) sGen_IN;
function void build_phase(uvm_phasephase);
super.build_phase(phase);
uvm_resource_db#(virtual ams_src_if)::
set("*", "uvm_ams_src_if", aif, this);
sGen_IN= sv_ams_sine_voltage_gen#
(-1.0, +1.0, 1.0E6)::type_id::create("sine", this);
endfunction

but how to manage the communication between the two classes? could i simply assign the module output “sine” to “Ain”

kt is quite urgent

Kind Regards,

In reply to saketa:

Hi,
Question is not clear to me. I think you are trying to pass values from module to your class. In that case make use of uvm_config_db class, just set value in module and get that value in your class. If you change value in module same value will appear in class variable. You can also make use of uvm_pool or uvm_queue.

Regards,
Raghu

In reply to RAGHU_BHAT:

The key question where does it come from (sine). I’m guessing it is somewhere in the toplevel module of your UVM testbench. The most easy and consistent way ist to add this variable to an interface. Then you can pass it through the class-based part of your testbench.

In reply to chr_sue:

hi RAGHU_BHAT,

Thank you for you suggestion
i was thinking of using interface for my sine wave module,

the updated code is:

class env extends uvm_env;

virtual SDM_if m_if;
virtual sine_if si_if;

function new(string name, uvm_component parent = null);
super.new(name, parent);
endfunction

function void connect_phase(uvm_phase phase);
`uvm_info(“LABEL”, “Started connect phase.”, UVM_HIGH);
// Get the interface from the resource database.
assert(uvm_resource_db#(virtual SDM_if)::read_by_name(
get_full_name(), “SDM_if”, m_if));
`uvm_info(“LABEL”, “Finished connect phase.”, UVM_HIGH);
assert(uvm_resource_db#(virtual sine_if)::read_by_name(
get_full_name(), “sine_if”, si_if));
`uvm_info(“LABEL”, “Finished connect phase.”, UVM_HIGH);
endfunction: connect_phase

task run_phase(uvm_phase phase);
phase.raise_objection(this);
`uvm_info(“LABEL”, “Started run phase.”, UVM_HIGH);

begin

  int reset_n = 0'h0;
  @(m_if.cb);
  m_if.cb.Ain <= si_if.cb.sine_out;
  m_if.cb.reset_n <= reset_n;
  repeat(2) @(m_if.cb);
  
end
`uvm_info("LABEL", "Finished run phase.", UVM_HIGH);
phase.drop_objection(this);

endtask: run_phase

endclass

it compile fine but when simulating the following error appear:

Virtual interface resolution cannot find a matching instance for ‘virtual SDM_if’

why thi appear?

many thanks,

In reply to saketa:

This error message means the virtual interface is not available.
It is highly recommended to use uvm_config_db/set/get instead of uvm_resource_db.
You have to pass the virtual interface from the initial block of the toplevel module through the class-based testbench.
What is your command for doing this?

Yes, uvm_config_db should be used to set from module and get in class. Config_db class is recommended.

In reply to RAGHU_BHAT:

To help you I need the commands in detail. I believe something is wrong with the arguments in the commands.

In reply to chr_sue:

the full code is:

import uvm_pkg::;
import math_pkg::
;
`include “uvm_macros.svh”
//----------------
// environment env
//----------------

class env extends uvm_env;

virtual SDM_if m_if;
virtual sine_if si_if;

function new(string name, uvm_component parent = null);
super.new(name, parent);
endfunction

function void connect_phase(uvm_phase phase);
`uvm_info(“LABEL”, “Started connect phase.”, UVM_HIGH);
// Get the interface from the resource database.
assert(uvm_resource_db#(virtual SDM_if)::read_by_name(
get_full_name(), “SDM_if”, m_if));

assert(uvm_resource_db#(virtual sine_if)::read_by_name(
get_full_name(), “sine_if”, si_if));
`uvm_info(“LABEL”, “Finished connect phase.”, UVM_HIGH);

endfunction: connect_phase

task run_phase(uvm_phase phase);
phase.raise_objection(this);
`uvm_info(“LABEL”, “Started run phase.”, UVM_HIGH);

begin

  int reset_n = 0'h0;
  @(m_if.cb);
  m_if.cb.Ain <= si_if.cb.sine_out;
  m_if.cb.reset_n <= reset_n;
  repeat(2) @(m_if.cb);
  
end
`uvm_info("LABEL", "Finished run phase.", UVM_HIGH);
phase.drop_objection(this);

endtask: run_phase

endclass

//-----------
// module top
//-----------
module top;

bit clk_1mhz;
env environment;

sdm_rnm dut(.clk_1mhz (clk_1mhz));

initial begin
environment = new(“env”);
//Put the interface into the resource database.
uvm_resource_db#(virtual sdm_if)::set(“env”,
“SDM_if_if”, dut.SDM_if_if0);

clk_1mhz = 0;
run_test();

end

initial begin
forever begin
#(50) clk_1mhz = ~clk_1mhz;
end
end

initial begin
// Dump waves
$dumpvars(0, top);
end

endmodule
// SDM2 module
module sdm_rnm (Ain, clk_1mhz, reset_n, Dout);
input Ain, clk_1mhz, reset_n;
output Dout;
real Ain, dlay[2:1];
reg Dout;
real sdm_sign_val;
real sdm_sum1, sdm_sum2;
always @(negedge clk_1mhz)
begin
set_dlay (1, sdm_sum1);
set_dlay (2, sdm_sum2);
sdm_sum1 = (Ain/8.0) + dlay[1] - (sdm_sign_val/8);
sdm_sum2 = (sdm_sum1/2.0) + dlay[2] - (sdm_sign_val/8);
if (dlay[2] > 0.0) begin
sdm_sign_val = 1.0 ;
end
else if (dlay[2] < 0.0) begin
sdm_sign_val = -1 ;
end
else begin
sdm_sign_val = 0.0 ;
end
if (sdm_sign_val < 0.0) begin
Dout = 0;
end
else begin
Dout = 1;
end
end
endmodule

//---------------------------------------
// Interface for the adder/subtractor DUT
//---------------------------------------
interface SDM_if(input bit clk_1mhz, input bit reset_n, input Ain, output Dout);

clocking cb @(posedge clk_1mhz);
output Ain;
input Dout;
endclocking // cb

endinterface: SDM_if

//---------------
// Interface bind
//---------------
bind sdm_rnm SDM_if SDM_if_if0(
.clk_1mhz(clk_1mhz),
.Ain(Ain),
.Dout(Dout),
.reset_n(reset_n)
);

module sv_ams_sin_voltage_gen(output real sine_out);
parameter sampling_time = 5;
const real pi = 3.1416;
real time_us, time_s ;
bit sampling_clock;
real freq = 20;
real offset = 2.5;
real ampl = 2.5;
always sampling_clock = #(sampling_time) ~sampling_clock;
always @(sampling_clock) begin
time_us = $time/1000;
time_s = time_us/1000000;
end
assign sine_out = offset + (ampl * sin(2pifreq*time_s));
endmodule

interface sine_if(output real sine_out, input bit clk_1mhz);

clocking cb @(posedge clk_1mhz);

input sine_out;

endclocking
endinterface: sine_if

any help will be appreciated,

many thanks

In reply to saketa:

You are facing a name issue in the resource database. This is your set command:
uvm_resource_db#(virtual sdm_if)::set(“env”, “SDM_if_if”, dut.SDM_if_if0);
You are storing the interface under the name ‘SDM_if_if’.
The read command from the resource db is:
uvm_resource_db#(virtual SDM_if)::read_by_name(get_full_name(), “SDM_if”, m_if);
And you are trying to read from the name ‘SDM_if’ in the env. But there is no entry in the resource db for this name. You have to adopt the names.
By the way, I’m not sure which methodology you are following. But this definitely not what UVM is proposing. It looks like Mentor Graphic’s early days AVM. I’d recommend to refine your code and moving to UVM.

Hope this helps.

In reply to chr_sue:

i’m using Modelsim 10.1c

i had tested the same architectur on a simple module (SUB ADD) and it work fine.

now i had done the naming change (just replacing SDM_if_if by SDM_if) but there is an issu:

Virtual interface resolution cannot find a matching instance for ‘virtual sine_if’.

In reply to chr_sue:

It is a UVM code belive me :)

In reply to saketa:

I don’t want to struggle with you about UVM. But one key feature of the UVM is the seperation of test from the testbench. This requires that a test is cerating a testbench which is customized to the needs of this test.And this will not happen in the inital block the toplevel module. A seecond thing is you should never call the constructor new to create your own testbench components. You should always use the create function of the factory which adds a type_id to this component.

In reply to chr_sue:

Many thanks Chr_Sue,

i understabnd that, right now i’m focusing on the issue regarding the virtual sine_if, Why it happen???

In reply to saketa:

As I said, you are storing sine_if wth a certain name. But when getting this interface you are using another name which is not in the config_db. Align the names and it will work.

In reply to chr_sue:

I’m defining the module sine wave generator, and it’s interface,

i’m tryning to pass it’s output variable to “m_if.cb.Ain”

now i’m facing another isuue:

Variable ‘/top/dut/Dout’, driven via a port connection, is multiply driven. See D:/sigma_delta_SV/FirstSDM.sv(114)

In reply to saketa:

Many thanks Chr_sue
i solvet it but,

i dont know why another issuue has arising:
Failed to find ‘set_dlay’ in hierarchical name '/set_dlay

the modifyed code is:

module sdm_rnm (SDM_if SDM_if2);
  real dlay[2:1];
  reg Dout;
  real sdm_sign_val;
  real sdm_sum1, sdm_sum2;
  always @(negedge SDM_if2.clk_1mhz)
  begin
  set_dlay (1, sdm_sum1);
  set_dlay (2, sdm_sum2);
  sdm_sum1 = (SDM_if2.Ain/8.0) + dlay[1] - (sdm_sign_val/8);
  sdm_sum2 = (sdm_sum1/2.0) + dlay[2] - (sdm_sign_val/8);
  if (dlay[2] > 0.0) begin  
    sdm_sign_val = 1.0 ;
  end
else if  (dlay[2] < 0.0) begin
  sdm_sign_val = -1 ;
end
else begin 
  sdm_sign_val = 0.0 ;
end
if (sdm_sign_val < 0.0) begin
  SDM_if2.Dout = 0;
end
else begin
  SDM_if2.Dout = 1;
end
end
endmodule

the mofule rnm compile fine

Best Regards,

In reply to saketa:

I guess set_dlay is a function. Where do you define it?
If it is in a package you have to import this package in module sdm_rnm.

In reply to chr_sue:

Thank you chr_sue, i had changed the module(no need to this function)

but it still an issue with the DPI function i’m using:

Failed to find user specified function ‘sin’ in DPI precompiled library search list "C:/modeltech_10.1c/uvm-1.1b\win32\uvm_dpi.dll

i had downloaded uvm 1.2, but there is no DLL inside,
my setting is the following:

Win32, ModfelSim 10.1c

In reply to saketa:

saketa,

“sin” has nothing to do with the UVM, and this the first time you mention “sin”; all other times you have “sine” without the ‘e’.

It’s going to be hard to help you without seeing all of your code, and that might be too much to deal with in this forum. I suggest you seek out some local help, perhaps from your tool vendor.

In reply to saketa:

Either your tool installation has been corrupted or you have installed a 64-bit version. In this case \uvm-1.2\win32 is empty.
Please note UVM requires Questa with specific licenses.
Dave might have more details.