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?
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 ?
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...
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.
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
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.
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
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.
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
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.
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
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.
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?
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.
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.
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
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.
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
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
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
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
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
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.
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?
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
>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
>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?
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.
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.
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?
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?
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.
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.
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
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.
@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.
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?
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... ;-)
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...
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
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.
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?
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?
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.
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
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.
> 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
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?
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.
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?
@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
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.
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
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
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
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@(posedgestart_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...
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.
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.
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
ifrising_edge(start_compare)then-- eine explizite Abfrage auf eine steigende Flanke
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
alwaysbegin
2
@(posedgeClock);
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
alwaysbegin
2
begin
3
Sum=0;
4
for(i=0;i<10;i=i+1)
5
begin
6
@(posedgeClock)
7
if(CountEn[i])Counter[i]=Counter[i]+1;
8
@(posedgeClock)
9
if(Counter[i]==0)Sum=Sum+1;
10
end
11
end
12
end
Und Synplify hat mir tatsächlich eine Art Statemaschine gebaut.
>> 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:
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
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?
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?
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