这是“Moku Cloud Compile with MathWorks HDL Coder”教程的第 2 部分。 可以找到第 1 部分 此处. 在第 2 部分中,我们将使用 MathWorks 的 Simulink 在 Moku:Pro 上构建和部署双通道施密特触发器。 MATLAB 脚本方法和 Simulink 模型方法之间的一般工作流程相似,但 Simulink 提供额外的第一方 DSP 和随时可用的测试块。 基于框图的设计方法提供了一种更直观的方式来构建 DSP 工作流程,特别是对于更复杂的系统。 在本教程中,我们将通过混合 MATLAB-Simulink 设计构建第一个通道,并使用 Simulink 库构建第二个通道。
概述
Liquid Instruments 的 Moku Cloud Compile (MCC) 工具使用户能够设计自定义仪器以在 Moku 平台上实施。 与基于 CPU 和专用集成电路 (ASIC) 的 DSP 方法相比,FPGA 提供 ASIC 级别的输入到输出延迟,同时像 CPU 一样是软件定义和可重新编程的。 FPGA 编程通常使用硬件描述语言 (HDL) 完成。 与软件编程语言相比,HDL 编码的学习曲线可能比较陡峭,但有一些工具可用于将其他编程语言的脚本转换为 HDL。 在本教程的第一部分中,我们介绍了如何使用 MathWorks HDL 编码器将 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 代码,您需要使用 MATLAB with Simulink、HDL Coder 和 Fixed-Point Converter。 注意:Mac 用户还需要为 MATLAB 安装 XCode 以生成 VHDL 代码。 要编译 VHDL 代码,您需要访问 Moku Cloud Compile。 要实现编译的乐器比特流,您需要有一个运行固件版本 551 或更高版本的 Moku:Pro,Moku: iPad 应用程序,并在您的 Moku:Pro 上访问多乐器模式。
设计和构建 DSP
调整模板
创建模型的第一步是调整 Simulink 模板以适合我们的 DSP 设计。 由于我们的设计是双通道系统,因此我们只需要 InputA、InputB、OutputA 和 OutputB 端口。
图 2:删除冗余通道
浮点DSP设计
在本节中,我们将构建两个施密特触发器,第一个通道使用 MATLAB 功能块,第二个通道使用 Simulink 触发器块。
可以在仿真选项卡下的“库浏览器”中找到 Simulink 构建块。 搜索功能是查找所需元素的最佳方式。 请注意,并非所有 Simulink 模块都支持 HDL 代码生成。 对于 DSP 子系统中的所有内容,我们建议仅使用“HDL Coder”或“HDL Support”目录下的块。
图 3:可以通过库浏览器找到 Simulink 构建块。
对于第一个通道,我们将在模型中放置一个 MATLAB 功能块。 由于MATLAB函数是浮点模型,Simulink模板已经为所有端口预定义了数据类型,所以数据类型不会匹配。 我们通过在 MATLAB 函数块前后放置两个“转换”块来解决这个问题。 用户可以使用定点算法设计模型,但我们发现在模型中实现 MATLAB 功能块时,从浮点开始更容易。 请注意,可能需要在 HDL 转换步骤之前删除第一个转换块。
要将施密特触发器函数添加到 MATLAB 函数块,请双击该块。 我们将使用与教程第一部分相同的 MATLAB 函数,函数名称除外(因此我们不会为 MATLAB 函数和 Simulink 子系统使用相同的名称)。
图 4:基于 MATLAB 函数的施密特触发器的框图设计。
功能 输出 A = 施密特触发器(输入 A)
%#代码生成
坚持 输出0; %在函数调用之间保留变量值。
if 空(out0) %初始化第一次调用的值。
输出 0 = 0;
结束
上阈值 = 下限(2^15/10); %将上限阈值设置为完整正值范围的 1/10。
下阈值 = -floor(2^15/10); %将下限阈值设置为整个负值范围的 1/10。
if 输入 A >上阈值 %逻辑执行施密特触发器功能。
输出0=2^15-1; %映射到最大的正数。
elseif 输入A
输出 0 = 0;
结束
输出A = out0; %将变量 out0 赋值给 OutputA。
对于第二个通道,我们将使用 Simulink 的“继电器”块来执行施密特触发器逻辑。 我们将继电器块放在 InputB 和 OutputB 之间,然后双击“继电器”块以将开关打开和关闭阈值分别更改为 floor(2^15/10) 和 – floor(2^15/10)。 在“信号属性”选项卡中,将信号输出设置为 修复 (1, 16,0) 以匹配输出。
图 5:“继电器”块设置为执行与第一个通道相同的施密特触发逻辑。
构建测试平台
Simulink 具有内置信号发生器、示波器和其他常用测试和测量设备块。 这使我们能够以更直观的方式设计测试平台。 请注意,HDL Coder 不需要支持 DSP 系统之外的构建块,因为它们仅用于仿真。
为了构建测试台,我们使用了一个“信号发生器”块来产生与第 I 部分中用于测试台的信号相同的信号。我们重新调整并转换了来自发生器的信号,以匹配我们系统的 16 位有符号输入。 在将信号馈送到输入之前,添加了一个额外的“转换”块以将浮点数转换为定点数。 然后,我们将发生器信号、OuputA 和 OutputB 馈入示波器以观察系统响应。
图 6:基于 Simulink 的测试平台框图
构建系统后,我们将运行模拟并验证输出。 我们观察到输出信号符合预期。
图 7:示波器上 DSP 子系统的输出。
定点转换
在为我们的 DSP 子系统生成 VHDL 代码之前,我们需要将浮点 MATLAB 功能块转换为定点功能块。 我们使用 MathWorks 的“Apps”选项卡中的 Fixed-Point Tool 和“Iterative Fixed-Point Conversion”方法来实现这一点。 请注意,如果我们从一开始就使用定点 DSP 构建 Simulink 模型,则不必运行定点转换。
图 8:迭代定点转换可以通过 Simulink Apps 选项卡启动。
接下来,我们选择 MATLAB 函数作为目标,并通过单击“收集范围”按钮启动转换过程。 Simulink 使用 testbech 数据点作为转换模型的参考。
图 9:MATLAB 函数被选为“System Under Design”。
然后,我们可以使用“建议数据类型”按钮让 Simulink 决定最佳定点精度。 底部的直方图显示每个信号的范围。 如果需要,我们可以手动覆盖任何信号精度。 确定精度后,我们可以使用“应用数据类型”按钮进行转换。
图10:(1)根据测试台数据提出信号精度; (2) 用直方图观察信号范围; (3) 继续将模型转换为定点设计。 (4) 删除第一个“convert”块。
定点转换后,需要去掉第一个“Convert”块; 因为新的“MATLAB Function”块采用定点数而不是浮点数/双精度数。
定点模型验证
转换模型后,重要的是要运行另一轮仿真以确保行为和精度损失符合预期。
VHDL代码生成
单击 HDL 代码选项卡下的“生成 HDL 代码”按钮可以生成 HDL 代码。 HDL Coder 生成设置已经在 Simulink 模板中进行了预配置,因此我们无需在此处调整设置。
图 11:“生成 HDL 代码”按钮位于 HDL 代码应用程序下方。
使用第三方工具的 VHDL 仿真(可选)
单击 HDL 代码应用程序下的“生成测试台”按钮可以生成 VHDL 测试台文件。 验证步骤与 MATLAB 示例相同。
图 12:“Generate Testbench”按钮位于 HDL Code 应用程序下方。
DSP编译部署
Moku Cloud Compile 内置了一个标准包装器,允许自定义乐器与 Moku:Pro 的其他部分进行交互。 标准包装器使用仪器的所有四个输入通道和输出通道; 这与我们的施密特触发器示例不匹配,该示例具有两个输入和两个输出。 因此,我们需要根据提供的模板为仪器创建一个自定义包装器。
请注意,即使选择了“Minimize clock enables”选项,有时 HDL Coder 仍会生成 VHDL 代码 时钟启用 和 ce_输出 端口(如本教程中所示)。 我们将连接 时钟启用 如果这些端口是在 VHDL 转换过程中创建的,则使用恒定的高信号并保持 ce_out 端口打开。
建筑设计 HDL编码包装器 OF 自定义包装器 IS
-- 信号声明
信号 ConstantHigh:std_logic。 :='1';
--组件声明
零件 DSP
端口(时钟: IN 标准逻辑;
重置 : IN 标准逻辑;
clk_enable : IN 标准逻辑;
输入A: IN 签名(15 DOWNTO 0); -- sfix16_En16
输入B : IN 签名(15 DOWNTO 0); -- sfix16_En16
ce_out_0 : 输出 标准逻辑;
ce_out_1 : 输出 标准逻辑;
输出A: 输出 签名(15 DOWNTO 0); -- sfix16_En14
输出B: 输出 签名(15 DOWNTO 0); -- sfix16_En14
);
结束组件;
开始
u_DSP:DSP
港口地图(时钟 => 时钟,
重置 => 重置,
clk_enable => ConstantHigh,
输入A => 输入A,
输入 B => 输入 B,
ce_out_0 => 打开,
ce_out_1 => 打开,
输出A => 输出A,
输出 B => 输出 B
);
结束 HDLCoderWrapper;
编译和部署工具
有关如何使用 Moku Cloud Compile 构建仪器比特流和部署仪器的详细说明,请参见我们的 Moku云编译入门指南.
要编译施密特触发器,请在 Liquid Instruments 的 Moku Cloud Compile 上创建一个新项目。 在这个项目中,为DSP_fixpt.vhd创建一个文件,这是施密特触发器的VHDL代码; 还为前面部分中的自定义包装器创建一个包装器文件。 选择目标设备作为具有 4 个插槽的 Moku:Pro 并构建项目。 构建比特流后,您将能够使用 Web 界面和 iPad 应用程序在您的 Moku:Pro 上部署施密特触发器。
为了证明施密特触发器按照我们的概念设计发挥作用,我们使用 Moku: App 和多仪器模式在 Moku:Pro 上实现了仪器。 在插槽 1 中,我们放置了一个任意波形发生器以生成我们在测试台中使用的相同信号作为施密特触发器的输入信号。 在插槽 2 中,我们放置了施密特触发器。 在插槽 3 中,我们放置了一个示波器来比较施密特触发器和任意波形发生器的输出信号。
我们首先验证使用 MATLAB 功能块设计的通道 A 中的施密特触发器。 我们可以确认,当输入信号高于 110 mV 时,施密特触发器的输出切换为高电平,并等到信号降至 -110 mV 以下才切换为零。
图 13:(a) 用于测试 MATLAB 功能块施密特触发器的多仪器系统配置。 (b) 验证施密特触发器是否按设计运行的示波器测量。
我们还验证了通道 B 中的施密特触发器,它是使用 Simulink 触发器块设计的,并观察到相同的行为。
图 14:(a) 用于测试 Simulink 触发器块施密特触发器的多仪器系统配置。 (b) 验证施密特触发器是否按设计运行的示波器测量。
最后,我们将两个输出通道放在一起进行比较,可以验证它们在同一点切换为高电平和低电平。
图 15:使用 MATLAB 功能块设计的施密特触发器和触发器块具有相同的行为。
结论
在本教程的第二部分中,我们介绍了如何利用 MathWorks 的 Simulink 和 HDL Coder 在 Moku:Pro 上构建、验证和部署 DSP 模型。 与仅使用 MATLAB 的方法相比,Simulink 使您可以选择通过其 DSP 库设计 DSP,并使用定点模型从头开始构建模型。 建议用于构建复杂的 DSP 系统。
代码可用性
该项目的源代码可以通过以下方式下载 此链接.
有疑问或想要可打印版本?
请与我们联系 support@liquidinstruments.com