venerdì 16 giugno 2017

FPGA: Computer Vision con D8M-GPIO (seconda parte)

Dopo aver introdotto nel precedente articolo gli elementi principali del sistema, approfondiamo l’architettura del sensore CMOS OV8865.

ov8865

Il blocco principale è l’ image sensor core che si occupa di generare un flusso di dati digitali rappresentanti l’immagine, è composto da varie parti come illustrato nello schema sopra presentato tratto dal Product Brief di Omnivision.

L’image array è composto da pixel con tecnologia BSI-2 (Back-Side Illumination), dove il fotodiodo è posto prima di altri strati. Una tale struttura permettte sostanzialmente una sensibilità maggiore. Termini come Quantum Efficiency e Full-Well Capacity che è possibile leggere nell’immagine seguente saranno maggiormente chiari tra poco.

OmniBSI-2

Senza approfondire troppo l’architettura elettronica dei pixel possiamo dire che il primo passo nel digitalizzare la luce è convertire i fotoni in elettroni, l’efficienza di questo processo è misurata dalla Quantum Efficiency (efficienza quantica). Ad esempio una Quantum Efficiency del 50% indica la generazione di 5 elettroni ogni 10 fotoni sul sensore. L’efficienza come mostrato dal grafico tratto dal paper The Mass Production of Second Generation 65 nm BSI CMOS Image Sensors di Omnivision varia in base alla lunghezza d’onda. Nel grafico sono mostrate per ogni tecnologia tre curve per le prestazioni dei canali R,G,B.

image

Con la tecnologia BSI-2 migliora inoltre il crosstalk ottico spaziale. In sostanza i filtri del colore (o Color Filter Array, CFA)  sono posizionati ad una distanza non nulla dalla superficie dei fotodiodi a causa del metallo e/o degli strati isolanti. La luce proveniente ad un angolo diverso da quello ortogonale può essere assorbita dai fotodiodi adiacenti. Con la Back-Side Illumination, avendo il fotodiodo sopra agli strati di metallo si riduce questa distanza.

Tecniche di correzione del colore come ad esempio attraverso delle Color Correction Matrix (CCM) mirano a correggere tramite post-elaborazione il problema del crosstalk, che può avere anche origini di altra natura (es. crosstalk elettrico). Alcuni sensori integrano direttamente questa funzionalità, ottenibile altrimenti generalmente tramite ISP (Image Signal Processor) esterno.

Image-Comparison-CCM-White-BalanceA sinistra Color Correction Matrix disabilitata, a Destra abilitata. Fonte https://www.ptgrey.com/truecolor

Dal grafico dell’efficienza quantica visto sopra è possibile notare il crosstalk delle varie tecnologie, di seguito sono riportate alcune formule di esempio per calcolare il valore numerico percentuale tratte dal paper Crosstalk and Sub-Pixel Distribution of Sensitivity in Color CMOS Image Sensor di Photobit, comperata da Micron, acquisita poi da ON Semiconductor.

crosstalk

Tecnologie più recenti come PureCel di Omnivision o IsoCell di Samsung creano ulteriori barriere per minimizzare ulteriormente il crosstalk. E’ sotto illustrato il funzionamento di massima di IsoCell.

isocell

Prima della lettura i pixel vengono precaricati (pre-charging) nel cosiddetto Well (“pozzo” in italiano) la cui capacità è definita come Full-Well Capacity e dopo un certo periodo di tempo vengono campionati (sampling). Tra queste due operazioni la carica elettrica nei pixel decresce con l’esposizione alla luce incidente, questo intervallo di tempo è il cosidetto tempo di esposizione.Tanto minore sarà la carica elettrica letta sul pixel, tanto più luminoso sarà il suo valore. Tempi maggiori di esposizione permetteranno quindi di ottenere immagini più luminose.

NB: Il tempo di esposizione è un valore configurabile nel sensore OV8865 in unità di linee.

Curiosità: Il Range Dinamico (Dynamic Range) del pixel, cioè l’abilità di catturare sia oggetti molto luminosi che molto scuri in una singola immagine è dato dal rapporto tra il massimo segnale ottico che può essere rilevato senza saturare il Well ed il segnale ottico minimo rilevabile, limitato dal rumore.

Da notare come le righe in questa tipologia di sensori vengano precaricate in sequenza, senza aspettare le letture complete delle righe precedenti, per ottenere frame-rate più elevati come mostrato nel seguente schema (tratto dalla tech note Rolling Shutter vs. Global Shutter di qimaging).

rollingvglobalshutter-fig2

NB: Un ottimo testo per chi desiderasse approfondire l’elettronica e la fisica dei sensori CMOS è Image Sensors and Signal Processing for Digital Still Cameras redatto da Junichi Nakamura.

