应用笔记

Moku 云编译

入门指南

更新了March 19,2024

Moku 云编译是 Moku:Pro、Moku:Lab 和 Moku:Go 上提供的一项创新功能。 Moku 系列测试和测量工具包含基于 FPGA 的仪器,Moku Cloud Compile 允许您将自定义 VHDL 代码部署到 Moku。该代码可以提供自定义功能并与现有仪器交互,以解锁只有 Moku 片上仪器架构才有可能实现的新的、独特的仪器。

本教程将指导您如何创建 Moku Cloud Compile 帐户以及一些 VHDL 示例的编码和部署。读完本指南后,您将掌握编译自定义代码并将其部署到 Moku 的基础知识。本说明使用 Moku:Pro,但所有这些示例也可在 Moku:Lab 和 Moku:Go 上使用。

下载打印版本

先决条件

Moku:Pro、Moku:Lab 或 Moku:Go with

多仪器模式 (MiM)

 Moku云编译(MCC)

概述

Moku 云编译工具使您能够设计自定义处理和功能以在 Moku 平台上实现。与基于 CPU 和专用集成电路 (ASIC) 的 DSP 方法相比,FPGA 平台提供接近 ASIC 级别的延迟和性能,同时仍然是软件可编程的,更像传统的 CPU。

虽然有许多广泛使用的软件语言可用于为基于 CPU 的设计编写软件,但 FPGA 编程通常仅限于 VHDL 或 Verilog。这些通常需要大型且复杂的本地工具链安装。可用于部署 VHDL 代码的平台通常仅限于 FPGA 供应商的评估板或各种功能有限的开源硬件板。 Moku Cloud Compile 提供了一个集成的、基于云的 VHDL 编译器,并与 Moku 硬件的可靠性相结合。

具有 Moku Cloud Compile 功能的 Moku:Pro 满足了对具有研究级硬件和定制处理功能的高性能实验室仪器的需求,而无需传统 FPGA 设计软件的开销。 MCC 在云中编译您的自定义 VHDL,并提供一个准备部署到任何支持 MCC 的 Moku 的包。

图1:Moku云编译部署流程

多仪器模式和Moku云编译

多仪器模式 (MiM) 允许同时部署和操作多台仪器。在最高级别,MiM 提供了四个插槽,代表 Moku:Pro 上 FPGA 的四个分区,以及 Moku:Go 和 Moku:Lab 上的两个插槽。您可以将灵活的仪器部署到这些插槽中。图 1 显示了 MiM 接口,其中示波器部署在插槽 1 中,频谱分析仪部署在插槽 2 中,而插槽 3 和 4 仍有待填充。可用仪器包括相位计、激光锁盒、数据记录器、数字滤波器盒、PID 控制器、示波器、频谱分析仪、锁相放大器、波形发生器、频率响应分析仪、FIR 滤波器生成器、任意波形发生器、逻辑分析仪和云编译。

它是 Moku Cloud Compile 工具,占据图 4 中的插槽 2,您可以在其中部署已编译的设计。因此,除了 ADC 和 DAC 输入和输出之外,MiM 还使您的设计能够与 Moku 仪器交互。


图 2:构建多仪器模式系统

 

 


图 3:使用 Moku Cloud Compile slot 构建的 MiM

设置Moku云编译账号

在编译代码或将代码部署到 Moku 之前,您需要一个在线帐户。这是一个简单的过程:

  • 在以下位置设置 MCC 用户帐户:  编译.liquidinstruments.com
  • 如果您是首次使用,您需要选择“注册”
  • 如果您是现有用户,您可以通过用户名或电子邮件地址登录,然后输入密码
  • 注册页面仅需要用户选择的用户名、有效的电子邮件地址和用户定义的密码。
  • 注册并登录后,您将看到 Projects 页面,该页面最初是空的,请参见图 4。


图 4:新建项目菜单

