Durchblicker

Wechseln zu: Navigation, Suche

von Benutzer:Fpgakuechle (Volker Urban)

Dieser Artikel beschreibt einen auf einen FPGA-Board realisierten Logic-analyzer. Im Unterschied zu ähnlichen Projekten wird kein PC zur Steuerung/Datendarstellung benötigt, die Zeitverläufe werden über ein an das Board angeschlossenen VGA-Monitor direkt ausgegeben.

Das Projekt ist noch in der Entwicklung, erste Ergebnisse können bereits gezeigt werden:

Alle Display-Elemente implementiert


Systembeschreibung

Konzept

Sechszehn Signale werden permanent in dem FPGA-internen Speicher (xilinx 1 BRAM a 8kbit) aufgezeichnet. Für die Aufzeichnung langsame veränderliche Signale wie RS232/PS2-IF wird über einen Teiler ein sample-write enable erzeugt. Nach Auftritt eines Triggerevents endet das zyklische beschreiben nach 50% der Speicherkapazität. Damit sind die Signalwerte vor und während des Triggervents gesichert. Die Daten aus dem Samplespeicher werden im FPGA zu einem Waveformdiagramm aufbereitet und auf einem an das Board angeschlossenen VGA-Monitor dargestellt. Zur Auswertung sind zwei Vertikal-Cursor implementiert, der Bitvector "unter" dem Cursor und der Abstand zwischen den Cursor wird als hexadezimalzahl ausgegeben.

Das Triggerevent (Quelle: einer aus den 16 Kanälen oder externer Trigger, Flanke) und Modus (single, autotrigger, continous, force) ist frei wählbar. So erhält der Entwickler einen on-chip Logicanalyzer ähnlich Chipscope (Xilinx), Signaltap (Altera) oder CLAM (Actel) ohne das Lizenzengebühren anfallen oder ein spezieller JTAG-programmer nötig ist.

Erweiterungsoptionen

  • Skalierung der Anzahl der aufgezeichneten Signale durch mehrfache Instanziierung des sig_record Modul und Einfügen eines multiplexers zum display Modul
  • komplexe Triggerfunktionen durch Beschaltung des Eingangs externer Trigger

Bedienkonzept

Sampledarstellung

In jeder Spalte wird ein sample dargestellt, damit können 512 Samples auf 512 Spalten eines 800x600 dargestellt werden und der u.U. schwer lesbare Seitenrand wird ausgespart. Um den Wert einzelner sample bei dieser dichten Anordnung noch zu unterscheiden zu können wird der samplewert wie folgt dargestellt

Sample Darstellung
t-1 t Beschreibung Darstellung Signal Darstellung Cursor
'0' '0' konstant low einzelnes Pixel unterer Rand volle Länge mit Farbpixel unten
'0' '1' auf High steigend mehrere Pixel in unterer Hälfte Halblang obere Hälfte, unten Farbpixel
'1' '0' auf Low fallend mehrere Pixel in oberer Hälfte Halblang untere Hälfte, oben Farbpixel
'1' '1' konstant high einzelnes Pixel oberer Rand volle Länge mit Farbpixel unten

wobei t das Sample zu gegenwärtigen Zeitpunkt ist, t-1 das am vorhergehenden Samplezeitpunkt davor.

Detail Sample '0' -> '0','0' -> '1','1' -> '0','1' -> '1'


In mittleren Statuszeile wird der Signalwert als vierstellige Hexadecimal-Zahl angezeigt.

Bildschirmeinteilung

der Bildschirm ist in 18 horizontale Sektionen (Streifen) geteilt:

Sample Darstellung
Nummer section (von oben) Was Darstellung
1-8 signal(0) bis signal(7) Waveform + x-Raster
9 Werte unter Cursor 1 und 2 2xHex a 16 bit
10-17 signal(8) bis signal(15) Waveform + x-Raster
18 Position Cursor 1 und 2 2xHex a 12 bit

