主页 > imtoken安卓官方版 > 使用 Zynq SoC 实现高效的比特币挖掘系统

使用 Zynq SoC 实现高效的比特币挖掘系统

imtoken安卓官方版 2023-01-16 23:34:29

亚历山大·斯坦德里奇

硕士研究生

加州大学北岭分校 asstandridge@gmail.com

何嘉文

硕士研究生

加州大学北岭分校 calvin.ho.67@my.csun.edu

沙纳姆·米尔扎伊

助理教授

加州大学北岭分校 shahnam.mirzaei@csun.edu

拉明公鸡

教授

比特币的矿机_比特币矿机商城_比特币矿机品牌

加州大学北岭分校 ramin.roosta@csun.edu

将可编程逻辑和处理器子系统集成到单个设备中,可以开发适应性强且价格合理的比特币采矿设备。

比特币是一种虚拟货币,在过去几年中越来越受欢迎。 因此,比特币的追随者以购买或“挖掘”比特币的形式投资他们的部分资产以支持该货币。 挖矿是使用计算机硬件对比特币网络进行数学计算的过程。 提供服务的比特币矿工将获得一笔费用(目前为 25 个比特币)加上任何嵌入式交易费用。 由于网络奖励是根据所有矿工完成的计算来分配的,因此挖矿竞争异常激烈。

比特币挖矿最初是在 CPU 和 GPU 等低成本硬件上运行的软件进程。 但随着比特币的流行,挖矿过程发生了戏剧性的转变。 早期的矿工不得不使用耗电的处理器来达到令人满意的“哈希率”或挖掘速度。 虽然 CPU/GPU 挖矿效率很低,但它足够灵活以适应比特币协议的变化。 近年来,挖矿活动的重点已慢慢转移到专用或半专用 ASIC 硬件上,以优化和实现高效的“哈希速度”。 切换到这种硬件提高了挖矿效率,但代价是适应挖矿协议变化的灵活性降低。

ASIC 是用于特定应用程序以有效执行特定任务的专用硬件。 虽然 ASIC 比特币矿机的成本相对较低,由此产生的“哈希速度”也相当不错,但代价是灵活性降低,难以适应协议的变化。

与ASIC类似,FPGA也可以作为高效矿机系统,成本相对较低。 此外,FPGA 比 ASIC 更灵活,可以适应比特币协议的变化。 当前的挑战是设计一个完全高效和灵活的挖矿系统,可以在不依赖 PC 主机或中继设备的情况下连接到比特币网络。 我们的团队使用 Xilinx Zynq-7000 All Programmable SoC 成功完成了这项任务。

大概的概念

要设计一个由可行的比特币节点、高效灵活的矿机等组成的完整挖矿系统,我们需要某种功能强大的 FPGA 芯片来同时满足灵活性和性能要求。 除了FPGA,我们还需要使用处理引擎来提高效率。

在这个完整的片上系统 (SoC) 上,我们需要优化的内核来运行所有必需的比特币任务,包括网络维护和交易处理。 满足所有这些标准的硬件是 ZedBoard 开发板上的 Zynq-7020 SoC。 ZedBoard 的价格约为 300 到 400 美元,与同类产品相比相当便宜(参见 参考资料)。

Zynq-7020 SoC 芯片集成了两个 ARM® Cortex™-A9 处理器和 85,000 个 Artix®-7 FPGA 逻辑单元。 ZedBoard开发板还内置了512MB DDR3内存,可以让我们更快的运行SoC设计。 最后,ZedBoard 还提供了一个 SD 卡槽用于大容量存储,这样我们就可以将整个更新的比特币程序存储在 SD 卡上。

我们使用 ZedBoard 实现了我们的 SoC 比特币矿工。 它由主机、中继器、驱动程序和矿工组成。 我们使用原始比特币客户端的非图形界面作为主机与比特币网络进行交互。 中继使用驱动程序将工作从主机传递给矿工。

比特币矿机品牌_比特币的矿机_比特币矿机商城

简单来说,比特币挖矿过程可以归结为 SHA-256 过程和比较器的组合。 SHA-256 进程负责对区块头信息进行双重处理,然后将其与比特币网络的扩容目标难度进行比较。

矿芯深度

我们开始根据美国商务部 SHA-256 规范使用 Vivado® HLS(高层次综合)开发挖矿核心。 利用Vivado HLS的快速行为测试能力,我们快速完成了多个原型挖矿内核的布局,从简单的单进程系统到复杂的多进程系统。 但在深入研究挖矿内核的详细结构之前,了解 SHA-256 过程的基本知识会很有帮助。

