Materials like Silicon Carbide (SiC) or Gallium Nitride (GaN) are making our power electronics converters faster and faster. This means small inductors and capacitors that make, in most cases, the cost of the devices decrease. This also means that the control devices also have to be faster, and not only the microcontrollers or the digital signal processors but the simulation benches where these devices are tested against models also have to follow the materials allowing faster simulations. For small models running on FPGA this is not a big deal. FPGA are capable of running models very fast but when we have complex models, this task can turn complicated.

If we analyze what an FPGA has to do to simulate a power electronics model, the first is capturing the control signal, which in the 95% of cases is a PWM signal so, let’s start from the beginning.

PWM signal

A PWM signal seems a square signal with two big differences. The first one is that the PWM has an offset, which means that the lower value of the signal will be zero. On the other hand, in a square signal, the time that the signal value is one is half of the period, making that the average value of the signal, or the DC component of the signal will be amplitude divided by two. In a PWM signal, the time in which the signal value is high is different than the time in which the value of the signal is low, so the DC value of a PWM can be different than the amplitude divided by two. We can find that PWM signals are defined by their period \(T\), and their duty cycle which can be calculated as \(\frac{t_{on}}{T}\). Also we can define the \(t_{off}\) as \(T-t_{on}\).

If we analyze the PWM signal applying a DFT, we can find what we mentioned before, there is a DC value in the PWM that corresponds with the duty cycle (\(D\)) times the Amplitude (\(A\))

\[DC = D \cdot A\]

Since the PWM signal is a kind of square wave, the DC component is not the only component we can find in the DFT. Like a square signal, the harmonic spectrum draws a \(sinc\) function starting in the base frequency. The asymmetry in the PWM signal has some effects on its frequency spectrum. In the next figure, we can find how the amplitude of the different harmonics changes according to the duty cycle of the signal. For example, for a duty cycle of 0,5 or 50%, we can see how the even harmonics are canceled, and the first harmonic is even greater than the DC value.

Now, that we know what is a PWM signal, the next is to learn how devices like the Speedgoat can capture that signal.

Capturing the PWM signal

Capturing a PWM signal is not different than capturing any other signal. We just need to “read” the input pin in order to know the state of the signal, and then execute the model with the read value. In addition, since the value of a PWM signal can be only ‘1’ or ‘0’, we just need a digital input to capture the signal, easy? Well, it depends.

While reading the digital input pin is a very easy task, an Arduino Nano can do it, calculating the effects of that value in the rest of the model can be very complex. In the next image, we can find three different PWM signals, all of them with the same duty cycle, so the DC value of each one is the same, but all three signals have different frequencies. In gray we can find the points where the PWM signal is captured with a frequency of \(fs\). If we don’t think in the model, we can see that for the first signal, the first harmonic is located at \(fs/16\). For the second one, the first harmonic is located at \(fs/8\), and for the third one is located at \(fs/4\). If we continue increasing the PWM frequency, the first effect we will find is aliasing, so images of high-power harmonics will appear near the DC value, distorting this value and making the signal unreadable.

Another effect that we may encounter if the sampling frequency is not far enough from the PWM frequency is related to the time step of the model. When the PWM signal is captured, the next step is calculating the next output of the model. According to the complexity of the model, the time spent in the calculation, the time step, could be so much, so the sampling frequency has to be reduced. If the sampling frequency is not reduced, we will find timing errors in the model since a new input is captured while the last output is not calculated yet. This effect may break the model and likely will stop the simulation. In the case that the time step of the model and the capture frequency will be so near, the entire model can be aliased, so the fidelity of the model will decrease, which can be an effect worse than the latest because this time, the model could seem working fine, but the results are far from the reality.

In any case, the fact that the PWM frequency and the time step of the model are close is a big problem. In order to fix this problem, we can apply the Subcycle Average technique. Let’s explain this.

Subcycle average