In der 800x600 Auflösung besteht jede Sektion aus 32 pixel, so dass real 18,75 Sektionenen angezeigt würden, die 0,75 werden der unteren Sektion (Cursor-Position) zugeschlagen. Für die 16 Signale sind 4 Farben möglich. Die Vertikala Aufteilung ist in der Datei display_pkg.vhd in der konstanten CONSTANT C_SECTION_POS definiert.

  CONSTANT C_SECTION_POS : T_POS_SECTION :=
    (CHANNEL, CHANNEL, CHANNEL, CHANNEL,
     CHANNEL, CHANNEL, CHANNEL, CHANNEL,
     STATUS_VALUE,
     CHANNEL, CHANNEL, CHANNEL, CHANNEL,
     CHANNEL, CHANNEL, CHANNEL, CHANNEL,
     STATUS_CPOS);

Für einen Channel-Streifen ist die Anordnung im selben package in der Konstanten C_LINE_POS hinterlegt:

 CONSTANT C_LINE_POS: T_LINE_SECTION :=(
     EMPTY,        CH_HI,        CH_HI,        CH_TRANS_FAL, CH_TRANS_FAL, CH_TRANS_FAL, CH_TRANS_FAL, CH_TRANS_FAL,
     CH_TRANS_FAL, CH_TRANS_FAL, CH_TRANS_FAL, CH_TRANS_FAL, CH_TRANS_FAL, CH_TRANS_RIS, CH_TRANS_RIS, CH_TRANS_RIS,
     CH_TRANS_RIS, CH_TRANS_RIS, CH_TRANS_RIS, CH_TRANS_RIS, CH_TRANS_RIS, CH_TRANS_RIS, CH_TRANS_RIS, CH_TRANS_RIS,
     CH_LO,        EMPTY,        EMPTY,        GRID_COARSE,  GRID_COARSE,  GRID_FINE,    EMPTY,        EMPTY);

Die beiden Elemente CH_HI hintereinander bewirken das High-Wertt durch einen doppelt breite Linie dargestellt wird. Bei GRID_COARSE (Grob-Skala) wird eine Zeitmarke aller 10 pixel gesetzt, für GRID_FINE (Fein-Skala) wird für jedes zweite Pixel ein Punkt gesetzt.

Zeichendarstellung

Die Position der Cursor und der Wert aller Signale wird als Hexadezimalzahl dargestellt. Für die Werte 10 -15 werden die Kleinbuchstaben a-f verwendet um Verwechslungen mit den Zahlzeichen auszuschließen. Die Cursorposition wird nicht als Dezimalzahl dargestellt um die Logikressourcen für die Umwandlung zur BCD-Darstellung einzusparen.

Liniencursor

Bei der dichten Darstellung von mehreren hundert Signalwechsel auf 16 Kanälen sind Liniencursor unverzichtbar. Zwei vertikale Punktlinien werden als solche Hilfslinien eingeblendet, eine davon ist als "aktiv" auswählbar. Der aktive Liniencursor kann schrittweise nach rechts und links verschoben werden, die Schrittweite ist dabei aus 1, 10 oder 100 Pixel wählbar. Überschreitet der Cursor einen Seitenrand wird er auf dem gegenüberliegende Seite positioniert.

Detail Cursor

Zwei vertikale Liniencursor sind definiert, die als Strichlinie dargestellt werden. Einer der beiden ist aktiv, d.h. er kann seitlich verschoben werden. Der aktive Cursor wird in einer Punkt-leer-Punkt Linie dargestellt, der inactive in einer Punkt-leer-leer-leer-Punkt Linie. Die Cursorlinie wird von der Signallinie überdeckt.

Die Position der Cursor und das Delta wird als Hexadezimal in der unteren Statuszeile angezeigt, die Statuszeilen in der Mitte zeigt den Signalwert aller 16 Kanäle an der Cursorposition als Hex-Zahl.

Als weitere Bedienelemente stehen ein Taster zum Auslösen eines Triggers (ForceTrigger) zur Verfügung und Schalter zur Auswahl des Triggermodus (RUN;auto|normal).


Bedienelemente

Das Modul button_map setzt Schalterstellungen o.ä. für den Logicanalyzer um. Da jedes Board unterschiedliche Bedienelemte aufweis, findet sich dieses Modul im /board_specific Zweig der Quellen. Daneben ist auch die Nutzung einer PC-Tastatur als Steuerkonsole denkbar, viele FPGA-boards bieten dafür USB oder PS/2 Buchsen.


