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)

实现包括三个子步骤:

  1. 布局(Place)——把网表中的单元放到FPGA的物理位置上
  2. 布线(Route)——用可编程连线把这些单元连起来
  3. 时序分析(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 查找表 4/6输入真值表 组合逻辑实现 FF 触发器 D触发器阵列 时序逻辑存储 BRAM 块RAM 18Kb/36Kb 单/双端口 DSP 数字信号处理 27x18乘法 乘加运算 可编程互连线(Routing) 连接所有逻辑单元,实现任意电路 I/O 接口 时钟管理 配置逻辑 JTAG FPGA = LUT + FF + BRAM + DSP + 互连线 + I/O 所有模块均可通过编程重新配置

这张图把FPGA的核心模块和它们之间的关系都画出来了。你仔细看,LUT和FF是成对出现的——它们组合在一起就是所谓的"逻辑片"(Slice)。BRAM和DSP是独立的大模块,分布在芯片的不同位置。而可编程互连线,就是把这些模块粘合在一起的"胶水"。

好了,FPGA基础就回顾到这里。这些内容虽然基础,但后面做RISC-V移植时,你会反复用到——比如评估一个RISC-V核需要多少LUT、多少BRAM,或者分析为什么某个指令跑不快。嗯,到时候你就知道今天讲的东西有多重要了。


公众号:蓝海资料掘金营,微信deep3321