FPGA & Linux
TEKNİK REHBER FPGA & LINUX ARAÇLAR 2026

Vivado & Quartus
IP Tasarımı & Bitstream

Vivado Block Design ve IP Integrator akışı, VHDL/Verilog AXI-Lite özel periferel, zamanlama kısıtları, bitstream üretimi. Quartus Platform Designer, HPS köprüleri ve pratik PWM periferali.

00 Vivado Block Design iş akışı

Vivado Block Design (BD), IP bloklarını grafiksel olarak bağlamaya ve AXI Interconnect'i otomatik oluşturmaya olanak tanıyan entegre bir tasarım ortamıdır. Zynq SoC projeleri için temel araç akışıdır.

Yeni Zynq projesi oluşturma

  Vivado → New Project → RTL Project
    → Part seçimi (örn. xc7z020clg484-1 ZedBoard)
    → IP Catalog açık tutulur

  Create Block Design (BD):
    IP Integrator → Create Block Design → "design_1"
    → Add IP → Zynq-7000 PS (ZYNQ7 Processing System)
    → Run Block Automation (PS MIO/DDR ayarları)
    → Add IP → (özel bloklarınız)
    → Run Connection Automation (AXI bağlantıları)
    → Validate Design
    → Generate Output Products
    → Create HDL Wrapper

Temel Vivado akış adımları

IP CatalogXilinx'in hazır IP kütüphanesi: FIFO, BRAM, AXI-DMA, Video, DSP blokları; özel IP'ler de eklenir
Block AutomationZynq PS eklenince MIO, DDR ve sabit bağlantıları otomatik yapılandırır
Connection AutomationAXI slave'leri AXI Interconnect'e ve ardından PS GP/HP portuna otomatik bağlar
Address EditorHer AXI slave'e bellek haritasında adres aralığı atanır; DTS ile uyumlu olmalı
HDL WrapperBD'den sentezlenebilir top-level HDL modül; synthesis/implementation için giriş noktası
NOT

Vivado 2020.2+ sürümünden itibaren Tcl scriptleme tam destek görür. Tüm Block Design işlemleri Tcl ile otomatikleştirilebilir; bu sayede CI/CD pipeline entegrasyonu kolaylaşır.

Bu bölümde

  • Block Design: grafiksel IP bağlama ortamı; AXI Interconnect otomatik üretilir
  • Block/Connection Automation: PS yapılandırması ve AXI bağlantıları otomatik
  • Address Editor: AXI slave adres atama — DTS ile uyumlu olmalı
  • HDL Wrapper: BD'den sentez girişi; Tcl ile tam otomatik

01 IP Integrator ve Zynq PS yapılandırması

Zynq PS (ZYNQ7 Processing System) IP bloğu, PS'in MIO pinleri, DDR arayüzü, PLL saatleri ve PS-PL AXI portlarını yapılandırır. Bu adım her Zynq projesinin temelidir.

PS yapılandırma kategorileri

KategoriAyarlarTipik değer
PS-PL ConfigGP/HP port etkinleştirme, AXI geniş/darGP0 etkin, HP0 etkin (64-bit)
MIO ConfigUART, I2C, SPI, USB, GigE, SD pin atamalarıUART1: MIO48/49, SD0: MIO40-45
Clock ConfigCPU_6x4x, DDR_3x2x, FCLK_CLK0–3 frekanslarıCPU=667 MHz, FCLK0=100 MHz
DDR ConfigDDR tipi, hız, genişlik, gecikmeDDR3, 533 MHz, 32-bit
InterruptsIRQ_F2P etkinleştirme16 bit PL interrupt girişi

FCLK — PL saat kaynağı

PS, PL'e 4 adet bağımsız saat çıkışı (FCLK_CLK0–3) sağlar. Her FCLK, PS PLL'inden türetilir ve 10–250 MHz arasında ayarlanabilir. AXI Interconnect ve özel IP'ler bu saatlerden beslenmelidir; birden fazla saat etki alanı kullanıldığında CDC (Clock Domain Crossing) tasarımı gerekir.

