Main Content

Deploy Simscape Grid Tied Converter Model to Speedgoat IO Module Using HDL Workflow Script

This example shows how to deploy a three-phase two-level voltage source converter connected to a low voltage grid modeled in Simscape™ to a Speedgoat IO334 Simulink®-programmable I/O module to achieve a simulation time step of 1 microsecond (us).

The PWM signals can be captured with an increased resolution by modeling the converter using the sub-cycle averaging method. A maximum resolution of 4ns is possible, allowing to simulate state of the art power converters with switching frequencies above 100kHz. The switching frequency of this example is 20kHz.

This example demonstrates how to:

  1. Convert your Simscape model into an HDL-compatible implementation model by using the Simscape HDL Workflow Advisor

  2. Generate HDL code and FPGA bitstream for the IO334 module by using the HDL Workflow Advisor.

  3. Deploy the real-time model to the Speedgoat real-time target machine by using Simulink Real-Time.

The plant model runs eventually at a 1us time step on the FPGA and the controller is executed at a 50us time step on the CPU of the real-time system. To generate HDL code and FPGA bitstream, this example shows how to run the HDL workflow script from the command line. You can use the Workflow Advisor User Interface to run this workflow. For more information, 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\2020.1\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.

Three-Phase Two-Level Voltage Source Converter Model

To see the three-phase two-level converter model, run this command:

     open_system('sschdlexThreePhaseConverterWithGridExample')

This example model consists of a three-phase two-level voltage source converter connected to a low voltage grid through an LC filter. A circuit breaker allows to disconnect and connect the converter with the grid. There is a low voltage load on the grid side and a transformer connecting to the medium voltage grid.

In the first step, the model is used to validate the closed-loop control by desktop simulation. The controller consists of a phase-locked loop for grid synchronization and PI current control in the synchronous reference frame.

In a second step, the model can be deployed to the real-time platform for HIL testing of the embedded controller.

The model has been partitioned into parts that run on the FPGA and parts that run on the CPU in real time. Parts inside the green FPGA subsystem run on the FPGA. Parts outside this subsystem run on the CPU in real time.

     open_system('sschdlexThreePhaseConverterWithGridExample/FPGA')