Nexsys3

Das Board ist so ausgerichtet das die Kante mit den Schaltern und Knöpfen dem Bediener zugewandt ist: Geklammerte Funktionen sind noch nicht implementiert


Belegung des Knopfkreuzes
Triggering Channel ++
CursLi force Trigger CursRe
Triggering Channel --


Belegung der Schalter
S7 S6 S5 S4 S3 S2 S1 S0
STOP SINGLE Auto-trigger Step = 100 Step = 1 Cursor1 aktiv
RUN CONTINOUS normal Step = F(S1) Step = 10 Cursor2 aktiv

Xilinx Starterkit Spartan3

t.b.d Die Belegung der Schalter kann von Nexsys3 übernommen werden. Buttons bietet diese Board nur 4 die in einer Reihe angeordnet sind. Die beiden rechts könnten die Cursorsteuerung übernehmen,

PC-Tastatur

Da eine PC-Tastatur bekanntlich nur Knöpfe aber keine Schalter bietet, muss eine "eingerastete Stellung" explizit signalisiert werden. Beispielsweise durch eine Statusanzeige auf dem VGA-Monitor, oder über leuchtende/nicht leuchtende LED's die den "Schaltern" zugeordnet sind.

Modulbeschreibung

Durchblicker Top

  • durchblicker.vhd [1]
  • durchblicker_pkg.vhd [2]
  • sk_wrapper.vhd [3] Wrapper für Nexsys3 kit mit Testpatterngenerator (Binärzählrt, PRN-Generator)