Vivado Tcl — PS IP ekle ve yapılandır
# Yeni Block Design oluştur
create_bd_design "design_1"

# Zynq PS IP ekle
create_bd_cell -type ip -vlnv xilinx.com:ip:processing_system7:5.5 ps7_0

# ZedBoard preset uygula
set_property -dict [list \
  CONFIG.PCW_USE_S_AXI_HP0 {1} \
  CONFIG.PCW_USE_M_AXI_GP0 {1} \
  CONFIG.PCW_FPGA0_PERIPHERAL_FREQMHZ {100} \
  CONFIG.PCW_UART1_PERIPHERAL_ENABLE {1} \
  CONFIG.PCW_UART1_UART1_IO {MIO 48 .. 49} \
  CONFIG.PCW_SD0_PERIPHERAL_ENABLE {1} \
] [get_bd_cells ps7_0]

# PS saatini PL'e bağla
connect_bd_net [get_bd_pins ps7_0/FCLK_CLK0] \
               [get_bd_pins ps7_0/M_AXI_GP0_ACLK]

Bu bölümde

  • PS IP: MIO, DDR, PLL, GP/HP portları, IRQ_F2P — tek yapılandırma noktası
  • FCLK0–3: PS'ten PL'e saat; 10–250 MHz arası ayarlanabilir
  • Tcl ile tam otomatik yapılandırma — CI/CD için gerekli

02 AXI-Lite özel periferel — register haritası tasarımı

Vivado'nun "Create and Package New IP" sihirbazı, AXI-Lite slave şablonunu otomatik oluşturur. Bu şablona register haritanızı ve uygulamanızı eklersiniz.

AXI-Lite slave şablonu oluşturma

  Tools → Create and Package New IP
    → Create a new AXI4 Peripheral
    → Interface Type: AXI4-Lite
    → Data Width: 32 bit
    → Number of Registers: 4 (veya ihtiyaca göre)
    → Finish → "Edit IP"

  Vivado şunları üretir:
    my_ip_v1_0.vhd          — üst seviye wrapper
    my_ip_v1_0_S00_AXI.vhd  — AXI-Lite slave mantığı

Register haritası ekleme (VHDL)

my_ip_v1_0_S00_AXI.vhd — özel register mantığı
-- Şablona eklenen özel register mantığı
-- REG0 (0x00): kontrol register'ı
-- REG1 (0x04): veri çıkışı
-- REG2 (0x08): durum (salt okunur)
-- REG3 (0x0C): kesme enable

-- Yazma işlemi (şablonun write bölümüne ekle)
when b"00" =>
    for byte_index in 0 to (C_S_AXI_DATA_WIDTH/8-1) loop
        if ( S_AXI_WSTRB(byte_index) = '1' ) then
            slv_reg0(byte_index*8+7 downto byte_index*8) <=
                S_AXI_WDATA(byte_index*8+7 downto byte_index*8);
        end if;
    end loop;

-- Uygulama mantığı (entity port'larına bağla)
CTRL_OUT  <= slv_reg0(7 downto 0);   -- kontrol bitleri
DATA_OUT  <= slv_reg1;                 -- veri çıkışı
slv_reg2  <= "000" & STATUS_IN;       -- durum okuma
IRQ_EN    <= slv_reg3(0);             -- kesme etkinleştir

Verilog alternatifi

AXI-Lite slave — register yazma (Verilog)
// AXI4-Lite yazma FSM (basitleştirilmiş)
always @(posedge S_AXI_ACLK) begin
    if (!S_AXI_ARESETN) begin
        reg_ctrl <= 32'h0;
        reg_data <= 32'h0;
        reg_irqen <= 32'h0;
    end else if (slv_reg_wren) begin
        case (axi_awaddr[3:2])
            2'h0: reg_ctrl  <= S_AXI_WDATA;
            2'h1: reg_data  <= S_AXI_WDATA;
            // 2'h2: STATUS salt okunur — yazma yok
            2'h3: reg_irqen <= S_AXI_WDATA;
        endcase
    end
end

// Okuma multiplexer
always @(*) begin
    case (axi_araddr[3:2])
        2'h0: reg_data_out = reg_ctrl;
        2'h1: reg_data_out = reg_data;
        2'h2: reg_data_out = {{31}}{1'b0}, status_in};
        2'h3: reg_data_out = reg_irqen;
    endcase