Run Desktop Simulation of Simscape model

     % The base sample rate is set to 100ns to accelerate desktop simulation
     Tbase = 100e-9;
     % Set the simulation and step time to close the circuit breaker
     set_param('sschdlexThreePhaseConverterWithGridExample','StopTime','0.09');
     set_param(['sschdlexThreePhaseConverterWithGridExample','/Step'],'Time','0.03');
     % Desktop simulation of the model
     sim('sschdlexThreePhaseConverterWithGridExample')
     % Display output signals of three-phase two-level voltage source
     converter in Simulink Data Inspector
     Simulink.sdi.clearAllSubPlots
     Simulink.sdi.setSubPlotLayout(2,1);
     allIDs = Simulink.sdi.getAllRunIDs;
     runID1 = allIDs(end);
     run1 = Simulink.sdi.getRun(runID1);
     run1.name = 'Desktop Simulation';
     Vabc_grid = run1.getSignalsByName('Vabc_grid');
     Iabc_conv = run1.getSignalsByName('Iabc_conv');
     plotOnSubPlot(Vabc_grid.Children(1),1,1,true);
     plotOnSubPlot(Vabc_grid.Children(2),1,1,true);
     plotOnSubPlot(Vabc_grid.Children(3),1,1,true);
     plotOnSubPlot(Iabc_conv.Children(1),2,1,true);
     plotOnSubPlot(Iabc_conv.Children(2),2,1,true);
     plotOnSubPlot(Iabc_conv.Children(3),2,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 one iteration at each sample step. The Simscape HDL Workflow Advisor uses the solver settings in the next step for deterministic real-time behaviour.

     % The averaged switch model allows us to set the solver itearions to 1
     set_param(['sschdlexThreePhaseConverterWithGridExample','/FPGA/Solver Configuration'],'DoFixedCost','on')
     set_param(['sschdlexThreePhaseConverterWithGridExample','/FPGA/Solver Configuration'],'MaxNonlinIter','1')

To accelerate the sschdladvisor we reduce the sample time of the model. The time at which the circuit breaker closes is adapted to make sure that the workflow advisor captures all switching modes during simulation.

     set_param('sschdlexThreePhaseConverterWithGridExample','StopTime','0.002');
     set_param(['sschdlexThreePhaseConverterWithGridExample','/Step'],'Time','0.001');

To open the Advisor, run the sschdladvisor function for your model: sschdladvisor('sschdlexThreePhaseConverterWithGridExample')

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 generated model in the Generate implementation model task. This model has the same name as your original model with the prefix gmStateSpaceHDL_.

     % We set the simulation and step time to the original values
     set_param('sschdlexThreePhaseConverterWithGridExample','StopTime','0.09');
     set_param(['sschdlexThreePhaseConverterWithGridExample','/Step'],'Time','0.03');

Prepare Implementation Model for HDL Code Generation

To open the implementation model, click the link in the Generate implementation model task.

     open_system('gmStateSpaceHDL_sschdlexThreePhaseConverter')

     set_param('gmStateSpaceHDL_sschdlexThreePhaseConverter','StopTime','0.09');
     set_param(['gmStateSpaceHDL_sschdlexThreePhaseConverter','/Step'],'Time','0.03');

The model contains a switched linear Simulink replacement of the original three-phase two-level voltage source converter model. You see that the Simscape model was replaced.

     open_system('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA')

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_sschdlexThreePhaseConverter/FPGA/HDL Subsystem/HDL Algorithm')

Run Desktop Simulation of HDL Implementation Model and Validate HDL Algorithm

You can simulate the switched linear state-space model of the three-phase two-level voltage source converter in Simulink and display the signals in Simulation Data Inspector. The comparison of the runs show that the numeric results match with the original Simscape model.

     % Simulate the HDL implementation model.
     sim('gmStateSpaceHDL_sschdlexThreePhaseConverter')
     % Display output signals of three-phase two-level voltage source converter
     Simscape model in Simulink Data Insapector
     Simulink.sdi.clearAllSubPlots
     Simulink.sdi.setSubPlotLayout(2,1);
     allIDs = Simulink.sdi.getAllRunIDs;
     runID1 = allIDs(end);
     run2 = Simulink.sdi.getRun(runID1);
     run2.name = 'HDL Model Simulation';
     Vabc_grid = run2.getSignalsByName('Vabc_grid');
     Iabc_conv = run2.getSignalsByName('Iabc_conv');
     plotOnSubPlot(Vabc_grid.Children(1),1,1,true);
     plotOnSubPlot(Vabc_grid.Children(2),1,1,true);
     plotOnSubPlot(Vabc_grid.Children(3),1,1,true);
     plotOnSubPlot(Iabc_conv.Children(1),2,1,true);
     plotOnSubPlot(Iabc_conv.Children(2),2,1,true);
     plotOnSubPlot(Iabc_conv.Children(3),2,1,true);
     Simulink.sdi.view;

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_sschdlexThreePhaseConverter/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

You can export the HDL Workflow Advisor settings to a script to expedite and automate your workflow. 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_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 three-phase two-level voltage source 
    % converter model, and for deploying the code to the FPGA on board the 
    % Speedgoat IO334-325K module.
    %% -----------------------------------------------------------------------
    
    %%
    set_param(['gmStateSpaceHDL_sschdlexThreePhaseConverter','/FPGA/Data Type Conversion Va'],'OutDataTypeStr','single');
    set_param(['gmStateSpaceHDL_sschdlexThreePhaseConverter','/FPGA/Data Type Conversion Vb'],'OutDataTypeStr','single');
    set_param(['gmStateSpaceHDL_sschdlexThreePhaseConverter','/FPGA/Data Type Conversion Vc'],'OutDataTypeStr','single');
    
    %% ------------------------------------------------------------------------
    % Make the model ready for HDL code generation
    
    % Set all data type conversion blocks to type single (except the
    % conversions for the analog output signals.
    load_system('gmStateSpaceHDL_sschdlexThreePhaseConverter');

    DataTypeConversionBlocks = Simulink.findBlocksOfType(['gmStateSpaceHDL_sschdlexThreePhaseConverter','/FPGA'],'DataTypeConversion',Simulink.FindOptions('SearchDepth',1));
    for i = 1:length(DataTypeConversionBlocks)
      BlockName = get_param(DataTypeConversionBlocks(i),'Name');
      if ~any(strcmp(BlockName,{'Data Type Conversion DAC1','Data Type Conversion DAC2'}))
        set_param(['gmStateSpaceHDL_sschdlexThreePhaseConverter','/FPGA/',BlockName],'OutDataTypeStr','single');
      end
    end
    
    set_param(['gmStateSpaceHDL_sschdlexThreePhaseConverter','/Data Type Conversion Vg'],'OutDataTypeStr','single');
    set_param(['gmStateSpaceHDL_sschdlexThreePhaseConverter','/Data Type Conversion Breaker'],'OutDataTypeStr','single');
    
    % Set the sample time to 5e-9 (equal to a clock tick at 200MHz target
    % frequency)
    Tbase = 5e-9;
    
    %% Set Parameters for HDL Code Generation 
    
    % Model HDL parameters
    % -------------------------------------------------------------------------
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter', 'FloatingPointTargetConfiguration', hdlcoder.createFloatingPointTargetConfig('NativeFloatingPoint', 'LatencyStrategy', 'MIN'));
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter', 'HDLSubsystem', ['gmStateSpaceHDL_sschdlexThreePhaseConverter','/FPGA']);
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter', 'Oversampling',1);
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter', 'ScalarizePorts', 'DUTLevel');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter', 'TargetFrequency', 200);
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter', 'Workflow', 'Simulink Real-Time FPGA I/O');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter', 'TargetPlatform', 'Speedgoat IO334-325k');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter', 'TargetDirectory', 'c:\hdl_prj\hdlsrc');
    
    % Set a sharing factor for the matrix vector products
    hdlset_param(['gmStateSpaceHDL_sschdlexThreePhaseConverter','/FPGA/HDL Subsystem/HDL Algorithm/Output/Multiply Input'], 'SharingFactor', 50);
    hdlset_param(['gmStateSpaceHDL_sschdlexThreePhaseConverter','/FPGA/HDL Subsystem/HDL Algorithm/Output/Multiply State'], 'SharingFactor', 50);
    hdlset_param(['gmStateSpaceHDL_sschdlexThreePhaseConverter','/FPGA/HDL Subsystem/HDL Algorithm/State Update/Multiply Input'], 'SharingFactor', 50);
    hdlset_param(['gmStateSpaceHDL_sschdlexThreePhaseConverter','/FPGA/HDL Subsystem/HDL Algorithm/State Update/Multiply State'], 'SharingFactor', 50);
    
    % Enable flatten hyrarchy
    hdlset_param(['gmStateSpaceHDL_sschdlexThreePhaseConverter','/FPGA'], 'FlattenHierarchy', 'on');
    
    % Interfaces
    
    % Set Inport HDL parameters
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/modWave', 'IOInterface', 'PCIe Interface');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/modWave', 'IOInterfaceMapping', 'x"100"');
    
    % Set Inport HDL parameters
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/Period', 'IOInterface', 'PCIe Interface');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/Period', 'IOInterfaceMapping', 'x"114"');
    
    % Set Inport HDL parameters
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/Enable', 'IOInterface', 'PCIe Interface');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/Enable', 'IOInterfaceMapping', 'x"118"');
    
    % Set Inport HDL parameters
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/DeadBand', 'IOInterface', 'PCIe Interface');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/DeadBand', 'IOInterfaceMapping', 'x"11C"');
    
    % Set Inport HDL parameters
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/Grid Voltage', 'IOInterface', 'PCIe Interface');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/Grid Voltage', 'IOInterfaceMapping', 'x"120"');
    
    % Set Inport HDL parameters
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/breaker', 'IOInterface', 'PCIe Interface');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/breaker', 'IOInterfaceMapping', 'x"134"');
    
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/HDL Subsystem/HDL Algorithm/Mode Selection/Generate Mode Vector', 'Architecture', 'MATLAB Datapath');
    
    % Set Outport HDL parameters
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/PCIe_FrameData', 'IOInterface', 'PCIe Interface');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/PCIe_FrameData', 'IOInterfaceMapping', 'x"1000"');
    
    % Set Outport HDL parameters
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/DAC_1', 'IOInterface', 'IO334 AO Data [0:15]');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/DAC_1', 'IOInterfaceMapping', 'Channel 01');
    
    % Set Outport HDL parameters
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/DAC_2', 'IOInterface', 'IO334 AO Data [0:15]');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/DAC_2', 'IOInterfaceMapping', 'Channel 02');
    
    % Set Outport HDL parameters
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/DAC_3', 'IOInterface', 'IO334 AO Data [0:15]');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/DAC_3', 'IOInterfaceMapping', 'Channel 03');
    
    % Set Outport HDL parameters
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/DAC_5', 'IOInterface', 'IO334 AO Data [0:15]');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/DAC_5', 'IOInterfaceMapping', 'Channel 05');
    
    % Set Outport HDL parameters
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/DAC_6', 'IOInterface', 'IO334 AO Data [0:15]');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/DAC_6', 'IOInterfaceMapping', 'Channel 06');
    
    % Set Outport HDL parameters
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/DAC_7', 'IOInterface', 'IO334 AO Data [0:15]');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/DAC_7', 'IOInterfaceMapping', 'Channel 07');
    
    % Set Outport HDL parameters
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/DAC trigger 1_8', 'IOInterface', 'IO334 AO Trigger [0:1]');
    hdlset_param('gmStateSpaceHDL_sschdlexThreePhaseConverter/FPGA/DAC trigger 1_8', 'IOInterfaceMapping', 'Channel 01 to 08');
    
    %% Workflow Configuration Settings
    % Construct the Workflow Configuration Object with default settings
    hWC = hdlcoder.WorkflowConfig('SynthesisTool','Xilinx Vivado','TargetWorkflow','Simulink Real-Time FPGA I/O');
    
    % Specify the top level project directory
    hWC.ProjectFolder = 'c:/hdl_prj';
    
    % Set Workflow tasks to run
    hWC.RunTaskGenerateRTLCodeAndIPCore = true;
    hWC.RunTaskCreateProject = true;
    hWC.RunTaskBuildFPGABitstream = true;
    hWC.RunTaskGenerateSimulinkRealTimeInterface = true;
    
    %% Run the workflow
    hdlcoder.runWorkflow('gmStateSpaceHDL_sschdlexThreePhaseConverter/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, getting model ready for real time testing:

     generated_model = get_param(gcs,'Name');
     % comment through all rate transition blocks
     RateTransitionBlocks = Simulink.findBlocksOfType(generated_model,'RateTransition',Simulink.FindOptions('SearchDepth',1));
     for i = 1:length(RateTransitionBlocks)
         BlockName = get_param(RateTransitionBlocks(i),'Name');
         if ~any(strcmp(BlockName,{'Data Type Conversion DAC1','Data Type Conversion DAC2'}))
             set_param([generated_model,'/',BlockName],'Commented','through');
         end
     end
     % uncomment the subsystem for logging
     set_param([generated_model,'/CPU Signal Logging'],'Commented','off');

Connect to Target Machine and Run Real-Time Simulation

The model can now be deployed to the Speedgoat real-time target machine. The three-phase two-level voltage source 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;
     while strcmp(tg.status,'running')
         pause(10);
     end

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.

     % Display grid voltage and converter current in SDI
     Simulink.sdi.clearAllSubPlots
     Simulink.sdi.setSubPlotLayout(2,1);
     allIDs = Simulink.sdi.getAllRunIDs;
     runID1 = allIDs(end);
     run3 = Simulink.sdi.getRun(runID1);
     run3.name = 'Real-Time Simulation';
     Vabc_grid = run3.getSignalsByName('Vabc_grid');
     Iabc_conv = run3.getSignalsByName('Iabc_conv');
     plotOnSubPlot(Vabc_grid.Children(1),1,1,true);
     plotOnSubPlot(Vabc_grid.Children(2),1,1,true);
     plotOnSubPlot(Vabc_grid.Children(3),1,1,true);
     plotOnSubPlot(Iabc_conv.Children(1),2,1,true);
     plotOnSubPlot(Iabc_conv.Children(2),2,1,true);
     plotOnSubPlot(Iabc_conv.Children(3),2,1,true);
     Simulink.sdi.view;

Alternatively, you can measure the signals at the analog output of the IO334.

See Also

Functions

Related Topics