SHA-256 通过 64 次移位、加法和异或运算迭代从 64 字节数据生成 32 字节哈希值。 在这个操作过程中,8个4字节的寄存器用来保存每一轮迭代的结果。 当这个过程完成时,四个寄存器被连接起来生成散列值。 如果输入数据小于63字节,则填充为63字节,第64字节用来存放输入数据的长度。 更常见的情况是输入数据的长度大于 63 字节。

在这种情况下,数据被填充到最接近的 64 的倍数,最后一个字节保留用于存储数据长度。 每个64字节的数据块都使用前一个数据块的输出(也称为中间状态)作为下一个数据块的基础,依次运行SHA-256过程。

使用 Vivado HLS,SHA-256 过程是一个简单的“for”循环设计:一个数组保存每次迭代所需的常量,另一个数组保存后续迭代所需的临时值,8 个变量保存每次迭代,并定义逻辑运算。 如图2所示。

比特币的矿机_比特币矿机品牌_比特币矿机商城

简单来说,比特币挖掘过程可以归结为 SHA-256 过程和比较器的组合。 SHA-256 进程负责对区块头信息进行双重处理,然后将其与比特币网络的扩容目标难度进行比较,如图 3A 所示。 这个简单的概念在硬件中实现起来很复杂,因为第一个版本的比特币块头有 80 个字节长。 这意味着初始路径需要运行两次 SHA-256 进程,而后续路径只需运行一次,如图 3B 所示。 这种定义两个单独的 SHA-256 模块的双重路径会使情况复杂化,因为我们需要使 SHA-256 模块尽可能通用以节省开发时间并实现重用。 这个对SHA-256模块的一般要求决定了我们使用的输入输出,可以设置为32字节的初始值,64字节的数据,32字节的哈希值。 因此,在隔离 SHA-256 进程的内核端之后,我们可以按照自己喜欢的方式布置这些输入。

比特币矿机商城_比特币的矿机_比特币矿机品牌

我们开发的三个原型中的第一个使用单个 SHA-256 处理模块。 我们从一开始就知道这个核心是三个核心中最慢的,因为没有使用管道。 但我们想看看最小的 SHA-256 进程是多少。

第二个原型构建了三个串联的独立 SHA-256 处理模块,如图 3C 所示。 当第一个进程处理标头的前 64 个字节时,此配置允许静态类型化。 第二个进程处理标头中剩余的 16 个字节以及填充数据所需的 48 个字节。 第三个进程负责处理前两个进程得到的哈希值结果。 这三个独立的过程简化了控制逻辑并允许使用简单的流水线。

比特币的矿机_比特币矿机品牌_比特币矿机商城

第三个也是最后一个原型使用两个 SHA-256 进程模块,并利用比特币挖矿社区使用的比特币标头和挖矿进程中的专用补丁。 该数据头信息仅在修改模块以更改前 64 个字节时才会布局。 这意味着一旦处理完前 64 个字节,就可以保存输出数据(中间状态),只处理数据头中的最后 16 个字节,这可以大大提高散列速度(见图 3D)。

比较器是关键组件,可以通过适当的设计显着提高性能。 解决方案是一个小于比特币系统定义的 32 字节扩展目标难度的哈希值。 这意味着必须比较生成的每个哈希,等待是否可以找到解决方案。 由于有用于扩展目标难度配对的专用补丁,因此无论难度如何,前四个字节始终为 0。 随着网络难度的增加,前导零的数量也会增加。 在撰写本文时,扩展目标难度的前 13 个字节均为零。 因此,除了将整个哈希与目标难度进行比较之外,我们还需要检查第一个字节中有多少是零。 如果它们为零,我们将哈希值与目标难度进行比较。 如果它们不为零,我们需要丢弃这个散列并重新开始。

在清理了各种现有原型的结果后,我们最终选择了比特币开源社区为Xilinx FPGA开发的第三核。

伊势发展

比特币挖矿是一场寻找 0 到 232-1 之间可解数字的竞赛。 因此,提高挖矿核心性能的方法实际上只有两种:加快处理速度或分而治之。 我们使用 Spartan®-3 和 Spartan-6 开发板测试了一系列不同的频率、流水线技术和并行化方法。

