第一章:FPGA基础与开发环境
各位同学好,我是老张。做FPGA这行十几年了,踩过的坑比走过的路还多。今天咱们聊聊FPGA的基础,这些东西看着简单,但真到了项目里,很多人就是在这上面翻的车。
1.1 FPGA内部结构——说白了就是这几样东西
FPGA内部到底有什么?我习惯把它想象成一个乐高积木盒。里面有几类基本模块,你拿它们拼出想要的电路。
LUT(查找表)
LUT是FPGA最核心的单元。它本质上是一个小型的RAM,输入地址,输出结果。比如一个4输入LUT,可以实现任意4输入的组合逻辑。我在项目中遇到过有人用LUT实现了一个复杂的加法器,结果资源爆了——其实用DSP更划算。
FF(触发器)
FF用来存储状态。说白了就是寄存器的基本单元。每个LUT后面通常跟着一个FF,这样组合逻辑的结果可以寄存一拍。嗯,这里要注意:FF的复位方式有同步和异步之分,选错了容易出时序问题。
BRAM(块RAM)
BRAM是FPGA内部的存储资源。容量从几Kb到几十Mb不等。我建议你优先用BRAM做数据缓存,别用LUT搭RAM——那玩意儿又慢又费资源。
DSP(数字信号处理单元)
DSP专门做乘加运算。一个DSP48E2可以做到18x25的乘法,还能级联。我曾经用DSP做FIR滤波器,比纯LUT实现快了3倍。
SerDes(串行器/解串器)
SerDes负责高速串行通信。比如PCIe、SATA、以太网都用它。这玩意儿布线要求极高,我建议新手直接调用IP核,别自己手写。
核心要点:FPGA内部结构就是LUT+FF+BRAM+DSP+SerDes这五样。你想想看,所有数字电路都能用这五样搭出来。
1.2 主流厂商介绍——Xilinx vs Intel
目前市场上就两家主流:Xilinx(现在叫AMD)和Intel(原Altera)。我两家都用过,说说我的感受。
| 特性 | Xilinx(AMD) | Intel(原Altera) |
|---|---|---|
| 开发工具 | Vivado / Vitis | Quartus Prime |
| 主流系列 | Artix、Kintex、Virtex | Cyclone、Arria、Stratix |
| 编程语言 | Verilog/VHDL | Verilog/VHDL |
| IP核生态 | 非常丰富 | 也很丰富 |
| 调试工具 | ChipScope / Vivado Logic Analyzer | SignalTap |
我个人习惯用Xilinx,因为Vivado的时序分析工具更顺手。但Intel的Quartus在低功耗方面做得更好。选哪家?看你项目需求。做高速通信,Xilinx强;做低功耗嵌入式,Intel香。
1.3 Vivado/Vitis开发流程——别被工具吓到
很多新手一打开Vivado就懵了。其实流程很简单,就这几步:
- 创建工程——选芯片型号,设好约束文件
- 编写代码——Verilog或VHDL,写你的逻辑
- 综合——把代码转成网表
- 实现——布局布线,生成比特流
- 下载调试——烧到板子上,用逻辑分析仪看波形
我曾经犯过一个低级错误:综合前没加时序约束,结果布局布线后时序全红。嗯,记住:约束文件一定要在综合前写好。
小技巧:Vivado的Tcl脚本很好用。我习惯把整个流程写成脚本,一键跑完。省时省力,还不会漏步骤。
1.4 硬件描述语言快速回顾——Verilog/VHDL
Verilog和VHDL,选哪个?我建议新手学Verilog,语法简单,上手快。VHDL更严谨,适合大型项目。但说实话,现在大部分公司都用Verilog。
Verilog基础语法
// 一个简单的D触发器
module d_flip_flop (
input wire clk,
input wire rst_n,
input wire d,
output reg q
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
q <= 1'b0;
else
q <= d;
end
endmodule
这段代码里,always @(posedge clk or negedge rst_n)是时序逻辑的标准写法。注意:复位用异步复位,同步释放——这是我在项目里踩过的坑。
VHDL基础语法
-- 同样的D触发器
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity d_flip_flop is
Port ( clk : in STD_LOGIC;
rst_n : in STD_LOGIC;
d : in STD_LOGIC;
q : out STD_LOGIC);
end d_flip_flop;
architecture Behavioral of d_flip_flop is
begin
process(clk, rst_n)
begin
if rst_n = '0' then
q <= '0';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
end Behavioral;
VHDL的process和Verilog的always本质一样。区别在于VHDL更啰嗦,但类型检查更严格。
避坑指南:我曾经在项目中混用阻塞赋值和非阻塞赋值,结果仿真和实际行为不一致。记住:时序逻辑用非阻塞赋值(<=),组合逻辑用阻塞赋值(=)。
1.5 本章知识体系
下面这张图是我自己画的,把本章的核心内容串起来了。你想想看,FPGA开发就是:先搞懂内部结构,再选好厂商工具,然后按流程走,最后用语言实现。
好了,第一章就到这里。记住:FPGA开发不是写软件,是画电路。你写的每一行代码,最终都会变成实实在在的硬件。所以,多想想你的代码会综合成什么电路,而不是只盯着仿真波形看。
课后思考:如果你用LUT实现一个32位加法器,和用DSP实现,资源消耗差多少?试试看。