Dopo che il circuito di sample/hold ha campionato una riga di pixel, i dati vengono presentati uno alla volta nell’amplificatore analogico (indicato da AMP nello schema).

Il guadagno dell’amplificatore è personalizzabile ed è la strada per migliorare la luminosità dell’immagine dopo aver aumentato l’esposizione, è identificato anche come sensibilità ISO. Il segnale una volta amplificato viene digitalizzato dall’ADC a 10 bit.

Modificando, tramite appositi registri di controllo, la sequenza di campionamento è possibile capovolgere e/o rovesciare l’immagine (funzionalità di mirror e flip) evitando un post-processing e mantenendo così i consumi energetici molti contenuti. E’ anche possibile campionare solamente una sottofinestra dei pixel attivi (image windowing), funzionalità interessante nel caso in cui non tutta l’immagini serva per la propria applicazione ma solamente una ROI (Region Of Interest). Alcuni sensori, particolarmente orientati al controllo qualità tramite visione artificiale, permettono inoltre di definire più ROI.

Il blocco successivo è l’ image sensor processor che include una piccola memoria OTP e funzionalità di Digital Signal Processor (DSP) come la Defective Pixel Cancellation (DPC), il Manual White Balance (MWB) e la Lens Correction (LENC).

La cancellazione dei pixel difettosi permette di mascherare pixel morti (dead pixel) cioè sempre bianchi o neri, e generalmente anche i pixel feriti (wounded pixel) la cui luminosità non varia come gli altri pixel. Macchine fotografiche point-and-shoot presentano anche decine di pixel difettosi, considerato il numero totale di pixel però non è un problema così grave. Per chi fosse curioso ho caricato un archivio con una foto fatta con il modulo D8M con DPC attivato e DPC non attivato. Attenzione le foto sono PNG non compressi per non perdere le informazioni relative ai pixel difettosi e l’archivio pesa circa 9MB. I pixel difettosi di fabbrica, assieme ad altri elementi, possono inoltre creare una sorta di impronta digitale del sensore.

La memoria One Time Programmable (OTP) permette al produttore e al progettista di memorizzare una serie di informazioni come delle impostazioni di default alternative.

Il Bilanciamento Manuale del Bianco (MWB) permette di impostare un guadagno digitale distinto per i canali Rosso, Verde e Blu (R, G, B). Per una taratura manuale generalmente si inizia impostando al minimo tutti i guadagni, per poi aumentare gradualmente prima il Rosso ed il Blu. Il verde necessita infatti generalmente di un guadagno minore. Mantenendo i valori al minimo necessario si eviterà di amplificare ulteriore rumore.

I valori ideali del bilanciamento del bianco dipendono dall’illuminazione della scena inquadrata, una luce solare necessiterà di valori differenti da una luce al neon. Spesso vengono realizzati un insieme di combinazioni per le condizioni di illuminazione standard (es. soleggiato, nuvoloso, incandescente, fluorescente, etc..) ed il bilanciamento automatico (Auto White Balancing AWB), non fornito con questo sensore, provvede a scegliere la migliore nella più semplice delle ipotesi.

I modelli di macchine fotografiche più avanzate realizzano tecniche complesse per trovare il bilanciamento migliore, grandi passi in avanti sono stati compiuti rispetto ai primi modelli basati ad esempio su modelli di Gray World, dove si assumeva che l’immagine doveva contenere mediamente la stessa quantità di rosso, verde e blu. La tematica del bilanciamento automatico è ad ogni modo ancora oggi fonte di studio e miglioramento.

NB: Il guadagno digitale, se attivato, è applicato dal sensore OV8865 sui dati grezzi in uscita e sarà quindi presente anche salvando direttamente i pixel in uscita dal sensore prima di ulteriori elaborazioni (es. foto RAW).

UPDATE: A titolo di esempio sotto è illustrata una foto di un paesaggio con bilanciamento manuale impostato in modo non proprio soddisfacente, a destra il bilanciamento è disabilitato e la foto tende al verde essendo il colore più sensibile al sensore.

ov8865_mwb_on ov8865_mwb_off
A sinistra foto con OV8865 con MWB attivato, a destra MWB disattivato

Alcuni dettagli come le sfumature delle nuvole e l’orologio del campanile sono però andati persi nel bilanciamento manuale. Eseguendo un bilanciamento automatico partendo dalla foto con MWB disabilitato è possibile correggere a piacere il bilanciamento, senza perdere ulteriori dettagli nella foto.

ov8865_mwb_off_post_proc_awb ov8865_mwb_off_post_proc
Foto precedente con MWB disattivato e corretta in post-processing col software RawTherapee: a sinistra col solo bilanciamento automatico del bianco, a destra con anche altre impostazioni modificate.