在编写第一个 VHDL 示例之前,您应该配置目标设备。选择“设备”选项卡并进行配置,如图 5 所示。选择一个方便的名称,然后选择硬件版本、固件版本和插槽数量,如图所示。您可以通过桌面应用程序(右键单击 Moku 图标 -> 设备信息)或 iPad 应用程序(在“选择您的设备”屏幕上触摸并按住 Moku 图标)来确定 Moku 的固件版本。


图 5:配置新的 Moku 设备

VHDL 示例 #1:将输入路由到输出

输入VHDL代码

现在您的 Moku Cloud Compile (MCC) 帐户已设置并且您熟悉了界面,您将编写、编译和部署最基本的工具。您的第一个简单乐器将简单地获取 Moku Cloud Compile 插槽的输入信号并将它们直接连接到输出。

首先,选择“新项目”并输入适当的名称。这个例子是“输入2输出”。

 

CustomWrapper 的架构行为是 begin OutputA <= InputA; 输出B <= 输入B; 端架构;

图 6:示例#1 的完整代码; 输入到输出.vhdl

第一个示例的代码如图 6 所示。该代码必须定义实体“CustomWrapper”的体系结构。 “CustomWrapper”是 MCC 设计必须符合的模板。它提供了自定义 MCC 仪器的基本 I/O 端口定义。请参阅中的完整定义 在线文档.

在“Inputs2Outputs”项目中,选择编辑器,创建一个名为“Inputs2Outputs.vhd”的新文件,如图 7 所示。


图 7:编辑器中的新文件

输入图 6 中的文本。它应该类似于图 8。


图 8:编辑器中的 VHDL 代码

构建代码

选择“目标设备”、“保存”,然后选择“构建”。然后代码将被提交到MCC服务器,您可以选择Build 选项卡观察该过程,如图 9 所示。这将需要几分钟才能完成。


图 9:构建正在进行中

代码编译完成后,“Synthesize”、“Route”、“Report”和“Bitstream”应该都是绿色的。该屏幕的最底部是比特流或工件“bitstream.tar.gz”。然后,可以通过单击小下载图标将文件“bitstream.tar.gz”下载到本地 PC。不要解压或解压该文件。

您可能会看到许多编译器或合成器警告;对于我们的目的来说,这些大多可以被忽略。但是,任何错误都需要注意,因为它们会停止构建过程。


图 10:构建成功

部署代码

现在使用 Moku 应用程序,选择 MiM,然后配置插槽和 I/O,如图 10 所示。这将为 Moku 云编译比特流准备 Moku:Pro。


图 10:示例 1 的 MiM 插槽配置

要部署比特流,请点击 Moku 云编译工具并选择“上传比特流”,如图 10 所示。浏览并选择之前下载到本地 PC 的文件“bitstream.tar.gz”。

要测试新的自定义仪器,请配置插槽 1 波形发生器,在输出 A 上配置 10 MHz 正弦波,在输出 B 上配置 1 MHz 斜波,如图 13 所示。然后,该波形发生器将通过我们的简单仪器。通过将示波器部署在插槽 3 中,我们可以观察部署在插槽 2 中的 MCC 仪器的正确“直通”操作。


图 13:插槽 2 波形发生器设置


图 14:插槽 4 示波器确认自定义仪器操作

VHDL 示例 #2:输入相减/相加

示例 1 非常详细地说明了编译和部署一个非常简单的 VHDL 示例所需的步骤。

CustomWrapper 的架构行为是 begin OutputA <= InputA + InputB; 输出 B <= 输入 B - 输入 B; 端架构;

示例 2 显示了用于添加和减去输入的 VHDL。虽然这也是一个基本示例,但它在测试和测量领域有许多实际场景。在数字域中对信号进行求和或相减,无需数模转换和外部模拟求和放大器,从而简化了许多应用。

我们鼓励用户采用此示例并重复示例 1 中概述的编译和部署步骤。与第一个示例一样,验证可能包括在插槽 1 中使用 MiM 和波形生成器、在插槽 2 中使用 Moku 云编译器以及在插槽 3 中使用示波器。对正确操作的视觉确认可能包括添加和减去交替的正弦波。同相和 180 度异相。

VHDL 示例 #3:缩放和偏移输入/DSP 切片