下面开始用Spartan-3E开发板进行频率测试。 但很快就变得很明显,超过 50MHz 就无能为力了。 为此,我们不得不使用Spartan-6来完成频率测试。

我们在Spartan-6开发板上测试了50、100和150MHz三种不同的频率,得到了可以预见的结果,分别得到0.8MHps、1.6MHps和2.4MHps。 我们还在并行化和流水线测试中尝试了 75MHz 和 125MHz,但这两个频率只是为了让矿工适应 Spartan-6 而做出的妥协。

我们选择开源社区挖矿核心的原因之一是它的设计理念是使用深度变量来控制流水线的阶段数。 深度是一个0到6之间的指数值,它以2的幂控制VHDL“生成”命令的执行次数,即20到26次。 我们初始频率测试的深度为0,即每个进程只执行一轮。

在 Spartan-3e 上,我们测试了深度 0 和 1,直到遇到时序限制。 深度 0 在 50MHz 时可以获得大约 0.8MHps,深度 1 可以获得大约 1.6MHps。

在 Spartan-6 上,我们可以在运行到时间约束之前达到 3 的深度。 在深度为 0 和 1 的情况下以 50MHz 运行,Spartan-6 给出与 Spartan3 相同的结果。 在这一点上比特币矿机品牌,我们注意到一个有趣的趋势。 将频率加倍与增加流水线深度具有相同的效果。 上限由可用路由资源决定,峰值平均值约为3.8MHps,如图4所示。

比特币的矿机_比特币矿机品牌_比特币矿机商城

比特币矿机商城_比特币矿机品牌_比特币的矿机

SHA-256处理模块需要完成10次不同的32位加法。 在这个设计中,我们尽量在一个时钟周期内完成所有的加法运算。 为了缩短最长路径,我们尝试将加法器链细分为一系列阶段。 但这样做会显着改变整个核心的控制逻辑,需要完全重写。 我们放弃了这些修改以节省时间和精力。

我们测试的最后一个性能改进方法是并行化。 稍微修改一下,SHA-256 组的数量可以增加一倍和四倍。 每组由两个 SHA-256 处理模块组成。 对于组数翻倍的SHA-256,这种调整有效地将组数减半; 对于将组数翻两番的 SHA-256,它是四分之一。 为了让这些额外的 SHA 进程在 Spartan-6 上运行,我们必须降低系统频率。 四组 SHA-256 处理模块以 75MHz 运行,两组以 125MHz 运行。 哈希速度的提高很难记录下来。 我们可以很容易地看到单个 SHA-256 组的哈希速度,但是由多个 SHA-256 组组成的挖掘内核可以比隐含的哈希速度更快地找到解决方案。

使用EDK

FPGA 测试完成后,下一步就是将挖矿核心连接到 Zynq SoC 的 AXI4 总线上。 Xilinx 嵌入式开发套件 (EDK) 预加载了专为 Zynq SoC 设计的配置实用程序,使我们能够轻松配置各个方面。 默认情况下,系统启用了 512MB DDR3、以太网、USB 和 SD 接口,这是比特币 SoC 所需的全部。

两个 Cortex-A9 处理器使用 AXI4 接口,而不是以前软核系统中使用的 PLB 系统。 所有外设都通过 AXI4 接口连接到处理器,如图 5 所示。

比特币矿机品牌_比特币矿机商城_比特币的矿机

EDK Custom Peripheral Wizard为AXI4接口的不同变体提供存根代码,作为矿芯AXI接口开发的基础。 为简单起见,我们使用AXI4-Lite接口为挖矿核心提供简单的读写功能。 理想情况下,开发人员会希望使用标准 AXI4 接口来利用高级接口控制功能,例如数据突发。

为了简单起见,我们使用三个内存映射寄存器来处理挖矿核心的I/O。 第一个寄存器负责将主机数据包提供给矿工。 该寄存器记录传递的数据量,传递完第11个字后自锁。 找到解决方案后比特币矿机品牌,锁将自动解锁。 如有必要,也可以通过状态寄存器手动解锁。

我们将第二个寄存器作为状态寄存器,标记特定的位来表示矿核在运行过程中所处的不同状态。 鉴于我们设计的简单性,我们只使用了三个标志,加载标志、运行标志和发现标志。 当挖矿核心接收到 11 个字时,加载标志被触发,并且如前所述,当我们写入它时,它被清除。 启动/运行标志在挖矿内核启动时设置,并在找到解决方案时由挖矿内核清除。 最后一个寄存器是输出寄存器,用于加载找到的解决方案。