In a perfect world, the time step of a model would be zero. Since this is not a perfect world, this time is related to three different points.

  1. Complexity of the model.
  2. Speed of the device that has to execute the model.
  3. Performance of the solver.

The complexity of the model is a parameter that is (relatively) out of our hands. If we need to execute a Dual Active Bridge (DAB) model, we cannot change it by an RC filter model in order to make it simpler but is true that we can apply some modifications to the DAB model to make it easy to simulate. The second point is the speed of the device, which is obvious, if we can calculate the operations that describe the model quickly, we will be ready to read a new input sample before. Finally, the solver is the algorithm that generates the different equations from the model, so if the solver generates simpler equations to describe the same behavior, then the device will calculate these equations quickly, reducing the time step.

For the Speedgoat devices, the time step of the model can be calculated as follows.

\[Time Step = \frac{FPGA_{CLK}}{OversamplingFactor \cdot NSolverIterations}\]

The FPGA clock is related to the second point while the other parameters are related to the solver and the complexity of the model. For a model and a device, the time step is given so, in principle, the PWM frequency is limited by the time step, but just in principle. There is a method that allows us to decouple the PWM frequency and the time step of the model. Let’s take a look at the next diagram.

We can see an external control that generates a PWM signal at 100 kHz. Then, we can see a Speedgoat with a CPU that executes its model with a time step of 50 us, and an FPGA that executes the model at 10us (\(tsm\)) but, there is a little part of the FPGA model named PWM capture that is executed ten times faster (\(ts\)). If you are familiar with FPGA development, you will notice that we can find two different clock domains, and in the same way that we need to use synchronizers to connect different clock domains, this time we need to do the same with the block name Rate Converter.

Focusing on the PWM capture module, it has to oversample the PWM signal to get an accurate value duty cycle. The oversampling factor we need to apply depends on the PWM resolution we need. The PWM resolution is the number of steps in which we split a PWM cycle, therefore the oversampling factor will be \(\frac{T_{PWM}}{PWM_{resolution}}\). The output of the PWM capture module will be a value between 0 and 1 that represents the duty cycle of the signal, and it will be computed at \(tsm\). In the next model you will find the Simulink model that implements the PWM capture module where the value of the duty cycle captured is PWM pu.

The above model essentially counts the samples at \(ts\) where the input signal value is ‘1’, and also the samples in which the PWM signal value is zero. To obtain a value in the range 0 to 1, we need to divide by the oversampling factor \(tsm/ts\). The output ton of this module, for a PWM of 70 kHz, and a duty cycle of 20% is the next.

We can find how the PWM pu signal takes values in the range 0 to 1, and it is updated at \(tsm\) rate. The average value of PWM pu signal is 0.2. Having a continuous signal instead of a PWM, as we can expect, makes it possible to lose some of the information but, in terms of control, the regulators and systems, in general, have a reduced bandwidth, so to simulate correctly the control loop, we just need to compute the model faster than the bandwidth of the system. In the next figure we can see that the output of the control loop is indeed a continuous signal, so the PWM is “just” a way to transmit that signal to the power stage.

At this point, we have converted the PWM signal into a continuous signal that represents the average value of the signal of interest, and this is very important because we need to know which is our signal of interest, which is related to the bandwidth of the regulator. If we are controlling a DC-DC converter, we know that both the input and the output are DC, so, in short, the output of the regulator will be also a DC, therefore the bandwidth needed is small. In an AC-DC converter, the input signal is moving, so the regulator has to be able to control this moving signal, in other words, the bandwidth of the regulator has to be enough for the input signal, and not just the regulator but the bandwidth of the path from the regulator to the converter has also to be able to manage that bandwidth. This bandwidth can be controlled in a subcycle average model with the time-step of the model and the capture block.

Now, how can we integrate the subcycle average in a power stage model? If we take the Buck converter model I used in other articles, the switch expects a boolean signal, so we cannot connect into the control port a single signal with a value between 0 and 1, so we need to use different blocks to create the Buck converter model. In this example, I have used an integrated Buck Converter block.

