Forum: FPGA, VHDL & Co. Logic Element (LE) programmieren


von Chris (Gast)


Lesenswert?

Hallo!

Ich bin neu in Sachen FPGA Programmierung - ich habe nur Kenntnisse im 
allgemeinen Programmieren - C, C++, Java etc.
Da ich eine leistungsfähige Plattform brauche habe ich mir ein Developer 
Board von Altera besorgt - mit Cyclone II FPGA.
Diesen möchte ich nun programmieren - Tutorials erfolgreich absolviert 
:) -
genauer gesagt, möchte ich explizit LEs programmieren (Logic Element) 
http://www.altera.com/literature/hb/cyc2/cyc2_cii51002.pdf

Ich möchte so eine Art Abtastung eines Bildes machen, jede LE wird einem 
Pixel eines Bildes zugeordnet.

wie kann man sich das vorstellen?
ich habe also ein bild dass 100x100 pixel groß ist. dementsprechend hat 
jeder pixel 8 nachbarpixel. nun soll sich eine LE den zustand des 
korrespondierenden pixels merken - wie auch immer, sei mal 
dahingestellt.
die LE soll dann irgendwann einmal den zustand des pixels modifizieren - 
farbe ändern oder ähnliches - dies ist aber abhängig von den pixeln in 
der nachbarschaft - es müssen also informationen zwischen den nachbarn 
(LE-nachbarschaft) ausgetauscht werden.

was mir nun kopfzerbrechen macht:
- wie programmiere ich explizit eine LE - etwas Logik muss rein.
- wenn ich mir das ganze als 2d array vorstelle - wie komme ich an die 
information, welche LE welche LEs als Nachbarn hat? - gibt es hier eine 
Möglichkeit der positionierung nach i und j ?
- in der beschreibung habe ich gelesen dass eine LE 4 inputs hat - ich 
bräuchte jedoch mindestens 8 - 8 nachbarn + ein paar andere 
informationen, die man wahrscheinlich anders besorgen könnte - im 
speicher o.ä.
- die position ist auch wichtig für die LEs die für die Randpixel 
vorgesehen sind.

Ich hoffe mir kann jemand ein paar tipps geben.
Ich sehe leider noch nicht durch und ich habe bisher noch keinerlei 
Erfahrung mit Chipprogrammierung bzw. Microcontrollerprogrammierung 
gemacht.

Vielen Dank!

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Du hast also vor, jedem Pixel eine LE zuzuordnen? Das wären bei einem 
100x100-Bild ganze 10.000 LE's, was eine ganz schöne Verschwendung wäre. 
Falls deine Verarbeitung nicht innerhalb einer ganz kurzen Zeit 
geschehen muss, solltest du die Daten der einzelnen Pixel nacheinander 
verarbeiten, das dauert dann zwar länger (z.B. bei einer 
Verarbeitungsrate von 50 MHz wären das 1/50000000*100*100=200 us), spart 
aber jede Menge FPGA-Ressourcen, die du dann woanders für verwenden 
kannst. Ich vermute mal, deine Daten liegen in irgendeinem Speicher vor, 
vielleicht einem internen oder externen SRAM? Ich würde dir empfehlen, 
jeweils 8 Pixel auf einmal aus dem Speicher zu laden, dann mit etwas 
Logik den neuen Wert des mittleren Pixels zu berechnen, und in einen 2. 
Speicher schreiben. Das wiederholst du immer wieder für jedes Pixel, und 
dann enthält der 2. Speicher das verarbeitete Bild. Dass du dann 8 Werte 
verarbeiten musst, ist kein Problem - formuliere in der HDL einfach die 
Verknüpfung der 8 Signale, und das Synthese-Tool macht daraus 2 oder 3 
kaskadierte LE's, die das gewünschte Ergebnis haben.
Während der Berechnung müssen die 8 Werte und der Ergebniswert im FPGA 
gespeichert werden, dazu verwendest du dann die FlipFlops, davon 
brauchst du also 9 Stück, und nicht über 10.000. Falls diese Methode dir 
nur etwas zu langsam ist, kannst du ja mehrere Verarbeitungen 
gleichzeitig laufen lassen, vorausgesetzt, der Bus des Speichers ist 
breit genug.
Falls die Geschwindigkeit völlig egal ist, empfehle ich dir einen 
gewöhnlichen Mikrocontroller mit 4 KB SRAM (falls jedes Pixel 1 bit tief 
ist, also 2 versch. Farben habe kann - habe ich das richtig 
verstanden?), der das auch ganz gut schaffen könnte. Das ist sicherlich 
auch einfacher zu programmieren und vor allem viel, viel billiger (ein 
paar Euros.).
Falls das völlig an deinen Vorstellungen vorbei geht, solltest du 
vielleicht sagen, wie dein Bild auf den FPGA kommt, wie es wieder 
herauskommen soll, wie schnell die Berechnung sein soll, und ob es eine 
Vorgabe hinsichtlich der Speicher-Methode gibt.
Oder habe ich dich völlig falsch verstanden, und dein Bild muss auf 
jeden Fall immer in den FF's vorliegen, und das ganze Bild muss auf 
einmal berechnet werden?

