Logarithm in Verilog

I've a statement in verilog looking like integer level = log(N) (Where N is a parameter and level is to be determined) But I understand I cannot do complex math statements in verilog, so I'm wondering if there is an alternative solution to the above problem?

Any feedback appreciated!

7

5 Answers

If it is a logarithm base 2 you are trying to do, you can use the built-in function $clog2().

The answer to ADDRESS WIDTH from RAM DEPTH describes a couple ways to evaluate constant logarithms in this situation.

Verilog has functions for natural logarithm ($ln()), decadic logarithm ($log10()) and ceiling of binary logarithm ($clog2()). In constant expressions they should be synthesizable, but actual support by tools varies.

The following is synthesizable Verilog code:

module test(output [31:0] a, b, c);
  assign a = 1000 * $ln(123);
  assign b = 1000 * $log10(123);
  assign c = 1000 * $clog2(123);
endmodule

E.g. after RTL synthesis with Yosys (e.g. yosys -p 'prep; write_verilog -noattr' test.v):

module test(a, b, c);
  output [31:0] a;
  output [31:0] b;
  output [31:0] c;
  assign a = 32'd4812;
  assign b = 32'd2090;
  assign c = 32'd7000;
endmodule

But I understand I cannot do complex math statements in Verilog

Verilog is first and foremost a hardware description language. What hardware log(N) statement is describing? Modern FPGAs consist of LUTs, flops, small embedded memories, simple DSPs that implement MAC (multiply-accumulate) primitives. log(N) and other complex math statements cannot be mapped directly into those primitives. The same goes with ASICs.

By analogy, log(N) doesn't get executed by a processor. It calls a bunch of lower-level assembly instructions to do so. Those assembly instructions are part of the log(N) library (C, C++, etc.)

To be able to synthesize log(N) for ASIC/FPGA it requires an instance of a log(N) IP core.

I like to think of (logarithm base n of value) as answering the question "How many base n digits do I need to represent 'value' independent numbers?" (Keeping in mind that 0 counts as a number)

Thinking of it that way, you can implement your own log base 2 in SystemVerilog:

function bit [31:0] log_base_2 (bit [31:0] log_input);
  bit [31:0] input_copy;
  bit [31:0] log_out = 0;
  input_copy = log_input;

  while(input_copy > 0)begin
    input_copy = input_copy >> 1;
    log_out = log_out + 1;
  end
  log_out = log_out - 1;

  if(log_input != (1 << log_out))
    log_out = log_out + 1;

  return log_out;
endfunction

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Marcus Vance

Marcus Vance

Cybersecurity & Digital Privacy Researcher

Marcus Vance is a cybersecurity auditor and technology writer dedicated to educating the public about online safety, data privacy regulations, enterprise security, and emerging cyber threats.

Share this article
Twitter Facebook Pinterest