1. 跳出“等货”思维:先看懂这次短缺为什么不一样
这几年做硬件的人,几乎没有谁没被FPGA的货期和价格折腾过。早些年我们聊FPGA选型,第一反应是看逻辑资源、看高速串行收发器、看开发环境顺不顺手;现在聊FPGA,第一句往往变成“这个型号现在好不好买、要等多少周”。我自己就经历过一次项目停摆:主控用的某颗7系列芯片,原计划交期8周,结果供应商一推再推,最后拖到20周还没影,整个团队被迫临时改方案。从那以后我形成一个习惯,任何新项目启动前,先花半天时间把FPGA的供应链状态摸一遍,再谈技术选型。
这次短缺和以往不一样的地方在于,它不是单纯的“某个物料缺货”,而是整个产业链的产能排挤。先进制程的晶圆资源优先供给手机SoC、AI加速卡这类高利润产品,FPGA这种出货量相对分散、单颗价值量又没那么夸张的芯片,排产优先级自然靠后。再加上车规、工控、通信几个赛道同时在抢产能,交期被拉到二三十周甚至更长就成了一种常态。对于研发工程师来说,这意味着“按常规交期倒排项目计划”的做法已经失效了,我们必须把供应链风险纳入到架构设计里,而不是等项目启动之后再被动应对。
那具体怎么应对?我的经验是三个方向同时发力:第一,设计上做“可迁移”的方案,不能把鸡蛋全押在一颗芯片上;第二,选型上主动拥抱国产和成熟工艺的替代方案,而不是死守单一品牌;第三,项目管理上把FPGA的备货和验证挪到更靠前的位置,甚至在原理图还没冻结的时候就开始做小批量样品验证。这三个方向没有哪个是万能的,但组合起来,能让项目在“等货”的缝隙里依然往前走。
这篇内容我打算围绕期刊上读到的几篇FPGA供应链分析文章,结合我自己实际做过的几个项目,把这些策略拆开讲透。适合正在做FPGA开发、或者正在为项目选主控的工程师参考,也适合刚入门FPGA、对行业现状还不熟悉的同学用来建立全局认知。下面从项目设计的源头讲起。
2. 项目设计阶段就要做的供应链预案
2.1 首选与备选方案并行评估,而不是串行等待
过去我们做FPGA选型,流程通常是先看需求,然后锁定一个厂商的一个系列,接着把开发板买回来、搭环境、写代码,一路做下去。等到芯片买不到的时候,才想起来看有没有替代料,这时候往往已经晚了——代码可能用了原厂的硬核IP,PCB已经按原芯片的封装画完,想换几乎等于重做。
后来我调整了做法:在项目需求分析阶段,就同时评估两款FPGA,一颗是首选,一颗是备选。首选可以是性能更合适、开发资源更多的型号,备选则是供货更有保障、但可能在某些指标上弱一点的型号。评估的内容不只是逻辑资源够不够,还包括封装是否兼容、引脚定义能否复用、用的IP核有没有跨平台的可替代方案。如果两颗芯片能做到“PCB兼容、代码可移植”,那备选方案就是实实在在的保险,而不是纸面上的plan B。
举个例子,我之前做过一个工业视觉项目,首选方案是Xilinx的Artix-7系列,备选方案是一颗国产28nm FPGA。两颗芯片的封装完全不同,但我们从一开始就定义好了一个“接口抽象层”,所有对外通信(比如LVDS、SPI、I2C)都封装成统一模块,内部逻辑通过宏定义切换平台。最后因为交期原因真的切到了国产芯片,从改代码到跑通demo,只花了一周半。这个代价远比项目停摆两个月小得多。
2.2 把“降规格”作为常用手段,而不是最后的救命稻草
FPGA短缺的时候,很多团队第一反应是找同系列的更大容量芯片顶上,理由是“反正资源多一点,编译肯定能过”。这个思路其实问题很大,首先大容量芯片的交期往往比主流容量更差,因为它用的晶圆制程更紧俏;其次大容量芯片的封装更大、功耗更高,PCB和散热都要跟着改,等于自己给自己挖坑。
我更推荐的做法是反过来:审视一下当前设计里真正用掉了多少资源。很多时候我们习惯性地把缓存开大、把位宽设宽、把流水线层级加深,资源占用不知不觉就上去了。如果能在架构层面做减法——比如把一部分不常用的功能搬到CPU上去做软处理,比如精简图像处理里的缓存策略,fpga的逻辑资源需求是可以压下来的。资源降下来之后,可以选的芯片范围就大多了,既有国产的成熟制程产品,也有国际厂商的老型号库存,交期和价格都会友好很多。
这里有一个我反复验证过的经验:fpga设计的逻辑资源占用,通常不是由核心算法决定的,而是由缓存、跨时钟域处理、调试逻辑这几块决定的。算法本身往往只占20%~30%的资源,剩下的都被“为了稳妥而加的冗余”吃掉了。把冗余砍掉,规格自然就下来了。
2.3 pcie、图像处理、电机控制等场景的性能取舍
fpga做的事情五花八门,但追根溯源无非是几类场景:高速接口(pcie、mipi、hdmi)、数据采集与信号处理(lvds、adc、tdc)、图像处理(isp、缩放、降噪)、运动控制(biss-c、编码器、pwm)。不同场景对芯片资源的诉求差异很大,应对短缺的策略也不一样。
接口类场景,尤其是pcie,最大的约束往往不是逻辑资源,而是高速串行收发器的数量和协议栈的完整性。这类场景换芯片的代价最大,因为pcie硬核、mipi phy这些资源在不同系列之间差别很大,几乎没有简单的平移方案。我的建议是项目早期就要确认好这些硬核资源,并且优先选择供货周期稳定的系列——哪怕单颗贵一点,也比项目延期划算。
图像处理场景相对灵活,算法逻辑可以改,缓存深度可以调,行存、帧存的比例也能变,只要资源和带宽够用,换芯片的迁移成本可控。我做过一个图像项目,原本用Zynq做,后来缩减成纯逻辑的中端fpga,把图像前处理全放在PL侧,ARM核的功能用外部单片机和上位机替代,资源省了一大截,供货问题也解决了。
电机控制和biss-c编码器这类场景,核心成本在位置环的实时性和抗干扰上。这种设计对外设接口要求不高,逻辑资源适中,非常适合用国产fpga承接。我自己测试过高云和紫光的中小容量型号,跑biss-c协议完全没问题,时序裕量也够,成本比进口芯片低了一半还多。
3. 选型与替代评估的实用方法论
3.1 从逻辑资源、引脚、封装三个维度做替代评估
很多工程师评估fpga替代方案的时候,喜欢直接比较“逻辑单元数量”这个参数。这个做法过于粗放了,实际项目里更应该关注三个维度:逻辑资源、可用引脚、封装兼容性。
逻辑资源方面,不要只看LUT和FF的数量,还要看DSP slice、BRAM、时钟资源的分布。有些算法对乘法器消耗很大,有些对片上存储敏感,如果新芯片的LUT数量够但DSP不够,一样跑不起来。引脚方面,要仔细核对电源引脚、配置引脚、高速串行收发器的分布。不同厂商的引脚定义差异很大,尤其是供电管脚的位置和数量,稍不留神就会导致PCB要重新画。封装兼容性是最容易踩坑的地方,同样叫FGG484,不同系列的实际焊盘定义可能完全不同,不要想当然地认为“封装一样就能替换”。
我自己的做法是做一个替代评估表格,把5个维度的参数列出来逐项比:逻辑资源、BRAM、DSP、高速收发器、封装引脚。每一项都标出“相同、兼容、不兼容”的状态,然后综合打分。只有三项以上达到“兼容”或者“相同”,并且关键资源没有硬伤,才会把替代方案纳入候选。
3.2 国产fpga的承接能力:高云、紫光、黑金等平台的实测感受
国产fpga这几年进步很明显,但产品和产品之间的成熟度差异也很大。我在几个项目里用过高云、紫光,配合过黑金的开发板,简单说说实测感受。
高云的小封装芯片在接口控制、电机驱动这些场景里表现得非常稳定,开发软件GVDS上手挺快,基本逻辑资源和简单IP核的功能都完整,但大容量型号的选择还不多,高速串行收发器也相对少。紫光的Logos系列在逻辑资源上更丰富一些,适合图像处理、通信协议这些对资源有一定要求的场景,但部分IP核的成熟度还需要打磨,我在做ddr控制器时遇到过时序收敛比较费劲的情况。黑金作为开发板厂商,生态做得挺好,有大量的例程可以参照,对于刚转国产平台的工程师来说能省不少时间。
整体上我的判断是:国产fpga在中小容量、中低速率场景已经完全具备替代能力,而且交期和价格优势明显;但在大容量、高速率、复杂生态(比如pcie硬核方案)这些场景,还需要谨慎评估,最好先用开发板做原型验证,再决定是否切换。
3.3 zynq与纯fpga的路线选择:是否要把arm核砍掉
Zynq这种带ARM核的异构方案,在过去几年非常流行,因为一片芯片既能跑Linux系统又能做逻辑处理,硬件设计简洁,开发效率高。但放在fpga短缺的背景下,Zynq的劣势就暴露出来了:它的制程更先进、封装更复杂、供货更紧张,而且在纯逻辑需求不大的项目里,ARM核那一部分的成本完全浪费了。
我现在做方案选型时,会先问一个问题:这个项目真的需要Linux吗?如果只是做数据采集、协议转换、图像预处理这些纯逻辑任务,完全可以用“fpga+外部廉价MCU”的方式替代。fpga负责高速并行处理,MCU负责配置管理和对外通信,两边各司其职,成本更低,供货选择也更宽。我做过一个数据采集项目,原来用Zynq跑Linux+采集逻辑,后来改成纯fpga采数据、STM32做网络上传,整体物料成本降了三分之一,交期压力也小了很多。
当然,如果项目明确需要跑Linux、需要复杂文件系统或者网络协议栈,那Zynq还是更合适的选择。这时候建议优先评估Zynq系列里更成熟的型号,同时把ARM侧的软件功能尽量精简,降低整个系统对芯片性能的依赖。
4. fpga开发核心环节的实战要点
4.1 时序约束和跨时钟域处理:换芯片后最常翻车的两个地方
fpga开发里有一句老话:“逻辑仿真跑得通,上板不一定跑得稳。” 换芯片之后,这句话的应验概率会大幅上升。时序约束和跨时钟域处理,是移植代码时最常出问题的两个环节。
时序约束这块,不同厂商的约束文件语法差异很大。Xilinx用XDC,Lattice和部分国产芯片用SDC,虽然都是基于SDC衍生出来的,但具体命令的写法、时钟组定义的细节都有差别。换芯片之后,不能直接把约束文件拿过来改个名字就完事,一定要逐条检查每个时钟域的定义、每条路径的约束是否合理。我吃过一次亏:把Xilinx工程里的create_clock命令照搬到国产芯片上,结果因为没有明确虚拟时钟,导致一组跨时钟域路径的约束完全失效,板子跑起来偶发数据错乱,排查了两天才发现是这个问题。
跨时钟域处理的坑则更深。原来在Xilinx上用了FIFO IP来做异步数据交互,换成国产芯片后,IP核的参数设置不完全一致,FIFO的读写时序差了几个纳秒,导致数据偶尔丢一拍。后来我把所有跨时钟域的逻辑都改成了手写的双口RAM+格雷码指针方案,虽然代码量大了,但可移植性强了很多,任何芯片上都能用,再也不用依赖厂商IP的兼容性了。
4.2 lvds接收、spi配置、ddr搬移的实现与调试记录
高速接口的实现,是fpga开发中难度最大、也最容易出问题的部分。lvds接收、spi配置、ddr数据搬移这三个场景,是我自己在不同项目里反复碰到的,每个都踩过不少坑。
lvds接收的难点在于时序对齐。7系列fpga做lvds时,可以用ISERDES来实现串并转换,bit slip和delay calibration都容易配置;但换到国产芯片后,不同系列的io delay资源差异很大,需要仔细看datasheet确认delay line的精度和可调范围。我以前做过一个lvds图像接收项目,在Xilinx上跑得好好的,换芯片后图像一直有锯齿条纹,查了半天发现是lvds的bit同步没有对准,最后通过调整delay值把采样点移到眼图正中央才解决。经验就是:lvds调试时不要直接看图像或数据对不对,先看同步信号和delay的扫描结果,把物理层的对齐搞定再谈上层协议。
spi配置的坑相对少一些,但有一个细节值得注意:fpga从spi flash加载配置的时间,不同芯片差异很大。有些国产芯片的加载时间比Xilinx长不少,如果系统里有时序敏感的电路,比如biss-c编码器在上电后很快就会发送位置请求,fpga还没配置完成就会漏掉数据。解决方案是在fpga配置完成之前,用一个外部逻辑(比如单片机的gpio或一个简单的逻辑门)把编码器的时钟屏蔽掉,等fpga发出init_done信号之后再把时钟放行。
ddr的读写搬移,是fpga开发里最考验功底的活。ddr控制器的时序复杂,尤其在做多端口访问仲裁的时候,带宽利用率和延迟很难兼顾。我之前一个项目是ad7606高速采集+dsp搬移,fpga要把adc采到的数据不停写入ddr,同时还要周期性读出做算法处理。遇到的问题就是网上常说的“ddr的读有效信号一直为低”,查了很久发现是写通道的优先级设置过高,控制器持续响应写请求,读请求被饿死了。调整仲裁策略后,读写带宽的比例恢复正常,问题立刻消失。从这里得到的经验是:fpga控制ddr遇到读信号异常时,首先查仲裁和优先级配置,而不是怀疑硬件连接或控制器IP的问题。
4.3 从零开始搭建一个fpga项目的标准流程
很多刚接触fpga的同学,第一件事就是打开开发环境、找一个例程、改一改就跑。这个做法不是不行,但对真正要落地的项目来说,还是需要一个更稳妥的搭建流程。我自己总结的标准流程是五步走:需求拆解、时钟规划、接口定义、功能划分、验证计划。
需求拆解是把自然语言的需求翻译成fpga能实现的模块和信号,比如biss-c编码器读取,要拆成时钟产生、数据接收、crc校验、位置寄存器、错误标志这几个部分。时钟规划是提前想好每个模块用哪个时钟域、跨时钟域的接口怎么处理。接口定义是最重要的一步,所有模块之间的信号名、位宽、有效电平、时序关系都要在动笔写代码之前定义清楚,这能省掉后面大量的联调时间。功能划分是决定哪些逻辑放PL侧、哪些逻辑放外部芯片或软件侧。验证计划则是提前想好每个模块怎么测试,防止最后全部堆到上板阶段才排查。
这套流程看起来有点繁琐,但真正执行过几次之后就会发现,它是所有后面省时间的根源。尤其是换芯片、换平台的时候,如果原来的设计文档和接口定义足够清晰,迁移的工作量会大幅度降低。
4.4 fpga常见名词与基础概念扫盲
如果刚入门fpga,看资料时会被一堆名词砸晕。这里挑几个最常见的做个扫盲,方便大家快速进入状态。
LUT是查找表,fpga里最基础的可编程逻辑单元,本质上是一个小型的真值表,可以实现任意组合逻辑。FF是触发器,用来寄存数据,是seq逻辑的基础。BRAM是块RAM,fpga内部嵌入的存储块,可以用来做缓存、FIFO、寄存器堆。DSP slice是数字信号处理单元,里面有乘法器和加法器,做滤波、fft这种运算时比纯LUT实现高效得多。PLL和MMCM都是时钟管理单元,用来产生不同的时钟频率,Xilinx的7系列是MMCM,很多国产芯片则普遍集成PLL。
还有一个容易被忽略的概念是Slices。LUT和FF不是独立分布的,而是组成一个逻辑块,这个块在Xilinx里叫Slice,在Lattice和国产芯片里叫PFU之类。一部芯片的逻辑资源是用“有多少个Slice”来描述的,而不是单个LUT数量。看芯片选型表时,要注意区分厂商给出的资源定义方式,比如Xilinx的Artix-7 XC7A35T,逻辑单元大约是33280个,但如果你看的是Slice数量,应该是5200个左右。两边的数值差了好几倍,不搞清楚定义会产生严重误判。
5. 常见问题与调试技巧实录
5.1 时序约束不生效的检查步骤
时序约束不生效,是fpga开发里最容易让人抓狂的问题之一。代码逻辑完全正确,综合也过了,但上板后就是偶发出错,最后定位到约束根本没有生效。我的排查步骤是这样:
先去编译报告里搜索有没有关于约束的warning,尤其是“unconstrained path”这类提示。如果约束文件根本就没被读进去,综合器通常会提示路径未约束。其次检查约束文件的优先级,不同厂商的编译环境里,多个约束文件同时存在时,后加载的可能会覆盖先加载的,尤其是对同一个时钟的约束,如果出现多个定义,等效于没约束。然后看时钟命名是否正确,create_clock指定的时钟名必须和综合之后netlist里的时钟名一致,如果中间改了名字,比如加了一级BUFG,时钟名可能就变了。最后确认约束文件的作用域,比如testbench里的时钟约束和综合后的约束要分别管理,千万不要把simulation的约束混进综合文件里。
5.2 编译资源爆炸但逻辑并不复杂的原因分析
有一种情况很费解:明明代码逻辑看起来不复杂,但编译出来的资源占用却大得离谱,甚至直接超出芯片容量。我遇到过的典型原因有三类。
第一类是case语句没有default分支,综合器会认为所有可能的输入都必须有输出,从而生成很多额外的优先级编码逻辑。第二类是for循环的展开,大部分fpga综合工具会把for循环完全展开,如果循环次数写大了,资源占用会指数级增长。第三类是大型MUX的使用,比如用一个很大的case来选数,综合器会生成一棵巨大的选择树,非常耗费LUT。排查方法很简单:在综合报告里看哪类资源占用量最大,对照代码找对应的逻辑结构,基本一眼就能定位。
5.3 上板偶发错误的上电时序排查思路
fpga上电偶发错误,是比固定错误更难受的问题。固定错误可以通过看波形、查代码快速定位,偶发错误则往往是上电时序相关的,极难复现。
我的排查顺序是先检查电源的上电时序,用示波器同时抓fpga的多个电源轨和复位信号,确认它们的时序关系满足芯片要求。很多国产fpga对内核电压、io电压、辅助电压之间的上电顺序有严格要求,如果先给io供电、再给内核供电,可能导致启动异常。其次是检查配置引脚的状态,比如模式选择引脚有没有被外部电路误拉到错误电平。最后是检查外部复位信号的长度,fpga的配置需要一定的时间,如果复位信号在配置完成前就被释放,芯片可能进入不确定状态。我碰到过一个案例:外部复位引脚接到了RC电路上,时间常数设计得太短,比fpga启动时间还短,导致芯片上电后刚复位完又意外复位了一次,数据链路经常掉线。加大RC时间常数之后就一切正常了。
5.4 fpga远程升级的风险控制与spi接口实现
fpga远程升级,是一个让很多人既爱又恨的话题。爱的是不用到现场就能更新逻辑,恨的是升级出错有可能让设备变砖。spi接口的远程升级方案是目前比较主流的方式,核心思路是应用区收到新固件后,先把数据写到备用区,校验通过后再切换启动指针。但这里面的坑依然不少。
最大的风险在于掉电。如果升级过程中截图到一半突然掉电,flash里的数据不完整,设备就无法启动。应对方案是使用双镜像启动,也就是flash里保留两个镜像,一个golden镜像、一个update镜像,update升级失败后还能从golden恢复。第二个风险是flash型号兼容性,不同品牌、不同容量甚至不同批次的spi flash,擦除命令和写命令可能有细微差别,fpga读配置时一般都能兼容,但你自己写升级逻辑时,一定要确认操作命令的正确性。第三个风险是校验策略。我目前的做法是收完一个分块就回读校验一次,全部写完后再做整体回读比对,双重校验通过后才修改启动指针。
5.5 从biss-c编码器到传感器融合:按场景选择合适的fpga
biss-c编码器在工业伺服、机器人关节里用得越来越普遍,它本质上是一种高速双向串行通信,fpga因为能提供确定性极好的时序,非常适合处理这种协议。biss-c要求主站发出时钟信息后,从站同步返回位置数据,整个过程对时钟连续性和响应延迟非常敏感,用fpga实现是天然的优势。
处理biss-c这类高实时性传感器协议,对fpga的资源要求并不高,但对接下来的信号调理和数据处理有讲究。如果只是读取位置数据然后通过spi或者uart转发出去,一颗小容量的国产fpga就绰绰有余。但如果要做高精度的运动控制,需要把位置数据融合编码器信息、电流信息一起做伺服环路,那就要考虑fpga的dsp资源和延迟特性了。我做过一个机器人关节方案,biss-c读取用fpga完成,位置环放到了外部dsp上,fpga只负责数据搬运和时序控制,整体效果稳定可靠,而且芯片选型范围很宽,供货从来不是问题。
6. 项目管理层面的几点个人体会
聊了这么多技术细节,最后再分享几个项目管理层面的体会。这些内容看似和技术无关,但说实话,在fpga短缺的背景下,它们对项目成败的影响比任何一个具体技术决策都大。
第一,fpga的备货要提前,而且要有冗余。不要等到原理图冻结了、PCB画完了才开始下单买芯片。在方案评估阶段就把目标芯片锁定,先买几片样品做验证板,同时小批量备货。验证版验证的是技术可行性,备货防的是交期波动,两条腿走路的成本不高,但保险效果极好。
第二,和供应商共享未来的需求计划,而不是“用到再买”。很多代理商的分配额度是根据需求预测来的,如果你能提前给出未来两个季度的用量预估,会更容易拿到优先分配权。这个做法在紧缺型号上尤其有效,我见过不少项目就是因为提前提交了预测而被优先供货。
第三,建立“可迁移开发”的团队习惯。代码风格、模块划分、注释规范、命名约定,都尽量做到平台无关。这样即便真的需要临时切换芯片,整个团队也能有条不紊地推进,而不是一个人对着代码发愁。我们把常用的接口模块都做成了兼容多个平台的标准库,换芯片时只需要改底层的原语和约束文件,上层逻辑几乎不动。
我个人的经验是,fpga短缺不会是一个短期的现象,它大概率会变成未来几年电子行业的一种新常态。与其每次遇到供货问题都焦头烂额地救火,不如从项目一开始就把供应链风险当作一个普通的技术约束来对待。把方案做成“无论哪颗芯片都能上”,把团队练成“换平台也不慌”,这个适应过程虽然需要投入一些精力,但对项目、对团队长期来说都是非常划算的投资。