von Chris (Gast)


Lesenswert?

Hallo!

Vielen Dank für die rasche Antwort!

Naja das ganze soll schon sehr sehr schnell passieren - also parallel.
ich versuche damit eine echtzeitanwendung zu realisieren.
zb algorithmen auf das bild anwenden - wie contranst enhancement - wo 
die abhängigkeit der pixel untereinander gegeben ist.

hmm wegen der speicherung - also wie das bild in den fpga kommt hab ich 
mir noch keine gedanken gemacht - ich habe ja auch noch kein fundiertes 
wissen über die ganzen abläufe.
aber meine vorstellung war schon in die richtung die pixelinformation in 
einen FF zu laden - und zwar bei allen LEs auf einmal. dann die 
bearbeitung parallel geschehen lassen - die einzelnen LEs tauschen die 
informationen aus... etc.

wie gesagt, die verarbeitungszeit ist enorm wichtig.
der chip hat auch über 30000 LE, von demher...


also würde es funktionieren wenn ich eine architektur erstelle die mit 8 
inputs hantiert und außerdem logik implementiert - diese wird dann auf 
zb. 3 LE synthetisiert. nur wie weiß ich dann welche LEs - abstrakt 
gesehen - benachbart sind? ich nehme nur inputs von direkten nachbarn 
an.


noch eine kleine frage, ich werde wohl mit gleitkommazahlen arbeiten 
müssen... also die inputs sollten gleitkommazahlen sein - im internet 
habe ich ein paar open source libraries gefunden, aber ich weiß nicht so 
recht.

