FPGA Based Beamforming in Simulink: Part 2 - Code Generation
This tutorial is the second of a two-part series that will guide you through the steps to generate HDL code for a beamforming algorithm and verify that the generated code is functionally correct. The first part of the tutorial FPGA Based Beamforming in Simulink: Part 1 - Algorithm Design shows how to develop an algorithm in Simulink suitable for implementation on hardware, such as a Field Programmable Gate Array (FPGA), and how to compare the output of the fixed-point, implementation model to that of the corresponding floating-point, behavioral model.
This tutorial uses HDL Coder™ to generate HDL code from the Simulink® model developed in part one and verifies the HDL code using the HDL Verifier™. We use the HDL Verifier™ to generate a cosimulation test bench model to verify the behavior of the automatically generated HDL code. The test bench uses ModelSim® for cosimulation to verify the automatically generated HDL code.
The Phased Array System Toolbox™ Simulink blocks model operations on framed, floating-point data and provides the behavioral reference model. We use this behavioral model to verify the results of the implementation model and ultimately the automatically generated HDL code.
HDL Coder™ generates portable, synthesizable Verilog® and VHDL® code for over 300 Simulink blocks that support HDL code generation. Those Simulink blocks operate on serial data using fixed-point arithmetic with proper delays to enable pipelining by the synthesis tool.
HDL Verifier™ lets you test and verify Verilog® and VHDL® designs for FPGAs, ASICs, and SoCs. We'll verify RTL generated from our Simulink model against a test bench running in Simulink® using cosimulation with an HDL simulator.
This tutorial assumes that you have a properly setup Simulink model that contains a subsystem with a beamforming algorithm designed using Simulink blocks that use fixed-point arithmetic and support HDL code generation. FPGA Based Beamforming in Simulink: Part 1 - Algorithm Design shows how to create such a model.
Alternatively, if you start with a new model, you can run
hdlsetup (HDL Coder) to configure the Simulink model for HDL code generation. And, to configure the Simulink model for test bench creation needed for verification, you must open Simulink's Model Settings, select Test Bench under HDL Code Generation in the left panel, and check HDL test bench and Cosimulation model in the Test Bench Generation Output properties group.
Comparing Results of Implementation Model to Behavioral Model
Run the model created in the FPGA Based Beamforming in Simulink: Part 1 - Algorithm Design to display the results. You can run the Simulink model by clicking the Play button or calling the sim command on the MATLAB command line as shown below. Use the Time Scope blocks to compare the output frames visually.
modelname = 'SimulinkBeamformingHDLWorkflowExample'; open_system(modelname); % Ensure model is visible and not obstructed by scopes. open_system(modelname); set(allchild(0),'Visible','off'); sim(modelname);
Once you verify that your fixed-point, implementation model produces the same results as your floating-point, behavioral model, you can generate HDL code and test bench. To do that, you must first set the appropriate HDL Code Generation parameters in Simulink via the Configuration Parameters dialog. For this example, we set the following parameters in Model Settings under HDL Code Generation:
Target: Xilinx Vivado synthesis tool; Virtex7 family; Device xc7vx485t; package ffg1761, speed -1; and target frequency of 300 MHz.
Optimization: Uncheck all optimizations except Balance delays
Global Settings: Set the Reset type to Asynchronous
Test Bench: Select HDL test bench and Cosimulation model
The reason we turn off optimizations is because some blocks used in our implementation are already HDL-optimized blocks, which could conflict.
HDL Code Generation and Test Bench Creation
Once you've set Simulink's Model Settings, you can use HDL Coder™ to generate HDL code for the HDL Algorithm subsystem. For an example, see Generate HDL Code from Simulink Model (HDL Coder).
% Uncomment these two lines to generate HDL code and test bench. % makehdl([modelname '/HDL Algorithm']); % Generate HDL code % makehdltb([modelname '/HDL Algorithm']); % Generate Cosimulation test bench
Notice that when you execute the makehdl command, information is displayed in the MATLAB command window. In that information is the amount of delay added during the automatic code generation process. In this case 24 delays are added which results in an extra delay of 24*1ms = 24ms. This delay will be noticed when looking at our final results which have a total delay of 79ms.
Also, because of this extra delay added during automatic code generation the output of our floating-point, behavioral model needs to be delay balanced by adding 24 delays to the original 55. This will align the output of the behavioral model with the implementation model as well as the cosimulation output.
After generating the HDL code and test bench a new Simulink model named gm_<modelname>_mq containing a ModelSim® block is created in your working directory, which looks like this:
% Uncomment the following two lines to open the test bench model. % modelname = ['gm_',modelname,'_mq']; % open_system(modelname);
At this point, you might want to change the delay setting in HDL Latency block to 79 to account for the 24 delays added by the code generation process. Using a delay of 79 will ensure that the behavioral model output is time-aligned with the output of the implementation and cosimulation output.
HDL Code Verification via Cosimulation
The following steps will launch ModelSim; therefore, make sure that the command to start ModelSim, vsim, is on the path of the machine you're on.
To run the cosimulation model, first double-click the blue rectangular box in the upper-left corner of the Simulink test model to launch ModelSim.
Run the Simulink test bench model to display the simulation results. You can run the Simulink model by clicking the Play button or calling the sim command on the MATLAB command line as shown below. The test bench model includes Time Scope blocks to compare the output of the cosimulation performed with ModelSim with the output of the HDL subsystem in Simulink.
% Uncomment the following line, if ModelSim is installed, to run the test bench. % sim(modelname);
After starting ModelSim, running the Simulink test bench model will populate the Questa Sim with the HDL model's waveforms and Time Scopes in Simulink. Below are examples of the results in Questa Sim and Simulink scopes.
NOTE: You must restart Questa Sim each time you want to run the Simulink simulation. You can do that by executing "restart" at the Questa Sim command line. Alternatively, you can quit Questa Sim and re-launch it by double-clicking the blue box in the upper-left corner of the Simulink test bench model.
The Simulink scope below shows both the cosimulation and HDL model (DUT) producing a 79ms delayed version of the original signal produced by the behavioral model, as expected, with no difference between the two waveforms. The 79ms delay is due to the original 55ms delay added in the HDL Algorithm subsystem to enable pipelining by the synthesis tool and an additional 24ms delay due to the delay balancing that's done during the automatic HDL code generation. The additional 24 delays added is reported during the code generation step above.
The Simulink scopes comparing the results of the cosimulation can be found in test bench model inside the Compare subsystem, which is at the output of the HDL Algorithm_mq subsystem.
% Uncomment the following line to open the subsystem with the scopes. % open_system([modelname,'/Compare/Assert_beamformingOutHDL'])
This example is the second of a two-part tutorial series on how to automatically generate HDL code for a fixed-point, sample-based beamforming algorithm and verify the generated code in Simulink. The first part of the tutorial FPGA Based Beamforming in Simulink: Part 1 - Algorithm Design shows how to develop an algorithm in Simulink suitable for implementation on an FPGA. This example showed how to setup a model to generate the HDL code and a cosimulation test bench for a Simulink subsystem created with blocks that support HDL code generation. It showed how to setup and launch ModelSim to cosimulate the HDL code and compare its output to the output generated by the HDL implementation model.