9

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!

hammar
  • 138,522
  • 17
  • 304
  • 385
Max Eastman
  • 91
  • 1
  • 1
  • 2
  • What kind of logarithm are you trying to computer? An integer log base 2 is easy. A floating point log base e is much harder. – Gabe Apr 09 '11 at 00:58
  • Is N a compile-time constant? – Andy Apr 09 '11 at 01:00
  • yes! Its a parameter to the module – Max Eastman Apr 09 '11 at 01:03
  • 1
    In that case it's pretty easy. You can use a lookup table if N is small and speed is an issue. If N can get large, you can just loop over the bits of N from left to right, until you find a 1 bit. – Gabe Apr 09 '11 at 01:08
  • how do you do a lookup table? Also N caps out at 128 or maybe 256 but thats about it – Max Eastman Apr 09 '11 at 01:13
  • You can find an explanation and an implementation in SystemVerilog (quite similar to Verilog) of a Logarithm in base 2 in this website: http://sistenix.com/logarithm.html Once the log2 is simpler to be implemented compared to other bases, you can calculate other logarithms in different bases just multiplying the result of log2 by a constant number. –  Aug 26 '16 at 12:07
  • @Gabe would you please let me more how I can do this " If N can get large, you can just loop over the bits of N from left to right, until you find a 1 bit."? – Carter Feb 12 '18 at 14:52

5 Answers5

10

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

Qiu
  • 5,651
  • 10
  • 49
  • 56
abettino
  • 146
  • 1
  • 3
5

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

Community
  • 1
  • 1
Andy
  • 4,789
  • 23
  • 20
4

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
CliffordVienna
  • 7,995
  • 1
  • 37
  • 57
2

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.

Qiu
  • 5,651
  • 10
  • 49
  • 56
OutputLogic
  • 756
  • 4
  • 12
1

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
dolphus333
  • 1,232
  • 1
  • 13
  • 18