Forum: FPGA, VHDL & Co. Verilog for Schleife


von hans (Gast)


Lesenswert?

Hallo


ich habe mal eine Frage zur Verilog for schleife.

Ich möchte von einem Feld die Feldelemente nacheinander auslesen dabei 
ist die reihenfolge wichtig.
Die for Schleife wird ja paralell ausgeführt ist es nun so das es bei 
blocking assignments trotzdem die reihenfolge der for schleife 
eingehalten wird oder ist die abfolge beliebig. Wenn beliebig wie kann 
ich ohne große FSM erreichen das diese in richtiger Reihenfolge 
ausgeführt werden. Gibt es einen Trick?

1
for(i=0;i<steps;i=i+1) begin
2
3
4
      for(j=0;j<((psd_max-psd_min)/psd_intervall)+1;j=j+1) begin 
5
          
6
      if(psd[i]<=(psd_max-j*psd_intervall + 0.5*psd_intervall) && psd[i] > psd_max - (j+1)*psd_intervall + 0.5*psd_intervall) begin
7
      
8
                counter[j]=counter[j]+1;
9
      end // end if
10
      
11
      
12
  
13
      end // end j
14
15
end // end i

Diese for Schleife wird z.b. auf eine postitive Flanke ausgeführt. Wie 
kann ich zusätzlich ein Signal auf high setzen sobald die for Schleife 
komplett durchgelaufen ist?


wenn ich einfach trigger=1; darunter setze kann es doch sein das es vor 
dem letzten Befehl der Schleife ausgeführt wird ?

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


Lesenswert?

hans schrieb:
> 0.5*psd_intervall
Ich mache zwar normalerweise VHDL, trotzdem frage ich:
Geht das tatsächlich?

> Diese for Schleife wird z.b. auf eine postitive Flanke ausgeführt.
Die wird gar nicht ausgeführt, sondern die wird "aufgerollt" und ist 
parallel da, und deshalb bekommst du auch ein RAM, das für jedes Bit 
eine eigene Datenleitung haben muss. Das ist aber eine recht unübliche 
Bauform von RAM...

von Lattice User (Gast)


Lesenswert?

Lothar Miller schrieb:
>> Diese for Schleife wird z.b. auf eine postitive Flanke ausgeführt.
> Die wird gar nicht ausgeführt, sondern die wird "aufgerollt"

Ohne "generate" wird in Verilog 2001 nix aufgerollt. So wie es dasteht 
ist es nicht synthesierbar.

von hans (Gast)


Lesenswert?

hey

ich benutze SystemVerilog geht es dort ohne generate?

aber mal generell wenn es aufgerollt ist wird das dann nach reihenfolge 
oder beliebig durchgeführt?

und wie bekomme ich es hin das nach den ganzen befehen der for schleife 
ich dann ein done signal auf high setze ich bräuchte da mal einen 
anstoß?


Danke

von Stachele (Gast)


Lesenswert?

>ich benutze SystemVerilog geht es dort ohne generate?

Mit welchem Tool synthetisierst du das?

von hans (Gast)


Lesenswert?

Quartus 2 von Altera

von auch Hans (Gast)


Lesenswert?

Lattice User schrieb:
> Ohne "generate" wird in Verilog 2001 nix aufgerollt. So wie es dasteht
> ist es nicht synthesierbar.

Also soweit ich weiß wird eine for-Schleife in einem getaktetem 
always-Block durchaus durch Loop-Unrolling aufgelöst.
Es sieht ja so aus, als würden i und j jeweils in Einer-Schritten erhöht 
und das Ergebnis eines Schleifendurchlaufs hat keinerlei Rückwirkung auf 
den nächsten Durchlauf. Das Ergebnis sollte exakt dem einer 
sequentiellen Abarbeitung der Schleifen entsprechen, später aber in 
Hardware parallel erfolgen.
Wofür brauchst du das trigger-Signal? Die Schleife wird in jedem Takt 
komplett abgearbeitet. Die ist dann immer fertig, wenn der Always-Block 
beendet ist.

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


Lesenswert?

hans schrieb:
> geht es dort
Nein, es gibt kein solches Bauteil: ein RAM, das ALLE Bits einzeln an 
eine Leitung heruasgeführt hätte.
Oder doch ja: indem jedes Bit einzeln ein "richtiges" Flipflop einer 
Logikzelle auffrisst...   :-o

von auch Hans (Gast)


Lesenswert?

Lothar Miller schrieb:
> Nein, es gibt kein solches Bauteil: ein RAM, das ALLE Bits einzeln an
> eine Leitung heruasgeführt hätte.
> Oder doch ja: indem jedes Bit einzeln ein "richtiges" Flipflop einer
> Logikzelle auffrisst...   :-o

Hat ja auch keiner was von 'nem RAM erzählt. Keine Ahnung was das für 
eine Logikwolke wird. Sinnig ist es evtl. nicht. Habe aber keine Ahnung 
wie groß es werden soll. Evtl sind das ja nur 10 oder 20 Bit. Die Frage 
ist ja auch nicht ob es Resourcen schont, sondern wofür das 
trigger-Signal sein soll, und wann das Ergebnis fertig berechnet ist.

von hans (Gast)


Lesenswert?

Also,


ich habe ein Array mit verschiedenen Werten. In einem ersten Schritt 
soll das Array in der hinsicht ausgewertet werden, dass gezählt wird wie 
oft ein bestimmter wert vorkommt. ( z.b. 2x die 5 , 1x die 7 usw). Dabei 
ruf ich diese Verarbeitung aus einer Statemachine auf die auch die 
weiteren verarbeitungsschritte aufruft. Der trigger done soll hierzu als 
transitionsbedingung für diese FSM herhalten. Es soll also 
weitergeschalten werden wenn der Prozess beendet ist.

Ich gehe davon aus das es vielleicht länger als ein Clockcycle (150Mhz) 
dauert darum der Trigger.

Wird nun beim unrolling der for schleife eine reihenfolge festgelegt 
oder wird es bei jedem durchlauf zu einer beliebigen abfolge kommen? Es 
ist ja nicht direkt paralell da ich blocking assignments verwende oder 
verstehe ich das falsch?
Kann man das irgendwie erreichen das es nach einer bestimmten 
Reihenfolge geht ( so wie im simulator)? Das wäre für einen weiteren 
Arbeitschritt gut wo ich ein Array daraufhin untersuchen will wie lange 
ein bestimmter Wert gleich bleibt. Dazu muss es ja nacheinander 
abgefragt werden. gibt es da einen guten Ansatz ohne eine riesige FSM zu 
schreiben?


Danke

von auch Hans (Gast)


Lesenswert?

Also wenn du eine Schleife hast, dann wird die so abgearbeitet wie du 
sie hinschreibst. Innerhalb der Schleife werden keine Laufzeitprobleme 
auftauchen. Das Synthesetool wird die Schleife so zerpflücken, daß es 
passt. Und wenn das von der Geschwindigkeit her nicht passt, dann wird 
dir das Synthesetool schon sagen wo es nicht klappt. Einfach nur einen 
trigger zu setzen hilft da doch nichts...woher soll der denn wissen, daß 
die Berechnung länger dauert.

von hans (Gast)


Lesenswert?

Was meine Frage ist wird immer zuerst j=0 abgearbeit dann J=1 oder kann 
es auch zuerst j=5 und dann j=3 sein. Das ist mir nicht ganz klar ob die 
logische Reihenfolge auf dem FPGA eingehalten wird. Und das done Signal 
möchte ich gerne nachdem die Schleifen zu Ende sind setzen das ich genau 
weiss es ist fertig, sonst kann es dazu kommen das meine FSM, wenn die 
Bearbeitung der Schleifen länger als 1 Clockcycle dauert, schon 
weiterspringt ohne das ich das will.




