前面我们花了大约20篇文章,基本将AMBA中的AXI、APB和AHB讲完了。这些总线协议实际上主要针对的是SoC设计。除了买IP做SoC集成以外,一个公司想要有竞争力,那就必须要有自己设计的IP。
IP的类型非常多,其中有一大类可以统称为算法硬件IP。接下来我打算花一二十篇文章,讲解如何“翻译”算法代码,即从算法到RTL实现。
此类芯片的开发流程基本如下:
- 算法工程师通过MATLAB或者C等语言对算法进行建模
- 芯片前端设计工程师对算法充分理解以后,将算法手工转换为RTL代码
- RTL与算法产生的输出对比进行验证
- 迭代面积时序功耗等等.....
很多学生朋友,或者是初入职场的新人工程师,碰到的第一个任务。可能就是让你学习某一个算法,然后让你用RTL实现,在FPGA跑起来。如何将算法转换成RTL,就是本系列文章讨论的重点。
其实这些算法,归根结底就是一系列的数学公式或者逻辑运算。对于算法设计者而言,可能没有什么复杂的,但是对于硬件实现完全不是这么回事。比如除法、求幂运算、正余弦函数这些稀松平常的数学运算,用硬件实现起来可远没有那么容易。我之前碰到一个实习生,直接写三个32bit的数相乘,用assign输出给下一级模块。大概如下:
module( ... output d ) assign d=a*b*c; endmodule
这种就属于完全没入门,没理解自己在设计的是硬件,而不是软件。希望我的这些文章能帮助大家掌握最基本的算法到RTL的设计思想。
1、芯片设计的定点化
算法,核心就是数。整数可能还好一点,问题是我们在实际的芯片设计中,经常会遇到浮点数的处理。当我们碰到浮点数的时候,应该怎么去处理呢?接下来带大家探讨这一问题。
首先我们明确,为什么需要定点化?首先记住这一结论:因为存在浮点运算的需要,所以需要定点化(但不是所有的浮点运算,都采用定点化的方式去处理,比如可以用IEEE754的浮点格式处理,这些内容后面说)。定点化可以将浮点运算转换为整型的运算,其比起直接算浮点数,高效的多。定点的精度决定了系统的性能,所以我们经常会将RTL的输出和软件的输出比对,误差小于某个范围则认为可以忽略,用于权衡速度和精度。
所谓的定点,实际上就是把小数点给固定下来,我们的数字电路中,都是一堆0和1。并没有某个信号可以去表示一个点,所以其实这个点在哪里,是取决于我们是怎么规定的。正所谓心中有点,点就在那里。
那么哪些芯片的设计需要用到浮点数值的定点化呢?最典型的有以下几种:
①:通信芯片,比如5G芯片、WIFI芯片、蓝牙芯片等。凡是需要和空气信道打交道的,那就必然面临调制解调相关的处理。这个时候必然会有小数产生。
②:DSP及其相关的芯片,其实其本质上还是跟信号处理相关,比如从ADC采集的数据,后续的处理就必然会有小数。此外此处的信号处理可能是更加广泛的信号处理,包括但不限于现在的神经网络加速器、图像处理芯片、音视频编解码芯片等。这些芯片可能都需要处理小数,因此也会涉及到浮点数的定点化。此外还有一些加解密芯片也会涉及到定点化。
接下来让我们看这样的一个问题:
问:如何根据数值范围和精度要求,来判断所需要的比特宽度?比如最大可以到达100,要求达到的精度是0.001
答:非常的简单,碰到这种问题就用 ���2� 算。比如这个例子中,我们直接用log100往上取整,得到7,然后log(-0.001)向下取整得到-10。因此可以得到整数部分用7个bit,小数部分用10个bit。如果是有符号数再加一个符号位,总共需要18个比特。
2、小数的四舍五入
讲到定点化,就不得不提到数据截取。毕竟很多时候我们需要挑数据的某些比特来使用,那大家是否有想过数据截取的数学含义呢?
我们看这样的一个无符号数,4'b1111。如果看做一个整数,那么它就是15,假如我们截取它的高两比特,那么就是2'b11,也就是3。实际上3相当于floor(15/4)。即直接截取默认是向下取整,对于正数负数都是如此。这种情况就可能出现,你的软件模型的输出和你RTL代码的输出不一致,进而导致对比不通过。那么如何保证你的RTL代码和软件模型的输出代码一致呢?默认向下取整自然不可取,可能算着算着数就没了。最先想到的应该是进行四舍五入取整,软件与其保持一致,才能验证比对通过,并且精度不会太差。
那么如何进行四舍五入呢?要知道计算机看到的是一堆0和1,当你看到15/4的时候,你可能会知道它是3.75,四舍五入是4。可数字电路它不知道啊!你必须要设计一个合理的运算机制,才能完成四舍五入,其运算如下:
- 首先将计算结果保留1位小数,如上面的例子中,4'b1111,我们做扩展为5'b01111,本来要截取2位,我们多保留1位,为4'b0111
- 然后在数值上加1,即4'b1000
- 我们再正常截取小数部分,只保留整数部分。即3'b100为4。
非常的神奇啊,我们完成了四舍五入!大家可以试一下别的数,都是成立的。其实背后的数学原理为,看它有没有那个“0.5”。上述的方法对于负数实际上也是成立的,不过有一点要注意,对于-5.5这样的数,上面的运算得到的是-5而不是-6。其实对于这种刚好小数部分是0.5的数,四舍五入到哪一边对结果影响没那么大,重点是0.25、0.75这样的数据千万不能四舍五入错了。
最后说明一点,上面的有符号数还是无符号数,其实是取决于你自己,即芯片设计者是怎么认为的。此外这些定点数,不管是正数还是负数,其实际上都是用补码的方式表示的。(数字电路自己不知道什么是补码,它只知道0和1,但是仿真工具默认它是补码,作为设计者的你也应该知道)