NB: Le foto a colori mostrate sono state demosaicizzate linearmente per brevità, presentano quindi difetti di vario tipo. Hanno inoltre una discreta quantità di micro-mosso visto che non è stato utilizzato un cavalletto.

La funzionalità di Lens Correction (LENC) serve per corregere la mancata uniformità di illuminazione dei bordi dell’immagine per difetti della lente, effetto chiamato anche vignettatura o lens shading. Sostanzialmente viene aumentato il guadagno dei pixel meno luminosi.

lenc on lenc off
Foto con D8M (sensore OV8865) con LENC attivata a sinistra e disattivata a destra

NB: Questa funzionalità non corregge altri tipi di difetti introdotti da lenti non perfette, come le distorsioni radiali e tangenziali.

L’ultimo blocco del sensore è l’image output interface dove i pixel in uscita vengono bufferizzati in una memoria FIFO prima del loro invio serializzato tramite interfaccia MIPI.

Le specifiche MIPI CSI-2 sono disponibili solamente ai membri della MIPI Alliance previ abbonamenti che in data di stesura di questo articolo partono da 4000$ annui.

Il sensore permette di configurare il numero di lane (canali) da utilizzare per la trasmissione dei dati così come tutta una serie di parametri per ottimizzare la comunicazione (eventuali skew sui segnali, etc..).

Il sensore dispone inoltre di un paio di PLL (Phase-Locked Loop) per generare i vari clock del sensore partendo da un singolo clock di riferimento (MCLK), nel nostro caso il clock di riferimento sarà generato dal convertitore MIPI TC358748XBG. I clock generati sono il clock dell’interfaccia MIPI, il Pixel Clock (o PCLK), il System Clock (SCLK) ed il DAC Clock. Particolare attenzione va riposta nella impostazione di queste frequenze, in quanto influenzano direttamente il frame-rate e la banda MIPI richiesta.

Il frame-rate è dato dalla formula:

FPS = SCLK / (HTS * VTS)

dove HTS è la Horizontal Total Size e VTS è la Vertical Total Size, ovvero il totale dei pixel orizzontali e verticali contando anche la regione di blanking. La regione di blanking (o dummy lines) è particolarmente importante e può essere impostata in modo tale da limitare il frame-rate per ovviare a problemi di banda MIPI. Il convertitore MIPI TC358748XBG ha infatti un buffer di linea interno limitato e picchi di banda prolungati potrebbero manifestare problemi in condizioni particolari.

Il tempo di esposizione è inoltre determinato sommando al valore del registro dell’esposizione il valore HTS mentre il valore VTS ne determina il valore massimo.

NB: Il Clock del DAC è probabilmente dovuto ad un ADC con architettura a pipeline o che comunque richieda un DAC.

Dopo aver fatto una carellata delle funzioni disponibili, all’atto pratico possiamo configurare il sensore tramite l’interfaccia SCCB (Serial Camera Control Bus), un analogo del bus I2C. I registri di controllo purtroppo non sono in genere ben documentati ed il datasheet per quel poco che dice prevede una conoscenza teorica profonda del sensore, che spero di aver reso un poco tramite questo articolo.

Questa mancanza di documentazione probabilmente è in parte voluta sia per non diffondere troppi dettagli ai concorrenti sia in quanto un sensore d’immagine ben configurato può dare ad un dispositivo tecnologico un valore superiore tramite immagini visivamente accattivanti ed i produttori dei sensori sembra che vogliano in qualche modo lavorare direttamente insieme ai produttori dei dispositivi finali.

domenica 7 maggio 2017

FPGA: Computer Vision con D8M-GPIO (prima parte)

Un campo promettente per le FPGA è sicuramente l’elaborazione di flussi video in tempo reale (anche detta elaborazione di immagini). Sebbene le schede grafiche diventino sempre più potenti sotto molti punti di vista, pensiamo a settori come l’automotive dove tematiche come la guida automatica o sistemi Advanced Driver Assistance Systems (ADAS) sono sempre di maggiore attualità. I requisiti sono bassi consumi energetici, elaborazione in tempo reale e riprogrammabilità; in scenari come questo l’utilizzo delle logiche programmabili comporta, sopratutto riguardo ai consumi, grandi vantaggi.

Il primo passo di qualsiasi sistema di visione è l’acquisizione dell’immagine da elaborare, vediamo come è possibile compiere questo passo con la scheda FPGA DE0-Nano ed il modulo Digital Camera D8M-GPIO di Terasic, evoluzione per certi versi del modulo D5M. Nell’immagine seguente è mostrato a sinistra il modulo collegato alla scheda ed a destra la vista frontale del modulo.

de0-nano d8m              de0-nano d8m

Abbiamo già parlato della DE0-Nano in diverse occasioni, vediamo adesso cosa ci offre il D8M.

Architettura