end

Bu bölümde

  • Vivado sihirbazı AXI-Lite slave şablonunu (wrapper + slave logic) otomatik üretir
  • Register haritası: slv_reg0–3 alanlarına mantık eklenerek özelleştirilir
  • Salt okunur register: yazma durumunda yoksay; okuma multiplexer'da STATUS geri döndür
  • VHDL ve Verilog şablonları Vivado tarafından her ikisi için de üretilebilir

03 AXI-Stream veri akışı periferali

AXI-Stream periferaller, sürekli akan veri üzerinde işlem yapar: filtreleme, şifreleme, sıkıştırma, protokol dönüştürme. Vivado'da AXI-Stream IP'ler AXI-DMA ile birlikte kullanılır.

AXI-Stream FIFO ile bağlantı

  PS (AXI-DMA MM2S) → AXI4-Stream FIFO → Özel İşlemci → AXI4-Stream FIFO → PS (AXI-DMA S2MM)

  MM2S: Memory-to-Stream (DDR'dan PL'e veri gönder)
  S2MM: Stream-to-Memory (PL'den DDR'a veri yaz)
  AXI-DMA: iki kanallı (MM2S + S2MM) scatter-gather DMA

Basit AXI-Stream geçiş filtresi (Verilog)

axis_pass_filter.v — TLAST korumalı geçiş
module axis_pass_filter #(
    parameter DATA_WIDTH = 32
)(
    input  wire                   aclk,
    input  wire                   aresetn,
    // Slave (giriş)
    input  wire [DATA_WIDTH-1:0]  s_tdata,
    input  wire                   s_tvalid,
    output wire                   s_tready,
    input  wire                   s_tlast,
    // Master (çıkış)
    output wire [DATA_WIDTH-1:0]  m_tdata,
    output wire                   m_tvalid,
    input  wire                   m_tready,
    output wire                   m_tlast,
    // Kontrol (AXI-Lite'dan)
    input  wire [DATA_WIDTH-1:0]  threshold
);
    // Eşiği geçen örnekleri maskele
    wire pass = (s_tdata <= threshold);
    assign m_tdata  = pass ? s_tdata : {DATA_WIDTH{1'b0}};
    assign m_tvalid = s_tvalid;
    assign s_tready = m_tready;
    assign m_tlast  = s_tlast;
endmodule
TDATAVeri taşıyıcısı; genişlik parametre — 8/16/32/64/128/512 bit
TVALID / TREADYHandshake: kaynak TVALID'i assert eder, alıcı TREADY ile kabul eder
TLASTPaket/frame sonu işaretçisi; AXI-DMA S2MM kanalının bellekte yazmayı sonlandırması için gerekli
TKEEP / TSTRBHangi byte lane'lerinin geçerli olduğunu belirtir; kısmi transferlerde kullanılır

Bu bölümde

  • AXI-Stream: TDATA/TVALID/TREADY/TLAST; handshake tabanlı akış kontrolü
  • AXI-DMA: MM2S (DDR→PL) + S2MM (PL→DDR) — iki kanallı
  • TLAST: AXI-DMA S2MM için paket sonu — zorunlu doğru kullanım
  • Filtre örneği: eşik tabanlı maskeleme; threshold AXI-Lite'dan ayarlanır

04 Zamanlama kısıtları (XDC)

Zamanlama kısıtları (XDC — Xilinx Design Constraints), sentez ve yer-yönlendirme araçlarının hedef frekansı ve özel zamanlama gereksinimlerini bildiği dosyadır. Hatalı XDC, çalışmayan veya kararsız bir tasarımla sonuçlanır.

Temel saat kısıtı

constraints.xdc — temel saat ve IO
## Birincil saat — 100 MHz PS FCLK0
create_clock -period 10.000 -name clk_100 \
    [get_ports {FCLK_CLK0}]

## ZedBoard — harici 100 MHz osilatör (PL direkt)
create_clock -period 10.000 -name sys_clk \
    [get_ports {sys_clk_p}]

## I/O zamanlama (AXI master/slave dışı GPIO)
set_input_delay  -clock clk_100 2.0 [get_ports {btn_*}]
set_output_delay -clock clk_100 2.0 [get_ports {led_*}]

## Yanlış yol (false path) — asenkron reset
set_false_path -from [get_ports {cpu_resetn}]

## CDC — farklı saat etki alanları arası yol
set_false_path -from [get_clocks clk_100] \
               -to   [get_clocks clk_200]

Timing summary yorumlama

MetrikAnlamıHedef
WNS (Worst Negative Slack)En kötü zamanlama açığı; pozitif = geçti≥ 0 ns
TNS (Total Negative Slack)Toplam zamanlama açığı0 ns
WHS (Worst Hold Slack)Hold zamanı en kötü durumu≥ 0 ns
WPWS (Worst Pulse Width Slack)Minimum pulse genişliği≥ 0 ns
DİKKAT

WNS negatifse tasarım timing kapatmamıştır. Sentez parametrelerini sıkılaştırın (strategy: Performance_ExplorePostRoutePhysOpt), pipeline ekleyin veya hedef frekansı düşürün. Negatif slack ile bitstream üretmek donanım arızasına yol açar.

Bu bölümde

  • create_clock: tüm birincil saatler XDC'de tanımlanmalı
  • set_false_path: asenkron reset ve CDC yolları için
  • WNS ≥ 0: tasarım timing'i kapattı — bitstream üretmeye hazır
  • Negatif WNS: pipeline ekle, frekansı düşür veya sentez stratejisini değiştir

05 Bitstream üretimi ve BOOT.BIN

Vivado implementation sonrasında .bit dosyası üretilir. Zynq için bu dosya FSBL ve U-Boot ile birleştirilip BOOT.BIN olarak paketlenir.

Implementation ve bitstream

  Synthesis → Implementation → Generate Bitstream

  Synthesis:   RTL → gate-level netlist (XDC uygulanır)
  Implementation:
    opt_design    — optimizasyon
    place_design  — LUT/FF/BRAM yerleşimi
    route_design  — sinyal yönlendirme
    phys_opt      — post-route fiziksel optimizasyon
  Generate Bitstream: .bit dosyası üretir

BOOT.BIN oluşturma (BIF dosyası)

boot.bif — Bootgen yapılandırması
// Zynq-7000 BOOT.BIN yapılandırması
the_ROM_image:
{
    [bootloader] fsbl.elf        // FSBL — OCM'de çalışır
    design_1_wrapper.bit         // PL bitstream
    u-boot.elf                   // U-Boot
}
BOOT.BIN üretme komutu
# Vitis veya Petalinux araçlarıyla
bootgen -arch zynq -image boot.bif -w on -o BOOT.BIN

# SD karta kopyala
cp BOOT.BIN /media/boot/
cp image.ub /media/boot/   # FIT imaj (kernel + DTB + initrd)

# veya TFTP ile U-Boot'tan yükle
# U-Boot prompt:
# tftpboot 0x3000000 image.ub && bootm 0x3000000

Partial bitstream (.pbin)

Kısmi yeniden yapılandırma (Partial Reconfiguration — PR) etkinleştirildiğinde, yalnızca PL'in belirli bir bölgesi yeniden programlanabilir. .pbin dosyası tam bitstream yerine kullanılır; çalışma süresi kesintisi minimuma iner.

Bu bölümde

  • Implementation: synth → opt → place → route → phys_opt → bitstream
  • BOOT.BIN: BIF dosyasıyla FSBL + bitstream + U-Boot birleştirme
  • bootgen -arch zynq -image boot.bif -w on -o BOOT.BIN
  • Partial bitstream: .pbin ile sadece PR bölgesi yeniden programlanır

06 Quartus Platform Designer (Qsys)

Intel Quartus Prime'ın Platform Designer (eski adıyla Qsys) aracı, Vivado Block Design'a karşılık gelen sistem entegrasyon ortamıdır. HPS ve FPGA bileşenlerini Avalon veya AXI veri yollarıyla bağlar.

Platform Designer bileşenleri

HPS ComponentCyclone V HPS yapılandırması: MIO, DDR, periferaller, EMAC, USB, H2F/F2H köprü etkinleştirme
Avalon-MM SlaveBellek eşlemeli arayüz; read/write sinyalleri ile basit register erişimi
Avalon-STAXI-Stream muadili akış veri yolu; valid/ready handshake
AXI BridgeAXI↔Avalon dönüştürücü; standart IP'leri Platform Designer'a bağlar
Clock SourcePLL çıkışları sistemin saatini dağıtır; Clock Crossing Bridge CDC yönetir

Platform Designer iş akışı

  Quartus Prime → Tools → Platform Designer
    → HPS bileşenini ekle ve yapılandır
    → Özel IP bileşenlerini ekle (Component Editor ile)
    → Bağlantıları çiz (Avalon veya AXI)
    → Address Map düzenle
    → Generate HDL → Synthesis Files

  Quartus: top-level projeye Platform Designer çıkışını dahil et
    → Analysis & Synthesis → Fitter → Assembler → .sof/.rbf

Bu bölümde

  • Platform Designer: Qsys — Vivado Block Design Intel muadili
  • Avalon-MM: Cyclone V'nin yerel veri yolu; AXI köprüsüyle standart IP bağlanır
  • HPS Component: MIO, DDR, köprü yapılandırması tek yerden
  • Çıkış: .sof (JTAG programlama) veya .rbf (runtime yükleme)

07 HPS-to-FPGA köprüleri yapılandırması

Cyclone V SoC'ta HPS ve FPGA arasındaki veri yolu köprüleri Platform Designer'da yapılandırılır. Her köprünün bant genişliği, gecikme ve adres eşlemesi farklıdır.

Köprü yapılandırma seçenekleri

KöprüVeri genişliğiMax frekansMax bant
H2F (HPS→FPGA)32/64/128-bit250 MHz~4 GB/s
F2H (FPGA→HPS)32/64/128-bit250 MHz~4 GB/s
Lightweight H2F32-bit125 MHz~500 MB/s
F2H SDRAM128/256-bit200 MHz~6 GB/s

Linux köprü yönetimi

socfpga — köprü etkinleştirme (C)
// Cyclone V SoC — sysmgr üzerinden köprü kontrolü
// Kernel sürücüsü: drivers/fpga/altera-hps2fpga.c

// Kullanıcı alanından sysfs üzerinden:
// echo 1 > /sys/bus/platform/drivers/altera-hps2fpga/ff400000.bridge/enable

// veya devmem2 aracıyla SYSMGR.FPGAINTF register'ı:
// SYSMGR_BASE = 0xFFD08000
// FPGAINTF_EN_2 offset = 0x28
// bit[0]: H2F, bit[1]: LWH2F, bit[2]: F2H

#define SYSMGR_BASE    0xFFD08000UL
#define FPGAINTF_EN_2  0x28

volatile uint32_t *sysmgr = mmap_region(SYSMGR_BASE, 0x1000);
sysmgr[FPGAINTF_EN_2 / 4] |= (1 << 0) | (1 << 1);  // H2F + LWH2F

Bu bölümde

  • H2F (128-bit, 250 MHz): yüksek bant genişliği HPS→FPGA
  • LWH2F (32-bit): düşük bant, düşük gecikme — CSR register erişimi
  • F2H SDRAM: FPGA DMA → HPS DDR; en yüksek bant genişliği
  • Linux'ta köprü: altera-hps2fpga sürücüsü veya SYSMGR register

08 Pratik: AXI-Lite PWM periferali

Bu bölümde Vivado'da AXI-Lite kontrol register'larına sahip, frekans ve görev döngüsü yazılımdan ayarlanabilir bir PWM (Pulse Width Modulation) periferali tasarlanacak ve Linux'tan kontrol edilecektir.

PWM register haritası

OffsetRegisterAçıklama
0x00CTRLbit[0]=enable, bit[1]=polarity
0x04PERIODPeriyot (saat döngüsü sayısı − 1)
0x08DUTYYüksek süre (saat döngüsü sayısı)
0x0CSTATUSbit[0]=çalışıyor, bit[1]=periyot aşımı

PWM çekirdeği (Verilog)

pwm_core.v
module pwm_core (
    input  wire        clk,
    input  wire        rst_n,
    input  wire        enable,
    input  wire        polarity,
    input  wire [31:0] period,    // saat döngüsü sayısı - 1
    input  wire [31:0] duty,      // yüksek süre
    output reg         pwm_out,
    output wire        running
);
    reg [31:0] counter = 0;

    assign running = enable;

    always @(posedge clk) begin
        if (!rst_n || !enable) begin
            counter <= 0;
            pwm_out <= polarity ? 1'b0 : 1'b1;
        end else begin
            if (counter >= period)
                counter <= 0;
            else
                counter <= counter + 1;

            if (counter < duty)
                pwm_out <= polarity ? 1'b1 : 1'b0;
            else
                pwm_out <= polarity ? 1'b0 : 1'b1;
        end
    end
endmodule

Linux kullanıcı alanı — PWM kontrolü

pwm_ctrl.c — /dev/mem ile PWM ayarlama
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/mman.h>

#define PWM_BASE   0x40000000UL
#define MAP_SIZE   0x10000UL

#define REG_CTRL   0x00
#define REG_PERIOD 0x04
#define REG_DUTY   0x08
#define REG_STATUS 0x0C

/* 100 MHz saat, 10 kHz PWM, %75 görev döngüsü */
#define CLK_HZ     100000000UL
#define PWM_HZ     10000UL
#define DUTY_PCT   75

int main(void)
{
    uint32_t period = CLK_HZ / PWM_HZ - 1;         // 9999
    uint32_t duty   = period * DUTY_PCT / 100;      // 7499

    int fd = open("/dev/mem", O_RDWR | O_SYNC);
    volatile uint32_t *pwm =
        mmap(NULL, MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, PWM_BASE);

    pwm[REG_CTRL   / 4] = 0;       /* durdur */
    pwm[REG_PERIOD / 4] = period;
    pwm[REG_DUTY   / 4] = duty;
    pwm[REG_CTRL   / 4] = 1;       /* enable, normal polarity */

    printf("PWM: %u Hz, duty=%u/%u (%d%%)\n",
           (uint32_t)PWM_HZ, duty, period, DUTY_PCT);
    printf("STATUS: 0x%08X\n", pwm[REG_STATUS / 4]);

    munmap((void *)pwm, MAP_SIZE);
    close(fd);
    return 0;
}
İPUCU

Gerçek üretim kodunda Linux PWM subsystem (CONFIG_PWM) üzerinden sysfs arayüzü (/sys/class/pwm/) kullanın. Platform driver yazan sürücü, pwm_chip yapısı aracılığıyla kernel PWM çerçevesine entegre olur. Böylece kullanıcı alanı uygulamaları donanımdan bağımsız kalır.

Bu bölümde

  • PWM: 4 register (CTRL, PERIOD, DUTY, STATUS) — AXI-Lite üzerinden
  • Period = CLK / PWM_HZ − 1; Duty = Period × duty% / 100
  • Verilog: counter tabanlı; polarity invertible
  • Üretimde: Linux PWM subsystem + pwm_chip driver — sysfs arayüzü