Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
17 years ago

Determine address width in Verilog HDL with $clog2

Dear all,

Does anybody know how to use the Verilog HDL $clog2 math function with the Quartus II software?

I am trying to use the clog2 (=ceil(log2(x))) function to calculate the address width needed for a RAM block with x number of words, since I think it's a bit silly to have to input two different parameter values in a parametrized module when the parameters are equivalent. However, when I try to compile my design in Quartus, I get the follwing error:

Error (10174): Verilog HDL Unsupported Feature error at VPP.v(82): system function "$clog2" is not supported for synthesis

Any idea what I did wrong? Thanks in advance.

Faruk

8 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    In quartus, you have to use the so called "constant functions". This is a function that operates only on cosntants, and so can be used during the first steps of the synthesis:

    For example :

    module pulse(input Clk, input Reset, output Pulse);
    parameter COUNTS = 33;
    reg  count;
    assign Pulse = count == 0;
    always @(posedge Clk or posedge Reset)
    	if (Reset)
    		count <= 0;
    	else
    		count <= count + 1;
    //ceil of the log base 2
    function integer CLogB2;
    	input  Depth;
    	integer i;
    	begin
    	 	i = Depth;		
    		for(CLogB2 = 0; i > 0; CLogB2 = CLogB2 + 1)
    			i = i >> 1;
    	end
    endfunction
    endmodule

    Stefaan
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hello Stefaan,

    Thanks very much, I was able to use your code example to calculate the address widths.

    By the way, the IEEE Verilog standard mentions that the constant function must be defined locally within the module. This would mean that every time I would like to use the CLogB2 function I have to define the function within that module (locally). I guess that one way to solve this is to define useful functions in a header file and include the header when necessary:

    main.v

    
    module main(..)
     
    `include "MathFun.vh"
    parameter address_width=CLogB2(num_words);
     
    endmodule
    

    MathFun.vh

    
    //ceil of the log base 2
    function integer CLogB2;
        input  Depth;
        integer i;
        begin
             i = Depth;        
            for(CLogB2 = 0; i > 0; CLogB2 = CLogB2 + 1)
                i = i >> 1;
        end
    endfunction
    

    Another way would be to try convince Altera that a function such as log2 is actually very useful in the real world ...(and that they should listen to the IEEE guys who have $clog2 as part of the standard :) )

    Faruk
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Faruk,

    I put the function in the module everytime (I copy it in at the bottom every time). It's not that much work, and the functionality stays like you wrote it. For example if for some reason the function has to change, it can affect all your files that include MathFun.vh. I know in this case it will be unlikely that the CLogB2 function will change...

    Although for altera it can be outside the module, but this is not standard, and can cause problems with some simulators.

    Stefaan
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Although for altera it can be outside the module, but this is not standard, and can cause problems with some simulators.

    --- Quote End ---

    Quartus II allows global functions if you are compiling with SystemVerilog extensions. Otherwise, you should get an error.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Put the function into a package, and then call it from anywhere. I do it in package utils and then call it with utils::clog2()

    Simple and organized, and there is no need to add an include.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Quartus II 9.1 supports the built-in $clog2 function from Verilog 2005 in all Verilog and SystemVerilog modes. Yes, this technically goes beyond the standard but also matches the behavior of other tools.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    In quartus, you have to use the so called "constant functions". This is a function that operates only on cosntants, and so can be used during the first steps of the synthesis:

    For example :

    module pulse(input Clk, input Reset, output Pulse);
     
    parameter COUNTS = 33;
     
    reg  count;
     
    assign Pulse = count == 0;
     
    always @(posedge Clk or posedge Reset)
        if (Reset)
            count <= 0;
        else
            count <= count + 1;
     
     
     
    //ceil of the log base 2
    function integer CLogB2;
        input  Depth;
        integer i;
        begin
             i = Depth;        
            for(CLogB2 = 0; i > 0; CLogB2 = CLogB2 + 1)
                i = i >> 1;
        end
    endfunction
     
    endmodule

    Stefaan

    --- Quote End ---

    Thanks for your code Stefaan

    Can u please guide me if this were the case of a floor function instead of ceiling? My code includes a portion where i have to calculate the floor log of a variable. Your function worked great for a ceiling computation. Can u help me with floor function? Thanks alot