Skip to content

Latest commit

 

History

History
1138 lines (875 loc) · 44.6 KB

README-CN.md

File metadata and controls

1138 lines (875 loc) · 44.6 KB

全设备仿真的定制固件开发指南

目录

  1. 介绍
  2. 关键定义
  3. 设备兼容性
  4. 需求
  5. 收集捐赠设备信息
  6. 初始固件定制
  7. Vivado项目设置与定制
  8. 高级固件定制
  9. 仿真设备特定功能
  10. 事务层数据包(TLP)仿真
  11. 构建、闪存和测试
  12. 高级调试技术
  13. 故障排除
  14. 仿真精度和优化
  15. 固件开发的最佳实践
  16. 附加资源

前言

注意,你们这些盗贼渣滓。 我不是来溺爱或纵容你们可悲的阴谋的。去你妈的AQUA,也就是更广为人知的Aqua Teen Paster Force——对任何有一点诚信的人来说都是耻辱。去你妈的DIVINER,还有DUCK?去别的地方贬低自己。DMA KINGDOM?你和你们寄生的帝国以及这些骗子一起在地狱里腐烂。SHITLETTE和你们这些贪图金钱的贼人,准备迎接报应。神的愤怒?你们即将理解真正毁灭的意义。要么为你们的贪婪赎罪,要么被你们应得的毁灭席卷而去。既然我们谈到这个话题,比尔·盖茨你也去他妈的。

对于那些来学习的人,你们选择了真正启蒙的道路。你们用这本指南构建的东西将超越这些江湖骗子能梦想到的任何东西。你们正走在卓越的道路上,携手一起焚烧他们建立财富所基于的失败。


联系方式

如果您需要帮助、有疑问或希望合作,请随时联系。我可以提供指导、排除复杂问题或详细讨论想法。

Discord - VCPU | 服务器


支持我的工作

如果您觉得这本指南有帮助,并希望支持更多项目,请考虑捐助以帮助维持一切运作。每一笔捐款都能帮助我继续创建、分享和支持社区,衷心感谢。

买杯咖啡

加密捐赠(LTC)

  • MPMyQD5zgy2b2CpDn1C1KZ31KmHpT7AwRi

我通过销售固件赚得不多——大约5笔销售,总额约300美元——但我知道许多使用这本指南的人将会赚得更多。如果这本指南帮助您走上成功之路,请考虑回馈,以便我可以继续为大家提供这些资源。

特别奖励

如果您捐赠,请通过Discord(VCPU)联系我并告知。我很乐意亲自感谢您,并提供一些回报。我甚至会进行随机抽奖——无论是免费固件、私人源代码,还是一些绕过ACS的见解,都会有特别的东西给您。

您的支持对我意义重大,我们可以一起继续建设和分享未来。谢谢!


没有时间或精力自己制作固件?我提供最低60美元的固件服务。也欢迎转售商!

随时联系以获取支持或进一步讨论本指南或相关主题。无论您是需要深入帮助的开发人员,还是深入FPGA仿真的研究人员,我都在这里确保您的成功之路顺利且信息充分。让我们一起构建一些卓越的东西。

如果您不确定是否正确完成了某个步骤,或希望我审核您的实现,我会这样做,但您必须在需要审核的部分标记为 //VCPU-REVIEW// 并解释您的问题,以免浪费我的时间。

我相信你们中的很多人将超越我的能力。如果您发现了新东西或制作了一些很棒的固件,我很想看到它的实际运行。此外,我还有一些非常强大的字节和位可以分享,但如果我在这里分享,Riot PD会把我抓到警车上。

分享知识,传播充满爱的善意。愿上帝保佑。


1. 介绍

1.1 指南目的

本指南的主要目标是为开发人员、安全研究人员和硬件工程师提供必要的知识和实际步骤,以开发用于精确1:1硬件设备仿真的定制DMA固件,使用基于FPGA的系统如PCILeech-FPGA。这使得在硬件测试、系统调试、恶意软件分析以及其他需要不可检测或看似合法的设备仿真的场景中应用成为可能。

1.2 目标受众

  • 固件开发人员:为硬件仿真、测试或绕过硬件限制构建定制固件的工程师。
  • 硬件测试人员:仿真故障或过时的硬件设备,以评估系统弹性或兼容性的专业人士。
  • 安全研究人员:利用定制固件进行漏洞测试、恶意软件分析或安全评估的个人。
  • FPGA爱好者:探索FPGA定制和低级硬件仿真的爱好者。

2. 关键定义

理解术语对于有效地遵循本指南至关重要。以下是与PCIe、DMA和设备仿真相关的关键定义:

  • DMA(直接内存访问):一种允许硬件设备直接从系统内存读取或写入数据而无需CPU干预的能力,促进快速数据传输。
  • TLP(事务层数据包):PCIe架构中通信的基本单元,封装控制和数据信息。
  • BAR(基地址寄存器):PCIe设备中的寄存器,将设备内存映射到系统内存空间,定义内存和I/O地址区域。
  • FPGA(现场可编程门阵列):一种可重新配置的集成电路,可编程以执行特定的硬件功能,实现定制的设备仿真。
  • MSI/MSI-X(消息信号中断):PCIe设备用于向CPU发送中断的机制,处理异步事件。
  • 设备序列号(DSN):与特定设备相关联的唯一标识符,通常用于高级设备识别和验证。
  • PCIe配置空间:PCIe设备提供有关自身信息和配置操作参数的内存区域。
  • 捐赠卡:用于提取配置和识别详细信息以在FPGA上仿真其行为的PCIe设备。