falls jemand ressourcenschonendere Ansätze für dieses Problem hat wäre 
ich auch dankbar :D

von auch Hans (Gast)


Lesenswert?

Du kannst nicht einfach ein Bit setzen, wenn die Schleife fertig ist. 
Die Schleife wird zu kombinatorischer Logik. Die ist irgendwann fertig. 
Dann sagt dir dein Timing Analyzer später ob es in einen Taktzyklus 
passt (wenn du die richtigen Constraints gesetzt hast). Aber es ist im 
Design keinerlei Information enthalten, wann die Kombinatorische Logik 
fertig ist.
Der Takt "guckt" ja nur zu festen Zeitpunkten auf die Logik und tastet 
die Werte ab. Wenn das Timing passt, ist die Logik zu den Flanken fertig 
mit berechnen. Ansonsten nicht... Der Takt muß dann halt langsam genug 
sein.

von hans (Gast)


Lesenswert?

Aber falls es  nicht in einen takt passt könnte ich ja auch 2 warten bis 
die FSM schaltet.


Geht folgendes auf dem FPGA?

ich lass in der einen for schleife eine weitere Variable p hochzählen 
und füge dem alwqays block folgendes hinzu. Dann würde er doch wenn die 
Schleife druch ist zur nächsten Taktflanke den Trigger setzen oder?

1
@(posedge(clk)) begin
2
3
  if(p==loop_max) begin
4
     trigger_done=1;
5
  end
6
end

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


Lesenswert?

Weil die Schleife sowieso in jedem Takt komplett abgearbeitet wird, wird 
in jedem Takt das done gesetzt werden...

Probiers doch einfach mal aus, und sieh dir den RTL Plan an.

von Lattice User (Gast)


Lesenswert?

auch Hans schrieb:
> Lattice User schrieb:
>> Ohne "generate" wird in Verilog 2001 nix aufgerollt. So wie es dasteht
>> ist es nicht synthesierbar.
>
> Also soweit ich weiß wird eine for-Schleife in einem getaktetem
> always-Block durchaus durch Loop-Unrolling aufgelöst.

Ok, ich habe es ausprobiert.
Wird tatsächlich ausgerollt, man lernt nie aus.
Wobei es egal ist ob getaktet oder nicht, innerhalb eines always 
constructs wird ausgerollt.

von hans (Gast)


Lesenswert?

Ok die Schleife wird in jedem takt abgearbeit aber kann es durch delays 
usw dazu kommen das es nicht geschafft wird? wäre es dann nicht besser 
so eine Sicherung einzubauen ?


Und hat noch jemand einen Ansatz wie man es am elegantesten löst in 
einem  feld danach zu suchen wie lange einer bestimmter Wert sich 
wiederholt? Das lässt mit so einer for schleife doch schlecht 
realisieren oder denk ich heir total falsch?



Danke für die zahlreichen Antworten

von Lattice User (Gast)


Lesenswert?

hans schrieb:
> Ok die Schleife wird in jedem takt abgearbeit aber kann es durch delays
> usw dazu kommen das es nicht geschafft wird? wäre es dann nicht besser
> so eine Sicherung einzubauen ?

Nochmal, hier wird nichts abgearbeitet. Vergiss die Softwaredenkweise.

Ausrollen der Schleifen bedeutet, dass für jedes i und j kombinatorische 
Hardware erzeugt wird. Das wird sehr schnell gross und damit langsam. 
Bei 10 steps und 10 intervallen sind da schon 200 Vergleicher fällig.

Ausserdem müssen natürlich die Schleifenkontrollvariablen (steps, psd_ ) 
zur Synthesezeit feststehen.

von Harald F. (hfl)


Lesenswert?

hans schrieb:
> Und hat noch jemand einen Ansatz wie man es am elegantesten löst in
> einem  feld danach zu suchen wie lange einer bestimmter Wert sich
> wiederholt? Das lässt mit so einer for schleife doch schlecht
> realisieren oder denk ich heir total falsch?

Hallo Hans,
Ja, ich glaube schon, dass Du da falsch herangehst. Der Gedanke "ich 
gehe das Feld Element für Element durch" zeugt von einem sequenziellen 
Ansatz, mithin Software. Und wenn Du genau das in Hardwar machen willst, 
dann müsstest Du schon dafür Sorgen, dass "irgendjemand" das Feld 
Element für Element durchsucht. Dafür müsstest Du dir einen Automaten 
bauen (auch state machine genannt), der ein Elemente nach dem anderen 
auswählt (= Multiplexer) und dann die gewünschre Operation mit dem Wert 
macht (=Vergleicher). Die Bearbeitung dauert dann genau soviele Takte, 
die das Feld Elemente hat.
Trifft das deinen Wunsch?

Grüße,
Harald

von hans (Gast)


Lesenswert?

Lattice User schrieb:
> Nochmal, hier wird nichts abgearbeitet. Vergiss die Softwaredenkweise.
>
> Ausrollen der Schleifen bedeutet, dass für jedes i und j kombinatorische
> Hardware erzeugt wird. Das wird sehr schnell gross und damit langsam.
> Bei 10 steps und 10 intervallen sind da schon 200 Vergleicher fällig.

Hallo Lattice User,


das ausrollen der Schleife ist mit klar aber im Zusammenhang mit den 
blocking assignsments wie verfällt sich das in Hardware? Das bedeutet 
doch das diese "Anweisungen" hintereinander geschaltet werden da sie 
sich ja blockieren bis eins fertig ist, dann das nächste usw. Versteh 
ich das mit der Hintereinanderschaltung richtig und wenn ja welche 
reihenfolge wird da genommen (beliebig?) und wenn nein wie verhält sich 
das dann nun mit den blocking assignments vielleicht versteh ich die 
einfach nur falsch.


Danke

von Harald F. (hfl)


Lesenswert?

hans schrieb:
> und wenn nein wie verhält sich
> das dann nun mit den blocking assignments vielleicht versteh ich die
> einfach nur falsch.

Hallo Hans,

ich bin zwar nicht Lattice User, aber zum Thema blocking assignments 
kann ich 'was sagen. Bei der Synthese der Schaltung ist blocking / 
non-blocking im allgemeinen irrelevant. Kein Synthesetool kümmert sich 
dadrum, und wenn, dann nur um eine Fehlermeldung auszugeben, dass die 
gleiche Variable nicht einmal blocking und einmal non-blocking benutzt 
werden kann. Blocking und non-blocking sind nur für die Simulation 
relevant. Der erfahrere Verilog-Anwender nutzt die beiden 
Zuweisungsarten außerdem um anzuzeigen, was er modellieren will. Zum 
Beispiel non-blocking bei sequenzieller Logik, blocking bei 
kombinatorischer Logik.

Grüße,
Harald

von Stachele (Gast)


Lesenswert?

1. Wieviele Einträge willst Du maximal durchsuchen können?
2. Wie hoch ist fMAX?

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Harald Flügel schrieb:
> Bei der Synthese der Schaltung ist blocking / non-blocking im allgemeinen
> irrelevant. Kein Synthesetool kümmert sich
> dadrum, und wenn, dann nur um eine Fehlermeldung auszugeben, dass die
> gleiche Variable nicht einmal blocking und einmal non-blocking benutzt
> werden kann. Blocking und non-blocking sind nur für die Simulation
> relevant.

