Zybo Z7–20 ADI “axi_i2s_adi.vhd” Slave-Mode HDL Re-designing Memorandum

4 min readFeb 26, 2021

This is the Hardware Designing (Vivado) part of the Zybo Z7–20 audio system project and I have edited the ADI’s HDL code for I2S IP to support the I2S slave mode function. Appreciated who wrote the simple original HDL code.

The tool environments and preparation

Before starting this project, I have confirmed a LINUX boot on the Zybo Z7–20 Rev. B board with following the tool environments as an initial preparation.

OS: Ubuntu 18.04 LTS on VirtualMachine 6.1 on MacBook Pro
HW: Xilinx Vivado/Vitis 2020.2
SW: Petalinux 2020.2

Integrate Master/Slave configuration switch.

I would like to switch Master and Slave mode by IP configuration on Vivado as below screenshot.

Need to edit “axi_i2s_adi_ip.tcl” file by the following instruction.

  1. I2S_MASTER_MODE property and list of selection as 1:MASTER or 0:SLAVE.
  2. Change i2s bus name to i2s_m for master mode and add i2s_s for slave mode.
  3. Set bus_dependency both i2s_m and i2s_s by switching I2S_MASTER_MODE.

See below screenshot;

Edit “axi_i2s_adi.vhd”

  1. Add bclk_i and lrclk_i as input ports.
  2. Add I2S_MASTER_MODE as a generic integer parameter to bridge IP configuration and to switch HDL internal function.
  3. Pass the bclk_i and lrclk_i signals into the “i2s_controller.vhd” module which is the main part of I2S functioning, and I2S_MASTER_MODE as well as the below screenshots.

Edit “i2s_controller.vhd”

  1. Add bclk_i and lrclk_i as well as the top module.
  2. Generate channel_sync_in and frame_sync_in by lrclk_i and bclk_i as the below screenshot.

Initilaize “cdc_sync_stage0_tick”

Set initialize state to cdc_sync_stage*_tick signal in “i2s_controller.vhd” and “fifo_synchronizer.vhd”. Since the HDL simulation cannot run without initializing this signal, it is no problem on HW synthesis though.

signal cdc_sync_stage0_tick : std_logic :=’0';
signal cdc_sync_stage1_tick : std_logic :=’0';
signal cdc_sync_stage2_tick : std_logic :=’0';
signal cdc_sync_stage3_tick : std_logic :=’0';

Switch signal connections by C_I2S_MASTER_MODE

Add selector code to switch IN/OUT connection to tx_sync and rx_sync module by switching C_I2S_MASTER_MODE as the below.

In the case of the slave mode, no need for the internal BLCK/LRCK generator, clk_gen entity, but need timing trim BLCK/LRCK to synchronize on I2S interface so inserted “i2s_clkgen_slave.vhd” between rx_sync_fifo_out to tx_sync_fifo_in then both are switching by C_I2S_MASTER_MODE.


In the original master mode, the BCLK and LRCK output signals are identical between different I2S ports, so the BCLK and LRCK in the slave mode should be also identical between different I2S ports. It means all BCLK and LRCK inputs on different I2S ports should be fully synchronized in the slave mode.

Note: the original HDL code seems to support more than single I2S channels on both TX/RX modules, but it just copies the data on AIX to all other I2S(0:NUM) ports on the TX side. In addition, the ADI’s LINUX device-driver seems to support only a single L/R channel currently. I may try to contact ADI and somehow increase the channel number for both HDL and LINUX device-driver later.

Simulation results

SLAVE mode


Have confirmed no fatal error for synthesizing both Master and Slave mode.

SLAVE mode

Continue to the Software part