例3介绍了控制寄存器的使用。部署后,通过单击 MCC 仪器并选择打开仪器,访问 Moku:MCC 仪器应用程序界面上的寄存器。用户可以在应用程序中更改这些 32 位控制寄存器,并在 VHDL 代码中使用它们。在示例3中,Control1的最低有效位(LSB)用作使能;当设置为“1”时,InputA 和InputB 分别传递到OutputA 和OutputB。当 Control1 LSB 设置为“0”时,输出设置为 0。

使用 WORK.MercurySupport.ScaleOffset; IEEE 图书馆;使用 IEEE.Std_Logic_1164.all;使用 IEEE.Numeric_Std.all; CustomWrapper 的架构行为从 Control1(0) 开始,当 '1' 时选择 OutputA <= InputA,当其他时选择 OutputA <= InputA (OTHERS => '0');使用 Control1(1) 选择 OutputB <= InputB 当 '1' 时,(OTHERS => '0') 当其他时;最终架构;

图 14:控制寄存器

VHDL 示例 #4:缩放和偏移输入/DSP 切片

此示例比前三个示例稍微复杂一些。

该代码引用了 VHDL 库 Moku.Support,这是一个 Liquid Instruments 库。有关其内容的更多信息,请访问 MCC 网站的帮助部分。具体来说,实体 ScaleOffset 被命名。该实体包装了专用于执行乘法和加法功能的特定硬件块。该实体被实例化为名为“DSP”的块,并用于提供以下数学函数:

 

莫库库;使用 Moku.Support.ScaleOffset; CustomWrapper 的架构行为开始 -- Z = X * Scale + Offset -- 将 Z 剪辑到最小值/最大值(防止上溢/下溢) -- 包括舍入 -- 一个时钟周期延迟 DSP:ScaleOffset 端口映射( Clk => Clk,重置 => 重置,X => 输入 A,比例 => 有符号(Control1(15 降至 0)),偏移 => 有符号(Control2(15 降至 0)),Z => 输出 A,有效 => '1',OutValid = > 打开);最终架构;

在此示例中,scale 和 offset 都是 16 位、有符号 2 的补码数。比例从 -1 映射到 +1。此外,输出 Z 会被限幅,以防止数学运算的溢出或溢出。在线文档中提供了有关 ScaleOffset 的更多信息,包括如何从 -1 扩展到 +1: https://compile.liquidinstruments.com/docs/support.html#scaleoffset

VHDL 示例 #5a:输出限制设置

示例 #5a 提供了一种将输出信号限制到上限(或下限)的方法。

正如示例#3 中一样,此示例使用 Moku.Support 库,这次使用“clip”函数。

现在,OutputA 被分配给InputA 的经过剪辑的低9 位。这提供了2^power削波功能,即将信号削波到0 – 2的范围9.

示例 #4 提供了一种将输出信号限制在上限(或下限)的方法。

图书馆 IEEE; 使用 IEEE.Numeric_Std.all; 使用 WORK.MercurySupport.clip; Customwrapper 的架构行为是 begin OutputA <= resize(clip(InputA, 8, 0), 16); 端架构;

VHDL 示例 #5b:通用输出限制设置

示例#5b 提供了一种将输出信号限制到任意上限和下限的方法。

虽然示例 #5a 将提供粗略但快速的 2 次幂裁剪,但此示例提供了更通用的裁剪函数。 OutputA 被分配给InputA,但被限制在+2387 和-7462 的范围内。

IEEE 图书馆;使用 IEEE.Numeric_Std.all;莫库库;使用Moku.Support.clip_val; CustomWrapper 的架构行为是 begin OutputA <= Clip_val(InputA, -7462, 2387);最终架构;

VHDL 示例 #5:来自模拟输入的 PWM