3. 设备兼容性

3.1 支持的基于FPGA的硬件

虽然本指南主要关注**Squirrel DMA(35T)**卡,但所述方法可适用于其他基于FPGA的DMA硬件。以下是兼容设备列表:

  • Squirrel (35T)

    • 描述:价格实惠且广泛可获取的基于FPGA的DMA设备。
    • 使用案例:适用于标准内存获取和设备仿真任务。
  • EnigmaX1 (75T)

    • 描述:中档FPGA,提供增强的资源和性能。
    • 使用案例:适合需要更高带宽的更具挑战性的内存操作。
  • ZDMA (100T)

    • 描述:高性能FPGA,优化用于快速内存交互。
    • 使用案例:最适合需要快速和广泛内存读写的场景。
  • Kintex-7

    • 描述:先进的FPGA,具备强大的能力用于复杂项目。
    • 使用案例:适用于大规模或高度定制的DMA解决方案。

3.2 PCIe硬件考虑事项

为确保顺利仿真,必须解决多个PCIe特定功能:

  • IOMMU/VT-d设置

    • 建议:禁用IOMMU(英特尔的VT-d),以允许不受限制的DMA访问。
    • 理由:IOMMU可能会限制DMA操作,可能干扰内存获取和仿真。
  • 内核DMA保护

    • 建议:禁用现代系统中的内核DMA保护功能。
    • 步骤
      • Windows:这可能涉及禁用安全启动或基于虚拟化的安全性(VBS)。
      • BIOS/UEFI:访问固件设置以关闭相关安全功能。
    • 注意:禁用这些功能可能会使系统面临风险;确保在安全和隔离的环境中操作。
  • PCIe插槽要求

    • 建议:使用与FPGA设备要求匹配的兼容PCIe插槽(例如x1、x4、x16)。
    • 理由:确保与主机系统的最佳性能和兼容性。

3.3 系统要求

  • 主机系统

    • 处理器:多核CPU(Intel i5/i7或同等)
    • 内存:至少16GB RAM
    • 存储:至少100GB可用空间的SSD
    • 操作系统:Windows 10/11(64位)或兼容的Linux发行版(例如Ubuntu、Debian)及必要的驱动程序
  • 外围设备

    • JTAG适配器:用于将固件闪存到FPGA
    • PCIe插槽:确保主机系统有可用的与DMA卡兼容的PCIe插槽

4. 需求

4.1 硬件

  • 捐赠PCIe设备

    • 用途:用于欺骗的设备ID和配置数据来源。
    • 示例:网络适配器、存储控制器或任何不在主机PC上使用的通用PCIe卡。
  • DMA FPGA卡

    • 描述:能够执行DMA操作的基于FPGA的设备。
    • 示例:Squirrel (35T)、EnigmaX1 (75T)、ZDMA (100T)、Kintex-7
  • JTAG程序员

    • 用途:用于将固件闪存到FPGA。
    • 示例:Xilinx Platform Cable USB、Digilent JTAG USB Cable

4.2 软件

  • Vivado

    • 描述:Xilinx的FPGA开发软件,用于综合和构建固件项目。
    • 下载Xilinx Vivado
  • Visual Studio

  • PCILeech-FPGA

  • Arbor

    • 描述:用于收集设备信息的PCIe设备扫描工具。
    • 下载MindShare 的 Arbor
    • 注意:需要创建账户;提供14天试用。
  • 替代工具

    • Telescan PE
      • 描述:可以作为Arbor替代的PCIe流量分析工具。
      • 下载Teledyne LeCroy Telescan PE
      • 注意:免费但需要手动注册批准。

4.3 环境设置

  1. 安装Vivado

    • 步骤
      1. 访问 Xilinx Vivado 下载页面
      2. 下载与您的FPGA设备兼容的适当版本。
      3. 按照Xilinx提供的安装说明进行安装。
      4. 启动Vivado并确保其正确配置。
  2. 安装Visual Studio

    • 步骤
      1. 访问 Visual Studio 下载页面
      2. 下载并安装 Visual Studio Community Edition
      3. 在安装过程中,确保包括与使用C++进行桌面开发相关的工作负载,以支持硬件描述语言(HDL)如Verilog或VHDL。
  3. 克隆PCILeech-FPGA存储库

    • 步骤
      1. 打开终端或命令提示符。
      2. 使用Git克隆存储库:
        git clone https://github.com/ufrisk/pcileech-fpga.git
      3. 进入克隆的目录:
        cd pcileech-fpga
  4. 设置干净的开发环境

    • 建议:在隔离的环境中工作,以防止意外交互,尤其是如果使用固件进行敏感任务如恶意软件分析。
    • 步骤
      1. 使用专用的开发机器或虚拟环境。
      2. 确保没有其他应用程序干扰PCIe操作或FPGA编程。

