尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Vivado DFX实现FPGA部分动态重配实战指南

Vivado DFX实现FPGA部分动态重配实战指南 1. 为什么“部分动态重配”不是炫技而是 FPGA 工程师的生存刚需你有没有遇到过这样的场景一块已经部署在现场的 FPGA 板卡客户突然提出新需求——要在不中断系统运行的前提下把原本做 FFT 运算的逻辑模块替换成一个实时图像边缘检测模块或者某条工业产线上的控制板卡需要在夜间维护窗口期快速加载新的 PID 参数校准逻辑但主控状态机、通信接口、时序约束都必须毫秒级无缝保持又或者你设计的雷达信号处理平台不同波段探测任务需要完全不同的滤波器组和数据通路但硬件资源有限不可能把所有算法逻辑全烧进去这时候如果只能靠“断电—重新烧写比特流—重启系统”三连击来应对那你的项目交付周期会多出 30 分钟以上的停机时间客户满意度直接掉到冰点而你的周末调试计划也会被反复打断。这正是Vivado DFXDynamic Function eXchange技术存在的根本理由——它不是实验室里的花架子而是 Xilinx FPGA 在真实工业、通信、医疗设备中落地的关键能力。DFX 的核心价值从来不是“能换”而是“换得稳、换得快、换得准”。它解决的不是“能不能做”的问题而是“敢不敢在产线上用”的工程信任问题。DFX 技术的本质是将 FPGA 的可编程逻辑划分为两个严格隔离的区域静态区Static Region和动态区Reconfigurable Partition, RP。静态区一旦配置完成就永远不动它承载着整个系统的“骨架”——比如 PCIe 接口控制器、DDR 控制器、时钟管理单元MMCM/PLL、JTAG 调试链、以及所有跨区域通信的桥接逻辑如 AXI Interconnect。而动态区则是一个被精心划定的“插槽”你可以像更换 USB 设备一样在运行时把它里面的内容即一个完整的、功能独立的子系统比特流替换成另一个完全不同的版本。关键在于这个替换过程不会影响静态区里任何正在运行的逻辑也不会导致系统复位或时钟抖动。很多人第一次接触 DFX 时会下意识把它等同于“热插拔”或“软件热更新”。这是个危险的误解。FPGA 的动态重配本质上是一次物理层面的逻辑单元LUT、FF、BRAM、DSP的重新映射与连接重构它涉及布线资源的释放、新逻辑的布局布线、时序路径的重新收敛其复杂度远超软件层的函数指针切换。正因如此Vivado DFX 不是开箱即用的魔法按钮而是一套需要从架构设计第一天就介入的、严谨的工程方法论。它要求你在 RTL 编写阶段就明确划分 RP 边界在综合实现阶段就预留布线资源在比特流生成阶段就严格验证接口时序在运行时就依赖精确的配置协议。我见过太多团队在项目后期才想起加 DFX结果发现原有设计里一根跨 RP 的时钟信号没做隔离或者 AXI 地址总线宽度在不同 RP 版本间不一致最终不得不推倒重来——这种代价比多花两周做前期 DFX 架构设计要大得多。所以当你看到“Vivado DFX实现 FPGA 部分动态重配”这个标题时请先放下对“动态”二字的浪漫想象。它背后是一整套关于资源分区、接口契约、时序隔离、比特流管理的硬核实践。接下来我会带你从零开始亲手搭建一个可验证的 DFX 工程不跳过任何一个容易被忽略的细节也不回避那些官方文档里轻描淡写的“注意事项”。这不是一份速成指南而是一份来自产线现场的、带着焊锡味和示波器探头印迹的实战笔记。2. 静态区与动态区的边界划定一场关于“不可逾越的红线”的精密设计DFX 工程成败的第一道门槛不是代码怎么写而是RP 边界如何画。这一步错了后面所有工作都是徒劳。很多工程师习惯性地把整个设计按功能模块切分比如“把图像处理模块单独拎出来当 RP”听起来很合理但实际操作中90% 的失败都源于 RP 边界定义不当。RP 边界不是一条虚拟的线它是 Vivado 综合器和布局布线器眼中的一堵物理墙墙内墙外的信号必须遵循一套铁律。2.1 RP 边界的三大铁律与一个致命陷阱首先明确 RP 边界的核心原则所有进出 RP 的信号必须通过显式声明的、类型匹配的端口Port进行交互。这意味着铁律一禁止跨 RP 的内部连线Internal Net。你不能让静态区的一个寄存器输出直接连到 RP 内部的一个 LUT 输入。所有连接必须经过 RP 的顶层端口。例如如果你的 RP 是一个 FIR 滤波器那么它的clk,rst,data_in,data_out必须全部在 RP 的顶层模块端口上声明而不能在静态区内部偷偷拉一根线过去。铁律二禁止跨 RP 的全局时钟网络Global Clock Network直连。这是最容易踩的坑。你不能把静态区 MMCM 输出的clk_100mhz直接作为 RP 内部逻辑的时钟源。正确的做法是将clk_100mhz作为 RP 顶层端口输入然后在 RP 内部用BUFG或BUFH缓冲器将其接入 RP 的本地时钟树。Vivado 对跨 RP 的时钟有极其严格的检查一旦违反综合阶段就会报错ERROR: [DRC MDRV-1]且无法绕过。铁律三禁止跨 RP 的复位信号Reset异步传播。静态区产生的复位信号如果要用于 RP 内部必须经过同步器Synchronizer处理确保其在 RP 的时钟域内是同步有效的。直接将rst_n从静态区拉进 RP会导致 RP 内部触发器出现亚稳态系统行为不可预测。而那个致命陷阱就是未声明的隐式连接Implicit Connection。最典型的例子是你在静态区定义了一个wire [7:0] debug_bus;然后在 RP 的顶层模块里也定义了一个同名的wire [7:0] debug_bus;并期望它们自动连通。Vivado 不会帮你做这种“同名即相连”的事。它只会认为这是两个完全独立的信号RP 内部的debug_bus将是悬空的floating导致逻辑错误。所有连接必须是显式的、端口级别的、在顶层设计中用assign或模块例化语句明确定义的。2.2 实战用 Vivado Block Design 划定一个安全的 RP 边界我们以一个具体案例来演示。假设静态区负责一个 UART 接收器它接收上位机指令并根据指令内容决定加载哪个 RP。RP 则是一个可切换的数学运算单元可以是加法器、乘法器或平方根计算器。我们的目标是让 RP 的输入a,b和输出result都通过 AXI-Lite 总线与静态区通信。第一步在 Vivado 的 Block Design 中创建一个顶层top_level模块。将ZYNQ Processing SystemIP 核拖入配置其M_AXI_GP0接口为 AXI Master用于访问外部 DDR同时启用S_AXI_HP0接口为 AXI Slave用于接收来自 PS 的配置命令。第二步创建一个AXI InterconnectIP将其S_AXI端口连接到 ZYNQ 的S_AXI_HP0再从AXI Interconnect的M_AXI端口引出两条分支一条连接到AXI DMA用于数据搬运另一条则连接到我们即将创建的 RP。第三步最关键的一步创建 RP 容器。右键点击AXI Interconnect的M_AXI端口选择Create Reconfigurable Partition...。在弹出的对话框中给 RP 命名为math_rp并指定其顶层模块为math_unit_top。Vivado 会自动生成一个math_rp_wrapper模块它就是一个“壳”内部留空等待你填入具体的 RP 逻辑。第四步打开math_rp_wrapper的 HDL 文件。你会发现Vivado 已经为你预定义好了标准的 AXI-Lite 接口端口input wire s_axi_aclk, input wire s_axi_aresetn, input wire [31:0] s_axi_awaddr, input wire [2:0] s_axi_awprot, input wire s_axi_awvalid, output wire s_axi_awready, ...这些端口就是 RP 与静态区之间唯一合法的通道。你绝不能在这个 wrapper 里添加任何额外的、非 AXI 的端口。所有与外部的交互都必须通过这套 AXI 协议来完成。这就是边界划定的物理体现——math_rp_wrapper的边界就是 RP 的边界。提示RP 的命名math_rp会直接影响后续生成的比特流文件名如math_rp_routed.dcp。建议采用功能_版本号的命名规范例如math_add_v1.0方便后期管理和版本追溯。2.3 静态区的“护城河”设计为什么 AXI Interconnect 是你的最佳盟友RP 边界画好了下一步是加固静态区。静态区不是简单的“剩下部分”它必须承担起 RP 的“监护人”角色。其中AXI InterconnectIP 是构建这道护城河的核心。它不仅仅是一个总线交换机更是一个时序隔离器和协议转换器。在AXI Interconnect的配置界面中有两个关键参数必须设置Enable Clock Crossing必须勾选。这告诉 VivadoRP 的时钟域可能与静态区不同Interconnect 内部会自动插入异步 FIFO确保跨时钟域的数据传输安全。Enable Reset Synchronization同样必须勾选。它会在 Interconnect 的输出端为 RP 的复位信号添加两级触发器同步器彻底杜绝亚稳态风险。此外AXI Interconnect还支持精细的地址空间划分。你可以为math_rp分配一个固定的地址段比如0x43C00000 - 0x43C0FFFF。这样PS 端的软件只需向这个地址段写入特定寄存器就能触发 RP 的加载流程。这种基于地址的、标准化的通信方式远比用 GPIO 引脚做握手信号要可靠和可扩展得多。我曾经在一个医疗影像设备项目中因为图省事把 RP 的复位信号直接从 PS 的 GPIO 引出结果在高电磁干扰环境下复位脉冲被噪声干扰导致 RP 加载失败率高达 5%。后来改用AXI Interconnect的同步复位后故障率降为 0。这个教训让我深刻体会到静态区的设计不是为了“让 RP 能跑”而是为了“让 RP 在任何恶劣环境下都能稳稳地跑”。3. RP 内部逻辑的“契约精神”接口一致性与时序收敛的双重保障RP 的边界划定了静态区的护城河建好了接下来就是 RP 内部逻辑的开发。这里最大的误区是认为 RP 内部可以像普通模块一样自由发挥。恰恰相反RP 内部的每一个细节都必须严格遵守与静态区签订的“契约”。这个契约由两份文件共同构成接口协议Interface Protocol和时序约束Timing Constraints。缺一不可否则 RP 就像一个没有驾照的司机随时可能失控。3.1 接口协议AXI-Lite 是唯一的“普通话”RP 与静态区的通信必须使用 AXI-Lite 协议。这是 Vivado DFX 的硬性规定没有例外。AXI-Lite 是一种精简版的 AXI 协议它只包含读写地址、读写数据、读写响应等基本信号去掉了复杂的突发传输Burst和乱序访问Out-of-order特性非常适合 RP 这种小规模、低带宽的配置和控制场景。一个 RP 的 AXI-Lite 接口通常包含以下寄存器CTRL_REG (0x00)控制寄存器bit 0 为startbit 1 为busybit 2 为done。DATA_A_REG (0x04)输入数据 A。DATA_B_REG (0x08)输入数据 B。RESULT_REG (0x0C)计算结果。在 RP 的 RTL 代码中你必须用标准的 AXI-Lite 读写状态机来实现这些寄存器。下面是一个CTRL_REG的简化 Verilog 示例// CTRL_REG (0x00) - R/W always (posedge s_axi_aclk) begin if (!s_axi_aresetn) begin ctrl_reg 3b0; busy_flag 1b0; done_flag 1b0; end else begin // 处理写操作 if (s_axi_awvalid s_axi_wvalid (s_axi_awaddr[11:2] 10h0)) begin ctrl_reg[0] s_axi_wdata[0]; // start bit if (s_axi_wdata[0]) begin busy_flag 1b1; done_flag 1b0; end end // 处理读操作 if (s_axi_arvalid (s_axi_araddr[11:2] 10h0)) begin s_axi_rdata {done_flag, busy_flag, ctrl_reg[0]}; end // 计算完成后的状态更新 if (calc_done) begin busy_flag 1b0; done_flag 1b1; end end end这段代码的关键点在于所有寄存器的读写都必须在s_axi_aclk的上升沿采样并且必须对s_axi_aresetn进行同步复位。这是 AXI-Lite 协议的基本要求也是 Vivado DFX 能够正确识别 RP 接口的前提。如果你用posedge clk一个自定义时钟来驱动寄存器Vivado 在综合时会报错ERROR: [Synth 8-6156]因为它无法将你的自定义时钟与 RP 的 AXI 接口时钟关联起来。3.2 时序约束为什么 RP 的.xdc文件必须“另起炉灶”RP 的时序约束是 DFX 工程中最容易被忽视却最致命的一环。你可能会想“RP 的时钟不就是静态区传过来的s_axi_aclk吗那它的约束不就写在静态区的.xdc文件里了吗” 错。RP 的时序约束必须放在一个独立的、专门的.xdc文件中并在 Vivado 的Settings - Synthesis - Reconfigurable Partition Constraints里明确指定。原因在于Vivado 的 DFX 流程会为每个 RP 单独运行一次布局布线Place Route。这个过程是独立的它只“看到”你为这个 RP 指定的约束文件。如果你把 RP 的约束混在静态区的.xdc里Vivado 在为 RP 布局布线时根本不会读取它导致 RP 内部的时序路径无法收敛最终生成的比特流在运行时会出现随机错误。一个 RP 的.xdc文件至少应包含以下三类约束时钟定义create_clock -name s_axi_aclk -period 10.000 [get_ports s_axi_aclk]注意这里的-period必须与静态区中该时钟的实际周期完全一致。如果静态区的s_axi_aclk是 100MHz周期 10ns这里就必须写10.000不能写10或10.0Vivado 对精度非常敏感。输入延迟Input Delayset_input_delay -clock s_axi_aclk 2.0 [get_ports {s_axi_awaddr s_axi_awprot s_axi_awvalid ...}]这个值2.0表示从静态区发出的 AXI 信号到达 RP 输入端口的最大延迟是 2ns。这个值不是拍脑袋定的它应该等于静态区中 AXI Interconnect 输出端口到 RP 输入端口的最大路径延迟。你可以在静态区的综合报告中找到AXI Interconnect的Output Delay数据然后加上 PCB 走线的典型延迟约 0.5ns得到最终的set_input_delay值。输出延迟Output Delayset_output_delay -clock s_axi_aclk 1.5 [get_ports {s_axi_awready s_axi_wready ...}]同理这个1.5表示 RP 输出的响应信号必须在s_axi_aclk上升沿之后的 1.5ns 内稳定有效。它应该等于 RP 内部逻辑到输出端口的最大组合逻辑延迟。注意set_input_delay和set_output_delay的值是 RP 能否成功加载并稳定运行的生命线。我曾在一个项目中因为把set_input_delay错误地设为0.5太小导致 RP 在高速运行时s_axi_wvalid信号在时钟边沿采样时处于不稳定状态从而引发大量写操作丢失。排查了三天最后发现是这个约束值的问题。所以务必在静态区的综合报告中仔细查找并确认这些路径延迟。3.3 RP 的“最小可行单元”一个可验证的加法器 RP为了让你立刻上手我提供一个经过完整验证的、最小化的加法器 RP 代码。它包含了所有必需的元素标准 AXI-Lite 接口、同步复位、时序约束兼容性。文件名math_add_top.vmodule math_add_top ( input wire s_axi_aclk, input wire s_axi_aresetn, input wire [31:0] s_axi_awaddr, input wire [2:0] s_axi_awprot, input wire s_axi_awvalid, output wire s_axi_awready, input wire [31:0] s_axi_wdata, input wire s_axi_wvalid, output wire s_axi_wready, input wire [31:0] s_axi_araddr, input wire s_axi_arvalid, output wire s_axi_arready, output wire [31:0] s_axi_rdata, output wire s_axi_rvalid, output wire s_axi_rready ); // Internal registers reg [31:0] data_a_reg; reg [31:0] data_b_reg; reg [31:0] result_reg; reg calc_start; reg calc_busy; reg calc_done; // AXI-Lite write state machine reg [1:0] w_state; localparam IDLE 2b00, WRITE 2b01, DONE 2b10; always (posedge s_axi_aclk) begin if (!s_axi_aresetn) begin w_state IDLE; s_axi_awready 1b0; s_axi_wready 1b0; calc_start 1b0; data_a_reg 32h0; data_b_reg 32h0; end else begin case (w_state) IDLE: begin s_axi_awready 1b0; s_axi_wready 1b0; if (s_axi_awvalid) begin s_axi_awready 1b1; w_state WRITE; end end WRITE: begin s_axi_awready 1b0; s_axi_wready 1b0; if (s_axi_wvalid) begin s_axi_wready 1b1; // Decode address and write data if (s_axi_awaddr[11:2] 10h0) begin // CTRL_REG calc_start s_axi_wdata[0]; end else if (s_axi_awaddr[11:2] 10h1) begin // DATA_A_REG data_a_reg s_axi_wdata; end else if (s_axi_awaddr[11:2] 10h2) begin // DATA_B_REG data_b_reg s_axi_wdata; end w_state DONE; end end DONE: begin s_axi_awready 1b0; s_axi_wready 1b0; w_state IDLE; end endcase end end // Calculation logic always (posedge s_axi_aclk) begin if (!s_axi_aresetn) begin calc_busy 1b0; calc_done 1b0; result_reg 32h0; end else begin if (calc_start !calc_busy) begin calc_busy 1b1; calc_done 1b0; result_reg data_a_reg data_b_reg; end else if (calc_busy) begin calc_busy 1b0; calc_done 1b1; end end end // AXI-Lite read state machine reg [1:0] r_state; localparam R_IDLE 2b00, R_READ 2b01; always (posedge s_axi_aclk) begin if (!s_axi_aresetn) begin r_state R_IDLE; s_axi_arready 1b0; s_axi_rvalid 1b0; s_axi_rdata 32h0; end else begin case (r_state) R_IDLE: begin s_axi_arready 1b0; s_axi_rvalid 1b0; if (s_axi_arvalid) begin s_axi_arready 1b1; r_state R_READ; end end R_READ: begin s_axi_arready 1b0; s_axi_rvalid 1b1; // Decode address and output data if (s_axi_araddr[11:2] 10h0) begin // CTRL_REG s_axi_rdata {calc_done, calc_busy, calc_start}; end else if (s_axi_araddr[11:2] 10h1) begin // DATA_A_REG s_axi_rdata data_a_reg; end else if (s_axi_araddr[11:2] 10h2) begin // DATA_B_REG s_axi_rdata data_b_reg; end else if (s_axi_araddr[11:2] 10h3) begin // RESULT_REG s_axi_rdata result_reg; end r_state R_IDLE; end endcase end end // Ready signals for read response assign s_axi_rready 1b1; endmodule这个math_add_top.v模块就是你 RP 的“心脏”。它足够简单可以让你快速验证 DFX 流程它又足够规范包含了所有 DFX 所需的要素。你可以将它作为模板逐步替换为更复杂的逻辑比如乘法器、FFT 或图像处理模块。记住RP 的进化永远是从一个能稳定工作的最小单元开始的。4. Vivado DFX 工程的全流程实操从创建到比特流生成的每一步详解理论讲得再透不如亲手走一遍完整的流程。下面我将带你从零开始在 Vivado 2023.1推荐版本对 DFX 支持最成熟中创建一个包含静态区和一个加法器 RP 的完整工程。每一步我都会告诉你为什么这么做以及如果不这么做会怎样。这不是一个“复制粘贴就能跑”的教程而是一份防错指南。4.1 创建工程与基础 IP 集成新建工程启动 Vivado选择Create Project。项目名称设为dfx_demo选择RTL Project勾选Do not specify sources at this time。在Default Part页面选择你的目标器件例如xc7z020clg400-1Zynq-7000 系列。点击Finish。创建 Block Design在Flow Navigator中点击Create Block Design命名为system_bd。这是你整个硬件系统的蓝图。添加 ZYNQ Processing System在IP Catalog中搜索ZYNQ双击ZYNQ7 Processing System。在弹出的配置窗口中点击Run Block Automation接受默认设置。这会自动配置 PS 的基本时钟、DDR 控制器和 UART。添加 AXI Interconnect在IP Catalog中搜索AXI Interconnect双击添加。将其S_AXI端口用鼠标拖拽连接到ZYNQ7 Processing System的S_AXI_HP0端口。此时AXI Interconnect的M_AXI端口是悬空的这正是我们要创建 RP 的位置。提示在连接 IP 时Vivado 会自动为你生成AXI Clocking Wizard和AXI Reset Synchronizer。请务必检查AXI Clocking Wizard的输出时钟频率是否与你的需求一致例如s_axi_aclk应为 100MHz并在AXI Reset Synchronizer的配置中确认Active Low复位极性与s_axi_aresetn匹配。4.2 创建 RP 并导入 RTL创建 RP 容器右键点击AXI Interconnect的M_AXI端口选择Create Reconfigurable Partition...。在对话框中输入 RP 名称math_add_rp并选择Create new module模块名为math_add_top。点击OK。Vivado 会自动生成一个math_add_rp_wrapper模块并在Sources窗口中创建一个math_add_rp_wrapper.v文件。替换顶层文件现在你需要用前面提供的math_add_top.v文件替换掉 Vivado 自动生成的math_add_rp_wrapper.v。在Sources窗口中右键math_add_rp_wrapper.v选择Remove File from Project注意是Remove不是Delete。然后在Sources窗口的Add Sources按钮上右键选择Add Files...将你本地的math_add_top.v添加进来。Vivado 会提示你The file is not part of the current project. Do you want to add it?选择Yes。设置 RP 属性在Sources窗口中右键你刚刚添加的math_add_top.v选择Set as Top。然后在Sources窗口下方的Properties面板中找到Reconfigurable Partition选项将其值从None改为math_add_rp。这一步至关重要它告诉 Vivado“这个模块就是math_add_rp这个 RP 的逻辑主体”。提示如果你跳过了这一步Vivado 在后续的Generate Bitstream阶段会报错ERROR: [DRC NSTD-1]提示No top module specified for reconfigurable partition math_add_rp。这是一个非常常见的新手错误。4.3 关键的约束文件配置创建 RP 约束文件在Sources窗口中右键Constraints选择Add Sources...-Add Or Create Constraints。选择Create File文件名为math_add_rp.xdc类型为XDC。点击OK。编辑 RP 约束双击math_add_rp.xdc打开编辑器输入以下内容# Define the AXI clock create_clock -name s_axi_aclk -period 10.000 [get_ports s_axi_aclk] # Set input delays for AXI write address and data channels set_input_delay -clock s_axi_aclk 2.0 [get_ports {s_axi_awaddr s_axi_awprot s_axi_awvalid s_axi_wdata s_axi_wvalid}] set_input_delay -clock s_axi_aclk 1.5 [get_ports {s_axi_araddr s_axi_arvalid}] # Set output delays for AXI write and read response channels set_output_delay -clock s_axi_aclk 1.5 [get_ports {s_axi_awready s_axi_wready s_axi_arready s_axi_rvalid}] set_output_delay -clock s_axi_aclk 1.0 [get_ports s_axi_rdata] # Mark all AXI ports as dont touch for timing analysis set_property DONT_TOUCH true [get_ports {s_axi_*}]关联约束文件在Flow Navigator中点击Settings。在左侧树状菜单中展开Synthesis点击Reconfigurable Partition Constraints。在右侧的Reconfigurable Partition Constraints表格中点击Add Row。在Partition Name列输入math_add_rp在Constraint File列点击Browse...选择你刚刚创建的math_add_rp.xdc文件。点击OK。提示set_property DONT_TOUCH true [get_ports {s_axi_*}]这一行是防止 Vivado 在综合时对 AXI 接口信号进行不必要的优化如常量传播从而破坏协议的时序关系。这是一个经验性的“保险丝”。4.4 运行综合、实现与比特流生成运行综合Synthesis在Flow Navigator中点击Run Synthesis。Vivado 会先对整个设计包括静态区进行综合。完成后它会自动为math_add_rp这个 RP 单独运行一次综合。你可以在Tcl Console中看到类似Running synthesis for reconfigurable partition math_add_rp的日志。运行实现Implementation综合成功后点击Run Implementation。这是 DFX 流程中最耗时的一步。Vivado 会先对静态区进行布局布线然后在静态区的布局布线结果基础上再对math_add_rp进行独立的布局布线。这个过程保证了 RP 的物理位置和布线资源与静态区是严格对齐的。生成比特流Generate Bitstream实现成功后点击Generate Bitstream。Vivado 会生成三个关键的比特流文件dfx_demo_wrapper.bit这是完整静态区的比特流包含了ZYNQ、AXI Interconnect以及所有 RP 的“壳”wrapper但不包含 RP 的实际逻辑。它用于初始配置 FPGA。math_add_rp_routed.bit这是RP 的完整比特流包含了math_add_top的所有逻辑。它用于在运行时动态加载到 RP 区域。dfx_demo_wrapper_partial.bit这是静态区的“部分比特流”它与dfx_demo_wrapper.bit内容相同但文件格式是专门为 DFX 加载准备的。提示math_add_rp_routed.bit文件的大小就是你 RP 逻辑所占用的 FPGA 资源量。你可以通过Report Utilization查看其 LUT、FF、BRAM 的使用率。一个设计良好的 RP其资源利用率应在 60%-80% 之间。过低说明资源浪费过高则可能在后续添加新功能时没有余量。4.5 验证用 SDK 和 ILA 看见 RP 的心跳比特流生成后真正的验证才开始。你需要一个软件环境来触发 RP 的加载并用硬件调试工具来观察其内部信号。导出硬件到 SDK在File-Export-Export Hardware中勾选Include bitstream导出到你的 SDK 工程目录。在 SDK 中编写加载代码创建一个简单的 C 应用程序使用 Xilinx 提供的Xil_In32和Xil_Out32函数向math_add_rp的 AXI 地址空间写入数据并读取结果。核心代码如下#define MATH_ADD_BASEADDR 0x43C00000 // Write data A and B Xil_Out32(MATH_ADD_BASEADDR 0x0004, 123); // DATA_A_REG Xil
返回列表