Das Verhalten kann sich schon erheblich unterscheiden. Gäbe es im 
Schleifenrumpf durch die blocking assignments Abhängigkeiten zwischen 
den Iterationen, also beispielsweise:
1
if (j > 0)
2
   counter[j]=counter[j-1]+1;
3
else
4
   counter[j]=counter[j]+1;
Dann muss das auch vom Synthesetool berücksichtigt werden.

Gruß
Marcus

von hans (Gast)


Lesenswert?

Hallo harald,


Danke für die Antwort das war mit überhaupt nicht klar gewesen, dass es 
bei der Synthese keinen Unterschied macht.


Was ich mich frage ich lasse ja in den for Schleifen Zähler hochzählen 
falls mehere Werte den selben Zhalenwert haben. Bei der paralellen 
Verarbeitung auf dem FPGA kommen dann trotzdem richtige Werte raus(ein 
wird ja auf ein zähler mehrfach zugegriffen) wie in der Simulation oder 
kann ich das vergessen wenn ja wie realisiert man das dann 
sythetisierbar (Statemachine?)?





Danke

von hans (Gast)


Lesenswert?

Stachele schrieb:
> 1. Wieviele Einträge willst Du maximal durchsuchen können?
> 2. Wie hoch ist fMAX?

ich möchte max 300 Werte durchsuchen beo 150Mhz

von auch Hans (Gast)


Lesenswert?

Harald Flügel schrieb:
> zum Thema blocking assignments
> kann ich 'was sagen. Bei der Synthese der Schaltung ist blocking /
> non-blocking im allgemeinen irrelevant. Kein Synthesetool kümmert sich
> dadrum, und wenn, dann nur um eine Fehlermeldung auszugeben, dass die
> gleiche Variable nicht einmal blocking und einmal non-blocking benutzt
> werden kann.

Das würde ich mal bezweifeln...
Folgende Codebeispiele sollte vom Synthesetool schon nicht gleich 
behandelt werden:
1
always @(posedge clk) begin
2
   a <= a + 1;
3
   a <= a + 1;
4
end
5
6
always @(posedge clk) begin
7
   a = a + 1;
8
   a = a + 1;
9
end

Erster Fall wäre wirklich a = a + 1, der zweite ja wohl eher a = a +2.

hans schrieb:
> Ok die Schleife wird in jedem takt abgearbeit aber kann es durch delays
> usw dazu kommen das es nicht geschafft wird? wäre es dann nicht besser
> so eine Sicherung einzubauen ?

Deine Sicherung ist der Timing Analyzer. Der sagt dir ob es in einen 
Taktzyklus passt. Wenn ja, dann passt es immer. Wenn nein, dann mußt du 
das manuell so hinbiegen und mehrere Takte warten, bis es passt. Mit 
entsprechenden Timing Constraints sagt dir dann der Timing Analyzer auch 
wieder ob es passt oder nicht.

Ich glaube du solltest dir mal ein paar Grundlagen des digitalen 
Schaltungsdesigns anlesen. Sonst wird das alles niemals laufen.

von Harald F. (hfl)


Lesenswert?

auch Hans schrieb:
> Erster Fall wäre wirklich a = a + 1, der zweite ja wohl eher a = a +2.

Hallo auch Hans,

Ich stelle fest, dass meine langjährige Erfahrung mit Synthesetools 
aufgefrischt werden muss. Ich habe deine Beispiele mal durchlaufen 
lassen und - Wunder über Wunder - im zweiten Fall zählt der Zähler 
tatsächlich bei jedem Takt um zwei weiter. Wow!

Aber was sagt uns das? Synthesetools werde immer trickreicher. Ist das 
gut? Bin mir nicht sicher. So ein Ausdruck wie

always @(posedge clk) begin
   a = a + 1;
   a = a + 1;
end

sollte meiner Meinung nach vermieden werden, denn er legt die Vermutung 
nahe, dass es einen Zeitpunkt gibt, zu dem die Variable a um 1 
hochgezählt wurde. Diesen Zeitpunkt gibt es aber nicht. Blocking 
assignments haben IMHO bei sequenzieller Logik nix verloren. Andere 
Meinungen?

von Stachele (Gast)


Lesenswert?

>ich möchte max 300 Werte durchsuchen beo 150Mhz

Wieviele Bits hat ein Wert?

von hans (Gast)


Lesenswert?

8 bit


Hallo Harald,


ich habe in deinem Buch gelesen das zwischen begin und end die 
reihenfolge der anweisungen berücksichtigt wird ist das nur in der 
simulation so oder auch real auf dem fpga?


Falls hier fragen die ich stelle für euch redundant oder einfach nur 
dumm erscheinen möchte ich mich hiermit entschuldigen ich starte gerade 
mit verilog und habe wenig erfahrung bis auch die bücher die ich 
angerissen habe. ein großen problem für mich ist was ist nur für die 
simulation und was synthetisierbar gibt es da irgendein gutes 
nachschlagewerk?



Danke

von SuperWilly (Gast)


Lesenswert?

>das zwischen begin und end die reihenfolge der anweisungen berücksichtigt >wird


Aus "A Verilog HDL Primer":

A blocking procedural assignment is executed before any of the 
statements that follow it are executed, that is, the assignment 
statement is executed completely before the next statement is executed.


Das verhält sich in Verilog also so wie mit Variablen in VHDL.

Meiner Meinung nach gilt dies für Simulation und Synthese gleichermaßen!


VG, SuperWilly

von Stachele (Gast)


Lesenswert?

>In einem ersten Schritt soll das Array in der hinsicht ausgewertet werden, >dass 
gezählt wird wie oft ein bestimmter wert vorkommt.

Kannst du nicht schon beim Schreiben des Wertes überprüfen, um welche 
Zahl es sich handelt (0.255) und statt des Wertes einen Zählerwert (der 
angibt, wie oft die Zahl vorkommt) in das Array in die entsprechende 
Adressposition schreiben?

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


Lesenswert?

Lothar Miller schrieb:
>> 0.5*psd_intervall
> Geht das tatsächlich?
Kapiert der Compiler das? Und lässt automatisch das LSB wegfallen?

von auch Hans (Gast)


Lesenswert?

Lothar Miller schrieb:
> Kapiert der Compiler das? Und lässt automatisch das LSB wegfallen?

Der Compiler sollte hier automatisch den kompletten Vergleich im 
Real-Datentyp berechnen. Bei Verilog werden in Expressions alle Werte 
implizit in Real umgewandelt, sobald ein Real-Datentyp in der Expression 
vorkommt (jedenfalls in diesem Fall, sonst gibt es da einige Ausnahmen).
Was die Synthese daraus macht weiß ich nicht. Könnte mir auch 
vorstellen, daß der Hans das noch nie synthetisiert hat.

von auch Hans (Gast)


Lesenswert?

Harald Flügel schrieb:
> So ein Ausdruck wie
>
> always @(posedge clk) begin
>    a = a + 1;
>    a = a + 1;
> end
>
> sollte meiner Meinung nach vermieden werden, denn er legt die Vermutung
> nahe, dass es einen Zeitpunkt gibt, zu dem die Variable a um 1
> hochgezählt wurde. Diesen Zeitpunkt gibt es aber nicht. Blocking
> assignments haben IMHO bei sequenzieller Logik nix verloren. Andere
> Meinungen?