Vielen Dank

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Ja, du kannst problemlos Architectures mit beliebig vielen Ein-und 
Ausgängen bauen, das Synthese-Tool baut das in die benötigten LE's um.
Vermutlich solltest du das aber anders machen:
Du baust dir eine Architecture, in dessen HDL-Beschreibung du einen 
Prozess schreibst.
Die Architecture enthält 2 signal-Vectoren, der erste enthält alle Pixel 
des Ausgangsbildes, der 2. alle Pixel des neuen Bildes.
Der Prozess enthält zwei ineinander verschachtelte Schleifen, sodass der 
in der inneren Schleife stehende Code für jedes Pixel einmal 
"ausgeführt"(=vom Synthese-Tool in LE's übersetzt) wird. Dieser Code 
könnte dann in Abhängigkeit von den Schleifenvariablen die 
entsprechenden Pixel des Ausgangsbildes, die sich ja im 1. signal-Vector 
befinden, verknüpfen und das Ausgabe-Pixel berechnen, welches dann dem 
entsprechenden Pixel im Ausgabe-Vector zugeordnet wird. z.B. bei einer 
Taktflanke könntest du die Ausgabepixel in FlipFlops übernehmen, deren 
Ausgänge du auch mit dem Ausgans-Vektor verbinden könntest. In etwa so:
1
architecture icalc_arch of icalc is
2
  -- Ausgansbild
3
  signal  IMG_IN : std_logic_vector (9999 downto 0);
4
  -- Verarbeitetes Bild
5
  signal  IMG_OUT: std_logic_vector (9999 downto 0);
6
begin
7
  process (IMG_IN,CLK)
8
  begin
9
    for X in 99 downto 0 loop
10
      for Y in 99 downto 0 loop
11
        -- Pixel des Ausgabebildes an Position X/Y in Abhängigkeit des Eingabebildes berechnen
12
        IMG_OUT (Y * 100 + X) <= IMG_IN ( Y * 100 + X - 1 ) ....
13
        
14
        if (CLK'event and CLK = '1') then
15
          -- ... Das Ausgabebild in Flipflops speichern, und die Ausgänge der Flipflops ale Eingabe-Bild
16
          -- verwenden, sodass bei der nächsten Taktflanke das Ausgabebild nocheinmal verarbeitet würde.
17
          IMG_IN <= IMG_OUT;
18
          -- Sinnvollerweise hier eine weitere Anweisung einfügen, die z.B., falls ein anderes Eingabesignal
19
          -- '1' ist, IMG_IN einen Wert "von außen" zuweist - sodass nicht das neu berechnete Bild
20
          -- eingespeichert wird, sondern das neu eingelesene.
21
        end if;
22
      end loop;
23
    end loop;
24
  end process;
25
end icalc_arch;
Das Synthese-Tool produziert daraus ganz viele LE's und FF's.
Allerdings stellt sich das Problem, wie du die Daten so schnell auf den 
FPGA bekommen willst - kein FPGA hat 10.000 Eingänge, sodass du es 
irgendwie seriell machen musst, was auch eine serielle Verarbeitung 
sinnvoll macht. Nur leider sind solche schnellen Übertragungen alles 
andere als einfach. Dadurch könntest du die Rechengeschwindigkeit des 
FPGA's nicht voll ausnützen. Es wäre hilfreich, wenn du eine ungefähre 
Angabe machen würdest, wie schnell es denn sein soll.
Von Floating-Point-Arithmetik habe ich keine Ahnung, aber vielleicht 
jemand anderes hier. Ich habe allerdings mal wo gelesen, dass 
fixed-Point oftmals auch Sinn macht und einfacher ist.

von Chris (Gast)


Lesenswert?

Hallo!

Vielen Dank für die echt konstruktiven Antworten - bin echt überrascht 
:)!

Die Software Simulation die ich verwende, gibt etwa als Referenzwert 
eines Chips aus 72 usec.
Die Software Simulation selbst benötigt 92 msec. ich kann hier aber nur 
von einer 12x12 Pixel Simulation berichten.

Der Prototyp wird einfach nur folgendes machen - auch nachdem ich eure 
vorschläge gelesen habe:

serielles einlesen des bildes (schwarz==1/weiß==0)

eine solche abgeschlossene einheit konzipieren - diese zellen sind so 
definiert - ich bin also gezwungen dies so zu gestalten.
1
entity one_cell is
2
    
3
  -- in example: cell 5 has 8 neighbours - (1,2,3,4,6,7,8, and 9)
4
  -- [ ]-[ ]-[ ]-[ ]-[ ]
5
  --  | X | X | X | X |
6
  -- [ ]-[1]-[2]-[3]-[ ]
7
  --  | X | X | X | X |
8
  -- [ ]-[4]-[5]-[6]-[ ]
9
  --  | X | X | X | X |
10
  -- [ ]-[7]-[8]-[9]-[ ]
11
  --  | X | X | X | X |
12
  -- [ ]-[ ]-[ ]-[ ]-[ ]
13
  
14
  PORT(      
15
    -- inputs of neighbors
16
    neighbour_input_11 : IN STD_LOGIC_VECTOR (1 downto 0);     -- '00' = white, '01' = light grey, '10' = dark grey, 11' = black
17
    neighbour_input_12 : IN STD_LOGIC_VECTOR (1 downto 0);
18
    neighbour_input_13 : IN STD_LOGIC_VECTOR (1 downto 0);
19
    
20
    neighbour_input_21 : IN STD_LOGIC_VECTOR (1 downto 0);
21
    neighbour_input_22 : IN STD_LOGIC_VECTOR (1 downto 0);    -- its me
22
    neighbour_input_23 : IN STD_LOGIC_VECTOR (1 downto 0);
23
    
24
    neighbour_input_31 : IN STD_LOGIC_VECTOR (1 downto 0);
25
    neighbour_input_32 : IN STD_LOGIC_VECTOR (1 downto 0);
26
    neighbour_input_33 : IN STD_LOGIC_VECTOR (1 downto 0);
27
    
28
    -- output y_ij        
29
    neighbour_output_11 : OUT STD_LOGIC_VECTOR (1 downto 0);
30
    neighbour_output_12 : OUT STD_LOGIC_VECTOR (1 downto 0);
31
    neighbour_output_13 : OUT STD_LOGIC_VECTOR (1 downto 0);
32
    
33
    neighbour_output_21 : OUT STD_LOGIC_VECTOR (1 downto 0);
34
    neighbour_output_22 : OUT STD_LOGIC_VECTOR (1 downto 0);  -- its me
35
    neighbour_output_23 : OUT STD_LOGIC_VECTOR (1 downto 0);
36
    
37
    neighbour_output_31 : OUT STD_LOGIC_VECTOR (1 downto 0);
38
    neighbour_output_32 : OUT STD_LOGIC_VECTOR (1 downto 0);
39
    neighbour_output_33 : OUT STD_LOGIC_VECTOR (1 downto 0);
40
    
41
  );
42
end entity one_cell;
43
44
-- jetzt nur PSEUDOCODE
45
architecture cell of one_cell is
46
47
function neuen_zustand_berechnen(t_i : real; x_i : STD_LOGIC_VECTOR (1 downto 0)) return real is  
48
    variable x    : real  := 0.0;
49
    variable t    : real  := 0.0;
50
  begin    
51
    return x_i + t_i * 2.0;    
52
  end neuen_zustand_berechnen;
53
54
function output_berechnen (x_i : STD_LOGIC_VECTOR (1 downto 0)) return real is  
55
  begin    
56
    return x_i * lambda;    
57
  end output_berechnen;
58
59
begin
60
    x_actual    :    STD_LOGIC_VECTOR (1 downto 0);
61
    x_new       :    STD_LOGIC_VECTOR (1 downto 0);
62
    counter       :    STD_LOGIC_VECTOR (9999 downto 0); -- ich arbeite diskret - diesen counter brauche ich 
63
--dann in der funktion neuen_zustand_berechnen.
64
65
-- wobei x_acutal in einem d-flipflop gespeichert ist.
66
67
    x_new <= neuen_zustand_berechnen(counter, x_actual);
68
    neighbour_output_11 <= output_berechnen(x_actual);
69
--...
70
    neighbour_output_33 <= output_berechnen(x_actual);
71
    
72
73
end architecture cell;

jetzt gibt es mehrere zyklen - ein pixel muss mehrfach bearbeitet werden 
bis die verarbeitung abgeschlossen ist. wie oft dies geschehen muss, 
muss ich noch abklären - eventuell bis es nur mehr eine ganz kleine 
änderung am zustand einer zelle gibt - im prototyp wahrscheinlich zu 
vernachlässigen, da nur 4 zustände geplant.

bei den ganzen berechnungen in den funktionen brauche ich aber float 
operationen. wie kann ich das am besten realisieren?

wenn die berechnungen abgeschlossen sind, lese ich einfach den inhalt 
der d-flip flops aus... das bild sollte fertig verarbeitet worden sein.
1
library IEEE;
2
use IEEE.std_logic_1164.all;
3
4
5
-- implementation of a D FlipFlop
6
entity module_d_flipflop is
7
  port( CLK, D : in std_logic;
8
        Q      : buffer std_logic);
9
end module_d_flipflop;
10
11
12
architecture A1_DFF of module_d_flipflop is
13
begin
14
  P1: process( CLK )
15
  begin
16
    if( CLK'event and CLK = '1' ) then
17
       Q <= D;
18
    end if;
19
  end process;
20
end A1_DFF;
oben die implementierung des d-flipflops in dem ich die zustände 
speichern will.


ich habe also auch ein gröberes problem bei den real - std_logic 
übergängen.
zwangsläufig muss genauigkeit verloren gehen.


was ich noch nirgendwo herausgelesen habe: wie verdrahtet man die 
einzelnen zellen untereinander? wegen der nachbarschaft.

mfg
Chris

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

> was ich noch nirgendwo herausgelesen habe: wie verdrahtet man die
> einzelnen zellen untereinander? wegen der nachbarschaft.

Ich würde das anders machen - eben halt nicht eine architecture für ein 
einzelnes Pixel, sondern eine architecture, die alle Pixel berechnet, 
die, wie oben beschrieben, alle Pixel mit den 2 Schleifen berechnet und 
speichert. So kannst du halt auch problemlos auf die Werte der 
Nachbar-Pixel zugreifen, indem du bei IMG_IN den Index rauf oder 
runterzählst. Und das FlipFlop als einzelne architecture zu 
implementieren, kannst du dir so auch sparen, da die FF über die 
if-Abfrage im process automatisch generiert werden. Denke nicht in einer 
einzelnen Zelle, die mit ihren Nachbarn kommuniziert, sondern in einem 
process, der anhand von der Eingabe IMG_IN die Ausgabe IMG_OUT 
berechnet. Der process hat ja Zugriff auf das gesamte Eingabebild 
IMG_IN, kann also problemlos mehrere Pixel zur Berechnung verwenden.
PS: ISBN 978-3-486-58192-8

von Chris (Gast)


Lesenswert?

Hallo!

aber in einem process wird jedes statement sequentiell abgearbeitet?
das modell dass ich implementiere - ähnlich zu einem neuralen Netz, muss 
parallel funktionieren.

Ich weiß ich stelle mir das etwas anders vor - komme aus der "normalen" 
Programmierwelt.
Aber wäre es nicht möglich, in dieser doppelten for schleife ein 
generate aufzufurufen, dass mir beliebig viele Zellen erzeugt.
jeder Zelle gebe ich dass das IMAGE_BUFFER, auf welchem jede Zelle 
operiert.
außerdem die X und Y position - damit ich die Zellen zuordnen kann.

tut mir leid, ich muss mich leider auf das modell versteifen, da es um 
parallele verarbeitung geht und neurale netze dieses paradigma haben.

aber ich denke es wird probleme geben wenn ich das image_signal mehrfach 
verwende? doppelte device vergabe ist so ein keyword?

mfg
Chris

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> aber in einem process wird jedes statement sequentiell abgearbeitet?
> das modell dass ich implementiere - ähnlich zu einem neuralen Netz, muss
> parallel funktionieren.
Ja, jetzt wirds aber Zeit, dass du dir ein paar VHDL-Grundlagen 
aneignest. Sonst wird das peinlich hier :-/

Ein Prozess wird von oben nach unten interpretiert. Er wird aber 
parallel in Hardware abgebildet. Die Abarbeitung eines Prozesses 
braucht keine Zeit, weil sie parallel geschieht.
Bei einem getakteten Prozess wird mit jedem Takt der gesamte Prozess 
abgearbeitet. Danach haben die sich ergebenden Signale Zeit, sich zu 
beruhigen, dann kommt der nächte Takt...

EDIT:
Mit deiner Logic-Element Denkweise beschreibst du eine Struktur. 
Wesentlich angenehmer und Protabler ist eine Verhaltensschreibweise. Die 
Abbildung auf LE überlässt du dann der Toolchain.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

> aber in einem process wird jedes statement sequentiell abgearbeitet?
Ja, so wird es immer formuliert. Aber wenn ich mich nicht komplett irre, 
werden alle Anweisungen in einem process tatsächlich gleichzeitig 
ausgeführt. Nur macht z.B. das Ergebnis der 3. Anweisung nicht sofort 
einen Sinn, wenn es auf dem Ergebnis der 2. und der 1. Anweisung beruht, 
die ja auch erst einmal berechnet werden müssen. Veranschaulichung:

Aus diesem process:
1
process (A,B,C)
2
  variable TEMP : std_logic_vector;
3
begin
4
  TEMP := A and B;
5
  X <= TEMP or C;
6
end process;
wird folgende Schaltung:
1
A >--+---+   TEMP
2
     | & +----------+----+
3
B >--+---+          | or +---> X
4
                 +--+----+
5
C >--------------+
Du siehst, dass die beiden Gatter gleichzeitig rechnen. Nur sobald sich 
einer der Eingabewerte ändert, braucht es einen kurzen Moment, bis sich 
TEMP ändert, und dann noch etwas, bis sich X ändert - daher sequentiell 
(wie schnell das konkret bei einem Cyclone ist weiß ich nicht, aber z.B. 
bei einem Xilinx Spartan-3A dauert es ca. 600ps, und der ist angeblich 
vergleichbar). Wenn du jetzt mit einer for-Schleife ganz viele von 
diesen Konstruktionen baust, und die einzelnen "Iterationen" der 
Schleife nicht von den Ergebnissen der anderen Iterationen abhängen, 
wird faktisch jeder Schleifendurchlauf gleichzeitig "durchgeführt", und 
die bei jedem Schleifendurchlauf generierte Logik agiert parallel; genau 
wie bei einem neuronalen Netzwerk.
Und es gibt in VHDL generate-Schleifen; für jede Iteration wird die in 
der Schleife beschriebene Logik erzeugt, und auf dem FPGA parallel 
abgearbeitet. Es müsste dabei exakt das gleiche herauskommen wie bei dem 
process. Nur, bei dem process kannst du durch die getaktete Anweisung 
(die if-Abfrage mit dem CLK'event) noch automatisch FlipFlops einbauen 
lassen, daher hatte ich keine generate-Schleife verwendet. Wenn es dir 
besser gefällt, kannst du auch eine generate-Schleife verwenden, und dir 
mit einem process die FlipFlops generieren lassen. In diese 
generate-Schleife könntest du entweder direkt die Logik für die 
Berechnung schreiben, oder eine Instanz von one_cell anlegen, und dessen 
I/O-Ports mit den entsprechenden Teil-Signalen aus IMG_IN und IMG_OUT 
verbinden; das wäre mir allerdings zu umständlich ;)
> aber ich denke es wird probleme geben wenn ich das image_signal mehrfach
> verwende? doppelte device vergabe ist so ein keyword?
Nein, das ist überhaupt kein Problem, du kannst jedes Signal beliebig 
oft als Eingangssignal für andere Berechnungen verwenden - aber 
sinnvollerweise nicht als Ausgangssignal, du kannst nicht die Ausgänge 
zweier Gatter mit ein und demselben signal verbinden, das würde 
vermutlich den FPGA zerstören, und deswegen lässt kein Synthese-Tool das 
zu. Faktisch kannst du ein Signal nur bei einer bestimmten 
Maximal-Anzahl(der sog. Fan-Out) von weiteren Gattern als Eingangssignal 
verwenden, da die Ausgabe-Treiber der Gatter nicht unendlich stark sind; 
da brauchst du dich aber nicht drum zu kümmern, das Synthese-Tool baut 
dann automatisch weitere Gatter als "Verteiler" ein.
> Ja, jetzt wirds aber Zeit, dass du dir ein paar VHDL-Grundlagen
> aneignest. Sonst wird das peinlich hier :-/
Siehe dazu die ISBN am Ende meines letzten Posts, das Buch ist m.E. ganz 
gut zum Einstieg.

von Chris (Gast)


Lesenswert?

Dankeschön für die hilfreichen Antworten!

> Ja, jetzt wirds aber Zeit, dass du dir ein paar VHDL-Grundlagen
> aneignest. Sonst wird das peinlich hier :-/
Fragen zu stellen doch nicht peinlich. vorallem wenn man eben erst mit 
vhdl angefangen hat und keine wirkliche ahnung von hardware hat.


> Siehe dazu die ISBN am Ende meines letzten Posts, das Buch ist m.E. ganz
> gut zum Einstieg.
Danke, werde es mir umgehend bestellen.

mfg

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

Lesenswert?

> Nur sobald sich einer der Eingabewerte ändert, braucht es einen kurzen
> Moment, bis sich TEMP ändert, und dann noch etwas, bis sich X ändert
Nach der Synthese (als RTL-Schematic) sieht das noch so aus, aber mit 
den nachfolgenden Arbeitsschritten wird jede logische Funktion mit bis 
zu 4 Eingängen wird in 1 LUT gepackt (z.B. bei Xilinx Spartan 3).
Diese Variable TEMP existiert innerhalb des FPGAs nicht mehr. Der 
Prozess wird parallel abgearbeitet. Wobei parallel durchaus bedeutet, 
dass da Laufzeiten im Spiel sind, insbesondere, wenn auch die reduzierte 
Logik nicht mehr in 1 LUT passt, kommen mehrere dieser Durchlaufzeiten 
und Verdrahtungslaufzeiten zusammen. Diese begrenzen dann auch die 
maximale Taktfrequenz des Designs.

> Siehe dazu die ISBN am Ende meines letzten Posts, das Buch ist m.E. ganz
> gut zum Einstieg.
Ja, die ISBN ist ok ;-)

EDIT:
> Fragen zu stellen doch nicht peinlich.
Nein, das nicht.
Aber dir fehlt aktuell (noch) der Hintergrund, die Antworten zu 
verstehen. Und daraus ergeben sich dann wieder Fragen...

von Matthias G. (mgottke)


Lesenswert?

Hallo Chris,

noch eine kleine Anmerkung zur Umsetzung:
Wenn Du wirklich ein Bild von 100x100 Pixel hast, dann wird das wohl 
nicht komplett parallel in Dein FPGA passen. Bei 8 Eingangssignale in 
einem Berechnungsschritt benötigst Du mindestens 3 LUTs. Da jede LUT nur 
4 Eingänge hat, dann kann man mit zwei LUTs im günstigsten Fall max. 7 
Eingänge auswerten (4 für den Zwischenwert und im zweiten LUT braucht 
man ja schon den Ausgang aus der ersten LUT als Eingang).
Das Laden der Pixel und deren Adressierung sind da noch nicht 
eingerechnet. Je nach Filterformel schätze ich mal so ca. 5 bis 6 LUTs 
pro Pixel werden schon nötig sein.
Daraus ergibt sich aber schon eine Anzahl von 50k bis 60k LUTs. Die 
Umsetzung am Eingang und Ausgang so wie die Floatpoint-Aritmetik noch 
nicht inbegriffen.
Des weiteren solltes Du bedenken, dass ein FPGA sich nur zu ca. 70% bis 
85% sinnvoll "füllen" läßt. Danach wird es mit dem internen Routing im 
FPGA schwierig und die maximale Taktrate wird erheblich langsamer.

Egal wie viel Du parallelisierst, Die 10k Bits müssen ja doch irgendwie 
in den FPGA kommen. Das geht auch nicht in einem Takt. Vermutlich steht 
da irgend ein Daten-Adress-Interface dahinter, oder aber eine sehr 
schnelle serielle Anbindung. Du könntest aber das Bild in Blöcke (z.B. 
in 16x16 Pixel) unterteilen. So hättest Du immerhin schon 256 Pixel, 
welche Du parallel filten könntest. 256 Bit breiten Speicher kann man 
problemlos implementieren. Die Pixelblöcke könntest Du dann überlagernd 
laden, so dass dann in 7x7 Schritten ein Filterschritt erledigt sein 
könnte. Das wären bei einer Taktrate von z.B. 50 MHz und 49 Schritten 
eine us Filterzyklus. Bei 10 Filterzyklen wäre immernoch eine 
Bildwiederholrate von ca. 100 kHz drin. Ich denke die "Kamera" mit so 
einer Bildrate muss noch erfunden werden. Bei 100 kHz müssten ja auch 
noch irgendwie die 1 GPixel/s in den FPGA und wieder raus.

Also nochmal überdenken! Da muss man erst einmal genau die Anforderungen 
an die Verarbeitungstiefe und die tatsächlich geforderte Geschwindigkeit 
wissen. Dann ist es auch möglich ein Konzept zur Umsetzung zu entwerfen. 
Alles andere führt nur zur Frustration.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> das ganze soll schon sehr sehr schnell passieren
Mit 100MHz Taktfrequenz könntest du nach deiner Denkweise 100 Millionen 
Bilder/Sekunde verarbeiten. Ist diese Geschwindigkeit nötig?
Wenn nein: reichen 100 Tausend Bilder/Sekunde oder gar 100 
Bilder/Sekunde?

Angenommen, es würden 100000 Bilder/sec reichen, dann hättest du bei 
einer Taktfrequenz von 100MHz eintausend Zyklen Zeit, etwas mit dem Bild 
zu machen. D.h. du könntest es evtl. zeilenweise abarbeiten.
Lass dir diese überschlägige Logik mal auf der Zunge zergehen (wie 
Matthias schon sagte).

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.