I have a Module which has a port whos width should depend on a value from a function: (Syntax is Verilog/Systemverilog mixed as i am using yosys for synthesis, which only supports a limited amount of SV)
module MY_MODULE#(
parameter MY_PARAM = 2,
parameter PARAM_TWO = 10
)(
input logic CLK_CI,
...
input logic [myfunc(MY_PARAM, PARAM_TWO):0] RND,
...
output logic Finish_SO
);
The problem is that the function needs to calculate the value using a for loop, as i need the sum some calculated values. Example:
function automatic int myfunc(input loop_control, input variables);
int carry;
int variables_next = 0;
for (int i = 0; i < loop_control; i++) begin
carry = variables_next & 1;
variables_next = (variables_next >> 1) + carry;
end
myfunc = carry;
endfunction
Technically, the output of the function is constant as long as the inputs are constant. In my case, i always call the function with localparams, which are constant. However as i am using a for loop and the carry variable changes, it is considered non-constant.
Error from verilator: Expecting expression to be constant, but can't determine constant for FUNCREF 'myfunc'
Error from yosys: Non-constant function call in constant expression.
Is there a way to have a function with a for loop as a constant function?
I could hardcode the values in a parameter array, however i would prefer to not do that.
I wanted to create a function which uses constant (localparams) inputs to create outputs which can be used with port definition. One approach i have tried was to get the values i needed within the generate for loop i have, however i have not found a way to add up the localparams in the generate for loop.
You can try precalculate your parameter as follows
module MY_MODULE#(
parameter MY_PARAM = 2,
parameter PARAM_TWO = 10,
localparam my_func_data = my_func(MY_PARAM, PARAM_TWO)
)(
input logic CLK_CI,
input logic [my_func_data:0] RND,
output logic Finish_SO
);
function automatic int my_func(input loop_control, input variables);
int carry;
int variables_next = 0;
for (int i = 0; i < loop_control; i++) begin
carry = variables_next & 1;
variables_next = (variables_next >> 1) + carry;
end
my_func = carry;
endfunction
endmodule
Alternatively, you can declare my_func_data
as a parameter to be able to modify it externally.
Another reason why Vivado, in my case, is also throwing an warning in your construction is that your function is named myfunc
, but you are trying to call my_func
. The first error raised in such a case is 'range must be bounded by constant expressions', and the second one is 'my_func' is not declared'.