Opening the configuration of this block, we can find that we can select the Switching Device. This selection allows us to use different kinds of transistors, and a different configuration named Averaged Switch.

Using this configuration, the “gate” of the switching device becomes a continuous input where we can connect a signal with values between 0 and 1, exactly what we need. Notice that the time step of this block is \(tsm\), the time step of the model execution.

To connect the PWM Capture module, which runs at \(ts\), and the Buck converter model, we need to include Rate Converter blocks, configuring them with a time step of \(tsm\).

If we activate the timing legend on Simulink, we can differentiate two different time-step regions. The fastest region, which runs at \(ts\) includes the PWM capture, a Data Type Conversion block, and the Rate Converter.

And the slowest region that runs at \(tsm\) includes the Buck converter model and the IO334 conversions.

To test the model, I added a PWM generator with a Step block in the duty cycle input, and a Low-pass filter to smooth the duty cycle step.

To execute the model I have created the next script where I can modify the time steps and the PWM frequency to check the results. The duty cycle of the model is set initially at 20% with a step to 80% in t=0.2.

In the first test, I used a realistic scenario where the model was executed six times slower than the PWM capture.

clear all
close all
clc

Ts = 1e-6;
Tsm = 6e-6;

Fpwm = 100e3;
Tpwm = 1/Fpwm;
Vdc = 100;

sim("sca_buck_ss.slx")

In the vout response, we can see the fast artifacts of the converter like the step oscillation. Due to the oversampling performed by the PWM capture module, the ramp is shown as different steps.

Zooming into the signal, we can see that the PWM pu signal has an average of 0.8, and the output voltage has a value of 80 volts. Notice that the ripple in the Vout is missing.

In the next example, I have increased the \(tsm\) to 15us.

clear all
close all
clc

Ts = 1e-6;
Tsm = 15e-6;

Fpwm = 100e3;
Tpwm = 1/Fpwm;
Vdc = 100;

sim("sca_buck_ss.slx")

This time, we can see that the PWM pu signal is close to the average value. In reality, we are applying an average filter to the PWM signal so is normal that the signal will be close to its DC value.

Zooming into the signal we can see that the vout is pretty similar to the last one.

This time I have increased the value of \(tsm\), making the ratio \(tsm/T_{PWM}\) an integer value, so the value of the PWM pu will be always the average value. In this case, talking DSP, the signal is a multiple of the sampling frequency, so the image signal is located at DC.

clear all
close all
clc

Ts = 1e-6;
Tsm = 20e-6;

Fpwm = 100e3;
Tpwm = 1/Fpwm;
Vdc = 100;

sim("sca_buck_ss.slx")

Increasing the value of \(tsm\) will make us obtain different responses, in other words, the image signals will be located in different frequencies. This time, with a value of 23us, we can see how the ripple in the PWM pu signal is decreased with respect to 15 us.

clear all
close all
clc

Ts = 1e-6;
Tsm = 23e-6;

Fpwm = 100e3;
Tpwm = 1/Fpwm;
Vdc = 100;

sim("sca_buck_ss.slx")

Finally, if we increase the value of \(tsm\) to 100us, all the harmonics disappear, and the output of the model is a continuous signal. Even with this model, we will be able to test a DC regulator, but is true that we can find some issues in the dynamic response.

clear all
close all
clc

Ts = 1e-6;
Tsm = 100e-6;

Fpwm = 100e3;
Tpwm = 1/Fpwm;
Vdc = 100;

sim("sca_buck_ss.slx")

Now, is the time to deploy this model in the Speedgoat Performance, more specifically, we are going to deploy the model in the FPGA of the Speedgoat Performance. To do that, first, we need to make some changes to the model to make it compatible with the HDL generation. First, we need to change the solver of the Simscape model to Partitioning Solver.

This solver splits the model into different parts and uses different solvers for each one, represented by its state variable. Once the solver is updated, we need to update the model using Ctrl+D. Now, we can check which solver is used for each part of the model. This information is available on Debug > Simscape > Statistics viewer.

