FPGA基础回顾:从内部结构到开发流程
各位同学,咱们开始上课。今天要聊的是FPGA的基础知识。说实话,这部分内容看起来有点枯燥,但它是后面所有RISC-V移植工作的基石。我自己带过不少新人,发现很多人一上来就急着写代码,结果遇到时序问题、资源不够用的时候,才回头补基础——嗯,那其实更浪费时间。
FPGA内部到底长什么样?
FPGA不是一块简单的逻辑芯片。它更像一个乐高积木盒,里面有各种可配置的模块。我习惯把它的核心结构分成四块:LUT、FF、BRAM和DSP。咱们一个一个说。
1. LUT(查找表)—— 最基础的逻辑单元
LUT说白了就是一个可编程的真值表。你给它几个输入,它就能输出你想要的结果。常见的LUT有4输入、6输入甚至8输入的。
举个例子,你想实现一个与门:
// 用LUT实现 Y = A & B
// 4输入LUT,只用其中2个输入
LUT4 #(.INIT(16'h8)) u_lut (
.I0(A),
.I1(B),
.I2(1'b0),
.I3(1'b0),
.O(Y)
);
这里的INIT值16'h8,其实就是真值表的内容。我在项目中遇到过有人把INIT值写错,结果仿真全对,上板就翻车——查了两天才发现是LUT配置错了。所以,写LUT的INIT值时一定要仔细核对真值表。
2. FF(触发器)—— 时序逻辑的基石
FF负责存储状态。每个FF通常包含一个D触发器,带有时钟、复位、使能等控制信号。FPGA里的FF数量很关键,因为它决定了你能做多复杂的流水线设计。
个人经验:我建议你在做资源评估时,先看FF够不够用。LUT不够可以优化逻辑,但FF不够往往意味着架构要重改。我曾经在一个视频处理项目里,因为FF用超了,不得不把8级流水线砍成4级——性能直接掉了一半。
3. BRAM(块RAM)—— 片上存储的利器
BRAM是FPGA内部的专用存储模块。它比用LUT搭出来的寄存器阵列省资源得多。常见的BRAM容量是18Kb或36Kb,可以配置成单端口、双端口、真双端口等模式。
| 配置模式 | 数据宽度 | 深度 | 典型应用 |
|---|---|---|---|
| 单端口 | 1~36位 | 512~36K | 简单数据缓存 |
| 简单双端口 | 1~36位 | 512~36K | FIFO、帧缓冲 |
| 真双端口 | 1~36位 | 512~36K | 双核共享内存 |
你想想看,如果不用BRAM,用LUT搭一个32Kb的FIFO,那得吃掉多少资源?我算过,大概要2000多个LUT——而一个BRAM就搞定了。所以,能用BRAM就别用LUT搭大存储。
4. DSP(数字信号处理单元)—— 算力担当
DSP模块是专门为乘法、乘加运算设计的硬核。现在的FPGA里,DSP48E2(Xilinx 7系列)或者DSP58(Versal系列)都支持27x18的乘法,还能级联做FIR滤波器。
关键点:DSP的延迟是固定的,通常2~3个时钟周期。但如果你用LUT搭乘法器,延迟和资源都会爆炸。我在做RISC-V的乘法指令扩展时,就用了DSP来实现MUL指令——一个周期出结果,比用LUT搭快了5倍。
FPGA开发流程:三步走
开发FPGA,说白了就是三步:综合、实现、下载。但每一步都有坑,我一个个说。
第一步:综合(Synthesis)
综合是把你的HDL代码(Verilog/VHDL)翻译成网表。网表里就是LUT、FF、BRAM这些基本单元的连接关系。
综合工具会做几件事:
- 语法检查——看看代码有没有写错
- 逻辑优化——把冗余逻辑去掉
- 工艺映射——把逻辑映射到具体的LUT、FF上
避坑指南:我曾经在综合时遇到一个诡异的问题——代码仿真全对,但综合出来的网表功能不对。查了半天,发现是综合工具把一段组合逻辑优化掉了,因为我觉得"这段代码肯定不会被综合掉"——结果它真被优化了。所以,综合后一定要看报告,检查资源使用和警告信息。
第二步:实现(Implementation)
实现包括三个子步骤:
- 布局(Place)——把网表中的单元放到FPGA的物理位置上
- 布线(Route)——用可编程连线把这些单元连起来
- 时序分析(Timing Analysis)——检查能不能跑到目标频率
布局布线是FPGA开发里最耗时的环节。一个复杂的RISC-V处理器,布局布线可能要跑几个小时。我习惯在综合后先做一次快速实现,看看时序大概什么情况,再决定要不要改代码。
第三步:下载(Download)
下载就是把生成的比特流文件烧到FPGA里。这一步看起来简单,但要注意:
- JTAG链是否正确——多片FPGA级联时容易搞错
- 配置模式对不对——主模式还是从模式?SPI还是BPI?
- 电压是否匹配——1.8V还是3.3V?
嗯,这里要注意,下载失败时别急着怀疑硬件。先检查一下下载线驱动有没有装好——我遇到过好几次,折腾半天发现是驱动掉了。
常用EDA工具介绍
做FPGA开发,工具链是绕不开的。我按厂商分类说一下:
| 厂商 | 工具名称 | 特点 | 我的评价 |
|---|---|---|---|
| Xilinx(AMD) | Vivado | 功能全面,支持7系列及以后 | 综合能力强,但吃内存 |
| Intel(Altera) | Quartus Prime | 界面友好,编译速度快 | 适合中大规模设计 |
| Lattice | Diamond / Radiant | 轻量级,适合小芯片 | 低功耗场景首选 |
| 开源 | Yosys + nextpnr | 免费,支持Lattice为主 | 适合学习和研究 |
我个人习惯用Vivado做主力,因为它对RISC-V的支持最好——Vivado里可以直接例化MicroBlaze,也能很方便地集成第三方RISC-V核。但如果你做的是小项目,Lattice的Radiant启动快、占内存小,其实更舒服。
小技巧:不管用哪个工具,一定要学会看时序报告。很多新人只关心代码能不能综合过,却不管时序是否收敛。我见过一个项目,综合过了、实现也过了,但上板就是跑不起来——最后发现是setup time违例了0.1ns。0.1ns啊,就差这么一点。
本章知识体系
下面这张图是我画的FPGA基础结构图,帮你把今天讲的内容串起来:
这张图把FPGA的核心模块和它们之间的关系都画出来了。你仔细看,LUT和FF是成对出现的——它们组合在一起就是所谓的"逻辑片"(Slice)。BRAM和DSP是独立的大模块,分布在芯片的不同位置。而可编程互连线,就是把这些模块粘合在一起的"胶水"。
好了,FPGA基础就回顾到这里。这些内容虽然基础,但后面做RISC-V移植时,你会反复用到——比如评估一个RISC-V核需要多少LUT、多少BRAM,或者分析为什么某个指令跑不快。嗯,到时候你就知道今天讲的东西有多重要了。
公众号:蓝海资料掘金营,微信deep3321