5. 收集捐赠设备信息

精确的设备仿真依赖于从捐赠设备中提取关键信息。这些数据使您的FPGA能够在PCIe配置和行为方面模拟目标硬件。

5.1 使用Arbor进行PCIe设备扫描

Arbor是一个强大的工具,用于扫描PCIe设备并提取必要的信息。按照以下步骤收集捐赠设备的详细信息:

  1. 安装Arbor

    • 步骤
      1. 访问 Arbor下载页面
      2. 如果需要,创建一个账户。
      3. 下载并安装Arbor到您的系统上。
  2. 扫描PCIe设备

    • 步骤
      1. 启动Arbor。
      2. 导航到 本地系统 标签。
      3. 扫描选项 下,确保默认设置适当。
      4. 点击 扫描/重新扫描 以检测所有连接的PCIe设备。
  3. 识别捐赠设备

    • 标准
      • 不应在主机PC上使用。
      • 示例:PCIe WiFi卡、存储控制器或通用PCIe设备。
    • 步骤
      1. 在扫描设备列表中找到您的捐赠设备。
      2. 点击设备以查看详细配置。
  4. 捕获设备数据

    • 需要提取的信息

      • 设备ID
      • 厂商ID
      • 子系统ID
      • 修订ID
      • 基地址寄存器(BARs)
      • 功能(例如,MSI、电源管理、PCIe链路宽度/速度)
      • 设备序列号(DSN)(如果可用)
    • 步骤

      1. 导航到Arbor中的 PCI配置 标签。
      2. 滚动浏览 解码 部分,找到并记录上述详细信息。
      3. 截屏或记录每个值,以便在固件定制过程中参考。
    • 示例提取

      设备ID

      厂商ID

      修订ID

      BAR大小

      子系统ID

      DSN

    • 注意:并非所有设备都包含DSN。如果不可用,在定制过程中DSN字段使用零即可。

5.2 提取和记录设备属性

扫描后,确保准确记录捐赠设备的以下属性:

  1. 设备ID:硬件设备的唯一标识符。
  2. 厂商ID:设备制造商的标识符。
  3. 子系统ID:标识与设备相关联的特定子系统。
  4. 修订ID:硬件版本的修订号。
  5. 基地址寄存器(BARs):定义设备的内存和I/O地址区域。
  6. 功能:如电源管理(PM)、MSI/MSI-X、PCIe链路速度和宽度。
  7. 设备序列号(DSN):如果适用,与设备关联的唯一序列号。

重要注意事项

  • BAR大小:确保内存映射I/O区域与捐赠设备的配置匹配。
  • 功能:正确仿真所有功能以确保与主机系统的无缝集成。
  • DSN:提高仿真的逼真度;如果可用,请使用。

6. 初始固件定制

在掌握必要的捐赠设备信息后,继续定制固件中的PCIe配置空间和内存映射,以欺骗捐赠设备。

6.1 修改配置空间

  1. 导航到配置文件

    • 路径/PCIeSquirrel/src/pcileech_pcie_cfg_a7.sv
    • 描述:此Verilog文件包含设备的PCIe配置逻辑。
  2. 在Visual Studio中打开文件

    • 步骤
      1. 启动 Visual Studio
      2. 打开位于 /PCIeSquirrel/src/ 目录下的 pcileech_pcie_cfg_a7.sv 文件。
  3. 修改设备ID和厂商ID

    • 步骤
      1. 使用 Ctrl + F 搜索 cfg_deviceid
      2. 使用捐赠设备的值更新设备ID:
        cfg_deviceid <= 16'hXXXX;  // 将XXXX替换为捐赠设备的设备ID
      3. 同样,搜索 cfg_vendorid 并更新:
        cfg_vendorid <= 16'hYYYY;  // 将YYYY替换为捐赠设备的厂商ID
  4. 修改子系统ID

    • 步骤
      1. 搜索 cfg_subsysid
      2. 更新子系统ID:
        cfg_subsysid <= 16'hZZZZ;  // 将ZZZZ替换为捐赠设备的子系统ID
  5. 根据捐赠设备调整BARs

    • 步骤

      1. 找到BAR大小配置。
      2. 设置BAR大小以匹配捐赠设备:
        bar0_size <= 32'hXXXX_YYYY;  // 将XXXX_YYYY替换为捐赠设备的BAR0大小
      3. 根据需要重复设置其他BAR(BAR1, BAR2等)。
    • 示例

      bar0_size <= 32'h00004000;  // BAR0的16KB

6.2 插入设备序列号(DSN)

