Main Content

FPGA-in-the-Loop

FPGA-in-the-loop (FIL) enables you to run a Simulink® or MATLAB® simulation that is synchronized with an HDL design running on an FPGA board. This link between the simulator and the board enables you to verify HDL implementations directly against Simulink or MATLAB algorithms. You can apply real-world data and test scenarios from these algorithms to the HDL design that is running on the FPGA.

In Simulink, you can use the FIL Frame To Pixels and FIL Pixels To Frame blocks to accelerate communication between Simulink and the FPGA board. In MATLAB, you can modify the generated code to speed up communication with the FPGA board.

FPGA-in-the-Loop Simulation with Vision HDL Toolbox Blocks

This example shows how to modify the generated FPGA-in-the-loop (FIL) model for more efficient simulation of the Vision HDL Toolbox™ streaming video protocol.

Autogenerated FIL Model

When you generate a programming file for a FIL target in Simulink, the HDL Workflow Advisor creates a model to compare the FIL simulation with your Simulink design. For details of how to generate FIL artifacts for a Simulink model, see FIL Simulation with HDL Workflow Advisor for Simulink (HDL Verifier).

For Vision HDL Toolbox designs, the FIL block in the generated model replicates the pixel-streaming interface and sends one pixel at a time to the FPGA. The model shown was generated from the example model in Design Video Processing Algorithms for HDL in Simulink.

The top part of the model replicates your Simulink design. The generated FIL block at the bottom communicates with the FPGA. ToFILSrc subsystem copies the pixel-stream input of the HDL Algorithm block to the FromFILSrc subsystem. The ToFILSink subsystem copies the pixel-stream output of the HDL Algorithm block into the Compare subsystem, where it is compared with the output of the HDL Algorithm_fil block. For image and video processing, this setup is slow because the model sends only a single pixel, and its associated control signals, in each packet to and from the FPGA board.

Modified FIL Model for Pixel Streaming

To improve the communication bandwidth with the FPGA board, you can use the generated FIL block with vector input rather than streaming. This example includes a model, FILSimulinkWithVHTExample.slx, created by modifying the generated FIL model. The modified model uses the FIL Frame To Pixels and FIL Pixels To Frame blocks to send one frame at a time to the generated FIL block. You cannot run this model as is. You must generate your own FIL block and bitstream file that use your board and connection settings.

To convert from the generated model to the modified model:

  1. Remove the ToFILSrc, FromFILSrc, ToFILSink, and Compare subsystems, and create a branch at the frame input of the Frame To Pixels block.

  2. Insert the FIL Frame To Pixels block before the HDL Algorithm_fil block. Insert the FIL Pixels To Frame block after the HDL Algorithm_fil block.

  3. Branch the frame output of the Pixels To Frame block for comparison. You can compare the entire frame at once with a Diff block. Compare the validOut signals using an XOR block.

  4. In the FIL Frame To Pixels and FIL Pixels To Frame blocks, set the Video format parameter to match the video format of the Frame To Pixels and Pixels To Frame blocks.

  5. Set the Vector size in the FIL Frame To Pixels and FIL Pixels To Frame blocks to Frame or Line. The size of the FIL Frame To Pixels vector output must match the size of the FIL Pixels To Frame vector input. The vector size of the FIL block interfaces does not modify the generated HDL code. It affects only the packet size of the communication between the simulator and the FPGA board.

The modified model sends an entire frame to the FPGA board in each packet, significantly improving the efficiency of the communication link.

FPGA-in-the-Loop Simulation with Multipixel Streaming

When using FPGA-in-the-Loop with a multipixel streaming design, you must flatten the pixel ports to vectors for input and output of the FIL block. Use Selector blocks to separate the input pixel streams into NumPixels vectors, and use a Vector Concatenate block to recombine the output vectors.

If each pixel is represented by more than one component, the FIL Frame To Pixels block has one data port per component and the FIL block has NumPixels×NumComponents ports. Split each component matrix into NumPixels vectors.

This model shows a multipixel, single component design.

Multipixel, single component FIL model

For VHDL code generation, in Configuration Parameters > HDL Code Generation > Global Settings > Ports, set the Scalarize ports parameter to DUT Level.

Configuration parameters, open to the HDL Code Generation > Global Settings pane and showing the drop down menu options for the Scalarize ports parameter

FPGA-in-the-Loop Simulation with Vision HDL Toolbox System Objects

This example shows how to modify the generated FPGA-in-the-loop (FIL) script for more efficient simulation of the Vision HDL Toolbox™ streaming video protocol. For details of how to generate FIL artifacts for a MATLAB® System object™, see FIL Simulation with HDL Workflow Advisor for MATLAB (HDL Verifier).

Autogenerated FIL Function