d8m architectureSostanzialmente ci fornisce un sensore CMOS OV8865 da 8 Megapixel prodotto da Omnivision assieme ad una lente con focus regolabile e tutta la circuiteria necessaria per dialogare facilmente con questi elementi.

Facendo un rapido calcolo, la quantità di dati generata da un sensore d’immagine a 30 fps e piena risoluzione (8 MP) è di: 3264 x 2448 pixel x 30 fps x 10 bit / pixel = 2.397.081.600 bit/s = 2,23 Gbps a cui si aggiungono in realtà altri dati per la sincronizzazione (overhead LVDS, segnali HSYNC, VSYNC, etc...). E’ facilmente intuibile come problematiche di integrità dei segnali non siano da porre in secondo piano.

Il sensore CMOS vista la grande quantità di dati che genera, comunica tramite 4 linee con standard elettrico LVDS (Low-voltage differential signaling) ad alta velocità, ogni linea infatti può trasferire fino a 1.2 Gbps. Il sensore supporta inoltre lo standard MIPI CSI-2 che indica come interpretare in dati i segnali elettrici.

Per semplificare il collegamento con la FPGA il modulo converte i segnali LVDS in segnali paralleli tramite un integrato TC358748XBG di Toshiba, visibile al centro della scheda. Il convertitore supporta un uscita parallela con frequenza fino a 100 MHz e una certa flessibilità, necessita però dell’appropriata programmazione.

NB: L’integrato convertitore supporta fino a 1 Gbps per linea e ha alcune limitazioni legate alla quantità di memoria FIFO interna al chip, non sarà quindi possibile raggiungere 8 MP a 30 fps ma più verosimilmente circa 2/4 fps. A risoluzioni minori sarà comunque possibile raggiungere frame-rate più elevati.

E’ di lato mostrata l’architettura del modulo D8M dove è anche possibile osservare che sia il convertitore sia il sensore CMOS dispongono di un’interfaccia di controllo I2C.

Sistema di messa a fuoco

Non è evidenziato nello schema precedente ma l’interfaccia I2C è utilizzata anche per controllare tramite l’integrato VM149C un piccolo motore VCM (Voice Coil Motor) che serve a regolare la messa a fuoco spostando la posizione della lente e quindi la distanza di quest’ultima dal sensore.

Curiosità: Il nome Voice Coil Motor proviene dalle sue prime applicazioni, la vibrazione del cono di carta degli altoparlanti.

Questo tipo di motore è molto semplice e la lo spostamento generato è proporzionale al flusso di corrente che attraversa la bobina del motore, per questo l’integrato è un driver a corrente costante. L’accuratezza nel posizionamento di questo tipo di motori può essere molto elevata, anche inferiore al micron. E’ di seguito riportato lo schema di funzionamento del VM149C:

VCM architecture

Analizzando “in linea” le immagini ottenute è possibile creare un sistema di messa a fuoco automatica, nei reference design di Terasic è possibile trovare un esempio di semplice autofocus scritto in Verilog, anche se purtroppo non è documentato molto bene.

Sistema ottico

Per quanto riguarda la lente, elemento spesso sottovalutato ma molto importante in un sistema di acquisizione immagini, le caratteristiche principali riportate sono:

Lens Type 1/4 inch   1/3.2 inch
Effective Focal Lenght (EFL) 3.37 mm
F-number 2.8
Distorsion < 1%
Lens Module Dimensions 8.5 x 8.5 x 5.4 mm

Essendo il sensore CMOS da 1/3.2 di pollice la lente risulta il collo di bottiglia del sistema per ottenere immagini di qualità superiore, è comunque una qualità accettabile in svariate applicazioni.

UPDATE: Dopo aver segnalato il problema al produttore è stato corretto il datasheet cambiando il tipo di lente da 1/4 di pollice a 1/3.2 pollici. Kailaptech ha motivato il cambiamento di specifiche come errore di battitura.

Dato che: F-number = Focal Lenght / Aperture Diameter abbiamo 2.8 = 3.37 / Aperture Diameter da cui ricaviamo un diametro di apertura di 1.2 mm che corrisponde effettivamente alla dimensione dell’apertura fisica della lente.

La profondità di campo (Depth of View) risulta limitata essendo proporzionale all’F-number, le immagini saranno però più luminose rispetto ad F-number maggiori in quanto la quantità di luce entrante sarà maggiore.

aperture dof lens

La lunghezza focale (Focal Lenght) molto ridotta permette un angolo di campo (o Angle of View) molto elevato, la lente abbinata al sensore OV8865 permette una visuale di circa 70° da datasheet. Il perché è facilmente intuibile dal seguente schema:

focal lenght lens

La lente ed il sensore sono in realtà a loro volta un modulo con identificativo JAL-OV8865-A898B con tanto di connettore, è quindi possibile sostituire questo modulo in caso di necessità, fermo restando che il nuovo modulo dovrà essere per forza di cosa pin-to-pin compatibile.

