这是“Moku Cloud Compile with MathWorks HDL Coder”教程的第 2 部分。 可以找到第 1 部分 开始现在,我们将使用 MathWorks 的 Simulink 在 Moku:Pro 上构建和部署一个双通道施密特触发器。MATLAB 脚本方法和 Simulink 模型方法的工作流程大致相同,但 Simulink 提供了额外的即用型第一方 DSP 和测试模块。基于框图的设计方法提供了一种更直观的 DSP 工作流程构建方法,尤其适用于更复杂的系统。在本教程中,我们将通过混合 MATLAB-Simulink 设计构建第一个通道,并使用 Simulink 库构建第二个通道。
在演示模式下试用 Moku
下载 Moku 应用 →
获取常见问题的答案
访问知识库 →
与全球的 Moku 用户建立联系
加入用户论坛 →
概述
Liquid Instruments 的 Moku Cloud Compile (MCC) 工具使用户能够设计定制仪器,并在 Moku 平台上实现。与基于 CPU 和专用集成电路 (ASIC) 的 DSP 方法相比,FPGA 提供 ASIC 级别的输入输出延迟,同时又像 CPU 一样具有软件定义和可重编程的特性。FPGA 编程通常使用硬件描述语言 (HDL)。与软件编程语言相比,HDL 编码的学习曲线可能较为陡峭,但有一些工具可以将其他编程语言的脚本转换为 HDL。在本教程的第一部分中,我们介绍了如何使用 MathWorks HDL Coder 将 MATLAB 脚本转换为 HDL 代码,以便在 Moku:Pro 上实现。在本第二部分中,我们将演示如何从 Simulink 模型生成 HDL 代码。Simulink 是 MathWorks 开发的一款基于图形的建模工具。其基于框图的设计理念简化了将手绘数字信号处理 (DSP) 系统转换为计算机模型的过程。虚拟测试和测量仪器,例如波形发生器和示波器,提供了一种更直观的方式来构建测试平台并验证 DSP 模型。此外,用户还可以选择使用 Simulink 从头开始构建定点系统。某些逻辑运算使用 MATLAB 函数更容易实现,在这种情况下,用户可以将 MATLAB 函数块添加到他们的设计中。对于更复杂的系统,同时使用这两种工具可以显著简化设计流程。在本教程中,我们将构建一个双通道施密特触发器。施密特触发器的基础知识和概念设计可以在教程的第一部分中找到。对于第一个通道,我们将使用与教程第一部分中完全相同的 MATLAB 函数来构建 DSP。对于第二个通道,我们将使用 Simulink 内置的 DSP 模块来实现相同的功能。
图 1:Moku Cloud Compile + HDL Coder DSP 设计的建议操作流程。
申请条件
在开始构建和实现施密特触发器之前,请确保您的系统满足以下要求。要从 Simulink 模型生成 VHDL 代码,您需要安装包含 Simulink、HDL Coder 和 Fixed-Point Converter 的 MATLAB。注意:Mac 用户还需要安装 XCode 才能使用 MATLAB 生成 VHDL 代码。要编译 VHDL 代码,您需要访问 Moku Cloud Compile。要实现编译后的仪器比特流,您需要拥有运行固件版本 601 或更高版本的 Moku:Pro、Moku: 应用程序以及访问 多仪器并行模式 在您的 Moku:Pro 上。设计和构建 DSP
选取合适的模板
创建模型的第一步是调整并选取适合我们 DSP 设计的 Simulink 模板。 由于我们的设计是双通道系统,因此我们只需要 InputA、InputB、OutputA 和 OutputB 这四个端口。
图 2:移除冗余通道。
浮点 DSP 设计
在本节中,我们将构建两个施密特触发器,第一个通道使用 MATLAB 函数模块,第二个通道使用 Simulink 触发器模块。Simulink 构建模块位于“仿真”选项卡下的“库浏览器”中。使用搜索功能是查找所需组件的最佳方法。请注意,并非所有 Simulink 模块都支持 HDL 代码生成。我们建议 DSP 子系统中的所有模块都仅使用“HDL Coder”或“HDL Support”目录中的模块。
图 3:可以通过 Library Browser 找到 Simulink 创建模块。
图 4:基于 MATLAB 函数的施密特触发器的框图设计。
function OutputA = Schmitt_Trigger(InputA)
%#codegen
persistent persistent out0; %在函数调用过程之间维持变量值不变。
if isempty(out0) %初始化第一次函数调用时的值。
out0 = 0;
end
upperThreshold = floor(2^15/10); %将阈值上限设置为正值范围的 1/10。
lowerThreshold = -floor(2^15/10); %将阈值下限设置为负值范围的 1/10。
if InputA >upperThrehold %激活施密特触发功能的逻辑判定条件。
out0 = 2^15-1; %将最大正值赋值给 outXNUMX。
elseif elseif InputA <lowerThreshold
out0 = 0;
end
OutputA = out0; %将变量 out0 赋值给 OutputA 并输出。
对于第二个通道,我们将使用 Simulink 的“继电器”模块来实现施密特触发器逻辑。我们将继电器模块放置在 InputB 和 OutputB 之间,然后双击“继电器”模块,将开关的开启和关闭阈值分别更改为 floor(2^15/10) 和 - floor(2^15/10)。在“信号属性”选项卡中,将信号输出设置为 fixdt(1, 16,0) 与输出匹配。
图 5:“Relay”模块设置为与第一个通道上施密特触发相同的逻辑判定。
创建测试平台
Simulink 内置了信号发生器、示波器和其他常用的测试测量设备模块。这使得我们可以更直观地设计测试平台。请注意,DSP 系统之外的构建模块无需 HDL Coder 支持,因为它们仅用于仿真。为了构建测试平台,我们使用了一个“信号发生器”模块来生成与第一部分测试平台相同的信号。我们对来自发生器的信号进行了重新缩放和转换,使其与我们系统的 16 位有符号输入相匹配。在将信号输入到输入端之前,我们添加了一个额外的“转换”模块,将浮点数转换为定点数。然后,我们将发生器信号、输出 A 和输出 B 输入到示波器,以观察系统响应。
图 6:基于 Simulink 的测试平台的框图。
图 7:示波器上 DSP 子系统的输出。
定点转换
在为我们的 DSP 子系统生成 VHDL 代码之前,我们需要将浮点 MATLAB 函数模块转换为定点函数模块。 我们使用 MathWorks 下“Apps”选项卡中的 Fixed-Point Tool 和“Iterative Fixed-Point Conversion”方法来实现。 请注意,如果我们从一开始就使用定点 DSP 构建 Simulink 模型,则不必运行定点转换。
图 8:迭代定点转换可以通过 Simulink Apps 选项卡调用。
图 9:MATLAB 函数被选为“设计中的系统”。
图10:(1)根据测试台数据由软件自动推荐信号精度; (2) 用直方图观察信号范围; (3) 继续将模型转换为定点设计。 (4) 删除第一个“convert”模块。
定点模型验证
模型转换完成后,重要的是要执行另一轮仿真以确保函数表现和精度损失符合预期。VHDL 代码生成
单击 HDL Code 选项卡下的“Generate HDL Code”来生成 HDL 代码。 HDL Coder 的生成设定已经在 Simulink 模板中进行了预配置,因此我们无需在此处调整设置。
图 11:“Generate HDL Code”位于 HDL Code 应用选项卡下方。
使用第三方工具进行 VHDL 仿真(可选)
单击 HDL 代码应用选项卡下的“Generate Testbench”可以生成 VHDL 测试台文件。 验证步骤与第 XNUMX 部分的 MATLAB 示例相同。
图 12:“Generate Testbench”位于 HDL Code 应用选项卡下方。
为 DSP 生成 VHDL 代码、编译并部署
Moku Cloud Compile 内置了一个标准封装器,允许自定义仪器与 Moku:Pro 的其他部分进行交互。该标准封装器使用了仪器的全部四个输入通道和输出通道;这与我们的施密特触发器示例不符,该示例只有两个输入和两个输出。因此,我们需要根据提供的模板为仪器创建一个自定义封装器。请注意,即使选择了“最小化时钟使能”选项,HDL Coder 有时仍然会生成带有特定信息的 VHDL 代码。 时钟使能 和 ce_out 端口(如本教程所示)。我们将连接…… 时钟使能 如果这些端口是在 VHDL 转换过程中创建的,则保持 ce_out 端口打开,并保持其处于高电平状态。
ARCHITECTURE HDLCoderWrapper OF CustomWrapper IS
-- 声明信号变量
SIGNAL ConstantHigh:std_logic. :='1';
--声明组件
COMPONENT DSP
PORT(Clk : IN std_logic;
Reset : IN std_logic;
clk_enable : IN std_logic;
InputA : IN signed(15 DOWNTO 0); -- sfix16_En16
输入 B : IN signed(15 DOWNTO 0); -- sfix16_En16
ce_out_0 : OUT std_logic;
ce_out_1 : OUT std_logic;
OutputA: OUT signed(15 DOWNTO 0); -- sfix16_En14
OutputB: OUT signed(15 DOWNTO 0); -- sfix16_En14
);
END COMPONENT;
BEGIN
u_DSP:DSP
PORT MAP(Clk => Clk,
Reset => Reset,
clk_enable => ConstantHigh,
InputA => InputA,
InputB => InputB,
ce_out_0 => open,
ce_out_1 => open,
OutputA => OutputA,
OutputB => OutputB
);
END HDLCoderWrapper;
编译和部署施密特触发器
有关如何使用 Moku Cloud Compile 构建仪器比特流和部署仪器的详细说明,请参阅我们的文档。 Moku Cloud Compile 入门指南要编译施密特触发器,请在 Liquid Instruments 的 Moku Cloud Compile 上创建一个新项目。在该项目中,创建一个用于存放 DSP_fixpt.vhd 的文件,该文件是施密特触发器的 VHDL 代码;同时,创建一个用于存放前面章节中自定义封装器的封装文件。选择目标设备为具有 4 个插槽的 Moku:Pro,然后构建项目。比特流构建完成后,您可以使用网页界面和 Moku 应用将施密特触发器部署到您的 Moku:Pro 上。为了演示施密特触发器是否按照我们的概念设计运行,我们使用 Moku 应用和多仪器模式在 Moku:Pro 上实现了该仪器。在插槽 1 中,我们放置了一个任意波形发生器,用于生成与测试平台中用作施密特触发器输入信号的相同信号。在插槽 2 中,我们放置了施密特触发器。在插槽 3 中,我们连接了一台示波器,用于比较施密特触发器和任意波形发生器的输出信号。首先,我们验证了通道 A 中用 MATLAB 函数块设计的施密特触发器。我们可以确认,当输入信号高于 110 mV 时,施密特触发器的输出切换到高电平;当输入信号降至 -110 mV 以下时,输出切换到零电平。
图 13:(a) 用于测试 MATLAB 函数块施密特触发器的多仪器系统配置。(b) 示波器测量验证施密特触发器是否按设计运行。
图 14:(a) 用于测试 Simulink 触发器块施密特触发器的多仪器系统配置。(b) 示波器测量验证施密特触发器是否按设计运行。
图 15:使用 MATLAB 函数模块设计的和使用触发器模块设计的施密特触发器均具有相同的行为表现。



