blob: 54d8a37e0db39bc0e4fa1d64f5a1fc01a3c8e967 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
/**
* Utility functions
*/
package prim_util_pkg;
/**
* Math function: $clog2 as specified in Verilog-2005
*
* Do not use this function if $clog2() is available.
*
* clog2 = 0 for value == 0
* ceil(log2(value)) for value >= 1
*
* This implementation is a synthesizable variant of the $clog2 function as
* specified in the Verilog-2005 standard (IEEE 1364-2005).
*
* To quote the standard:
* The system function $clog2 shall return the ceiling of the log
* base 2 of the argument (the log rounded up to an integer
* value). The argument can be an integer or an arbitrary sized
* vector value. The argument shall be treated as an unsigned
* value, and an argument value of 0 shall produce a result of 0.
*/
function automatic integer _clog2(integer value);
integer result;
// Use an intermediate value to avoid assigning to an input port, which produces a warning in
// Synopsys DC.
integer v = value;
v = v - 1;
for (result = 0; v > 0; result++) begin
v = v >> 1;
end
return result;
endfunction
/**
* Math function: Number of bits needed to address |value| items.
*
* 0 for value == 0
* vbits = 1 for value == 1
* ceil(log2(value)) for value > 1
*
*
* The primary use case for this function is the definition of registers/arrays
* which are wide enough to contain |value| items.
*
* This function identical to $clog2() for all input values except the value 1;
* it could be considered an "enhanced" $clog2() function.
*
*
* Example 1:
* parameter Items = 1;
* localparam ItemsWidth = vbits(Items); // 1
* logic [ItemsWidth-1:0] item_register; // items_register is now [0:0]
*
* Example 2:
* parameter Items = 64;
* localparam ItemsWidth = vbits(Items); // 6
* logic [ItemsWidth-1:0] item_register; // items_register is now [5:0]
*
* Note: If you want to store the number "value" inside a register, you need
* a register with size vbits(value + 1), since you also need to store
* the number 0.
*
* Example 3:
* logic [vbits(64)-1:0] store_64_logic_values; // width is [5:0]
* logic [vbits(64 + 1)-1:0] store_number_64; // width is [6:0]
*/
function automatic integer vbits(integer value);
`ifdef XCELIUM
// The use of system functions was not allowed here in Verilog-2001, but is
// valid since (System)Verilog-2005, which is also when $clog2() first
// appeared.
// Xcelium < 19.10 does not yet support the use of $clog2() here, fall back
// to an implementation without a system function. Remove this workaround
// if we require a newer Xcelium version.
// See #2579 and #2597.
return (value == 1) ? 1 : _clog2(value);
`else
return (value == 1) ? 1 : $clog2(value);
`endif
endfunction
endpackage