Sensore CMOS

Il sensore OV8865 è, come tutti i sensori d’immagine moderni, un oggetto relativamente complesso, vediamo alcune delle caratteristiche principali:

Active array size 3264 x 2448
Lens Size 1/3.2 inch
Pixel Size 1.4 um x 1.4 um
Output format 10-bit RAW (BG/GR Bayer pattern)
Sensitivity 940 mV/Lux-sec
Dynamic Range 68.8 dB
Scan mode Progressive (Electronic Rolling Shutter)

La risoluzione è un parametro abbastanza intuitivo, è il numero di pixel attivi che possiamo ottenere, in questo caso 8 MegaPixel. In realtà il sensore presenta anche dei pixel otticamente isolati che leggeranno quindi sempre il valore corrispondente al valore nero. Questo in poche parole serve per determinare l’eventuale rumore a cui sono soggetti i pixel e rimuoverlo dai pixel attivi.

La dimensione del sensore, in questo caso 1/3.2 pollici, influenza direttamente la dimensione e quindi la capacità di raccogliere la luce dei pixel. Non è chiaramente comparabile con sensori full-frame di macchine reflex ma è comunque già una dimensione utilizzata su sensori di smartphone di fascia alta.

Il sensore utilizza il pattern di Bayer, ovvero davanti ad ogni pixel è presente un filtro ottico per far passare solamente la luce di un determinato colore secondo uno schema che alterna linee con sequenze di Blu/Verde a righe con sequenze Verde/Rosso.

d8m bayer

L’immagine originale prima della demosaicizzazione è quindi un’immagine dove la posizione di ogni pixel e la luminosità ne determinano il colore. Essendo i pixel verdi doppi rispetto ai pixel rossi e blu le immagini RAW risultano di tonalità molto verde. Ogni pixel è rappresentato da 10 bit corrispondenti alla luminosità, il colore nell’immagine finale viene stimato grazie ad un algoritmo di demosaicizzazione che può consistere in una semplice interpolazione lineare per applicazioni a basse prestazioni oppure in algoritmi molto sofisticati per risultati migliori.

raw image false color raw image demosaicized

Esempio di immagine RAW in falsi colori

Stessa immagine RAW demosaicizzata linearmente

Nel caso in cui il colore non sia richiesto è possibile ottenere una maggiore sensitività utilizzando sensori in bianco e nero senza quindi il filtro di bayer che introduce, seppur minimamente, una perdita di luminosità. In alternativa è spesso necessario scegliere un sensore di dimensioni maggiori se non è possibile modificare l’illuminazione o il sistema ottico.

Continuando nell’analisi delle caratteristiche è possibile notare una gamma dinamica di 68.8 dB, simile ai sensori degli smartphone di qualche anno fa e non comparabile coi sensori più avanzati HDR (High Dynamic Range) attuali che possono raggiungere 90 dB. Ad ogni modo è capace di cogliere buone immagini in condizioni di illuminazione adeguata.

La scansione dell’immagine avviene riga per riga, l’immagine non è quindi letta tutta contemporaneamente e in caso di movimenti molto veloci può sussistere un artefatto del movimento. Questa modalità è chiamata Electronic Rolling Shutter, è elettronica in quanto non è presente un otturatore meccanico e si differenzia dal Global Shutter per la sua lettura progressiva.

Vedremo più avanti altre caratteristiche e funzionalità offerte da questo sensore, così come interfacciarlo nella pratica alla FPGA.

Per concludere questa panoramica vi lascio un immagine del software disponibile sul mio GitHub (‘ultima versione del software potrebbe variare rispetto alla schermata mostrata) per gestire il modulo D8M collegato alla DE0-Nano dal PC tramite JTAG. Il programma, assieme al design FPGA, sarà disponibile anche per altre schede di sviluppo come la BeMicro CV A9 e la DE1-SoC e permetterà di provare numerose impostazioni del sensore in modo semplice e veloce senza richiedere il collegamento ad uno schermo esterno VGA o HDMI, interfacce non disponibili tra l’altro su tutte le schede di sviluppo.

fpga d8m image software

Alla prossima.

UPDATE: Ecco alcune foto di una Dahlia a risoluzione 1600x900 (1.4 MP) scattate con la D8M ed il progetto di cui parleremo prossimamente nel blog, la curva del blu è stata leggermente corretta con Gimp per rendere maggiormente acceso il giallo ed una foto è stata leggermente ritagliata. Facendo click sulle foto è possibile vederle a piena risoluzione.

fpga d8m dahlia image 

fpga d8m dahlia image

