FPGA使用的越来越广泛,除了可用于设计控制电路以为,数字信号处理电路更是FPGA的强项和难点。个人可以说才刚刚入门FPGA设计,也做过一些数字信号处理方面的电路设计,记录下个人心得体会。
(一)善用MATLAB来为设计做充分的准备和验证。
在学习EDA课程的时候,我们往往都是按照要求,直接打开QuartusII,噼里啪啦开始疯狂敲代码,然后仿真——不对——再改再仿真——还不对——再改直到仿真结果正确为止。不错,这的确是人们先入为主的一种方法。但这只是我们学习HDL语言,学习使用开发工具时候比较直接的方法,也只是适用于那个自己什么都不懂的阶段。面对大工程,复杂的数字逻辑,精确的数字信号处理,这样的方法只会让你无从下手。
MATLAB对数字信号处理而言,可以说是万能的。它基本包含了所有我们想要实现的运算,也可以完全得帮我们仿真出我们想要实现的某种算法。所以,在实际工程实现的时候,我们都会先使用MATLAB来仿真实现我们的目标,比如上几篇文中提到的FIR滤波器。
首先,我们使用MATLAB自带的函数,得到我们的理想值;
再用我们将采用的算法在MATLAB进行算法级的仿真(所谓算法级仿真,即和我们硬件实现的方法一致,如,卷积运算不能采用conv函数,而需要一步一步的进行相乘累加相乘累加……);有的人说这样是多此一举的,我也可以直接就在QuartusII里写代码,跳过这一步。其实,这是急功近利的做法,恰恰这一步是很重要的。如果设计顺利,这一步看起来的确有些多余。可当我们发现,算法仿真结果与我们的理想值(我们用函数算出来的值)不一致的时候,或者在之后进行FPGA设计时序仿真出现问题的时候,它的优势就来了,MATLAB的算法级仿真,可以很快的帮你找到并解决这个问题。例如:我们设计FIR滤波器,最后时序仿真结果和我们的算法仿真不一致!怎么办?哪里的问题?是不是设计都错了?不一定,我们的算法级仿真给了我们所有的中间过程的正确结果,我们可以通过比对他们,来确定是哪个环节出了问题。
完成了MATLAB的算法级仿真,就可以开始我们的硬件代码设计了。这个时候我们会发现,不再是无从下手了,因为我们只需要按照算法级仿真代码,按照HDL语言的语法要去,再以相应数字电路的coding style编写就可以了。随后再进行仿真,对比着算法仿真的结果,进一步修正硬件代码,这个过程将十分的轻松。
(二)经常查看RTL图。
做设计,最忌讳“想当然”。当我们做过几个设计,自认为有点经验的时候,很容易会有“想当然”的心态。老是觉得,我这么写代码,那最后出来的RTL电路就一定是这个样子的……其实不然。我们知道,从代码变换到RTL电路这个过程,叫做综合,而每个型号的芯片,综合规则都是不一样的,而且有时候我们还需要设定相应的综合规则来实现我们想要的结果。本人亲身的一次经历,做一个简单的单口RAM,首先是使用IP核设计,于是思维定势的觉得,既然是IP核生成的,那肯定是同步RAM,无需再进行设定了。可直到最后输出时序总是不理想,才又让我怀疑起了这个RAM,果不其然,查看了RTL图才发现,它不是同步RAM……有了这次教训,深刻得认识到,只有看到(RTL图),才能相信那是真的。
(三)尽量只做简单设计。
很多复杂的逻辑,实现起来很多人都想一口气用一个逻辑块来实现。这样做是很危险的……大家有空可以看看那些大牛们写的代码,再复杂的逻辑,无非多加个状态机,都不会有太多太乱的代码。一个复杂的逻辑实现,应该把它尽可能得分成简单逻辑的组合,因为如果逻辑设计得越复杂,时钟也就不能跑得很高,这对其它部分的设计带来了瓶颈,是相当不利的。
(四)遵从FPGA厂家给出的coding style。
不管是Altera还是Xilinx都给出了各自的coding style。虽然大多数情况,我们不按照那样的方式来编写代码并不会照成逻辑性的错误,但是却给设计带来了安全隐患。这样的隐患如果一旦出错,便很难通过仿真等手段来发觉。
(五)不要以为每款FPGA都是一样的。
同样的设计,换做不同的FPGA平台,其结果是不一样的!如果要深入设计FPGA,那一定要仔细阅读一款FPGA的芯片手册。个人建议是先挑一款较为大众的芯片阅读它的手册,然后可以基本掌握FPGA的结构和它工作的原理等。等熟悉了以后,就算换了芯片或者平台,也可以很快找到新的芯片的独特之处了。