Ich habe anfänglich mal solche Konstrukte benutzt um temporäre Variablen 
innerhalb eines Blocks zu erzeugen. Ähnlich wie bei VHDL die Variables 
benutzt werden. Macht aber alles nur unübersichtlich. Daher bin ich dazu 
übergegangen alles was rein kombinatorisch ist über assign-Anweisungen 
oder über rein kombinatorische always @(*) Blöcke (dort auch mit 
blocking assignment) zu machen und dann das Ergebnis innerhalb 
getakteter Blöcke zu weiter zu verwenden.

von Harald F. (hfl)


Lesenswert?

Der Thread entwickelt sich wirklich interessant! Dem Hans gebührt Dank 
dafür, und, nein, Du musst dich auf ger keinen Fall dafür entschuldigen. 
Es ist nunmal so, dass man heutzutage viel in Software macht, früh C 
lernt, dabei die sequenzielle Denkweise inhaliert und sich dann wundert, 
dass das im FPGA alles anders geht.

Mit persönlich hat beim FPGA-Design am ehesten geholfen, mich auf das zu 
konzentrieren, was ich im Studium der Digitaltechnik gelernt habe: Es 
gibt kombinatorische Logik und sequenzielle Logik. Mehr nicht. Dafür 
schreibe ich ein Modell in VHDL oder Verilog. Alles was ich schreibe, 
muss zu einer dieser beiden Logiken passen. Der "auch Hans" hat das sehr 
passend beschrieben, dem gibt's nichts hinzuzufügen. Außer vielleicht, 
dass Lothar (wie immer) auch recht hat, wenn er auf die Grenzen 
hinweist. Der Datentyp real ist für die Synthese im allgemeinen nicht 
geeignet. Wenn in deinem Feld Fließkommazahlen stehen, dann wird das 
deutlich aufwändiger. Muss das sein?

von hans (Gast)


Lesenswert?

Stachele schrieb:
> Kannst du nicht schon beim Schreiben des Wertes überprüfen, um welche
> Zahl es sich handelt (0.255) und statt des Wertes einen Zählerwert (der
> angibt, wie oft die Zahl vorkommt) in das Array in die entsprechende
> Adressposition schreiben?

Ich bekomme das Feld aus dem Speicher ich weiss also vorher nicht was 
drin ist.


Zu den 0.5*psd_intervall. ich möchte bei der abfrage einfach garantieren 
das um +- dem intervall/2 die Werte aus dem Feld als ein Wert erkannt 
werden der den zähler hochzählt.

z.b. wenn das intervall 10 und psd_max 30 ist und der Wert im Feld 22 
dann soll der zähler bei 22 den Counter für 20 hochzählen.

Ich weiss jetzt nicht genau wo das Probem ist liegt es an den 0.5 das es 
eien Komamzahl ist wäre das mit /2 erledigt oder liegt es generell am 
multiplizieren das habe ich einfach von folgendem Tutorial.

http://www.asic-world.com/verilog/operators1.html#Arithmetic_Operators


Ich habe auch im Moment das FPGA dev board nicht da kann ich noch anders 
überorüfen was bei der Synthese rauskommt meinen Erwartungen entspricht 
als es auf dem FPGA laufen zulassen?

von auch Hans (Gast)


Lesenswert?

hans schrieb:
> Ich weiss jetzt nicht genau wo das Probem ist liegt es an den 0.5 das es
> eien Komamzahl ist wäre das mit /2 erledigt oder liegt es generell am
> multiplizieren das habe ich einfach von folgendem Tutorial.

Die Problematik ist, daß du mit einem Real-Datentyp rechnest. Das ist 
alles nicht synthesefähig (soweit ich weiß). Wenn du durch zwei teilst 
rundest du natürlich das Ergebnis. Muß dir halt klar sein. Ist das 
Interval 11 wird aus 0.5 * psd_interval eine 5.5, psd_interval / 2 wird 
aber zu 5.

Mal ne andere Frage:
Sind psd_max, psd_min uns psd_intervall eigentlich konstant? Wenn die 
Werte nämlich nicht zum Synthesezeitpunkt berechenbar und konstant sind, 
kann die for-Schleife nicht synthetisiert werden.

Hast du denn überhaupt schonmal eine Synthese gestartet? Brauchst ja 
kein FPGA Board um zu gucken ob die Synthese überhaupt läuft.

von hans (Gast)


Lesenswert?

Ja habe das schon synthetisiert da hat er keine Fehler erzeugt 
allerdings hatte ich zu dem Zeitpunkt das module noch nicht im top-level 
integriert (optimiert er es dann weg?).  Die größe der for Schleife 
steht vorher fest.

von SuperWilly (Gast)


Lesenswert?

Das Zauberwort lautet: "CAM" auf Embedded-RAM-Basis

Dann klappt es auch in einem Takt. Altera bietet im Megawizard-Manager 
soetwas doch an.


Die Treffer-Maske musst du dann noch selber auswerten.


VG, SuperWilly

von auch Hans (Gast)


Lesenswert?

hans schrieb:
> allerdings hatte ich zu dem Zeitpunkt das module noch nicht im top-level
> integriert (optimiert er es dann weg?).

Ja. Was nirgendwo im Design drin ist wird auch nicht Synthetisiert.

von Harald F. (hfl)


Lesenswert?

@hans

Also ein Board brauchst Du nicht um zu prüfen, ob eine Beschreibung 
synthetisierbar ist. Das geht auch ohne.

Und was deine Schaltung angeht, so würde ich da so vorgehen (unter der 
Voraussetzung, dass keine Fließkommazahlen verwendet werden).

1. Ein Zähler adressiert den Speicher. Dieser gibt die gespeicherten 
Werte sequenziell aus.
2a. Jeder Wert wird zeitgleich an eine Reihen von 
größer/kleiner-Vergleichern angelegt. Damit bekommt man in einem Rutsch 
raus, in welchem Intervall der Wert liegt. Der zugehörige Zähler wird 
erhöht. Zeitgleich wird der Adresszähler für den Speicher erhöht.
2b. Alternativ kann man den Schritt 2 auch sequenziell machen indem man 
nur ein Vergleicherpaar verwendet und mittels eines zweiten Zähler die 
Grenzen variiert. Dauert länger, braucht dafür weniger Logikzellen.

Meiner Erfahrung nach muss man sich den Ablauf wenigstens soweit wie 
oben beschrieben überlegen und dann modellieren. Deine zwei 
geschachtelte for-Schleifen beschreiben den Algorithmus, aber die 
Abbildung auf die Takte einer kombinatorischen Logik, die nimmt einem 
kein Tool ab.

von hans (Gast)


Lesenswert?

Also versteh ich das richtig,


Ich lasse einen Zähler jeden Taktschritt @(posedge clk) eins hochzählen 
nehme das zugehörige Feldelement und vergleiche es z.b in dem ich eine 
forschleife dafür benutze um die Vergelicher zu erstellen. Das heisst 
ich brauche dann ca soviele Takte zeit wie ich Feldelemente habe oder?

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


Lesenswert?

hans schrieb:
> ich brauche dann ca soviele Takte zeit wie ich Feldelemente habe oder?
Ja, und dann hätte ich das RAM, auf das ich so sehnlich warte...  ;-)

von SuperWilly (Gast)


Lesenswert?

>ich brauche dann ca soviele Takte zeit wie ich Feldelemente habe oder?

Wenn du eine CAM-Struktur verwendest -> 1 Takt


;-) SuperWilly

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


Lesenswert?

SuperWilly schrieb:
> Wenn du eine CAM-Struktur verwendest
Und die Ressourcen übrig hast....

> Wenn du eine CAM-Struktur verwendest
Und mit der resultierenden geringen Taktfrequenz leben kannst...