UPDATE: Ecco un ulteriore foto, anche se forse non perfettamente a fuoco. Un dettaglio del bottom della scheda DE1-SoC in prossimità dell’integrato FPGA, dove sono ben visibili i vias ed i condensatori di disaccoppiamento. La foto è stata scattata ad 8 MegaPixel con la D8M, è possibile notare una distorsione barrel dovuta all’ottica, che è comunque possibile correggere a posteriori dopo una dovuta calibrazione.

camera_063114

sabato 20 agosto 2016

FPGA: Comunicazione tramite JTAG UART con C#

Le schede di sviluppo come la DE1-SOC così come le più compatte DE0-Nano o BEMICRO-CV-A9 non dispongono di un’interfaccia di comunicazione semplice ed interoperabile verso un computer per i propri progetti.

La soluzione più diffusa è l’aggiunta di un modulo USB-Seriale esterno, il che comporta però degli svantaggi quali: costi aggiuntivi, ulteriori dimensioni del sistema finale e utilizzo dei pin di I/O, non sempre disponibili agevolmente su schede di fascia elevata.

usb-uart-moduleEsempio di modulo USB-Seriale a basso costo

Nel caso in cui i propri design non utilizzino bus AXI o Avalon è però senza ombra di dubbio la scelta più semplice per il collegamento a dispositivi host USB come computer (classici o raspberry, etc..).

E’ però già disponibile nella quasi totalità delle schede di sviluppo, una porta USB per la programmazione, collegata ad un circuito USB-Blaster o equivalente di cui il componente principale è generalmente una CPLD collegata tramite interfaccia JTAG alla FPGA.

L’utilizzo della porta nei propri design su FPGA necessità però di IP dedicati come l’Altera Virtual JTAG di non semplice utilizzo e di programmi server lato computer come quartus_stp.exe. Per chi fosse interessato ad ogni modo ad intraprendere questa strada (su dispositivi Altera) ecco un buon tutorial.

E’ possibile utilizzare IP come l’Altera Avalon Jtag Uart per nascondere la complessità del protocollo sottostante. Se utilizzato assieme a soft-core come NIOS II è possibile nascondere anche i dettagli di comunicazione grazie ai driver inclusi nell’IP e disporre di un interfaccia stream standard STDIN, STDOUT per una programmazione molto semplice lato firmware.

Lato computer però la situazione è ancora abbastanza complicata in quanto è necessario utilizzare il programma nios2-terminal in modalità standalone o tramite la versione di Eclipse dedicata inclusa negli strumenti di sviluppo di Altera, il che però presuppone l’installazione di tutto il pacchetto EDA di svariati GB.

nios-ii-terminal
Programma nios2-terminal

eclipse-terminal
Finestra Nios II Console all’interno di Eclipse personalizzato per NIOS II

Lato computer è invece spesso necessaria un interfaccia API utilizzabile tramite qualsiasi linguaggio di programmazione, per poter automatizzare nel modo più comodo la comunicazione.

Altera non rende disponibile una documentazione ufficiale, ma tramite la libreria jtag_atlantic fornita con Quartus, la stessa utilizzata internamente da nios2-terminal, è possibile gestire la comunicazione. La libreria jtag_atlantic utilizza a sua volta la libreria jtag_client, che sarà quindi necessario avere anch’essa (sempre inclusa con Quartus).

Il progetto non ufficiale https://github.com/thotypous/alterajtaguart offre gli header della API e degli esempi per poter utilizzare jtag_atlantic tramite C/C++.

Per i linguaggi .NET come il C#, molto utili per la prototipazione rapida di software, non esiste purtroppo una libreria pronta all’utilizzo. Per ovviare al problema ho quindi scritto una libreria che risolvesse il problema. Oltre ad offrire gli header C# delle API eleva il livello di programmazione offrendo una classe di semplice utilizzo che incapsula al contempo tutte le funzionalità.

Vediamone rapidamente la struttura. La classe principale con cui interfacciarsi è chiamata JtagUart, il cui diagramma è sotto mostrato:

ClassDiagram1

Dispone di metodi intuitivi come Open, Read, Write e Close per gestire la comunicazione ed implementa il pattern Dispose per chiudere automaticamente la connessione dopo l’utilizzo. La classe presenta inoltre alcuni metodi per semplificare la lettura di stringhe, per leggere e scrivere singoli byte e per recuperare informazioni sulla connessione. E’ ben documentata nel possibile, visto che comunque la libreria jtag_atlantic non è ufficialmente documentata.

NB: Nel caso la propria applicazione richieda la lettura di una gran quantità di dati è consigliabile chiamare GetAvailableBytes per verificare se sono effettivamente disponibili ed evitare chiamate multiple alla funzione Read. Tramite la scheda di sviluppo DE1-SOC è possibile raggiungere una velocità di circa 850 KBytes/secondo durante la trasmissione al PC di informazioni.

