Forum: FPGA, VHDL & Co. for loop in VHDL um Schreibarbeit zu sparen


von D. S. (des)


Lesenswert?

Hallo zusammen,

ich möchte Daten aus einem fortlaufenden Datenstrom zusammengefasst, 
also zu einem bestimmten Zeitpunkt, in ein Byte-Array schreiben, das 
dann als Paket verschickt werden soll.

Meine Überlegung war jetzt, die Daten in ein Schieberegister zu schieben 
(bei jedem Takt 4 Byte) und dann mittels einer for loop die Daten zu 
einem bestimmten Zeitpunkt auf einen Schlag in das Array zu kopieren, 
von dem aus dann die Daten verschickt werden.

Da die Datenlänge recht groß ist, war meine Überlegung, die 
Schreibarbeit durch eine for loop übernehmen zu lassen. Angefangen 
werden soll bei einem Offset. (Ich hoffe, ich habe damit den Sinn der 
for loop in VHDL richtig vestanden, quasi, dass alles in parallelen Code 
umgesetzt wird, jetzt wollte ich mich - auch verständnishalber - mal 
daran versuchen)

Die Daten:
1
data : in std_logic_vector(13200 downto 0);
2
type tBytearray is array (0 to 1400) of std_logic_vector(7 downto 0);
3
signal Bytearray : tBytearray;

