Passing a parameter to a bind entity

I’m trying to bind an interface to an RTL design as shown:

bind bf_framer_ifc bf_sample_sif #(
   .SOURCE_IS_DUT ( IS_DUT[BF_FRAMER] ),
   .DEST_IS_DUT   ( IS_DUT[BF_TGC]    )
) raw (
   . . .
);

When I run this in Questasim, I get error vopt-2730, Undefined variable: IS_DUT. It occurs to me that Questasim is trying to get IS_DUT from the hierarchical level in which the bound interface is instantiated, rather than the level that has the bind statement. Is there a way I can pass this parameter to the bound entity as needed?

In reply to tonyle:

I also tried the following:

bind bf_framer_ifc bf_sample_sif #(
   .SOURCE_IS_DUT ( $unit::top.IS_DUT[BF_FRAMER] ),
   .DEST_IS_DUT   ( $unit::top.IS_DUT[BF_TGC]    )
) raw (
   . . .
);

and

bind bf_framer_ifc bf_sample_sif #(
   .SOURCE_IS_DUT ( $root.top.IS_DUT[BF_FRAMER] ),
   .DEST_IS_DUT   ( $root.top.IS_DUT[BF_TGC]    )
) raw (
   . . .
);

(top is the name of my top-level testbench.) In both cases, I get the error “The expression for a parameter actual associated with the parameter name (‘SOURCE_IS_DUT/DEST_IS_DUT’) for the module instance (‘raw’) must be constant” – even though IS_DUT is declared as a localparam array in top.

The syntax for the bind statement works exactly as if a bound instance statement was written source code inside the target instance. You are not allowed to override parameters with hierarchical references to other parameters.

In reply to dave_59:

Thanks for pointing that out. So I take it $unit doesn’t work because it’s in reference to the bf_framer_ifc compilation unit. Before you answered, I realized that bf_framer_ifc doesn’t have my enumerated types imported, so I added the package reference to them:

bind bf_framer_ifc bf_sample_sif #(
   .SOURCE_IS_DUT ( $root.top.IS_DUT[type_pkg::BF_FRAMER] ),
   .DEST_IS_DUT   ( $root.top.IS_DUT[type_pkg::BF_TGC]    )
) raw (
   . . .
);

I thought for sure this would work but still no dice. My current solution is this monstrosity:

bind bf_framer_ifc bf_sample_sif raw (
   . . .
);

defparam fpga.bff.raw.SOURCE_IS_DUT = IS_DUT[BF_FRAMER];
defparam fpga.bff.raw.DEST_IS_DUT   = IS_DUT[BF_TGC];

Yes, this makes me feel dirty on multiple fronts; but based on what you’ve said, I can’t think of any other way.

In reply to tonyle:

Years too late, but here’s my current workaround: Create a package and refer to it. It’s already compiled as it gets compiled in the module that creates the bind. And therefore it’s findable using it’s namespace in the bind line.

package bind_parameters;
localparam int MY_PARAM = 5;
endpackage
module tb ();
import bind_parameters::;

INST my_inst(.
);
bind my_inst MOD # (.MY_PARAM(bind_parameters::MY_PARAM)) my_inst_mod (.*);
endmodule

This is cleaner than the defparam (which I have been using until now…). It’s definitely cleaner than using `defines as well.