> Wenn du eine CAM-Struktur verwendest
Und den Bedarf dafür hast...

von SuperWilly (Gast)


Lesenswert?

>Und mit der resultierenden geringen Taktfrequenz leben kannst...

Das Ding fluppt ganz schön performant ;-)


VG, SuperWilly

von SuperWilly (Gast)


Lesenswert?

>Und den Bedarf dafür hast...

Der ist ja anscheinend gegeben

von SuperWilly (Gast)


Lesenswert?

Was für ein Altera-FPGA soll es denn werden?

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Harald Flügel schrieb:
> Aber was sagt uns das? Synthesetools werde immer trickreicher. Ist das
> gut? Bin mir nicht sicher.

Ein Synthesetool, dass sich in dieser Situation anders verhält ist nicht 
weniger trickreich, sondern fehlerhaft.

Gruß
Marcus

von hans (Gast)


Lesenswert?

1
always @(posedge start_compare) begin
2
3
compare_done=0;
4
counter='{counter_quantity+1{0}};
5
for(i=0;i<steps;i=i+1) begin
6
7
   
8
      for(j=0;j<((psd_max-psd_min)/psd_intervall)+1;j=j+1) begin 
9
          
10
      if(psd[i]<=(psd_max-j*psd_intervall + psd_intervall/2) && psd[i] > psd_max - (j+1)*psd_intervall + psd_intervall/2) begin
11
      
12
                counter[j]=counter[j]+1;
13
      end // end if
14
      
15
      
16
  
17
      end // end j
18
    p=p+1;
19
end // end i
20
21
22
  
23
  if(p==steps) begin  
24
    compare_done=1;
25
   p=0;
26
   end
27
 
28
29
end // end always


ich haeb diesen Code jetzt auf meinen  FPGA gebracht und er tut was er 
soll. Ich benutze compare_done als trigger um dann meine FSM 
weiterzuschalten. Ich denek das ist ziehmlich c ähnlich geschrieben und 
bestimmt nicht perfekt aber komischer weise funktionirt es.

Muss ich bei dieser Programmierweise mit irgendwelchen Problemen rechnen 
? kann man irgendwie testen wielange (zeitlich) die abarbeitung dieses 
Teil dauert oder geht das nur mit einer Timing Analsye? (damit hab ich 
mich noch nicht beschäftigt) Weil ich würde gernen wissen ob diese Art 
länger dauert als wenn ich per Taktcycle immer den Counter hochzähle. 
Vom Ressourcenverbrauch geht es bei mir auch bin jetzt bei 17% habe aber 
schon einiges an Peripherie wie CPU, Speichercontroller usw drinnen.

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


Lesenswert?

hans schrieb:
> Ich denek das ist ziehmlich c ähnlich geschrieben
Soso...

> wielange (zeitlich) die abarbeitung dieses Teil dauert
Ich habe den Verdacht, da steckt 100% Softwaredenkweise hinter dieser 
Frage...

> kann man irgendwie testen wielange (zeitlich) die abarbeitung dieses
> Teil dauert oder geht das nur mit einer Timing Analsye?
Falsche Richtung!
Du sagst der Toolchain mit Timing-Constraints vorher, wie schnell sie 
das machen muss und die versucht dann, das zu realisieren (das Ganze ist 
eh' komplett kombinatorisch, von daher ist das start-Signal eh' für die 
Katz). Wenn sie es nicht schafft, wird sie dir das schon sagen...

hans schrieb:
> Vom Ressourcenverbrauch geht es bei mir auch bin jetzt bei 17%
Welchen Wert haben denn steps, psd_max, psd_min und psd_intervall?

von auch Hans (Gast)


Lesenswert?

Wen ich den code so lese möchte ich nochmal an mein Zitat weiter oben 
erinnern:

auch Hans schrieb:
> Ich glaube du solltest dir mal ein paar Grundlagen des digitalen
> Schaltungsdesigns anlesen. Sonst wird das alles niemals laufen.

compare_done wird immer gesetzt, auch wenn die Logik, die deine 
for-Schleife realisiert noch lange nicht fertig ist. Es bringt nichts, 
hier in einem always-Block eine Variable zu setzen, um anzuzeigen wenn 
etwas fertig ist. Woher sollen denn die Gatter im FPGA, die das done 
setzen, wissen, wann der andere Teil der Schaltung fertig ist?

von auch Hans (Gast)


Lesenswert?

Lothar Miller schrieb:
> (das Ganze ist
> eh' komplett kombinatorisch, von daher ist das start-Signal eh' für die
> Katz).

Ist es nicht noch schlimmer? Das ganze wird mit dem start-Signal 
getaktet.

von hans (Gast)


Lesenswert?

auch Hans schrieb:
> compare_done wird immer gesetzt, auch wenn die Logik, die deine
> for-Schleife realisiert noch lange nicht fertig ist. Es bringt nichts,
> hier in einem always-Block eine Variable zu setzen, um anzuzeigen wenn
> etwas fertig ist. Woher sollen denn die Gatter im FPGA, die das done
> setzen, wissen, wann der andere Teil der Schaltung fertig ist?

Wird durch die blocking assignments nicht alle anderen solange blockiert 
bis eins fertig ist?

Lothar Miller schrieb:
> Du sagst der Toolchain mit Timing-Constraints vorher, wie schnell sie
> das machen muss und die versucht dann, das zu realisieren (das Ganze ist
> eh' komplett kombinatorisch, von daher ist das start-Signal eh' für die
> Katz). Wenn sie es nicht schafft, wird sie dir das schon sagen...


Wie sieht so eine contraint ungefähr aus hast du dafür ein Beispiel?
kannst du das bitte noch etwas näher erläutern warum das start signal 
für die katz ist?


Danke

von auch Hans (Gast)


Lesenswert?

hans schrieb:
> Wird durch die blocking assignments nicht alle anderen solange blockiert
> bis eins fertig ist?

Nein. Es geht da nur um den Zeitpunkt der Zuweisung der Werte an ein 
Signal.
1
reg a = 0;
2
3
always @(posedge clk) begin
4
   a = a + 1;
5
   b = berechne_das_unmoegliche(a);
6
   a = a + 1;
7
end

Nehmen wir das Beispiel oben. a hat am Anfang den Wert 0. Zuerst wird 
eins zu a addiert. Dann wird eine Funktion mit dem aktuellen Wert von a 
(also 1) aufgerufen. Da die das Unmögliche berechnet braucht die in der 
Synthese generierte Logik dafür sehr sehr lange. Danach wird a nochmals 
um eins erhöht. Nach dem Durchlauf würde also gelten a == 2

Nun Beispiel 2:
1
reg a = 0;
2
3
always @(posedge clk) begin
4
   a <= a + 1;
5
   b = berechne_das_unmoegliche(a);
6
   a <= a + 1;
7
end
Zuerst wird a um eins erhöht. Aber jetzt kommt der Trick. Der neu 
berechnete Wert von a wird dem Signal noch nicht zugewiesen. Dann wird 
die Funktion aufgerufen. Da a jetzt aber noch seinen alten Wert hat wird 
der Funktion aber eine 0 übergeben. Und nun wird dem a wieder um eins 
erhöht. Da a aber noch den alten Wert von 0 hat, wird der Simulator auch 
mit dem rechnen. Und er merkt sich wieder den neuen Wert für a. Den bei 
der ersten Addition errechneten Wert vergisst er allerdings.
Und wenn der Block zuende ist wird der neue Wert dem Signal zugewiesen. 
Das wäre in diesem Fall a == 1.