如果您的捐赠设备有设备序列号(DSN),将其纳入固件可以增强仿真的逼真度。

  1. 定位DSN字段

    • 步骤
      1. pcileech_pcie_cfg_a7.sv 中搜索 rw[127:64]
      2. 该字段代表 cfg_dsn(配置空间设备序列号)。
  2. 插入DSN

    • 步骤
      1. 用捐赠设备的DSN替换占位符:
        rw[127:64] <= 64'hXXXXXXXX_YYYYYYYY;  // 将X和Y替换为捐赠设备的DSN
      2. 示例
        • 捐赠设备DSN:上DW:01 00 00 00,下DW:68 4C E0 00
        • 组合DSN64'h01000000684CE000
        rw[127:64] <= 64'h01000000684CE000;  // 捐赠设备的DSN
      • 无DSN可用
        rw[127:64] <= 64'h0000000000000000;  // 无DSN
  3. 保存更改

    • 步骤
      1. 修改DSN后,保存文件以保留更改。

7. Vivado项目设置与定制

在定制配置空间后,将这些更改集成到Vivado项目中,以准备固件进行综合和实现。

7.1 生成Vivado项目文件

  1. 打开Vivado

    • 步骤
      1. 在您的开发机器上启动 Vivado
      2. 确保Vivado已正确安装并为您的FPGA设备配置。
  2. 访问Tcl控制台

    • 步骤
      1. 在Vivado中,找到应用程序窗口底部的 Tcl控制台
      2. 如果不可见,导航到 窗口 > Tcl控制台 以显示它。
  3. 导航到PCIeSquirrel目录

    • 步骤

      1. 在Tcl控制台中,确定当前目录:
        pwd
      2. 切换到克隆的 pcileech-fpga 存储库中的 PCIeSquirrel 文件夹:
        cd C:/Users/YourUsername/Desktop/pcileech-fpga/PCIeSquirrel
        根据您的设置替换 YourUsername 和路径。
      • 注意:如果遇到反斜杠 (\) 的错误,使用正斜杠 (/):
        cd C:/Users/YourUsername/Desktop/pcileech-fpga/PCIeSquirrel
  4. 生成Vivado项目

    • 步骤
      1. 在Tcl控制台中,执行项目生成脚本:
        source vivado_generate_project.tcl -notrace
      2. 等待脚本完成。此过程将使用必要的配置设置Vivado项目。
  5. 打开生成的项目

    • 步骤
      1. 成功生成后,Vivado应自动打开 .xpr(Vivado项目)文件。
      2. 保持项目打开以进行进一步的定制。

7.2 修改IP模块

  1. 访问PCIe IP核

    • 步骤
      1. Sources 窗格中,导航到:
        pcileech_squirrel_top > i_pcileech_pcie_a7 : pcileech_pcie_a7
        
      2. 双击PCIe IP核 (i_pcie_7x_0 : pcie_7x_0) 以打开 重新定制IP 窗口。
  2. 定制设备ID和BARs

    • 步骤
      1. 重新定制IP 对话框中,导航到 IDs 标签。
      2. 输入从捐赠设备收集的 设备ID厂商ID子系统ID
      3. 验证 类代码
        • 返回Arbor或您的扫描工具,以确定捐赠设备的类代码。
        • 重新定制IP 窗口中,设置类代码以匹配捐赠设备。
      4. 示例
        • 设备ID0x1234
        • 厂商ID0xABCD
        • 子系统ID0x5678
        • 类代码0x030000(例如,网络控制器)
  3. 配置BAR大小

    • 步骤
      1. 重新定制IP 对话框中导航到 BARs 标签。
      2. 设置 BAR0大小 以匹配捐赠设备的BAR0大小。
        • 示例:如果捐赠设备的BAR0是16KB:
          BAR0 Size: 16KB
      3. 如果捐赠设备使用了额外的BAR(BAR1、BAR2等),请重复设置。
  4. 完成IP定制

    • 步骤
      1. 设置所有必要参数后,点击 确定 以应用更改。
      2. Vivado可能会提示重新生成IP核;确认并允许过程完成。
  5. 锁定IP核

    • 目的:防止Vivado在综合过程中覆盖手动配置。
    • 步骤
      1. 打开Vivado中的 Tcl控制台
      2. 执行以下命令以锁定IP核:
        set_property is_managed false [get_files pcie_7x_0.xci]
      3. 解锁(如果将来需要):
        set_property is_managed true [get_files pcie_7x_0.xci]

8. 高级固件定制

为了实现精确的1:1仿真,进一步定制PCIe参数、BARs、内存映射、电源管理和中断处理。

8.1 配置用于仿真的PCIe参数

  1. 匹配PCIe链路速度和宽度

    • 重要性:确保仿真设备以与捐赠设备相同的速度和宽度进行通信。
    • 步骤
      1. pcileech_pcie_cfg_a7.sv 中,找到PCIe链路速度和宽度配置。
      2. 更新这些参数以匹配捐赠设备的规格。
        pcie_link_speed <= 4'bXXXX;  // 将XXXX替换为捐赠设备的PCIe链路速度
        pcie_link_width <= 8'b00000100;  // 将其替换为捐赠设备的PCIe链路宽度(例如x1、x4、x8)
      • 示例
        • 捐赠设备PCIe链路速度:Gen3(8 GT/s)
        • 捐赠设备PCIe链路宽度:x4
          pcie_link_speed <= 4'b0011;  // Gen3
          pcie_link_width <= 8'b00000100;  // x4
  2. 设置能力指针

    • 目的:确保PCIe功能正确链接并被主机系统识别。
    • 步骤
      1. pcileech_pcie_cfg_a7.sv 中找到能力指针配置。
      2. 设置能力指针以匹配捐赠设备的配置。
        capability_pointer <= 8'h40;  // 示例值;根据捐赠设备的能力指针替换

