Forum: FPGA, VHDL & Co. variabler Zugriff auf Array Elemente in Verilog


von gunni (Gast)


Lesenswert?

Hallo,

angenommen ich habe ein Feld mit 200 Werten

reg signed [7:0] feld [0:199];

Nun möchte ich Elemente dieses Feldes für Verarbeitungen nutzen z.B.

möchte ich je zwei Elemente von 10 aufeinanderfolgenden Werte 
vergleichen die von einer zuvor bestimmten Variable var_1 abhängen.

for(int j=0;j<10;j=j+1) begin

if(feld[var_1+j]<feld[var_1+j+1])

.
.
.

end

Nun kommt es mir so vor als wenn eine solche Vorgehensweise sehr 
ressourcenfresend ist. Gibt es dort bessere Möglichkeiten oder hat 
jemand Suchbegriffe für mich?
Ich hatte auch schon die Idee vorher die 10 benötigten Werte aus dem 
Array zu extrahieren aber feld_neu[0:9]<=feld[var_1+:10] bringt einen 
Fehler bei der Synthese gibt es dort vielleicht noch andere Ansätze.


Danke Gunni

von Petger (Gast)


Lesenswert?

Eine der wichtigsten Fragen zu Beginn: Wieviele Takte hast du dafür 
Zeit?

von gunni (Gast)


Lesenswert?

wollte das möglichst in einem schaffen wenn das geht

von Petger (Gast)


Lesenswert?

gunni schrieb:
> wollte das möglichst in einem schaffen wenn das geht

Dann kommst du kaum um einen 256 bit shifter mit einem 11 bit breiten 
datenausgang + vergleicher 0:9 mit 1:10 drum herum. Das Timing wird dann 
aber vergleichsweise schlecht. Wenn du mehrere Takte Zeit hast, könnte 
man durch vorladen sicherlich einiges rausholen, sowohl vom Timing, als 
auch von den Ressourcen.

von Lattice User (Gast)


Lesenswert?

gunni schrieb:
> wollte das möglichst in einem schaffen wenn das geht

Bei welcher Taktfrequenz?

von gunni (Gast)


Lesenswert?

150Mhz wenn es aebr nicht in einem geht dann muss es halt in meheren 
sein aber halt so schnell wie möglich



Petger kannst du das mit dem vorladen noch etwas weiter beschreiben


Danke

von Lattice User (Gast)


Lesenswert?

gunni schrieb:
> 150Mhz wenn es aebr nicht in einem geht dann muss es halt in meheren
> sein aber halt so schnell wie möglich

Wird nicht gehen, zumindestens nicht mit deinem Ansatz, der braucht 
nämlich riesige (200:1) Multiplexer.

Dein Ansatz ist die typische vorgehensweise eines C-Programmierers, 
einfach als Programm hinschreiben und hoffen dass es der Synthesier dann 
hinbiegt.

Um es mal ketzerisch auszudrücken;
Für solche Aufgabenstellungen wurden Zustandsautomaten erfunden. Diese 
gibt es frei programmierbar fertig zu kaufen mit Taktfrequenzen bis zu 4 
GHz. Hersteller sind Intel,AMD,TI,Atmel .....

von gunni (Gast)


Lesenswert?

Hast du einen anderen Ansatz der in eine richtige Richtung geht ich muss 
nämlich einen FPGA verwenden hab da keinen Einfluss drauf;)

von Lattice User (Gast)


Lesenswert?

gunni schrieb:
> Hast du einen anderen Ansatz der in eine richtige Richtung geht ich muss
> nämlich einen FPGA verwenden hab da keinen Einfluss drauf;)

Du überlegst dir was für Hardwareblöcke du brauchst, wie diese Aussehen 
und beschreibts diese dann in Verilog/VHDL. Dann ist es auch relativ 
leicht Dinge wie Pipelining zu realisieren um auf Geschwindigkeit zu 
kommen. Braucht halt Zeit bis man soweit ist dass alles geht.

Das Thema hatten wir hier schon oft;
Verilog/VHDL sind Hardwarebeschreibungssprachen und keine 
Programmiersprachen. Der Ansatz einfach den Algorithmus hinzuschreiben 
funktioniert nur in ganz wenigen Fällen wie manche DSP Anwendungen.

von Petger (Gast)


Lesenswert?

gunni schrieb:
> 150Mhz wenn es aebr nicht in einem geht dann muss es halt in meheren
> sein aber halt so schnell wie möglich
>
>
>
> Petger kannst du das mit dem vorladen noch etwas weiter beschreiben
>
>
> Danke

Fang einfach an Register einzusetzen und guck dir an was mit dem Timing 
passiert. Das erste setzt du zwischen Shifterausgang und Vergleicher, 
das nächste setzt du im Shifter ein. Dafür baust du idealerweise einen 
Binärbaum auf. Hier mal ein Minimalbeispiel zum Verständnis:

Noobie-Shifter:
1
c <= data(3 downto 0) when val = "00" else
2
     data(2 downto 0) & '0' when val = "01" else
3
     data(1 downto 0) & "00" when val = "10" else
4
     data(0) & "000";

Profi-Shifter:
1
stage2(6 downto 0) <= data(3 downto 0) & "000";
2
3
stage1(4 downto 0) <= stage2(4 downto 0) when val(1) = '1' else
4
                      stage2(6 downto 2);
