Synthesizer hardware design in Vivado

Yuhei Horibe
5 min readNov 30, 2020
Figure 1. Hardware block design in Vivado

Overview

In this section, the focus will be on generating synthesizer hardware bitstream for Zedboard. Entire system overview including software architecture is explained here.

Designing digital musical synthesizer on Zedboard

Detail of the synthesizer hardware design is explained below.

Digital Synthesizer Hardware Design

Also, designed hardware Verilog source code is available here.

“src” folder includes all the modules instantiated in IP, “sim” folder has all the testbenches, and “hdl” folder contains top module of the IP.

Creating block design

As I explained before, CPU (ARM Cortex-A9 dual core) to run Linux will be needed in this project. Open Vivado, create new project for Zedboard. Then instantiate Processing System (PS7) in the block design. This article explains how to instantiate PS, and how to create AXI4 Lite slave IP.

Connecting Device to Processor

Create new AXI4 Lite IP, and select “Edit in IP packager”, then you will see 2 Verilog source codes in the project.

  • <IP name>_v1_0.v … This is top module of this IP.
  • <IP name>_v1_0_S00_AXI.v … This module describes interface between CPU and IP module.

Second module is pretty important, since all the registers visible through MMIO are defined here. Also, the offset of each register will be described here. I don’t explain the detail now, but if you download the synthesizer IP source code from my repo, you can simply replace all the contents with my module in “hdl” folder. Also, to instantiate core logic of the IP, add all the Verilog source codes in “src” folder. Then, this IP should be able to be synthesized, and implemented. If Synthesis design, and Implement design are successful, package this IP, and return back to the original project.

In original block design, you should see “Report IP status” on top of the block design. Click it, and upgrade the IP (this is also explained in the link above). If it’s successful, you’ll see all the input (AXI slave interface) and output (I2S clocks, and serial data output). “Run connection automation”, then you will see new blocks;

  • Processor System Reset block (rst_ps7_0_100M)
  • AXI interconnect (ps7_0_axi_periph)

Those are instantiated and connected automatically.

Add new clock source and reset block

In this design, my module won’t use 100MHz clock. Because, I2S audio master clock will be generated from the master clock, and 100MHz is not suitable for that. Instead, 98.304MHz clock will be used (Actually, the frequency would be 98.305MHz), because 48kHz (audio sampling frequency) * 2048 = 98.304MHz. To add new clock source, right click blank space in block design, and select “Add IP”, and search “Clocking Wizard”. When it appears there, right click the module, and select “Customize IP” before running connection automation.

Figure 2. Clocking wizard customization

Important thing is, make sure “MMCM” is selected in “Primitive” section. Then open “Output Clocks” tab.

Figure 3. Output Clock customization

Make sure, “clk_out1” in “Output Clock” column in selected, and “Requested” frequency is “98.304MHz”. Then, the closest possible clock frequency will be appeared in “Actual” column. In my case, it’s “98.30508MHz”. This is close enough for targeted clock frequency.

When Clocking Wizard IP is customized, run connection automation. Now it’s time to replace master clock with newly created 98MHz clock. If “connection automation” does not instantiate Processor System Reset for 98MHz clock, instantiate system reset IP as well.

Figure 4. System clock connection

Make sure “clk_out1” from clk_wiz_0 is connected to;

  • “slowest_sync_clk” in “rst_clk_wiz_0_98M”
  • “M00_ACLK” in “ps7_0_axi_periph”
  • “s00_axi_aclk” in synthesizer module

In my case, AXI I2C IP is also using 98MHz clock, but it doesn’t have to be 98MHz, and “connection automation” should connect 100MHz clock, and reset for that properly to this device (explained later).

Also, “locked” output from “clk_wiz” should be connected to “dcm_locked” in “rst_clk_wiz_0_98M”.

Next, connect reset signal for 98MHz clock domain appropriately.

Figure 5. System reset signal connection

When you remove connections from below;

  • “M00_ARESETN” in “ps7_0_axi_periph”
  • “s00_axi_aresetn” in synthesizer IP