8.2 调整BAR和内存映射

精确的内存映射对于仿真硬件设备至关重要。基地址寄存器(BARs)定义设备的内存和寄存器在系统内存空间中的位置。

  1. 设置BAR大小

    • 步骤
      1. pcileech_pcie_cfg_a7.sv 中,找到BAR大小分配。
      2. 将BAR大小设置为与捐赠设备匹配。
        bar0_size <= 32'h00004000;  // BAR0的16KB
        bar1_size <= 32'h00008000;  // BAR1的32KB(如果适用)
  2. 定义BAR地址空间

    • 步骤
      1. 确保BAR地址空间不重叠,并与捐赠设备的内存布局匹配。
      2. 使用记录的BAR大小适当地设置地址范围。
        bar0_addr <= 32'hF0000000;  // 示例地址;根据捐赠设备的BAR0地址替换
        bar1_addr <= 32'hF0004000;  // 示例地址;根据需要替换
  3. 处理多个BAR

    • 步骤
      1. 如果捐赠设备使用多个BAR,请重复配置每个BAR。
      2. 确保每个BAR的大小和地址与捐赠设备的规格一致。

8.3 仿真设备电源管理和中断

正确仿真电源管理和中断处理确保主机系统与仿真设备无缝交互。

  1. 电源管理(PM)配置

    • 步骤
      1. pcileech_pcie_cfg_a7.sv 中,找到电源管理能力设置。
      2. 设置PM能力以匹配捐赠设备。
        PM_CAP_VERSION <= 4'b0011;  // 示例版本;根据捐赠设备的PM版本替换
        PM_CAP_D1SUPPORT <= 1'b1;   // 如果捐赠设备支持D1,则启用
        PM_CAP_AUXCURRENT <= 4'b1000; // 示例值;根据捐赠设备调整
        PM_CSR_NOSOFTRST <= 1'b0;   // 示例值;根据需要调整
  2. MSI/MSI-X(中断)配置

    • 步骤
      1. pcileech_pcie_cfg_a7.sv 中找到MSI/MSI-X配置。
      2. 启用并配置MSI/MSI-X以正确处理中断。
        MSI_CAP_64_BIT_ADDR_CAPABLE <= 1'b1;  // 如果支持,启用64位MSI
        cfg_interrupt <= 1'b1;               // 启用MSI中断
  3. 实现中断处理逻辑

    • 步骤
      1. pcileech_pcie_cfg_a7.sv 中,确保中断信号正确路由。
        assign cfg_interrupt_di = cfg_int_di;
        assign cfg_interrupt_assert = cfg_int_assert;
      2. 测试中断功能,确保主机系统正确接收和处理来自仿真设备的中断。

9. 仿真设备特定功能

为了实现真正的1:1仿真,除了基本的PCIe交互之外,还必须复制捐赠设备的独特功能。

9.1 实现高级PCIe功能

大多数PCIe设备支持高级错误报告(AER)链路速度协商扩展能力等高级功能。仿真这些功能确保主机系统将仿真设备视为与捐赠设备相同。

  1. 高级错误报告(AER)

    • 步骤
      1. pcileech_pcie_cfg_a7.sv 中,找到AER配置。
      2. 如果捐赠设备支持,启用AER。
        AER_CAP_VERSION <= 4'b0001;  // 示例版本;根据捐赠设备的AER版本替换
        AER_CAP_NEXTPTR <= 8'h00;    // 适当地设置下一个指针
      3. 实现错误处理逻辑以管理与AER相关的事件。
  2. 链路速度协商

    • 步骤
      1. 确保PCIe链路速度和宽度协商与捐赠设备匹配。
      2. 8.1 所述,调整链路速度设置。
  3. 扩展能力

    • 步骤
      1. 确定捐赠设备使用的任何扩展能力(例如,厂商特定的扩展能力、LTR、VSEC)。
      2. 通过在 pcileech_pcie_cfg_a7.sv 中定义适当的寄存器和逻辑,实现场这些能力。
        // 示例:厂商特定的扩展能力
        VSEC_CAP_ID <= 16'hXXXX;       // 将XXXX替换为厂商特定的ID
        VSEC_CAP_VERSION <= 8'hYY;    // 将YY替换为版本
        VSEC_CAP_NEXTPTR <= 8'hZZ;    // 下一个能力指针

9.2 仿真厂商特定功能

一些设备包含专有或厂商特定的功能,必须准确仿真以确保与主机系统的无缝集成。

  1. 识别厂商特定功能

    • 步骤
      1. 使用PCIe流量分析工具(例如,Wireshark、Teledyne LeCroy)监控厂商特定的TLP。
      2. 记录捐赠设备在典型操作中使用的独特寄存器、命令或行为。
  2. 实现厂商特定逻辑

    • 步骤
      1. pcileech_pcie_cfg_a7.sv 中,添加逻辑以处理厂商特定功能。
        // 示例:厂商特定寄存器
        vendor_specific_reg <= 32'hXXXXXXXX;  // 将其替换为实际值
      2. 确保任何专有命令或响应被准确复制。
  3. 测试厂商特定功能

    • 步骤
      1. 使用厂商特定的驱动程序或应用程序与仿真设备交互。
      2. 验证所有专有功能是否按预期运行。

