Main Content

Model Design for AXI4 Slave Interface Generation

To perform lightweight data transfer or to access control registers, use AXI4 slave interfaces. The AXI4 slave interfaces include the AXI4 and AXI4-Lite interfaces. With the HDL Coder™ software, you don't have to implement AXI4 or AXI4-Lite protocol in your model. The software generates AXI4 or AXI4-Lite interfaces in the HDL IP core.

When you model your design, specify the data ports, you want to map to the AXI4 slave interfaces. HDL Coder then maps the data ports to memory-mapped registers and allocates address offsets for the ports.

Considerations

When you map your DUT ports to AXI4 or AXI4-Lite interfaces:

  • You can map all scalar, vector, or bus ports in your design to either AXI4 or AXI4-Lite interfaces.

  • You cannot map some DUT ports to AXI4 interfaces and other DUT ports to AXI4-Lite interfaces for the same design.

Map Scalar Ports to AXI4 Slave Interface

When you use scalar data types at the DUT interface ports, you can directly map the interface ports to AXI4 or AXI4-Lite interfaces. The code generator assigns a unique address to each data port that you want to map to the AXI4 interface.

For an example that shows how to map scalar ports to AXI4-Lite interfaces, open the model hdlcoder_led_blinking.

openExample('hdlcoder/IPCoreGenWorkflowWithAMicroBlazeProcessorKC705Example',...)
'supportingFile','hdlcoder_led_vector.slx')

In this model, the subsystem led_counter is the hardware subsystem. It models a counter that blinks the LEDs on an FPGA board. Two input ports, Blink_frequency and Blink_direction, are control ports that determine the LED blink frequency and direction. All the blocks outside of the subsystem led_counter are for software implementation.

In Simulink®, you can use the Slider Gain block or the Manual Switch block to adjust the hardware subsystem's input values. The ARM® processor controls the generated IP core by writing to the AXI interface accessible registers in the embedded software. The output port of the hardware subsystem connects to the LED hardware. You can use the output port Read_back to read data back to the processor.

When you run the IP Core Generation workflow, in the Set Target Interface task, you see that the ports Blink_frequency, Blink_direction, and Read_back map to AXI4-Lite interfaces.

To learn more about this example, see:

Map Vector Ports to AXI4 Slave Interface

When you use vector data types at the DUT interface ports, you can directly map the interface ports to AXI4 or AXI4-Lite interfaces. The code generator assigns a unique address for each data port that you want to map to the AXI4 interface.

When you map vector ports, HDL Coder uses additional strobe registers for each port to maintain the synchronization with the IP core algorithm logic. For input ports, the strobe registers control the enable signals for a set of shadow registers, making the IP core algorithm logic see the updated vector elements simultaneously. For output ports, the strobe registers make sure that the vector data to be read is captured synchronously.

For an example that shows how to map vector ports to AXI4-Lite interfaces, open the model hdlcoder_led_vector.

open_system('hdlcoder_led_vector')

In this model, the subsystem DUT implements the LED blinking algorithm and has vector output ports. When you run the IP Core Generation workflow, you see that the input ports and output ports map to AXI4-Lite interfaces in the Set Target Interface task.

To learn more, see IP Core Generation Workflow with a MicroBlaze processor: Xilinx Kintex-7 KC705.

Map Double Data Types and Data Larger than 32 bits to AXI4-Slave Interfaces

When your DUT port has double data types or data types with width greater than 32 bits, HDL Coder:

  • Splits the data into individual 32 bit words to match the register width of the AXI4 or AXI4-Lite interface.

  • Assigns each 32 bit word to an individual address. You can find the resulting start and end addresses in the IP Core Generation report under the Register Address Mapping section.

  • Creates an additional strobe register to synchronize the data at the DUT boundary. The strobe logic behaves the same as the strobe register for vector ports. For more information on how vector ports are handled, see Map Vector Ports to AXI4 Slave Interface.

