This post lists step-by-step instructions for creating an AXI slave Central Data Management Access (CDMA) controller, integrating the slave into a Zynq-7000 system using Vivado, writing a driver that exercises the CDMA, and running everything on a ZC702. More commonly referred to as DMA, DMA's are useful for passing data between a CPU (in this case, the Processing System (PS)) and external peripherals. DMA allows the PS to be idle while transfers are happening, freeing up the PS to do other things, and access the data when it's convenient for the PS to do so. Use cases include reading/writing to memory, to a radio controller, HDMI, Serial Busses, etc.
As shown in the high-level diagram below, this design uses general-purpose AXI to interface the ARM A9 processor with the CDMA, and high-performance AXI to interface the CDMA with DDR memory on a ZC702 prototype board. Pseudo-random data is stored and read back in a two transaction CDMA transfer. The returned data is compared with the sent data to verify the CDMA transaction completed successfully.
Credit: Xilinx
Versions Used
Xilinx Vivado 2018.2 & SDK 2018.2
ZC702 Rev 1.1
Windows 10 Professional v1909
Before you Start
Review the ZC702 JTAG and serial port set up instructions @ [link]. These instructions are also reviewed below.
Contents
Part 1: Create the Vivado Project
Part 2: Create the Zynq-7000 in IP Integrator
Part 3: Create the CDMA AXI Slave and Concat IP blocks
Part 4: Connect the Interrupt Lines
Part 5: Configure the PS High Performance AXI buses
Part 6: Configure the CDMA
Part 7: Automate remaining connections
Part 8: Address configuration
Part 9: Create a Top-Level HDL Wrapper
Part 10: Synthesize and Generate the Bitstream
Part 11: Export the Design and Open the SDK
Part 12: Install the USB-to-UART Driver and Get the COM Assignment
Part 13: Configure the Board to Boot from JTAG, Connect it to the PC and Power it On
Part 14: Create the Test App and BSP
Part 15: Test Debug Run + Further Config
Part 16: Test the CDMA Module
Part 1: Create the Vivado Project
Step 1:
A: Press Start
B: Expand Xilinx Design Tools
Step 2: Select Vivado 2018.2
Step 3: Select Create Project
Step 4: Click Next
Step 5:
A: Set Project name to cdmaslave
B: Set Project location to C:/vivadoprjs (create C:/vivadoprjs if it doesn't exist)
C: Click the Create project subdirectory checkbox
D: Click Next
Step 6:
A. Select RTL Project
B. Check the Do not specify sources at this time check box
C. Click Next
Step 7:
A. Click Boards
B. Type ZC702
C. Click on the ZYNQ-7 ZC702 Evaluation Board box
D. Click Next
Step 8: Click Finish
Part 2: Create the Zynq-7000 in IP Integrator
Step 1: Click Create Block Design
Step 2: Use defaults, click OK
Step 3: Click +
Step 4:
A. Type Zynq
B. Double-click on ZYNQ7 Processing System
Step 5: Click Run Block Automation
Step 6: Use defaults, click OK
You should see:
Part 3: Create the CDMA AXI Slave, Concat, and Timer IP blocks
Step 1: Click + again
Step 2:
A. Type CDMA
B. Double-click on AXI Central Direct Memory Access
You should now see:
Step 3: Click + a third time
Step 4:
A. Type concat
B. Double-click on Concat
You should now see:
Step 5: Click + one final time
Step 6:
A. Type timer
B. Double-click on AXI Timer
You should now see:
Part 4: Connect the Interrupt Lines
Step 1: Double click the ZYNQ block
Step 2: Enable IRQ_F2P[15:0]
A. Click Interrupts
B. Check the Fabric Interrupts checkbox
C. Expand the Fabric Interrupts drop-down
D. Expand the PL-PS Interrupt Ports
E. Check the IRQ_F2P[15:0] checkbox
F. Click OK
You should then see the IRQ_F2P[0:0] port on Zynq:
Step 3: Connect IRQ_F2P[0:0] to xlconcat_0 interrupt output
A: Click and hold mouse button on IRQ_F2P[0:0]
B: Drag and release mouse button on xlconcat_0 dout[1:0]
You should see:
Step 4: Connect axi timer interrupt to concatenate block
A: Click and hold mouse button on axi_timer_0 interrupt
B: Drag and release mouse button on xlconcat_0 In0[0:0]
You should see:
Step 5: Connect CDMA interrupt to concatenate block
A: Click and hold mouse button on axi_cdma_0 cdma_introut
B: Drag and release mouse button on xlconcat_0 In1[0:0]
You should see:
Part 5: Configure the PS High Performance AXI buses
Step 1: Double click the ZYNQ block
Step 2: Enable the High Performance AXI interfaces
A. Click PS-PL Configuration
B. Expand the HP Slave AXI Interface drop-down
C. Check the S AXI HP0 Interface checkbox
D. Check the S AXI HP2 Interface checkbox
E. Click OK
The PS7 should now look like this:
Part 6: Configure the CDMA
Step 1: Double click the CDMA
Step 2: Configure the CDMA
A: Uncheck Enable Scatter Gather
B: Set Write/Read Data Width to 1024
C: Set Write/Read Burst Size to 32
D: Click OK.
The CDMA IP block should now look like this:
Part 7: Automate remaining connections
Step 1: Click Run Connection Automation
The completed diagram should now look as follows:
Step 2: Click OK to close the Critical Message. We will correct the address mapping in the next section.
Part 8: Address configuration
Step 1: Select the Address Editor tab
Step 2: Adjust the high performance addresses
A: Expand axi_cdma_0
B: Expand Data
C: Adjust S_AXI_HP0 Offset Address to 0x2000_0000
D: Set S_AXI_HP0 Range to 256M
E: Adjust S_AXI_HP2 Offset Address to 0x3000_0000
F: Set S_AXI_HP2 Range to 256M
Part 9: Create a Top-Level HDL Wrapper
A. Click Sources
B. Right-click design_1 (design_1.bd) (1)
C. Click Create HDL Wrapper...
D. Leave Let Vivado manage wrapper and auto-update, click OK
After a little time you should see:
Part 10: Synthesize and Generate the Bitstream
Step 1: Click Run Synthesis
Step 2: Use defaults, click OK
You'll see the status in the upper right corner.
A sample of the output:
Step 3:
Wait approximately 10 min (using a custom built CPU with a Ryzen 5 2400G, M.2 SSD, and DDR4 Memory) until you see Synthesis Complete in the upper right corner...
...and click OK to Run Implementation
Step 4: Use defaults, click OK
Again, you'll see status in the upper right:
Step 5:
Wait approximately 10 min (using a custom built CPU with a Ryzen 5 2400G, M.2 SSD, and DDR4 Memory) until you see Implementation Complete in the upper right corner...
A. Select Generate Bitstream
B. Click OK
Step 6: Use defaults, click OK
Again, you should see the status in the upper right:
Step 7: Click Cancel
You may see this window pop-up:
Feel free to send feedback, set a reminder or click No. If you click No you may see:
...click OK to dismiss.
Part 11: Export the Design and Open the SDK
Step 1:
A. Click File
B. Click Export
C. Click Export Hardware...
Step 2:
A. Click the Include bitstream checkbox
B. Click OK
Step 3:
A. Click File
B. Click Launch SDK
Note: you can open the workspace directly from the SDK by opening the SDK and specifying C:\vivadoprjs\cdmaslave\cdmaslave.sdk as the workspace.
Step 4: Use defaults, click OK
You should see:
Part 12: Install the USB-to-UART Driver and Get the COM Assignment
Steps:
A. Goto [link] for the Silicon Labs CP210x USB to UART Bridge VCP Drivers
B. Download and unzip the correct installer for your OS
C. Install the driver (I did not need to restart on Windows 10 Professional)
D. Right-click the Windows Icon
E. Click Device Manager
F. Expand the Ports (COM & LPT)
G. You should see Silicon Labs CP210x USB to UART Bridge
H. Note the COM port # (you'll need this later)
Part 13: Configure the Board to Boot from JTAG, Connect it to the PC and Power it On
Step 1: Set SW16 to JTAG mode [mode documentation see p.16]
For the rest of the jumpers see the high-resolution photo of the board in the correct state at [link]. Step 2: Connect a Micro-B to Type-A (host connection) USB cable from U23 (Diglent USB JTAG interface) to the host PC
U23:
Micro-B connector:
Type-A connector:
Step 3: Connect a Mini-B to Type-A (host connection) USB cable from J17 (CP2103GM USB-to_UART Bridge) to the host PC.
J17:
Mini-B connector:
Type-A connector:
Step 4: Turn on the board
Part 14: Create the Test App and BSP
Step 1:
A. Click File
B. Click New
C. Click Application Project
Step 2:
A. Type testcdmaslave into Project name:
B. Ensure the Board Support Package: Create New radio button is clicked and the name given is testcdmaslave_bsp
C. Click Next
Step 3:
A. Click Hello World
B. Click Finish
You should see:
Part 15: Test Debug Run + Further Config
These instructions allow debugging to be set up more easily than entering the details manually. After running a debug session, the Debug Configuration is fixed up to reset the FPGA and program the bitstream. The debugger COM port is also configured so that output can be read and the steps to test it and see Hello World are listed.
Step 1:
A. Right-click testcdmaslave
B. Click Debug As
C. Click Launch on Hardware (System Debugger)
Step 2: Click OK (if you see this)
If you see this message click Yes. We'll handle this in the next part.
...click Yes.
You should see the Debug Perspective display the code broken on init_platform():
A. Debug context on main()
B. helloworld.c on init_platform()
Step 3:
A. Click Run
B. Click Debug Configurations...
Step 4:
A. Ensure System Debugger using Debug_testaxislave on Local is selected (it should be)
B. Click the Reset entire system checkbox
C. Click the Program FPGA checkbox
D. Click Apply
E. Click Close
Step 5: Configure Debug View COM
A. Click SDK Terminal
B. Click the '+' (Connect to serial port.)
Step 6: Set Debug View COM settings
A. Enter the COM# from above
B. Click OK
You should see:
Step 7: Make sure you see Hello World on the console
A. Click on the bug
B. Click OK
C. Wait for the system to hit the breakpoint on main()
D. Click Resume
E. Wait until you see exit():
F. Click on SDK Terminal
G. Observe Hello World
Part 16: Test the CDMA Module
Step 1: Click on the C/C++ view
Step 2:
A. Expand testcdmaslave
B. Expand src
Step 3:
A. Right-click on src
B. Hover over New
C. Click File
D. Type testcdma.c
E. Click Finish
F. Copy and paste the following code into testcdma.c. Note that this code comes directly from this [link] and has some minor modifications to conform with Linux Kernel Code Convention and to be able to use a header file in future steps.
Step 4:
A. Right-click on src
B. Hover over New
C. Click File
Step 5:
A. Type testcdma.h
B. Click Finish
Step 6: Copy and paste the following code into testexample.h
int testcdmaexample(void);
Step 9: Update helloworld.c
A. Double-click helloworld.c
B. Add #include "testcdma.h” as shown
C. Add testcdmaexample(); as shown
D. Click save-all
Step 7: Run it
A. Click on the bug
If you see WARNING pop-up this click OK
B. Click Yes to confirm the switch to the Debug perspective
C. You should see execution stopped at main(
D. Click Resume
E. You should see that the DMA transfer was successful.
References
· Xilinx logo found via https://twitter.com/xilinxinc at [link]
· Zynq-7000 All Programable SoC: Embedded Design Tutorial [link]
· Xilinx Design Files [link]