10. 事务层数据包(TLP)仿真

准确仿真事务层数据包(TLP)对于确保基于FPGA的设备与主机系统无缝通信至关重要,模仿捐赠设备的行为。

10.1 理解和捕获TLP

TLP是PCIe通信的基本单元,处理内存读写、配置访问和中断信号。

  1. 从捐赠设备捕获TLP

    • 步骤
      1. 使用PCIe分析工具如 Teledyne LeCroy的Telescan PE 或支持PCIe的 Wireshark 监控捐赠设备生成的TLP。
      2. 记录捐赠设备在典型操作中使用的TLP的结构、类型和模式。
  2. 分析TLP结构

    • TLP的组成部分

      • 头字段:定义类型、格式、地址和其他控制信息。
      • 数据载荷:实际传输的数据。
      • 尾字段:附加信息,如字节计数和序列号。
    • 示例TLP结构

      tlps_static.tdata[127:0] = {TLP头字段, 数据载荷};
  3. 仿真合法流量

    • 步骤
      1. 确保FPGA生成的TLP在类型、地址、长度和数据方面与捐赠设备捕获的TLP一致。
      2. 实现处理不同类型TLP的逻辑,如内存写、内存读和配置访问。

10.2 为特定操作制作自定义TLP

为了准确模仿捐赠设备,您必须制作自定义TLP,以复制其在各种操作中的行为。

  1. 内存写TLP示例

    • 描述:表示对系统内存的写操作。
    • Verilog示例
      tlp_mem_write <= {
          1'b0,                    // 保留位
          7'b10_00000,             // TLP类型:内存写
          1'b0,                    // TLP格式
          address[31:0],           // 写入地址
          data[31:0]               // 数据载荷
      };
  2. 内存读TLP示例

    • 描述:表示从系统内存的读操作。
    • Verilog示例
      tlp_mem_read <= {
          1'b0,                    // 保留位
          7'b00_00000,             // TLP类型:内存读
          1'b0,                    // TLP格式
          address[31:0],           // 读取地址
          tag[7:0]                 // 事务识别标签
      };
  3. 配置访问TLP示例

    • 描述:表示配置空间访问。
    • Verilog示例
      tlp_config_access <= {
          1'b0,                    // 保留位
          7'b01_00000,             // TLP类型:配置读/写
          1'b0,                    // TLP格式
          config_address[31:0],    // 配置空间地址
          config_data[31:0]        // 配置数据载荷
      };
  4. 中断信号TLP示例

    • 描述:表示向CPU发送中断信号。
    • Verilog示例
      tlp_interrupt <= {
          1'b0,                    // 保留位
          7'b11_00000,             // TLP类型:中断
          1'b0,                    // TLP格式
          interrupt_address[31:0], // 与中断相关的地址
          interrupt_data[31:0]     // 中断数据载荷
      };
  5. 实现TLP处理器

    • 步骤
      1. 在固件中,实现不同TLP类型的处理器,以确保正确处理和响应。
      2. 使用状态机或逻辑块管理TLP生成、处理和响应处理。

11. 构建、闪存和测试

在定制固件并确保所有配置与捐赠设备一致后,继续在您的FPGA设备上构建、闪存和测试固件。

11.1 综合与实现

  1. 运行综合

    • 步骤
      1. 在Vivado中,点击 运行综合
      2. 监控综合过程中的任何警告或错误。
      3. 在继续之前解决任何关键问题。
  2. 运行实现

    • 步骤
      1. 综合成功后,启动 运行实现
      2. 确保实现阶段在没有关键警告的情况下完成。
      3. 查看实现报告以识别任何潜在问题。
  3. 生成比特流

    • 步骤
      1. 一旦实现完成,点击 生成比特流
      2. 确认生成比特流的任何提示。
      3. 等待比特流生成成功完成。

11.2 闪存比特流

  1. 通过JTAG连接FPGA

    • 步骤
      1. 确保您的FPGA设备通过JTAG接口连接到主机系统。
      2. 为FPGA设备供电。
  2. 打开Vivado硬件管理器

    • 步骤
      1. 在Vivado中,导航到 窗口 > 硬件管理器
      2. 点击 打开目标 > 自动连接 以检测连接的FPGA设备。
  3. 编程FPGA

    • 步骤
      1. 在硬件管理器中,右键点击检测到的设备并选择 编程设备
      2. 浏览到生成的比特流文件(pcileech_squirrel_top.bit)。
      3. 点击 编程 以将固件闪存到FPGA。
      4. 通过硬件管理器控制台确认编程成功。