Learn how HDL Coder splits and maps data with bit widths greater than 32 bits to individual addresses. In this example model there are three input ports and three output ports:

  • Input and output port one: Scalar with uint64 datatype.

  • Input and output port two: Scalar with ufix45_En10 datatype.

  • Input and output port three: Vector of three elements with 64 bit datatype.

This image shows the example DUT with the corresponding datatypes on the input and output ports. Each port is mapped to the AXI4 interface.

Example DUT with greater than 32 bit width data mapped to DUT ports

When HDL Coder processes the DUT it converts the data into 32 bit words and maps each 32 bit word to a specific address. This image shows the target interface configuration and register address mapping sections of the generated IP core report. The register address mapping section mentions the start address, number of 32 bit words and the final register address for data with bit widths greater than 32 bits.

Target platform interface table and register address mapping sections of IP core generation report

For input port one the 64 bit data is split into two 32 bit words. The two words are mapped to addresses 0x100 and 0x104. Bits zero through 31 are mapped to 0x100 and bits 32 through 63 are mapped to 0x104. Output port one is split across addresses 0x148 and 0x14C.

For input port two the 45 bit data is split into two 32 bit words. The two words are mapped to addresses 0x110 and 0x114. Bits zero through 31 are mapped to 0x110 and bits 32 through 63 are mapped to 0x114. Output port two is split across addresses 0x158 and 0x15C.

For input port three, each vector element is split into two 32 bit words. This results in a total of six 32 bit words for the entire vector. The six words are mapped to the addresses 0x120, 0x124, 0x128, 0x12C, 0x130, and 0x134.

  • Bits zero through 31 of the first vector element are mapped to 0x120.

  • Bits 32 through 63 of the first vector element are mapped to 0x124.

  • Bits zero through 31 of the second vector element are mapped to 0x128.

  • Bits 32 through 63 of the second vector element are mapped to 0x12C.

  • Bits zero through 31 of the third vector element are mapped to 0x130.

  • Bits 32 through 63 of the third vector element are mapped to 0x134.

Output port three is split into 6 32 bit words. The six words are mapped to addresses 0x180, 0x184, 0x188, 0x18C, 0x190, 0x194.

Limitations

HDL Coder does not support mapping::

  • Bit widths greater than 128 bits to AXI4-Slave ports

  • Complex number data to AXI4-Slave ports

  • Shift register data to AXI4-Slave ports

Map Bus Data Types to AXI4 Slave Interface

When you use bus data types at the DUT interface ports, you can directly map the interface ports to AXI4 or AXI4-Lite interfaces.

When you map a port with bus data types to an AXI slave Interface, HDL Coder assigns a unique address for each bus element. HDL Coder treats bus ports as a group of independent scalar and vector ports. When HDL Coder assigns an address to bus elements, they are treated as separate registers and the addresses are not contiguous. When you change the address of a bus port in the target interface table, only the address of the first element changes.

Model Bus Element

Model a bus element by using a bus creator block or bus element block to create a bus port.

Model a bus element by using a bus creator block.

Different data types connected to a bus creator block with the bus creator block parameters window open

Model a bus element by using bus element blocks:Different data types connected to a bus element block with the bus element block parameters winddow open

For more information, see Map Bus Data Types to AXI4 Slave Interfaces.

Specify Initial Value of AXI4 Slave Registers

When you run the IP Core Generation workflow or the Simulink Real-Time FPGA I/O workflow, you can specify an initial value for input ports mapped to the AXI4 slave registers. You can specify an initial value when mapping to these target interfaces:

  • AXI4

  • AXI4-Lite

  • PCIe

By default, the initial value is zero. To specify a nonzero value:

  1. In the target platform interface table, when you map an input DUT port to an AXI4 slave interface, an Options button appears in the Interface Options column.

  2. Click the Options button, and then specify the RegisterInitialValue.

The specified value is saved on the DUT Inport blocks as the HDL block property IOInterfaceOptions in the Target Specification tab. For example, if you map a DUT input port to AXI4-Lite interface, set RegisterInitialValue to 5, and then run the Set Target Interface task. The IOInterfaceOptions property of that input port is saved with the value {'RegisterInitialValue','5'}.