Assieme alla classe è fornito un esempio di di classico ECHO che richiede lato firmware NIOS un programma di echo come il seguente:

nios-ii-firmware

Per progetti in cui è richiesto lo scambio di valori int32, double, etc.. tra PC e NIOS II è possibile estendere senza grossi problemi con funzioni ReadInt32, ReadDouble, WriteInt32, WriteDouble, etc.. la classe.

Con la libreria, abbinata ad un interfaccia utente, è possibile ottenere sicuramente dei risultati accattivanti. Buona comunicazione... tramite JTAG. Scarica il progetto

domenica 5 giugno 2016

Cyclone V SoC: Configuriamo ARM DS-5

Precedentemente avevamo visto come collegare la scheda DE1-SoC al computer tramite cavo ethernet, vediamo adesso come configurare al meglio il software DS-5 per essere maggiormente produttivi nella scrittura del software.

In particolare all’interno dello stesso programma riusciremo ad avere sotto controllo il filesystem, i processi ed un terminale per interagire col nostro sistema ed il debug remoto dei nostri programmi.

Come prima operazione cambiamo la password al nostro sistema Linux tramite il comando passwd,questo ci permetterà di collegarci tramite SSH in quanto una password, per quanto semplice sia, è mandatoria.

passwd

Apriamo adesso Eclipse for DS-5 e scegliamo il menù Window / Open Perspective / Other come mostrato nella figura seguente:

ds5_menu_perspective

Scegliamo Remote System Explorer e confermiamo con OK

open_perspective

Apparirà un nuovo pannello, facciamo click col tasto destro del mouse su Local e scegliamo New / Connection

new_connection

Alla richiesta del tipo di sistema remoto scegliamo Linux e facciamo click su Next. Specifichiamo adesso i dati di connessione della scheda e premiamo nuovamente Next.

new_connection_first_step

Selezioniamo ssh.files tra le configurazioni disponibili per utilizzare il protocollo Sftp per accedere al filesystem e premiamo Finish.

new_connection_files

Espandendo la voce DE1SOC e navigando tra i menù avremo adesso la possibilità di copiare file tramite drag-and-drop, visionare e terminare processi ed interagire col sistema tramite terminale.

ds5

NB: Verrà chiesta la password prima di accedere alle risorse del sistema remoto e la prima volta un messaggio di Warning ci informerà che l’autenticità dell’host non può essere stabilita, premete semplicemente Yes in quanto con una connessione diretta tramite ethernet non ci sono particolari problematiche di sicurezza.

rsa_fingerprint

Creiamo adesso un nuovo progetto scegliendo File / New / C Project. Scegliamo GCC come Toolchain, utilizzeremo gli strumenti gratuiti inclusi nella versione ARM DS-5 Community Edition.

w2

Il progetto creato sarà inizialmente vuoto, aggiungiamo un file sorgente scegliendo New / Source File ricordandoci di aggiungere l’estensione .C al nome del file.

w3

Creiamo un semplice Hello Arm con il seguente codice e compiliamo tramite Project / Build All:

hello

Selezioniamo Debug Configurations premendo il triangolino vicino al pulsante Debug, come illustrato nell’immagine seguente:

w5

A questo punto scegliamo come target Linux Application Debug / Application Debug / Connections via gdbserver / Download and debug application visto che andremo a fare il debug di un applicazione Linux. La versione più completa di DS-5 mostrerà in questa schermata anche altre opzioni di cui però non ci occuperemo.

w6

Spostandoci nella scheda adiacente Files scegliamo come Application on host to download tramite il pulsante Workspace l’eseguibile creato in precedenza.

w7

Nei campi Target download directory e Target working directory impostiamo il percorso /home/root

Confermiamo con Apply e chiudiamo la finestra di dialogo. Siamo adesso pronti ad effettuare un debug remoto con strumenti quali breakpoint, esecuzione passo passo e la visualizzazione di dati relativi a variabili e thread. Premiamo semplicemente il pulsante Debug per iniziare.

w8

Una volta terminata la sessione di Debug esplorando i file presenti nel sistema remoto noteremo la presenza dell’eseguibile, che sarà richiamabile anche in modo tradizionale tramite terminale.

fs

Nonostante questo articolo sia meno tecnico del solito, avere a disposizione la corretta procedura può accelerare la messa a punto della propria postazione di sviluppo. Alla prossima.

martedì 24 novembre 2015

FPGA: Numeri a virgola fissa (seconda parte)

Dopo aver introdotto i numeri fixed point vediamo un semplice blocco in VHDL che calcola la circonferenza di un cerchio dato il raggio.


Possiamo vedere come sia stata definita una costante two_pi che intuitivamente conterrà il valore 2 * pi greco.

