Function with variable input buswidth

Hi,
I’ve a code where there is a piece of logic which keeps getting reused multiple times like the below code:


    function void acb(input bit[5:0] data0, input bit[5:0]data1)
            $display("The value of data:%h", data0^data1);
    endfunction

when I call this function, i want to have a flexibility to pass data0 & data1 of width 6bits or 128bits or 32bits.

I’m trying to find if there is a better re-usable way of implementing this instead of explicitly implementing for each type.

In reply to hk123:

You can declare the function using the maximum dimensions you are planning to use (128) and pass every data (with dimension up to your maximum). Then SV will usually truncate om the output, the 0s in the XOR will result in 0s and if you use %0h will be removed during the print.

Alternatively you can use params and change it before compiling, if you need something at run time then i can’t think at moment at better ways.

In reply to hk123:

You need to explain what you intend to do with the function as there are many possibilities.

A maximum size is just one way. You can also create a parameterized function by wrapping it in a class.

There is also a ‘1et’ construct with typeless arguments.

You can also create dynamic arrays of bits.

In reply to dave_59:

Dave & Rsignori92,
Here is the sample snippet of code I’m trying to do:


task a();
  bit [5:0]a0, b0;
   abc(a0,b0);
endtask

task b();
  bit [10:0]a0, b0;
   abc(a0,b0);
endtask

task c();
  bit [128:0]a0, b0;
   abc(a0,b0);
endtask

    function void abc(input bit[5:0] data0, input bit[5:0]data1) // Here i want the flexibility to vary the bit width of inputs
            $display("The value of data:%h", data0^data1);
    endfunction

In reply to hk123:

I was looking to see more of what you really wanted to do in function abc. But based on what you have shown, you could do:

module top;
virtual class C #(type T);
   static function void abc(input T data0, data1);
            $display("The value of data:%h", data0^data1);
   endfunction
endclass
task a();
  bit [5:0]a0, b0;
  C#(type(a0))::abc(a0,b0);
endtask
 
task b();
  bit [10:0]a0, b0;
  C#(type(a0))::abc(a0,b0);
endtask
 
task c();
  bit [128:0]a0, b0;
  C#(type(a0))::abc(a0,b0);
endtask
  initial begin
    a;b;c;
  end
endmodule

In reply to dave_59:

Thanks Dave. This seems like a good option. However, I’m curious why did you decide to use static function?

Also, I’m curious about the other solution you were suggesting in your initial post regarding “creating dynamic array of bits”. Why did you not choose this option as a solution?

In reply to hk123:

Making it a static function means you never have to construct an instance of class C. It also makes it synthesizable. See section 13.8 Parameterized tasks and functions in the IEEE 1800-2017 SystemVerilog LRM

I’m assuming the one $display in your abc function is not what you really want to do. What you really want to do could have a profound impact the the way to handle this.

module automatic top;
  typedef bit bitstream_t[$];
  function void abc(input bitstream_t data0, data1);
    bitstream_t result;
    string hexresult;
    if (data0.size != data1.size) $fatal("You have a problem");
    // computing data0 ^ data1 with a dynamic array is trivial
    foreach(data0[i]) result.push_back(data0[i]^data1[i]);
    // displaying the result as a single hexadecimal number is more complicated
    while(result.size%4!=0) result.push_front(0); 
    for(int i = 0;i<result.size-1;i+=4) 
      hexresult = $sformatf("%s%h", hexresult, 4'(result[i+:4]));
    $display("The value of data:%s", hexresult);
   endfunction

task a();
  bit [5:0]a0, b0='h2a;
  abc(bitstream_t'(a0),bitstream_t'(b0));
endtask
 
task b();
  bit [10:0]a0, b0='h123;
  abc(bitstream_t'(a0),bitstream_t'(b0));
endtask
 
task c();
  bit [127:0]a0, b0=128'h12345678A;
  abc(bitstream_t'(a0),bitstream_t'(b0));
endtask
  initial begin
    a;b;c;
  end
endmodule

In reply to dave_59:

As an alternative to a parameterized class, one can also stick the function in a parameterized interface. This is more convenient if one already has a handy nearby interface to use, but creating one - just for the parameterized function - is certainly possible (and synthesizable)

Regards,
Mark