When you generate a programming file for a FIL target in MATLAB, the HDL Workflow Advisor creates a test bench to compare the FIL simulation with your MATLAB design. For Vision HDL Toolbox designs, the DUTname_fil function in the test bench replicates the pixel-streaming interface and sends one pixel at a time to the FPGA. DUTname is the name of the function that you generated HDL code from.

This code snippet is from the generated test bench TBname_fil.m, generated from the example script in Pixel-Streaming Design in MATLAB. The code calls the generated DUTname_fil function once for each pixel in a frame.

for p = 1:numPixPerFrm
    [pixOutVec( p ),ctrlOutVec( p )] = PixelStreamingDesignHDLDesign_fil( pixInVec( p ), ctrlInVec( p ) );
end

The generated DUTname_fil function calls your HDL-targeted function. It also calls the DUTname_sysobj_fil function, which contains a System object that connects to the FPGA. DUTname_fil compares the output of the two functions to verify that the FPGA implementation matches the original MATLAB results. This snippet is from the file DUTname_fil.m.

% Call the original MATLAB function to get reference signal
[ref_pixOut,tmp_ctrlOut] = PixelStreamingDesignHDLDesign(pixIn,ctrlIn);
  ...
% Run FPGA-in-the-Loop
[pixOut,ctrlOut_hStart,ctrlOut_hEnd,ctrlOut_vStart,ctrlOut_vEnd,ctrlOut_valid] ...
  = PixelStreamingDesignHDLDesign_sysobj_fil(pixIn,ctrlIn_hStart,ctrlIn_hEnd,ctrlIn_vStart,ctrlIn_vEnd,ctrlIn_valid);
  ...
% Verify the FPGA-in-the-Loop output
hdlverifier.assert(pixOut,ref_pixOut,'pixOut');

For image and video processing, this setup is slow because the function sends only one pixel, and its associated control signals, in each packet to and from the FPGA board.

Modified FIL Test Bench for Pixel Streaming

To improve the communication bandwidth with the FPGA board, you can modify the autogenerated test bench, TBname_fil.m. The modified test bench calls the FIL System object directly, with one frame at a time. These snippets are from the PixelStreamingDesignHDLTestBench_fil_frame.m script, modified from FIL artifacts generated from the example script in Pixel-Streaming Design in MATLAB. You cannot run this script as is. You must generate your own FIL System object, function, and bitstream file that use your board and connection settings. Then, either modify your version of the generated test bench, or modify this script to use your generated FIL object.

Declare an instance of the generated FIL System object.

fil = class_PixelStreamingDesignHDLDesign_sysobj;

Comment out the loop over the pixels in the frame.

%         for p = 1:numPixPerFrm
%            [pixOutVec( p ),ctrlOutVec( p )] = PixelStreamingDesignHDLDesign_fil( pixInVec( p ), ctrlInVec( p ) );
%         end

Replace the commented loop with the code below. Call the step method of the fil object with vectors containing the whole frame of data pixels and control signals. Pass each control signal to the object separately, as a vector of logical values. Then, recombine the control signal vectors into a vector of structures.

[pixOutVec,hStartOut,hEndOut,vStartOut,vEndOut,validOut] = ...
    fil(pixInVec,[ctrlInVec.hStart]',[ctrlInVec.hEnd]',[ctrlInVec.vStart]',[ctrlInVec.vEnd]',[ctrlInVec.valid]');
ctrlOutVec = arrayfun(@(hStart,hEnd,vStart,vEnd,valid) ...
    struct('hStart',hStart,'hEnd',hEnd,'vStart',vStart,'vEnd',vEnd,'valid',valid),...
    hStartOut,hEndOut,vStartOut,vEndOut,validOut);     

These code changes remove the pixel-by-pixel verification of the FIL results against the MATLAB results. Optionally, you can add a pixel loop to call the reference function, and a frame-by-frame comparison of the results. However, calling the original function for a reference slows down the simulation.

for p = 1:numPixPerFrm
     [ref_pixOutVec(p),ref_ctrlOutVec(p)] = PixelStreamingDesignHDLDesign(pixInVec(p),ctrlInVec(p));
end

After the call to the fil object, compare the output vectors.

hdlverifier.assert(pixOutVec',ref_pixOutVec,'pixOut')
hdlverifier.assert([ctrlOutVec.hStart],[ref_ctrlOutVec.hStart],'hStart')
hdlverifier.assert([ctrlOutVec.hEnd],[ref_ctrlOutVec.hEnd],'hEnd')
hdlverifier.assert([ctrlOutVec.vStart],[ref_ctrlOutVec.vStart],'vStart')
hdlverifier.assert([ctrlOutVec.vEnd],[ref_ctrlOutVec.vEnd],'vEnc')
hdlverifier.assert([ctrlOutVec.valid],[ref_ctrlOutVec.valid],'valid')

This modified test bench sends an entire frame to the FPGA board in each packet, significantly improving the efficiency of the communication link.

See Also

Blocks

Objects

Related Topics