Und jetzt mal grob zu der Schaltung, die aus dem ersten Beispiel aus der 
Synthese rauskommt.

                    Addierer a + 1
                          |
                          |
                -----------------------
                |                     |
       Addierer a + 1         Das Unmögliche(a)
                |                     |
                |                     |
                a                     b

Also es könnten evtl zwei Addierer generiert werden. Und wenn man sich 
das anguckt sieht man, daß kein Pfad von dem Ergebnis von b zu dem 
Ergebnis von a führt. a wird durch zwei hintereinandergeschaltete 
Addierer realisiert. b benötigt einen Addierer und Logik für die 
Funktion. Das bedeutet aber, daß a schneller berechnet werden kann (und 
wird) als b. a hat auch garkeine Informationen über den Zeitpunkt, an 
dem b berechnet wurde.

von Stachele (Gast)


Lesenswert?

> Wird durch die blocking assignments nicht alle anderen solange blockiert
> bis eins fertig ist?

Das wäre eine Super-Funktion, könnte man gut gebrauchen. Quasi ein 
Handshake ...

LOL

von hans (Gast)


Lesenswert?

Danke auch Hans das beispiel hilft mir wirklich weiter.


Das bedeutet also das p immer hochgezählt wird unabhängig von der 2 . 
Schleife diese kann viel länger dauern damit ist das nutzlos und 
compare_done wird imemr 1 gesetzt je nachdem wie lange es dauert p 
hochzuzählen.


Nun haeb ich noch eine frage zum inneren der 2. for schleife. Es wird ja 
jeder psd[i] wert an 2xj vergleicher angelegt. Dabei können ja mehere 
psd[i] in einen Bereich fallen und den selben Counter hochzählen. 
Inwiefern laufen denn diese vergleiche paralell oder laufen diese 
aufgrudn des möglichen Zugriffs auf einen zähler alle hintereinander?

Und zu dem start signal sollte man das einfach weglassen und nur always 
benutzen dann ändern sich die Werte ja sobald sich psd ändert oder?

von Lattice User (Gast)


Lesenswert?

hans schrieb:
> Das bedeutet also das p immer hochgezählt wird unabhängig von der 2 .
> Schleife diese kann viel länger dauern damit ist das nutzlos und
> compare_done wird imemr 1 gesetzt je nachdem wie lange es dauert p
> hochzuzählen.

Du bist immer noch in der Softwaredenkweise.

Die Schleife wird nur bei der Synthese ausgwertet, danach existiert 
parallele kombinatorische Hardware. Die Schleifenzähler gibt es nicht 
mehr. Man kann daher auch nicht davon reden dass die Schleife Zeit 
braucht.

Jedes Ausgangssignal hat eine Verzögerung die von seinen Eingangssignale 
und ihrer Logikverknüpfung abhängt, und das völlig unabhängig von allen 
anderen Ausgangssignalen.
Insbesondere ist die Logikkomplexität deines Done Signals sehr einfach 
und damit schnell.

Wie schnell deine kombinatorische Logik ist kann man nur durch eine 
Timinganalyse bestimmen. Wobei hier der bevorzugte Weg wie schon 
mehrfach erwähnt umgekehrt ist, man gibt die gewünschte Gesschwindigkeit 
vor. Wenns nicht reichen sollte muss man halt die Vorgabe anpassen oder 
sein Konzept überdenken.

von hans (Gast)


Lesenswert?

Lattice User schrieb:
> Du bist immer noch in der Softwaredenkweise.
>
> Die Schleife wird nur bei der Synthese ausgwertet, danach existiert
> parallele kombinatorische Hardware. Die Schleifenzähler gibt es nicht
> mehr. Man kann daher auch nicht davon reden dass die Schleife Zeit
> braucht.

p ist ja in dem fall kein schleifenzähler. Die die synthese wird doch p 
= p+1 genau steps mal(schleife) hintereinander geschaltet da der neue 
ergebnis ja von dem alten abhängt oder verteh ichd as wieder falsch.

Lattice User schrieb:
> Jedes Ausgangssignal hat eine Verzögerung die von seinen Eingangssignale
> und ihrer Logikverknüpfung abhängt, und das völlig unabhängig von allen
> anderen Ausgangssignalen.
> Insbesondere ist die Logikkomplexität deines Done Signals sehr einfach
> und damit schnell.

Das bedeutet also das in meiner 2. for Schleife an jeden Zähler 
(counter[j]) steps x 2 vergleicher ausgangssignale gehen. Die 
vergleicher werden paralell abgearbeitet und jenachdem wie die 
eingangssignale an dem Zähler sind wird der Zähler auf 2 ,3 usw gesetzt?

von Duke Scarring (Gast)


Angehängte Dateien:

Lesenswert?

@hans:

Kann Die Dein Tool nicht mal die generierte Hardware anzeigen?
Xilinx kann das -> Synthesize -> View RTL Schematic

Quartus kann das auch.

Damit bekommst Du vielleicht ein Gefühl dafür, was das Tool aus Deiner 
Beschreibung generiert.

Duke

von Lattice User (Gast)


Lesenswert?

hans schrieb:
> p ist ja in dem fall kein schleifenzähler. Die die synthese wird doch p
> = p+1 genau steps mal(schleife) hintereinander geschaltet da der neue
> ergebnis ja von dem alten abhängt oder verteh ichd as wieder falsch.

p hat für jeden einzelenen Teil der durch die Schleife erzeugten 
Hardware einen vorhersagbaren konstanten Wert. Und nur im letzen Teil 
wird ein Ausgangssignal erzeugt. Die Folge: die ganzen p = p + 1 fallem 
dem Optimizer zum Opfer.

Befolge Dukes Rat und schau dir die erzeugte Hardware an. Wobei auch 
View Technology ganz interresant ist, zwsichen RTL Schematic und 
Technology ist nochmal ein Optimierungsschritt.

von hans (Gast)


Lesenswert?

Duke Scarring schrieb:
> Kann Die Dein Tool nicht mal die generierte Hardware anzeigen?
> Xilinx kann das -> Synthesize -> View RTL Schematic
>
> Quartus kann das auch.
>
> Damit bekommst Du vielleicht ein Gefühl dafür, was das Tool aus Deiner
> Beschreibung generiert.

Danke ein sehr wertvoller tip

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


Lesenswert?

hans schrieb:
>> Kann Die Dein Tool nicht mal die generierte Hardware anzeigen?
> Danke ein sehr wertvoller tip
Den hast du schon vor 3 Tagen bekommen. Erinnerst du dich?  :-/
Lothar Miller schrieb:
>>>> Probiers doch einfach mal aus, und sieh dir den RTL Plan an.
Wenn du nicht weißt, was ein RTL-Plan ist, warum (a) fragst du nicht
oder (b) probierst das mit der Brille mal aus:
http://www.google.de/search?q=rtl%20plan%20fpga

von hans (Gast)


Lesenswert?

Lothar Miller schrieb:
> hans schrieb:
>>> Kann Die Dein Tool nicht mal die generierte Hardware anzeigen?
>> Danke ein sehr wertvoller tip
> Den hast du schon vor 3 Tagen bekommen. Erinnerst du dich?  :-/
> Lothar Miller schrieb:
>>>>> Probiers doch einfach mal aus, und sieh dir den RTL Plan an.
> Wenn du nicht weißt, was ein RTL-Plan ist, warum (a) fragst du nicht
> oder (b) probierst das mit der Brille mal aus:
> http://www.google.de/search?q=rtl%20plan%20fpga

