So the basic declaration is:
function [<msb>:<lsb>] funcName(
... // inputs
);
//local vars
// e.g. reg [3:0] myVal;
begin
//body of function
//...
//return value by assigning to function name:
funcName = <value>;
end
endfunction
A function can return up to 1 value.
The width of the return value for the function is set by the range specifier in the declaration. This must be a constant width - e.g. a literal width, a parameter value, etc.
Returning a value is achieved by assigning a value to the function name. You can assign in multiple different places with the body, e.g. within for loops, if-else statements, or at the end.
In your code, you have several things I'd change.
You have 'reg' in the function definition, rather than a range specifier. This is unnecessary and it may confuse some more picky synthesis tools.
If you want it to be a single bit wide, simply omit the range and reg
.
Wrap the body of the function in begin-end
for clarity.
Verilog is not like C. You can't have values of variable width. So declaring the internal signal W
as width k
won't work.
In your case, you could simply make the internal signal W
wide enough for your desired maximum k
value. You could also make it an integer
if 32bit is enough. Then initialise the value to all 1's. The for loop can then modify k
bits and the reduction-AND with them still work (e.g. ~16'b0
for a 16bit signal).
You can also add a parameter outside the function to set the maximum width of you prefer. Parameters and local parameters in the module that is declaring the function are visible inside the function. Handy if you want to extend to more nibbles in the future.
Of course as pointed out in @toolic's answer, for your current case this can be done without a function by using simple comparisons.