So würde das aussehen, wenn ich es von Hand schreiben würde
1
-- Offset für den Header von 65
2
Bytearray (65) <= data (7 downto 0);
3
Bytearray (66) <= data (15 downto 8);
4
Bytearray (67) <= data (23 downto 16);
5
Bytearray (68) <= data (31 downto 24);
6
Bytearray (69) <= data (39 downto 32);
7
Bytearray (70) <= data (47 downto 40);
8
Bytearray (71) <= data (55 downto 48);
9
:                      :
10
:                      :
11
Bytearray (1300) <= data (...

Und jetzt der Gedanke, das in einer for loop zu machen:
1
write_data_in_datagram : process (e_clk)
2
  variable counter_x : integer := 0;
3
begin
4
  if rising_edge(e_clk) then
5
    if res_signal = '1' then
6
      for x in 0 to 1300 loop         
7
        Bytearray(x + 65) <= data((counter_x + 7) downto (counter_x));
8
        counter_x := counter_x + 8;
9
      end loop;
10
    end if;
11
  end if;
12
end process;

Das lässt sich aber so noch nicht synthetisieren bei mir. Bin ich damit 
auf dem richtigen Weg oder hab ich da noch etwas falsch gemacht? Ist das 
vielleicht zu viel für den FPGA?

Eine andere Frage so nebenbei: Ist diese Vorgehensweise überhaupt klug 
und sinnvoll oder verschwende ich so nur Ressourcen? (habe einen Spartan 
6 XC6SLX45)

Wie macht man das sonst? Denn die Daten müssen ja einmal als Ganzes 
vorhanden sein, um das Paket zusammenzusetzen.

von user (Gast)


Lesenswert?

Verwende die vorhanden BlockRAMs, und baue das packet darin zusammen, du 
musst ja nie auf alle Bits einzeln zugreifen können

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


Lesenswert?

D. S. schrieb:
> Das lässt sich aber so noch nicht synthetisieren bei mir.
Und mit welcher Beanstandung?

> Eine andere Frage so nebenbei:
Die sollte eigentlich im Vordergrund stehen...
> Ist diese Vorgehensweise überhaupt klug und sinnvoll
Vermutlich nicht.
> oder verschwende ich so nur Ressourcen?
Wenn du die Zuweisung nicht in jedem Takt brauchst, dann ja. Und zwar 
extrem viele, denn das ist kein Speicherbereich, der da hin- und 
herkopiert wird, sondern das sind (mindestens) 13201+11208 Flipflops 
(gut 24000) deines FPGAs und entsprechend viele Verdrahtungsressourcen 
die dafür benötigt werden...

> habe einen Spartan 6 XC6SLX45
Der hat laut DB gerade mal 54,576 Flipflops. Ist dir diese billige 
Zuweisungsoperation fast die Hälfte deines FPGAs wert?

> Wie macht man das sonst?
Schon dort geht es los:
   data : in std_logic_vector(13200 downto 0);
Wozu so einen Monstervektor? Woher kommen die Daten wie schnell herein?

> Denn die Daten müssen ja einmal als Ganzes
> vorhanden sein, um das Paket zusammenzusetzen.
Durchaus, aber man kann die Daten in einen Speicher (RAM) ablegen, und 
danach häppchenweise zusammensetzen. Man hat ja üblicherwiese ein paar 
Takte Zeit dafür...

von PittyJ (Gast)


Lesenswert?

Ich war auch mal drauf und dran, so etwas zu machen.
Doch dann habe ich mit richtigen Profis zusammengearbeitet. Die haben 
alles immer in Fifos gepackt. Und wenn die ersten 60 Bytes überlesen 
werden sollen, dann wurde eben mal 60 Bytes ausgelesen und ignoriert. 
Der Rest wurde dann weiter-gepiped. Das ganze System war dann recht 
übersichtlich und einfach zu bedienen/programmieren/verändern.

Diese Array-Konstrukte haben wir nie benutzt.

von D. S. (des)


Lesenswert?

Ich möchte nur 4 Pakete pro Sekunde senden, die jeweils 1300 Byte groß 
sind. Also nur 4x pro Sekunde diese Aktion. Externen Speicher habe ich 
dafür nicht (der wäre zwar auf meinem Eval-Board drauf, aber den habe 
ich einfach noch nicht zum laufen gebracht und brauche daher jetzt eine 
einfachere und schneller zu implementierende Lösung).

Die Frequenzangabe für die Eingangsdaten kann ich gerade nicht finden, 
ich meine so um die 100MHz. Eingang sind Bilddaten. Ein großer Teil der 
Eingangsdaten soll aber nicht berücksichtigt werden.

Die Idee mit dem FIFO klingt schon mal ganz gut, quasi immer bspw 50 
Bytes aus dem FIFO auszulesen und jeweils an die entsprechende Stelle 
ins Paket zu schreiben.

Den Platz, den das Bytearray wegnimmt, muss ich dann aber immer noch 
abdecken... Oder kann man das in Block RAMs umsetzen?

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


Lesenswert?

D. S. schrieb:
> Ich möchte nur 4 Pakete pro Sekunde senden
Wie schnell mit was wohin?

> Externen Speicher habe ich dafür nicht
Aber du hast 2 Millionen Bits RAM im FPGA...

> und jeweils an die entsprechende Stelle ins Paket zu schreiben.
Vergiss dieses Array und denke in RAMs. Wie musst du die Daten 
organisieren, damit sie in die RAMs abgelegt werden können? Kannst du 
die Daten beim Herienkommen schon "richtig" sortieren? Oder reicht es 
aus, die Daten beim Senden umzusortieren? Ich würde sagen: zweimal ja.

> Oder kann man das in Block RAMs umsetzen?
Summa summarum: das ist die einzige wirklich sinnvolle Möglichkeit.

von D. S. (des)


Lesenswert?

Senden mit 125MHz per Gigabit Ethernet. Ich habe einen ganz simplen 
Ethernet MAC, komplett in VHDL, der nur das Nötigste macht, mit festen 
Adressen, festgelegter Länge,...

Im Moment liegen die Daten eben in diesem Array drin (im Ethernet MAC)
1
type tBytearray is array (0 to 1400) of std_logic_vector(7 downto 0);
2
signal Bytearray : tBytearray;
von dem aus in jedem Takt ein Datum an die Sendeeinheit übergeben wird.

Dann wäre für mich die Frage natürlich - ich habe leider keine Ahnung 
von RAMs im FPGA - wie ersetze ich dieses Array durch RAMs? Und gibt es 
dann eine Möglichkeit, diese Daten auch für mehrere Module zugänglich zu 
machen?

Ich vermute, dass zu erklären, wie man das macht, wäre ein bisschen 
aufwendig, ich werde mir dann also erstmal ein paar Grundlagen anlesen 
müssen. Aber schon mal vorweg die Frage, ist das kompliziert? Kann man 
sich das schnell anlernen?

von D. S. (des)


Lesenswert?

ok, ich habe gerade den Link zu deiner Seite entdeckt, wo du etwas über 
BRAMs schreibst. Und ich habe auch gerade über "View Technology 
Schematic" gesehen, dass die ja sowieso schon in meinem Design so 
umgesetzt wurden. Das heißt quasi doch "Arrays" benutzen, bloß in der 
richtigen Art und Weise?

Kann ich das Array auch über mehrere Module verfügbar machen, sodass es 
denoch über ein internes RAM umgesetzt wird?

von eingast (Gast)


Lesenswert?

D. S. schrieb:
> Dann wäre für mich die Frage natürlich - ich habe leider keine Ahnung
> von RAMs im FPGA - wie ersetze ich dieses Array durch RAMs? Und gibt es
> dann eine Möglichkeit, diese Daten auch für mehrere Module zugänglich zu
> machen?

In dem du in VHDL einen RAM beschreibst, dann setzt die Synthese das 
automatisch in einen Blockram oder Distributed RAM um, je nach dem was 
sie für sinnvoll hält. XAPP463 (Google -> spartan ram vhdl template) 
sagt dir, wie du diese templates im Xilinx ISE einfügen kannst.

Wenn du auf diesen RAM zugreifen willst, legst du eine Adresse an und 
die Daten für die Adresse kommen raus (wie bei jedem RAM halt :-). 
Üblicherweise sind in den FPGAs Dualport-RAMs verbaut, d.h. du kannst 
maximal zwei unterschiedliche Adressen gleichzeitig anlegen um 2 
unterschiedliche Werte auszulesen

von Christian R. (supachris)


Lesenswert?

Im SPartan 6 XST User Guide sind auch jede Menge Beispiele für Block- 
und Distributed RAM generisch beschrieben drin.

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


Lesenswert?

D. S. schrieb:
> ok, ich habe gerade den Link zu deiner Seite entdeckt, wo du etwas über
> BRAMs schreibst. Und ich habe auch gerade über "View Technology
> Schematic" gesehen, dass die ja sowieso schon in meinem Design so
> umgesetzt wurden. Das heißt quasi doch "Arrays" benutzen, bloß in der
> richtigen Art und Weise?

> Und ich habe auch gerade über "View Technology Schematic" gesehen,
> dass die ja sowieso schon in meinem Design so umgesetzt wurden.
Das ist seltsam. So ein massiv paralleles Ram mit einer Datenwortbreite 
von 1301*8 = 10400 Bits gibt es nicht...

> Kann ich das Array auch über mehrere Module verfügbar machen, sodass es
> denoch über ein internes RAM umgesetzt wird?
Ja, entweder über das bereits angesprochene Dual-Port-Interface, oder 
wie "früher" über einen Multipexer, der von zwei (oder mehr) Komponenten 
die jeweils interessante Adresse (und beim Schreiben auch die Daten) 
auswählt und ans RAM weitergibt.

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.