Interface Top-module
Name Type Minimalbeschaltung Beschreibung
Takte
vga_clock std_logic 40 MHz clock Takt für VGA-Interface (800x600)
sig_clock std_logic clock der Testsignale Takt der Testsignale
Testport
sig_port_i std_logic_vector(15 downto 0) Testsignale 16 Testsignale
pow2_div_i std_logic_vector(3 downto 0) "0000" Teiler 1:2**x (für langsame Signale
Anzeige (VGA-Interafce & Cursor)
hsync_o std_logic VGA-Port Horizontaler Sync f. VGA-Display
vsync_o std_logic VGA-Port Vertikaler Sync f. VGA-Display
pixel_o std_logic_vector(7 downto 0) VGA-Port 8-bit Farbe f. VGA-Display
posx_curs0_i std_logic_vector(10 downto 0) x"010" X-Position Cursor 0
posx_curs1_i std_logic_vector(10 downto 0) x"100" X-Position Cursor 1
cursor0_active_i std_logic '0' Auswahl Aktiver (beweglicher) Cursor
Triggercontrol
trigger_ext_i std_logic '0' externer Trigger
sel_channel4trigger_i std_logic_vector(4 downto 0) "00000" Auswahl trigger aus 16 testsignale oder ext. trigger
force_trigger_i std_logic '0' Zwang-Trigger (Taste)
auto_trigger_i std_logic '1' selbst generierte Trigger (Tot-zeit)
edge_rising_i std_logic '1' Trigger event bei steiegnder Flanke
run_i std_logic '1' auf trigger wartend
single_trigger_i std_logic '0' nach nächsten Trigger inaktiv

Anzeige

Source Files:

  • display_pgk.vhd [4]
  • display.vhd [5]
  • charrom.vhd [6]

Trigger Generierung

Source Files:

  • trigger.vhd [7]
  • trigger_pkg.vhd [8]

Sample-Speicher

Source Files:

  • sig_record.vhd [9]
  • sig_record_pkg.vhd [10]

Das Modul sig_record ist der Signalrekorder des Logikanalyzers. In diesem Modul wird ein FPGA-interner Speicherblock als DualPort RAM instanziiert und die Schreib- sowie Leseradresse generiert. Geschrieben werden die Signale der Messleitungen als 16bit Wort, der Leseport wird vom Anzeigemodul angesteuert. Auf der Leseseite wird immer nur ein Signal ausgelesen. Die beiden Datenports sind somit unterschiedlich breit, auf der Schreibseite 16 bit auf der Leseseite 1 bit. Da der Speicher ständig ausgelesen wird, wird das zyklische Schreiben der Pretriggersamples als "Störung" sichtbar, insbesonders bei normal trigger mode mit seltenen triggerevent oder force-trigger.

Der Speicherbklock wird als Core generiert, da die VHDL-Beschreibung des Blocks bedingt durch die unterschiedlichen Wortbreiten komplexer ist als eine direkte Beschreibung als array. Auch kann so Architekturabhängig der ideale Speicher eingebunden werden, gegebenfalls FPGA-externer Speicher.

Benutzer-Interface

Source File: board_specific/nexys3/src/button_map.vhd [11]

Ressourcenbedarf

Um nur den einen unbedingt nötigen BRAM zur verwenden und die gesamte andere Logik aus LUT's aufzubauen wurde im Synthesetool (XST) die Option -bram_utilization_ratio 1# gesetzt, Für einen den Spartan6 - LX16 im CSG324 Gehäuse mit Speedgrade 3 ergibt sich mit der ersten beta-Implementation (2013-07-13) damit:

Ressourcen S6-LX16
Ressource Anzahl Prozent zu FPGA
Slices-FF 266 1%
SLice-LUT 344 3%
Slices 136 6%
BRAM 1 3%

Das ist für diesen FPGA ein geringer Aufwand für ein deutliches Plus an debug-Funktionalität. Durch den kompletten Verzicht auf die HexaDez Ausgabe könnte etwas Logik gespärt werden, allerdings wird durch das Auszählen von bits das Analysieren von Businhalten mühsam.

Quellen

Sourcedepot

Die Quelldateien (VHDL, konfigurationsfile, scripte) liegen auf sourceforge.net, ebenso erfolgt das gesamte source-code handling (bug tracking etc) auf SF:

Board- und Architekturunabhängigen Files liegen im Verzeichnis /src; files für bestimmte boards im Verzeichniss /board_specific bspw für das Digilent nexys 3 Boord Spartan6 unter /board_specific/nexys3/. Für die Generierung eines Bit-Files in das Verzeichnis /board_specific/nexys3/script wechseln und dort make bit starten.

VHDL-Sourcen
Datei Verzeichniss Beschreibung
vga_controller_800_60.vhd /src Controlsig f. VGA-Monitor
display_pkg.vhd /src Bildschirmaufteilung etc.
charrom.vhd /src Zeichensatz 0-F
display.vhd /src Waveforms zeichnen
trigger_pkg.vhd /src Typen für triggermodule
trigger.vhd /src Triggersteuerung
sample_mem.vhd /boardspecific/Nexsys3/ embedded Speicherblock als recording mem
sig_record_pkg.vhd /src bspw. Portdefiniton recording mem
sig_record.vhd /src Speicherungcontroller
durchblicker_pkg.vhd /src Platzhalter, derzeit ungenutzt
durchblicker.vhd /src Top-entity embedded logic analyzer
clk_ctrl.vhd /boardspecific/Nexsys3/ Takterzeugung (VGA_clk, signal_clk)
button_map.vhd /boardspecific/Nexsys3/ Tasten des Evalboards zur Steuerung LA
sk_wrapper.vhd /boardspecific/Nexsys3/ Gesamtdesign für starterkit

Status

  • 2013-06-30: freilaufender Trigger funktioniert Cursors können per buttons verschoben werden
  • 2013-07-01: Ausgabe der Cursorposition in Hex
  • 2013-07-05: Ausgabe der Signalwerte "unter" Cursor -> [12]
  • 2013-07-10: Multiplexor zur Auswahl triggernder Kanal verdrahtet (Buttons Up/Down), Fixes in Anzeige
  • 2013-07-13: Umschalter für normal trigger hinzu, timing opts
  • 2013-08-29: H-Pegel als Doppellinie, Hervorhebung triggernder Kanal (rote Skala), timing opts vga_clk, minor bugfix
  • next: bugfixing trigger
  • next+: sample-enable divider per Taster einstellbar für langsame Signale

Bekannte Mängel

  • Fehler im pretrigger
  • veraltete Sampls nicht als ungültig erkennbar
  • falsche Pegelwechsel an Ende (rechts)
  • ...