【精品博文】FPGA定点小数计算(Verilog版)第七篇——平方根倒数运算(使用John Carmack方法)
有一段时间没有写博客了,突然想起前一段时间挖的坑,所以决定今天来填一下……其实,这一篇原本打算写的是采用牛顿迭代法的平方根运算的博文,现在改为平方根倒数运算,很显然就是之前的尝试失败了……
为什么说是失败了呢?主要原因就是相比于其他的求平方根方法:CORDIC和查表法,我的方法(先求平方根倒数,再求倒数)并没有足够的优势。可能有人会问,你是不是傻,求平方根就求平方根,非要搞这么复杂干什么?其实,这里的平方根倒数运算采用的是John Carmack的改进方法,基本上只进行一次牛顿迭代就可以满足大部分场合的精度要求,大家可以看一下我之前转载的一篇博文:
http://blog.chinaaet.com/justlxy/p/5100052325
事实证明,用Verilog语言设计的模块最终也达到了预期的理想效果(具体后面再说)。但是,问题出在除法上面,由于除法采用的是移位法(可以看一下我之前写的一篇整数的除法运算,小数的除法要比这个复杂一点:http://blog.chinaaet.com/justlxy/p/5100052068),如果采用迭代运算的方式,的确也用不了多少资源,但是运行速度(时钟速度)确难以提升上去,如果进行Pipelining的话,需要大量的触发器资源和LUT资源……想了好久也没有找到比较好的定点小数除法(或者求倒数)的实现方案,所以只能暂时放弃之前的想法了……如果有哪位有比较好的方法的,肯请赐教!感激不尽!
但是,忙活了这么多天了,还是有点成果的,所以就算把关于平方根倒数计算的设计整理一下,写一篇博文与大家分享一下。其实这个设计早就写好了,在前面几篇博文内容的基础上实现的平方根倒数计算的效果并不太好,花费了差不多1K的LUT和24个乘法器,最终只能运行到50MHz多一点的水平,实在不能忍了,所以又花了几天时间把所有的设计全部Pipelining了一遍,目前的实现效果如下:
具体可以参考该文档,文档中还详细描述了源码中的浮点小数和定点小数的数据格式:
使用Synplify Pro综合得到的RTL视图(顶层)如下:
从左到右,各模块依次为定点转换为浮点、浮点转换为定点,牛顿迭代……
所有逻辑均为Pipeline结构,其中定点到浮点的Latency为3个时钟,浮点到顶点为2个时钟,牛顿迭代为15个时钟。牛顿迭代中的乘法器采用了Pipeline的结构,每一级4个时钟的Latency。
牛顿迭代的详细RTL视图如下:
其中,乘法器单元是采用Lattice Clarity生成的Module。
本程序要实现的功能实际上就是下面的这一段C代码:
原理很简单,就不细说了。
目前,经过初步的优化和时序约束,设计可以稳定运行在200MHz(通过时序仿真,时序分析,和板上验证以及Reveal调试),如果需要,稍加优化,还可以将速度提升至250MHz左右……
由于代码太长了,再加上仿真脚本之类的,太多了,所以就不贴出来了,如果哪位有需要或者有兴趣的,可以联系我索取,E-mail:justlxy@mail.dhu.edu.cn