11.3 测试与验证

  1. 验证设备检测

    • 步骤

      1. 使用 lspci(在Linux上)或 设备管理器(在Windows上)验证FPGA是否被检测为捐赠设备。
      2. 确认 设备ID厂商ID子系统IDBARs 是否与捐赠设备的规格匹配。
    • 示例(Linux)

      lspci -vvv -s <PCI地址>
  2. 内存映射测试

    • 步骤
      1. 访问设备的 BARs 以确保正确的内存映射。
      2. 使用内存访问工具或简单的读写操作测试响应性。
  3. 中断测试

    • 步骤
      1. 通过仿真设备触发中断。
      2. 验证主机系统是否正确接收和处理这些中断。
      3. 使用系统日志或诊断工具确认中断处理。
  4. 性能测试

    • 步骤

      1. 运行DMA速度测试工具以测量数据传输速率。
      2. 将性能指标与预期值进行比较,以确保固件的稳定性和效率。
    • 示例工具

      • PCILeech DMA速度测试:在PCILeech工具集中可用。
      • 自定义基准测试脚本:执行读写操作以测量性能。
  5. 配置空间验证

    • 步骤

      1. 使用诊断工具检查PCIe配置空间。
      2. 确保所有字段(设备ID、厂商ID、BARs、功能)正确设置并与捐赠设备匹配。
    • 示例(Linux)

      lspci -vvv -s <PCI地址>

12. 高级调试技术

在开发定制固件时,遇到问题是常见的。高级调试技术可以帮助有效地识别和解决这些问题。

12.1 使用Vivado的集成逻辑分析仪

Vivado的**集成逻辑分析仪(ILA)**允许实时监控内部FPGA信号,有助于调试和验证。

  1. 设置ILA探针

    • 步骤
      1. 在Vivado中,导航到 Sources > 添加源 并添加一个 集成逻辑分析仪
      2. 在PCIe通信路径的关键点插入ILA探针,例如TLP生成器或BAR访问控制器。
        // 示例:为TLP数据添加ILA探针
        wire [127:0] tlp_data;
        assign tlp_data = tlps_static.tdata[127:0];
        ila_0 probe (
            .clk(clk),
            .probe0(tlp_data)
        );
  2. 配置触发器

    • 步骤
      1. 打开 ILA 配置对话框。
      2. 根据特定事件设置触发条件,例如TLP生成或内存访问。
        // 示例触发条件:内存写TLP的开始
        if (tlp_type == MEMORY_WRITE && tlp_valid) begin
            trigger_signal <= 1;
        end
  3. 分析信号波形

    • 步骤

      1. 启用ILA探针运行FPGA。
      2. 使用Vivado的 波形查看器 检查捕获的信号波形。
      3. 识别时序问题、不正确的逻辑状态或意外行为。
    • 优势

      • 实时查看内部信号。
      • 能够捕获和分析TLP处理过程中的瞬态问题。

12.2 PCIe流量分析工具

除了Vivado的ILA,外部PCIe流量分析工具提供了深入了解FPGA与主机系统之间PCIe通信的能力。

  1. 带有PCIe扩展的Wireshark

    • 描述:Wireshark可以通过适当的扩展或插件捕获和分析PCIe流量。
    • 步骤
      1. 安装带有PCIe支持的Wireshark。
      2. 配置Wireshark以捕获PCIe流量。
      3. 分析捕获的TLP,以确保其符合预期的捐赠设备行为。
  2. Teledyne LeCroy Telescan PE

    • 描述:专业级PCIe流量分析工具,提供全面的PCIe流量监控和分析功能。
    • 步骤
      1. 安装Teledyne LeCroy的Telescan PE。
      2. 将其连接到您的系统以监控PCIe流量。
      3. 使用其分析功能捕获和解析FPGA与主机系统之间交换的TLP。
  3. Total Phase Beagle

    • 描述:PCIe流量分析仪,允许实时捕获和分析PCIe通信。
    • 步骤
      1. 使用Total Phase Beagle PCIe分析仪设置您的系统。
      2. 配置其以监控和捕获PCIe流量。
      3. 使用其分析功能验证TLP的完整性和行为。

使用PCIe流量分析工具的优势

  • 全面的TLP分析:详细检查TLP,确保准确的仿真。
  • 错误检测:识别格式错误的TLP或意外的事务模式。
  • 性能指标:测量数据传输速率并识别瓶颈。

13. 故障排除

在固件开发过程中遇到问题是常见的。本节提供了在仿真过程中可能遇到的常见问题的解决方案。

13.1 设备检测问题

问题:主机系统未能检测到FPGA作为捐赠设备。

解决方案

  1. 验证设备ID

    • 步骤
      1. 仔细检查固件中的 设备ID厂商ID子系统ID 是否与捐赠设备匹配。
      2. 确保配置空间中没有拼写错误或不正确的值。
  2. 检查PCIe链路训练

    • 步骤
      1. 使用PCIe诊断工具验证PCIe链路是否正确训练。
      2. 确保链路速度和宽度配置与捐赠设备匹配。
  3. 确保正确的BAR配置

    • 步骤
      1. 确认 BAR大小地址范围 是否准确设置。
      2. 确保没有重叠或冲突的BAR配置。
  4. 电源和连接检查

    • 步骤
      1. 确保FPGA设备已正确连接并通电。
      2. 重新插拔PCIe卡以确保连接牢固。

