Passing parameterized interface to module port

See following code:


module dut(input bit clk, input bit [7:0] addr, input bit [31:0] data);
    always @(posedge clk)
        $display("%0d, %0d",addr,data);
endmodule

//module dut_wrapper(interface i);
module dut_wrapper(ex_if i);
    dut my_dut(
        .clk(i.clk),
        .addr(i.a),
        .data(i.d)
    );
endmodule

interface ex_if#(W1,W2)(input bit clk);
    bit [W1-1:0] a=3;
    bit [W2-1:0] d=5;
endinterface

interface bad_if(input bit clk);
    bit [7:0] a=4;
    bit [31:0] d=6;
endinterface

module Top;
    bit clk;

    initial begin
        clk = 0;
        #(2us);
        forever begin
            clk = ~clk;
            #(1us);
        end
    end

    ex_if#(8,32) my_if(clk);

    dut_wrapper DUT(.*,.i(my_if));

endmodule

I have 2 questions:

As this example works, it seems I can define the dut_wrapper module with an ex_if type port, without prior declaring ex_if? Similar to just using a generic interface reference (line commented out)? I find it a bit weird as the compiler doesn’t even know that ex_if is an interface at the moment it compiles dut_wrapper.

The LRM shows parameterized interfaces passed to modules, but only using the generic interface. My code above tries to be more strict and limits it to ex_if interfaces. However it seems I am not allowed to put the parameters in there? I.e.


module dut_wrapper(ex_if#(8,32) i);

does not compile. So there is no way I can restrict it to a particular parameter specialization? Not a big deal, I was just expecting that it would have been required to put the parameters, not that it is not allowed to put them.

In reply to NiLu:

You are correct, there is no way to restrict interface ports to particular parameter specializations, but you can put elaboration-time checks inside the module that it connects to the interface.

interface ex_if#(W1,W2)(input bit clk);
    bit [W1-1:0] a=3;
    bit [W2-1:0] d=5;
endinterface

module dut_wrapper(ex_if i);

  if (i.W1!=8) $error("W1 not 8"); // this is a generate block

endmodule

module top;

ex_if #(7,8) i1();
dut_wrapper DUT(i1);

endmodule

In reply to dave_59:

Hello @Dave,

  1. Say I use this module as interface_wrapper which binds at the TB Top. And this module contains the code to set the static interface to the testbench using config_db. Example code as shown below.

module dut_wrapper(ex_if i);
 initial begin 
   uvm_config_db#(virtual ex_if)::set(null, "*", "ex_if_vif", i);
 end 
endmodule

  1. But I face the compatibility issue with respect to the uvm_config_db, because the default element in the uvm_config_db expects a default parameters for the interface, but while we pass the interface to the module we set different parameters to the interface.

So how can we pass the parameters that you use to for the interface and pass the same to the uvm_config_db #(virtual ex_if #(? ?)).

Do I need to pass that as parameter inputs to the interface wrapper module and then set in the config_db as show below ? so that the data types matches ? [Because this way was able to configure the right parameters to the interface and as well to the virtual interface defined in uvm_config_db]


module dut_wrapper#(W1, W2)(ex_if i);
 initial begin 
   uvm_config_db#(virtual ex_if#(W1, W2))::set(null, "*", "ex_if_vif", i);
 end 
endmodule

module top;
 ex_if #(7,8) i1();
 dut_wrapper DUT#(7, 8)(i1);
endmodule

Or is there any other better way for the above scenario. Any suggestion would be highly helpful.

In reply to desperadorocks:

Yes, parametrization is part of the type of a virtual interface, so you need to make sure the parameterizations match.

There are many strategies for dealing with parameter matching problem, the simplest being to avoid using parameters unless absolutely necessary. There are many papers presented at the various DVCon conferences, one such is here.

In reply to dave_59:

Thanks a lot for the clarification Dave and as well for the pointers.