FPGA实现对数log2和10*log10

找到的实现对数的方式有三种:

  • LUT
  • Cordic
  • 无名

LUT只能用在输入参数较少的情况中,Cordic看了下,感觉还挺复杂的,就没看了……这里主要讲第三种方式,无名是因为没有找到叫什么名字,它的基本思路是先求log2然后在用换底公式求log10。

1. 求 l o g 2 log_2 log2

观察下面的表格可以发现,只要找到了输入二进制从高位开始第一个为1的bit的位置,就能知道其log2的整数部分。至于小数部分,则可以使用查表的方式来实现,如果要精度比较高,就将表做细一点。总的来说,这种开销是很小的。

二进制 log2
00100 2
00101 2.3219
00110 2.5850
00111 2.8074
00010 1
01000 3

2. 求 l o g 10 log_{10} log10

在求得 l o g 2 log_2 log2以后,就可以通过换底公式求 l o g 10 log_{10} log10

l o g a b = l o g c b l o g c a log_ab = \frac{log_cb}{log_ca} logab=logcalogcb

不过这里要求的 10 ∗ l o g 10 10*log_{10} 10log10,做如下推导

10 ∗ l o g 10 b = 10 ∗ l o g 2 b l o g 2 10 = 10 ∗ l o g 2 b 3.3219 = 3.0103 ∗ l o g 2 b 10*log_{10}b =\frac{10*log_2b}{log_210} = \frac{10*log_2b}{3.3219} = 3.0103*log_2b 10log10b=log21010log2b=3.321910log2b=3.0103log2b

不管误差,在HDL实现的时候有

3 ∗ l o g 2 b = 2 ∗ l o g 2 b + l o g 2 b = l o g 2 b < < 1 + l o g 2 b 3*log_2b = 2*log_2b + log_2b = log_2b << 1 + log_2b 3log2b=2log2b+log2b=log2b<<1+log2b

所以在没有使用任何乘除法的情况下,我们就实现了 l o g 2 log_2 log2 10 ∗ l o g 10 10*log_{10} 10log10

我用systemverilog实现了上述方法,代码链接如下,没分的可以留下邮箱,记得先点赞^^

https://download.csdn.net/download/qq_16923717/11570694

注意:不建议将该代码用到实际的工程中,精度不够是一个原因,更重要的是该代码中有很长的if else,时序可能不好

3. 求 l o g 10 ( a ) , 0 < a < 1 log_{10}(a), 0 < a < 1 log10(a)0<a<1

如果输入a小于1的话,上述方法就不行了,但是通过下面的公式,我们还是可以求出来。
l o g a ( x ∗ y ) = l o g a ( x ) + l o g a ( y ) log_a(x*y) = log_a(x) + log_a(y) loga(xy)=loga(x)+loga(y)
比如求 l o g 10 ( 0.01 ) log_{10}(0.01) log10(0.01)
l o g 10 ( 0.01 ) = l o g 10 ( 10 ) − l o g 10 ( 1000 ) = 1 − 3 = − 2 log_{10}(0.01) = log_{10}(10) - log_{10}(1000) = 1 - 3 =-2 log10(0.01)=log10(10)log10(1000)=13=2
这样我们只需要在输入前对 a a a 进行放大,然后对算出的结果减去一个固定值就好了。
.

参考链接
  1. 用verilog实现log2的一种方法

.
.
.
.
.
.

你可能感兴趣的:(数字信号处理)