把轮子做好
——写给仍在“增删查改”里挣扎的 FPGA 工程师
1 轮子、车与接口
代码之所以能被开源,是因为它天然是可复用的“轮子”。如果需要解决一个特定的问题,你可以使用所有程序员在互联网上开源的代码片段,也就是库函数。当然,在FPGA领域这个库函数被称为IP核,入门时期,老师通常喜欢用“黑盒子”这个词来程称呼库函数。无论这个黑盒子的逻辑有多么的复杂,你都可以不用去理解,你只需要知道,黑盒子的输入和对应的输出就好。这就是我理解的模块,也是“重复造轮子”这句经典名言中的“轮子”。当然,希望人们不要重复的去造轮子。有了这个轮子,我们就可以把不同的轮子放在不同的“车”上,来使得我们的车达到不同的功能。那这个轮子就是我们车辆整体的一个模块,无论轮子大小和形状如何,应该允许我们方便地把轮子装到我们的车上。车辆和轮子连接的地方就是“接口”。只要接口统一,轮子就能随意拆装,车就能千变万化。
可惜,现实常常八嘎:
在最近的“增删查改”学习中,出现了太多关于模块的问题。我时常想要在不同的程序框架下去更改一些功能,这些功能是已经存在于其他的框架中的功能,我需要把他们“ctrl+v”到新的框架下。这让我想起了上文中提到的换轮子的例子,我是否也可以把他们直接的换过来。事实上,并不能,也许在大部分的程序员应用场景都不能。原因就是,这个接口出问题了。
我不需要关注“功能”模块的逻辑和形状,我只需要知道他的"接口"就好。但是,实际情况是,不同的框架的接口并不相同,不同的功能接口也不相同。这就很八嘎了,没有统一的接口,在组合这些轮子的时候就不能发挥代码的复用性,尤其是在FPGA领域,因为资源总是拉满。
于是“重复造轮子”成了日常。
2 FPGA 调试地狱
• 在线调试:
查bug这件事是所有程序要必须要面对的,但对于FPGA来说,查bug的难度比软件或者嵌入式都要高很多。这是因为软件里打断点就能看变量,FPGA是在电路层进行操作,而你想要把电路层的实际运行过程提取出来进行观察是非常难的,工程师通常使用各个厂家软件自带的debug工具进行操作。由于debug工具需要对源码进行处理,在其中增加一些IP和接口,这也会导致FPGA资源利用率的提高。在实际工程中,经常会出现资源占用率过高导致没有空闲资源可以用来进行debug。
• 离线仿真:
其实,还有另外一种方式,就是进行仿真。使用matlab或者modelsim等工具,可以对FPGA的源码进行仿真操作,通过波形图来排查问题,上文的debug也是如此,只不过一个是按照逻辑仿真出的,一个是实际电路中的。当然,别想着仿真就可以顺利的看到想看的时序图。因为,仿真毕竟不是真正的电路情况,所以仿真需要进行仿真环境的搭建,还要对源码中的很多模块进行修改,让其不按照实际情况运行,否则会出现仿真速度非常慢、信号跳转错误等问题。很多时候,搭建仿真的成本也令人望而生畏。
调试成本如此之高,才显得“轮子”必须自带自检: 可仿真、可替换、可拔插。这也是做好模块的必要性。实际上,模块也可以过多,过多的模块也会导致资源占用过大,提高工程成本。所以怎么判断模块的大小是一件比较重要的事情,我认为有以下几个标准:
- 接口数量20个
- 单独的功能模块
- 接口握手协议统一性
- 时钟域隔离,跨域打拍子别让我猜
- 单个模块可仿真
在我收到的大部分工程中,大部分是这样的情况:在程序架构之初是有明显的框架和模块化的,但是随着后边不断地增删查改,由于程序在不断地更换人手,导致不了解的人并不想去继续地模块化一些功能,进而造成了耦合性不断地提高,这对于已经熟悉这些代码的人并不是什么太重要的事情。显而易见,我们需要把代码分享给别人,或者开源或者重复利用。这都要求我们要重视代码的模块化和耦合性问题。
一句话
从头开始的时候就把轮子做得足够小、接口足够统一、仿真足够轻。
1028






