FPGA & Linux
TEKNİK REHBER FPGA & LINUX SÜRÜCÜ 2026

Linux FPGA Manager
Runtime Bitstream Yükleme

Linux FPGA Manager subsystem, fpga_region ve fpga_bridge, Device Tree overlay akışı, tam ve kısmi yeniden yapılandırma, sysfs arayüzü ve RPi + Zynq pratik uygulaması.

00 Linux FPGA Manager subsystem'e genel bakış

Linux FPGA Manager subsystem (v4.7+, drivers/fpga/), FPGA yeniden yapılandırmasını standart bir kernel API'si üzerinden soyutlar. Her FPGA türü için özel bir driver yazmak yerine, tek bir sysfs/device tree overlay arayüzü kullanılır.

Subsystem bileşenleri

fpga_managerFPGA yapılandırma donanımına erişen alt seviye sürücü; bitstream yazmak için kullanılır
fpga_regionFPGA'nın yapılandırılabilir bölgesini temsil eder; birden fazla region kısmi yeniden yapılandırmaya olanak tanır
fpga_bridgePS-PL veri yolu köprüsü; yapılandırma sırasında kapatılır, tamamlandığında açılır
fpga_image_infoBitstream meta verisi: dosya adı, flags, PR bölge bilgisi

Desteklenen FPGA platformları

SürücüPlatformDosya
zynq-fpgaXilinx Zynq-7000drivers/fpga/zynq-fpga.c
zynqmp-fpgaZynq UltraScale+ MPSoCdrivers/fpga/zynqmp-fpga.c
socfpgaIntel Cyclone V SoCdrivers/fpga/socfpga.c
altera-ps-spiAltera (PS-SPI)drivers/fpga/altera-ps-spi.c
ice40-spiLattice iCE40 (SPI)drivers/fpga/ice40-spi.c
xilinx-spiXilinx (SPI slave serial)drivers/fpga/xilinx-spi.c

Sysfs arayüzü

/sys/class/fpga_manager/ — temel arayüz
# FPGA manager listeleme
ls /sys/class/fpga_manager/
# → fpga0

# Mevcut durum
cat /sys/class/fpga_manager/fpga0/state
# → operating  (yapılandırılmış ve çalışıyor)
# → unknown    (henüz yapılandırılmamış)
# → writing    (bitstream yazılıyor)

# İsim ve status flags
cat /sys/class/fpga_manager/fpga0/name
cat /sys/class/fpga_manager/fpga0/status

Bu bölümde

  • FPGA Manager: kernel API ile FPGA yapılandırmasını soyutlar (v4.7+)
  • fpga_manager + fpga_region + fpga_bridge: üç temel kavram
  • zynq-fpga, zynqmp-fpga, socfpga: platform özel sürücüler
  • /sys/class/fpga_manager/fpga0/state: çalışma durumu izleme

01 fpga_region ve fpga_bridge kavramları

fpga_region, belirli bir FPGA alanını temsil eder ve o alanı yönetmek için gerekli manager ve bridge referanslarını içerir. fpga_bridge, yapılandırma sırasında PS-PL arasındaki veri yolunu kontrol eder.

fpga_region yapısı (kernel)

include/linux/fpga/fpga-region.h (özet)
struct fpga_region {
    struct device           dev;
    struct fpga_manager    *mgr;         /* hangi manager kullanılacak */
    struct list_head        bridge_list; /* hangi bridge'ler kontrol edilecek */
    struct fpga_image_info *info;        /* bitstream bilgisi */
    int                   (*get_bridges)(struct fpga_region *);
    int                     priv;
};

Bridge durumları

enabled (açık)PS-PL veri yolu aktif; PL periferallere erişilebilir; normal çalışma modu
disabled (kapalı)Veri yolu kapatılmış; bitstream yazımı sırasında zorunlu; PS'i tanımsız davranıştan korur

Zynq-7000 bridge listesi

BridgeDT compatibleAçıklama
HP0–HP3 slave AXIxlnx,zynq-axi-fpga-port-hpPL→DDR yüksek performans portları
GP0/GP1 master AXIxlnx,zynq-axi-fpga-port-gpPS→PL genel amaç portları
ACPxlnx,zynq-axi-fpga-port-acpÖnbellek tutarlı PL erişimi

Bridge'in neden kapatılması gerekir?

Bitstream yazımı sırasında PL'deki lojik tanımsız durumdadır: register'lar rastgele değerler üretebilir, DMA motorları hatalı veri yazabilir, kesme hatları çok sayıda sahte kesme üretebilir. Bridge kapatılarak PS DDR'ı ve sistem bus'ı bu durumdan korunur.

Bu bölümde

  • fpga_region: FPGA alanı + manager + bridge listesi — tek yapılandırma birimi
  • fpga_bridge: bitstream yazımı öncesi kapatılır, sonra açılır
  • Zynq bridge'leri: HP0–HP3, GP0/GP1, ACP portları
  • Bridge kapatma zorunluluğu: PL tanımsız durumdayken DDR koruması

02 Device Tree overlay ile FPGA overlay

Device Tree overlay (DTBO), yeni bir bitstream yüklendiğinde PL'deki yeni periferalleri tanımlamak için dinamik olarak kernel'a eklenir. Bu sayede yeniden önyükleme gerekmez.

FPGA overlay DTS şablonu

fpga-overlay.dts — tam şablon
/dts-v1/;
/plugin/;  /* Overlay olduğunu belirtir */

/ {
    fragment@0 {
        target = <&fpga_full>;
        __overlay__ {
            /* Bitstream dosya adı (firmware/fpga/ dizininde) */
            firmware-name = "design_1_wrapper.bit.bin";
        };
    };

    fragment@1 {
        target = <&amba>;
        __overlay__ {
            /* PL'deki yeni AXI-Lite periferali */
            my_periph: my-periph@40000000 {
                compatible = "myco,my-periph-1.0";
                reg = <0x40000000 0x10000>;
                clocks = <&clkc 15>;
                clock-names = "s00_axi_aclk";
                interrupts = <0 29 4>;
                interrupt-parent = <&gic>;
                status = "okay";
            };
        };
    };
};

Bitstream formatı: .bit → .bit.bin

.bit dosyasını .bit.bin'e dönüştürme
# dd ile Xilinx .bit başlığını kaldır (ilk 96 byte genellikle başlıktır)
# Kesin offset: xxd design.bit | head -4 ile byte swap noktasını bul

# Yöntem 1: bootgen (Vitis/Petalinux araçları)
bootgen -arch zynq -process_bitstream bin -image design.bit

# Yöntem 2: Python ile byte swap + başlık kaldırma
python3 - <<'EOF'
import struct

with open('design.bit', 'rb') as fin:
    data = fin.read()

# Başlık boyutunu bul (0xFF 0xFF... dizisini ara)
i = data.index(b'\xff\xff\xff\xff')
raw = data[i:]

# Her 4 byte'ı byte-swap yap (Xilinx bit-endian → byte-swap)
out = bytearray()
for k in range(0, len(raw), 4):
    chunk = raw[k:k+4]
    if len(chunk) == 4:
        out.extend(bytes(reversed(chunk)))

with open('design.bit.bin', 'wb') as fout:
    fout.write(out)
print(f'Yazıldı: {len(out)} byte')
EOF

DTBO derleme

DTBO derleme ve yükleme
# DTS → DTBO derleme
dtc -@ -I dts -O dtb -o fpga-overlay.dtbo fpga-overlay.dts

# Bitstream'i firmware dizinine kopyala
cp design.bit.bin /lib/firmware/

# DTBO yükleme (configfs overlay interface)
mkdir /sys/kernel/config/device-tree/overlays/fpga0
cp fpga-overlay.dtbo /sys/kernel/config/device-tree/overlays/fpga0/dtbo

# Durum kontrolü
cat /sys/kernel/config/device-tree/overlays/fpga0/status
# → applied

Bu bölümde

  • DTBO: /plugin/ direktifiyle overlay; fragment@0 bitstream, fragment@1 periferaller
  • .bit → .bit.bin: başlık kaldırma + byte swap (bootgen veya Python)
  • dtc -@: overlay desteğiyle derleme (phandle referansları korunur)
  • configfs: /sys/kernel/config/device-tree/overlays/ — runtime DTBO yükleme

03 Tam yeniden yapılandırma (full reconfiguration)

Tam yeniden yapılandırma, tüm PL dokusunu yeni bir bitstream ile programlar. Tüm mevcut PL tasarımı silinir ve yenisi yüklenir.

Yeniden yapılandırma akışı

  1. Sürücü: fpga_region_program_fpga() çağrısı
  2. Bridge'leri devre dışı bırak (fpga_bridges_disable)
  3. fpga_mgr_load(): bitstream → FPGA yapılandırma mantığı
     a. state = FPGA_MGR_STATE_WRITE_INIT
     b. state = FPGA_MGR_STATE_WRITE (chunk'lar halinde)
     c. state = FPGA_MGR_STATE_WRITE_COMPLETE
  4. Bridge'leri etkinleştir (fpga_bridges_enable)
  5. fpga_region'a DT overlay'i uygula (yeni periferaller)
  6. state = FPGA_MGR_STATE_OPERATING

fpga_image_info yapısı

Kernel sürücüsü — tam yeniden yapılandırma örneği
#include <linux/fpga/fpga-mgr.h>
#include <linux/fpga/fpga-region.h>

static int load_full_bitstream(struct fpga_region *region,
                                const char *firmware_name)
{
    struct fpga_image_info *info;
    int ret;

    info = fpga_image_info_alloc(&region->dev);
    if (!info)
        return -ENOMEM;

    info->firmware_name = devm_kstrdup(&region->dev,
                                        firmware_name, GFP_KERNEL);
    info->flags = 0;   /* FPGA_MGR_PARTIAL_RECONFIG değil */

    region->info = info;
    ret = fpga_region_program_fpga(region);

    fpga_image_info_free(info);
    return ret;
}
DİKKAT

Tam yeniden yapılandırma sırasında PL üzerinde çalışan tüm DMA işlemleri, aktif kesme kaynakları ve PL bağlantılı sürücüler önceden durdurulmalıdır. Aksi hâlde sistem kilitlenmesi veya bellek bozulması yaşanabilir.

Bu bölümde

  • Tam yapılandırma: WRITE_INIT → WRITE → WRITE_COMPLETE → OPERATING
  • Bridge'ler yazım öncesi kapatılır, sonra açılır
  • fpga_image_info: firmware_name + flags; flags=0 → tam yapılandırma
  • Önceki DMA/IRQ'ları durdur: sistem kilitlenmesinden kaçın

04 Kısmi yeniden yapılandırma (partial reconfiguration)

Kısmi Yeniden Yapılandırma (Partial Reconfiguration — PR), PL'nin yalnızca belirli bir bölümünü yeniden programlarken geri kalanın çalışmaya devam etmesini sağlar. Vivado'da özel PR akışı gerektirir.

Vivado PR tasarım gereksinimleri

Statik bölgeDeğişmeyen PL tasarımı — toplam bitstream ile yüklenir; AXI Interconnect ve köprüler burada
Reconfigurable Partition (RP)Pconfig primitive ile çevrili bölge; PR bitstream ile yeniden programlanabilir
Reconfigurable Module (RM)RP için farklı implementasyon; her RM için ayrı .pbit/.pbin dosyası üretilir
PR DecouplerRP'ye giren/çıkan sinyalleri yapılandırma sırasında izole eder — tanımsız sinyal yayılmasını önler

Linux'ta PR yükleme

FPGA_MGR_PARTIAL_RECONFIG flag ile PR yükleme
/* Kısmi bitstream için flags */
info->flags = FPGA_MGR_PARTIAL_RECONFIG;
info->firmware_name = "partial_rm1.bin";

/* PR region için ayrı fpga_region tanımlanmış olmalı */
ret = fpga_region_program_fpga(pr_region);

/* Sysfs'ten PR yükleme (configfs overlay) */
# mkdir /sys/kernel/config/device-tree/overlays/pr_rm1
# cp pr-overlay.dtbo /sys/kernel/config/device-tree/overlays/pr_rm1/dtbo

Bu bölümde

  • PR: statik bölge çalışırken RP yeniden programlanır — kesinti yok
  • Vivado PR flow: RP tanımla → RM implementasyonları → .pbin üret
  • FPGA_MGR_PARTIAL_RECONFIG: Linux'ta kısmi yükleme için flag
  • PR Decoupler: RP izolasyonu — tanımsız sinyal yayılması önlenir

05 FPGA bridge etkinleştirme/devre dışı bırakma

Linux FPGA Manager, bridge'leri otomatik yönetir. Ancak bazı durumlarda manuel bridge kontrolü gerekebilir: hata kurtarma, özel yeniden yapılandırma sekansları veya tanılama.

Kernel API

fpga_bridge — kernel API (C)
#include <linux/fpga/fpga-bridge.h>

/* Tek bridge kontrolü */
struct fpga_bridge *bridge;
bridge = of_fpga_bridge_get(dev->of_node, NULL);
if (IS_ERR(bridge)) { /* ... */ }

fpga_bridge_disable(bridge);    /* Veri yolunu kapat */
/* ... bitstream yükleme ... */
fpga_bridge_enable(bridge);     /* Veri yolunu aç */
fpga_bridge_put(bridge);

/* Birden fazla bridge'i senkron kontrolü */
LIST_HEAD(bridge_list);
fpga_bridge_get_to_list(dev->of_node, NULL, &bridge_list);
fpga_bridges_disable(&bridge_list);
/* ... */
fpga_bridges_enable(&bridge_list);
fpga_bridges_put(&bridge_list);

Sysfs bridge kontrolü

/sys/class/fpga_bridge/ — bridge durumu
# Bridge'leri listele
ls /sys/class/fpga_bridge/
# → br0  br1  br2  br3

# Bridge durumu
cat /sys/class/fpga_bridge/br0/state
# → enabled veya disabled

# Manuel devre dışı bırakma
echo 0 > /sys/class/fpga_bridge/br0/enable
echo 1 > /sys/class/fpga_bridge/br0/enable

Bu bölümde

  • fpga_bridge_disable/enable: tekil bridge kontrolü
  • fpga_bridges_disable/enable: listedeki tüm bridge'leri atomik kontrol
  • /sys/class/fpga_bridge/br0/enable: sysfs üzerinden manuel kontrol
  • Tanımlama: of_fpga_bridge_get() — DT node'undan bridge al

06 xilinx-pr-decoupler

PR Decoupler, Reconfigurable Partition ile statik bölge arasındaki sinyalleri yapılandırma sırasında izole eden bir IP bloğudur. Linux'ta xlnx,pr-decoupler sürücüsü ile yönetilir.

PR Decoupler çalışma prensibi

  Statik Bölge → [PR Decoupler] → Reconfigurable Partition

  Yapılandırma başlamadan önce:
    Decoupler: sinyalleri kes (tüm girişler sabit değer)
    Bridge: devre dışı bırak

  Bitstream yazımı:
    RP tanımsız durumda
    Decoupler sinyalleri izole eder → statik bölge etkilenmez

  Yapılandırma tamamlandıktan sonra:
    Bridge: etkinleştir
    Decoupler: sinyalleri geçir (normal çalışma)

Device Tree tanımı

PR Decoupler — DTS
pr_decoupler_0: pr-decoupler@40010000 {
    compatible = "xlnx,pr-decoupler-1.00", "xlnx,pr-decoupler";
    reg = <0x40010000 0x10>;
    clocks = <&clkc 15>;
    clock-names = "aclk";
    #fpga-bridge-cells = <0>;
};

/* fpga_region bu bridge'i kullanır */
fpga-region0 {
    compatible = "fpga-region";
    fpga-mgr = <&devcfg>;
    fpga-bridges = <&pr_decoupler_0>;
    #address-cells = <1>;
    #size-cells = <1>;
    ranges;
};

Decoupler sysfs kontrolü

PR Decoupler — sysfs
# Decoupler'ı etkinleştir (izolasyon başlat)
echo 0 > /sys/class/fpga_bridge/pr_decoupler_0/enable

# PR bitstream yükle...

# Decoupler'ı devre dışı bırak (normal çalışma)
echo 1 > /sys/class/fpga_bridge/pr_decoupler_0/enable

Bu bölümde

  • PR Decoupler: statik←→RP sinyal izolasyonu; yapılandırma sırasında zorunlu
  • xlnx,pr-decoupler: Linux sürücüsü — fpga_bridge API ile entegre
  • DTS: #fpga-bridge-cells = <0>; fpga_region'a bağlanır
  • Sıra: decoupler kapat → bridge kapat → bitstream → bridge aç → decoupler aç

07 sysfs arayüzü ile yapılandırma

Linux FPGA Manager subsystem, sysfs üzerinden kullanıcı alanından doğrudan bitstream yüklemeye olanak tanır. Bu yöntem basit senaryolar ve hata ayıklama için uygundur.

Sysfs üzerinden bitstream yükleme

sysfs — bitstream yükleme adımları
# 1. Bitstream'i firmware dizinine kopyala
cp design.bit.bin /lib/firmware/design.bit.bin

# 2. FPGA manager'ı bul
ls /sys/class/fpga_manager/
# → fpga0

# 3. Mevcut durum
cat /sys/class/fpga_manager/fpga0/state
# → operating

# 4. Bitstream dosya adını yaz (yükleme başlar)
echo "design.bit.bin" > /sys/class/fpga_manager/fpga0/firmware

# 5. Yükleme durumunu izle
cat /sys/class/fpga_manager/fpga0/state
# → writing ... → operating (başarı)
# → write_err       (hata)

Hata durumları ve çözümleri

DurumAnlamıÇözüm
write_errBitstream yazımı başarısızdmesg'i kontrol et; .bit.bin formatını doğrula
write_init_errFPGA başlatma hatasıPS reset; saat frekansı kontrolü
write_complete_errDONE sinyali gelmediHedef cihaz eşleşmesi; bit-endian kontrolü
unknownHenüz yapılandırılmamışNormal; boot sonrası ilk yükleme öncesi

flags sysfs attribute

Partial reconfiguration via sysfs flags
# PR için flags yaz (FPGA_MGR_PARTIAL_RECONFIG = 1)
echo 1 > /sys/class/fpga_manager/fpga0/flags
echo "partial_rm.bin" > /sys/class/fpga_manager/fpga0/firmware

# Tam yapılandırma için flags sıfırla
echo 0 > /sys/class/fpga_manager/fpga0/flags

Bu bölümde

  • firmware attribute: dosya adı yazınca yükleme başlar (/lib/firmware/ aranır)
  • state attribute: operating/writing/write_err — durum izleme
  • flags attribute: 0=tam yapılandırma, 1=kısmi yapılandırma (PR)
  • write_err: dmesg + .bit.bin format doğrulama ile tanı

08 Pratik: Zynq runtime DT overlay ile bitstream yükleme

Bu bölümde Zynq-7000 tabanlı bir sistemde (veya Zynq'e bağlı Raspberry Pi senaryosunda) runtime DT overlay kullanılarak yeni bir bitstream yüklenecek ve PL'deki yeni periferale erişilecektir.

Senaryo

Zynq-7000 (ZedBoard / PYNQ-Z2) üzerinde Linux çalışıyor. Başlangıçta PL boş (veya başka bir tasarım yüklü). Çalışma sırasında yeni bir AXI-Lite LED denetleyici bitstream'i yüklenecek ve DT overlay ile periferale erişilecek.

Adım 1: Kernel yapılandırması

Gerekli kernel config seçenekleri
# menuconfig'de etkinleştir
CONFIG_FPGA=y
CONFIG_FPGA_MGR_ZYNQ_FPGA=y
CONFIG_FPGA_REGION=y
CONFIG_FPGA_BRIDGE=y
CONFIG_OF_OVERLAY=y
CONFIG_OF_CONFIGFS=y   # configfs DT overlay için

Adım 2: Bitstream hazırlama

Bitstream dönüştürme ve kopyalama
# Vivado'dan alınan design_1_wrapper.bit → .bit.bin
bootgen -arch zynq -process_bitstream bin \
        -image design_1_wrapper.bit

# Zynq Linux'a SCP ile kopyala
scp design_1_wrapper.bit.bin root@192.168.1.1:/lib/firmware/

# Zynq'te doğrula
ls -la /lib/firmware/design_1_wrapper.bit.bin

Adım 3: DT overlay oluşturma

led-fpga-overlay.dts
/dts-v1/;
/plugin/;

/ {
    fragment@0 {
        target = <&fpga_full>;
        __overlay__ {
            firmware-name = "design_1_wrapper.bit.bin";
        };
    };

    fragment@1 {
        target = <&amba>;
        __overlay__ {
            led_ctrl: led-ctrl@40000000 {
                compatible = "xlnx,led-ctrl-1.0";
                reg = <0x40000000 0x10000>;
                clocks = <&clkc 15>;
                clock-names = "s00_axi_aclk";
                status = "okay";
            };
        };
    };
};

Adım 4: Overlay derleme ve uygulama

Zynq üzerinde overlay uygulama
# DTBO derleme (çapraz derleme veya hedef üzerinde)
dtc -@ -I dts -O dtb -o led-fpga-overlay.dtbo led-fpga-overlay.dts

# configfs mount (genellikle zaten mount edilmiş)
mount -t configfs configfs /sys/kernel/config

# Overlay uygula
mkdir /sys/kernel/config/device-tree/overlays/led_fpga
cp led-fpga-overlay.dtbo \
   /sys/kernel/config/device-tree/overlays/led_fpga/dtbo

# Durum kontrol
cat /sys/kernel/config/device-tree/overlays/led_fpga/status
# → applied

# FPGA manager durumu
cat /sys/class/fpga_manager/fpga0/state
# → operating

# Yeni periferali doğrula
ls /sys/bus/platform/devices/ | grep led
# → 40000000.led-ctrl

Adım 5: LED periferalini test et

LED test — /dev/mem ile
# devmem2 aracıyla (genellikle Zynq Linux'ta mevcut)
devmem2 0x40000000 w 0xFF   # Tüm LED'leri yak
devmem2 0x40000000 w 0x00   # Söndür
devmem2 0x40000000 w 0xAA   # Alternatif desen

# dmesg çıktısında overlay ve sürücü logları
dmesg | tail -20
# [  42.123] fpga_manager fpga0: writing design_1_wrapper.bit.bin to Xilinx Zynq FPGA Manager
# [  43.456] fpga_manager fpga0: state transition: operating

# Overlay'i kaldır (PL sıfırlanmaz, sadece DT kaldırılır)
rmdir /sys/kernel/config/device-tree/overlays/led_fpga
İPUCU

PYNQ framework (Jupyter üzerinden Python), aynı FPGA Manager subsystem'i kullanır ancak Python API'siyle sarmalar. from pynq import Overlay; ol = Overlay("design.bit") komutu aynı DT overlay mekanizmasını tetikler. Düşük seviye anlamak için kernel akışını öğrenmek önemlidir.

Bu bölümde

  • Kernel config: FPGA_MGR_ZYNQ_FPGA + FPGA_REGION + OF_OVERLAY + OF_CONFIGFS
  • bootgen -process_bitstream bin: .bit → .bit.bin dönüşümü
  • configfs overlay: mkdir + cp dtbo → state: applied
  • Temizlik: rmdir overlay dizini — DT kaldırılır; PL yeniden yapılandırılmaz