top of page
Writer's pictureAngelo Jacobo

UberDDR3 Update: AXI4 Interface - Post #4

UberDDR3 new feature alert: AMBA AXI4 interface is now available! Previous versions only had the pipelined Wishbone interface (B4 version Wishbone Standard). This blog post will detail on the implementation of this AXI4 interface, how to use this feature in your next project, and end with an example simulation using the AXI Traffic Generator IP from Vivado.


Table of Contents:


I. Implementation Process

The AXI4 interface is built on top of the Wishbone interface by adding an AXI to Wishbone converter. We used an open-source AXI to Wishbone bridge from the ZipCPU wb2axip repository, which is already formally verified and tested. This bridge takes AXI commands and converts them into pipelined Wishbone commands.


Analyzing this bridge, it has two main parts: a read and a write half, connected through a Wishbone arbiter. The write half consists of the write address, data, and response channels from the AXI master and generates the Wishbone signals:

Meanwhile, the read half consists of the read address and read data channels and also generates Wishbone signals:


Notice there are now two sets of Wishbone signals coming from each half. But we only need one! That’s where the Wishbone arbiter comes in — it manages access between the read and write halves using a priority-based method. By default, it alternates access during simultaneous requests.


To integrate this bridge, we simply connect it on top of the ddr3_top module. This is what the ddr3_top_axi module is for. So finally, UberDDR3 now has AXI4 interface!


II. How to Use the UberDDR3 with AXI4 Interface

To use the AXI interface instead of the Wishbone Interface, instantiate the ddr3_top_axi module. Make sure to include all Verilog files inside rtl/axi directory, as they contain the necessary components for the AXI to Wishbone bridge.


The ddr3_top_axi module uses the standard AXI4 interface. I will not elaborate on the mechanism behind AXI4 protocol, but a great starting guide on AXI4 is this Introduction to AMBA AXI4.


III. Test and Simulation with AXI Traffic Generator IP

For testing and simulation of this new AXI interface, we will use the testbench ddr3_axi_traffic_gen_tb. This testbench instantiates the ddr3_top_axi, the Micron DDR3 model, and the AXI traffic generator IP from Vivado.

Our intent here is for the AXI traffic generator to act as the AXI Master of UberDDR3. The read and write transactions received by the UberDDR3 should then properly be reflected to the DDR3 RAM. Straightforward and very simple!


III.I Setting Up a New Vivado Project with UberDDR3

1. Retrieve the UberDDR3 repository by git cloning:

Or if you do not have git installed, go to my GItHub repo:

then click the <> Code button and then Download Zip. Unzip this file after downloading.


2. Create a new Vivado project (as shown below, I named it uberddr3_test). Then on Add Sources page click Add Directories, then choose the folder UberDDR3 which we just cloned earlier.


3. Skip the Add Constraints page and Choose Board page, as we will only be doing testbench simulation.


III.II Generate the AXI traffic Generator IP

1. Under the hierarchy of Simulation Sources, set the module ddr3_axi_traffic_gen_tb as the top module. Notice how the module axi_traffic_gen_inst is still missing, this is the AXI traffic generator IP from Vivado. We have to generate this IP.


2. Click on IP Catalog, search for keyword "AXI traffic", and then open up the AXI Traffic Generator IP.


3. Choose Custom for Profile Selection, AXI4-Lite for the Protocol, then System Test for the Mode.


We are using an AXI4-Lite in this simulation since the full AXI4 option requires a processor to handle the generated traffic, but that will make this testbench too complicated. For a processor-less AXI traffic generator, we have to use the AXI4-Lite. Lastly, we chose System Test for the mode so we can generate both read and write AXI transactions.


We need to specify COE files for the address, data, mask, and control, replacing the need for a processor. You can find these COE files in the testbench/axi_tb directory. After choosing these files, it should look like this:


 

III.II.I How to create your own COE files?

Let us take a break here. You might ask how to generate the COE files yourselves, well you can manually create one yourself using the sample COE files as template. But on my case, I use this open source project which is a python script to manage and generate the COE files.


Let us run through shortly how you can use this COE file generator.



2. Inside the directory of the cloned repo, open a new terminal then install tkinter:

Then run the python script:

This will open a GUI:


3. Follow the instructions in the project repo on how to use this GUI. Basically, we specify the AXI transactions that will be generated by the AXI traffic generator. Specifically, we need to specify the access type (read or write), address of the transaction, write data, and write mask.


There is already a given atg file which you can just load on this GUI. As shown below, the AXI transactions are alternating writes and reads. Note that AXI is byte-addressable, thus we increment by 16 bytes per transaction here (or 'h10 as shown below) since the testbench instantiates an x16 DDR3 (16 bits * 8 burst = 128 bits or 16 bytes).


4. Click on Export to generate the COE files (files will be generated inside the axi-traffic-gen repository).

 

3. The AXI traffic generator IP should now be available. Next click Run Simulation.


4. The default waveform configuration is not a good starting point to explore the design, as it does not contain the signals we actually want to see. Click on File > Simulation Waveform > Open Configuration. Choose the ddr3_axi_traffic_gen_behav.wcfg inside testbench/axi_tb/.


III.III Explore the Simulation Results

UberDDR3 will go through the power-up sequence and calibration stages. Running the simulation will take some time, for the mean time you can go through the previous blog post, Getting Started with UberDDR3 (Part 1), as it details the power-up sequence and calibration of UberDDR3 via simulation.


Once it finishes calibration, the AXI traffic generator will be released from reset. Shown below are the first four AXI transactions.


The first transaction writes the data 0x1234567 to address 0x00. The second transaction reads back the data from that same address of 0x00. As shown above, we can verify that the data read back matches what was written: 0x1234567.


The third transaction writes 0x89abcdef data to address 0x10 and then the fourth transaction is reading back that data. Again, the data read back matches what was written: 0x89abcdef.


We can also look on the Wishbone transaction received by the UberDDR3 (converted from AXI via the AXI to Wishbone bridge). Shown below are the first four Wishbone transactions. First transaction writes to address 0x00 with data 0x1234567 while second transaction reads that data back. And as shown below, the data read back matches what was written: 0x1234567.

Third transaction writes to address 0x01 with data 0x89abcdef while fourth transaction reads back that data.


You might wonder why the next Wishbone address after 0x00 is 0x01 instead of 0x10 (or decimal 16) as in the AXI transaction? As mentioned earlier, AXI is byte-addressable so we need to increment by 16 bytes (DDR3 used here is x16: 16 bits * 8 burst = 128 bits or 16 bytes). But the Wishbone transaction is word-addressable, where a single address already pertains to all 16 bytes of data word, thus we increment the address only by one.


Note that these AXI transactions just follow what we had specified on the COE files. The simulation will contain 16 AXI transactions (8 writes and 8 reads), and you can verify on the waveform how all data read back matches what was written.


And there you go, we are now done with this simple testing and simulation of UberDDR3 with AXI interface!


IV. Conclusion

By using the open-source AXI to Wishbone bridge from ZipCPU, we've easily added AXI4 functionality to our existing Wishbone interface. This blog explained the implementation process, how you can use the UberDDR3 with AXI4 interface in your projects, and demonstrated a simple guide for testing and simulation with Vivado's AXI Traffic Generator IP.


That wraps up this post. Catch you in the next blog post!

244 views

Comments


Computer Processor

Subscribe to Our Newsletter

Thanks for submitting!

bottom of page