To view the IOInterfaceOptions value, if the full path to your DUT port is hdlcoder_led_blinking/led_counter/LED, enter:

hdlget_param('hdlcoder_led_blinking/led_counter/LED',...
             'IOInterfaceOptions')

Specify the initial value for scalar ports.

hdlset_param('hdlcoder_led_blinking/led_counter/LED', ...
     'IOInterfaceOptions', {'RegisterInitialValue','5'});

To set the initial value for a bus, specify a struct whose field names match the bus element names. For example,bus data type initial values

You can also specify the initial value by using a variable defined in the MATLAB® workspace. For example:

bus1_initialvalue = struct('scalar_in1',1,'scalar_in2',2,'scalar_in3',3,'scalar_in4',4,'vector_in',[1 3])
bus initial value variable as bus data type initial value

Read Back Value of AXI4 Slave Interfaces

When you run the IP Core Generation workflow, you can read back the value that is written to the AXI4 slave registers by using the AXI4 slave interface. For example, you can read back the values that are written to the AXI4 slave registers by using the devmem command in the Linux® console of the ARM processor. If you have HDL Verifier™ installed, you can use the AXI Manager IP to read back the values.

To use this capability, in the Generate RTL Code and IP Core task of the IP Core Generation workflow, select the Enable read back on AXI4 slave write registers check box, and then run the Generate RTL Code and IP Core task

When you run this task, HDL Coder saves the read back setting that you enabled on the model. In the HDL Block Properties of the DUT Subsystem, on the IP Core Parameter section of the Target Specification tab, you see a parameter AXI4RegisterReadback set to on. If you export the HDL Workflow Advisor run to a script, you see this setting saved on the model by using hdlset_param.

hdlset_param('hdlcoder_led_vector/DUT', 'AXI4RegisterReadback', 'on');

These examples show how you can read back values by using the devmem command in the Linux console with a program such as PuTTy™.

To read back values when mapping scalar ports to AXI4 interfaces, you first write values to the AXI4 registers, and then read back the values. You can see the memory address of the AXI4 registers in the IP Core Generation report.

To read back values when mapping vector ports to AXI4 interfaces, you first write to the AXI4 registers, then write the strobe register address with 0x1, and then read back the values. You can see the memory address of the AXI4 registers and the strobe register in the IP Core Generation report.

Optimize AXI4 Slave Read Logic

When your model contains several output registers and you want to read back data from multiple AXI4 slave registers, the read back logic becomes a long mux chain that can reduce the synthesis frequency. If you select the Enable readback on AXI4 slave write registers setting in the Generate RTL Code and IP Core task, HDL Coder adds a mux for each AXI4 register in the Address Decoder logic. As the number of AXI4 slave registers increases, the mux chain becomes longer, which further reduces the synthesis frequency.

You can optimize the readback logic and achieve the target frequency that you want. When you run the IP Core Generation workflow, in the Generate RTL Code and IP Core task, you see a setting AX4 slave port to pipeline register ratio. The default value of this setting is auto. This setting indicates how many AXI4 slave registers a pipeline register is inserted for. For example, an AX4 slave port to pipeline register ratio of 20 means that one pipeline register is inserted for every 20 AXI slave registers. The auto setting means that the code generator inserts a certain number of pipelines for the AXI4 slave ports depending on the number of ports and the synthesis tool that you specify. You can disable this setting or specify one of these valid values, off, 10, 20, 35, 50.

When you run this task, HDL Coder saves the value that you specified for the setting on the model. In the HDL Block Properties of the DUT Subsystem, on the IP Core Parameter section of the Target Specification tab, you see a parameter AX4SlavePortToPipelineRegisterRatio set to the value that you specified. If you export the HDL Workflow Advisor run to a script, you see this setting saved on the model by using hdlset_param.

hdlset_param('hdlcoder_led_vector/DUT', ... 
                    'AXI4SlavePortToPipelineRegisterRatio', '20');

Related Examples

More About