示例6更复杂。它从模拟输入 A 生成脉宽调制 (PWM) 信号。它包含两个文件:Counter.vhdl 和 pwm.vhdl。用户在一起构建之前将这些文件作为单独的文件在 MCC 文件编辑器中输入。此示例特定于 Moku:Pro 及其 312.5 MHz 时钟,但可以分别适用于具有 125 MHz 和 31.25 MHz 时钟的 Moku:Lab 和 Moku:Go。有关 Moku:Go、Moku:Lab 和 Moku:Pro 上的 Moku Cloud Compile 之间差异的更多信息,请阅读数据表 此处.


-- counter.vhdl 库 IEEE;使用 IEEE.Std_logic_1164.all;使用 IEEE.Numeric_Std.all; --每 2^指数/增量输出选通输入选通 --将量化为舍入整数,但保持溢出,因此 --将随着时间的推移进行平均,但会有 +-1 周期抖动。实体计数器是通用的( EXPONENT : Positive := 8; PHASE90 : boolean := false );端口(Clk:在 std_logic 中;复位:在 std_logic 中;启用:在 std_logic 中;增量:在 unsigned 中;Strobe:在 std_logic 中);最终实体;计数器的架构行为是信号 Count : unsigned(EXPONENT downto 0);开始断言增量'长度<=计数'长度严重性失败; process(Clk) 开始,如果 Riding_edge(Clk) 那么如果 Reset = '1' 那么 Count <= (others => '0');如果 PHASE90 则 Count(EXPONENT - 1) <= '1';万一; elsif Enable = '1' then --修剪 MSB 但允许溢出。 --这在选通脉冲上提供了单个 Clk 周期输出脉冲。 Count <= resize(Count(Count'left-1 downto 0), Count'length) + Increment; else Count(Count'left) <= '0';万一;万一;结束进程;频闪 <= Count(Count'left);最终架构;

 


-- pwm.vhdl 库 IEEE;使用 IEEE.Std_Logic_1164.all;使用 IEEE.Numeric_Std.all;莫库库;使用 Moku.Support.ScaleOffset;使用Moku.Support.clip; CustomWrapper 的架构行为是常量 HI_LVL :signed(15 downto 0) := x"7FFF";常量 LO_LVL : 有符号(15 降到 0) := x"0000";信号值:有符号(12 降到 0);信号计数:无符号(12 降到 0);信号脉冲50kHz:std_logic;信号脉冲:std_logic;信号输出A:std_logic; begin INPUT_SCALE: ScaleOffset 端口映射 ( Clk => Clk, Reset => Reset, X => InputA & "0", Scale =>signed(Control1(15 downto 0)), -- 对于内部总线 2Vpp;0x0200 映射的设置well Offset =>signed(Control2(15 downto 0)), -- 对于 2Vpp 的内部总线,0x0400 的偏移适用于 +/-1 v 内部总线 Z => Value,Valid => Pulse50kHz,OutValid => open ) ; OSC:实体 WORK.Counter 通用映射 (22) -- 来自 5MHz 端口映射的 ~312.5 kHz(Clk、Reset、'1'、to_unsigned(67, 8)、Pulse50kHz); OSC2:实体 WORK.Counter 通用映射 (11) --5kHz/2048 约 10 MHz 端口映射(Clk、Pulse50kHz、'1'、to_unsigned(65, 9)、Pulse);如果上升沿(Clk)则开始处理(Clk),则如果 Pulse50kHz = '1' 则 Count <= resize(unsigned(clip(Value, 11, 0)), Count'length); elsif Pulse = '1' 且 Count /= 0 则 Count <= Count - 1;万一;万一;结束进程;当 Count /= 0 时,OutputA <= HI_LVL,否则 LO_LVL;最终架构;

总结

本应用笔记介绍了 Moku Cloud Compile 在 Moku:Pro 上作为多仪器模式的一部分运行时的一些优点和好处。涵盖了整个过程,从在示例 #1 中输入最简单的 VHDL 代码到构建、部署和确认预期操作。

进一步的示例代码被呈现并简要解释,邀请您尝试 MCC 带来的可能性。

可以根据这些基础知识开发进一步的 MCC 设计,包括更复杂的数学运算、自定义触发模式和其他应用程序。


有疑问或想要可打印版本?

请与我们联系 support@liquidinstruments.com