7

Is there any synthesizable way to pass an interface to a function or a task? My use case is the following: I have a package with several functions (though I could convert them to tasks, if that helps :) ), all of which might be used in a module and might need to access the ports of the module. Now, usually I'd just group all ports in an interface, add it to the module, and pass the it as virtual to the function. However, the manual of my synthesis tool mentions that virtual is not supported.

Am I missing anything? There must be a way to provide ports to tasks for synthesis, similar to VHDL's signal arguments?

Some example code:

module mymod (
    input logic clk,
    input logic rst,
    input uint16_t adr,
    input bit cyc,
    input uint32_t dat_m,
    input bit stb,
    input bit we,
    output bit ack,
    output uint32_t dat_s
    );

    always_comb begin
        mypack::do_something(a, b, c, adr, cyc, dat_m, stb, we, ack, dat_s);
endmodule

Ideally, the task mypack::do_something would be able to use the ports as ports, i.e. wait for changes on them, write values to them, etc; basically, the same you'd achieve in VHDL by passing them as signal arguments (as opposed to variable or constant arguments).

rainer
  • 6,769
  • 3
  • 23
  • 37

2 Answers2

2

Normally you'd declare any interface-specific functions in the interface definition itself. That way any task or function declarations already have the interface ports in scope.

interface int1(ports...);
  function func1(args...);
  // Do stuff with ports and args
  endfunction
endinterface

module mod1(input wire clk,interface intf);
...
  always @(posedge clk)
    intf.func1(module_specific_data); 
...
endmodule
  • Thanks for the idea. However, in my case the function implements module-specific behavior that just happens to use some of the module's ports. This rather strange indirection is due to the fact that the code is automatically generated and uses functions/packages for reasons outside of this question ;). – rainer Jan 23 '13 at 11:44
2

Unfortunately it looks like a interface must be virtual to be passed though a functions or tasks port list.

The SystemVerilog IEEE Std 1800-2009 says a function port list must be a data_type. See Section 13.4, Annex A.2.6, and Syntax 13-2 for the syntax of declaring a function. And see A.2.2.1 for defining a data_type. I checked the IEEE Std 1800-2005 too and it also seems to have the same restriction, just not spelled out clearly. See Section 12.3 and Annex A of 1800-2005.

If you want to use an interface, try using a translation function in the interface to make a struct (may require packed, see IEEE Std 1800-2009 Section 13.4, footnote#12):

interface myif ( /* ... */);
/* signal list */
function mypack::var_list_s toStruct();
   /* make translation */
endfunction : toStruct
endinterface : myif

module mymod(myif my_if);
always_comb
   mypack::do_something(my_if.toStruct(), my_if.ack, my_if.dat_s);
endmodule : mymod

Alternatively you can always do the classic `include "myports" where ever needed method.

Greg
  • 18,111
  • 5
  • 46
  • 68