Recently, I did a project tutorial covering how to integrate Diligent's new Digitizer Zmod on Eclypse Z7 into a custom design in Vivado/Vitis 2022.1 and I wanted to continue that thread with also showing how to use their AWG Zmod in a custom design as well.
Digilent's Analog Waveform Generator (AWG) Zmod is a SYZYGY-compatible Dual-channel 14-bit Digital-to-Analog Converter Module, that I'm again using on the Zynq-7000 based Eclypse Z7 FPGA development board and Vivado/Vitis 2022.1.
The DAC module in the AWG Zmod takes in a digital binary "code" that correlates to a specific analog value output. Varying this binary code in a given pattern is how one can use a DAC to create any desired waveform within the spec limits of the DAC chip and supporting circuitry. There are plenty of great articles and resources that explain the theory of operation of DACs so I won't dive into it here.
As a high level description of what this design is doing in hardware, the Zmod AWG Controller IP is instantiated in the block design of a Vivado project targeting the Eclypse Z7 with the input being fed values directly from DDR memory via an AXI DMA controller. This allows the C application running on the Zynq's ARM-core processor to write binary code values to the DDR that are then read out to the Zmod AWG Controller IP.
If you haven't already, create a new Vivado 2022.1 project targeting the Eclypse Z7 and add the Digilent Vivado library as a repository to the project. See my previous project post here for those steps.
Vivado Hardware DesignThe Zmod AWG Controller IP can be instantiated either directly in HDL or in a block design. Since there are lots of handy features in the block design workflow in Vivado such as connection automation and auto connect of target board peripherals, I'm using the block design workflow. I've broken up this section into subsections based on the IP blocks being added to the block design. Hopefully this is helpful to those adding the Zmod AWG to an existing design as well.
Zynq Processing System
First things first, the Zynq Processing System IP needs to be instantiated so the design has the hooks for its ARM-core processor for later. After the Zynq PS IP is added, the option to run Block Automation will appear that will apply the settings for the Zynq specific to the Eclypse Z7 board.
After running the Block Automation for the Zynq PS, double-click on it in the diagram to open its configuration window. A high-performance AXI port is required for the DMA controller in the PL to be able to access the DDR, so under PS-PL Configuration > HP Slave AXI Interface, enable S AXI HP0 interface:
Then under MIO Configuration > I/O Peripherals > GPIO, enable EMIO GPIO with a width of 2 (this will be explained in a later step):
Constant
Next, add a Constant IP. Open its configuration window and set its value to 0. Optionally, you can name it "gnd".
AXI DMA Controller
Add an AXI DMA Controller to the block design and open its configuration window. Disable the scatter gather engine unless you plan to specifically use it. Also also only leave read channel enabled unless specifically planning to use the write channel, and enable option to allow unaligned transfers for the read channel.
Click OK on the DMA's configuration window to save/apply changes. After the window closes, the option for connection automation will appear a few moments later. Run this resulting connection automation with the default settings Vivado wants to apply.
Clocking Wizard
Instead of adding a Clocking Wizard using the + button or Add IP... option from the right-click menu in the diagram, switch the Board tab for the option to connect board components/peripherals from the Eclypse Z7.
Under Clocks, right-click on System Clock and select the option Connect Board Component... Chose to connect the system input clock, clock_CLK_IN1
, to a new Clocking Wizard IP.
Open the Clocking Wizard's configuration window and make the following changes:
- Enable
clk_out1
with a frequency of 100MHz and a phase of 0 - Enable
clk_out2
with a frequency of 100MHz and a phase of 90 - Change the reset to Active Low to match the rest of the design.
AXIS Data FIFO
Add an AXIS Data FIFO to the block design, and enable the option for independent clocks for the master/slave AXIS ports.
This is to handle the clock domain crossing the binary codes go through coming out of the DDR and going into the Zmod AWG Controller.
To elaborate on this, the Zmod AWG Contoller requires that the DAC_Clk
be the same 100MHz frequency as DAC_InIO_Clk
, but 90 degrees out of phase from DAC_InIO_Clk
. In order to generate a clock with a 90 degree phase offset from another given clock while also remaining synchronous to it, the easiest way I found was to use a MMCM from a Clocking Wizard. However, you can't drive clk_in
of a Clocking Wizard with a PL clock (FCLK_CLK
) from the Zynq PS because it causes a redefinition of the PL clock in the Vivado tool. This is why I had to use the system clock of the Eclypse board to drive the Clocking Wizard.
This means all the clocks of the Zmod AWG Contoller are clocked by sys_clock
, putting it in a separate clock domain from the AXI DMA Controller in FCLK_CLK0
's domain. Simply using a FIFO with independent clocks was much easier than trying to convert everything to sys_clock
's clock domain (which I'm guessing would have some hangups of its own trying to put the DMA on it since sys_clock
is derived from the Ethernet PHY instead of the Zynq on the Eclypse board).
Connect the FIFO's S_AXIS
to M_AXIS_MM2S
of the DMA Controller, s_axis_aclk
to FCLK_CLK0
of the Zynq PS,s_axis_aresetn
to peripheral_aresetn
of the Processor System Reset (that will have been generated from running connection automation for the AXIS DMA Controller), and m_axis_aclk
to clk_out1
of the Clocking Wizard.
Zmod AWG Controller
It's finally time for the star of the show: add the Zmod AWG Controller to the block design and open its configuration window.
Disable the options for external gain configuration signals, external calibration signals, and SPI indirect access port unless you specifically plan to use them. Leaving these ports enabled and unconnected causes the tool to try to guess how to tie them off in order to prevent unexpected behavior (which is usually tying them to ground) which can also cause unexpected behavior.
Connect InputDataStream
to M_AXIS
of the AXIS Data FIFO, SysClk100
& DAC_InIO_Clk
to clk_out1
of the Clocking Wizard, DAC_Clk
to clk_out2
of the Clocking Wizard, and sDAC_EnIn
to locked of the Clocking Wizard (there is no point in enabling the DAC's output if the clocks running it aren't stable).
Connect aRst_n
to peripheral_aresetn
of the Processor System Reset (that will have been generated from running connection automation for the AXIS DMA Controller).
Then connect sTestMode
to the "gnd" Constant. Driving the test mode signal low just hardcodes the Zmod AWG Controller in normal operation. The test mode is only used for calibration/zeroing of the DAC.
Add a Concat block and connect sInitDoneDAC
& sConfigError
to its inputs.
Connect the Concat'sdout[1:0]
to GPIO_I[1:0]
of the Zynq PS, while leaving GPIO_O[1:0]
& GPIO_T[1:0]
unconnected. This is how the Zynq PS will read the status of the DAC from the Zmod AWG Controller during operation.
Finally, connect the rest of the Zmod AWG Controller outputs to external ports (right-click and select "Make External").
The overall block design turned out as:
Validate the block design to verify there are no errors or critical warnings, then save the block design. After saving it, create an HDL wrapper to instantiate it in the design (I've shown how to create an HDL wrapper in many past project posts).
Vivado ConstraintsCreate three constraints files (this is just a personal preference, this could all be in one file): one for SYZYGY port A specific signals, SYZYGY port B specific signals, and one for the Eclypse Z7 specific signals:
Starting with the constraints for the Eclypse Z7 signals, DO NOT specify the period for the system clock of the Eclypse Z7. Just specify the FPGA package pin and IO voltage (3.3v).
Specifying the period for the system clock causes routing issues in the hardware due to Vivado overwriting settings from the underlying board constraint files in the Eclypse's board preset files, even if you're specifying the exact same value for the clock period.
I'm guessing this is an oddity of 2022.1 because the master constraints file for the Eclypse Z7 in Digilent's Github repo specify the period for the system clock. Blindly copy+pasting it will result in cryptic Methodology critical warnings in the implemented design, as well as unexpected behavior in the hardware since the two clocks being sourced by the Clocking Wizard that sys clock is driving need to be synchronous.
I'm using the AWG Zmod on the SYZYGY Port B and nothing on SYZYGY Port A, I've attached the constraints file for the AWG Zmod on Eclypse SYZYGY Port B I created below for you to use.
Export HardwareWith the design complete run synthesis, implementation, and generate a bitstream. Open the implemented design to see how the timing results turned out and how much of the programmable logic is utilized:
Finally, export the hardware design, including the bitstream by selecting File > Export > Export Hardware and following the prompt windows.
Vitis Software DesignThe C application to control this design is simply a matter of writing the desired string of binary codes for the DAC to a buffer in memory, then pointing the AXI DMA controller to that memory space and kicking off the DMA read transaction, which I have detailed in this project post.
This project post is the first of a series, where I will be using the AWG Zmod on the Eclypse Z7 in custom projects so keep an eye out!
Comments