Code Generation and Deployment | Developing Radio Applications for RFSoC with MATLAB & Simulink, Part 4
From the series: Developing Radio Applications for RFSoC with MATLAB and Simulink
In the final video of the series, see how to use Simulink® models with SoC Blockset™ to perform code generation and deployment on hardware. To start, the Simulink model used in the previous video is augmented with a radar target simulation and a command interface for remotely controlling the radar algorithm over a UDP link to the host computer. Then see a demonstration of the radar algorithm running on the ZCU111 board, controlled by a MATLAB® script. An overview of the Simulink model for HDL and C code generation comes next, with more details on the command interface and how it interacts with the processor and FPGA, as well as the details on portions of the algorithm running on the FPGA.
Next comes the process of HDL and C code generation. The SoC Builder tool within SoC Blockset is used to configure code generation, including task mapping, configuring the memory map, validating the Simulink model, and launching C and HDL code generation.
You can then view the generated Vivado® project in Vivado IP Integrator, including the range-Doppler IP core, DMA cores, and RF data converter block.
Once the process of building the application and generating the bitstream is complete, the SoC Builder tool connects to the ZCU111, loads the design, reboots the board, and downloads the application to enable testing controlled from a MATLAB session.
Published: 16 Feb 2021
In this video series you'll learn how to use a model based design approach to develop radio frequency applications for the Xilinx RFSoC platform. In part 3, we looked at a range doppler radar system and evaluated different hardware software partitioning strategies using a mix of simulation and hardware profiling analysis. Finally, in part 4, we'll show how to generate C and HDL code for the range doppler radar algorithm and automate the deployment of a prototype design to the Xilinx, ZCU111. Development kit.
So after flushing out the implementation details of our algorithm between hardware and software subsystems, we're ready to build a prototype designed to run on the board. So at this stage, we've added a couple of extra components to the design. On the FPGA side, we have a programmable target simulator, which allows us to transmit a radar target return over a loopback cable to the receiver.
This is important because now we can test our system without transmitting over the air. On the processor side, we had a command interface, which lets us control the radar remotely over a UDP link to host PC. Using HTML and embedded coder, we can generate HTML and C code directly from the Simulink model. And then with us to see blocks that we're able to automate, the building deployment of the application to the target ZCU111 board.
Let's take a look at this prototype system running. All right. So I have my ZCU111 board powered on connected over ethernet. And I'm going to run this script here, which is going to first start the application running on hardware and then configure my radar target simulator with two targets across four coherent processing intervals.
So here I have one target of 4,000 meters now there are 3,000. And we see them step here and move across the four CPIs. And so what's happening in MATLAB is each time the steps, I'm just sending a UDP packet to initiate a new CPI But on the hardware we're doing the range of velocity processing and sending back this range-doppler map that you see here.
And then on the right on the host PC in MATLAB we're feeding that range-doppler map into CFAR detector and then doing some clustering to pull out the single range of velocity estimates that you see here. So let's take a look at the models that I use to generate this application.
All right. So this is the top level model for our prototype system implementation. You notice that it looks pretty similar to the previous iteration of the model. We've got FPGA and processor subsystems partitioned out. We've added a couple of extra components here. We have the host UDP interface, so we can simulate the UDP packets exchange between the processor and the host machine.
We've added another memory channel here. So this is DMA from the processor memory, streaming into the FPGA. So we use this to program the radar target simulator. And then finally we have this RF data converter block here. This is going to give us the interface from the FPGA to the RF SSC ADC's dacs.
Let's dig in to just a couple spots here in the model on the processor side. So take a look at this UDP received function. So here this is our command and control interface right. So we're receiving a UDP packet and then parsing it here in this MATLAB function block.
So we have a command protocol that we've established here where we have certain values that indicate what's included in the packet and then we pass it accordingly, print status messages which will actually display in the terminal on the board. So most of what we're doing here is sending data to actually light registers on the FPGA. With this test mode enable able so we write to a register and then we also trigger this subsystem here.
Which is going to read the test mode data from a file, binary file on the file system, Linux and then we write that data to the DMA stream, memory map to stream interface, which is going to go to the FPGA. On the FPGA side, so this is where we can really get into some of the implementation details within an HTL coder.
So for example in the range processing. We see here doing things like pipeline in my design. And that's just something I like to do is color my pipeline delays blue this is just a regular delay block. But we're pipeline in the input and output here, we have a matched filter here, which we have two samples per clock cycle. So this implements a two sample vector FIR.
We're doing here using a lookup table. So you can see this is pipe lined as well, this multiplier. We have two pipeline stages coming in and out. And then we have a single pipeline delay for reading from RAM here with this lookup table. So let's see now how we can generate code from this mode.
So we start by going to the system on chip tab and click the Configure build and deploy button to launch the SOC builder wizard. So we're going to run through a couple of configuration steps for the model before we build. First, on the software side would review all the tasks in their mapping to event sources, fine with all these, so I'll OK.
Next, on the FPGA side we're going to review the memory map. And so this is what's going to show up in the address editor in the border. We have an entry here for our range-doppler TXRX subsystem which we're generating an IP core for. So we have a base address with the individual registers in the IP at their own offset addresses.
And so the processor can access these registers during runtime to configure various parameters and hardware. We see a couple of other entries show up. We have two memory channels in the design and so we see two entries for each of those. One here is just the best address in main memory, which is used for the DMA operations. And then another one for the DMA core itself, which is a discrete component in our provided sign.
Then we also see the RF data converter, IP shows up with its own base address. Next, will set the project folder used to hold all of the generated files. OK with that. Click Next. Here we're going to select the action for build in the software model.
I like to control when my software model executes, I don't want it to go in and run automatically. So I'm going to pick this build only option. Now I'm going to run through a couple of steps here to validate the settings in my model to the compile and just double check that all of my settings here are going to be valid for the build.
And then next we see all the build steps here. So first we're going to generate the C-code build a software application and then we'll run through the FPGA side first generating HTL, and an IP core for the range-
doppler subsystem, and then creative Vivado project, and then run through synthesis implementation in bitstream generation.
So I'm not going to run those now. I've already done that and we can just use the files that I've already built. Let's take a look at the Vivado project that gets generated and see how that corresponds to some of the components in the model. So use our IP integrated block design and Vivado
And if we Zoom in we'll see the range-doppler IP core that was generated. This IP has it actually light interface which is used to configure the registers in the core. We have ADC input and dac output, which are connected to the RF data converter in the block design.
Then we also have to actually stream interfaces which are connected to two DMA cores. So we have the stream to memory map, DMA, and then the memory map to stream DMA core. And these cores were inferred automatically because of the memory channel blocks that we have in the Simulink model.
Over in the bottom right the design here we could see the RF data converter block which is automatically inferred because of the RF data converter block in the Simulink model. And then if we look at the IP customization parameters here. So we see actually-- now looking back and Simulink that these parameters are propagated from the interface to Simulink. So we've configured the things like the sampling rate, interpolation mode, samples per clock cycle. All of these show up here they're automatically propagated when we generate the Vivado Project.
That's the power of the SSC builder tool. Is that we can dynamically generate the Vivado project based on the content of your Simulink model. So after my project is finished building you go back into SSC builder to program in board. So this time, I'm going to select Load existing binaries into the project folder.
And then I have my board powered on and connected over ethernet because we're going to download the FPGA bitstream and software application. All right. So my connection is good. Click Next. Then I'll click Load and Run. And there's a couple of steps that are happening under the hood here.
First, we're generating a new device tree which will be used by Linux. So the device tree needs to be updated to reflect the memory map on the FPGA. So we download the new device tree along with the FPGA bitstream and then update the bootloader variables so that these new files will be used the next time the board boots. Then we trigger a reboot of the board and finally download the software application.
All right. So once this finishes, I'll be able to run my test bench script from the host that I was running earlier, OK? Let's go back into MATLAB now. On the script. Then we see our test mode running like we saw before.
This concludes the video series. If you're interested in what you saw and want to learn more, you can check out mathworks.com/rfsoc to see all the ways that you can use MATLAB and Simulink for your next RFSoC project. Please contact your account manager if you'd like a trial of any of the products shown. Thank you for watching.