13.2 内存映射和BAR配置错误

问题:不正确的内存映射导致内存访问失败或不准确。

解决方案

  1. 仔细检查BAR大小和地址

    • 步骤
      1. 验证固件中的每个BAR大小是否与捐赠设备的配置匹配。
      2. 确保BAR地址空间设置正确且不重叠。
  2. 使用诊断工具

    • 步骤
      1. 利用 lspciArbor 等工具检查PCIe配置空间。
      2. 确认BARs是否正确映射并可访问。
  3. 调整内存区域

    • 步骤
      1. 如果内存区域不可访问,调整BAR配置以更好地匹配系统的内存映射。
      2. 确保固件逻辑正确处理内存读/写操作。

13.3 DMA性能和TLP错误

问题:DMA性能缓慢或与事务层数据包(TLP)相关的错误。

解决方案

  1. 优化TLP生成

    • 步骤
      1. 确保TLP格式正确且无错误。
      2. 使用Vivado的ILA和PCIe流量分析工具识别并修正格式错误的TLP。
  2. 调整有效载荷大小

    • 步骤
      1. 将最大读取请求和有效载荷大小设置为4KB或捐赠设备支持的最高值。
        max_read_request_size <= 4;  // 4KB
        max_payload_size <= 4;       // 4KB
      2. 避免设置超出捐赠设备支持的有效载荷大小,以防止系统不稳定。
  3. 检查PCIe链路设置

    • 步骤
      1. 验证PCIe链路速度和宽度是否正确配置。
      2. 确保FPGA与主机系统准确协商链路参数。
  4. 固件完整性

    • 步骤
      1. 审查并验证固件的所有最近更改,确保没有引入无意的修改。
      2. 如果性能问题持续存在,恢复到已知稳定的固件版本。

14. 仿真精度和优化

确保仿真的精度对于无缝集成和不可检测的行为至关重要。本节概述了提高仿真精确度和优化性能的技术。

14.1 精确时序仿真的技术

匹配捐赠设备的时序特性确保主机系统与仿真设备交互时如同与原始硬件设备一样。

  1. 使用匹配的时钟域

    • 步骤
      1. 确保FPGA的时钟与PCIe链路的时钟速率匹配。
      2. 同步FPGA内部的时钟,以符合PCIe时序要求。
  2. 控制响应延迟

    • 步骤
      1. 实现寄存器或计数器,以管理TLP确认和中断处理的响应时间。
      2. 确保响应延迟与捐赠设备的典型响应时间匹配。
  3. 实现流水线阶段

    • 步骤
      1. 在FPGA设计中使用流水线技术,以与捐赠设备的数据处理阶段对齐。
      2. 这减少了延迟,并确保及时的TLP生成和处理。

14.2 对系统调用的动态响应

基于系统交互仿真设备的动态行为,确保FPGA设备在各种条件下适当响应。

  1. 实现状态机

    • 步骤
      1. 在FPGA中设计状态机,以管理仿真设备的不同操作状态。
      2. 确保状态之间的过渡基于系统调用和交互,模仿捐赠设备的行为。
  2. 跟踪并响应系统请求

    • 步骤
      1. 监控传入的系统请求,并动态调整设备的响应。
      2. 确保FPGA固件能够处理不同的工作负载,并准确响应不同类型的TLP。
  3. 处理异步事件

    • 步骤
      1. 实现逻辑,以管理异步事件如中断或错误条件。
      2. 确保固件能够以与捐赠设备一致的方式生成和响应这些事件。

15. 固件开发的最佳实践

遵循最佳实践确保开发过程高效、可维护且安全。

15.1 持续测试和文档记录

  • 频繁测试

    • 步骤
      1. 每次修改后进行定期测试,以确保固件按预期运行。
      2. 使用自动化脚本或测试台持续验证固件功能。
  • 记录更改

    • 步骤
      1. 为固件的每次更改保持详细的文档记录。
      2. 包括更改的原因及其对整体设计的影响。

15.2 管理固件版本

  • 使用版本控制

    • 步骤
      1. 实施版本控制系统(例如 Git),以管理固件的不同迭代版本。
      2. 定期提交更改,并附上描述性消息,以跟踪项目的演变。
  • 分支策略

    • 步骤
      1. 使用分支管理功能开发、修复漏洞和实验性更改。
      2. 仅在彻底测试后将稳定分支合并到主分支。

15.3 安全考虑

  • 防止未经授权的访问

    • 步骤
      1. 确保固件不会将系统内存或硬件暴露给未经授权的访问。
      2. 在固件中实施访问控制和验证检查。
  • 保护固件完整性

    • 步骤
      1. 避免在固件开发过程中引入漏洞或后门。
      2. 定期进行安全审查和代码审计,以维护固件的完整性。
  • 安全处理敏感数据

    • 步骤
      1. 如果固件与敏感数据交互,实施加密和安全的数据处理实践。
      2. 确保通过固件接口或日志不泄露敏感信息。

16. 附加资源

为了进一步提升您在开发用于设备仿真的定制固件方面的理解和能力,以下资源非常宝贵: