« 2014年7月 | トップページ | 2014年9月 »

2014.08.29

高速ADコンバータからのデータをZYNQで受信

ZYNQ搭載のADCボード「Cosmo-Z」では、アナログデバイセス社のAD9633というADコンバータを搭載しています。

Zynq_iserdes

このAD9633は最高125MHz,12bitでサンプリングすることができます。125MHz,12bitなのでデータレートは1.5Gbpsにもなります。このデータは2本のLVDSになって、(つまり4本の線で)750Mbpsで送られてきます。これをZYNQのI/Oピンで受け取ろうというわけです。

XILINXのFPGAは、Spartan-6以降ではすべてのI/OピンがISERDESというデシリアライザを搭載しています。だから、FPGAの普通のI/Oピンで1Gbpsクラスの信号を受信することができるのです。

Zynq_iserdes_1_2

しかも、ISERDESの前にはIDELAYという可変遅延回路があって、78psくらいの精度で32段階で遅延時間を自由に設定できます。

さて、ISERDESを使って750MHzのデータを受け取ろうとするわけですが、今回の回路では、ADコンバータから送ってくるビット同期用クロックもフレーム同期用クロックも使わずに、FPGAの中で作り出したクロックでサンプリングしようと思います。

それをするためには、ADコンバータが送ってきた信号をちょうどよいポイントでサンプリングしなければなりません。その概念を次の図に示します。

Zynq_iserdes_2

上の図はADコンバータから送られてくる波形を、どのポイントでサンプリングするかを示したものです。▲の点がサンプリングするポイントです。

一番上の青い例は、OKな例です。次のオレンジ色のはNGな例です。信号が変化するタイミングでサンプリングしては正しくサンプリングできません。

最もベストなのは、一番下の黄色の例です。ちょうど信号の安定している真ん中の点でサンプリングします。

実際にIDELAYのタップを32個分変えて実験してみました。

Zynq_iserdes_3

このようになりました。

遅延を増やしていくと、不安定になる点が5タップ分くらいあります。約17タップ動かすと再び安定する領域になるので、17タップで1bitの時間ずれるということでしょう。

今回の波形は750MHzのLVDSなので、1bitが約1.333nsですから、これが17タップに相当します。これゆえ1タップは約78psであると推測できます。

まぁ、この波形から推測するとZYNQ 7030のI/Oピン(HighPerformance Port)は2Gbpsくらいまではいけるのではないかと思います。

実際の回路では、まず、ADCにキャリブレーション用のテストパターンとして「100000 100000」という波形を出させて、タップを順番に変えていって、変化が止まった点から7タップ後に止めるようにします。こうすると、ほぼ真ん中のスイートな点でサンプリングできることになります。

そうしたら、bitslipを1つずつ動かして、MSBが1になるように回転させます。こうすると、ビット同期とフレーム同期がぴたっと取れます。

Zynq_iserdes_4

こうなると、どこまでいっても同じタイミングでサンプリングできるので、ADCのデータがちゃんとデコードできるようになります。

Zynq_iserdes_5


ADCにテストパターンではなく、実際のサンプリングデータを出力させてみました。

Zynq_iserdes_6

こんな感じでAD変換結果を確認することができました。

余談ですが、最初は当社のスタッフに実験してもらっていたのですが、ChipScopeを使って非常に苦労していました。

特電スタッフのPCがLinuxマシンだからMITOUJTAGが使えないため仕方なくChipScopeを勧めたのですが、FPGAの書き込みや、ChipScopeの起動、VIOの操作、ChipScopeの信号への名前付け、トリガの設定などでとても苦労していたようです。

Zynq_iserdes_7

横から見ていて、MITOUJTAGのほうがはるかに使い勝手がいいです。世界中でChipScopeで苦労している人たちのためにも、MITOUJTAGのロジアナ機能をもっと伸ばしていこうと決意した次第です。

| | コメント (2)

2014.08.26

ZYNQのADCボード、ADCからの信号を確認!

ZYNQのADCボード「Cosmo-Z」で、ADCからの信号が確認できました。

Ad9633x2_2


このボードで使っているADCは、AnalogDevices社のAD9633というもの。最高125MHz 12bitのLVDS2組で信号を出してきます。125MHzで12bitということはビットレートが1500Mbpsにもなってしまうので、さすがのLVDSでも厳しくなります。そこで、2ペアのLVDSに分散させて信号を送ることでデータレートを750Mbpsに抑えることができます。

LVDSで送ってくる信号をZYNQで受けるときに、DIFF_TERMをONにしておくと、FPGA内で終端抵抗を入れてくれるので便利です。DIFF_TERMを使うには、IBUFDSをインスタンシエートするときに、genericで

inst_ibufds_adc2_0c : IBUFDS generic map (
	 DIFF_TERM => TRUE
)
 port map (
	I => adc2_d0c_p_ip,
	IB => adc2_d0c_n_ip,
	O => adc2_d0c
);

と指定します。またVCCO=1.8Vにしておく必要があります。(HR I/OでLVDS_25ならばVCCIOを2.5Vにする)

さて、AD9633から送られてきたデータはFPGAで正しく受け取れているでしょうか。それをサクッと調べるには、バウンダリスキャンが便利です。バウンダリスキャンというのは、瞬間瞬間のFPGAの端子の状態(H/L)をJTAGを通じて読み出すことができる技術です。

バウンダリスキャンを行うためのツールには、MITOUJTAG(みとうジェイタグ)というソフトウェアを使います。MITOUJTAGでバウンダリスキャンをして波形にしてみると・・

Bscan_ad9633_2

このように、PとNが対称的な波形になっていることがわかります。LVDSの+と-ですから、対称的になるのは当然なのですが、面白いことに、LVDSの信号は数百MHzで動いていて、バウンダリスキャンはせいぜいkHzのオーダーなのですが、ちゃんとPとNが対称的に動いているということです。

バウンダリスキャンのサンプリングは、すべての端子が時間的に同時に行われるので、遅いサンプリングでもLVDSの対称性が見えるのです。

さて、AD9633には内蔵レジスタがいくつもあって、SPIを通じて様々な値に設定できます。VREFの電圧とか、オフセットとか、様々なパラメータをSPI経由で設定できます。

ZYNQのソフトウェアを作って、この内蔵レジスタの値を表示してみることにしました。下記の図のような感じで、内蔵レジスタの設定が見えます。

Ad9633_reg

見るだけではなく、レジスタを書き換えることができるようにもしました。それが、アドレスの0x0dのレジスタ。「Test mode」

Ad9633_reg2

このレジスタをいじると、LVDSの出力がADC変換値ではなく、テスト用のパターンに変更できます。つまり、100000000000とか、101010101010といった固定パターンを出すことができるようになります。この機能を使ってZYNQ内のISERDESのキャリブレーションをしようというわけです。

とりあえず、UARTのコンソールからwrreg d 1で、midscale shortというパターンを出してみました。

Bscan_ad9633_1

ADC変換値を出力していたのが、ピタッと止まります。デフォルトではADCは2の補数出力なので、midscaleは000000000000だからです。

次に、wrreg d 2とコマンドを与えます。これは+full scaleの出力です。

Bscan_ad9633_3

今度は動き出しますが、D1A、D1B、D1C、D1Dの方だけが動きます。D0Aは下位6ビット、D1Aは上位ビットを示しています。011111111111を出力しようとしているので下位6bitは1のまま、上位6bitは011111を出力しているから、H:Lは5:1の割合で出てくることになります。

どうやら、ADCはちゃんと動いているようです。PとNが対称的に見えているので、FPGAの端子への接続やクロストークも問題なさそうです。

このようにバウンダリスキャンを使うと、端子の状態をすぐに見ることができます。ChipScopeなどと違い、FPGAに何もプログラミングされていない状態でも使えるので、FPGAの中身をまだ作っていない開発の初期段階からすぐに使えるので便利です。

次はISERDESのDELAYを自動調整する回路を作ります。

| | コメント (0)

2014.08.20

Coxmo-ZでLinuxが起動!

ZYNQ搭載のADCボード「Cosmo-Z」でLinuxが起動するようになりました。

Cosmoz_linux

当社のスタッフがわずか1日でLinuxを移植してくれました。

起動メッセージのすべてを参考までに掲載します。

Xilinx First Stage Boot Loader
Release 14.5/2013.1     Aug 19 2014-21:36:06
Devcfg driver initialized
Silicon Version 3.1
Boot mode is SD
SD: rc= 0
SD Init Done
Flash Base Address: 0xE0100000
Reboot status register: 0x60400000
Multiboot Register: 0x0000C000
Image Start Address: 0x00000000
Partition Header Offset:0x00000C80
Partition Count: 3
Partition Number: 1
Header Dump
Image Word Len: 0x0016CFC8
Data Word Len: 0x0016CFC3
Partition Word Len:0x0016CFC8
Load Addr: 0x00000000
Exec Addr: 0x00000000
Partition Start: 0x000055D0
Partition Attr: 0x00000020
Section Count: 0x00000001
Checksum: 0xFFBB386B
Bitstream
Encrypted
In FsblHookBeforeBitstreamDload function
PCAP:StatusReg = 0x40000A30
PCAP:device ready
PCAP:Clear done
Level Shifter Value = 0xA
Devcfg Status register = 0x40000A30
PCAP:Fabric is Initialized done
PCAP register dump:
PCAP CTRL 0xF8007000: 0x4E00E07F
PCAP LOCK 0xF8007004: 0x0000001A
PCAP CONFIG 0xF8007008: 0x00000508
PCAP ISR 0xF800700C: 0x0802000B
PCAP IMR 0xF8007010: 0xFFFFFFFF
PCAP STATUS 0xF8007014: 0x00070A30
PCAP DMA SRC ADDR 0xF8007018: 0x00100001
PCAP DMA DEST ADDR 0xF800701C: 0xFFFFFFFF
PCAP DMA SRC LEN 0xF8007020: 0x0016CFC8
PCAP DMA DEST LEN 0xF8007024: 0x0016CFC3
PCAP ROM SHADOW CTRL 0xF8007028: 0xFFFFFFFF
PCAP MBOOT 0xF800702C: 0x0000C000
PCAP SW ID 0xF8007030: 0x00000000
PCAP UNLOCK 0xF8007034: 0x757BDF0D
PCAP MCTRL 0xF8007080: 0x30800100
...................................................................................................
DMA Done !

FPGA Done !
In FsblHookAfterBitstreamDload function
Partition Number: 2
Header Dump
Image Word Len: 0x0001498D
Data Word Len: 0x0001498D
Partition Word Len:0x0001498D
Load Addr: 0x04000000
Exec Addr: 0x04000000
Partition Start: 0x001725A0
Partition Attr: 0x00000010
Section Count: 0x00000001
Checksum: 0xF7E4FB47
Application
Handoff Address: 0x04000000
Enabling Level Shifters PL to PS Address = 0xF8000900 Value = 0xF
AXI Interface enabled
FPGA Reset Register Address = 0xF8000240 , Value = 0x0
In FsblHookBeforeHandoff function
SUCCESSFUL_HANDOFF
FSBL Status = 0x1


U-Boot 2014.01-dirty (Aug 20 2014 - 11:30:24)

I2C:   ready
Memory: ECC disabled
DRAM:  512 MiB
MMC:   zynq_sdhci: 0
SF: Detected N25Q128A with page size 256 Bytes, erase size 64 KiB, total 16 MiB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   Gem.e000b000
Hit any key to stop autoboot:  0
Device: zynq_sdhci
Manufacturer ID: 45
OEM: 2d42
Name: TEAMTran Speed: 50000000
Rd Block Len: 512
SD version 2.0
High Capacity: No
Capacity: 1.8 GiB
Bus Width: 4-bit
reading uEnv.txt
** Unable to read file uEnv.txt **
Copying Linux from SD to RAM...
reading uImage
3360016 bytes read in 296 ms (10.8 MiB/s)
reading devicetree.dtb
7461 bytes read in 13 ms (559.6 KiB/s)
reading uramdisk.image.gz
5310018 bytes read in 461 ms (11 MiB/s)
## Booting kernel from Legacy Image at 03000000 ...
   Image Name:   Linux-3.14.0-xilinx
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    3359952 Bytes = 3.2 MiB
   Load Address: 00008000
   Entry Point:  00008000
   Verifying Checksum ... OK
## Loading init Ramdisk from Legacy Image at 02000000 ...
   Image Name:
   Image Type:   ARM Linux RAMDisk Image (gzip compressed)
   Data Size:    5309954 Bytes = 5.1 MiB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK
## Flattened Device Tree blob at 02a00000
   Booting using the fdt blob at 0x2a00000
   Loading Kernel Image ... OK
   Loading Ramdisk to 1f61e000, end 1fb2e602 ... OK
   Loading Device Tree to 1f619000, end 1f61dd24 ... OK

Starting kernel ...

Uncompressing Linux... done, booting the kernel.
Booting Linux on physical CPU 0x0
Linux version 3.14.0-xilinx (xcomp@xcomp-Z87M-D3H) (gcc version 4.7.3 (Sourcery CodeBench Lite 2013.05-40) ) #2 SMP PREEMPT Wed Aug 20 11:56:41 JST 2014
CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=18c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
Machine model: Xilinx Zynq
bootconsole [earlycon0] enabled
cma: CMA: reserved 128 MiB at 17400000
Memory policy: Data cache writealloc
PERCPU: Embedded 8 pages/cpu @dfba1000 s9024 r8192 d15552 u32768
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 130048
Kernel command line: console=ttyPS0,115200 root=/dev/ram rw earlyprintk
PID hash table entries: 2048 (order: 1, 8192 bytes)
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
Memory: 376368K/524288K available (4596K kernel code, 232K rwdata, 1536K rodata, 188K init, 192K bss, 147920K reserved, 0K highmem)
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xfff00000 - 0xfffe0000   ( 896 kB)
    vmalloc : 0xe0800000 - 0xff000000   ( 488 MB)
    lowmem  : 0xc0000000 - 0xe0000000   ( 512 MB)
    pkmap   : 0xbfe00000 - 0xc0000000   (   2 MB)
    modules : 0xbf000000 - 0xbfe00000   (  14 MB)
      .text : 0xc0008000 - 0xc06055ac   (6134 kB)
      .init : 0xc0606000 - 0xc0635340   ( 189 kB)
      .data : 0xc0636000 - 0xc06701a0   ( 233 kB)
       .bss : 0xc06701ac - 0xc06a033c   ( 193 kB)
Preemptible hierarchical RCU implementation.
        Dump stacks of tasks blocking RCU-preempt GP.
        RCU restricting CPUs from NR_CPUS=4 to nr_cpu_ids=2.
RCU: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=2
NR_IRQS:16 nr_irqs:16 16
ps7-slcr mapped to e0802000
zynq_clock_init: clkc starts at e0802100
Zynq clock init
sched_clock: 64 bits at 333MHz, resolution 3ns, wraps every 3298534883328ns
ps7-ttc #0 at e0804000, irq=43
Console: colour dummy device 80x30
Calibrating delay loop... 1325.46 BogoMIPS (lpj=6627328)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
CPU: Testing write buffer coherency: ok
CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
Setting up static identity map for 0x457ae8 - 0x457b40
L310 cache controller enabled
l2x0: 8 ways, CACHE_ID 0x410000c8, AUX_CTRL 0x72760000, Cache size: 512 kB
CPU1: Booted secondary processor
CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
Brought up 2 CPUs
SMP: Total of 2 processors activated.
CPU: All CPU(s) started in SVC mode.
devtmpfs: initialized
VFP support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 4
regulator-dummy: no parameters
NET: Registered protocol family 16
DMA: preallocated 256 KiB pool for atomic coherent allocations
cpuidle: using governor ladder
cpuidle: using governor menu
syscon f8000000.ps7-slcr: regmap [mem 0xf8000000-0xf8000fff] registered
hw-breakpoint: found 5 (+1 reserved) breakpoint and 1 watchpoint registers.
hw-breakpoint: maximum watchpoint size is 4 bytes.
zynq-ocm f800c000.ps7-ocmc: ZYNQ OCM pool: 256 KiB @ 0xe0880000
bio: create slab 

at 0 vgaarb: loaded SCSI subsystem initialized usbcore: registered new interface driver usbfs usbcore: registered new interface driver hub usbcore: registered new device driver usb media: Linux media interface: v0.10 Linux video capture interface: v2.00 pps_core: LinuxPPS API ver. 1 registered pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti

PTP clock support registered EDAC MC: Ver: 3.0.0 Advanced Linux Sound Architecture Driver Initialized. Switched to clocksource arm_global_timer NET: Registered protocol family 2 TCP established hash table entries: 4096 (order: 2, 16384 bytes) TCP bind hash table entries: 4096 (order: 3, 32768 bytes) TCP: Hash tables configured (established 4096 bind 4096) TCP: reno registered UDP hash table entries: 256 (order: 1, 8192 bytes) UDP-Lite hash table entries: 256 (order: 1, 8192 bytes) NET: Registered protocol family 1 RPC: Registered named UNIX socket transport module. RPC: Registered udp transport module. RPC: Registered tcp transport module. RPC: Registered tcp NFSv4.1 backchannel transport module. Trying to unpack rootfs image as initramfs... rootfs image is not initramfs (no cpio magic); looks like an initrd Freeing initrd memory: 5184K (df61e000 - dfb2e000) hw perfevents: enabled with ARMv7 Cortex-A9 PMU driver, 7 counters available futex hash table entries: 512 (order: 3, 32768 bytes) jffs2: version 2.2. (NAND) (SUMMARY)  c 2001-2006 Red Hat, Inc. msgmni has been set to 1001 io scheduler noop registered io scheduler deadline registered io scheduler cfq registered (default) dma-pl330 f8003000.ps7-dma: Loaded driver for PL330 DMAC-2364208 dma-pl330 f8003000.ps7-dma:     DBUFF-128x8bytes Num_Chans-8 Num_Peri-4 Num_Events-16 ,ヒkスア[ttyPS0] enabledS0 at MMIO 0xe0001000 (irq = 82, base_baud = 6249999) is a xuartps console [ttyPS0] enabled bootconsole [earlycon0] disabled bootconsole [earlycon0] disabled xdevcfg f8007000.ps7-dev-cfg: ioremap 0xf8007000 to e0866000 [drm] Initialized drm 1.1.0 20060810 brd: module loaded loop: module loaded m25p80 spi0.0: found n25q128a11, expected n25q128 m25p80 spi0.0: n25q128a11 (16384 Kbytes) 5 ofpart partitions found on MTD device spi0.0 Creating 5 MTD partitions on "spi0.0": 0x000000000000-0x000000100000 : "qspi-fsbl-uboot" 0x000000100000-0x000000600000 : "qspi-linux" 0x000000600000-0x000000620000 : "qspi-device-tree" 0x000000620000-0x000000c00000 : "qspi-rootfs" 0x000000c00000-0x000001000000 : "qspi-bitstream" e1000e: Intel(R) PRO/1000 Network Driver - 2.3.2-k e1000e: Copyright(c) 1999 - 2013 Intel Corporation. libphy: XEMACPS mii bus: probed xemacps e000b000.ps7-ethernet: pdev->id -1, baseaddr 0xe000b000, irq 54 ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver ehci-pci: EHCI PCI platform driver zynq-dr e0002000.ps7-usb: Unable to init USB phy, missing? usbcore: registered new interface driver usb-storage mousedev: PS/2 mouse device common for all mice i2c /dev entries driver zynq-edac f8006000.ps7-ddrc: ecc not enabled cpufreq_cpu0: failed to get cpu0 regulator: -19 Xilinx Zynq CpuIdle Driver started sdhci: Secure Digital Host Controller Interface driver sdhci: Copyright(c) Pierre Ossman sdhci-pltfm: SDHCI platform and OF driver helper mmc0: no vqmmc regulator found mmc0: no vmmc regulator found mmc0: SDHCI controller on e0100000.ps7-sdio [e0100000.ps7-sdio] using ADMA usbcore: registered new interface driver usbhid usbhid: USB HID core driver TCP: cubic registered NET: Registered protocol family 17 Registering SWP/SWPB emulation handler regulator-dummy: disabling drivers/rtc/hctosys.c: unable to open rtc device (rtc0) ALSA device list:   No soundcards found. RAMDISK: gzip image found at block 0 mmc0: new high speed SD card at address 0001 mmcblk0: mmc0:0001 TEAM 1.83 GiB mmcblk0: p1 VFS: Mounted root (ext2 filesystem) on device 1:0. devtmpfs: mounted Freeing unused kernel memory: 188K (c0606000 - c0635000) Starting rcS... ++ Mounting filesystem FAT-fs (mmcblk0p1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck. ++ Setting up mdev ++ Starting telnet daemon ++ Starting http daemon ++ Starting ftp daemon ++ Starting ssh daemon random: sshd urandom read with 11 bits of entropy available rcS Complete zynq>

起動メッセージを読んでみると、なんだかArtix-7のMicroBlaze Linuxよりも豪華です。例えば、u-bootでSPI ROMが認識されていたり、SDカードが使えたりしています。

| | コメント (0)

2014.08.19

ZYNQのFSBLが動かない場合の対処法

なひたふは、「Cosmo-Z」というZYNQ7030搭載のADCボードを作っているのですが、FSBLが起動しなくて約一週間も悩んでいました。

Zynq_cosmoz

ZedBoardやMicroZEDなど、XILINXが全面的に協力しているボードなら簡単なことなのでしょうが、自作したボードでFSBLを起動することが、こんなに困難だとは思いもしませんでした。

そして今日ついにFSBLが安定して起動するようになりました。長かった・・

この1週間、ずっとFSBLをSDKでステップ実行したり、いろいろな部品を取り換えたりして試行錯誤していました。そんなFSBLが動かない場合の対処法を紹介します。

① QSPI ROMからのFSBL起動は難易度が高い。迷わずSDカードを選択せよ!

ZYNQは、NOR型フラッシュ、NANDフラッシュ、QSPI、SDカードなどから起動できます。

しかし、QSPIから起動できるとはいうものの、SPIモードではなく、必ずQSPIモードでのアクセスとなります。しかも、QSPIモードはROMベンダによって規格が微妙に異なるので、ZYNQで使えるSPI ROMの品種は非常に限られています。

例えば、MicronやNumonyx、SSTなどのSPI ROMは使えないようです。

SPIモードではアクセスできないので、結局のところ、1品種か2品種くらいしか該当品がありません。しかも入手困難です。あきらめて、SDカードブートにしたほうがよいでしょう。

② FSBL自体は読み込まれているか?

ZYNQの中のBOOTROMはSDカード内のBOOT.BINを読み出して実行します。FSBLは同じくBOOT.BINを読み出します。

一度目の、BOOTROMが読み出すBOOT.BINはたいてい成功しています。しかし、FSBLが読み出すBOOT.BINで失敗することがよくあります。

その理由は、

  1. カード検出信号が検出されていない
  2. SDIOのクロックの設定が速すぎる(?)
  3. IO電圧の設定が間違っている ※オシロで見ると信号が出てこない

です。つまり、FSBLが起動していないと思っても、実はFSBL自体は起動しているけど、二度目のBOOT.BINの読み出しで失敗しているということが結構あります。

③ FSBLのデバッグオプションをONにする

FSBLには様々なデバッグメッセージをUARTに出力するコードがあります。これを有効にするには、fsbl_debug.hに

#define FSBL_DEBUG_INFO

を追加すればいいのですが、それだけではうまくいかないことが多々あります。

そんな場合は、SDKでHelloWorld.cなど適当なアプリを生成して、その中にあるplatform_config.hと、platform.cと、platform.hを持ってきます。

そして、main.cで、先頭の#includeのところに、

#include "platform.h"

を追加します。

それから、main()の中のSlcrUnlock();の後に

init_platform();

を追加します。

fsbl_debug.hの、fsbl_printfのマクロ定義を

#define fsbl_printf(type, ...) \
  {xil_printf (__VA_ARGS__); }

に変えます。

これで確実にデバッグメッセージをUARTに出力できるようになります。

TeraTermなどで見ると、起動に失敗したときにこんなメッセージが出ると思います。

Fsbl_debug

Xilinx First Stage Boot Loader
Release 14.5/2013.1     Aug 17 2014-22:39:33
Devcfg driver initialized
Silicon Version 3.1
Boot mode is SD
SD: rc= 0
send_cmd: Error: (0x00038000) cmd: 0 arg: 0x0
send_cmd: Error: (0x00038000) cmd: 8 arg: 0x1AA
send_cmd: Error: (0x00038000) cmd: 55 arg: 0x0
send_cmd: Error: (0x00038000) cmd: 41 arg: 0x40300000
SD: Unable to open file BOOT.BIN: 3
SD_INIT_FAIL
FSBL Status = 0xA011

④ カードはDETECTされているか?

FSBL自体は起動したものの、FSBLがBOOT.BINを読んでくれない場合、No SD card presentとなってしまいます。

Xilinx First Stage Boot Loader
Release 14.5/2013.1     Aug 17 2014-22:39:33
Devcfg driver initialized
Silicon Version 3.1
Boot mode is SD
SD: rc= 0
No SD card present.
SD: Unable to open file BOOT.BIN: 3
SD_INIT_FAIL
FSBL Status = 0xA011

こうなる原因は、CD信号とWP信号がただしく読み出せていないためです。CDとWPは、カード検出と、ライトプロテクトの意味です。これらの信号がLレベルになっていないと、FSBLは正しく動作しません。

CDとWPは、SDカードが挿入されるとスイッチでGNDに接続されるピンなのですが、Cosmo-Zでは、CDとWPピンに直列に1kΩの抵抗を入れていました。すると、カードが挿入された状態で、信号線はほぼ0Vで、TTLレベルで見てもCMOSレベルで見ても明らかに0Vなのですが、ZYNQのFSBLはLと認識してくれません。

Sch_sd_csz

一方、ZedBoardでは、直列抵抗は499Ωです。

Sch_sd_zed

この抵抗が1kΩだとダメで、499Ω以下だと認識されます。オシロで見てもLレベルなので区別はつきませんが、ZYNQのソフトウェアは区別しています。

微妙ですね。

⑤ BOOTROMとFSBLではSDカードのアクセス方法が違うことに注意せよ

ZYNQは起動すると、内部にあるユーザから見えないROM「BOOTROM」から起動します。

このBOOTROMと、FSBLでは、SDカードのアクセスの方法が異なります。

◆BOOTROM

  • ZED Boardで使われているようなES品のZYNQでは、1bitモードでSDカードにアクセスする。
  • ZED Boardで使われているES品のZYNQでは、MIO0をCD(カード検出信号)として扱う
  • 最近のプロダクション版ZYNQでは、4bitモードでアクセスする
  • 最近のプロダクション版ZYNQでは、MIO47をCDとする

◆FSBL

  • 4bit モードでSDカードにアクセスする
  • CDとWPの割り当ては、ps7_init.cで設定されている。つまり、EDKで設定したMIOの任意のポートに割り当てられる 

⑥ CDとWPピンは設定したか?

EDKでSDカードを有効にしても、デフォルトではCDとWPのピンが割り当てられていないので、FSBLはSDカードを認識しません。

この割り当てを設定するために0xF8000830番地のレジスタを直接操作すること

*(volatile unsigned long *)0xf8000830  = 0x002f002e;

のようなことを紹介するページもあるのですが、実は、そんなことはしなくても大丈夫です。EDKのPS設定画面で、SD0の設定を開き、CDとWPを然るべきMIOピンに割り当てます。

ZEDと同じ(ZYNQの標準)にするなら、CD=MIO47、WP=MIO46にします。

Psconf_1_2

これで、上のコードと同じことが初期化ルーチン(ps7_init.c)内で安全に行われるようになります。

⑦ SDIOのクロックは50MHzにする

デフォルトでは125MHzになっているようなので50MHzにします。どんな周波数の範囲ならOKなのかはわかりませんが、50MHzにしておきます。

Psconf_3

⑧ EDKでIOピンの設定を1.8Vにしたか?

PSの設定で、I/Oの電圧を設定するところがあります。これはShow I/O Standard Optionsをチェックしないと出てきません。

このチェックを入れて、Bank0とBank1の電圧を適切に設定します。

デフォルトでは3.3Vになっていますが、実際のボードが1.8Vだと信号が出てこないようです。

この設定が見つけられず、3日間くらい悩みました。これを確実に設定してください。

Psconf_2

以上の設定で、ちゃんとFSBLはBOOT.BINを読み込んでくれるようになると思います。

まとめ

FSBLが動かない場合は

① デバッグを有効にして、No SD card presentと出ていれば、CDとWPの確認をする

② CD(MIO47)とWP(MIO46)の割り当てが正しければ、SDカードのSW端子でGNDへ引っ張る直列抵抗を確認する

③ SDIOクロックは50MHzになっているか確認する

④ I/O電圧は1.8Vになっているか確認する

これでちゃんと起動するようになると思います。

この記事が自作派ZYNQerの皆様のお役に立てば幸いです。

| | コメント (1)

2014.08.13

ZYNQのADCボードの実装があがりました

本日、ZYNQのADCボード「Cosmo-Z」の実装があがってきました。2枚あります。

Cosmoz3

ZYNQはこんなパッケージでした。これがFBG656ってやつですね。初めてみました。上に見えるのはDDR3 SDRAM、右に見えるのがEZ-USB FX3です。

Cosmoz1

ずらっと並んだ高速ADCと、メザニン。

Cosmoz2

実装していなかったコネクタやコンデンサなど、すべての部品を手作業ではんだ付けして、完成です。

Cosmoz4

安定化電源をつなぎ、1Vから徐々に電圧を上げていき、各電源が異常な電圧を出さないかどうかチェックした。1.0,1.2,1.5,3.3VすべてOK。

ZYNQに何も書き込まない状態で消費電流測ったら890mAです。結構食います。アナログ部の消費電力が結構大きいようです。

おそるおそる電源を入れ、EZ-USB FX3にUSB-JTAGのファームウェアを書き込んで、MITOUJTAGでをつないだら認識できました!

ここまでくれば一安心です。

Cosmoz5

このボードのUSBコネクタはライトアングルタイプで上に出てくるやるなので、ポキッと折れそうで怖いです。エポキシで固めるなどの補強が必要かもしれません。

Cosmoz6

さて、いろいろ書き込んだり、プログラムを動かそうとしているのですが、なかなか安定して動作しません。どうやら、MIO[6:2]の設定でいろいろあるようです。

ZYNQをJTAGで見ると、ARMのDAPというものと、FPGAの部分と、2つ見えるはずなのでうが、これが1つしか見えていません。これはMIO[2]で決まるようです。

MIO[2]が0だとカスケードモードというやつになるそうなのですが、それでも1つしか見えないときがあります。たぶん、ZYNQの中の初期ブートコードがMIO[7:3]を見て起動モードを設定してしまって、そのときにDAPを隠すようなことをしているのだと思います。

特に、iMPACTでコンフィグするには、JTAG ブートモードにしなければならないのかもしれません。QSPIやSDカードモードではiMPACTでは失敗するようです。MITOUJTAGではどのモードでも書き込めるのに、なぜかiMPACTでは失敗します。

Zynq_boot

このあたりのジャンパをいろいろ変えて試しているのですが、そのときに、MITOUJTAGが使えてとても助かりました。

MIOはモード設定ピンと、QSPIの出力を兼ねるので、リセット時の状態がどうなっているかは起動してしまうとわかりません。MITOUJTAGのバウンダリスキャンを使えば、ZYNQの起動前のMIOの状態が見ながらいろいろ試すことができました。

Zynq_mio

ZYNQ起動する前後の波形です。

Zynq_boot_wave

PS_POR_BがLに下がると、各MIOの端子が出力を停止し、その後、SD_DATAが激しく動いてブートプログラム(boot.bin)を読みに行っているのがわかります。起動した後はMIO/BOOT_MODEは出力に変わってしまっています。

上の波形では、

  • VCFG[1:0]="11"・・バンク1、バンク0ともに1.8V
  • MIO[6]/BOOT_MODE[4]=1・・PLLバイパス
  • MIO[5]/BOOT_MODE[3]=1・・SDカードブート
  • MIO[4]/BOOT_MODE[2]=1・・SDカードブート
  • MIO[3]/BOOT_MODE[1]=0・・SDカードブート
  • MIO[2]/BOOT_MODE[0]=0・・・カスケードモード

ということがわかります。

起動する前のモードピンが正しい値になっているかを調べたり、ちゃんとSDカードを読みに行っているのかを調べたりすることは、MITOUJTAGを使わなければ不可能だったと思います。

| | コメント (0)

2014.08.11

A/D変換器のテストアプリを開発

今までA/D変換器の動作テストにはExcelで作ったVBAマクロを使ってきましたが、

Adc_vba

やはり実用的なことを考えると使いにくいので、Borland C++ Builderで簡単なアプリを作りました。

Ad_analyze_1

動作も速いし、安定しているし、いいことばかりです。

特電のA/D変換ボードには16bit 1MHzのDACも2ch搭載しているので、そのDACから疑似乱数やsin波、lamp波を出す回路をFPGAに作りこんでいます。そのコントロールもこのアプリでできるようにしました。

このアプリでは、ヒストグラムを取ることもできます。

下の図は、疑似乱数をsin波を入れてみて、そのヒストグラムをとったものです。

Ad_analyze_2

こんなのがリアルタイムにワキワキ動きます。

標準電圧発生器で定電圧を入れると、理想的にはガウス関数型のヒストグラムにはるはずなのですが、実際にはわずかに凹んだところが出てきます。

この凹みは、DNLが足りないコードの部分を示しています。

Ad_analyze_3

つまり、A/D変換器の階段がその値だけ狭いため、ヒストグラムが小さくなるという出方をするわけです。

上の図でいうと、本来の値から10%くらい減っている(そして左のところが10%くらい増えている)ので、±0.1LSBくらいのDNLがあることが速算できます。

使用しているAD変換ICでは、個体差もありますが、おおむね4つごとにDNLの大小が繰り返される傾向があります。

しかも、このヒストグラムの中心は、長い時間で見ると、0.1mVくらい揺れているのです。信号源に使っている標準電圧発生器がぴったりと安定させることができないためなのですが、つまりこれが1/f ゆらぎってやつなのでしょう。

A/D変換を目でみるのは、とても面白いです。仕事を忘れてついつい遊んでしまいます。

あと、このアプリにFFTの機能が実装できれば完璧です。ただ、サクッと使えるFFTのライブラリでいいのが見つからないので、自作するかどうか迷っています。

| | コメント (0)

2014.08.08

18bit A/D変換装置の精度を落としていた原因が判明

長い間、悩んでいた問題がようやく解決できました。

18bit A/D変換器のテストをしていて、入力電圧がフルスケールの端に近づくにつれて簡易的に測ったINLが悪化しているという問題があることに気が付きました。

簡易的な測定というのは、「GPIB制御の標準電圧発生器でいろんな電圧を作ってADCで測る」というシンプルなやり方です。

S字を描いていて直線的ではなく厄介な感じがしますが、INLが悪化といっても±400uVくらいだったので、この問題は個体差か、計測時のやり方の問題か、標準電圧発生器の問題だろうと思っていました。

Inl1

出荷テスト用に数台のボードを並べて測ってみて、すべてのボードで同じような現象が起きたので、これは何か理由があるな・・と。これはヤバい。

この原因を見つけるのはとても苦労しました。何日もかかってようやくわかりました。

対策をしたほうと、していない方を比べてみるとその差は歴然としています。

Inl2

対策をする前(青)は、0.8%くらいのゲイン誤差で、INLは±400uVくらいです。

それに対して、対策をした後(赤)は、0.02%くらいのゲイン誤差で、INLは±100uVくらいのように見えます。

しかし、上ののグラフで入力電圧が±1Vを超えるとギザギザが大きくなっているのは標準電圧発生器のノイズが増えているためです。実際には0V近辺の値が正しい値なので、このA/DボードのINLは±40uVと推定できます。つまり、±2LSBくらいです。

この綺麗なINLのグラフは何度やっても、同じようにとれるようになりました。

Inl3

何台かのボードで測ってみても、ゲイン誤差は0.03~0.05%以下になりました。2.5Vを与えたときに2.499くらいまでは正確にでます。

明日はよりしっかりとした測定をするため、、低ひずみな正弦波を使ってDNLを測定してみることにします。

今回判明した「精度を落としていた原因」については、次回の月刊特電のネタにしようと思います。ご期待ください!

| | コメント (0)

Cosmo-Zの基板が出来上がってきました

半年ほど前から開発しているZynq搭載のADCボードですが、7/31に出図して、今日、出来上がりました。

この基板は宇宙線の観測を主たる目的として開発しているので、「宇宙を見るZYNQ」ということで、Cosmo-Zという名前に決めました。

この暑い中、特電のスタッフに○板.comの倉庫に取りにいってもらって、それを実装屋さんまで届けてもらいました。結構な距離を移動したことだと思います。

出来上がった基板の様子は、

Cosmoz_1

裏面は、

Cosmoz_2


こんな感じです。

FPGAの左にあるメザニンのコネクタは裏表についていますが、このコネクタは、表と裏は独立しているのです。表32本、裏64本で計96本(LVDS48ペア)の高速ディジタル信号が通っています。なので、24個のADCを増設できるのです!

FPGAの部分を拡大してみます。

Cosmoz_3

ぐじゃーーーーーーーーっと。一発で動くといいな。

テスタで測ってみたところ、電源のショートはないみたいです。さて、動くといいのですが・・

実装が完了して、特電に届くのは8月13日。待ち遠しいです。

| | コメント (0)

« 2014年7月 | トップページ | 2014年9月 »