Error with SV Interface wrapper for Verilog DUT

Hi Users,

I am fairly new to SystemVerilog and trying to learn SV interface and modport construct by connecting a Verilog module with ports to a particular modport of an interface. I get “Cross module reference resolution error, illegal use of modport”.

Can anyone please hep me understand this basic coding practice?

//---------Verilog module (.v file)------
module add(a,b,sum,cout);
input[7:0] a,b;
output[7:0] sum;
output cout;
.
.
endmodule

//----------Interface(.sv)-------
interface adif();
logic[7:0] a,b,sum;
logic cout;

modport dut(input a,b, output sum,cout);
modport tb(input sum,cout, output a,b);

endinterface

//---------Wrapper (.sv file)-----
module add_wrap();

adif aif();

add i_add( .a(aif.dut.a), .b(aif.dut.b), .sum(aif.dut.sum), .cout(aif.dut.cout));
endmodule
//----------------------

Any help would be greatly appreciated. Also, if you know any workarounds, please do share.

Thanks,

In reply to nikhil.n:

Hi Nikhil. Modports are used to connect two modules together that employ interfaces in their port list, and to specify the port direction. In your case, module add does not use an interface. The module instantiation should be:

add i_add( .a(aif.a), .b(aif.b), .sum(aif.sum), .cout(aif.cout));

In reply to sbellock:

Thanks for your response and insight into this.

Even if I do like shown below, it throws error saying “Unconnected interface port”

//---------Wrapper------
module add_wrap(aif);

adif.dut aif;

add i_add( .a(aif.a), .b(aif.b), .sum(aif.sum), .cout(aif.cout));
endmodule

Thank you once again for your response.

In reply to nikhil.n:

Specify what modport you want to use in add_wrap. Since this is a wrapper for the DUT you would use the dut modport:


module add_wrap (adif.dut aif);
    add i_add (.a(aif.a), .b(aif.b), .sum(aif.sum), .cout(aif.cout));
endmodule

In reply to sbellock:

I did it on the second line as you can see. It gives the error still.

Is it that the modport is used for synthesis purpose only and not for testbench?

//---------Wrapper------
module add_wrap(aif);

adif.dut aif;

add i_add( .a(aif.a), .b(aif.b), .sum(aif.sum), .cout(aif.cout));
endmodule

Thank you once again for your response.

In reply to nikhil.n:

sorry but I have the same problem, how did you solve it?

In reply to AnwarSholi:

Please show your code and the errors you are getting. We can not make recommendations without knowing these.

Modports are used as encapsulation of signals. You should only reference the individual signals from where the modport is used as a port. If your DUT has a pin level interface, then you should connect only the pins. If your DUT uses a modport in place of pins, then you should connect the modport.

Hi all, I am trying to access signals through modport in my sub-module(DUT) and for that, I am using (interface.modport) in a module and in dut_wrapper which is a wrapper I am passing (interface_instance) in wrapper module. The code is passing but I have doubt whether dut(sub-module ) is using interface signal or modport signal.

Here My intention is to use modport for signal driving.
Please clear my doubt.
Thanks in advance
The used code is shared below -:

module Testbench;
parameter tb_data_size=16;
parameter tb_array_depth=10;
bit clk;
int clk_count;

 

// clock generation
assign dut_wrapper.clk = clk;
always #1 clk = ~ clk;

 

// Simulation temination based on clock count
always @(posedge clk) begin clk_count++; end
always @(negedge clk) begin if(clk_count == 20) $finish; end

 

// instatiation of different rtl
//intf#(tb_data_size) d_if(clk);      // interface instance

 

// stimulation genration and drive
    reg [tb_data_size-1:0]inp1[tb_array_depth];
//    reg [tb_data_size-1:0]inp2;
    wire[tb_data_size:0]out1[tb_array_depth];
assign dut_wrapper.d_if.inp1 = inp1;
//assign dut_wrapper.d_if.inp2 = inp2;
assign out1 = dut_wrapper.d_if.out1 ;

 

initial
    begin
    // initialization
    clk_count = 0;
    foreach (inp1[i]) inp1[i] = 0;
//    inp2 = 0;
#2;
    // stimulas
    //repeat(10) 
    for(int i=0; i<= 10; i++)
    begin
    #2
    //inp1 = $urandom_range(15,40);
    foreach (inp1[i])
    inp1[i] = $urandom;
//    inp2 = $urandom_range(50,60);    
    end
    end

 


    reg [tb_data_size:0]r_out1[tb_array_depth];
    int add_er;
always @(posedge clk)
    begin
    foreach (inp1[i])
    r_out1[i] = inp1[i] ;
    end    
always @(negedge clk) 
    begin
    foreach (out1[i])
    if(r_out1[i] != out1[i]) add_er ++;
    end   

 

// display statement
always @(posedge dut_wrapper.d_if.clk) 
    begin
    foreach (inp1[i])
    $display(":*TB:input1=%0d output1=%0d",inp1[i],out1[i]);
    end    

 

//final
final
    begin
    if(add_er != 0)
        $display("\n Test Failed:\n dut checking max arry size not working correct");
    else
        $display("\n Test Passed:\n dut checking max array size  working correct");
    end    

 

endmodule

 

interface intf#(data_size,array_depth)(input bit clk);
    logic [data_size-1:0]inp1[array_depth];
//    logic [data_size-1:0]inp2[array_depth];
    logic [data_size:0]out1[array_depth];

  modport mp(input clk,input inp1,output out1);

endinterface

 

module dut_wrapper;
    parameter dut_data_size=16;
    parameter dut_array_depth=10;
    reg clk;
    reg [dut_data_size-1:0]inp1[dut_array_depth];
    wire[dut_data_size:0]out1[dut_array_depth];

 

// rtl and other instantiation
  intf#(dut_data_size,dut_array_depth) d_if(clk);
  dut#(dut_data_size,dut_array_depth) dut1(d_if);

 

//initial foreach (inp1[i]) $monitor($time,,":DUT_wraper: input1=%0d  output=%0d",inp1[i],out1[i]);    
always @(posedge clk) foreach (inp1[i]) $display($time,,":DUT_wraper: input1=%0d  output=%0d",d_if.inp1[i],d_if.out1[i]);    

 


endmodule

 
module dut#(data_size,array_depth)(intf.mp d1);
//module dut#(data_size,array_depth)(clk,inp1,out1);
//parameter size = 8
    //input clk;
    //input [data_size-1:0] inp1[array_depth];
    //output [data_size:0]out1[array_depth];

 

    reg [data_size:0] r_out1[array_depth];

 

assign d1.out1 = r_out1;    

 

  always @(posedge d1.clk)    
    begin
      foreach (d1.inp1[i])
        r_out1[i] = d1.inp1[i];
      foreach (d1.inp1[i])
        $display($time,,":DUT:input1=%0d output=%0d",d1.inp1[i],d1.out1[i]);
    end
endmodule



In reply to Abhishek kumar Diwakar:

Modports are not separate objects, they are just lists of accessible signals.