跳到主要内容 FPGA 内部资源详解:LUT、FF、BRAM、DSP、PLL 及综合报告解读 | 极客日志
编程语言
FPGA 内部资源详解:LUT、FF、BRAM、DSP、PLL 及综合报告解读 FPGA 内部资源详解:LUT、FF、BRAM、DSP、PLL 及综合报告解读。文章解析 FPGA 五大核心硬件资源的工作原理与使用限制。通过 Artix-7 芯片资源概览,说明组合逻辑与时序逻辑的资源映射差异。讲解 Block RAM 的推断条件与同步读特性,DSP48 单元在乘加运算中的优势及强制属性方法。介绍 PLL 锁相环的时钟生成用途及锁定信号处理。最后提供综合报告 Utilization Report 的解读方法及资源使用率警戒线参考,帮助优化代码并理解硬件映射真相。
FPGA 内部资源详解:LUT、FF、BRAM、DSP、PLL 是什么?综合报告怎么看
1. 为什么要了解内部资源
很多初学者把 FPGA 当"黑盒"来用:代码写好,综合通过,下板能跑就行。这种方式在入门阶段没问题,但遇到以下情况就会卡住:
综合报告提示资源使用率 95%,不知道哪里占用多了
时序报告显示关键路径太长,不知道怎么优化
代码里用了乘法,不知道会映射到 DSP 还是 LUT,也不知道有什么区别
想用片内 RAM 存储一张查找表,不知道怎么写才会推断出 BRAM
了解内部资源,就是了解代码背后"硬件映射"的真相。
1.1 Artix-7 资源概览 以 Xilinx Artix-7(xc7a100t)为例,主要资源如下:
资源类型 数量(xc7a100t) 用途 LUT(6-input) 63 400 实现任意组合逻辑函数 FF(触发器) 126 800 存储 1 bit 状态,构成寄存器 BRAM(36Kb) 135 块 片内大容量存储器 DSP48E1 240 个 乘法、乘加、MAC 运算 MMCM/PLL 6 个 时钟倍频/分频/相位调整
2. LUT 查找表
2.1 LUT 是什么 LUT(Look-Up Table,查找表) 是 FPGA 实现组合逻辑的核心单元。Artix-7 使用的是 6-input LUT ,即有 6 个输入(A1~A6)和 1 个输出(O)。
LUT 的本质是一个 64 位的真值表存储器 (2⁶ = 64 种输入组合)。每种输入组合对应的输出值在编程时写入,运行时根据输入地址直接查表输出,延迟固定。
2.2 LUT 实现任意 6 输入函数 任何 6 变量以内的布尔函数,都能用一个 6-input LUT 实现:
// 以下所有函数综合后各只需 1 个 LUT
assign y = a & b; // 2 输入与门
assign y = a | b | c | d; // 4 输入或门
assign y = (a & b) | (c & d) | (e ^ f); // 6 变量函数
assign y = (a == 4'b1010) ? 1 : 0; // 4 位等值比较
// 8 输入与门:需要 2 个 LUT(先 4 输入与,再 2 输入与)
assign y = a & b & c & d & e & f & g & h;
2.3 LUT 的双输出模式(O5/O6) Xilinx 7 系列的 6-input LUT 可以同时配置为:
一个 6-input LUT(输出 O6)
同时输出一个 5-input LUT 的结果(输出 O5,使用前 5 个输入 A1~A5)
综合工具会自动利用这一特性打包逻辑,提高 LUT 使用效率,无需手动干预。
2.4 LUT vs FF:什么决定用哪个 信号类型 推断的资源 assign y = a & b;(组合逻辑)LUT always @(posedge clk) reg <= data;(时序逻辑)FF always @(posedge clk) reg <= a & b;(时序逻辑的输入是组合逻辑)LUT + FF
3. 触发器 FF 与寄存器
3.1 FF 的物理结构 FF(Flip-Flop,触发器) 是存储 1 bit 状态的基本单元。FPGA 中的每个 FF 实际上是一个 D 触发器 :
D:数据输入
Q:数据输出
CLK:时钟(上升沿触发)
CE(Clock Enable):时钟使能
R/S:复位/置位
// 综合为 1 个 FF
always @(posedge clk or negedge rst_n)
begin
if (!rst_n) q <= 1'b0;
else q <= d;
end
3.2 寄存器 = N 个 FF 的集合 N 位 reg 类型信号在综合后对应 N 个 FF:
reg [7:0] data_reg; // 综合为 8 个 FF
3.3 FF 的时钟使能(CE) 当 always 块中有 if (en) 条件时,综合工具会自动将 en 连接到 FF 的 CE 端口,而不是生成一个选择器:
always @(posedge clk)
begin
if (en) q <= d; // 综合后:d→D,en→CE,而不是 MUX
end
利用 CE 而不是 MUX 来实现使能,可以节省 LUT 资源并降低时序压力。
3.4 FF 的复位类型对综合的影响 写法 复位类型 FPGA 实现 always @(posedge clk) 内的 if(!rst_n)同步复位 额外的 LUT 实现选择器 always @(posedge clk or negedge rst_n) 的 if(!rst_n)异步复位 直接使用 FF 的 R 端口,不消耗 LUT
Xilinx 7 系列 FF 有异步复位端口,因此异步复位写法 更节省资源。
4. Block RAM
4.1 什么时候用 BRAM 片内 BRAM 适合存储较大量的数据 (几百字节以上):
需求 建议 几十 bit 的状态寄存器 用 FF/寄存器 几百字节的查找表 用 BRAM 或分布式 RAM 几 KB 以上的缓冲区、ROM 必须用 BRAM
如果用 LUT 来拼大容量存储,LUT 资源会迅速耗尽(每个 LUT 只能存 64 bit)。
4.2 BRAM 结构 Artix-7 的 BRAM 为 36Kb 双端口 RAM ,可配置为:
模式 说明 真双端口(TDP) 端口 A、端口 B 可独立读写,支持不同时钟 简单双端口(SDP) 一个端口写,一个端口读,最大数据宽度可达 72 bit 单端口(SP) 只用一个端口读写 ROM 模式 固化初始值,只读
一个 36Kb BRAM 也可以拆为两个 18Kb BRAM 使用。
4.3 Verilog 推断 BRAM 综合工具(Vivado)能从 Verilog 代码自动推断 BRAM,关键是遵循"同步读"写法:
// 推断单端口同步 RAM(综合为 BRAM)
module single_port_ram #(
parameter DATA_WIDTH = 8,
parameter ADDR_WIDTH = 8 // 深度 = 2^8 = 256
)(
input wire clk,
input wire we, // 写使能
input wire [ADDR_WIDTH-1:0] addr,
input wire [DATA_WIDTH-1:0] din,
output reg [DATA_WIDTH-1:0] dout
);
// 存储阵列
reg [DATA_WIDTH-1:0] mem [0:(1<<ADDR_WIDTH)-1];
always @(posedge clk)
begin
if (we) mem[addr] <= din;
dout <= mem[addr]; // 同步读(关键!异步读不会推断 BRAM)
end
endmodule
注意 :BRAM 是同步读 ——读操作在时钟沿触发,输出比输入延迟 1 个时钟周期。这与"组合逻辑读 ROM"不同,设计时要注意这个延迟。
4.4 ROM 初始化 // 正弦波查找表 ROM(64 点,8bit)
reg [7:0] sin_rom [0:63];
initial begin
sin_rom[0] = 8'd128;
sin_rom[1] = 8'd140; // ...(通常通过 $readmemh 从文件加载)
$readmemh("sin_table.hex", sin_rom);
end
5. DSP48 乘加单元
5.1 为什么乘法要用 DSP 一个 16×16 的乘法器如果用 LUT 来实现,需要消耗约 100 个以上的 LUT ,且时序性能差(关键路径长)。而 FPGA 片内专门集成了 DSP48 硬核乘加单元,一个 DSP48E1 就能实现 25×18 位的乘加运算:
其中 A 为 30 bit,B 为 18 bit,P 为 48 bit(Artix-7 DSP48E1 规格)。
5.2 自动推断 DSP 只要代码中出现乘法运算,综合工具通常会自动将其映射到 DSP:
// 以下代码会被综合工具自动推断为 DSP
wire signed [15:0] a, b;
wire signed [31:0] p;
assign p = a * b; // → 推断为 1 个 DSP48
5.3 MAC 累加器(乘累加) DSP48 内部有预加器和后加器,特别适合 MAC(Multiply-Accumulate)运算,如 FIR 滤波器、矩阵乘法:
// 乘累加:acc = acc + a * b
reg signed [47:0] acc;
wire signed [15:0] a, b;
always @(posedge clk or negedge rst_n)
begin
if (!rst_n) acc <= 48'd0;
else if (en) acc <= acc + (a * b); // 综合为 DSP 的 P = A×B + C 模式
end
5.4 强制推断 DSP 的属性 有时候综合工具可能"改主意"用 LUT 实现乘法。可以用综合属性强制指定:
(* use_dsp = "yes" *)
wire signed [31:0] p;
assign p = a * b;
6. PLL 锁相环
6.1 PLL 的用途 板载晶振只提供一个固定频率(通常 100 MHz)。实际项目中往往需要多个不同频率的时钟,这时需要 PLL(Phase-Locked Loop,锁相环) 来生成:
PLL 功能 示例 倍频 100 MHz → 200 MHz 分频 100 MHz → 25 MHz 相位偏移 产生 90° 相移时钟 抖动过滤 清洁外部输入时钟的抖动
6.2 Vivado 中使用 PLL IP 核 Xilinx 7 系列推荐用 Clocking Wizard IP 核配置 PLL/MMCM,具体步骤见后续章节。这里先了解 PLL 基本参数:
// PLL 例化示意(由 Clocking Wizard 自动生成)
clk_wiz_0 u_clk_wiz (
.clk_in1 (sys_clk), // 输入:100MHz
.clk_out1 (clk_200m), // 输出 1:200MHz
.clk_out2 (clk_50m), // 输出 2:50MHz
.clk_out3 (clk_25m), // 输出 3:25MHz
.locked (pll_locked), // PLL 锁定标志
.reset (~rst_n)
);
locked 信号很重要:PLL 上电后需要一段稳定时间(通常几微秒),在 locked 变高之前,输出时钟不稳定,应用 locked 做全局复位使能 :
assign sys_rst_n = rst_n & pll_locked; // 只有 PLL 锁定后才释放复位
7. 综合报告解读
7.1 打开 Utilization Report
Synthesis → Utilization Report(after synthesis):综合后估算
Implementation → Utilization Report(after implementation):实现后准确值
7.2 报告示例解读 +----------------------------+-------+-------+------------+-----------+-------+
| Site Type | Used | Fixed | Prohibited | Available | Util% |
+----------------------------+-------+-------+------------+-----------+-------+
| Slice LUTs | 312 | 0 | 0 | 63400 | 0.49 |
| LUT as Logic | 298 | 0 | 0 | 63400 | 0.47 |
| LUT as Memory | 14 | 0 | 0 | 19000 | 0.07 |
| Slice Registers | 256 | 0 | 0 | 126800 | 0.20 |
| Register as Flip Flop | 256 | 0 | 0 | 126800 | 0.20 |
| Block RAM Tile | 2 | 0 | 0 | 135 | 1.48 |
| RAMB36/FIFO | 2 | 0 | 0 | 135 | 1.48 |
| DSPs | 4 | 0 | 0 | 240 | 1.67 |
+----------------------------+-------+-------+------------+-----------+-------+
字段 含义 Used当前设计使用的数量 Available芯片上该资源的总数量 Util%使用率(Used/Available×100%) LUT as Logic用于实现逻辑的 LUT LUT as Memory用于实现分布式 RAM(小存储)的 LUT
7.3 资源使用率警戒线 使用率 状态 说明 < 70% 正常 布局布线有充足余量 70%~85% 注意 布局可能变紧张,时序变差 > 85% 危险 时序难收敛,可能报实现失败 > 95% 不可用 基本无法布通
当某类资源接近上限时,需要考虑:更换更大型号的 FPGA,或优化代码减少资源消耗。
附:本篇完整源码
resource_demo.v // ============================================================
// 文件名 : resource_demo.v
// 描述 : 演示 LUT/FF/BRAM/DSP 的 Verilog 推断方式
// ============================================================
// ---------- 示例 1:推断单端口同步 BRAM ----------
module sp_bram #(
parameter DATA_W = 8,
parameter ADDR_W = 8
)(
input wire clk,
input wire we,
input wire [ADDR_W-1:0] addr,
input wire [DATA_W-1:0] din,
output reg [DATA_W-1:0] dout
);
reg [DATA_W-1:0] mem [0:(1<<ADDR_W)-1];
always @(posedge clk)
begin
if (we) mem[addr] <= din;
dout <= mem[addr]; // 同步读 → 推断 BRAM
end
endmodule
// ---------- 示例 2:推断 DSP 乘累加 ----------
module mac_unit (
input wire clk,
input wire rst_n,
input wire en,
input wire signed [15:0] a,
input wire signed [15:0] b,
output reg signed [47:0] acc
);
always @(posedge clk or negedge rst_n)
begin
if (!rst_n) acc <= 48'd0;
else if (en) acc <= acc + ({{16{a[15]}}, a} * {{30{b[15]}}, b}); // 乘法部分推断为 DSP48
end
endmodule
// ---------- 示例 3:利用 FF CE 端的计数器 ----------
module cnt_with_en (
input wire clk,
input wire rst_n,
input wire en, // 使能,映射到 FF 的 CE 端口
output reg [7:0] cnt
);
always @(posedge clk or negedge rst_n)
begin
if (!rst_n) cnt <= 8'd0;
else if (en) cnt <= cnt + 1'b1; // en 会被综合工具优化为 FF 的 CE,节省 LUT
end
endmodule
相关免费在线工具 Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
JSON美化和格式化 将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online