SoC Zynq — PS + PL Integration

Understanding the Zynq architecture: the processor (PS) and FPGA (PL) sides, their AXI communication, and designing a complete embedded system.

What is a SoC?

A SoC (System on Chip) integrates onto a single die:

  • One or more processors (ARM, RISC-V…)
  • Programmable logic (FPGA)
  • Peripherals (memory, USB, Ethernet, UART…)

AMD/Xilinx's Zynq-7000 family is one of the most popular in the industry. It combines a dual-core ARM Cortex-A9 and an FPGA fabric on the same silicon.

Zynq-7000 architecture: PS (ARM Cortex-A9 + peripherals) connected to PL (FPGA) via AXI interfaces

Image à ajouter


The Two Sides of Zynq

Processing System (PS)

The PS side is the software world:

ElementDetail
CPUDual-core ARM Cortex-A9 (up to 866 MHz)
CacheL1 (32 KB) + L2 (512 KB)
RAMDDR3/DDR2/LPDDR2 (external connection)
PeripheralsUSB, Ethernet, UART, SPI, I2C, GPIO
OSBare-metal, FreeRTOS, Linux

The PS can operate independently of the FPGA side — it boots from its Flash or SD card.

Programmable Logic (PL)

The PL side is the classic FPGA fabric:

  • LUTs, flip-flops, BRAMs, DSPs
  • All your VHDL runs here
  • Can be reprogrammed at runtime (partially)
  • Typical clock rates: 100–300 MHz

PS ↔ PL Communication

The PS and PL communicate via AXI interfaces:

InterfaceDirectionUse
AXI HP (High Performance)PS ↔ PLHigh-speed DMA transfers to RAM
AXI GP (General Purpose)PS → PLCPU access to PL registers
AXI ACP (Accelerator Coherency Port)PL → PSCache-coherent access
EMIOPS ↔ PLGPIO, SPI, I2C extension through PL

AXI interfaces between PS and PL: AXI_GP (register access CPU→PL), AXI_HP (DMA PL→DDR), EMIO (extended GPIO)

Image à ajouter


Creating a SoC Project in Vivado

Step 1 — New Vivado Project

Create an RTL project and select your Zynq board (PYNQ-Z2, ZedBoard, Cora Z7…).

Vivado: project creation with PYNQ-Z2 board selected

Image à ajouter


Step 2 — Create the Block Design

In the left panel: IP Integrator → Create Block Design.

Vivado: Create Block Design menu in IP Integrator

Image à ajouter


Step 3 — Add the Processing System

Right-click in the canvas → Add IP → search for "Zynq7 Processing System".

Vivado Block Design: adding the ZYNQ7 Processing System block

Image à ajouter

Click "Run Block Automation" to automatically apply your board's constraints (DDR presets, clock…).

Vivado: Run Block Automation applies PYNQ-Z2 board presets

Image à ajouter


Step 4 — Configure the PS

Double-click the PS block to open its configuration:

  • PS-PL Configuration: enable the required AXI interfaces (GP0, HP0…)
  • Clock Configuration: set the PL clock frequency (100 MHz by default)
  • MIO Configuration: choose which PS peripherals to enable (UART, USB…)

Vivado: PS Zynq configuration window — PS-PL Configuration tab with AXI GP0 enabled

Image à ajouter


Step 5 — Add Your VHDL IP

To connect your VHDL to the PS, you wrap it in an IP with an AXI-Lite interface:

  1. Tools → Create and Package New IP
  2. Choose "AXI-Lite Slave" as the interface
  3. Define the AXI registers (read/write)
  4. Add your VHDL logic to the generated file

Vivado: Create and Package New IP wizard — AXI4-Lite interface selection

Image à ajouter


Step 6 — Connect the Blocks

After adding your IP to the block design:

  1. Right-click → Add IP and search for your custom IP
  2. Click "Run Connection Automation" → Vivado wires the AXI Interconnect automatically

Complete Vivado Block Design: PS Zynq + AXI Interconnect + custom IP — AXI connections visible

Image à ajouter


Step 7 — Generate the Bitstream

  1. Validate Design (F6) to check connections
  2. Right-click the block design → Generate Output Products
  3. Right-click → Create HDL Wrapper
  4. Generate Bitstream

Vivado: Generate Bitstream in progress — implementation progress shown

Image à ajouter


Step 8 — Export to Vitis / SDK

  1. File → Export → Export Hardware (include bitstream)
  2. Open Vitis (or SDK for versions < 2020.1)
  3. Create a C/C++ bare-metal or Linux application

Vitis: creating a bare-metal C project on the exported Zynq platform

Image à ajouter


CPU ↔ FPGA Communication in Practice

Once deployed, the CPU accesses your VHDL registers via AXI-Lite:

// Bare-metal C — read/write PL registers
#include "xparameters.h"
#include "xil_io.h"
 
// Base address of your IP (defined by xparameters.h)
#define MY_IP_BASEADDR   XPAR_MY_IP_0_BASEADDR
 
// Write to register 0 (offset 0x00)
Xil_Out32(MY_IP_BASEADDR + 0x00, 0xDEADBEEF);
 
// Read register 1 (offset 0x04)
uint32_t val = Xil_In32(MY_IP_BASEADDR + 0x04);

On the VHDL side, your IP reads/writes these registers through the AXI-Lite signals generated by Vivado.


Comparison: Pure FPGA vs Zynq SoC

CriterionPure FPGAZynq SoC
ProcessingAll in VHDLCPU for soft, FPGA for acceleration
FlexibilityVery highHigh (+ OS possible)
DebuggingHardware signalsprintf + hardware ILA
High-level interfacesCoded in VHDLUSB, Ethernet, Linux native
Dev timeLongShorter for the soft side
Use casePure real-time processingHardware/software co-design

Key Points to Remember

  • Zynq separates PS (ARM, software) and PL (FPGA, hardware)
  • PS ↔ PL communication goes through AXI interfaces
  • Vivado Block Design is the tool for visually assembling blocks
  • Your VHDL code becomes a packaged IP accessible from the CPU
  • Full flow: VHDL → Package IP → Block Design → Bitstream → Vitis/SDK