In my model, we can see that two different solvers are used, and we have linear and non-linear variables. In the Variables tab, we can check that the non-linear variables are related to the Buck Converter block used, specifically, they are related to the conductance (\(G\)) equations.

While solving non-linear equations is not a big deal for a desktop computer, Simulink cannot generate HDL code to solve this kind of equations. Fortunately, the Buck Converter block is prepared to be implemented in HDL, so we can change the value of Integer for piecewise constant approximation of gate input to a different value than zero. This will treat the conductance when the switch is saturated (\(G_{sat}\)) as a piecewise constant integer with a fixed range, which will linearize the conductance equation.

To make this change, we need to open the mask of the Buck Converter block and set the Integer for piecewise constant approximation of gate input to, for example, 10.

Now, if we compile the model, and re-check the partitioning, we will see that now, all the equations are linear, so the model is ready to be implemented in HDL.

The complete model that we are going to deploy in the FPGA contains, in addition to the Buck model, the PWM capture block, the Rate Converter blocks and the gain blocks for the analog outputs.

On the top of the model where we had the PWM generation, we will have just the FPGA Block and the PWM generation we use in the simulation. Since the PWM input will be connected to a digital input of the IO334 we can comment out those blocks.

The next step is to generate the space-state model of the Simscape model. To generate this model, I have used the following script, which sets the number of iterations and enables the fixed cost.

sca_buck_ss_init;

open_system(['sca_buck_ss.slx']);
set_param(['sca_buck_ss/FPGA/Buck/Solver Configuration'],'DoFixedCost','on')

% Set number of solver iterations
set_param('sca_buck_ss/FPGA/Buck/Solver Configuration','MaxNonlinIter','2')

% Launch SS HDL advisor
sschdladvisor('sca_buck_ss')

On the window that will be opened, we just have to click on Run All to generate the new model.

The generated model has the same behavior as the Simscape model but uses just math blocks. This model will be the one we use to generate the HDL code. From the generated model, we can make right-click on the FPGA block, and open the HDL Workflow Advisor.

The steps here are similar to the previous post. The following image shows the Set Interface Window of the HDL Workflow advisor.

The subcycle average model I presented in this article uses the block Buck converter from the Simulink Simscape library, but sometimes we are working with a complex converter so we need to build the model using switches and passive elements. In these cases, we can use linearized switches to build the converter. Linearized switches are approximations of IGBTS or MOSFETS where gate input accepts values from 0 to 1. Simulink has a dedicated library for these elements. To open it you just have to execute SimscapeFPGAHIL_lib in the Matlab command window.

Opening them, we will see that the power side of the switch is the same for all the models, but the controller that sets the collector-emisor voltage, or the drain-source voltage for MOSFETs is what makes their behavior different. On the web, we can also find these models as Pejovic models.

To finish, I would like to mention that subcycle average models are not useful just for increasing the PWM frequencies. When we have a model in the FPGA that is controlled by a regulator that we are testing in the microprocessor, the output of the regulator is a continuous signal, so the model that runs in the FPGA has to accept continuous signals as control signals, so we need to use average models also in this case.

Subcycle average models are a tool that allows us to simulate any kind of model, even with high-speed switching frequencies, in a Speedgoat Performance. These models extract the essential behavior of the semiconductors and transform them into mathematical expressions that can be executed at high speed. The very good side of this method is that the fidelity of the model can be adjusted by modifying just the time-step at which is executed the model. The method has also limitations, and the most important is the aliasing. We have seen how making the time-step of the model a multiple of the PWM frequency all the ripple disappears. The key of all of this is that, if you have to use subcycle average you will be able to make your models faster, but you have to know what you are doing and, most importantly, the meaning of what you are obtaining.

To get more information about subcycle averaging MATLAB has some interesting content on its webpage. This video about “Improving Resolution for Real-time Simulation” provides some extra information about this topic.