Here is the main body of the VHDL function:
-- fixed round function; this can implement all round types mentioned
-- in the fixed_round_t
function fixed_round(
int_part : signed;
frac_part : signed;
round_type : integer;
saturation : std_logic := '0')
return signed is
variable sign_bit : std_logic; -- S
variable one_bit : std_logic; -- D
variable half_bit : std_logic; -- F
variable other_bit : std_logic; -- R
variable is_saturated : std_logic;
variable addend : signed(int_part'range);
variable rounded : signed(int_part'range);
variable other_bits : std_logic_vector(frac_part'range);
variable int_slice : std_logic_vector(int_part'length-2 downto 0);
-- alias addend_bit : std_logic is addend(addend'right);
begin
-- first assign bits used to decide value of addend
sign_bit := int_part(int_part'left);
one_bit := int_part(int_part'right);
half_bit := frac_part(frac_part'left);
if (frac_part'length > 1) then
other_bits := std_logic_vector(frac_part);
other_bits(other_bits'left) := '0';
other_bit := or_reduce(other_bits);
else
other_bit := '0';
end if;
-- not determine the value of the addend required to round off the result
-- according to the specified method
addend := (others=>'0');
-- CODE SECTION NOT SHOWN
-- check if integer part is already at maximum value if saturation
-- is to be applied
int_slice := std_logic_vector(int_part(int_slice'range));
if saturation = '1' and sign_bit = '0' and and_reduce(int_slice) = '1' then
is_saturated := '1';
else
is_saturated := '0';
end if;
-- apply addition to round off the result, the addend could be zero
-- if this quantity can be simply truncated to apply rounding
if (not is_saturated) then
rounded := int_part + addend;
else
rounded := int_part;
end if;
--
return rounded;
end function;
Here the int_part and frac_part do not have any bounds. They shall take the attributes of the parameter passed into the function. Also, the addend, rounded and other_bits take the the range (the M downto N aspect) as the parameters. Later in the function we see occurence of int_part'left and int_slice'range.
I have written SystemVerilog function but it does not seem to work. What is the correct way to convert this into SystemVerilog?
The VHDL feature you describe in known as an unconstrained vector/array, which SystemVerilog does not have. Although VHDL is strongly typed, it treats vectors as if they were dynamically sized strings. This makes vector arithmetic much more difficult to optimize.
There are a number of ways of dealing with this in SV, depending on what you are attempting to accomplish. If you are just rearranging and selecting bits of these vectors, you can pass them in as unpacked dynamic arrays or queues of single bits. You would need to cast your inputs vectors to this type and cast the return value back.
typedef logic bitstream_da[];
typedef logic [15:0] uint16;
uint16 A,B,C;
function bitstream_da func_or(bitstream_da in1,in2);
if (in1.size != in2.size) $error(...);
func_or = new[in1.size);
foreach(func_or[i]) func_or[i] = in1[i] || in2 [i];
endfunction
...
A = uint16'( func_or(bitstream_da'(B), bitstream_da'(C)) );
You can also wrap your function in a parameterized class (synthesizable)
typedef logic bitstream_da[];
typedef logic [15:0] uint16;
uint16 A,B,C;
class W#(type T1,T2=T1,T3=T2);
function T1 func_add(T2 in1,T3 in2);
return in1 + in2;
endfunction
...
A = W#(uint16)::func_add(B,C);
Another possibility is declaring your function with the maximum sizes for your vectors, and then passing in the actual sizes as additional arguments. There are other possibilities using combinations of all the methods shown.