Entschuldigung das hatte ich damals irgendwie nicht auf dem Schirm.


Nach Sichtung des RTL Plans ist mir jetzt klar das die Berechnung von p 
keinen Sinn macht da dieser in meine RTL Plan paralell zum restlichen 
Teil hochgezählt wird.

Dann gibt es noch 2xj Vergleicher für die verschiedenen psd Werte und 
eine Hinterenanderschaltung von Addierern und Multiplexern(mit sel) für 
die einzelnen Zähler (counter[j]) die je nachdem ob die if Bedingung 
erfüllt ist oder nicht hochzählen.


Lothar Miller schrieb:
> hans schrieb:
>> Vom Ressourcenverbrauch geht es bei mir auch bin jetzt bei 17%
> Welchen Wert haben denn steps, psd_max, psd_min und psd_intervall?

ich habe 100 steps und es entstehen 20 vergleicher pro step um den Wert 
einem counter zuzurechnen dabei ist der verbrauch dann 17%.




Ich weiss nicht ob diese Frage redundant ist oder ob das schonmal 
verneint wurde aber ich muss nochmal explizit fragen. Gibt es eine 
Möglichkeit wie ich herrausbekomme wann der Block fertig ist z.b. durch 
ein Signal? das ich dann erst die Zustandsmaschine weiterschalte oder 
muss so ein Block in einen Clockcycle ausgeführt werden und zur Not die 
Taktrate gesenkt werden? In meinem Verständnis würde es sonst vielleicht 
zu Problemen kommen wenn ich im nächsten Schritt die Zähler schon 
anfange auszuwerten obwohl sie noch nicht belegt sind (oder ist das 
schon wieder softwaredenkweise?).


Und an Lothar Miller du meintest doch das mein start Signal für die Katz 
ist, kannst du das nochmal expliziter erklären warum? da steig ich noch 
nicht ganz durch. Mein gedanke dabei ist das bei neuen Werten im psd 
Array erst auf mein Startkommando wieder die neuen Zähler berechnet 
werden.



Danke

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


Lesenswert?

hans schrieb:
> Gibt es eine Möglichkeit wie ich herrausbekomme wann der Block fertig ist
Nein, die gibt es nicht.
Du kannst aber herausbekommen, wie lange die Kombinatorik höchstens 
braucht. Aber wie gesagt: normalerweise gibst du in Timing-Constraints 
deine Wünsche an...

hans schrieb:
> Und an Lothar Miller du meintest doch das mein start Signal für die Katz
> ist, kannst du das nochmal expliziter erklären warum? da steig ich noch
> nicht ganz durch.
Ich mache normalerweise VHDL, und da wäre die Sensitivliste nicht 
wichtig für die Synthese. Bei Verilog offenbar schon, und deshalb hast 
du dein Design ganz einfach mit start_compare *getaktet*:
1
 
2
  always @(posedge start_compare) begin


Und dort wird dann mit jedem Takt das hier gemacht:
1
 
2
  for(i=0;i<steps;i=i+1) begin
3
    p=p+1;
4
  end // wenn diese Schelife zuende ist, ist immer p==steps
5
  
6
  if(p==steps) begin  
7
    compare_done=1;
8
  end
D.h. mit jedem Takt von start_compare wird compare_done auf '1' gesetzt. 
Ein halbwegs schlaues Tool wird das Signal evtl. einfach komplett 
herausoptimieren...

von P. K. (pek)


Lesenswert?

hans schrieb:
> muss so ein Block in einen Clockcycle ausgeführt werden und zur Not die
> Taktrate gesenkt werden?

Nicht zwingend. Wenn Du nicht jeden Cycle Output brauchst, kannst Du 
set_multicycle_path benutzen. Ist dann aber Symptombekämpfung. Die 
grossen Fragezeichen liegen immer noch bei der Architektur.

von hans (Gast)


Lesenswert?

Lothar Miller schrieb:
> Ich mache normalerweise VHDL, und da wäre die Sensitivliste nicht
> wichtig für die Synthese.

Das interessiert mich jetzt näher.


Muss man dann um in VHDL so ein Trigger zu erreichen eine if Anweisung 
benutzen (if(start_compare==1))? da das synthesetool die sensivity list 
um psd und counter erweitert und bei einer änderung dieser sofort auch 
die anderen Änderungen durchgeführt werden.

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


Lesenswert?

hans schrieb:
> Muss man dann um in VHDL so ein Trigger zu erreichen eine if Anweisung
> benutzen (if(start_compare==1))? da das synthesetool die sensivity list
> um psd und counter erweitert und bei einer änderung dieser sofort auch
> die anderen Änderungen durchgeführt werden.
Dein Prozess würde etwa so aussehen:
1
  process (start_compare) begin
2
     if rising_edge(start_compare) then -- eine explizite Abfrage auf eine steigende Flanke
3
       p := 0;
4
       for i in 0 to steps loop
5
          -- mach den ganzen Kladderadatsch
6
          p:=p+1;
7
       end loop;           // wenn diese Schleife zuende ist, ist immer p==steps,
8
  
9
       if (p=steps) then   // und deshalb wird mit jedem Takt 
10
          compare_done<=1; // compare_done auf '1' gesezt.
11
       end if;
12
    end if; 
13
 end process;

von auch Hans (Gast)


Lesenswert?

Um das selbe Verhalten wie bei dir zu erreichen müsste es so aussehen
1
process(start_compare)
2
begin
3
  if (rising_edge(start_compare)) then
4
    ...
5
  end if;
6
end process;

Schön ist es aber nicht. Schöner wäre ein getakteter Prozeß.
Verilog:
1
always @(posedge clk) begin
2
  if (start_compare) begin
3
    ..
4
  end
5
end

VHDL:
1
process(clk)
2
begin
3
  if (rising_edge(clk)) then
4
    if (start_compare = '1') then
5
      ...
6
    end if;
7
  end if;
8
end process;

Oder alles rein kombinatorisch
Verilog:
1
always @(*) begin
2
  ..
3
end

VHDL:
1
process([hier alle Signale eintragen, die im Prozess lesend verwendet werden])
2
begin
3
  ...
4
end process;

Das start_compare mußt du in diesem Fall weglassen, da es sonst ein 
Latch erzeugen würde.

von Lattice User (Gast)


Lesenswert?

Lothar Miller schrieb:
> Ich mache normalerweise VHDL, und da wäre die Sensitivliste nicht
> wichtig für die Synthese. Bei Verilog offenbar schon, und deshalb hast
> du dein Design ganz einfach mit start_compare *getaktet*:

Jein.
Es gibt da nur einen sematischen Unterschied. Bei Verilog kann man die 
sensitivity auf eine Flanke bereits in der Sensitivityliste angeben.

Das hier funktioniert auch:
1
always begin
2
 @(posedge Clock);
3
 .....
4
end

Ist aber natürlich eine für Verilog unübliche Schreibweise, und auch 
nicht in den Codingstyles der Synthesizer aufgeführt. Gibt also keine 
Garantie ob es alle können, bzw keine Bugs haben.

Beim ausprobieren der for loop, hatte ich u.a. das getestet:
1
always begin
2
    begin
3
      Sum = 0;
4
      for(i = 0; i < 10; i = i + 1)
5
        begin
6
          @(posedge Clock)
7
          if( CountEn[i] ) Counter[i] = Counter[i] + 1;
8
          @(posedge Clock)
9
          if( Counter[i] == 0 ) Sum = Sum + 1;
10
        end
11
    end
