Project 3 The AXI4 Bus
AXI bus operations, and design verification using the Logic Analyzer and Simulator
Since its introduction in about 2003, the AXI bus has steadily grown in popularity, and it is now accepted as the standard interface for connecting custom IP blocks to processors. ZYNQ uses the AXI bus to move data between the ARM and FPGA, so any custom IP blocks in the FPGA that work with the processor must include an AXI interface block.
This project focuses more closely on the AXI bus, and the AXI-FPGA interface in particular. We will look at Xilinx’s implementation, but since AXI is independently specified and used by almost all IC manufactures, knowledge gained using the Xilinx tools is applicable to other environments as well.
This project starts with a tutorial showing how to use Xilinx’s hardware debugger tool (also known as a “logic analyzer”) to capture, record and visualize AXI bus signals in real time as the circuit operates. By monitoring a real circuit as it operates, and examining the time-course of important signals, you get a definitive view of exactly what’s happening. Capturing and recording signals as a circuit operates is the definitive way to debug a circuit. As circuits get more involved and complex, a logic analyzer is an invaluable debugging tool – it’s worth spending time to learn how to use it.
After completing the tutorial, you will create your own IP block to handle AXI write and read transactions. You will simulate your new IP block to gain more experience with the AXI bus and signal timing, and then use the block to read the switches and buttons.
The ZYNQ device uses the AXI bus to connect the FPGA to the ARM, so going forward, all of your projects will include an AXI bus component. The topic document provides a good introduction to AXI bus operations, and there are many other on-line resources as well. You are encouraged to read a few other AXI bus descriptions (such as those found on the ARM and Xilinx sites) to build a more complete understanding.
1. Demonstrate AXI4-Lite Read/Write Transaction at Runtime
Follow the tutorial, examine the AXI4-Lite interface at runtime and prove it’s working correctly.
2. Create your own AXI4-Lite Logic
The tutorial demonstrates how to handle AXI4-Lite write transactions into to a set of registers in the FGPA. After completing the tutorial, modify the module to handle the AXI reads as well as AXI writes. A module definition is provided below, but you need to write the logic and add it to your module.
my_axi_led( input axi_clk, input axi_rstn, input [31:0] axi_write_data, input write_data_valid, output write_data_ready, input [1:0] axi_write_addr, input write_addr_valid, output write_addr_ready, output [1:0] axi_write_resp, output write_resp_valid, input write_resp_ready, input [1:0] axi_read_addr, input read_addr_valid, output read_addry_ready, output [31:0] axi_read_data, output [1:0] axi_read_resp, output read_data_valid, input read_data_ready, output [3:0] led, output [5:0] rgb_led );
Now create a new IP in the IP packager called ‘mycustomled’. In the auto-generated top-level module, remove the instantiation of Xilinx’s AXI logic and add your own. Make sure you connect all AXI4-Lite signals properly. Modify your logic to include two memory mapped registers - one register to hold values for 4 green LEDs, and the other to hold values for the two RGB LED’s (one bit per each of the six channels).
3. Simulate an AXI IP cores AXI4-Lite Write Transaction
Create a testbench and simulate an AXI4-Lite write transaction for your IP core. Look at each of the channels, and verify that their operation is correct. The tutorial will guide you.
myled IP’s AXI4-Lite Interface’s Read Transaction
Based on your experience from requirement #3, simulate an AXI read transaction and confirm it’s working correctly. You will need to implement another task named
axi_read with a 32-bit input address to simulate the read transaction.
The following is a template for the
// Verilog task: axi_read task axi_read; // 'addr': 32-bit address (first parameter) input [31:0] addr; begin // Prepare the address and control lines // Wait until the Read Address handshake occures // Wait for handshake on the Read Data Channel end endtask
After you’ve implemented the task
axi_read, you can use the following template to test your AXI peripheral (Make sure you try reading and writing various values).
initial begin // Assert Reset Signal // Wait for 2 clock cycles, then deassert reset // write data to your peripheral // read data from your peripheral end
To simplify the task of reading and writing multiple values, use loops along with your written tasks to cut down on code copy and pasting.
5. Create a new IP named
myswitches_buttons and use it to trigger the LEDs
Make a new IP core that reads the current values of the switches and buttons on the blackboard. You’ll need to modify the generated code in the IP-packager to do this. Write a C program that uses your new switch/button IP core to control your LED module you made in the previous project. As always you should make a software API for your IP core (make sure you create aptly named header and source files).
The memory map for your custom IP core can look like the following table:
|IP_BASE_ADDR+0||Switches||9:0||Reading from this register returns the values of the switches|
|IP_BASE_ADDR+4||Buttons||3:0||Reading from this register returns the values of the buttons|
Simulate Before Implementation. You will save significant amount of time if you create a test bench for your IP and make sure that you are able to read data.
1. Debug the
myswitches_buttons IP and
my_LED IP Transaction during runtime
Setup debugs for both IPs (
myswitches_buttons IP and
my_LED IP) and using the Integrated Logic Analyzer (Debug) prove both transactions on the AXI bus are correct.