1. 为什么我会在2024年选择安路EG4S20这块板子1.1 从国产FPGA能不能用到真香的心路历程先说结论这块板子彻底改变了我对国产FPGA的固有印象。我以前一直在用Xilinx和Altera现在叫Intel的芯片手里攒了好几块不同型号的开发板。但2024年有个现实问题摆在我面前——国产替代的进程明显加快了尤其在一些特定项目上甲方明确要求核心器件要有国产供应链方案。研究了一圈之后发现安路科技Anlogic在国内FPGA厂商里属于第一梯队产品线覆盖了从低功耗小芯片到中高密度逻辑芯片。而我选中的这块EG4S20开发板则是安路生态里最常见的一块学习型板子网上能找到的资料数量虽然比不上Xilinx但在国产FPGA里已经算是社区最活跃的那一档了。EG4S20这个型号从名字就能读出不少信息。EG4是安路的Eagle系列第四代产品线主打低成本、低功耗、高性价比S20里的20大概对应20K量级的逻辑资源——具体来说是接近2万个LUT4四输入查找表内置RAM块总量在百Kbit级别还带了十几个DSP乘法器单元。这个规模放在今天肯定不算大但用来学习FPGA的基础逻辑、时序约束、UART通信、SPI接口、简易图像处理完全够用。如果你是从0开始学FPGA用这种20K级别的小芯片起步是非常合适的练手成本低编译速度快改代码到上板的迭代周期短。还有个最重要的理由便宜。一块EG4S20核心板加下载器的价格大概相当于同档次Xilinx Artix-7开发板的零头。即便在国内的国产FPGA板子里安路这块的性价比也非常突出。对自费学习、学生党、个人开发者来说这个价格决定了犯错的成本足够低——你敢大胆折腾才能快速成长。1.2 EG4S20的板载资源与我的实际使用感受我入手的这块EG4S20开发板板载资源比较典型的配置是EG4S20BG256主芯片、50MHz板载有源晶振、一个USB转UART的调试串口、板载USB-JTAG下载电路、四个独立按键、四个LED灯、一个RGB灯、若干扩展IO排针部分版本还带了SDRAM芯片。这个配置对新手来说是恰到好处LED和按键用来跑基础实验UART用来做通信实验扩展IO可以外接各种模块。实际拿到板子的时候第一感觉是做工对得起价格焊点饱满排针间距标准没有那种廉价开发板的毛刺感。板子的USB口有两个一个是下载口一个是串口别插错了。这个细节我第一次用的时候没注意插错口之后就出现了设备管理器里找不到下载器的情况——后面会专门讲到这个问题。1.3 选型时的同价位对比我为什么没选高云也没选紫光同创在掏钱之前我其实把国产FPGA的主流厂商都过了一遍。高云半导体Gowin的GW1NR/GW1N系列也是非常有竞争力的选择Tang Nano系列开发板在海外创客圈甚至还挺出名文档也比较规范。紫光同创的Logos系列则是另一条路线偏中高密度开发软件PDS的体验也还可以。但最终我选了安路主要原因有三个。第一安路的TD软件整体完成度更高更接近Vivado/Quartus的使用习惯。对于一个用惯了Xilinx工具链的人来说切入TD的学习成本相对低。第二EG4S20的价格优势太明显了同样是20K逻辑资源EG4S20的板子比高云同等资源的板子便宜。第三安路最近两年在学校和培训机构里铺得比较开B站、CSDN上关于EG4S20和EG4S20BG256的资料越来越多遇到问题能找到人讨论。对一个学习者来说生态比芯片本身的极限性能更重要——毕竟你的目标不是用20K的逻辑单元做出什么惊天动地的大项目而是把FPGA的核心设计理念和开发流程吃透。2. 开发环境搭建TD软件安装与License申请的坑2.1 TD软件的整体认知它其实就是一个完整的FPGA工具链安路的开发环境叫Tang Dynasty简称TD目前主流的版本是TD5.x系列。这个软件集成了从RTL代码编写、综合、布局布线、时序分析到下载调试的完整流程相当于把Vivado、ModelSim、ChipScope这几样东西合并成了一个统一的工具。TD软件的界面风格和Quartus有点像工程管理在左侧编译日志在下方主窗口是代码编辑区和各种报告视图。第一次打开会有点熟悉的感觉这对我这种从Quartus入门的人来说非常友好。安装过程本身不复杂Windows下双击安装包一路Next就行。但我建议你注意两点。第一安装路径不要带中文和空格这几乎是所有FPGA工具的通用禁忌第二建议以管理员身份运行安装程序避免后面出现权限问题。2.2 License申请的实际操作流程注意MAC地址别填错TD软件的License需要去安路官网申请。这个流程在国产FPGA工具里算是比较顺畅的——你先下载安装TD软件然后在安装目录下找到获取机器码的工具一般在TD安装目录的bin文件夹下运行之后会生成一串机器码把这串机器码填到官网的License申请页面提交后邮箱里会收到一个License文件把这个文件导入TD软件就能正常使用了。这里面有几个坑值得单独提一下。第一不同版本的TD软件可能对应不同的License格式如果你是老版本升级到新版本建议重新申请一个对应版本的License不要拿旧License硬套。第二申请到的License文件一般有有效期注意看清楚过期时间过期后重新申请即可。第三也是最重要的——机器码是绑定网卡MAC地址的如果你的电脑有多个网卡比如有线网卡、无线网卡、虚拟机虚拟网卡生成工具取的是哪块网卡的MAC地址不一定而后续使用时如果网卡顺序变了可能导致License失效。我自己的经验是在申请License前先禁用除主网卡之外的其他网卡确保生成的机器码稳定然后在日常使用中也保持同样的网络状态。2.3 下载器驱动与设备识别的完整排查装好软件、搞定License之后下一步就是连接开发板。这块EG4S20开发板板载了USB-JTAG下载电路用一个USB线连接开发板的下载口和电脑设备管理器里应该能识别出一个串行设备。但如果设备管理器里显示的是未知设备或者黄色感叹号有九成概率是驱动没装好。解决办法是在设备管理器里右键未知设备选择更新驱动程序手动定位到TD安装目录下的driver文件夹让系统从那里搜索驱动。装好之后设备会识别为一个Alink或类似名称的USB-JTAG设备。这里有一个很容易被忽略的细节USB线要用带数据传输的线不是所有的USB线都能传数据。有些USB线买来就只是充电线里面只有电源线没有数据线。我前后折腾了半小时最后换了一根数据线就正常了。这一条经验看似小儿科但真的能浪费你很多时间。3. 第一个工程实践从点亮LED到跑通完整流程3.1 新建工程时的参数选择芯片型号的坑打开TD软件新建工程的第一步就是选择芯片型号。EG4S20这块板子用的是EG4S20BG256这个型号里的BG256代表BGA封装的256引脚版本。新建工程时一定要选对封装否则后面引脚约束的时候会找不到对应的引脚。在TD新建工程向导里依次选择Family为Eagle系列、Device为EG4S20、Package为BG256速度等级选默认的即可。器件选错是新手最常见的错误之一——你的板子明明是BG256封装结果选了CS144封装到后面分配引脚的时候会完全找不到板卡上对应的引脚编号。另外TD的工程文件后缀是.apj一个工程下可以管理多个源文件。工程目录同样建议不要有中文路径和空格。3.2 流水灯Verilog代码最简单的模块也要讲究写法第一个程序我选了流水灯。这个经典实验虽然简单但能完整走通FPGA开发的全部流程代码编写、综合、布局布线、引脚约束、下载上板。下面是我实际使用的代码module led_flow ( input wire clk, // 50MHz 板载时钟 input wire rst_n, // 低电平复位 output reg [3:0] led ); reg [25:0] cnt; // 计数器 always (posedge clk or negedge rst_n) begin if (!rst_n) cnt 26d0; else if (cnt 26d49_999_999) cnt 26d0; else cnt cnt 1b1; end // 根据计数器的进位状态切换LED always (posedge clk or negedge rst_n) begin if (!rst_n) led 4b0001; else if (cnt 26d49_999_999) led {led[2:0], led[3]}; // 循环左移 end endmodule这段代码的逻辑很简单50MHz的时钟计数器从0加到49999999计数满一次正好是1秒。计数满的时候LED值循环左移一位实现流水灯效果。值得注意的是复位逻辑的写法。FPGA设计里异步复位、同步释放是更规范的做法但对于这个学习阶段的工程使用简单的异步复位也没有问题。关键是你要意识到复位信号的处理方式在真实项目中是有讲究的这里先用简单的写法后续在更复杂的工程里我会专门讨论这个问题。另外如果你使用的是有源晶振时钟信号直接接到FPGA的全局时钟引脚上即可如果是无源晶振就需要额外的时钟电路来配合EG4S20核心板基本都用的有源晶振不用操心这个。3.3 引脚约束从图形界面到底层约束文件的完整理解写完代码之后最关键的步骤就是引脚约束。所谓引脚约束就是把代码里的逻辑端口clk、rst_n、led[3:0]映射到FPGA芯片的实际物理引脚上告诉综合工具这些信号应该从芯片的哪些引脚进出。在TD软件里打开Floor Planner也可以叫Pin Planner界面左侧会列出代码里的所有端口右侧是芯片封装的引脚分布图。我手上这块EG4S20开发板的典型引脚分配如下信号引脚说明clkP17板载50MHz有源晶振rst_nR5板载按键默认上拉高电平led[0]R3LED灯led[1]P4LED灯led[2]P3LED灯led[3]P2LED灯不同版本的开发板引脚定义会不一样具体引脚序号以你手里板子的原理图为准。但我强烈建议你第一件事就是去板卡卖家页面或资料包里把原理图找出来打印出来或存成PDF随时随地查引脚。不要凭记忆不要猜。TD软件的图形化引脚分配用起来很顺手在端口列表里选中一个信号然后在右侧芯片图上找到对应的引脚双击或拖拽过去就行。分配完之后TD会自动生成一个物理约束文件后缀通常是.adc或其他格式。这个文件本质上是文本你也可以用文本编辑器直接手动修改方便在不同工程之间复用。时钟引脚要特别注意。在FPGA设计中时钟信号必须连接到芯片的全局时钟引脚Global Clock Pin上否则工具无法把时钟信号布线到全局时钟网络上会引发时钟偏斜clock skew问题。当你打开Pin Planner时时钟输入引脚在芯片封装图上的位置通常会用特殊颜色标注注意不要分配错。3.4 综合、布局布线与下载上板的完整操作链路引脚约束完成之后接下来是标准的编译流程。在TD软件里综合Synthesis和布局布线Place Route是两个分开的步骤也可以一步到位直接运行全流程。综合过程会把Verilog代码翻译成逻辑门级的网表布局布线则把网表映射到芯片实际的可配置逻辑块和布线资源上。EG4S20这种规模的芯片综合加布局布线的总时间大概在几十秒到一两分钟这个速度比Xilinx中大型芯片动辄几十分钟的编译时间舒服太多了。对于学习者来说这个快速的编译周期能够支撑高频率的试错随时改、随时跑学起来效率会非常高。编译通过之后打开下载界面选择对应的USB-JTAG设备把生成的bit流文件TD生成的下载文件后缀是.bit或.fs具体看版本烧录进FPGA芯片。这里有一个需要区分清楚的概念FPGA的配置方式有SRAM方式和Flash方式两种。下载到SRAM的话掉电之后程序丢失每次上电都要重新下载下载到配置Flash的话掉电不丢失上电自动加载。我建议学习阶段用SRAM方式下载因为调试时改代码方便。等你确认程序没问题了再烧到Flash里。TD软件里这两种模式一般是以不同按钮或选项形式提供的注意看一下界面说明即可。3.5 实测观察从上板的实际反应到代码逻辑的验证程序下载完成之后开发板上的四个LED应该开始循环点亮效果是依次左移然后循环回到最右端每秒位移一次。但我实际上板之后发现了一个问题LED的流动方向和我预期的是反的。我的代码里写的是循环左移实际效果却像是在往右流动。原因很简单板上四个LED的物理排列顺序和FPGA引脚编号顺序不是一一对应的——PCB布局的时候LED可能从右往左排而引脚约束是从P2到R3递增排列两者正好反了。这个问题在FPGA开发里很典型逻辑上的一回事和物理上的另一回事经常不匹配。解决办法有两个一是把代码里的移位方向反过来二是在引脚约束层面调整LED[0]和LED[3]的映射关系。我最终选择了改代码——因为LED的命名是逻辑概念不应该被物理位置绑架保持代码的可读性更重要。4. 仿真与在线调试TD工具的实操技巧与注意细节4.1 为什么学习阶段必须学会写Testbench很多初学者在点亮LED之后就迫不及待地往UART、SPI、图像处理这些复杂功能上冲。但我建议你先停下来——在跑第一个稍微复杂的实验之前先学会仿真。所谓仿真就是不用真实硬件在电脑上模拟FPGA内部逻辑的运行过程。FPGA开发有一个铁律先仿真后上板。原因很简单在真实芯片上调试一个复杂的内部信号非常困难你必须借助逻辑分析仪才能看到芯片内部节点的波形变化。而在仿真环境里所有内部信号都是透明的随时可以观察。仿真通过之后再上板验证遇到问题时的排查范围就能缩小很多。以我刚才那个流水灯为例虽然工程简单到不需要仿真但你可以练习一下写Testbench的流程。TD软件自带仿真工具也可以直接使用ModelSim或Vivado自带的仿真器——TD的RTL仿真支持Verilog和VHDL。这是我当时用的Testbench代码是一个标准的Verilog仿真测试文件timescale 1ns / 1ps module tb_led_flow; reg clk; reg rst_n; wire [3:0] led; led_flow uut ( .clk(clk), .rst_n(rst_n), .led(led) ); initial begin clk 0; rst_n 0; #100; rst_n 1; end always #10 clk ~clk; // 50MHz 时钟周期20ns initial begin #2000000; // 仿真2ms $finish; end endmodule注意仿真时有一个加速技巧把代码中的计数器目标值从49999999改小一点比如改成499这样仿真波形里就能快速看到LED翻转的效果。如果仿真也按真实的1秒翻转波形窗口得拉好长才能看到变化浪费时间。4.2 从波形图到上板的验证逻辑运行仿真后你能在波形窗口里看到clk信号、cnt计数器的递增过程以及当cnt达到设定值时led信号的跳变。我建议你在仿真时仔细观察以下两个信号的行为cnt到达最大值之后的清零时机是不是正确led的移位是否发生在cnt清零的同一个时钟沿。如果发现时序差了一个周期要去思考原因是什么——通常和always块里的事件触发机制有关。这种对时序细节的敏感性是FPGA开发者最重要的基本功之一靠看书是学不来的必须通过仿真波形去感受。4.3 在线逻辑分析仪当你需要看芯片内部真实信号时仿真做的再多最终还是要回到真实硬件上来。但上板之后有一个尴尬的问题芯片内部的信号是看不见的无法直接验证某个中间信号是否正常翻转。这时候就需要逻辑分析仪。TD软件自带了一个在线逻辑分析工具类似Xilinx的ChipScope或Intel的SignalTap它可以在芯片内部插入探针把你想观察的信号实时上传到电脑上显示波形。以UART通信实验为例如果你怀疑UART的发送端在某个数据位出错单纯用示波器去打引脚波形会很痛苦。而使用TD的内置逻辑分析仪你只需要在RTL代码里插入一个调试探针然后重新综合下载就能在PC上直接看到UART发送模块的内部状态机跳转和数据位变化。具体操作步骤是在代码里实例化一个调试探针模块把你想观察的信号连到探针上设置好触发条件比如上升沿触发或特定数据值触发然后编译下载软件会弹出逻辑波形分析窗口。这个方法比外接逻辑分析仪方便得多也是实际工程中最常用的调试手段之一。不过要注意的是插入逻辑分析仪探针会消耗芯片内部资源——EG4S20本身资源就不多探针数量太多可能导致布局布线失败。所以在调试复杂功能时建议只探针性地观察关键信号不要贪多。5. 实际踩坑记录编译错误、下载失败与引脚冲突的排查思路5.1 常见编译错误类型与定位方法这几周我用EG4S20练了不少例子几乎每个例子都出过错下面是我整理出来的几种高频编译错误和定位思路。第一类是语法错误。这类错误TD软件会在编译日志里明确暗示是哪一行属于最低级但也最容易犯的错误。常见的包括漏写分号、begin和end不匹配、module和endmodule不匹配。解决方式很直接看编译日志定位到具体行号。第二类是信号位宽不匹配。比如你定义了一个reg [3:0] led但赋值的时候用了led 5b00001编译就会报位宽不匹配。这类错误在很多EDA工具里只是警告而不是错误但真实电路上会带来不确定行为——高位的信号被截断了。第三类是赋值冲突。同一个信号在多个always块区块里面进行了赋值这在FPGA综合里面是禁止的。我刚开始学Verilog的时候经常犯这个错总是习惯性地把多个逻辑段都写成always块但它们操作的是同一个寄存器。5.2 下载失败时最有效的三步排查法比编译错误更让人头疼的是下载失败。我的经验是下载失败时按下面三步排查大多数情况下都能解决。第一步检查设备管理器里USB-JTAG设备是否正常识别。如果设备消失或者出现感叹号先重新插拔USB线再不行就重启电脑再试。TD软件偶尔会出现下载器占用未释放的情况重启通常能解决。第二步检查TD软件的下载界面里是否已正确选中设备。有时候电脑上插了多个USB设备TD会选错手动在下拉菜单里选到正确的设备再试。第三步检查开发板是否上电、电源指示灯是否点亮。EG4S20开发板可以用USB口供电但如果你同时插了下载线和串口线要确认供电的USB线插对了且电流输出足够。如果开发板用了某些大功耗外设比如接了摄像头模块可能出现电压跌落导致FPGA无法正常配置。5.3 第一次跑通UART通信时遇到的所有问题合集流水灯实验通过之后我做的第二个实验是UART串口通信。这个实验一下子把难度提上来了涉及到了FPGA学习中最重要的几个主题时钟分频、状态机设计、跨时钟域处理。我当时写了一个简单的UART发送模块把数据发出到电脑上用串口助手收到之后显示。看起来简单的功能实际上一共遇到了三个问题。第一个问题是波特率误差。UART通信要求发送方和接收方的波特率尽量一致误差要控制在2%以内。我本来以为用50MHz时钟分频到9600波特率是很简单的事情50_000_000 / 9600 5208.33。问题来了——不是我理解的整数。如果直接用整数5208做分频系数实际波特率是50_000_000 / 5208 9600.61误差大约0.006%这个误差很小可以接受。但如果用更奇葩的时钟频率和波特率组合误差可能非常大导致接收端乱码。解决方式是计算误差之后超过1%就换一个整数分频系数或者换一个能被整除的波特率比如50MHz时钟下用115200波特率因为50_000_000 / 115200 434.027...这其实还是整数误差所以尽量用常见的时钟频率和波特率组合。第二个问题是状态机的复位状态。我最初实现的UART发送状态机复位之后没有回到IDLE状态而是停留在当前状态这导致第一次发送时数据错乱。解决方式是确保复位信号能把状态机拉回IDLE状态并且每次发送完毕之后也要回到IDLE。第三个问题是信号同步。实际在EG4S20这种单时钟域设计里还没有太复杂的跨时钟域问题但如果你的设计中有多个时钟域比如异步串口接收的16倍频采样时钟和系统时钟不是同一个就需要用两级触发器同步跨时钟域信号。这个问题在EG4S20上做串口实验时可能还碰不到但后面做图像处理或者DDR接口时会频繁遇到现在先有这个意识。6. 基于EG4S20的后续学习路线规划6.1 从基础到进阶的资源推荐完成了基础实验之后我给自己的后续学习方向做了个简单规划这里也分享给你参考。第一步是把常用的基础外设通信接口都过一遍UART已经做完了接下来是SPI和I2C。这两个接口在传感器读取、Flash配置、屏幕驱动里非常常见。安路的IP核库里提供了对应的控制器但学习阶段建议自己手写从底层寄存器操作的角度去理解协议这对后续调试能力提升帮助很大。第二步是学习PLL锁相环的使用。EG4S20内部是有PLL资源的可以倍频或者分频产生不同频率的时钟。之前50MHz晶振直接用在全系统但真实项目中不同外设需要不同时钟频率这时候就必须用PLL来产生。TD软件里有PLL的IP核配置工具可以可视化配置输入输出频率配置完后会生成一个IP核模块你在代码里直接实例化调用即可。学会用PLL之后才算是真正把FPGA内部的时序资源用起来了。第三步是尝试简单的图像处理。EG4S20的资源虽然不大但做一些基本的图像缩放、灰度转换、边缘检测还是够用的。需要一个OV2640摄像头模块和一个显示屏模块在FPGA里实现的流程大致是摄像头采集数据写入FIFO缓存然后从FIFO读出数据经过图像算法模块处理再发给显示屏显示。这个项目能帮你把之前学的所有知识串起来——时钟管理、FIFO缓存、状态机设计、同步处理、接口协议。6.2 关于TDC直方图在EG4S20上的探索最近看到社区里有人在讨论FPGA TDCTime-to-Digital Converter时间数字转换器直方图测量这其实是一个非常有意思的应用方向。用FPGA实现TDC的基本思路是利用FPGA内部的进位链延迟单元Carry Chain作为时间测量的基本单位通过捕获信号在进位链上的传播位置来量化时间间隔。EG4S20这种量级的FPGA做TDC是可行的虽然精度不如Xilinx的高端芯片但作为学习原理和做演示项目绰绰有余。TDC和直方图结合的场景通常是用在激光雷达、医学成像、高能物理实验等领域但把它们拆开了看核心就是两个部分TDC负责测量时间差直方图负责统计分布。在FPGA里实现的时候TDC部分用的是进位链和触发器阵列直方图部分用的是Block RAM做统计存储。我计划后续专门写一篇关于在EG4S20上实现简易TDC直方图测距的学习记录这是把FPGA底层资源用明白的一个好案例也是目前社区里热度比较高的FPGA进阶方向之一。6.3 我在EG4S20上发现的几个国产特色与注意事项最后聊几个这块板子和TD工具链上国产特色的地方主要是为了让后面入手的朋友少走弯路。第一TD软件的更新频率在这个领域不算特别高但每次更新的变化也都比较大有时候升级之后工程文件需要重新编译。建议你确定一个稳定的版本后长期使用不要频繁追新。另外不同版本的TD生成的比特流文件格式可能有差异如果下载时报错bit file version mismatch就要核对一下软件版本和下载工具的匹配关系。第二安路的PLL IP核虽然能用但配置界面的可选项比Xilinx少一些某些高级功能比如动态相移支持有限。这个对学习阶段影响不大但如果你要做的是一个需要精细时序控制的项目要先确认一下IP核的能力边界。第三EG4S20的部分引脚是复用型的比如有些引脚在作为普通IO使用的同时也连接到板载的某些器件上。做引脚约束之前必须仔细核对原理图如果一个引脚已经被板载的USB转串口芯片或者其他外设占用了你再把它分配给你的逻辑信号上电后就可能出现电平冲突严重时甚至会损坏芯片。这也是FPGA开发中电气引脚分配前必须核对原理图这条铁律的由来。这几周用下来的整体感觉是EG4S20作为一款学习型FPGA芯片在功能、价格、生态之间找到了一个非常合理的平衡点。TD工具链虽然和Vivado、Quartus相比还有一些差距但核心功能都是齐全的综合、布局布线、时序约束、在线调试这些日常开发流程都能顺畅走通。对一个入门FPGA的开发者来说这个工具在够用这个维度上做得已经很好了——毕竟工具的价值在于帮你把设计跑起来而不是让工具的界面看起来多花哨。安路这块板子的另一个隐性价值在于当你习惯了国产FPGA的开发节奏之后会发现很多经验是可以平滑迁移的——约束的写法、时序分析的方法、IP核的使用逻辑这些底层思维都是一样的。后面我会继续更新学习记录2计划写PLL的使用和UART状态机的进阶实验。