Main Content

Map Bus Data types to AXI4 Slave Interfaces

This example shows how to map bus data types to an AXI4 slave interface, generate an HDL IP core with a AXI4 Master interface, perform matrix multiplication in HDL IP core, and write the output result to DDR memory.

Before You Begin

For this example, you must have the following software and hardware installed and set up:

Introduction

In this example, you:

  1. Create a bus element by using bus creator blocks and map the bus element to an AXI4 slave interface.

  2. Generate an HDL IP core with AXI4 Master interface.

  3. Access large matrices from the external DDR4 memory on the Xilinx Zynq Ultrascale+ MPSoC ZCU102 Evaluation Kit board using the AXI4 Master interface.

  4. Perform matrix vector multiplication in the HDL IP core and write the output result back to the DDR memory using the AXI4 Master interface.

This example models a matrix vector multiplication algorithm and implements the algorithm on the Xilinx Zynq FPGA board. Large matrices might not map efficiently to Block RAMs on the FPGA fabric. Instead, store the matrices in the external DDR memory on the FPGA board. The AXI4 Master interface can access the data by communicating with vendor-provided memory interface IP cores that interface with the DDR memory. This capability enables you to model algorithms that involve large data processing and requires high-throughput DDR access, such as matrix operations, computer vision algorithms, and so on.

The matrix vector multiplication module supports fixed-point matrix vector multiplication, with a configurable matrix size of 2 to 4000. The size of the matrix is run-time configurable through the AXI4 accessible register.

modelname = 'hdlcoder_axi_slave_bus_data_type';
open_system(modelname);

%
% Use HDL Coder to generate a custom IP core that performs large matrix
% operations on FPGAs by using external memory. In MATLAB, type:
%   hdladvisor('hdlcoder_axi_slave_bus_data_type/DUT')

Create Bus Element

Use a bus creator block to combine Matrix_Multiplication_On, Matrix_Size, and Burst_Length into a bus data type element. For more information on the bus creator block, see Bus Creator

open_system('hdlcoder_axi_slave_bus_data_type/InputSubsystem')
%

Functional Simulation in Simulink

You can simulate this example model and verify the simulation result by running this script in MATLAB:

hdlcoder_axi_slave_bus_data_type_simulation;

This script first initializes the parameters like Matrix_Size. By default, the Matrix_Size is 64, which means a 64-by-64 matrix. The default Matrix_Size is kept small for a faster simulation. After the DUT is implemented onto the FPGA board, the larger Matrix_Size is used as the FPGA calculation is much faster. You can also adjust these parameters in the script.

The script then simulates the model and verifies the result by comparing the logged simulation result to the expected value.

By default, the Matrix_Multiplication_On is true. The script verifies the matrix vector multiplication result.

When the Matrix_Multiplication_On is false, the script verifies the loop back mode, which means that the DUT read Burst_Length amount of data from DDR, and then wrote the data back to DDR.

Generate HDL IP Core with AXI4 Master Interface

Next, we start the HDL Workflow Advisor and use the IP Core Generation workflow to deploy the DUT on the Zynq hardware. For a more detailed step-by-step guide, refer to the Getting Started with Targeting Xilinx Zynq Platform example.

1. Set up the Xilinx Vivado synthesis tool path. Use your own Vivado installation path when you run the command. In the MATLAB command window type: hdlsetuptoolpath('ToolName', 'Xilinx Vivado', 'ToolPath', 'C:\Xilinx\Vivado\2020.1\bin\vivado.bat')

2. Start the HDL Workflow Advisor from the DUT subsystem hdlcoder_axi_slave_bus_data_type/DUT. The target interface settings are saved on the model. The Target workflow is IP Core Generation, and the Target platform is Xilinx Zynq Ultrascale+ MPSoC ZCU102 Evaluation Kit. The Reference Design is Default System with External DDR4 memory access and Target platform interface table settings are as shown

In this example, the bus datatype ports like matrix_info and input parameter ports like burst_from_ddr and burst start are mapped to the AXI4 interface. HDL Coder generates the AXI4 interface accessible registers for these ports. Later, you can use MATLAB to tune these parameters at run time when the design is running on FPGA board.

You can specify the bus data type initial values in the Target platform interface table by specifying either the initial values directly or by creating a variable to store the initial values in a struct data type and then using the variable name in the Interface Options window. To specify the initial value, click Options under the Interface Options column in the Target platform interface table.

Specify the initial values directly in the Interface Options window.

To store the bus data type initial values in a variable called businit, run this code:

businit = struct('matrix_mul_on',Matrix_Multiplication_On,'matrix_size',Matrix_Size,'burst_len',Burst_Length)

To specify the businit variable in the Interface Options window.

The AXI4 Master interface has separate read and write channels. The read channel ports like axim_rd_data, axim_rd_s2m, axim_rd_m2s are mapped to the AXI4 Master Read interface. The write channel ports like axim_wr_data, axim_wr_s2m, axim_wr_m2s are mapped to the AXI4 Master Write interface.

3. Right-click Generate RTL Code and IP Core, and then select Run to Selected Task to generate the IP core. You can find the register address mapping and other documentation for the IP core in the generated IP Core Report.

The report shows the individual bus elements and their address mappings:

If you specified the initial value for the bus element using the businit variable, the generated IP core report shows the bus element initial values.

4. Right-click Build FPGA Bitstream, and then select Run to Selected Task to generate the Vivado project.Build the FPGA bitstream.

During the project creation, the generated DUT IP core is integrated into the Default System with External DDR4 Memory Access reference design. This reference design is comprised of a Xilinx Memory Interface Generator IP to communicate with the onboard external DDR4 memory on the ZCU102 platform. The MATLAB as AXI Master IP is also added to enable MATLAB to control the DUT IP and to initialize and verify the DDR memory content.

Run FPGA Implementation on Xilinx Zynq Ultrascale+ MPSoC ZCU102 Evaluation Kit

After the FPGA bitstream is generated, run Program Target Device to program the FPGA board through the JTAG cable.

You can then run the FPGA implementation and verify the hardware result by running this script in MATLAB:

  hdlcoder_axi_slave_bus_data_type_hw_run_ZCU102.m

This script first initializes the Matrix_Size to 2000, which means a 2000-by-2000 matrix. You can adjust the Matrix_Size up to 4000.

The AXI4 Master read and write channel base addresses are then configured. These addresses define the base address that DUT reads from the external DDR memory, and writes to external DDR memory. In this script, the DUT reads from base address '80000000', and write to the base address '90000000'.

The MATLAB as AXI Master initializes the external DDR4 memory with input vector and matrix data and clears the output DDR memory location.

The DUT calculation is started by controlling the AXI4 accessible registers. The DUT IP core first reads input data from the DDR memory, performs the matrix vector multiplication, and then writes the result back to the DDR memory.

The output result is read back to MATLAB and compared to the expected value. The hardware results are verified in MATLAB.

Related Topics