做ARM和FPGA联合硬件平台,通信这块的原理图设计是很多人绕不过去的一道坎。我接触过不少项目,从工业控制到图像采集预处理,ARM负责协议解析、界面交互、系统调度,FPGA负责实时性高的信号采集、并行计算和高速接口扩展,两者一配合,整个系统的能力边界一下就拉开了。但恰恰是这两颗芯片之间的互联,原理图上看着就几根线,实际画起来和调起来到处是坑。这篇就专门讲ARM和FPGA之间通信的硬件设计,把原理图层面需要敲定的方案、电平匹配、信号完整性、电源时钟、调试预留这些事一次说清楚。
1. 从需求到原理图:通信方案怎么选
1.1 先问自己三个问题:速率、实时性、距离
画原理图之前,别急着连线。我在项目里一般先问三个问题:这条链路上要传什么数据?数据量多大?对延迟和实时性有多敏感?这三个问题直接决定你选哪种通信接口。
举个实际例子,如果你的ARM只需要给FPGA下发一些配置文件、寄存器参数、启停命令,数据量可能就是几十个字节,一分钟传一次,那SPI或者UART完全够用,而且接口简单可靠。但如果你做的是高速数据采集,比如ADC采样的数据通过FPGA做滤波,然后源源不断送给ARM做显示或者存储,那数据率可能是每秒几十兆字节甚至更高,SPI和UART就彻底不够看了,这时候要考虑并口总线、DMA搬运,甚至走RGMII或者PCIe级别的通道。
实时性要求也很关键。有些控制类应用,要求ARM下发一个命令之后,FPGA在微秒级以内做出响应。这种情况下,SPI和UART的轮询方式很可能满足不了,因为协议本身有帧间隔、有从机响应时间。这时候可以考虑并行总线,ARM直接把FPGA的寄存器映射到内存地址空间,对着地址写数据就等于给FPGA发命令,硬件上瞬间完成,不需要软件来回握手。
距离因素在原理图阶段容易被忽略。两颗芯片如果就放在同一块PCB上,走线距离三五厘米,几乎什么接口都能用。但如果ARM板是独立的核心板,FPGA在底板上,中间通过板对板连接器插接,那信号质量就要重新评估,高速并行总线在这个场景下很容易出时序问题,反而是串行接口更稳妥。
1.2 几种主流通信方式的选型对照
为了让你画原理图的时候心里有数,我把ARM和FPGA之间最常见的几种通信方式整理成了一个对照表。这个表格我做的项目里反复用,每次选型直接对照着看,基本不会跑偏。
| 通信方式 | 典型速率 | 引脚占用 | 硬件复杂度 | 适用场景 |
|---|---|---|---|---|
| UART | 最高几Mbps | 2根(TX/RX) | 极低 | 调试、低速命令交互 |
| SPI | 10Mbps~50Mbps | 4根(SCLK/MOSI/MISO/CS) | 低 | 配置下发、中等速率数据交换 |
| I2C | 100Kbps~3.4Mbps | 2根(SCL/SDA) | 低 | 寄存器读写、低速管理通道 |
| 并行总线(EMIF/FMC) | 100MB/s以上 | 20~40根 | 高 | 高速批量数据,内存映射控制 |
| RGMII(千兆以太网) | 1000Mbps | 12根 | 中高 | 大数据量、远距离、协议标准化 |
| PCIe | 数Gbps | 差分对若干 | 很高 | 极高速率,需专用IP核 |
选型的时候有个经验:能用串行解决的事,尽量不要上并行。串行接口引脚少,PCB布线压力小,调试逻辑简单,出问题的概率低。并行接口虽然速率上限高,但时序约束、等长布线、PCB层数要求都会跟着上来,对新手尤其不友好。
2. 原理图设计前的引脚规划与电平决策
2.1 引脚规划表比原理图本身更重要
很多人在画原理图的时候,直接打开EDA工具从元件库拖出ARM和FPGA,然后开始拉线。这是最容易翻车的做法。正确顺序是先做一张引脚规划表,把ARM端哪些引脚接到FPGA哪些引脚,一条一条列清楚,确认没有冲突,再落到原理图里。
引脚规划表要包含这些列:信号名(比如SPI1_CLK、UART2_TX)、ARM端引脚号、ARM端复用功能、FPGA端引脚号、FPGA端Bank和电平标准、信号方向(ARM到FPGA还是FPGA到ARM)、备注说明。这张表做完,你会发现自己能提前发现很多问题,比如ARM只有一个硬件SPI控制器但是你需要两路SPI,或者FPGA分配引脚的时候发现某个Bank的电平标准和ARM IO不一致,这些问题在表格阶段改起来成本极低,到了原理图完成甚至PCB打样回来才发现,代价就大了。
我做引脚规划的时候还有一个习惯:把FPGA所有空闲引脚也列出来,标注上电平标准和Bank编号。这样后续如果要扩展通信接口,不用重新翻数据手册,直接看表格就知道哪些引脚还能用。
2.2 电平标准:ARM的IO电压和FPGA的Bank电压不一定一致
这是原理图阶段最容易埋雷的地方。ARM芯片的IO电压常见的是3.3V和1.8V,比如不少Cortex-A系列处理器,Bank电压是1.8V;而FPGA的IO Bank电压可以灵活配置,同一颗FPGA上不同的Bank甚至可以用不同的电压。但在很多开发板上,FPGA的Bank为了方便接外设,默认设成3.3V,这就是冲突来源。
画原理图之前,必须搞清楚两件事:ARM通信引脚所在的电源域到底是几伏?FPGA对应BANK的VCCO接了几伏?这两个电压如果不一致,通信线上的信号电平就对不上。比如说ARM这边输出的是1.8V高电平,FPGA那边的输入引脚位于3.3V的Bank,那么FPGA识别1.8V高电平的阈值很可能不够,表现为通信偶尔正常、经常出错。反过来,如果3.3V信号直接灌进1.8V的引脚,长期工作有损坏IO的风险。
我见过最离谱的一次,板子上ARM是1.8V IO,FPGA是3.3V Bank,中间没做任何转换,直接连上了。现象就是FPGA能收到数据但偶尔丢字节,示波器一看波形,高电平幅度只有1.8V,上升沿还慢吞吞的。加了电平转换之后问题立刻消失。
2.3 电源域分配也是通信设计的一部分
很多人觉得电源设计是电源工程师的事,跟通信没关系。但实际上ARM和FPGA的IO电平匹配,本质就是电源域规划的问题。你在原理图阶段要为每个电压域想好:ARM核心电压、ARM IO电压、FPGA核心电压、FPGA Bank电压、DDR电压(如果有)、外设接口电压,这些电源从哪来,用什么芯片产生,上电时序怎么安排。
尤其是在FPGA这边,如果通信引脚分散在不同的Bank,那这些Bank的VCCO必须统一到你设计的目标电平上,否则FPGA内部逻辑虽然能跑,但IO电平就是不对。一个常用的做法是:让FPGA所有跟ARM通信的引脚集中在同一个Bank或者相邻Bank,这样电平标准一致,电源设计也简单,PCB布线也好处理。
3. 常用接口的原理图连线细节拆解
3.1 SPI接口:小数据量场景的万金油
SPI是ARM和FPGA通信里用得最多的接口之一,因为它简单、灵活、速率也不差。原理图里SPI就四根线:SCLK时钟线、MOSI主出从入、MISO主入从出、CS片选。ARM做主机,FPGA做从机,这是最常见的组合。连接关系很直接:ARM的SCLK接FPGA的SCLK,ARM的MOSI接FPGA的MOSI(FPGA视角里这是SDI),ARM的MISO接FPGA的MISO(FPGA视角里这是SDO),ARM的CS接FPGA的CS。
连线看似简单,但有几个地方要注意。第一,SCLK信号线上建议靠近源端串一个22欧姆到33欧姆的电阻,这能有效抑制振铃和过冲。SPI时钟速率做到几十兆的时候,走线稍微长一点,信号反射就很明显。第二,CS片选信号要加上拉电阻到高电平,防止ARM还没初始化的时候FPGA误以为被选中,进入错误的通信状态。上拉电阻阻值选10K欧姆左右就可以了。
还有一个细节是SPI的极性和相位,也就是CPOL和CPHA。这两个参数在ARM端和FPGA端必须配置一致。FPGA端通常是用Verilog或VHDL实现一个SPI从机逻辑,极性和相位完全由代码决定,所以原理图阶段你要在文档里明确标注默认使用哪种模式,方便后续写FPGA代码的人对照。我的习惯是统一用Mode 0,也就是CPOL=0、CPHA=0,空闲时时钟为低电平,第一个边沿采样数据。
SPI通信距离一般在10厘米以内比较可靠,超过这个长度速率就要降下来。如果你发现SPI在调试的时候时好时坏,先别怀疑代码,用示波器看看SCLK线上是不是有毛刺,CS信号是不是有抖动,很多时候都是硬件上的小问题。
3.2 UART接口:调试利器,但别接反线
UART只需要两根线,TX和RX,外加共地,是ARM和FPGA通信的最低成本方案。原理图上需要注意的只有一点:交叉连接。ARM的TX接到FPGA的RX,ARM的RX接到FPGA的TX。这个接线规则我强调过很多次,但依然经常有人在原理图评审的时候接反。
UART还有一个容易被忽视的问题:共地。两个芯片的GND必须可靠连接,如果ARM板和FPGA板各自供电但地没连在一起,UART信号的电平参考点都不一样,通信绝对不正常。在原理图设计时就要考虑到这一点,确保板级设计里ARM和FPGA的地平面是连通的。
是否需要接流控引脚RTS和CTS?我的建议是:如果通信速率不高、数据量不大,不接,用软件流控或者干脆不用流控。接硬件流控会多两根线,而且ARM和FPGA两边的驱动逻辑都要跟着复杂起来,收益很低。
UART在调试阶段还有一个隐藏价值:ARM和FPGA各留一个串口通过USB转串口芯片接到调试电脑,你会发现排查问题的时候效率高出好几倍。FPGA的串口可以用来打印内部状态机的运行状态,ARM的串口可以用来打印驱动层的通信日志,两边一对照,问题基本能定位到具体是哪个环节。
3.3 并行总线(EMIF/FMC):高速批量数据的主力方案
当数据吞吐量上来之后,比如图像数据、高速ADC采样数据,SPI和UART就不够用了。这个场景下我优先推荐用ARM的并行总线接口接FPGA,ARM这边的EMIF接口或者FMC接口,直接映射到FPGA的地址空间。
原理图的连接方式:数据线D[15:0]接FPGA的对应IO,地址线A[24:0]接FPGA的地址引脚,还有读写控制信号、片选信号、时钟信号。连接关系比较规整,但真正的难点在于时序设计。
并行总线的关键问题是ARM对外设的读写时序是否满足FPGA的响应要求。ARM这边通常有可配置的读写时序参数,比如建立时间、保持时间、片选到读写的延迟等。FPGA这边需要根据ARM的时序要求来设计内部逻辑,简单来说就是做一个“伪静态存储器”接口,ARM对它就像读写一个SRAM芯片一样,给地址、给读写信号、数据就出来了。
原理图设计阶段需要重点标注的:数据线要成组走线,尽量保持等长,长度差控制在几百密尔以内,这在PCB布局布线的时候要特别注意。如果ARM的并行总线频率比较高,比如50MHz以上,那数据线、地址线、控制线之间都要做等长约束,否则时序很容易跑不过。
FPGA端引脚分配的时候,最好把数据线放在同一个Bank,地址线放在另一个Bank,这样IO标准统一,时序也更稳定。我在一个项目里因为FPGA引脚分配太散,跨了好几个Bank,结果调试的时候发现每个Bank的电平标准要分别设置,还出现了信号间串扰,走了不少弯路。
3.4 RGMII千兆以太网接口:标准化高速通道
RGMII是千兆以太网的常用接口,ARM端如果自带MAC控制器,FPGA端实现了MAC功能,两者之间就能用RGMII直接连接。原理图连接12根信号线:TXD[3:0]发送数据、RXD[3:0]接收数据、TX_CTL发送控制、RX_CTL接收控制、TXC发送时钟、RXC接收时钟。
RGMII的核心特点是DDR模式,数据在时钟的上升沿和下降沿都采样。这个特点对信号质量要求比较高,原理图设计的时候要确保时钟线和数据线的长度差尽量小,时钟信号质量要好,不能有大的抖动。
RGMII的时钟频率是125MHz(千兆速率),此时PCB布线就要认真对待了,普通的随便拉线方式肯定不行。需要考虑阻抗控制,单端信号按50欧姆设计,走线要短而直,避免过孔。如果ARM和FPGA距离比较远,甚至要考虑在中间加电平转换缓冲芯片。
我个人的经验是,如果项目没有以太网协议处理的需求,尽量不要用RGMII做ARM和FPGA的板级通信,直接用并行总线或者PCIe更简单。RGMII的优势是标准化程度高,后续如果要通过网络传输数据,可以复用这套链路。但板级场景下,协议开销和实现复杂度都不低。
4. 电平匹配和信号完整性:最容易翻车的两个环节
4.1 电平域组合与转换方案
电平匹配这个问题,我在前面提过,但值得单独拿出来重点说,因为这是ARM和FPGA通信原理图设计里最常见的坑。我总结出几种典型的电平组合和对应的处理方式。
第一种,两边都是3.3V,这是最理想的情况,直接连就行,不需要任何转换。第二种,两边都是1.8V,同样直接连。第三种,ARM是1.8V,FPGA是3.3V Bank,这种情况需要电平转换。第四种,ARM是3.3V,FPGA是1.8V Bank,同样需要转换。
电平转换方案有三种。第一种是专用电平转换芯片,比如TXS0108E、SN74LVC8T245,这类芯片是自动方向感知的,适合多路信号转换,方向控制简单,稳定性好。第二种是分立MOS管方案,用N沟道MOS管做双向电平转换,成本低,但只适合低速信号,做UART、I2C这种还行,高速信号别用。第三种是电阻分压,只能用在信号方向固定的低速场合,而且驱动能力有限,我不推荐。
我自己的项目习惯是:如果只是两三根低速信号,用分立MOS管方案,成本几毛钱;如果是SPI四根线或者更高频率,直接用SN74LVC245这种总线转换芯片,稳妥。
4.2 串阻与端接:小电阻解决大问题
ARM和FPGA之间的信号线上,特别是在高速或者走线较长的场景,建议在源端串一个小电阻,典型值22欧姆到47欧姆。原理图设计的时候就要把这个电阻预留出来,不要等PCB做完了再想到要加。
这个串阻起什么作用?主要作用是抑制信号反射和过冲。信号从源端出发,沿着走线传到接收端,如果阻抗不匹配,信号会在两端来回反射,导致波形过冲、振铃、台阶。源端串阻的作用是降低源端的输出阻抗,让信号源和传输线之间的阻抗更匹配一些,从而减少反射。
阻值怎么选?我的经验是先用22欧姆起步,如果示波器看到过冲明显,再换33欧姆甚至47欧姆,找到波形最干净的阻值。注意串阻要放在靠近源端的位置,比如放在ARM输出引脚旁边,而不是靠近FPGA的那一端。
对于差分信号,比如LVDS,需要靠近接收端接100欧姆的差分匹配电阻,这个在原理图设计的时候就要画好。不过ARM和FPGA之间一般很少直接用LVDS连接,除非是做高速ADC数据采集的场景。
4.3 布线要点:等长、地平面、阻抗控制
原理图阶段虽然不涉及实际布线,但你在画原理图的时候就要为PCB布线预留好条件。我的做法是在原理图里用网络标签明确标注出哪些网络是高速信号,哪些需要等长约束,这样后面的PCB设计人员(哪怕是你自己)也能清楚知道哪些信号要重点照顾。
ARM和FPGA的高速并行信号线,比如并口数据线和地址线,需要做等长约束,误差控制在正负几十密尔的水平,这个在PCB设计工具里通过相对延迟约束来实现。时钟线记得要和对应的数据线做等长,否则时钟到达时刻和数据到达时刻对不上,时序就跑不过。
地平面的完整性也很关键。信号线正下方如果有完整的地平面作为回流路径,信号质量会非常好;但如果地平面被切开了,信号回流需要绕路,环路面积变大,辐射和串扰都会增加。在原理图设计阶段,你要规划好ARM和FPGA之间的地连接方式,确保下层有完整的地平面。
还有一个容易被忽略的点:尽量减少信号线跨层换层。换一次层,就多一个过孔,过孔的寄生电容和电感会破坏信号完整性。如果必须换层,记得在过孔旁边加一个地过孔,提供就近的回流路径。
5. 电源、时钟、复位:通信系统的隐形地基
5.1 电源树规划与上电时序
ARM和FPGA的通信要稳定,电源必须干净。我在原理图阶段会画一张完整的电源树,从输入电源开始,标注每一路输出电压、最大电流、用途、纹波要求。ARM核心通常需要一路低电压大电流的电源,比如1.1V/1.2V,可以用DCDC加LDO的组合;ARM的IO电源单独一路;FPGA核心电压、FPGA Bank电压、FPGA Aux电压(如果有)各一路。
FPGA对上电时序有要求,不同的FPGA厂商要求不太一样,但大方向是一致的:先给核心电压上电,然后再给IO电压上电,顺序反了可能导致IO输出不确定状态,甚至影响器件寿命。如果ARM和FPGA之间有直接连接的信号线,还要考虑上电瞬间两边IO的状态。比如ARM先上电输出高电平,FPGA核心还没起来,那ARM的高电平就会通过信号线倒灌到FPGA的IO引脚,长期这样可能损坏FPGA。
解决倒灌问题的办法有几种:在信号线上串联一个小电阻,限制倒灌电流;用支持断电隔离的电平转换芯片;或者用IO隔离芯片,在FPGA未上电时把信号线断开。原理图阶段就要提前做这个设计决策,不能等出了问题再补救。
5.2 时钟设计:同源还是独立
ARM和FPGA如果通信速率比较高,双方使用独立的时钟源也通常没有问题,因为通信协议本身有同步机制。但有一种情况要注意:如果ARM和FPGA做的是并行总线通信,而且总线频率很高,最好让FPGA的时钟和ARM的时钟有一定关系,或者是FPGA的时钟由ARM提供,这样时序分析更容易收敛。
时钟信号在原理图上要走专用通道,远离数据线和电源线。如果时钟频率超过25MHz,建议在源端串22欧姆或33欧姆电阻,抑制反射。如果ARM输出时钟给FPGA,要确认ARM的时钟输出引脚驱动能力够不够,FPGA的输入时钟引脚是否需要额外的端接。
我在一个项目里就遇到过时钟信号质量差的问题:ARM输出50MHz时钟给FPGA,FPGA老是偶发锁不住数据。用示波器看,时钟上升沿有明显的台阶,这是驱动能力不够的典型表现。后来在ARM输出端加了一级时钟缓冲器,问题就解决了。所以原理图设计时,如果担心驱动能力,预留一个时钟缓冲器的位置是很明智的做法。
5.3 复位信号:别让复位干扰通信
ARM和FPGA各自都需要复位信号,但如果你把两个芯片的复位连到一起,可能会互相干扰。ARM复位的时候IO状态不定,FPGA正好复位完成开始运行,如果ARM的IO恰好输出一个错误的信号,FPGA就接收到错误数据了。
我的原则是ARM和FPGA的复位电路独立设计,每个芯片用自己的RC复位电路或者复位芯片。如果要系统级联复位,就是用ARM的GPIO去控制FPGA的复位,这样ARM完全启动之后再手动触发FPGA复位,时序可控。
FPGA的复位信号建议加一个去抖电路,FPGA内部可以用简单的RC滤波或者状态机实现。原理图上要确保复位信号到FPGA引脚之间有上拉电阻,避免复位引脚悬空,悬空的复位引脚在电磁干扰下会误触发复位,导致FPGA配置丢失或者逻辑跑飞。
6. 调试接口与测试点:原理图阶段就要布局好
6.1 JTAG/SWD调试链路
ARM和FPGA都需要调试接口,原理图上要把调试连接器位置设计好。ARM用SWD的话,最少只要SWDIO、SWCLK、复位、地四根线,我用2.54mm的排针引出,方便调试器夹子夹上。FPGA用JTAG,需要TDI、TDO、TMS、TCK、TRST(可选)和地,通常用10针或者14针的连接器。
调试链路的布线不需要太讲究,但调试连接器的位置要放在板边,方便插拔和连接调试器。我在原理图设计时会标注调试连接器附近的净空区域,提醒PCB设计时不要把其他元件放太近,否则调试夹子不好夹。
还有一点值得注意:如果ARM和FPGA离得近,可以考虑把两者的JTAG信号串联成一个菊花链,用一个连接器同时调试两颗芯片。但这样调试的时候会互相牵制,我个人不太推荐,除非连接器位置实在紧张。
6.2 调试串口与指示灯
我做的每一块ARM+FPGA板卡上,至少会预留两路调试串口:一路给ARM打印日志用,一路给FPGA打印内部状态用。这两路串口通过板载USB转串口芯片接到USB连接器,插上调试电脑就能看到两边的运行日志。
指示灯这张“穷人示波器”也不能少。ARM预留两个GPIO接到LED,FPGA预留两个GPIO接到LED,调试的时候可以写代码翻转这些GPIO,用逻辑分析仪或者简单测一下电平就能判断系统是否正常运行。原理图上LED限流电阻按1K欧姆取值比较合适,3.3V供电下LED电流大约2mA到3mA,亮度足够又不会过流。
6.3 测试点、拨码与跳线
测试点这件事,原理图设计时一定要做,否则调试的时候只能拿示波器探头去找芯片引脚捅,非常痛苦。关键信号每个都加一个测试点:ARM和FPGA之间的时钟线、片选信号、复位信号、关键数据线、电源输出。测试点直接做成过孔或者小焊盘,标上网络名,调试时探头一放就能快速定位波形的对错。
拨码开关和跳线也要预留:ARM的启动模式选择、FPGA配置模式选择、通信接口的地址配置、甚至电平转换方案的开关选择,这些用拨码开关实现,调试时不用飞线,改配置就是拨一下的事。我曾经做过一块板子,板上的FPGA配置模式没有预留配置选择开关,每次改配置模式都要拿电烙铁飞线,简直是自己给自己找麻烦。
7. 实战中遇到的坑与排查思路
7.1 常见问题速查表
ARM和FPGA通信出问题,表现形式千奇百怪,但根子上基本都是硬件设计或者配置的少数几种问题。我把这几年遇到的典型问题整理成了表格,方便你排查时对照。
| 问题现象 | 可能原因 | 排查方向 |
|---|---|---|
| 通信完全不通 | 电平不匹配、接线错误、没共地 | 万用表测信号线通断,示波器看波形幅度 |
| 通信时好时坏 | 电平临界、信号质量差 | 示波器看信号波形,检查串阻和走线 |
| 数据错位/丢字节 | 时钟极性和相位不一致、时序不满足 | 检查SPI模式配置,核对读写时序 |
| 偶尔死机/重启 | 复位干扰、电源毛刺 | 检查复位信号,示波器测电源纹波 |
| FPGA配置失败 | 配置引脚被占用、电源时序不对 | 检查配置引脚连接,核对上电时序 |
| 高速数据偶发错误 | 等长不满足、地平面不完整 | 检查PCB布线,用示波器看数据眼图 |
7.2 排查方法实录
第一个建议:先看波形再看软件。很多工程师看到通信不通,第一反应是去查软件代码,在逻辑分析仪上抓包,搞了半天发现软件没问题。正确的做法是先拿示波器量信号线上有没有正常的波形,幅度对不对,极性对不对,时序大概对得上不对得上。硬件链路是通的,问题多半在软件配置;硬件波形都不对,软件再调也没用。
第二个建议:用回环测试来分段定位。调试ARM和FPGA的UART,先把ARM的TX短接到自己的RX,验证ARM串口本身能不能收发;再把FPGA的TX和RX短接,验证FPGA这边能不能收发。两边都通了,再对接联调,这时候问题范围就缩小到了连线或者电平匹配上。SPI也是同样的思路,先把MOSI和MISO短接,用ARM自发自收,验证ARM端正常。
第三个建议:示波器触发条件用好了,定位问题效率翻倍。抓写信号的时候,用片选信号作为触发源,触发沿设成下降沿,因为片选通常是低有效。这样示波器每次都在片选拉低的时刻开始抓波形,你就能清晰看到这一次操作里SCLK、MOSI、MISO的完整时序关系,慢慢对比数据手册上的时序图,问题总能看出来的。
第四个建议:电源质量永远是最优先检查的。ARM和FPGA通信不稳,先看电源纹波,尤其是两个芯片的IO电源和核心电源。示波器用交流耦合、20MHz带宽限制,如果纹波超过50mV,通信链路的信号质量再讨论意义也不大,先把电源搞干净再继续查。
7.3 几条独家避坑经验
串口调试助手收到的数据全是0x00或者0xFF,先看通信线的上下拉配置。比如SPI的MISO线,如果FPGA这边驱动能力弱或者处于高阻状态,线上又没有任何上下拉,ARM读回来就是不确定的值,很多时候表现就像串口收0xFF一样。解决方法是给关键信号线加上拉或者下拉电阻,具体看信号协议,SPI的MISO通常上拉到高电平,UART的RX线通常上拉到高电平。
并行总线调试时发现读写数据有时候对有时候错,但示波器看波形好像都正常,这种情况要怀疑ARM端的总线等待周期配置。并行总线的访问需要满足FPGA侧的最小时钟周期数,ARM如果配置的等待周期太少,FPGA还没来得及把数据放到数据总线上,ARM就已经采样了,读到的自然是垃圾数据。重新计算一下ARM的读写时序参数,把建立时间和保持时间留足余量,基本就能解决。
还有一个容易被忽略的:FPGA内部逻辑使用了未初始化的状态寄存器。ARM上电后给FPGA下发配置之前,FPGA内部的状态机可能已经跑飞了。最好的做法是ARM配置完成之后,给FPGA发送一个同步信号或者复位脉冲,让FPGA进入已知状态。这个同步机制在原理图和接口协议文档里就要定义清楚,否则后面联合调试的时候两边对不上。
做了这么多ARM和FPGA联合调试的项目,我现在最大的体会是:原理图阶段多花一天时间做引脚规划、电平核对、调试接口预留,后面能省下好几个星期的时间。很多通信问题看起来是软件Bug,追根溯源都是硬件设计时的小疏忽——电平不匹配、时钟质量差、调试手段缺失。要是你在原理图阶段就对这些问题了然于胸,把该留的电阻位置留好,该加的测试点加上,该做的电平转换做对,那ARM和FPGA之间的通信就会踏实很多,调试的时候也会顺利很多。