you can run connection automation to make sure all necessary reset signals are connected to appropriate places.

Adding I2C driver IP

I2C output is necessary to change the configuration of audio CODEC ADAU1761. Audio data itself will be passed via I2S output, but all the other configurations including sampling rate, mixing parameter etc will be communicated via I2C.

Right click any blank space in block design window, then “Add IP”, and search “AXI IIC”. Instantiate it, then “run connection automation”.

Important thing is, interrupt signal “iic2intc_irpt” must be connected to PS. Right click “ZYNQ7 Processing System” block and select “Customize block”. Select “Interrupt” tab at the bottom, then break down “Fabric Interrupts” →“PL-PS Interrupt Ports” → “IRQ_F2P[15:0]”. Check IRQ_F2P, and select OK. Then, you should see “IRQ_F2P[0:0]” input in “processing_system7_0” block.

Making external connections

Right now, all the necessary blocks are implemented and connected, but external ports are not defined yet. Right click terminals from all the signals below, and select “Make external”.

  • “i2s_mclk” in synthesizer IP
  • “i2s_bclk” in synthesizer IP
  • “i2s_lrck” in synthesizer IP
  • “i2s_tx” in synthesizer IP
  • “IIC” in “axi_iic_0"
  • “gpo[1:0]” in “axi_iic_0” (Customize axi_iic, and change “General Purpose Output width” to 2)

Edit constraints

You can edit it by opening implemented design, but easiest is, copy below, and paste it to text editor, and save it as “<filename>.xdc”. Then, “Add sources” in “Sources” window, and select this file.

set_property PACKAGE_PIN T22 [get_ports {led_out_0[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_out_0[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_out_0[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_out_0[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_out_0[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_out_0[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_out_0[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_out_0[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_out_0[0]}]
set_property PACKAGE_PIN T21 [get_ports {led_out_0[1]}]
set_property PACKAGE_PIN U22 [get_ports {led_out_0[2]}]
set_property PACKAGE_PIN U21 [get_ports {led_out_0[3]}]
set_property PACKAGE_PIN V22 [get_ports {led_out_0[4]}]
set_property PACKAGE_PIN W22 [get_ports {led_out_0[5]}]
set_property PACKAGE_PIN U19 [get_ports {led_out_0[6]}]
set_property PACKAGE_PIN U14 [get_ports {led_out_0[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {iic_addr[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {iic_addr[0]}]
set_property PACKAGE_PIN AB1 [get_ports {iic_addr[0]}]
set_property PACKAGE_PIN Y5 [get_ports {iic_addr[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports i2s_bclk_0]
set_property IOSTANDARD LVCMOS33 [get_ports i2s_lrck_0]
set_property IOSTANDARD LVCMOS33 [get_ports i2s_mclk_0]
set_property IOSTANDARD LVCMOS33 [get_ports i2s_tx_0]
set_property PACKAGE_PIN AB4 [get_ports iic_rtl_scl_io]
set_property PACKAGE_PIN AB5 [get_ports iic_rtl_sda_io]
set_property IOSTANDARD LVCMOS33 [get_ports iic_rtl_scl_io]
set_property IOSTANDARD LVCMOS33 [get_ports iic_rtl_sda_io]
set_property PACKAGE_PIN AA6 [get_ports i2s_bclk_0]
set_property PACKAGE_PIN Y6 [get_ports i2s_lrck_0]
set_property PACKAGE_PIN Y8 [get_ports i2s_tx_0]
set_property PACKAGE_PIN AB2 [get_ports i2s_mclk_0]

Synthesis, Implementation and Generate bitstream

Now, this block design should be ready to be synthesized and implemented. If both synthesis and implementation are successful, click “Generate Bitstream”, and you’ll get bitstream of this entire design.

From next section, I’ll explain Linux kernel driver stuff, and device tree. All the necessary drivers will be prepared, and kernel is properly configured, this module will be usable.

--

--