24

I am implementing a configurable DPRAM where RAM DEPTH is the parameter.

How to determine ADDRESS WIDTH from RAM DEPTH?

I know the relation RAM DEPTH = 2 ^ (ADDRESS WIDTH)

i.e ADDRESS WIDTH = log (base 2) RAM DEPTH.

How to implement the log (base 2) function in Verilog?

toolic
  • 46,418
  • 10
  • 64
  • 104
Ashwini
  • 255
  • 1
  • 3
  • 7

2 Answers2

37

The $clog2 system task was added to the SystemVerilog extension to Verilog (IEEE Std 1800-2005). This returns an integer which has the value of the ceiling of the log base 2. The DEPTH need not be a power of 2.

module tb;

parameter DEPTH = 5;
parameter WIDTH = $clog2(DEPTH);

initial begin
    $display("d=%0d, w=%0d", DEPTH, WIDTH);
    #5 $finish;
end

endmodule

Running a simulation will display this:

d=5, w=3

However, I do not know of a synthesis tool which supports $clog2. If you need to synthesize your code, you can use a function. This was copied from the IEEE 1364-2001 Std, but there are other versions floating around the web:

function integer clogb2;
    input [31:0] value;
    begin
        value = value - 1;
        for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1) begin
            value = value >> 1;
        end
    end
endfunction

My experience has been that using the function is more trouble than it's worth for synthesizable code. It has caused problems for other tools in the design flow (linters, equivalence checkers, etc.).

toolic
  • 46,418
  • 10
  • 64
  • 104
  • 1
    Since it has been a few years since this answer was posted, I would like to point out that (at least some) synthesis tools do support $clog2 now. If your tool doesn't support it I would see if you can request it since it is a very useful function. – nguthrie Dec 15 '15 at 12:17
  • 2
    Verified that icestorm can synthesize `$clog2`. – jkschneider Jan 19 '17 at 06:25
  • recent Quartus versions support this. But i have seen issues with simulators like Incisive IUS. – sebs Nov 06 '17 at 09:11
24

While $clog2 is the correct answer, until the tool vendors catch up, you can implement your own clog2 function as a verilog-2001 macro, which will work with all synthesis and simulation tools.

Such as:

`define CLOG2(x) \
   (x <= 2) ? 1 : \
   (x <= 4) ? 2 : \
   (x <= 8) ? 3 : \
   (x <= 16) ? 4 : \
   (x <= 32) ? 5 : \
   (x <= 64) ? 6 : \
   ..etc, as far as you need to go..
   (x <= 4294967296) ? 32 : \
   -1

parameter FOO_MAX_VALUE = 42;
parameter FOO_WIDTH = `CLOG2(FOO_MAX_VALUE);

Where the final "-1" is used to produce an illegal value the the simulator should flag.

(late edit: oops, fixed my off-by-one error!)

Jonathan Mayer
  • 1,076
  • 9
  • 14
  • It works... but it is hacky and sloppy; it reminds me of a C snippet I saw once where the programmer needed to know if a number was even, so he compared it to all the even numbers between 0 and 100 – Kaiser Keister Oct 15 '19 at 13:40
  • 1
    Subtle difference, your first version calculates the bit width; while your edit calculates the ceiling of log base 2. So both algorithms are useful. Perhaps you could edit your post to show them both, i.e. CLOG2(x) and BIT_WIDTH(x). – tim Jun 20 '20 at 16:24