12
end
Und Synplify hat mir tatsächlich eine Art Statemaschine gebaut.

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


Lesenswert?

Lattice User schrieb:
> Und Synplify hat mir tatsächlich eine Art Statemaschine gebaut.
Habe ich auch schon untersucht, wenn auch linear durch:
http://www.lothar-miller.de/s9y/archives/47-wait-im-Prozess.html
Ich finde es auch spannend, was die Synthesizer alles können... ;-)

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Lattice User schrieb:
> Das hier funktioniert auch:
>
1
> always begin
2
>  @(posedge Clock);
3
>  .....
4
> end
5
>
>
> Ist aber natürlich eine für Verilog unübliche Schreibweise,

So unüblich ist das gar nicht. Im Gegensatz zu VHDL haben Verilog 
Prozesse keine echte Sensitivity Liste. Es gibt drei Regeln in diesem 
Zusammenhang: Ein always block führt immer exakt ein Statement 
wiederholt aus. Jedem Statement kann ein event control vorangestellt 
werden. Durch begin/end können mehrere Statements zu einem 
zusammengefasst werden. Daher sind folgende Beschreibungen identisch:
1
always @(posedge clock) <statement>
2
always @(posedge clock) begin <statement> end
3
always begin @(posedge clock) <statement> end
Gruß
Marcus

von hans (Gast)


Lesenswert?

Ich habe jetzt mein Modul fertig und würde nun genre der Software 
mitteilen wie lange die Bearbeitung dauern darf bzw rausfinden wie lange 
sie max ist. Ich gehe davon aus ich dies in meiner sdc file in Quartus 
machen muss.

Hat jemand dafür ein gutes Tutorial oder hat sowas eine sdc file 
schonmal geschrieben und kann sie hier anhängen?


Danke

von P. K. (pek)


Lesenswert?

Guckst Du:

Quartus > Help > PDF Tutorials > PDF ... for Verilog Users > Specifying 
Timing Constraints

von hans (Gast)


Lesenswert?

1
always @(posedge clkin_150) begin
2
  if(copy_psd_to_new_psd==1)begin
3
    new_psd_reg=psd;
4
   new_psd_reg_temp=psd;
5
  end --// end copy_psd_to_new_psd
6
  
7
  if(start_square==1) begin
8
    for(j=0;j<process_steps;j=j+1) begin
9
10
   
11
           for(i=0;i<max_channels;i=i+1)  begin --// for every maxima value +/- tolerance delta, psd is compared and adapt to maxima value if in this interval
12
                           
13
            if (new_psd_reg_temp[j+steps_offset]<=maxima[i]+tolerance_delta && new_psd_reg_temp[j+steps_offset]>=maxima[i]-tolerance_delta) begin
14
            
15
              new_psd_reg[j+steps_offset]=maxima[i];
16
              
17
              
18
             end --// end if
19
             
20
             
21
          end  --// end i
22
    end --// end j
23
  end--// end if start_square
24
25
end --// end always
1
always @(posedge clkin_150) begin   --//  Count the occurences of the psd values
2
3
 if(delete_compare_values==1) begin
4
  counter='{counter_quantity+1{0}};
5
 end // end if delete values
6
7
 if(start_compare==1) begin
8
  
9
   for(i=0;i<process_steps;i=i+1) begin
10
11
        for(j=0;j<counter_quantity+1;j=j+1) begin 
12
      
13
         if(psd[i+steps_offset]<=(psd_max-j*psd_intervall + psd_intervall/2) && psd[i+steps_offset] > psd_max - (j+1)*psd_intervall + psd_intervall/2) begin
14
        
15
            counter[j]=counter[j]+1;
16
         end --// end if  
17
   
18
        end --// end j
19
    
20
   end --// end i
21
22
 end --// end if start compare
23
end --// end always


Hallo,


ich versuche den Resourcenverbrauch zu reduzieren. Dabei will ich nun 
immer nur 10 Wert e(process_steps) pro Zeitschritt auswerten und das 
entsprechend oft aufrufen. In meiner FSM zähl ich steps_offset also 
hoch.

Dazu habe ich 3 Fragen.

1) verringert das meinen Resourcenverbrauch wirklich ? Wird in der 
hardware dann die selben Vergleicher mehrmals benutzt? (ich kann das 
irgendwie nicht aus dem RTL View rauslesen)

2)Im zweiten Modul was ich gepostet habe mache ich ja etwas sehr 
ähnliches trotzdem dauert die Analyse und Synthese dieses Modul bei 
weitem nicht solange. Hat jemand eine Ahnung woran das liegen kann?

3)in meiner if Abfrage im ersten Modul frage ich einen Wert ab und falls 
die Bedingung stimmt möchte ich den selben Wert ändern. ist das zulässig 
oder muss ich wie hier versucht eine Dummyvariable nehmen 
(new_psd_temp). Das Probem ist wenn ich sie nicht benutze dauert die 
Analyse und Synthese viel länger warum?

von hans (Gast)


Lesenswert?

programmier ich da irgendwelche latches rein wenn ich das löschen 
vornehmen ?

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


Lesenswert?

hans schrieb:
> programmier ich da irgendwelche latches rein
Wenn sowieso alles getaktet ist, dann kanns keine Latches geben. Eher 
Latency...

von hans (Gast)


Lesenswert?

Lothar Miller schrieb:
> Wenn sowieso alles getaktet ist, dann kanns keine Latches geben. Eher
> Latency...

Das heißt was?

Im Vergleich zu dem wa sich vorher hatte @(posedge start_compare) usw 
dauert die Analyse/Synthese nun viel länger. Dem und deiner Aussage 
entnehme ich das ich nicht alles auf die clk takten soll ist das 
richtig?

von hans (Gast)


Lesenswert?

1
always @(posedge start_square) begin
2
3
 if(copy_psd_to_new_psd==1) begin
4
  new_psd_reg=psd;
5
  new_psd_reg_temp=psd;
6
 end --// end if copy
7
 else begin
8
   for(int i=0;i<max_channels;i=i+1)begin
9
10
   
11
           for(int j=0;j<process_steps;j=j+1)  begin --// for every maxima value +/- tolerance delta, psd is compared and adapt to maxima value if in this interval
12
                           
13
            if (new_psd_reg_temp[j+steps_offset_square]<=maxima[i]+tolerance_delta && new_psd_reg_temp[j+steps_offset_square]>=maxima[i]-tolerance_delta) begin
14
            
15
              new_psd_reg[j+steps_offset_square]=maxima[i];
16
              
17
              
18
             end --// end if
19
             
20
             
21
          end  --// end i
22
    end --// end j
23
24
 end --// end else
25
end --// end always


Hallo gemeinde,


ich muss nochmal eine frage bezüglich dieses Codes stellen.


Ich lasse steps_offset_square in einer FSM um je 10 hochzählen und führe 
dann dieses Codestück aus.

Allerdings verarbeitet er es beim zweiten aufrufen nicht. Ist es 
überhaupt so möglich wie ich es mir gedacht habe  das ich mit hilfe von 
steps_offset die selben Vergleicher mehrfach benutzen kann? Mein new_psd 
wert bleibt kontstant obwohl er sich ändern müsste. Wenn ich das 
steps_offset weglasse funktioniert der Code korrekt allerdings werden 
dann zuviele Resourcen verbraucht so das ich es splitten muss. Falls es 
so nicht geht hat jemand andere Vorschläge um den Ressourcenverbracuh zu 
reduzieren?


Danke

von Stachele (Gast)


Lesenswert?

Hast Du das Teil schon simuliert?

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.