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:
Xilinx Vivado Design Suite, with the supported version listed in HDL Language Support and Supported Third-Party Tools and Hardware
Xilinx Zynq Ultrascale+ MPSoC ZCU102 Evaluation Kit
HDL Coder Support Package for Xilinx Zynq Platform
HDL Verifier Support Package for Xilinx FPGA Boards
In this example, you:
Create a bus element by using bus creator blocks and map the bus element to an AXI4 slave interface.
Generate an HDL IP core with AXI4 Master interface.
Access large matrices from the external DDR4 memory on the Xilinx Zynq Ultrascale+ MPSoC ZCU102 Evaluation Kit board using the AXI4 Master interface.
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
Burst_Length into a bus data type element. For more information on the bus creator block, see Bus Creator
Functional Simulation in Simulink
You can simulate this example model and verify the simulation result by running this script in MATLAB:
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 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_m2s are mapped to the
AXI4 Master Read interface. The write channel ports like
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:
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.