I want to pass a parameter to a function and use it as a parameter (e.g. to select bits) but I don't know how to tell the function that this input is a constant.
For example, if I wanted to do this:
assign foo = bar[MY_PARAM:0];
I want to write my_function
so that I could do this:
assign foo = my_function(bar, MY_PARAM);
In my case I need to do a little more that just select bits but not too much, and I'll want it to work for inputs of different bit widths. If I just wanted to select a bit I could use the function below and I'd hope for a solution of similar form but I can't work out the syntax:
function my_function;
input [3:0] data, my_bit;
begin
my_function = data[my_bit];
end
endfunction
As per Silicon1602's answer, the code I'd need for this would be:
virtual class myClass#(parameter LOCAL_PARAM);
static function [LOCAL_PARAM:0] my_function;
input [LOCAL_PARAM:0] data;
begin
my_function = data[LOCAL_PARAM:0];
end
endfunction
endclass
assign foo = myClass#(MY_PARAM)::my_function(bar);
At first I forgot about the [LOCAL_PARAM]
part and was just getting 1-bit back.
The SystemVerilog LRM has a section on your particular case: 13.8 Parameterized tasks and functions. It says:
SystemVerilog provides a way to create parameterized tasks and functions, also known as parameterized subroutines. [...] The way to implement parameterized subroutines is through the use of static methods in parameterized classes (see 8.10 and 8.25).
In your case, you should declare your function like this:
virtual class myClass#(parameter MY_PARAM);
static function my_function;
input [MY_PARAM-1:0] data, my_bit;
begin
my_function = data[my_bit];
end
endfunction
endclass
You could then call your function like this:
assign my_function_output = myClass#(MY_PARAM)::my_function(data, my_bit);
Please note that you may declare multiple functions in your abstract class. So, if you have a whole bunch of functions which all depend on a parameter in the same way, you could all declare them in the same class.
Some additional information on the virtual
and static
keyword in the aforementioned context:
Section 8.10 of the LRM talks about static
methods.
A static method is subject to all the class scoping and access rules, but behaves like a regular subroutine that can be called outside the class, even with no class instantiation. A static method has no access to non-static members (class properties or methods), but it can directly access static class properties or call static methods of the same class.
By using the virtual
keyword for the class declaration, you show the compiler that this is an abstract class (see Section 8.21 in the LRM). Creating an object of a virtual class causes a compilation error. This enforces strict static usage of the method.
Since the question was also tagged as 'verilog', a similar trick could be played in a simple verilog. You can use parameterized modules to achieve the same effect. For example:
module util#(
parameter int W = 10)();
function funct;
input [W-1:0] inp;
funct = inp;
endfunction
endmodule
module top(out, in);
parameter W = 8;
output wire [W-1:0] out;
input wire [W-1:0] in;
util#(W) u1(); // inst util module with a parameter
assign out = u1.funct(in); // call the function
initial #1 $finish;
endmodule
By default, all functions declared within a module are static.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With