紫光同创PGL50H这颗芯片,在国产FPGA圈子里其实已经积累了一批忠实用户。不能说它性能有多炸裂,但在“成本可控、供货稳定、国产化替代”这个区间,它确实是很多人做通信、数据采集类项目时的第一选择。我手上这块盘古50KN网口开发板,就是围绕PGL50H做的一块带千兆网口的板子,拿来跑高速通信和数据处理刚刚好。这篇不是产品软文,也不是开发板说明书,而是我基于这块板子从零开始做网口通信的完整实战记录:硬件资源怎么用、PDS工具链怎么搭、RGMII/UDP协议栈怎么实现、带宽怎么测,以及在调试过程中踩过的那些坑。想入门国产FPGA,或者正纠结怎么把网口功能跑起来的,可以参考这份记录。
先说明一下,这套方案用到的关键点包括:PGL50H的片上资源分配、盘古50KN网口板的板级搭建、基于RGMII接口的千兆PHY通信、UDP协议栈的简化实现,以及跨时钟域FIFO的数据缓存策略。下面按我实际操作的顺序来写,有些内容看起来基础,但恰恰是这些基础决定了后面能不能稳定跑起来。
1. 为什么是PGL50H?盘古50KN网口板的硬件底子
1.1 PGL50H芯片的定位与资源摸底
PGL50H属于紫光同创的Logos系列,定位是中等规模、低功耗、高性价比的FPGA。官方数据手册里,它的资源规模大致在5万级逻辑单元这个档位,内部集成了不少DSP单元、块RAM、锁相环(PLL)以及高速收发器等资源。我没法把每个数字都精确背出来,毕竟不同批次手册上的参数会有微调,但有一点可以确定:在2.5G/千兆网口、图像处理、电机控制、工业总线协议这类中低端应用场景里,它的资源量级是完全够用的。
从实际开发的体验来说,PGL50H最让我满意的是IO资源相对充裕。做网口板的时候,除了要接RGMII信号,往往还需要接DDR3地址线、串口、LED、按键、扩展IO等,IO不够用就得拿pin脚复用方案硬凑,非常难受。PGL50H在这块板子上预留的IO数量比较宽裕,我在做数据采集扩展时,还额外接了一路并行ADC和一路SPI接口的传感器,资源占用上没有出现捉襟见肘的情况。
还有个细节值得提——PGL50H内部集成了DDR存储控制器相关的硬核辅助资源。虽然不少教程会让你用软核方式实现DDR控制,但在这块盘古50KN网口板上,官方已经提供了DDR3的参考设计,跑起来比自己调软核省心得多。做高速网口数据处理,如果没有DDR3做数据缓存,遇到突发流量基本必死,所以板载DDR3这个设计是非常关键的加分项。
1.2 板级资源:网口板到底“板”在哪里
盘古50KN网口板,顾名思义就是围绕PGL50H做的一块专门验证网络通信和高速数据处理的开发板。板上的核心外设可以分成几类:
- 千兆以太网PHY芯片,常见型号是瑞昱的RTL8211系列或裕太微的YT8531系列,具体到板子上需要查看原理图确认;
- DDR3内存颗粒或内存条接口,用于大容量数据缓存;
- UART串口,用来做调试日志输出和简单命令交互;
- 时钟系统,一般包含一颗25MHz的无源晶振或可编程时钟芯片,供PHY和FPGA内部PLL使用;
- 按键、LED、拨码开关这些交互元件,方便做状态指示和功能配置;
- 扩展排针或FPC连接器,引出大量用户IO、差分对、电源和地。
从电路设计角度来看,这块板子的网口部分,FPGA和PHY之间走的是RGMII接口,MAC逻辑在FPGA内部实现,PHY只负责物理层信号的编码、解码和收发。PHY的配置通过MDIO(Management Data Input/Output)接口读写内部寄存器来完成,这一点后面会详细说。
1.3 选型逻辑:什么场景选它,什么场景放弃
结合我对开发板的整体使用感受,这套方案适合下面几种场景:
- 项目要求国产化率,必须使用国产FPGA;
- 需要跑千兆以太网数据收发,但不需要跑到40G/100G那种量级;
- 需要一定量的数据缓冲能力,配合DDR3做数据暂存;
- 团队缺少FPGA开发经验,想选一块资料相对完善、学习曲线没那么陡峭的国产板子入门。
如果项目需求是超大逻辑资源、多路高速SerDes(比如PCIe Gen3 x8)、复杂SoC集成,那PGL50H这块板子确实不合适,应该去看更高端的Titan系列或者其他平台的方案。选型说白了就是对需求的诚实评估,资源够了就上,资源不够别硬塞,否则后面综合实现时序不过的时候,痛苦的还是自己。
2. 环境搭建与工程模板:PDS工具链的完整落地
2.1 PDS安装与License激活
紫光同创FPGA的官方开发环境是PDS(Programmable Design Suite),名字听起来有点像某国际大厂工具链的即视感,但使用逻辑和Vivado/Quartus大同小异。安装过程没有什么太特殊的坑,Windows下直接解压安装包,按提示把组件勾选完就行。有一点特别提醒:PDS对中文路径的支持并不友好,工程路径尽量不要出现中文和特殊字符,否则在跑综合实现时可能出现一些莫名其妙报错。我一开始没注意,放在“D:\工程\网口”下面,结果编译报错找半天发现是路径编码问题,改回纯英文路径后一切正常。
License是PDS绕不开的一个环节。紫光同创的License一般通过官方网站申请,绑定主机MAC地址或者网卡信息。申请下来后,在PDS里通过License Manager指定license文件路径即可。如果找不到License路径,可以先在环境变量里设置“LM_LICENSE_FILE”指向license文件,再启动PDS。注意License文件不要放在有中文或空格的目录里,我吃过这个亏,换成“D:\license.dat”后激活过程秒过。
2.2 从建工程到点亮LED:一次完整的代码流
这里用一个最简单的LED流水灯来走一遍流程,因为不管多复杂的系统,工程的建立和下载流程是共通的。
启动PDS后,新建工程,芯片型号选择PGL50H对应的具体封装。如果下拉列表里找不到型号,多半是器件库没有安装完整,回到安装包补装器件库组件即可。工程建好之后,会默认生成一个顶层文件,通常是Verilog格式。
接下来写代码,一个最小工程可以这样:
module led_test( input wire clk, input wire rst_n, output reg [3:0] led ); reg [24:0] cnt; always @(posedge clk or negedge rst_n) begin if (!rst_n) cnt <= 25'd0; else if (cnt == 25'd24_999_999) cnt <= 25'd0; else cnt <= cnt + 1'b1; end always @(posedge clk or negedge rst_n) begin if (!rst_n) led <= 4'b0001; else if (cnt == 25'd24_999_999) led <= {led[2:0], led[3]}; // 流水灯移位 end endmodule上面的代码基于一个假设:开发板上有50MHz时钟输入。如果实际晶振频率是25MHz,计数器的最大值要相应调整,否则LED闪动频率就不是预期的1秒。这是一种很常见的“参考代码参数需按硬件自行修正”的情况,建议拿到板卡先看原理图,确认时钟频率再接代码。
然后是管脚约束。PDS的约束文件后缀是.adc或.fdc,具体以工具版本为准。管脚约束的写法与Xilinx的XDC有一些相似,但关键词不同,建议直接用PDS自带的模板改。比如:
IO_LOC "clk" T14; IO_PORT "clk" IO_TYPE=LVCMOS33; IO_LOC "rst_n" K16; IO_PORT "rst_n" IO_TYPE=LVCMOS33; IO_LOC "led[0]" P4; IO_PORT "led[0]" IO_TYPE=LVCMOS33; IO_LOC "led[1]" P5; IO_PORT "led[1]" IO_TYPE=LVCMOS33; IO_LOC "led[2]" P6; IO_PORT "led[2]" IO_TYPE=LVCMOS33; IO_LOC "led[3]" P7; IO_PORT "led[3]" IO_TYPE=LVCMOS33;如果你拿到的是官方例程工程,里面的约束文件已经写好且经过验证,直接在此基础上改即可。因为你会经常增删管脚,建议在写约束之前先核对原理图上的网络标号和bank电压,避免管脚分配错误或电平标准不匹配导致下载后不工作甚至损伤芯片。
约束写完后,依次执行综合(Synthesis)和实现(Place & Route)。这个过程跑完大约需要几分钟,PGL50H属于中等规模芯片,综合速度还挺快的。最后生成bit流文件,连接下载器,在PDS里点击“Program Device”,把bit文件烧录到FPGA中。如果板卡连接正常,LED应该按照预期闪烁,第一个工程就算跑通了。
2.3 关于bit文件与环境的补充经验
热词里经常有人问“ISE生成的bit文件怎么下载到开发板”,这里顺带提一嘴:不同厂商的FPGA工具链,生成的配置文件格式不能通用。Xilinx用.bit,紫光同创用PDS生成的文件格式也不一样,需要各自的工具链配合相应的下载器才能烧录。国产FPGA的下载器接口往往与JTAG类似,PDS里直接识别即可。
另外,有朋友想在Ubuntu环境下跑PDS,这个是可以的。PDS官方提供了Linux版本安装包,安装后同样需要配置License。在Linux下使用PDS需要留意USB下载器的驱动权限设置,经常需要添加udev规则才能识别下载器,否则系统检测不到设备。这个问题在Windows下基本不存在,所以如果是新手,建议前期先用Windows环境,等跑通整个流程后再迁移到Linux。
3. 千兆网口实现:RGMII、PHY与UDP协议栈
3.1 RGMII接口时序,真的没那么玄乎
RGMII(Reduced Gigabit Media Independent Interface)是千兆以太网最常用的FPGA与PHY之间的接口方式。相比GMII动辄十几根线,RGMII把数据线减半,通过DDR双沿采样达到同样的带宽。RGMII总共有四组关键信号:
- TXD[3:0],发送数据线,在时钟上升沿发送低4位,下降沿发送高4位;
- TX_CLK,发送时钟,频率125MHz,由MAC(FPGA内部)产生给PHY;
- TX_CTL,发送控制信号,上升沿表示使能,下降沿表示错误标志;
- RXD[3:0]、RX_CLK、RX_CTL,接收方向对应的信号,其中RX_CLK是由PHY恢复出来的时钟,频率同样是125MHz。
用大白话讲,RGMII就是“在同一个时钟周期内,把8位数据劈成两半,分别用时钟的上沿和下沿传出去”。这样4根数据线配合双沿采样,等效一天内能传8位数据,正好匹配千兆(125MHz x 2 x 4bit = 1000Mbps)速率。
在PGL50H做网口设计时,FPGA内部需要例化以太网MAC逻辑,然后通过IO约束把MAC侧RGMII信号接到PHY芯片上。这里有个极易踩坑的点:TX_CLK到PHY的延迟和RX_CLK内部的相位关系。如果PCB走线长度不当或者FPGA内部没有做IO时序约束,可能出现PHY采不到正确数据的情况。常用的解决办法是,在PDS里对RGMII接口补上输入延时和输出延时的约束,具体数值根据PHY芯片手册的Tskew参数来计算。如果PDS自带的模板里已经包含RGMII约束,直接套用模板再做微调即可。
3.2 PHY芯片初始化:MDIO读写寄存器
FPGA内部实现MAC逻辑时,整个链路分为两层:MAC负责以太网帧的处理、CRC校验、字节流组装,而物理层的编码、线路信号收发则交给PHY芯片完成。要让PHY正常工作,必须通过MDIO接口对它的内部寄存器进行初始化,设置工作模式、速率、自协商开启状态等。
MDIO接口只有两根线:MDC时钟线和MDIO数据线,最多可以访问32个PHY地址。FPGA侧需要写一个简单的MDIO控制器,模拟MDIO时序来读写PHY寄存器。寄存器0是控制寄存器,bit0.13配置速度为1000Mbps,bit0.12配置全双工,bit0.9配置开启/关闭自协商。寄存器1是状态寄存器,用来确认协商结果。还有一个比较常用的寄存器是PHY的ID寄存器(寄存器2和3),读出来的值可以用来反查PHY型号,确认板子上实际用的什么芯片。
关于PHY初始化,我个人的经验是:不要一上来就手动强制配置千兆全双工,先默认开启自协商,等PHY把链路速率协商出来后再去读状态寄存器确认。这样做的原因是,很多网卡或交换机可能在协商过程中对主从模式有偏好,强制配置容易导致模式不匹配,物理上Link不上,之后排查起来更麻烦。
3.3 UDP协议栈:自研还是用IP核
以太网协议栈可以做得非常庞大,完整的TCP/IP协议栈实现起来工作量巨大。但在FPGA网口开发中,90%的需求用UDP就够了。UDP协议无连接、无重传,实现开销极小,非常适合实时数据采集和传输。
自研UDP协议栈需要处理的层次包括:
- MAC层:组装以太网帧头(目的MAC、源MAC、Type字段),追加FCS(帧校验序列);
- IP层:组装IP头(版本、头长、总长度、标识、TTL、协议号、源IP、目的IP),计算IP头部校验和;
- UDP层:组装UDP头(源端口、目的端口、长度、校验和),可选计算UDP校验和。
如果是在PDS里面例化现成的以太网IP核,MAC层往往已经帮你处理好了,你只需要把用户数据封装成IP和UDP的头部,按MAC核的接口时序送进去即可。如果PHY芯片和MAC核配合良好,PDS自带的IP核例化向导里甚至可以直接配置MAC地址、IP地址,省去不少手工拼头的工作。
在自研和IP核的选择上,我的建议是:
- 如果追求开发速度、项目周期短,用现成IP核;
- 如果希望深入理解以太网协议、方便后续定制特殊帧格式,自研;
- 如果数据量非常大,需要多通道并行发送,自研能更方便地做流水线优化。
我自己在这块板子上选择的是自研UDP发送模块加IP核MAC的组合,既保证了对帧格式的灵活控制,又不至于从零造MAC层轮子。工程里,用户数据经过FIFO缓存后,由状态机逐段拼装成UDP帧,送入MAC核发送。
3.4 跨时钟域处理:为什么网口设计离不开异步FIFO
网口设计里,用户逻辑运行在自定义频率下(比如150MHz),而MAC侧工作时钟通常是125MHz,两个时钟域之间交换数据时绝对不能用寄存器直接传递,必须经过异步FIFO或异步握手。
异步FIFO是跨时钟域数据缓存的标准方案。数据源侧以用户时钟写入FIFO,MAC发送侧以125MHz时钟从FIFO读出数据,两侧读写指针通过格雷码跨时钟域同步,避免亚稳态问题。在设计FIFO深度时,需要考虑两点:一是FIFO为空时MAC是否会产生欠载(通过加入最小帧长度的填充机制解决);二是FIFO为满时数据源是否要暂停写入(通过反压信号通知前级逻辑暂停发送)。
关于FIFO深度,我提供一个工程估算思路:假设数据源突发写入1KB数据,发送速率为千兆(约100MB/s),那么1KB数据在100MB/s速率下发完约需10微秒。如果写入速率是150MHz x 64bit约1200MB/s,那10微秒写入的数据量约12KB。这个场景下FIFO深度如果只有4KB,数据源必须在10微秒内停止写入,否则必丢数据。实际设计中,需要根据数据源的突发长度和发送带宽来反推FIFO最小深度,再留出至少2倍余量,避免时序抖动导致误差。
4. 高速数据通路:从数据源到网口发送的工程实践
4.1 系统架构设计:数据从哪里来,到哪里去
这块板子做“高速数据处理”,典型的数据通路是这样的:
数据源(ADC芯片、SPI传感器、或FPGA内部高速生成器)把数据写入异步FIFO的写端口;FIFO的读出端连接UDP发送模块;UDP发送模块把数据封装成以太网帧,通过RGMII接口经PHY发送到PC;PC端用自写的上位机软件或Wireshark抓包验证数据正确性。
在数据源的选择上,前期调试时我个人强烈建议先用FPGA内部生成固定模式的数据,比如递增值、伪随机序列(如LFSR)或者正弦波查表。用已知模式的数据做调试,一旦收到错误字节能立刻对照出来是哪个字节错了、错位量有多少。如果一上来就接真实ADC数据,数据本身就是随机的,收到异常数据很难判断问题出在链路、缓存、还是时序上。
以LFSR伪随机序列生成器为例,一个32位LFSR可以生成一个周期足够长的伪随机序列:
reg [31:0] lfsr; always @(posedge clk or negedge rst_n) begin if (!rst_n) lfsr <= 32'hDEAD_BEEF; else begin lfsr <= {lfsr[30:0], lfsr[31] ^ lfsr[21] ^ lfsr[1] ^ lfsr[0]}; end end接收端PC软件如果也实现了同样的LFSR算法,就能逐字节比对数据是否完全一致,这是验证链路可靠性的最直接方法。
4.2 UDP打包状态机:从数据到帧的组装流程
UDP发送模块的核心是一个状态机,负责把FIFO里的数据拆成若干个不超过1472字节的UDP数据段,逐段封装发送。
标准以太网MTU是1500字节,减去IP头20字节、UDP头8字节,UDP数据段最大就是1472字节。如果你一次性发超过这个长度的数据,就必须自己分片,否则上层协议或者PC网卡会直接丢包。所以写状态机的时候,必须每读到1472字节就强制成帧发送,剩余不足1472字节的数据最后单独一帧送出。
发送状态机的典型状态如下:
- IDLE:等待FIFO非空,进入PACK状态;
- PACK:拼接MAC头、IP头、UDP头,设定本次帧的数据长度;
- SEND_HEADER:发送头部数据(按字节宽度顺序送出);
- SEND_DATA:发送用户数据,每发送一个字节,读指针加一,计数减一,计数归零后进入SEND_FCS;
- SEND_FCS:由MAC核或自定义模块计算并附加CRC校验;
- WAIT:等待发送完成信号,返回IDLE,准备下一帧。
这里有一点要特别留意:UDP校验和如果懒得计算,可以把UDP头校验和字段设为0。在IPv4网络中,UDP校验和为0是合法值,接收端可以不校验。这样可以省掉一个较大的组合逻辑计算,对吞吐量提升有帮助。IP头校验和不能省略,但IP头只有20字节,计算量可以接受。
4.3 带宽计算与实测:千兆到底能跑多少
很多人以为千兆网口就能跑到1000Mbps的UDP吞吐量,实际不可能。1000Mbps指的是物理层速率,经过MAC层前导码、帧间隙、以太网头、IP头、UDP头的封装开销之后,有效数据吞吐大约在940Mbps左右,这还是在帧长度达到MTU上限的理想情况下。如果用100字节的小帧,有效吞吐率会掉到600Mbps以下,所以学会算封装开销是很有必要的。
一个典型的带宽计算例子如下:
- 以太网帧总开销 = 7字节前导码 + 1字节定界符 + 12字节帧间隙 + 14字节MAC头 + 4字节CRC + 20字节IP头 + 8字节UDP头 = 66字节;
- 假设每帧载荷1472字节,则总字节数 = 1472 + 66 = 1538字节;
- 有效带宽 = 1000Mbps × (1472 / 1538) ≈ 957Mbps。
实际测试中,我通过PC端网卡抓包统计,能够稳定跑到900Mbps左右。为什么比理论略低,一是PC的网卡主控和驱动有开销,二是PC端接收程序如果处理不过来也会造成丢包降速。所以如果你看到实测只有800-900Mbps,不用太焦虑,这是正常水平。
在FPGA侧做性能优化时,可以关注下面三个点:
- 发送数据的位宽:尽量使用32位或64位数据通路,而不是逐字节发送,能显著降低时钟频率需求;
- FIFO读出的连续性:FIFO读请求发出后,如果数据延时不固定,会拉长帧间隙,导致吞吐量下降,最好使用FWFT(First Word Fall Through)模式的FIFO;
- CRC计算方式:连续字节流的CRC建议用并行CRC实现,8位并行比逐位计算快得多。
4.4 接收链路不能忽视
做完发送数据,接收链路同样是调试重点。FPGA接收PC发来的UDP包时,MAC核会输出接收到的整帧数据,包含以太网帧头、IP头、UDP头和载荷。最简单的做法是在FPGA内部写一个帧解析模块,把MAC头、IP头、UDP头逐字节剥离,只把载荷部分存入FIFO,交给用户逻辑处理。
帧解析的流程可以用一个“状态过滤”的思路:检测到帧起始符后,先按字节计数跳过14字节MAC头,再判断IP头长度字段(通常20字节),跳过IP头,然后读取UDP头长度字段,最后一并提取载荷。解析时需要警惕短帧和错误帧,MAC核通常会提供接收数据有效信号和错误标志,在有效信号为低时清空状态机等待下一帧即可。
5. 排坑实录:网口调试的常见问题与解决思路
5.1 链路Layer不上的排查顺序
使用网口板最怕遇到的现象就是:插上网线后PHY的Link指示灯不亮,或者亮了但Ping不通,整个系统看起来死气沉沉。这里的排查顺序很重要,不要一上来就翻代码,而是先按照物理层—数据链路层—网络层逐层定位。
第一步确认PHY芯片供电和复位。用万用表测量PHY的电源引脚电压是否正常,复位引脚的电平状态是否处于释放状态。RTL8211等PHY芯片的复位要求低电平有效,如果复位引脚被电阻拉低或者 FPGA 侧一直输出低电平,PHY永远处于复位状态,指示灯自然不亮。
第二步确认PHY的时钟。大部分千兆PHY需要一个外部25MHz时钟,或者由FPGA提供一个参考时钟。如果PHY内部锁相环没有参考时钟,即使电源正常也无法工作。用示波器测量PHY晶体引脚或时钟输入引脚,确认125MHz或25MHz信号确实存在。
第三步确认MDIO配置是否成功。可以写一个简单的MDIO读操作,读取PHY ID寄存器(寄存器2和3)。如果读出来的值是0xFFFF或0x0000,说明MDIO链路有问题或者PHY地址不对,需要查看原理图上PHY地址引脚(如PHYAD[4:0])的上下拉配置,修改FPGA内部访问的PHY地址。
第四步确认RGMII数据是否真正在收发。用PDS自带的片上逻辑分析仪抓取RGMII的RX_DV信号和RXD数据,在PC端用ping命令往FPGA发数据。如果抓到的RXD全是0或者RX_DV不拉高,问题在PHY;如果RX_DV拉高且RXD数据符合预期,问题在MAC侧或上层协议栈。
5.2 RGMII时序的典型错误
如果你抓到的RGMII信号看起来明明有数据活动,但MAC核处理出来的帧校验总是错误,大概率是RGMII的时钟相位没有调整正确。RGMII的RX_CLK由PHY恢复输出,数据线相对于时钟有建立保持时间要求,FPGA内部必须对RX_CLK或者数据线加合适的延迟,否则采样的数据点落在数据转换的边缘,采到的就是乱码。
PDS里可以通过原语或IO约束来调整输入延时。具体做法是在约束文件里对RGMII的接收总线设置输入延时(Input Delay),数值通常为2ns左右,再根据实际抓波形的眼图中心微调。有的PHY支持通过寄存器配置内部的时钟延迟功能,比如RTL8211的部分版本有RX delay的配置位,可以在MDIO初始化时写入相应寄存器,减少PCB布线的时序压力。
发送方向比较简单,只要保证FPGA输出的TX_CLK与TXD、TX_CTL之间的相对关系满足PHY侧的要求即可。这里同样可以通过输出延时约束来做微调,如果遇到PHY收不到问题,优先调整发送方向的输出延时。
5.3 大流量场景下的丢包原因
通信速率一高,丢包问题就开始频繁冒头。结合实战经验,我把丢包原因分成三类:
第一类是FPGA侧FIFO溢出。如果数据源写入速率大于MAC发送速率,FIFO迟早被塞满。解决办法是增加FIFO深度,或者提前做数据分发与多通道并行发送,把单一发送通道的负载降下来。最有效的方法是让数据源侧感知发送状态,在FIFO快满时暂停数据产生,做成“反压式”数据流。
第二类是PC端接收处理能力不足。PC网卡接收到大量UDP包时,如果上位机程序没有启用足够大的接收缓冲区,操作系统会直接丢弃来不及处理的包。用Wireshark抓不到某些帧,不代表FPGA没发,很可能数据已经到网卡驱动,却被操作系统丢弃了。解决办法是增大接收缓冲、使用多线程接收或者降低PC端显示日志的频率。
第三类是UDP分片或乱序。如果发送端把一个大数据包强制拆成多个IP分片,有些网卡驱动对分片包的重组能力很差,表现为大量丢包。解决办法是无论如何都在应用层控制每个UDP包大小不超过1472字节,杜绝IP分片发生。
5.4 调试工具与心得
做FPGA网口调试,有两个工具是每天晚上都离不开的:PDS自带的片上逻辑分析仪,和PC端的Wireshark。片上逻辑分析仪主要用来抓FPGA内部信号,比如FIFO读写指针、发送状态机状态、MDIO读写波形;Wireshark则用来验证PC端实际看到的网络数据是否与期望一致。
我在调试中习惯先让FPGA向PC发送固定2024字节测试帧,再用Wireshark分析帧内容,检查MAC地址、IP地址、UDP端口和数据内容。确认没问题之后,才把数据源换成真实采样数据。如果能做到“发送端与接收端比对数据完全一致”,说明整条链路已经打通,剩下的就是性能优化和业务逻辑处理了。
6. 一些后话
这套板子做下来的整体感觉是:PGL50H加盘古50KN的组合,非常适合作为国产FPGA网口通信的入门平台和工程验证平台。芯片资源不算顶级,但把千兆网口、数据处理、DDR缓存、UART调试这些常用功能全都覆盖到了,社区资料和官方例程也比较丰富,遇到问题不至于完全没地方查。对我个人而言,最大的收获反而是对以太网协议栈和跨时钟域设计有了更深入的理解——这些知识不只是紫光同创能用,换到任何FPGA平台都是通用的。
如果你也准备在这块板子上做网口通信,最后分享一个小建议:先把简单链路跑通,再叠加业务复杂度。不要一上来就想着把UDP、DDR、ADC、传感器全部串起来,链路越复杂,调试时越难定位问题。先让PC和FPGA能互相收发纯测试数据,再逐步加功能模块,每一步都验证,后面反而省时间。国产FPGA的工具链虽然和国外主流平台有些差异,但使用逻辑是相通的,耐心啃了一遍,你会发现并没有想象中那么难。