Deploy Simscape Buck Converter Model to Speedgoat IO Module Using HDL Workflow Script
This example shows how to deploy a Simscape™ buck converter model to a Speedgoat IO334 Simulink®-programmable I/O module and then run the model in real-time at a sample step size as small as 1 microsecond. The example uses a DCDC converter topology to show how to prepare your power electronic converter model for hardware in the loop (HIL) simulation on a Speedgoat real-time target machine.
To use this workflow:
Convert your model into an HDL-compatible implementation model by using the Simscape HDL Workflow Advisor
Generate HDL code and FPGA bitstream for the IO334 module by using the HDL Workflow Advisor.
Deploy the real-time model to the Speedgoat real-time target machine by using Simulink Real-Time.
The model runs at a sample time of 1us till HDL code generation and then runs at 50us on the CPU in real time. To generate HDL code and FPGA bitstream, the example shows how to run the HDL workflow script from the command line. For an example that shows how you can use the Workflow Advisor User Interface to run this workflow, see Hardware-in-the-Loop Implementation of Simscape Model on Speedgoat FPGA I/O Modules.
Setup and Configuration
Before deploying your algorithm on the Speedgoat IO module:
1. Install the latest version of Xilinx® Vivado® as listed in HDL Language Support and Supported Third-Party Tools and Hardware.
Then, set the tool path to the installed Xilinx Vivado executable by using the hdlsetuptoolpath
function.
hdlsetuptoolpath('ToolName','Xilinx Vivado','ToolPath','C:\Xilinx\Vivado\2019.2\bin\vivado.bat')
2. For real-time simulation, set up the development environment and target computer settings. See Get Started with Simulink Real-Time (Simulink Real-Time).
3. Install the Speedgoat Library and the Speedgoat HDL Coder Integration packages. See Install Speedgoat HDL Coder Integration Packages.
Buck Converter Model
To see the buck converter model, run this command:
open_system('sschdlexBuckConverterModel')
This model is modified for real-time deployment and saved as sschdlex_IO334_BuckConverter
. The model has been partitioned into parts that run on the FPGA and parts that run on CPU. Parts inside the green FPGA
subsystem run on the FPGA. Parts outside this subsystem run on the CPU in real time.
open_system('sschdlex_IO334_BuckConverter') set_param('sschdlex_IO334_BuckConverter', 'SimulationCommand', 'Update')
You generate VHDL code for blocks that are inside the green FPGA subsystem that contains the PWM generator and buck converter. The code is then deployed to the FPGA on board the IO334 module. The outputs of the subsystem are mapped to DAC interfaces. The output signals from the Buck Converter subsystem are scaled within a 10V
range and converted to use uint16
data types. 50
samples are packed together to one frame to log the output signals on the CPU.
open_system('sschdlex_IO334_BuckConverter/FPGA')
To see the buck converter model, double-click the Buck Converter subsystem. The buck converter is a power converter model that steps down the input voltage at the output. The voltage at the output is stepped down by the duty cycle, D. The output voltage, Vout
, is calculated as Vin/D
open_system('sschdlex_IO334_BuckConverter/FPGA/Buck Converter')
Run Desktop Simulation of Simscape model
The Simulation input is a duty cycle step wave from 0.2
to 0.8
. The input signals that include the DC input voltage, PWM frequency, and duty cycle are generated on the top level of the model. The sample time for the Simscape model is set to 1us
. Signal logging is enabled on the top level of the model.
sim('sschdlex_IO334_BuckConverter') % Display the buck converter output signals in SDI Simulink.sdi.clearAllSubPlots Simulink.sdi.setSubPlotLayout(3,1); allIDs2 = Simulink.sdi.getAllRunIDs; runID2 = allIDs2(end); run2 = Simulink.sdi.getRun(runID2); run2.name = 'Simscape Desktop Simulation'; run2.getAllSignals; plotOnSubPlot(run2.getSignalsByName('Vout'),1,1,true); plotOnSubPlot(run2.getSignalsByName('Iinductor'),2,1,true); plotOnSubPlot(run2.getSignalsByName('Vdiode'),3,1,true); Simulink.sdi.view;
Generate HDL Implementation Model
For HDL code generation compatibility, you run the Simscape HDL Workflow Advisor to generate an HDL implementation model.
The Simscape solver is set to run for two iterations at each sample step. The Simscape HDL Workflow Advisor uses the solver settings in the next step for deterministic real-time behavior.
set_param('sschdlex_IO334_BuckConverter/FPGA/Buck Converter/Solver Configuration','DoFixedCost','on') set_param('sschdlex_IO334_BuckConverter/FPGA/Buck Converter/Solver Configuration','MaxNonlinIter','2')
To open the Advisor, run the sschdladvisor
function for your model:
sschdladvisor('sschdlex_IO334_BuckConverter')
To generate the implementation model, in the Simscape HDL Workflow Advisor, keep the default settings for the tasks, and then run the tasks. Run the tasks in the Advisor by clicking the Run all button. You see a link to the model in the Generate implementation model task. This model has the same name as your original model with the prefix gmStateSpaceHDL_
.
Prepare Implementation Model for HDL Code Generation
To open the implementation model, click the link in the Generate implementation model task.
open_system('gmStateSpaceHDL_sschdlex_IO334_BuckConverte'); set_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte', 'SimulationCommand', 'Update')
The model contains a switched linear Simulink replacement of the original buck converter model. You see that the Simscape model was replaced.
open_system('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/Buck Converter');
The implementation model replaces the Simscape subsystem with the HDL-compatible algorithm that performs the state-space computations. When you navigate inside this subsystem, you see several delays, adders, and Matrix Multiply blocks that model the state-space equations. From and Goto blocks inside this subsystem provide the same input as that of the original model to the HDL Subsystem
.
open_system('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/Buck Converter/HDL Subsystem/HDL Algorithm')
The data type of the buck converter output signals is set to single precision floating point for HDL code generation.
set_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/Signal Specification','OutDataTypeStr','single'); set_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/Signal Specification1','OutDataTypeStr','single'); set_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/Signal Specification2','OutDataTypeStr','single'); set_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/Signal Specification3','OutDataTypeStr','single'); set_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/Signal Specification4','OutDataTypeStr','single');
Run Desktop Simulation of HDL Implementation Model and Validate HDL Algorithm
You can simulate the switched linear state-space model of the buck converter in Simulink and display the signals in Simulation Data Inspector. The comparison of the runs show that the numeric results match.
Simulate the HDL implementation model.
sim('gmStateSpaceHDL_sschdlex_IO334_BuckConverte') % % Display output signals of buck converter Simscape model in Simulation % Data Inspector. Simulink.sdi.clearAllSubPlots Simulink.sdi.setSubPlotLayout(3,1); allIDs2 = Simulink.sdi.getAllRunIDs; runID2 = allIDs2(end); run2 = Simulink.sdi.getRun(runID2); run2.name = 'HDL Desktop Simulation'; run2.getAllSignals; plotOnSubPlot(run2.getSignalsByName('Vout'),1,1,true); plotOnSubPlot(run2.getSignalsByName('Iinductor'),2,1,true); plotOnSubPlot(run2.getSignalsByName('Vdiode'),3,1,true); Simulink.sdi.view;
Warning: Unable to resolve the name 'CloneDetector.ExclusionEditorUIService.getInstance'.
To verify that the HDL implementation model matches the original Simscape model, generate a state-space validation model. In the Generate implementation model task, select the Generate validation logic for the implementation model check box and then run this task. Simulating the model does not display assertions, which indicates that the numeric results match. See Validate HDL Implementation Model to Simscape Algorithm.
HDL Workflow Advisor
The HDL Workflow Advisor guides you through HDL code generation and the FPGA design process. Use the Advisor to:
Check the model for HDL code generation compatibility and fix incompatible settings.
Generate HDL code, test bench, and scripts to build and run the code and test bench.
Perform synthesis, timing analysis, and deploy the generated code on SoCs, FPGAs, and Speedgoat I/O modules.
You run the Advisor for the FPGA subsystem in your model. To open the HDL Workflow Advisor for the subsystem inside the model, use the hdladvisor
function. For example:
hdladvisor('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA')
To learn about the tasks in the Advisor, right-click that task, and select What's This?. See Getting Started with the HDL Workflow Advisor.
Run Workflow Script to Generate Simulink Real-Time Interface Model
For rapid prototyping, export the HDL Workflow Advisor settings to a script. The script is a MATLAB® file that you run from the command line. You can modify and run the script, or import the settings into the HDL Workflow Advisor User Interface. See Run HDL Workflow with a Script.
This example shows how to run the HDL Workflow script. To generate a Simulink Real-Time Interface model, open and run this MATLAB script.
edit('hdlworkflow_buck_IO334')
%% ------------------------------------------------------------------------ % This script contains the model, target settings, interface mapping, and % the Workflow Configuration settings for generating HDL code for the HDL % implementation model generated for the buck converter model, and for % deploying the code to the FPGA on board the Speedgoat IO334-325K module. %% ----------------------------------------------------------------------- %% Set Parameters for HDL Code Generation % Model HDL parameters % ------------------------------------------------------------------------- hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte', 'FloatingPointTargetConfiguration', hdlcoder.createFloatingPointTargetConfig('NativeFloatingPoint', 'LatencyStrategy', 'MIN')); hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte', 'HDLSubsystem', 'gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA'); hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte', 'Oversampling', 100); hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte', 'ScalarizePorts', 'DUTLevel'); hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte', 'TargetFrequency', 200); hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte', 'Workflow', 'Simulink Real-Time FPGA I/O'); hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte', 'TargetPlatform', 'Speedgoat IO334-325k'); hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte', 'AdaptivePipelining', 'off'); %% Map DUT Ports to Target Interfaces % Input port mapping % ------------------------------------------------------------------------- % All input signals to the "FPGA" subsystem are mapped to the PCIe % interface. I.e. these signals will be transferred from the CPU of the % real-time target machine to the IO334 FPGA over the PCIe bus. hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/PWM Period', 'IOInterface', 'PCIe Interface'); hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/Duty Cycle', 'IOInterface', 'PCIe Interface'); hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/DC Input Voltage', 'IOInterface', 'PCIe Interface'); % Output port mapping % ------------------------------------------------------------------------- % The scaled output signals of the converter are mapped to the analog % output interface of the IO334. hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/DAC V Out', 'IOInterface', 'IO334 AO Data [0:15]'); hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/DAC V Out', 'IOInterfaceMapping', 'Channel 01'); hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/DAC V Diode', 'IOInterface', 'IO334 AO Data [0:15]'); hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/DAC V Diode', 'IOInterfaceMapping', 'Channel 02'); hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/DAC I Inductor', 'IOInterface', 'IO334 AO Data [0:15]'); hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/DAC I Inductor', 'IOInterfaceMapping', 'Channel 03'); hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/DAC Trigger', 'IOInterface', 'IO334 AO Trigger [0:1]'); hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/DAC Trigger', 'IOInterfaceMapping', 'Channel 01 to 08'); % The signal frames are mapped to PCIe registers. They are read by the CPU for data logging. hdlset_param('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA/PCIe Out', 'IOInterface', 'PCIe Interface'); %% Workflow Configuration Settings % HDL Workflow Advisor is opened with the following settings. hWC = hdlcoder.WorkflowConfig('SynthesisTool','Xilinx Vivado','TargetWorkflow','Simulink Real-Time FPGA I/O'); % Specify the top level project directory. hWC.ProjectFolder = 'hdl_prj'; hWC.ReferenceDesignToolVersion = '2019.2'; % Set Workflow tasks to run. hWC.RunTaskGenerateRTLCodeAndIPCore = true; hWC.RunTaskCreateProject = true; hWC.RunTaskBuildFPGABitstream = true; hWC.RunTaskGenerateSimulinkRealTimeInterface = true; %% Run the Workflow hdlcoder.runWorkflow('gmStateSpaceHDL_sschdlex_IO334_BuckConverte/FPGA', hWC);
Prepare Simulink Real-Time Interface Model for Real-Time Simulation
Running the workflow script generates RTL code and IP core, creates a Vivado project, builds the FPGA bitstream, and then generates the Simulink Real-Time Interface model.
Before deploying the model to the Speedgoat real-time target machine:
1. Set the sample time for all blocks running on the CPU of the Speedgoat real-time target machine to 50us (including driver blocks for the FPGA).
generated_model = gcs; Ts = 50e-6; set_param([generated_model,'/FPGA'],'ts','Ts');
2. Set the Simulation Data Inspector setting Input processing to Columns as channels (frame based)
for the signals PCIe_V_out_frame
, PCIe_V_diode_frame
and PCIe_I_inductor_frame
. Inside the mask of the File Log
blocks, right-click the logging symbol and navigate to the Instrumentation Properties dialog box. To make the logging signal appear, you might have to update the model.
set_param(generated_model, 'SimulationCommand', 'update');
Alternatively, you can set signal logging to frame based mode by using these commands.
Simulink.sdi.setSignalInputProcessingMode([generated_model,'/File Log/Demux'], 1,'frame'); Simulink.sdi.setSignalInputProcessingMode([generated_model,'/File Log 1/Demux'], 1,'frame'); Simulink.sdi.setSignalInputProcessingMode([generated_model,'/File Log 2/Demux'], 1,'frame');
Connect to Target Machine and Run Real-Time Simulation
The model can now be deployed to the Speedgoat real-time target machine. The buck converter model is automatically loaded to the FPGA on the IO334.
Connect to the Speedgoat real-time target machine.
tg = slrealtime; tg.connect;
Build and download the model to the target machine.
rtwbuild(generated_model); tg.load(generated_model);
Start the model execution.
tg.start; pause(10);
The file logging blocks store the signals on the SSD of the target-machine. The data is automatically uploaded to the host computer once the model is stopped. The data is visualized in Simulation Data Inspector. You can verify that the results of the real-time simulation matches the original Simscape model.
Simulink.sdi.setSubPlotLayout(3,1);
allIDs = Simulink.sdi.getAllRunIDs;
runID = allIDs(end);
run = Simulink.sdi.getRun(runID);
run.name = 'Real Time Simulation on IO334';
run.getAllSignals plotOnSubPlot(run.getSignalsByName('PCIe_V_out_frame'),1,1,true); plotOnSubPlot(run.getSignalsByName('PCIe_I_inductor_frame'),2,1,true); plotOnSubPlot(run.getSignalsByName('PCIe_V_diode_frame'),3,1,true);
Simulink.sdi.view
Alternatively, you can measure the signals at the analog output of the IO334. This figure shows a plot of the signals in MATLAB.