%% Deploy Simscape Buck Converter Model to Speedgoat IO Module Using HDL Workflow Script
% This example shows how to deploy a Simscape(TM) buck converter model to
% a Speedgoat IO334 Simulink(R)-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 taret 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 
% <docid:hdlcoder_ug#example-sschil_speedgoat>.

% Copyright 2020 The MathWorks, Inc.

%% Setup and Configuration
% Before deploying your algorithm on the Speedgoat IO module:
%
% 1. Install the latest version of Xilinx(R) Vivado(R) as listed in 
% <docid:hdlcoder_gs#btp_jaq>. 
%
% Then, set the tool path to the installed Xilinx Vivado executable by using 
% the <docid:hdlcoder_ref#burmn3j-1> 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 <docid:slrealtime_doccenter#gscat>.
%
% 3. Install the Speedgoat Library and the Speedgoat HDL Coder Integration
% packages. See <https://www.speedgoat.com/help/hdlcoder/page/refentry_workflow 
% Install Speedgoat HDL Coder Integration Packages>.

%% Buck Converter Model
% To see the buck converter model, run this command:
%
%   open_system('sschdlexBuckConverterExample')
%
% 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
% subsytem 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;

%%
% <<../buck_converter_original_desktop_sim.png>>

%% 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 behaviour.
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 <docid:hdlcoder_ref#mw_0425d2c0-f407-4a8a-9e6b-b925600582db>
% 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;
%%
% <<../buck_converter_HDL_desktop_sim.png>>
%
% 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 <docid:hdlcoder_ug#mw_0366f2ea-94dd-4b68-9dad-4ca41d92b7dc>.

%% 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 
% <docid:hdlcoder_ref#bsgdu85> 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 <docid:hdlcoder_ug#bse5hm4>.

%% 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(R) 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 <docid:hdlcoder_ug#bu0ogdm-1>.
%
% 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')
%
% <include>hdlworkflow_buck_IO334.m</include>

%% 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.
%
% <<../buck_converter_IO334_slrt_model.png>>
%
% 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');
%
% <<../instrumentation_properties_sdi_buck_converter.png>>
%
% 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
%
% <<../buck_converter_real_time_simulation_sdi.png>>
%
% Alternatively, you can measure the signals at the analog output of the
% IO334. This figure shows a plot of the signals in MATLAB.
%
% <<../buck_converter_real_time_simulation_analog.png>>