5
6
stage0(3 downto 0) <= stage1(3 downto 0) when val(0) = '1' else
7
                      stage1(4 downto 1);
8
9
c <= stage0;

Beim Profi-Shifter kannst du jetzt recht simpel damit anfangen die 
einzelnen Stufen zu registern.

von Harald F. (hfl)


Lesenswert?

Hmmm, ich würde gern nochmal vorne einsteigen:

----(snip)----
angenommen ich habe ein Feld mit 200 Werten

reg signed [7:0] feld [0:199];

Nun möchte ich Elemente dieses Feldes für Verarbeitungen nutzen z.B.
möchte ich je zwei Elemente von 10 aufeinanderfolgenden Werte
vergleichen die von einer zuvor bestimmten Variable var_1 abhängen.
----(snap)----

Dein Feld alleine belegt ja schonmal 200*8=1600 LUTs und wenn es sich 
hier nicht um eine Übungsaufgabe handelt, dann ist hierfür ein RAM 
empfehlenswert, denn in einm Takt ... vergiss es. Und wenn erst 10 Bytes 
zusammengenommen einen Wert ergeben, dann bräuchtest Du ja einen 
80-Bit-Vergleicher. In einem Takt? Vegiss es. Also 10 Takte für den 
Vergleich von zwei Elementen, wobei es wichtig wäre, zu wissen, in 
welcher Reihenfolge die Daten im Feld liegen. Evtl kann man schon nach 
dem erste Vergleich wissen, was Sache ist, und muss nicht alle 10 Bytes 
vergleichen (bzw. aus dem RAM lesen und vergleichen). Kannst Du mir 
folgen?

Grüße,
Harald

von gunni (Gast)


Lesenswert?

@Petger

ich muss nochmal nachhaken. ich habe das so verstanden das ich den bit 
shifter dazu benutze das Feldelement auszuwählen richtig? In wie fern 
unterscheidet sich die direkte Implementierung mittels Bit shifter von 
einem Konstrukt wie feld[var_1+j] oder ähnlichem? Ich dachte die 
Synthese macht daraus so etwas oder kann man nicht davon ausgehen oder 
ist diese Variante sehr viel Ressourcenschonender?


@Hfl


Ich habe das Feld so vorliegen und ich möchte quasi ab dem Feldelement 
mit dem Index var_1 nachprüfen ob das jeweils nächste Feldelement größer 
ist das vorherige, wenn ja kann dort auch die Bearbeitung beendet werden 
( nicht immer alle 10 notwendig). Allerdings fehlt mir ein Ansatz wie 
ich diese Feldelemente abhängig von var_1 ressourcenschonend "anwähle" 
und wie ich dieses Problem auf mehere Takte aussplitten kann.


Danke für die Hilfe ich hoffe die Fragen sind nicht zu verwirrend :)

von Lattice User (Gast)


Lesenswert?

gunni schrieb:
> Ich habe das Feld so vorliegen und ich möchte quasi ab dem Feldelement
> mit dem Index var_1 nachprüfen ob das jeweils nächste Feldelement größer
> ist das vorherige, wenn ja kann dort auch die Bearbeitung beendet werden

Genau hier liegt der typische Denkfehler eines bisherigen 
Softwareentwicklers.

In Verilog/VHDL erzeugt eine for-Schleife parallele Hardware, diese muss 
immer alle 10 Elemente umfassen, beim Erzeugen der HW (Synthese) stehen 
ja die Eingangsdaten noch gar nicht fest. Es spart also gar nichts die 
"Bearbeitung vorher abzubrechen", denn es gibt kein vorher.

von Petger (Gast)


Lesenswert?

gunni schrieb:
> @Petger
>
> ich muss nochmal nachhaken. ich habe das so verstanden das ich den bit
> shifter dazu benutze das Feldelement auszuwählen richtig? In wie fern
> unterscheidet sich die direkte Implementierung mittels Bit shifter von
> einem Konstrukt wie feld[var_1+j] oder ähnlichem? Ich dachte die
> Synthese macht daraus so etwas oder kann man nicht davon ausgehen oder
> ist diese Variante sehr viel Ressourcenschonender?
>

Und wie willst du bei deiner Varianten Registerstufen einfügen? Gerade 
bei Konstrukten die am das Timing drücken, musst du punktgenau bestimmen 
können wie du die Logik verteilst.

Hast du dein Problem denn mittlerweile gelöst?

von Harald F. (hfl)


Lesenswert?

nochmalnachdenk

Also wahrscheinlich würde ich das so angehen: Ich würde mir so ein Modul 
bauen:

module compare
    (
    input  wire         clk_i,
    input  wire         rst_i,
    input  wire [79:0]  a_i,
    input  wire [79:0]  b_i,
    input  wire         start_i,
    output wire         done_o,
    output wire         a_greater_b_o,
    output wire         a_equal_b_o
    );

Dieses Modul enthält einen Zustandsautomaten für den Vergleich der 
beiden 80-Bit-Werte. Darüber würde ich dann ein zweites Modul bauen, das 
aus dem großem Vektor die beiden zu vergleichenden Teile per Multiplexer 
auswählt und den Vergleich anstößt. Ein Takt für die Übernahme der zu 
vergleichenden Werte, 1 bis 9 Takte für den Vergleich eines 
80-Bit-Wertepaares, ein Takt für die Übernahme des nächsten Paars ...

Oder so ähnlich.

Grüße,
Harald

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.