La costante è valorizzata tramite la funzione to_ufixed che provvederà a convertire un numero REAL (ma funziona anche con INTEGER, SIGNED e UNSIGNED)  nel tipo per l'appunto UFIXED senza dover convertire "a mano" il numero nella stringa di bit "00110010", approssimazione di 6.28 data la rappresentazione del numero con soli 3 bit per la parte decimale.

Il valore effettivo ottenuto sarà però 6.25, c'è quindi da porre particolare attenzione alla precisione con la quale si eseguono questo tipo di calcoli, il codice VHDL può infatti facilmente trarre in inganno.

Il raggio è costituito da un numero fixed point ad 8 bit mentre il risultato, per evitare overflow, è un numero di 16 bit, dato che è il prodotto di una moltiplicazione.

Per evitare errori in fase di compilazione bisogna tassativamente seguire le regole di dimensionamento, concepite per evitare problemi involontari di overflow, sotto riportate:



Nel nostro caso ci serviamo della riga A * B della tabella. A'left assume il valore INTEG_BIT-1, dato dal bound sinistro scelto nel tipo ufixed del segnale radius, mentre analogamente B'left vale INTEG_BIT-1, dato dalla costante two_pi.

A'right ed B'right avranno entrambi il valore -DECIM_BIT.

Il risultato dovrà avere, seguendo la tabella, un range pari a 2*(INTEG_BIT-1)+1 downto -2*DECIM_BIT, ovvero 9 downto -6 quindi un numero di 16 bit come già detto.

Il VHDL 2008 coi fixed point ci offre una funzione di ridimensionamento con saturazione (per problematiche di overflow) ed arrotondamento (per problematiche di underflow) chiamata resize per eventualmente adattare il risultato ad un numero con diversa risoluzione, vediamone un esempio:


Dove abbiamo come argomenti di resize il numero da ridimensionare, il bound sinistro ed il bound destro del risultato. In tal modo l'uscita circumference avrà la stessa dimensione di 8 bit dell'ingresso.

Sono disponibili diversi overload della funziona resize e rimando alla Fixed point package user’s guide per una descrizione esaustiva di tutte le funzioni.

Nella funzione resize di default sono abilitati l'arrotondamento e la saturazione, seppur è possibile scegliere di troncare e avvolgere (wrap) il valore per ottenere circuiti di velocità maggiore ed area minore.

Sotto è riportata la vista RTL del circuito generato con arrotondamento e saturazione abilitati

L'implementazione su Cyclone V è di 11 ALM ed 1 blocco DSP. Sotto è riportata una simulazione del blocco sopra descritto:



















E' possibile notare come l'uscita saturi a 31.875 (tutti i bit pari ad 1) in caso di valori d'ingresso eccessivi per la risoluzione utilizzata.

Disabilitando arrotondamento e saturazione, il circuito ottenuto sarà come è facile aspettarsi costituito dal solo moltiplicatore, implementato con un singolo DSP. Purtroppo spesso il risultato così ottenuto è poco utilizzabile.



Per modificare lo stile di arrotondamento e di overflow in tutte le operazioni è possibile modificare le costanti fixed_round_style e fixed_overflow_style nel file fixed_pkg_c.vhdl






Per gestire l'underflow, che può verificarsi quando la parte decimale non ha abbastanza risoluzione per rappresentare il risultato, si può utilizzare una modalità fixed_round in cui la parte decimale viene arrotondata al più vicino valore rappresentabile oppure una modalità fixed_truncate dove sono semplicemente persi i bit meno significativi.

L'underflow può verificarsi nella divisione, dove l'errore può accumularsi a causa della natura iterativa degli algoritmi. Per ridurre l'errore vengono inseriti automaticamente dei bit di guardia (guard bit) che aumentano temporaneamente la risoluzione della parte decimale nei calcoli intermedi. Di default il VHDL 2008 utilizza 3 bit di guardia per operazioni come la divisione.

Per gestire l'overflow è possibile utilizzar la modalità fixed_saturate oppure la modalità fixed_wrap che è spesso il "normale" comportamento dei calcolatori e non comporta l'utilizzo di hardware aggiuntivo, incrementando il numero più grande rappresentabile si otterrà il numero più piccolo.

Per singole operazioni è possibile utilizzare gli overload delle funzioni come per esempio









Non mi rimane che augurarvi buona aritmetica.. coi fixed point!


NB: Per rendere compatibile il codice mostrato con ModelSim e compilabile da Quartus 15 è stato modificato il nome della libreria ieee_proposed in ieee, modificando il file fixed_pkg_c.vhdl di cui si è parlato nel precedente articolo. In tale modo ModelSim non lamenterà la mancanza della libreria ieee_proposed, seppur sia possibile crearla. Compilando il codice con un sintetizzatore con supporto per i fixed point del VHDL 2008 non sarà così necessaria alcuna modifica.