在添加这个新组件之前,我们测试了 AXI4-Lite 接口开发的每个阶段。 我们还使用准系统 Xilinx 软件开发套件测试了 AXI4-Lite 接口。 测试有两个目的:一是确认矿芯AXI4-Lite接口是否正常工作; 第二,确保挖矿核心以正确的字节顺序格式接收数据。

为了在不牺牲适应性的情况下改进我们当前的设计,我们计划添加更多连接到比特币主节点的挖矿核心。 添加更多的挖矿核心可以显着提高性能并加快整体哈希率。

比特币矿机商城_比特币的矿机_比特币矿机品牌

嵌入式Linux

将挖矿核心与处理器连接后,我们就转入软件开发工作。 理想的考虑是使用 Linux 内核构建我们自己的固件以获得最佳性能。 为了简化开发工作,我们安装了完整的 Linux 发行版。 我们使用Xillybus开发的Xillinux,它是Ubuntu的衍生版本,用于快速完成嵌入式系统开发。

我们的首要任务是为 Cortex-A9 架构编译 Bitcoind。 我们使用原始的开源比特币软件来保证与比特币网络的兼容性。

测试比特币是一件简单的事情。 我们先运行后台程序,等待一个大型数据库链的下载,然后使用line命令启动Bitcoind内置的CPU挖矿软件。

对于 Linux 驱动程序,必须实现一部分专用功能并将其链接到 Linux 内核才能正常运行。 当加载了特定初始化函数的驱动程序运行时,准备系统与硬件交互。 在这个函数中,我们首先确认挖矿内核要链接到的内存地址可以使用,然后保留该地址。 与准系统不同,Linux 使用虚拟内存寻址方案,即在我们使用保留地址之前,我们必须首先请求挖矿核心的地址重新映射。 内核会通过重映射为我们提供一个虚拟地址,供我们与挖矿内核寄存器进行通信。

现在我们可以使用这个硬件了,然后初始化函数对挖矿核心进行简单的测试,以确认核心是否正常工作。 如果功能正常,则注册核心寄存器的主要和次要编号,以在用户程序中识别设备。 每个函数都有一个计数器,退出函数就是初始化函数的计数器。 使用此功能时,我们撤消初始化期间所做的一切,特别是释放驱动程序使用的主要和次要编号,然后释放映射的虚拟地址。

当我们第一次从中继程序调用挖矿内核时,开启功能开始工作。 我们在这里所做的只是确认初始化期间功能自检的成功。 如果自检失败,我们给出系统错误信息并在失败时退出。 当设备从中继程序中释放时调用关闭函数。 但是由于我们在open函数中只是查看自检结果,所以在close函数中无事可做。 read函数负责查看数据缓存,判断用户是从哪个端口读取的,然后从挖矿核心获取数据并发回。 write函数负责判断用户正在写入的寄存器,然后将数据传递给挖矿核心。

我们系统的最后一个组件是一个小型中继程序,用于通过驱动程序将工作从 Bitcoind 传递到挖矿内核,并将发送结果。 自然地,这个中继器需要检查 Bitcoind 是否正在运行,以及挖矿核心是否准备就绪并正常工作。 由于中继程序大部分时间都处于待命状态,因此我们将设计一个统计编译子系统来挖掘数据并将数据组织在日志文件中。 理想情况下,我们将使用 Web 主机界面进行配置、显示统计信息和显示设备状态。

完整高效的挖矿系统

我们在 ZebBoard 开发板上使用 Xilinx Zynq-7000 All Programmable SoC 来开发高效完整的比特币挖矿系统。 该开发板可以灵活适应比特币协议的变化,同时提供具有SoC功能的高性能FPGA解决方案。 为了在不牺牲适应性的情况下改进我们当前的设计,我们计划添加更多连接到比特币主节点的挖矿核心。 添加更多的挖矿核心可以显着提高性能并加快整体哈希率。

进一步优化此设计的另一项改进是使用专用固件。 我们当前的设计运行的是 Ubuntu Linux 12.04 版。 这个版本有很多不必要的进程与 SSH 等比特币程序同时运行。 在比特币程序运行时运行这些进程是对板资源的浪费。 在未来的版本中,我们将取消这些过程,只运行我们自己为比特币任务量身定制的固件。