Forum: FPGA, VHDL & Co. Verständnissproblem sequeziell/parallel


von spinne (Gast)


Lesenswert?

Hallo zu alle!

Ich habe eine Anfängerfrage:

wenn in einem Prozess alle Anweisungen sequenziell ablaufen, werden dann 
bei der folgenden Schreibweise 3 Multipliziereinheiten instantiiert?

process begin

result1 <= std_logic_vector(signed(x1)*signed(y1));
result2 <= std_logic_vector(signed(x2)*signed(y2));
result3 <= std_logic_vector(signed(x3)*signed(y3));
wait on x1;
end process;

und bei der:

process begin

result1 <= std_logic_vector(signed(x1)*signed(y1));
result2 <= std_logic_vector(signed(x2)*result1);
result3 <= std_logic_vector(result1*result2);
wait on x1;
end process;

wahrscheinlich auch?

Wann wird eigentlich nur 1 instantiiert? Wenn ich statt Signalen 
Variablen benutzen werde?

Danke im Voraus für die Hilfe!

von Gustl B. (-gb-)


Lesenswert?

Beim Ersten ist alles nach einem Takt fertig.

Beim Zweiten sind genauso wie beim Ersten auch drei parallele 
Multiplizierer, aber: Dein Ergebnis result3 ist erst nach 3 Takten das, 
was du erwartest.
ABER: result2 und result3 haben schon vorher einen Wert, irgendeinen 
oder einen Festen je nachdem was du vorgibst, aber erst nach dem 3. Takt 
haben die ein Ergebnis das bei der Rechnung rauskommt/das du erwartest.

Wie macht man sowas seriell - also nur mit einem Multiplizierer?

Vielleicht so:

signal count: integer range 0 to 2:=0;

process begin
wait until rising_edge(clock);

if count < 2 then
 count <= count +1;
end if;

if    count = 0 then
result1 <= std_logic_vector(signed(x1)*signed(y1));
elsif count = 1 then
result2 <= std_logic_vector(signed(x2)*result1);
elsif count = 2 then
result3 <= std_logic_vector(result1*result2);
end if;
end process;

Syntax hat vermutlich Fehler aber du kannst hoffentlich erkennen was ich 
meine. Jetzt wird nämlich in jedem Takt nurnoch eine Multiplikation 
durchgeführt.

von Sebastian H. (sebihepp)


Lesenswert?

Ist das VHDL? Sieht für mich jedenfalls so aus. Aber da fehlt doch das 
typische
1
if rising_edge(clk) then
oder nicht? Woher soll der Process denn sonst die Taktquelle kennen?

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


Lesenswert?

Das wait ist der Takt. Aber dass ein "wait on" auch geht, ist mir auch 
neu. Welcher Synthesizer kann das?

> Wann wird eigentlich nur 1 instantiiert?
Dann, wenn die Multiplikation zeitgleich nur 2 Faktoren hat.

von spinne (Gast)


Lesenswert?

Ja, es geht um VHDL. Das Clock-Signal möchte ich eigentlich nicht 
benutzen, das sollte ja auch irgendwie rein kombinatorisch gehen. Oder 
irre ich mich da?..
Wäre es eigentlich möglich bei einem rein kombinatorischen Prozess 
(getriggert z.B. auf Änderung von einem der Eingangssignalen) 
festzustellen, dass die Multiplikation gerade fertig geworden ist? Und 
dann reinkombinatorisch den Zustand umschalten? (Da stelle ich mir eine 
Art von endlichem Zustandautomaten vor) Würde sowas mit Variablen 
"Result" und zusätzlichen "Trigger-Signalen" auch vom Typ Variable 
gehen?

von spinne (Gast)


Lesenswert?

Lothar Miller schrieb:
> Das wait ist der Takt. Aber dass ein "wait on" auch geht, ist mir auch
> neu. Welcher Synthesizer kann das?

Der von Synopsis hat da nicht bemekert...

Lothar Miller schrieb:
> Dann, wenn die Multiplikation zeitgleich nur 2 Faktoren hat.

Genau da liegt mein Verständniss Problem: wenn in einem Prozess alle 
Schritte sequenziell ablaufen, also, nacheinander, es sollten ya mit 
Variablen klappen. Oder nicht?..

von Gustl B. (-gb-)


Lesenswert?

Ich hatte das eigentlich oben beschrieben ... und auch in einem Beispiel 
grob skizziert wie man das macht, dass in jedem Takt nur eine 
Multiplikation läuft.

VHDL ist nicht wie C oder so, dass Dinge die untereinander stehen 
nacheinander ablaufen. Alles geht gleichzeitig, ausser du machst es 
explizit wie ich oben in dem Beispiel anders.

-gb-

von Klaus F. (kfalser)


Lesenswert?

spinne schrieb:
> Genau da liegt mein Verständniss Problem: wenn in einem Prozess alle
> Schritte sequenziell ablaufen, also, nacheinander, es sollten ya mit
> Variablen klappen. Oder nicht?..

Gustl Buheitel schrieb:
> if    count = 0 then
> result1 <= std_logic_vector(signed(x1)*signed(y1));
> elsif count = 1 then
> result2 <= std_logic_vector(signed(x2)*result1);
> elsif count = 2 then
> result3 <= std_logic_vector(result1*result2);
> end if;
> end process;
>
> Syntax hat vermutlich Fehler aber du kannst hoffentlich erkennen was ich
> meine. Jetzt wird nämlich in jedem Takt nurnoch eine Multiplikation
> durchgeführt.

Das dürfte nur zur Hälfte stimmen.
In Hardware werden ziemlich wahrscheinlich 3 Multiplikationseinheiten 
angelegt, die mit jedem Takt multiplizieren, aber jedes Ergebnis wird 
immer nur zu einem bestimmten Takt verwendet.
Es würde mich stark wundern, wenn der Compiler so intelligent wäre, dass 
er erkennt, dass im Grunde nur immer nur eine Multiplikationseinheit 
verwendet wird.
Dein Beispiel ist deshalb eher unsinnig.

spinne schrieb:
> Genau da liegt mein Verständniss Problem: wenn in einem Prozess alle
> Schritte sequenziell ablaufen, also, nacheinander, es sollten ya mit
> Variablen klappen. Oder nicht?..

Ja, aber ...
Deine Beispiele sind aber nicht equivalent.
Dein erstes Beispiel berechnet 3 Multiplikationen x1*y1, x2*y2, x3*y3
Dein zweites Beispiel berechnet (x1*y1*x2)*(x1*y2), zumindest im 
Prinzip, da die x und y Werte von verschiedenen Takten verwendet werden.

Was willst Du wirklich berechnen?

von spinne (Gast)


Lesenswert?

Gustl Buheitel, ich verstehe das alles schon und glaube, dass ich meine 
Denkweise von C auf VHDL bereits umgestellt habe. Ich suche halt eine 
Möglichkeit einige Multiplikationen parallel durchzuführen und einige 
solche Schritte nacheinander zu machen. Dabei möchte ich möglichst 
schnell machen, also nicht getaktet, sondern kombinatorisch. Und dafür 
brauche ich z.B. ein gestzter Bit, den mir zeigt, dass die 
Multiplikation vollstendig ausgeführt wurde und die Eingenge dürfen nun 
gemultiplext werden. Villeicht irre ich mich und so was grundsetztlich 
nicht möglich ist. Genau da brauche ich Hilfe von erfahrenen 
VHDL-Entwickler.

von Gustl B. (-gb-)


Lesenswert?

Na dann mach es halt anders:

X <= Y * Z;

if    count = 0 then
Y <= x1;
Z <= y1;
elsif count = 1 then
Y <= x2;
Z <= X;
elsif count = 2 then
Y <= Z;
Z <= X;
end if;

Ach so, ja was willst du denn in diesem Fall machen? Sollen die 3 
Multiplikationen parallel laufen? Sollen die komplett nacheinander 
laufen um Hardware zu sparen?

von spinne (Gast)


Lesenswert?

Klaus Falser, als Beispiel:

Ich möchte möglichst schnell x^4 und y^4 berechnen. Dabei möchte ich die 
Anzahl der Multiplizierer auf 2 begrenzen, also, 2 Schritte zu machen:

x*x; x^2*x^2;

Frage: wann soll ich die Eingänge ändern? Wie erkenne ich, dass die 
Multiplikation vertig ist und der Wert am Ausgang stimmt?

von spinne (Gast)


Lesenswert?

Gustl Buheitel, in dem Fall werde ich wieder Clock-Signal brauchen um 
Zustände zu ändern. Gerade das möchte ich ungern...

von Gustl B. (-gb-)


Lesenswert?

Wann die Multiplikation fertig ist sagen dir die Tools des FPGA 
Herstellers, die machen eine Timing-Analysen und sagen dir mit welchem 
Takt du das ganze noch betreiben kannst damit es funktioniert.

von spinne (Gast)


Lesenswert?

Ja, da bin ich sicher, das sowas funktionieren würde. Es gilt für z.B. 
eine 16 Bit-Multiplikation: min 15ns bis max 75ns. Immer 75ns zu warten 
wäre aber uneffizient. Besser wäre eine fertige Multiplikation zu 
signalisieren. Geht das mit Sicherheit nicht?

Z.B.:
1
process 1 begin
2
3
result1 := std_logic_vector(signed(x1)*signed(y1));
4
a:=not a;
5
result2 := std_logic_vector(signed(x2)*signed(y2));
6
b:=not b;
7
result3 := std_logic_vector(signed(x3)*signed(y3));
8
c:=not c;
9
wait on t;--t ein external Trigger
10
end process;
11
12
process 2 begin
13
wait on (a and b and c);-- a,b,c - shared variable
14
result4 <= std_logic_vector(result1*result2);
15
result5 <= std_logic_vector(result1*result3);
16
result6 <= std_logic_vector(result2*result3);
17
18
end process;

Werden da 3 oder 6 Multiplizierer verwendet? Werden die Variablen a,b 
und c eigentlich sofort nach der Multiplikation zugewiesen?

von Gustl B. (-gb-)


Lesenswert?

Das geschieht ALLES gleichzeitig - und dauert so lange wie es jeweils 
dauert.

Also es passiert folgendes:

a:=not a;
b:=not b;
c:=not c;

geht schnell weil es nur ein NOT und keine Multiplikation ist.

result1 := std_logic_vector(signed(x1)*signed(y1));
result2 := std_logic_vector(signed(x2)*signed(y2));
result3 := std_logic_vector(signed(x3)*signed(y3));

Die drei brauchen etwas länger.

Also wirst du als Ergebins sehen, dass sich zuerst und zwar 
gleichzeitig, die Werte von a,b und c ändern und erst danach erst werden 
die Ergebnisse der Multiplikationen fertig sein. Die Ergebinsse der 
Multiplikationen natürlich auch wieder einigermaßen gleichzeitig.

Die Ergebinsse aus process 2 werden wohl nicht gültig sein, da der 
Process schon startet wenn a, b und c ihren Wert ändern - aber da sind 
die Multiplikationen in process 1 noch nicht fertig.

von spinne (Gast)


Lesenswert?

Hm... Ok, aber was bedeuten dann, dass Processe sequenzielle Instanzen 
sind? Das kapiere ich nun gar nicht. Ich stelle mir das so vor, dass 
zuerst erste Multiplikation durchgeführt wird, Result1 wird zugewiesen 
und unmittelbar danach wird Variable a zugewiesen und nur dann kann 
Result2 ausgerechnet werden usw... Falls a,b und c gleichzeitig 
zugewiesen werden, dass passiert auf jeden Fall früher, als die 
Multiplikationen durchgeführt werden - was ist dann hier "sequenziell" 
gemacht?

von Klaus F. (kfalser)


Lesenswert?

spinne schrieb:
> Ja, da bin ich sicher, das sowas funktionieren würde. Es gilt für
> z.B.
> eine 16 Bit-Multiplikation: min 15ns bis max 75ns. Immer 75ns zu warten
> wäre aber uneffizient. Besser wäre eine fertige Multiplikation zu
> signalisieren. Geht das mit Sicherheit nicht?
>
> Z.B.:
> process 1 begin
>
> result1 := std_logic_vector(signed(x1)*signed(y1));
> a:=not a;
> result2 := std_logic_vector(signed(x2)*signed(y2));
> b:=not b;
> result3 := std_logic_vector(signed(x3)*signed(y3));
> c:=not c;
> wait on t;--t ein external Trigger
> end process;
>
> process 2 begin
> wait on (a and b and c);-- a,b,c - shared variable
> result4 <= std_logic_vector(result1*result2);
> result5 <= std_logic_vector(result1*result3);
> result6 <= std_logic_vector(result2*result3);
>
> end process;
>
> Werden da 3 oder 6 Multiplizierer verwendet? Werden die Variablen a,b
> und c eigentlich sofort nach der Multiplikation zugewiesen?

Nimm es  bitte nicht persönlich, aber man sieht, dass Du wirklich noch 
einige Verständnisschwierigkeiten hast.
Zuerst einmal:
- "shared variable" : Vergiss das Wort und nimm es bitte die nächsten 5 
Jahre nicht mehr in den Mund.

Mit VHDL baust Du Hardware, d.h. Du verdrahtest Hardware-Einheiten (eben 
z.B. Multiplikatoren) miteinander. Diese Einheiten sind immer da, und 
arbeiten kontinuierlich.

z.B. Dein Prozess 1
Dieser ergibt z.B. 3 Multiplizierer, deren Ergebnis in result1 bis 
result3 gespeichert werden, wenn t sich ändert.
Dies ist so nicht synthetisierbar, weils Speicherelemente in FPGA's 
üblicherweise nur auf eine Flanke reagieren, also entweder t ändert sich 
von 0 auf 1 (rising edge) oder von 1 auf 0 (falling edge).
Wir reden also schon einmal über Hardware, die es nicht gibt.
Aber warum willst Du auf einen Trigger warten?
Wenn Du das ganze außerhalb eines Prozesses schreibst, dann arbeiten die 
Multiplikationseinheiten die ganze Zeit und das Ergebnis ist voll 
kombinatorisch.
Also zum Berechnen von

-- x * x
result1 <= std_logic_vector(signed(x)*signed(x));

-- und nun x^2 * x^2
result2 <= std_logic_vector(signed(result1)*signed(result1));

Das ergibt genau 2 Multiplikatoren, diese haben aber eine gewisse 
Durchlaufzeit.
Das Ergebnis result2 wird sich immer dann ändern, wenn sich x ändert, 
aber wann ändert sich x?
Und genau aus diesem Grunde verwendet man einen Takt, den Du so 
vermeiden willst.
Wenn Du das Design taktest, dann ändert sich x genau zur Taktflanke und 
der Multiplikator hat 1 Taktzyklus Zeit sein Ergebnis zu berechnen. Zur 
nächsten Taktflanke muss das Ergebnis stabil sein, denn da wird es von 
der nächsten Stufe weiterverarbeitet.

von spinne (Gast)


Lesenswert?

Klaus Falser schrieb:
> Nimm es  bitte nicht persönlich, aber man sieht, dass Du wirklich noch
> einige Verständnisschwierigkeiten hast.

Klar, deswegen bin ich ja hier =) Ich bin noch ziemlich am Anfang, aber 
habe vor, sich möglichst gut in VHDL einzuarbeiten. Leider wird diese 
Sprache in meinem Studiengang nicht unterrichtet, deswegen muss ich 
jetzt gleichzeitig  teoretische kenntnisse und praktische Vorgehensweise 
erwerben.

Und es bleibt für mich immer noch nicht ganz klar, was in Processen 
nacheinander abläuft. Warum sind sie sequenzielle Instanzen, wenn sogar 
die Reihenfolge von Zuweisungen nicht sequenziell ist?

Klaus Falser schrieb:
> Dies ist so nicht synthetisierbar, weils Speicherelemente in FPGA's
> üblicherweise nur auf eine Flanke reagieren, also entweder t ändert sich
> von 0 auf 1 (rising edge) oder von 1 auf 0 (falling edge).
> Wir reden also schon einmal über Hardware, die es nicht gibt.
> Aber warum willst Du auf einen Trigger warten?

Doch, das ist synthetisierbar und funktioniert zwar in der Hardware. Den 
Beisielcode kann ich bei Interesse am Montag hier posten. Den Process 
wird mit jeder Änderung des Zustandes aufgerufen, man kann ja auch auf 
Vektoren triggern, dann wird jede Änderung von einzelnen Bits 
detektiert. Das hatte ich auch bereits mal erfolgreich verwendet.
Auf den Trigger will ich deswegen warten, weil die Multiplikation nur 
dann stattfinden soll, wenn beide Signale aktuell sind. Genau das 
signalisiert mir das Triggersignal. Warum möchte ich kein Takt 
benutzen?.. Weil somit werden alle multiplikationen in gleicher Zeit 
erledigt, und diese Zeit ist dann die maximale Zeit. Werde ich meine 
Hardware schneller takten - werden die Ergebnisse nicht mehr stabil beim 
ablesen. Ich meine nur, wenn es z.B. zwei 16-Bit Vektoren multipliziert 
werden sollen, wird das Ergebnis von "0000000000000001" * 
"0000000000000001" schneller stabil als "1010101011100101" * 
"1111010001001101". Dann geht mehr als 90% Zeit verloren. Genau das 
möchte ich vermeiden, falls es geht.

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


Lesenswert?

spinne schrieb:
> Und es bleibt für mich immer noch nicht ganz klar, was in Processen
> nacheinander abläuft.
Nur die Berechnung des Ergebnisses im Simulator läuft da 
"nacheinander" ab. In der Hardware (CPLD, FPGA, ASIC) passiert immer(!!) 
ist alles gleichzeitig.

spinne schrieb:
> Ok, aber was bedeuten dann, dass Processe sequenzielle Instanzen sind?
Ich sage mal ein wenig provokant: dieses "sequenziell" und "parallel" 
wurde nur von Professoren erfunden, die ihre Studenten aufs Glatteis 
führen wollten.
Genauso wie das Wort "nebenläufig" in VHDL gar nichts mit "unwichtig" 
oder "zweitrangig" zu taun hat. Es bedeutet vielmehr "gleichzeitig"...

von Hmm (Gast)


Lesenswert?

Ich habe schon gestern überlegt, was zu schreiben, es dann aber 
gelassen. Das Problem ist, das diese Begriffe nur in Zusammenhang mit 
einer räumlichen und zeitlichen Dimension wirklich Sinn machen. Ich kann 
das, falls gewünscht noch weiter ausführen.

Andererseits hat Lothar sinngemäß recht, wenn er diese Begriffe 
abqualifiziert, da sie eine mehr oder weniger triviale Tatsache eher 
verbrämen als deutlich machen. Ich liebe ja Fremdwörter, aber hier 
stiften sie eher Verwirrung.

Du musst Dir zuallererst klarmachen, das Du Strukturen beschreibst und 
die Übernahme/Übergabe von Signalen anhand von Taktsignalflanken. Mehr 
ist das alles nicht, wenn man der traditionellen Auffassung folgt, und 
das ist für einen Anfänger ratsam (bin selbst noch halber Anfänger 
allerdings mit 30 Jahren Erfahrung in Elektronik und Software).

Da ich zu abseitigen Fragestellungen eine gewisse Affinität habe, habe 
ich auch Verständnis für diese: "Und dafür brauche ich z.B. ein gestzter 
Bit, den mir zeigt, dass die Multiplikation vollstendig ausgeführt 
wurde" auch wenn Du sie erstmal als Notwendigkeit und nicht als 
Abseitigkeit ansiehst.

Vielleicht hilft es Dir ein wenig, wenn Du Dir die Aufgabenstellung mal 
kurz vereinfachst. Nimm mal an, es handele sich um ein XOR-Verknüpfung. 
(Prinzipiell ist das nur eine wesentlich einfachere Kombinatorik) 
Überleg mal, beim Warten in der Mensa-Schlange, wie Du ein Bit berechnen 
würdest, das Dir anzeigt, das die Verknüpfung fertig ist.
Wie würdest Du das anfangen?

In der Praxis aber, wird das Verfahren, das hier schon von einigen 
beschrieben wurde, angewandt. Nämlich anhand von Takten Eingangswerte 
und Ausgangswerte erst dann zu sampeln, wenn die Laufzeit durch eine 
Kombinatorik garantiert abgelaufen ist.

von Hmm (Gast)


Lesenswert?

Oops, hier fehlt was:

>Vielleicht hilft es Dir ein wenig, wenn Du Dir die Aufgabenstellung mal
>kurz vereinfachst. Nimm mal an, es handele sich um ein XOR-Verknüpfung.
>(Prinzipiell ist das nur eine wesentlich einfachere Kombinatorik)
>Überleg mal, beim Warten in der Mensa-Schlange, wie Du ein Bit berechnen
>würdest, das Dir anzeigt, das die Verknüpfung fertig ist.
>Wie würdest Du das anfangen?

Und als nächstes, überleg Dir mal, wie Du in diesem Design, ein Bit 
bildest, das anzeigt, dass das Bit, das anzeigt, das die Verknüpfung 
fertig ist, fertig ist. :-)

von Gustl B. (-gb-)


Lesenswert?

Nun, bei der Multiplikation ist doch die Länge der beiden Werte dafür 
verantwortlich wie lange es dauert. Also bei einem 8x8 Bit 
Multiplizierer dauert ein "11010110" * "10100110" wohl länger wie ein 
"00000110" * "00000101".

Wenn als die Laufzeit der Multiplikation von der Länge der Faktoren 
abhängt, dann kann man da schon Bits haben die anzeigen wann die 
Multiplikation sicher fertig ist.
Man prüft dafür zuerst die Längen der Faktoren und gestaltet dann das 
Bit.
Also eben mit einer Festen Verzögerung für "Beide Faktoren sind 4 Bits 
lang".

Man hat dann viele Bits die nacheinander verzögert gesetzt werden, und 
zwar je nachdem wie man das abstufen will für viele unterschiedliche 
Längen der Faktoren. Das ist natürlich zusätzliche Logik und es muss 
auch die Länge der Faktoren überprüft werden - es überhaupt nur einen 
Sinn bei deutlich unterschiedlichen Faktoren, denn wenn sich deren Länge 
nur um wenige Stellen unterscheidet, ist der Zeitgewinn umso kleiner.

von Christian R. (supachris)


Lesenswert?

Was soll das denn bringen mit dem Busy-Bit? Da müsste ja das System, das 
die Operanden rein füttert und aufs Ergebnis wartet, viel schneller ein 
als der Multiplizierer. Und das externe System läuft ja ganz sicher mit 
einem Takt. Solange dieser Takt unter der Grenze für die Multiplikation 
bleibt, die die Toolchain nach dem Place&Route ausrechnet, kannst du 
davon ausgehen, dass die Multiplikation innerhalb eines Taktes "fertig" 
ist. Aktuelle FPGAs schaffen so eine Multiplikation locker bei 
250...500MHz Systemtakt.

von Gustl B. (-gb-)


Lesenswert?

Keine Ahnung was es bringen soll, der Threadersteller hatte danach 
gefragt, und Multiplikationen angegeben die nacheinander laufen sollen 
weil sie jeweils das Ergebnis der Vorherigen brauchen. Mit so einem Bit 
könnte man das rein kombinatorisch machen.
Ich bin aber natürlich auch wie hier schon im 2. Post klar werden sollte 
für eine getaktete Lösung.

von Christian R. (supachris)


Lesenswert?

Ist doch dann auch egal, ob man so ein Bit hat. Die Multiplikation muss 
doch sowieso im nächsten Takt fertig sein. Und bei einer Multiplikation 
sind doch alle Faktoren austauschbar (wenn man nicht irgendwelche 
Überlauf-Geschichten evtl. zwischendurch abfangen will). Da kann man 
genauso gut auch
1
d <= a * b * c;
hinschreiben. Die maximal ereichbare Taktfrequenz sinkt halt dann. 
Ungetaktet können meines Wissens (bei Xilinx) sowieso keine HW-MUL 
genommen werden.

von berndl (Gast)


Lesenswert?

Hmm schrieb:
> Und als nächstes, überleg Dir mal, wie Du in diesem Design, ein Bit
> bildest, das anzeigt, dass das Bit, das anzeigt, das die Verknüpfung
> fertig ist, fertig ist. :-)

Das ist eigentlich ganz einfach, aber komplett sinnlos: Du 
multiplizierst parallel 2 bekannte Zahlen, bei denen 'einfach' ein 
hoeherwertiges Bit als in deiner eigentlichen Berechnung gesetzt ist. 
Damit dauert diese Multiplikation laenger als die eigentlich 
gewuenschte. Und wenn du dieses (bekannte) Ergebnis detektierst, hast du 
einen Trigger der dir sicher sagen kann, dass deine eigentliche MULT 
fertig ist.

Aber die dazu benoetigte Logik ist mindestens 10x so komplex wie die 
eigentliche Multiplikation. Aber funktionieren wuerde es...

So als Hintergrund: In den 90ern gab es Experimente und sogar einen 
wirklich in Silizium gegossenen ARM mit 'self-timed logic' (ich meine 
der ARM war von der Uni Cambridge). Er hat funktioniert, war aber wegen 
des Ballasts deutlich langsamer als ein 'Standard'-Rechner. Das hatten 
die Jungs mal auf der Hot-Chips (1995 oder 96 oder 97) vorgestellt. Und 
bei meiner Ex-Firma haben wir mit sowas auch experimentiert, es aber 
dann sein lassen (zu komplex, Toolchains komplett ueberfordert, effektiv 
durch das mehr an Logik kein Gewinn, ...)

von berndl (Gast)


Lesenswert?

achja, haette auch gleich google fragen koennen:
http://de.wikipedia.org/wiki/AMULET

von Hmm (Gast)


Lesenswert?

>Das ist eigentlich ganz einfach, aber komplett sinnlos...

Ebenso sinnlos wie Deine Antwort.

An Dich war die Frage nicht gerichtet, sondern an den TO. Für DEN hat 
diese Überlegung ein didaktischen Zweck.
Du dagegen musstest Dich anscheinen profilieren.

Meine Güte.

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


Lesenswert?

@ Hmm
Warum so angesäuert? berndl hat doch nur seine (durchaus nennenswerten) 
Erfahrungen eingebracht. Er hat dich nicht persönlich angegriffen, 
sondern nur die Sinnlosigkeit des Verfahrens, die du schon 
herausgestellt hast, nochmal verdeutlicht...

spinne schrieb:
> Ich meine nur, wenn es z.B. zwei 16-Bit Vektoren multipliziert werden
> sollen, wird das Ergebnis von "0000000000000001" * "0000000000000001"
> schneller stabil als "1010101011100101" * "1111010001001101".
Das kannst du nur dann behaupten, wenn du die Struktur des 
Multiplizierers gut kennst. Bis dahin bleibt alles reine Vermutung...

von Hmm (Gast)


Lesenswert?

Lothar Miller schrieb:
> @ Hmm
> Warum so angesäuert? berndl hat doch nur ...

Ja. Schon gut. Sorry. Hätte ich auch ohne Sauerteig formulieren können.

Ich hielte es für besser, wenn der TO selbst sich Gedanken macht, 
anstatt, das andere ihm ihre Erfahrungen schildern (so relevant sie auch 
sein mögen).
Seine Erfahrung war doch garnicht gefragt, sondern das der TO selbst mal 
grübelt. Wenn man ihm das vorkaut, macht er keine eigenen Erfahrungen 
(selbst wenn es nur gedankliche sind). So sehe ich das.

von berndl (Gast)


Lesenswert?

Hmm schrieb:
> Ja. Schon gut. Sorry. Hätte ich auch ohne Sauerteig formulieren können.

Danke, angekommen und akzeptiert

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


Lesenswert?

Hmm schrieb:
> sondern das der TO selbst mal grübelt.
Ja, spinne sitzt gerade ganz arg im hardwaremäßigen Abseits fest.

spinne schrieb:
> Genau da liegt mein Verständniss Problem: wenn in einem Prozess alle
> Schritte sequenziell ablaufen, also, nacheinander, es sollten ya mit
> Variablen klappen. Oder nicht?..
Du denkst immer noch in einer (irgendeiner) prozeduralen 
(Schritt-für-Schritt) Programmiersprache.
> ich meine Denkweise von C auf VHDL bereits umgestellt habe.
Du musst auch nicht in VHDL "denken", sondern in "Hardware". Und dann 
VHDL nehmen, um das Gedachte zu beschreiben. Deshalb heißt es ja auch 
"Hardwarebeschreibungssprache"...

Und wenn in VHDL drei "*"-Zeichen stehen, werden da drei Multiplizierer 
instantiiert. Fertig. Wenn du für 3 Multiplikationen nur 1 
Multiplizierer nehmen willst, dann musst du den mit einem Multiplexer 
auf die unterschiedlichen Faktoren und Ergebnisse umschalten...

von berndl (Gast)


Lesenswert?

Lothar Miller schrieb:
>> Genau da liegt mein Verständniss Problem: wenn in einem Prozess alle
>> Schritte sequenziell ablaufen, also, nacheinander, es sollten ya mit
>> Variablen klappen. Oder nicht?..
> Du denkst immer noch in einer (irgendeiner) prozeduralen
> (Schritt-für-Schritt) Programmiersprache.

es ist doch eigentlich ganz einfach: Eine VARIABLE ist der D-Eingang 
eines FFs, ein SIGNAL ist der Q-Ausgang eines FFs. Dass bei D natuerlich 
noch alles andere vorher als Laufzeit dazu kommt sollte doch bitte klar 
sein! Bei Q faengt die Zeitrechnung eben einfacherweise wieder bei 0 
an...

von Olga (Gast)


Lesenswert?

berndl schrieb:
> es ist doch eigentlich ganz einfach

Ja, und zwar ganz einfach falsch. Signale und Variablen können beide 
auch in reinen kombinatorischen Verknüpfungen auftauchen und haben gar 
nichts mit FFs zu tun.

von berndl (Gast)


Lesenswert?

Olga schrieb:
> Ja, und zwar ganz einfach falsch. Signale und Variablen können beide
> auch in reinen kombinatorischen Verknüpfungen auftauchen und haben gar
> nichts mit FFs zu tun.

in einem PROCESS mit CLK sehr wohl. Und ja, concurrent statements sind 
auch nur 'fliegende' Logiksignale.

Ich habe mir folgendes angegewoehnt: Ein PROCESS hat eine clock, evtl. 
noch einen async. reset. Alles andere wird mit concurrent statements 
beschrieben. Damit ist auch klar: Ein 'signal' ist innerhalb eines 
Prozesses immer ein FF, ein 'signal' ausserhalb eines Prozesses immer 
ein 'fliegendes' Logiksignal. 'variable' verwende ich nur in Testbenches 
oder als temporaeres Signal innerhalb eines 'process'. Z.B. als Index in 
ein Array, oder weil ich zu faul bin, das ganze mehrmals zu tippen. Aber 
in diesem Zusammenhang niemals als speicherndes Element.

Und Fakt ist: eine VARIABLE ist immer der D-Eingang des FF im getakteten 
process. Mit dem ganzen Rattenschwanz davor...

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


Lesenswert?

"Variable" oder "Signal" ist doch egal. Wenn eines davon getaktet ist, 
gibts ein Flipflop...

von heinz (Gast)


Lesenswert?

FPGA Noob

So wie ich den TO versteh will er eine Multiplikation kombinatorisch 
(ohne Takt) laufen lassen und braucht irgendein Bit das anzeigt wenn die 
Multiplikation sicher beendet ist.

Normal ist doch der Takt der worst case?

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


Lesenswert?

Ein Multiplizierer ist per se kombinatorisch. Mit Aufbrechen von 
Kombinatorikpfaden und Einfügen von FFs kann er in einem getakteten 
Design "schneller" gemacht werden.

von John D. (Firma: Privat) (doejohn)


Lesenswert?

Hallo,

> Ich habe mir folgendes angegewoehnt: Ein PROCESS hat eine clock, evtl.
> noch einen async. reset. Alles andere wird mit concurrent statements
> beschrieben.

Ein Process hat eine Sensitivity List: process(SIGNAL1, SIGNAL2,...)

SIGNAL_X kann ein eine Clock sein dann ist es ein synchroner Process und 
wird in der Regel auf D-FFs abgebildet. Es muss aber keine Clock sein, 
dann ist es ein asynchroner Process, z.B. ein Bus-Multiplexer:

process(Select, Bus1, Bus2)

Für die Sensitivity List gibt es klare Regeln. Ist der Process syncron 
steht da nur die Clock! Eventuell noch ein asynchroner Reset, obwohl man 
asynchrone Resets heutzutage eigentlich nicht mehr verwendet( XILINX hat 
das in ihrem WhitePaper WP272 schön beschrieben). Ist der Process 
asynchron, dann müssen in der Sensitivity List alle Signale stehen, 
deren Wert GELESEN wird. Ansonsten produziert man da Latches und die 
will man nicht.
Bsp:

RICHIG:
-------
process(Select, Bus1, Bus2)
begin
  if Select='0' then
    Output <= Bus1;
  else
    Output <= Bus2;
  end if;
end process;

FALSCH:
-------
process(Select)
begin
  if Select ='0' then
    Output <= Bus1;
  else
    Output <= Bus2;
  end if;
end process;


> Damit ist auch klar: Ein 'signal' ist innerhalb eines
> Prozesses immer ein FF, ein 'signal' ausserhalb eines Prozesses immer
> ein 'fliegendes' Logiksignal.

Nee, ein Signal in einem geclockten Process wird nur dann zu einem 
Flip-Flop wenn es einem anderen Signal zugewisen wird. Man kann z.B. ein 
RegisterSet mit synchroner Logik folgendermaßen beschreiben:

process(Clk)
begin
  if rising_edge(CLK) then
    if Reset = '1' then
      Reg0 <= (others=>'0');
      Reg1 <= (others=>'0');
      Reg2 <= (others=>'0');
      Reg3 <= (others=>'0');
    elsif Write = '1' then
      case Addr is:
        when "00" => Reg0 <= Input;
        when "01" => Reg1 <= Input;
        when "10" => Reg2 <= Input;
        when "11" => Reg3 <= Input;
        when others => null;
    end if;
  end if;
end process;

Reset & Addr sind in diesem Fall zwei Signale, die aber nicht in FF 
umgewandelt werden. Addr wird zu einem Multiplexer, bzw. Selector für 
den Enable Eingang der Register.


>'variable' verwende ich nur in Testbenches
> oder als temporaeres Signal innerhalb eines 'process'. Z.B. als Index in
> ein Array, oder weil ich zu faul bin, das ganze mehrmals zu tippen. Aber
> in diesem Zusammenhang niemals als speicherndes Element.

Man sollte zwar vorsichtig mit Variablen sein, es gibt aber kein Grund 
sie nicht zu verwenden. In einem Counter z.B. können Variablen durchaus 
hilfreich sein. Dort werden sie auch in speichernde Elemente 
umgewandelt.

Beispiel:
process(clk)
  variable count : integer := 0;
  constant CMAX  : integer := 10;
begin
  if rising_edge(clk) then
    if Reset = '1' then
      count := 0;
    elsif Increment = '1' then
      if count = CMAX then  -- wrap around
        count := 0;
      else
        count := count +1;
      end if;
    end if;
  OutSignal <= std_logic_vector(count);
end process;

Generiert einen sauberen Counter, es werden nur Variablen verwendet und 
die Zuweising an das OutSignal wird ganz am Ende gemacht.
Es gibt von GAISLER Research sogar einen kompletten Processor, LEON3, 
der nur 2 Prozesse verwendet und massiv auf Variablen aufbaut.
Der einzige formelle Unterschied ist, dass eine Variable ihren Wert 
sofort annimmt, das Signal dagegen erst wenn der Process "suspendet" 
wird.

Bsp:
----

process(CLK)
  variable X, Y : std_logic;
begin
  if rising_edge(clk) then
    X := InputSignal;
    Y := X;
  end if;
  OutputSignal <= Y;
end process;

Generiert genau 1 D Flip-Flop: InputSignal -> D-FF -> OutputSignal


process(CLK)
begin
  if rising_edge(clk) then
    X <= InputSignal;
    Y <= X;
  end if;
end process;
OutputSignal <= Y;

Generiet ein Shiftregister aus 2 D-FF: InputSignal -> D-FF(X) -> D-FF(Y) 
-> OutputSignal




>
> Und Fakt ist: eine VARIABLE ist immer der D-Eingang des FF im getakteten
> process. Mit dem ganzen Rattenschwanz davor...

Nope! Kann auch zur Selektion dienen, zur Beschriebung kombinatorischer 
Logik, etc.

Gruss,
  DJ

von John D. (Firma: Privat) (doejohn)


Lesenswert?

Lothar Miller schrieb:

> Ich sage mal ein wenig provokant: dieses "sequenziell" und "parallel"
> wurde nur von Professoren erfunden, die ihre Studenten aufs Glatteis
> führen wollten.
> Genauso wie das Wort "nebenläufig" in VHDL gar nichts mit "unwichtig"
> oder "zweitrangig" zu taun hat. Es bedeutet vielmehr "gleichzeitig"...

Nee, die Begriffe wurden nicht von Professoren erfunden um die Studenten 
zu verwirren, sondern sind fundamentale Konzepte von (synchronem) 
Digital Design, was recht wenig mit Software Design zu tun hat, auch 
wenn VHDL und Verlog in ihrem Syntax aussehen wie Programmiersprachen. 
Ich denke eher, das verwirrt die Leute da es sich um ein Konzept handelt 
welches man von "normalen" Programmiersprachen nicht kennt. 
Thread-Programming, MPI oder CUDA/OpenCL kommen dem noch am nächsten.
Zwar läuft in einem Design alles parall ab aufgrund der Propagation 
elektrischen Signale aber durch getaktete Elemente wie Flip-Flops 
bekommt man ein diskretes Zeitverhalten, eben eine Sequenz. Und dieses 
Konzept braucht man, wenn man z.B. Counter, Statemachines, etc. 
modelieren möchte.

Eventuell haben Professoren ein Problem damit die Begriffe richtig zu 
erklären, die haben aber in jedem Fall ihre Berechtigung.

Hier ein Beispiel um es zu illustrieren. In VHDL istjedes Signal 
Statement (Instantierung und Port Mapping mal 
ausgenommen)gleichbedeutent mit einem Process.

X <= A * B ist das selbe wir

process(A,B)
begin
   X <= A * B;
end process;

Man kann also ein Design komplett nur mit Prozessen beschreiben. Alle 
diese Prozesse laufen PARALL ab, d.h. gleichzeitig/nebenläufig 
(concurrent). Die Abarbeitung innerhalb eines Prozesses ist jedoch 
SEQUENTIELL, d.h. der Code wird in der Reihenfolge durchlaufen, wie er 
da steht. Da erst macht die Modelierung von synchronen Prozessen mit 
einer Clock möglich. Der Prozess "hält an dieser Stelle" an, wartet bis 
er eine Rising/Falling Edge sieht und läuft dann erst weiter. Dadurch 
kann man Zeitverhalten modelieren, was anders nicht möglich ist.
Daher: ALLE Prozess laufen PARALLEL zueinander ab, aber innerhalb des 
Prozess Statements SEQUENTIELL. Bei einem asynchronen Prozess stoppt der 
Prozess nicht, er läuft genau ein mal durch, wenn ein Element in der 
Sensitivity List sich ändert und läuft dann bis zum Ende durch. Anders 
synchrone Prozesse. Die stoppen bei dem Rising/Falling Edge Statement 
und läufen erst dann weiter wenn die das Taktsignal sehen. Nur solche 
Prozesse kann man dazu verwenden nicht nur die aktuellen Inputs zu 
verwenden, sondern auch den Output.
Einfachstes Beispiel ist ein Counter. Der Ausgang hängt von dem 
aktuellen Wert ab, der inkrementiert wird. Man muss also den aktuellen 
Wert kennen.
Anders ausgedrückt, immer da wo man den vorhergegangen Wert kennen muss, 
also ein Feed-back hat, braucht man synchrone Logik und die ist per 
Definition sequentiell, da der Prozess an der Clock stoppt.

Einfaches Beispiel:

process(clk)
begin
  if rising_edge(clk) then
    D <= not D;
  end if;
end process;

Kann synthetisiert werden und gibt ein Signal D mit der halben Clock 
Frequenz.

process(D)
begin
  D <= not D;
end if;

Gibt einen Fehler im Synthesizer mit "Combinatorial Loop".

Gruss,
  JD

von berndl (Gast)


Lesenswert?

John Doe schrieb:
> Beispiel:
> process(clk)
>   variable count : integer := 0;
>   constant CMAX  : integer := 10;
> begin
>   if rising_edge(clk) then
>     if Reset = '1' then
>       count := 0;
>     elsif Increment = '1' then
>       if count = CMAX then  -- wrap around
>         count := 0;
>       else
>         count := count +1;
>       end if;
>     end if;
>   OutSignal <= std_logic_vector(count);
> end process;

Hi,
schoener Nickname uebrigens :o)

Jetzt sind wir ja auch bzgl. des Titels des Threads (Verständnissproblem 
sequeziell/parallel) wieder richtig...

Da fehlt erstens ein 'end if' und zweitens stoert mich, dass man mit der 
'lokalen' Variablen sich halt eine Abhaengigkeit der Reihenfolge der 
Statements einfaengt.

Mit Signalen wuerde ich auch schreiben koennen:
1
count <= count + 1;
2
if count = CMAX then
3
   count <= '0';
4
end if;
'count' sollte hier auch direkt dein 'OutSignal' sein, oder man kann 
count auch einfach in einem concurrent statement dem Ausgangssignal 
zuweisen.

Dein Beispiel
1
if count = CMAX then
2
   count := 0; 
3
else 
4
   count := count +1; 
5
end if; 
6
OutSignal <= std_logic_vector(count);
funktioniert natuerlich wunderbar. Weshalb ich das so aber nicht 
verwende: Die Reihenfolge der statements ist entscheidend, und deshalb 
verwende ich persoenlich diese Schreibweise nicht. Und jetzt stelle ich 
mir mal vor, der 'process' waere etwas komplexer und dann noch nicht 
getaktet sondern kombinatorisch... Es ist dann extrem schwer, den Ablauf 
noch zu durchschauen. Deshalb meine 'simple minded' Vorgehensweise: 
process nur als 'clocked' process, maximal mit async. Reset. variable 
nur als Platz sparendes 'fliegendes' Signal im process. Ansonsten 
Kombinatorik nur mit concurrent Statements.
Also mir gefaellt die Methode 'Gaisler/Leon' persoenlich ueberhaupt 
nicht, weil sich eben 'lokale variable' ganz anders verhalten (koennen) 
als 'global signal'.
Und richtig lustig wird es, wenn du 'variable' in einem nicht getakteten 
'process' verwendest. Sowas habe ich in eingekauften Designs schon 
gesehen und darueber auch schon mal einen Vormittag gebruetet... Ich bin 
halt ein Anhaenger der keep-it-simple Philosophie...

von John D. (Firma: Privat) (doejohn)


Lesenswert?

berndl schrieb:

> Hi,
> schoener Nickname uebrigens :o)
Danke! John Doe war leider schon vergeben, da konnte ich meiner 
Kreativität freien Lauf lassen ;-)

> Jetzt sind wir ja auch bzgl. des Titels des Threads (Verständnissproblem
> sequeziell/parallel) wieder richtig...
Yepp!

> Da fehlt erstens ein 'end if' und zweitens stoert mich, dass man mit der
> 'lokalen' Variablen sich halt eine Abhaengigkeit der Reihenfolge der
> Statements einfaengt.
Stimmt, habe den Code schnell aus'm Kopf runtergeschrieben, da geht 
schon mal was verloren.

> Mit Signalen wuerde ich auch schreiben koennen:
>
1
> count <= count + 1;
2
> if count = CMAX then
3
>    count <= '0';
4
> end if;
5
>

Naja, die Reihenfolge spielt hier ja auch eine Rolle.
1
 if count = CMAX then
2
    count <= '0';
3
 end if;
4
 count <= count + 1;

Reihenfolge vertauscht und der Code wird sich anders verhalten.

> 'count' sollte hier auch direkt dein 'OutSignal' sein, oder man kann
> count auch einfach in einem concurrent statement dem Ausgangssignal
> zuweisen.

Wenn 'count' ein internes Signal ist, dann kann man es natürlich, wie in 
deinem Beispiel direkt zuweisen. Bei einem Output geht das ja nicht, da 
auf 'count' auch lesend zugegriffen wird. O.k. Man kann "inout" oder 
"buffer" verwenden, aber das ist hässlich.


> Dein Beispiel
>
1
> if count = CMAX then
2
>    count := 0;
3
> else
4
>    count := count +1;
5
> end if;
6
> OutSignal <= std_logic_vector(count);
7
>
> funktioniert natuerlich wunderbar. Weshalb ich das so aber nicht
> verwende: Die Reihenfolge der statements ist entscheidend, und deshalb
> verwende ich persoenlich diese Schreibweise nicht. Und jetzt stelle ich
> mir mal vor, der 'process' waere etwas komplexer und dann noch nicht
> getaktet sondern kombinatorisch...Es ist dann extrem schwer, den Ablauf
> noch zu durchschauen.

Ist vermutlich Geschmackssache. Die Abhängigkeit der Reihenfolge hat man 
bei Signalen auch. Dazu kommt, dass Variablen direkt den Wert 
übernehmen, Signal dagegen erst, wenn der Process durchgelaufen ist und 
suspended wird. Beides hat seine Berechtigung und ist ne Frage wie man's 
gewohnt ist. Jemand der lange mit Variablen arbeitet wird es vermutlich 
einfacher finden damit zurecht zu kommen als mit Signalen. Ich 
persönlich vermeide Variablen ebenfalls.

> Deshalb meine 'simple minded' Vorgehensweise:
> process nur als 'clocked' process, maximal mit async. Reset. variable
> nur als Platz sparendes 'fliegendes' Signal im process. Ansonsten
> Kombinatorik nur mit concurrent Statements.

Ja, sehe ich genau so. Bis auf die Sache mit dem async. Reset! Der muss 
endlich mal aus dem Kopf der Leute raus. Darf man zwar haben (wenn er 
von extern kommt) aber dann bitte sauber (Synchronizer!) in die 
entsprechende Clock-Domain einsynchronisren und als sync. Reset 
verwenden.

> Also mir gefaellt die Methode 'Gaisler/Leon' persoenlich ueberhaupt
> nicht, weil sich eben 'lokale variable' ganz anders verhalten (koennen)
> als 'global signal'.
> Und richtig lustig wird es, wenn du 'variable' in einem nicht getakteten
> 'process' verwendest. Sowas habe ich in eingekauften Designs schon
> gesehen und darueber auch schon mal einen Vormittag gebruetet... Ich bin
> halt ein Anhaenger der keep-it-simple Philosophie...

Ja, - KISS : Keep It Simple, Stupid! - die goldene Regel des 
Digitaldesigns. Oder mit den Worten von Sergei Koroljow (dem russischen, 
daher leider ziemlich unbekannten aber genialen Gegenspieler von Werner 
von Braun) „The Genialität of a construction lies in their simplicity. 
Complicated to build everyone can.“

Ein Vorteil haben Variablen jedoch und zwar wenn es um die 
Simulationszeit geht. Signale sind ziemlich aufwendig zu simulieren, da 
sie für jeden DELTA-Cylce des Simulators evaluiert werden müssen. 
Variablen sind da super schnell und sparen Speicherplatz. Das fällt bei 
kleinen bis mittleren Designs nicht so ins Gewicht, aber große Designs 
bei entsprechend hohen Frequenzen (und damit ein kleine 
Simulatorzeiteinheit im Bereich von ps oder fs).... viel Speicher in den 
Server und ne Nacht schlafen gehen. Prozessoren zu simulieren macht da 
richtig viel Spaß, da treffen dann makroskopische Simulationszeiten im 
Bereich Millisekunden oder Sekunden auf mikroskopische 
Simulatorauflösungen im Bereich Piccosekunden... da sind Variablen dann 
auf jeden Fall dein Freund.

Gruss,
  JD

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


Lesenswert?

John Doe schrieb:
> Nee, die Begriffe wurden nicht von Professoren erfunden um die Studenten
> zu verwirren, sondern sind fundamentale Konzepte von (synchronem)
> Digital Design
Naja, mir scheint, der Begriff "concurrent" wurde einfach nur mit dem 
unüblichsten Wort übersetzt. Denn concurrent könnte heißen:
1
    gleichzeitig
2
    entsprechend
3
    simultan
4
    übereinstimmend
5
    gleichlaufend
6
    konkurrierend
7
    zusammenwirkend
8
    zusammenfallend
9
    nebenläufig
10
    nichtsequentiell
11
    nebeneinander bestehend
12
    durch einen Punkt gehend
13
    zusammentreffend
Und schon das erste Wort beschriebe den eigentlichen Sinn besser...

> Werner von Braun
Das würde dem Wernher gar nicht gefallen...
http://de.wikipedia.org/wiki/Wernher_von_Braun

> Ein Vorteil haben Variablen jedoch und zwar wenn es um die
> Simulationszeit geht.
Hast du das schon mal ausprobiert? Denn lustigerweise taucht genau 
dieses Argument (das ja früher(TM) auch für std_logic vs std_ulogic 
hergenommen wurde) bei der Gaisler-Anhängerschaft nie auf...

berndl schrieb:
> Und richtig lustig wird es, wenn du 'variable' in einem nicht getakteten
> 'process' verwendest.
Und diese Variablen dann implizit speichern oder auch nicht...
Siehe den Klassiker
Beitrag "Re: Variable vs Signal"

von spinne (Gast)


Lesenswert?

Ja, nun ist das Wochenende zu Ende und ich wundere mich, wie viele 
Antworten gab es auf meine Frage... Vielen Dank! Einiges ist klarer 
geworden, aber nicht alles. Die Hauptfrage bleibt immer noch offen: was 
genau sind Prozessen, für was steht "sequenziell" und zu welchem 
Zeitpunkt werden Signale bzw. Variablen zugewiesen (bei kombinatorischen 
Prozessen)?
1
process begin
2
3
result1 <= std_logic_vector(signed(x1)*signed(y1));
4
a <= not a;
5
wait on x1,y1;
6
end process;

Z.B., wann genau werden in so einem Prozess result1 und a zugewiesen?.. 
Und vor allem, wird das nun gleichzeitig passieren oder nicht?..

von Duke Scarring (Gast)


Lesenswert?

Lothar Miller schrieb:
>> Ein Vorteil haben Variablen jedoch und zwar wenn es um die
>> Simulationszeit geht.
> Hast du das schon mal ausprobiert? Denn lustigerweise taucht genau
> dieses Argument (das ja früher(TM) auch für std_logic vs std_ulogic
> hergenommen wurde) bei der Gaisler-Anhängerschaft nie auf...
Ich, als bekennender Anhänger der Zwei-Prozess-Methode, hätte einfach 
gar keine Lust die komplexe Logik, die ich mit der Zwei-Prozess-Methode 
realisieren kann, nochmal "klassisch" zu realisieren, nur um die 
Geschwindigkeit vergleichen zu können...

Mir graust es schon bei der Vorstellung daran, wie die "klassische" 
Implementierung mit verteilten x-Prozessen aussieht.

Für mich zählt Wartbarkeit und daß diverse Fallstricke (z.B. 
unvollständige Sensitvitätslisten, nicht initialisierte Signale, 
unerwünschte Latches) elegant umgangen werden.

Aber jeder soll bitte so Hardware beschreiben, wie er es vermag. Ich muß 
da niemanden bekehren :-)

Und um noch den Bogen zum ursprünglichen Problem zu spannen; Wenn man 
den Multipizierer mehrfach nutzen möchte, könnte man folgendes Konstrukt 
verwenden:
1
-- kombinatorisch
2
mul <= op1 * op2;
3
4
-- sequentiell
5
process
6
begin
7
  wait until rising_ege( clk);
8
  case state is
9
10
    when idle =>
11
      if startbedingung = '1' then
12
        op1   <= x;
13
        op2   <= x;
14
        state <= calcx2;
15
        busy  <= '1';
16
      end if;
17
18
    when calcx2 =>
19
      op1   <= mul;
20
      op2   <= mul;
21
      state <= calcx4;
22
23
    when calcx4 =>
24
      x_hoch_4 <= mul;
25
      op1      <= y;
26
      op2      <= y;
27
      state    <= calcy2;
28
   
29
    when calcy2 =>
30
      op1   <= mul;
31
      op2   <= mul;
32
      state <= calcy4;
33
   
34
    when calcy4 =>
35
      y_hoch_4 <= mul;
36
      state    <= idle;
37
      busy     <= '0';
38
39
  end case;
40
end process;

Duke

von Christian R. (supachris)


Lesenswert?

spinne schrieb:

> Z.B., wann genau werden in so einem Prozess result1 und a zugewiesen?..
> Und vor allem, wird das nun gleichzeitig passieren oder nicht?..

Es wird nichts "zugewiesen" da du nur rein kombinatorische Lokik 
beschreibst. Result1 und a ändern sich immer wenn sich an den 
Eingangssignalen was tut, in der Simulation sofort, auf der Hardware 
nach den Gatterlaufzeiten. Den Prozess kannst du in dem Fall weglassen. 
Das wait on wird sicherlich eh nur für die Simulation gebraucht, scheint 
die Sensitivitätsliste zu ersetzen.

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


Lesenswert?

spinne schrieb:
> Z.B., wann genau werden in so einem Prozess result1 und a zugewiesen?
Immer beim nächsten wait. Oder bei Prozessen ohne wait (also die 
"klassischen") immer am Ende des Prozesses.

spinne schrieb:
> wait on (a and b and c);
> wait on x1,y1;
Ich glaube noch immer nicht, dass das wie erwartet synthetisierbar ist. 
Denn das wäre ja ein Flipflop, das auf jede Änderung jedes der Signale 
getaktet werden könnte...
>> Welcher Synthesizer kann das?
> Der von Synopsis hat da nicht bemekert...
Das Synplify Pro, das bei Lattice dabei ist, kann es nicht. Das "wait 
on" wird ganz einfach IGNORIERT. Es kann nach wie vor nur "wait until" 
synthetisiert werden.

Aber vermutlich bin ich hier auf der falschen Spur und vermute ein 
Flipflop, wo du gar keines willst. Nochmal dein Code:
1
process begin
2
  result1 <= std_logic_vector(signed(x1)*signed(y1));
3
  result2 <= std_logic_vector(signed(x2)*signed(y2));
4
  result3 <= std_logic_vector(signed(x3)*signed(y3));
5
  wait on x1;
6
end process;
Mit dem "wait on x1" kannst du im Simulator (und nur dort!) steuern, 
dass die drei vorigen Rechenschritte nur dann "ausgeführt werden", wenn 
sich x1 ändert.

Richtigerweise wird es in der Hardware aber so implementiert:
1
process begin
2
  result1 <= std_logic_vector(signed(x1)*signed(y1));
3
  result2 <= std_logic_vector(signed(x2)*signed(y2));
4
  result3 <= std_logic_vector(signed(x3)*signed(y3));
5
  wait on x1,y1,x2,y2,x3,y3;
6
end process;
Oder gleichbedeutend und traditionell so:
1
process (x1,y1,x2,y2,x3,y3) begin
2
  result1 <= std_logic_vector(signed(x1)*signed(y1));
3
  result2 <= std_logic_vector(signed(x2)*signed(y2));
4
  result3 <= std_logic_vector(signed(x3)*signed(y3));
5
end process;
Was aber ohne Prozess concurrent mit exakt gleichem Ergebnis auch gleich 
so geschrieben werden könnte:
1
result1 <= std_logic_vector(signed(x1)*signed(y1));
2
result2 <= std_logic_vector(signed(x2)*signed(y2));
3
result3 <= std_logic_vector(signed(x3)*signed(y3));

spinne schrieb:
1
process begin 
2
  result1 <= std_logic_vector(signed(x1)*signed(y1)); 
3
  a <= not a; 
4
  wait on x1,y1; 
5
end process;
> Und vor allem, wird das nun gleichzeitig passieren oder nicht?..
Löse diesen unnötigen (und unvollständigen) Prozess einfach mal auf und 
schreibe diese beiden Zeilen ohne Prozess concurrent hin:
1
  result1 <= std_logic_vector(signed(x1)*signed(y1)); 
2
3
  a <= not a;
Und jetzt beantworte die Frage: was passiert hier gleichzeitig?
Antwort: in einem Teil des FPGAs wird ein Multiplizierer instanziiert, 
an den am Eingang x1 und y1 und am Ausgang result1 angeschlossen sind, 
und in einem anderen Teil bildet gleichzeitig ein Nicht-Gatter (das a) 
eine kombinatorische Schleife...

von spinne (Gast)


Lesenswert?

Ok, ich stelle die Frage etwas anders:

1)Es geht jetzt nur um Hardware
2)t ist ein externes Triggersignal (Ein Taster auf meinem 
Entwicklungsbord)
3)x1 und y1 sinde jeweils Taster, result1 - LEDs
4)a ist auch ein LED
5)es funktioniert alles in der Hardware und das Ergebnis der 
Multiplikation stimmt.
6)a ändert sein Wert mit jeder steigenden Flanke des t.

Nun die Fragen:

1) sind a und result1 gleichzeitig gesetzt?
2) ist der Zeitpunkt der Zuweisung (oder wie sich das sonst nennt) in 
etwe gleich "Zeitpunkt der rising_edge(t) + Multiplikationsdauer"?
1
architecture Behave of MUL is
2
signal b : std_logic;
3
begin
4
process begin
5
wait until rising_edge(t);
6
result1 <= std_logic_vector(signed(x1)*signed(y1));
7
b <= not b;
8
end process;
9
a <= b;
10
end;

von spinne (Gast)


Lesenswert?

Lothar Miller schrieb:
> spinne schrieb:
>> wait on (a and b and c);
>> wait on x1,y1;
> Ich glaube noch immer nicht, dass das wie erwartet synthetisierbar ist.
> Denn das wäre ja ein Flipflop, das auf jede Änderung jedes der Signale
> getaktet werden könnte...
>>> Welcher Synthesizer kann das?
>> Der von Synopsis hat da nicht bemekert...
> Das Synplify Pro, das bei Lattice dabei ist, kann es nicht. Das "wait
> on" wird ganz einfach IGNORIERT. Es kann nach wie vor nur "wait until"
> synthetisiert werden.

Sorry, Lothar, das war mein Fehler, natürlich hatte ich überall wait 
untill benutzt.

Lothar Miller schrieb:
> Löse diesen unnötigen (und unvollständigen) Prozess einfach mal auf und
> schreibe diese beiden Zeilen ohne Prozess concurrent hin:  result1 <=
> std_logic_vector(signed(x1)*signed(y1));
>
>   a <= not a;

Warum denn ist hier ein Prozess unnötig?

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


Lesenswert?

spinne schrieb:
> Warum denn ist hier ein Prozess unnötig?
Warum sollte einer nötig sein?


> natürlich hatte ich überall wait untill benutzt.
Also so etwa:
  wait until x1,y1;
Das geht nicht, weil:
Lothar Miller schrieb:
> das wäre ja ein Flipflop, das auf jede Änderung jedes der Signale
> getaktet werden könnte...


spinne schrieb:
> t ist (Ein Taster auf meinem Entwicklungsbord)
> ...
> wait until rising_edge(t);
Aua...
Such mal nach "Postulate" hier im VHDL-Forum...



Ok, die Karten werden neu gemischt:
spinne schrieb:
1
architecture Behave of MUL is 
2
signal b : std_logic; 
3
begin 
4
  process begin 
5
    wait until rising_edge(t); 
6
    result1 <= std_logic_vector(signed(x1)*signed(y1)); 
7
    b <= not b; 
8
  end process; 
9
10
  a <= b; 
11
end;

> 1) sind a und result1 gleichzeitig gesetzt?
Ja. So "gleichzeitig" wie möglich (ein paar ps sind da immer drin).

> 2) ist der Zeitpunkt der Zuweisung (oder wie sich das sonst nennt) in
> etwe gleich "Zeitpunkt der rising_edge(t) + Multiplikationsdauer"?
Nein.
Du schaltest hier hinter den Multiplizierer noch für jedes Bit 1 
Flipflop und du schaltest hinter ein Nicht-Gatter ein Fipflop. Und mit 
der steigenden Flanke wird das vorher berechnete Ergebnis der 
Multiplikation und der Negation (das sind die beiden Rechnungen, die im 
Prozess auftauchen) in diese Flipflops gespeichert.

Sieh dir einfach mal den RTL-Schaltplan deines Designs an...

von spinne (Gast)


Lesenswert?

Lothar Miller schrieb:
> Du schaltest hier hinter den Multiplizierer noch für jedes Bit 1
> Flipflop und du schaltest hinter ein Nicht-Gatter ein Fipflop. Und mit
> der steigenden Flanke wird das vorher berechnete Ergebnis der
> Multiplikation und der Negation (das sind die beiden Rechnungen, die im
> Prozess auftauchen) in diese Flipflops gespeichert.
>
> Sieh dir einfach mal den RTL-Schaltplan deines Designs an..

Also, dann müssen auch nach jedem IO-Pin auch FF's kommen? Sonst würde 
ja das Ergebnis nicht stimmen. Falls es so ist, fange ich langsam an zu 
verstehen, was eigentlich passiert. Dann kriege ich unmittelbar nach 
jede steigende Flanke von t die vorherige werte von a und result1, 
richtig?..

Lothar Miller schrieb:
> spinne schrieb:
>> t ist (Ein Taster auf meinem Entwicklungsbord)
>> ...
>> wait until rising_edge(t);
> Aua...
> Such mal nach "Postulate" hier im VHDL-Forum...

Da wird wahrscheinlich das "Einsynchronisieren" gemeint? Aber ich habe 
gar kein anderen Taktsignal. Oder liegt mein Fehler woanders?..

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


Lesenswert?

spinne schrieb:
> Also, dann müssen auch nach jedem IO-Pin auch FF's kommen?
Es sieht so aus:
1
 
2
   t ----------------.     
3
                     |    _____
4
           ____      o---|>    | viele Fliflops
5
   x1 ----|    \     |   |     |
6
          | x   >----+---|D   Q|----------------- result1
7
   y1 ----|____/     |   |_____|
8
                     |    _____
9
                     '---|>    | ein Flipflop
10
                         |     | 
11
                      .--|D   Q|---o------------- a
12
                      |  |_____|   |
13
                      |            | b
14
                      '-----o<|----'


spinne schrieb:
> Da wird wahrscheinlich das "Einsynchronisieren" gemeint?
Nimm einen Takt aus einem Taktoszillator. Synchronieisere den Taster ein 
und setze eine Flankenerkennung drauf.

von Schlumpf (Gast)


Lesenswert?

@Spinne
Ich hab´s jetzt nur überflogen und nicht alles genauestens durchgelesen, 
das mal vorweg.
Mein Eindruck ist, dass du weisst, dass ein Prozess in VHDL "getriggert" 
wird. Entweder durch die Sensitivity-Liste oder durch ein wait.
Das ist auch richtig, aber das ist etwas, was für die Simulation gedacht 
ist. In VHDL kann man viel mehr an Funktionalität beschreiben, als dann 
eigentlich so in Hadware abgebildet werden kann.

Die oben beschriebene Eigenschaft eines Prozesses kann man nicht ohne 
Weiteres der Synthese vorlegen und hoffen, dass sie da "Richtige" daraus 
bastelt.
Eine Zeitabhängigkeit kann auf realer Hardware nur vernünftig mit einem 
Takt realisiert werden, auf dessen Flanke reagiert wird. Und genau das 
sind dann Register. Natürlich gibt es auf der realen Hadware Laufzeiten 
zwischen den Logikfunktionen, aber sich die in einem FPGA zunutze machen 
zu wollen, ist etwas, was einem nur gelingt, wenn man recht tiefes 
Verständnis von der Materie hat und erfodert Fingerspitzengefühl beim 
Constraining.
Zu allem Übel sind diese Zeiten dann noch sehr temperaturabhängig.
Fazit: Sowas macht keiner freiwillig!

Wenn du einen ungetakteten Prozess bechreibst, bei dem alle Eingänge in 
der Sensitivity-Liste auftauchen, dann macht die Synthese meines 
Erachtens exakt das Gleiche daraus, wie wenn du es einfach concurrent 
hinschreibst.
Die Tatsache, dass du kombinatorische Zuweisungen in einen Prozess 
packst, macht diese noch lange nicht sequenziell.

Zurück zu deinem Problem.
Wenn du einen Multiplizierer merhfach verwenden willst, dann stelle dir 
vor, wie du das in Hardware lösen würdest.
Du würdest EINEN Multiplizierer verwenden, einen Multiplexer 
davorschalten und dann das Ergebnis der ersten Multiplikation in einem 
Register zwischenspeichern. Im nächsten Schritt würdest du dann den Mux 
umschalten und das gespeicherte Ergebnis mit dem nächsten Operand 
verknüpfen.

Und genau diesen "nächsten Schritt" kannst du nur sinnvoll mit einem 
Takt vom ersten Schritt separieren.

von spinne (Gast)


Lesenswert?

Genau, so habe ich mir das alles vorgestellt. Vielen Dank, Lothar, nun 
ist für mich viel mehr klar geworden. Was die Einsynchronisierung 
angeht, ich weiß, wie und wozu man das macht. Vielleicht, sieht das ganz 
dumm und komisch aus, aber ich habe einfach nach einer Möglichkeit 
gesucht ein getakteter Prozess durch ein kombinatorischen zu ersetzen 
und dadurch mehr Effizienz zu gewinnen (variable statt feste 
Abtastzeiten, weniger Stromverbrauch). Nun sehe ich, dass es nicht 
möglich ist.

von spinne (Gast)


Lesenswert?

Schlumpf schrieb:
> Fazit: Sowas macht keiner freiwillig!

Vielen Dank auch dir, Schlumpf, für deine Feedback!

Nun sehe ich meinen Gedankenfehler. Ich habe mir nur überlegt, dass so 
was möglich wäre. Leider habe ich überhaupt keine Erfahrung in 
Digitalelektronik und VHDL und konnte es mir nicht vorstellen, wie 
schwierig es wäre, so was zu realisieren. Nun weiß ich das.

von Schlumpf (Gast)


Lesenswert?

spinne schrieb:
> Leider habe ich überhaupt keine Erfahrung in
> Digitalelektronik

Hallo Spinne, das ist genau das Problem. Ohne Kenntnisse in de 
Digitalelektronik kann man keinen vernünftigen synthetisierbaren 
HDL-Code erzeugen. VHDL ist keine Programmiersprache, sondern eine 
Beschreibungssprache mit der man eben genau Digitalelektronik 
beschreibt.
Es ist ein Werkzeug, um mehr oder weniger komplexe Digitale 
Zusammenhänge abstrakt darzustellen. Wenn man aber von dem, was man 
beschreiben will, (noch) keine Kenntnisse hat, dann ist es eigentlich 
auch zum Scheitern verurteilt, dies abstrakt darzustellen :-)

Als Einstieg in die Materie würde ich dir empfehlen, dass du dich 
erstmal mit den Grundelementen der Digitaltechnik vertraut machst 
(Zähler, Gatter, Mux, ...). Im nächsten Schritt kannst du dann diese 
Elemente in VHDL darstellen. Dazu gibt es auch jede Menge Literatur. 
Aktuell gibt es sogar ein Buch zum kostenlosen Download. Den Link dazu 
findest du in einem der Threads hier.

Ein rein kombinatorisches Design kann man natürlich auch in einem FPGA 
machen, aber dann ist es eben rein kombinatorisch. Sobald aber 
Verknüpfungen und Funktionen in einer gewissen zeitlichen Ordung 
durchgeführt werden sollen, dann braucht dein System eine Zeitbasis. Und 
diese ist der Systemtakt.

von spinne (Gast)


Lesenswert?

Schlumpf schrieb:
> Als Einstieg in die Materie würde ich dir empfehlen, dass du dich
> erstmal mit den Grundelementen der Digitaltechnik vertraut machst
> (Zähler, Gatter, Mux, ...

So schlimm sieht's bei mir auch nicht aus =) Theoretische 
Grundkenntnisse sind ja vorhanden, leider nicht so viel, wie bei einem 
Elektrotechnikstudium. Und ich bin gerade dabei, vorhandene Lücken zu 
verschließen. Das VHDL-Synthese Buch von Reichardt/Schwarz versuche ich 
schon seit einer Woche herunterzuladen, geht leider in der letzten Zeit 
nicht. Schade, wäre ja sehr hilfreich.

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


Lesenswert?

spinne schrieb:
> Das VHDL-Synthese Buch von Reichardt/Schwarz versuche ich schon seit
> einer Woche herunterzuladen
Kauf es doch einfach. Ausdrucken kostet mehr...

von Schlumpf (Gast)


Lesenswert?

Momentan gibt es dieses Buch für lau...

http://www.degruyter.com/view/product/223820

von spinne (Gast)


Lesenswert?

Schlumpf schrieb:
> Momentan gibt es dieses Buch für lau...
>
> http://www.degruyter.com/view/product/223820

Dieses Buch habe ich gerade gestern Abend heruntergeladen.

Lothar Miller schrieb:
> spinne schrieb:
>> Das VHDL-Synthese Buch von Reichardt/Schwarz versuche ich schon seit
>> einer Woche herunterzuladen
> Kauf es doch einfach. Ausdrucken kostet mehr...

Ich könnte ja es auch in der Hochschulbibliothek ausleihen, mache aber 
mit Absicht nicht, weil ich praktisch nur unterwegs auf dem Tablet lese. 
Hoffe, dass es noch Möglichkeit geben wird, das Buch bis zum Ende August 
herunterzuladen...

von Spinne (Gast)


Lesenswert?

Hallo!

Seit meinem letzten Beitrag habe ich ziemlich große Vorschritte gemacht 
(im allg.Verständniss, als auch in meinem Projekt). Aber Probleme gibt 
es immer noch genug.
Mit zwei davon kämpfe ich seit 1 Woche und bis jetzt hab keine Lösung 
bzw. Antwort gefunden.

Das Herzstück meines Codes ist eine FSM mit derzeit 4 Zuständen. In 2 
Zuständen wird einen Zähler mit verschiedenen werten geladen (abhängig 
von der Anzahl der durchzuführenden Multiplikationen). Im Step1 wird den 
Zähler einige Durchläufe machen, im Step2 nur eins. Nun zu den Fragen:

1). Als erstes, hat mir aufgefallen, dass mein Design nach der Synthese 
unerwartet groß ist. Ich benutze nur 1 32-Bit Multiplizierer (laut 
Syntesizer 3,7k LE), 3 37-Bit Addierer (ca.0,7k LE) und diverse Register 
für geschätzt 2,5k LE max. Alles zusammen also ca 7k LE. Mein Design ist 
laut Synthesizer 16k LE groß. Könnte das sein, dass alles 2 mal 
implementiert wurde? Oder ist so was in Ordnung?

2). Ich kann die Funktionalität meines Codes nicht testen, weil es für 
den zur Verfügung stehenden Entwicklungsbord zu groß ist und die 
Simulation in ModelSim läuft nicht richtig. Die FSM funktioniert gar 
nicht, keiner von Zuständen wird gesetzt. Unten der gekürzte Code, den 
tadellos in der HW funktioniert, nicht aber in der Simulation. Woran 
kann das denn liegen?
1
library IEEE;
2
3
use IEEE.std_logic_1164.all;
4
use IEEE.NUMERIC_STD.ALL;
5
6
entity Parameterschaetzverfahren_Core_VHDL is
7
port (
8
  clk    : in  std_logic;
9
    I    : in   std_logic_vector(5 downto 0);          -- I als Trigger - Signal vom Datenerfassung Core
10
  test  : out  std_logic_vector(3 downto 0));
11
end Parameterschaetzverfahren_Core_VHDL;
12
13
architecture Verhalten of Parameterschaetzverfahren_Core_VHDL is
14
15
   -- signal, component etc. declarations
16
17
type fsm is (init, step1, step2, done);              --Zustandautomat
18
signal state    : fsm := init;
19
signal cnt      : integer range 0 to 50 := 0;
20
21
begin
22
Unterdeterminanten: process begin
23
wait until rising_edge(clk);
24
  if I(5) = '0' then state <= init;end if;
25
    case state is
26
      when  init  =>                  --Initialisieren von Signalen: Anfangszustand 0
27
          test    <= "1000";
28
          if I(5) = '1' then state <= step1; cnt <= 0;  --auf LSB von I triggern, Zustandsänderung
29
          end if;
30
      when  step1  =>
31
          test    <= "0100";
32
          if cnt < 50 then cnt <= cnt + 1; end if;
33
            case cnt is    
34
              when 50  =>
35
                  if I = "111111" then
36
                    state <= step2;
37
                    cnt <= 0;
38
                  else cnt <= 0;
39
                  end if;
40
              when others  => null;
41
            end case;
42
      when  step2  =>  
43
          test    <= "0010";    
44
          if cnt < 50 then cnt <= cnt + 1; end if;
45
            case cnt is
46
              when 50  =>
47
                state <= done;
48
                cnt <= 0;
49
            end case;
50
      when  done  =>
51
        test    <= "0001";
52
      end case;
53
  end process;
54
end verhalten;

Für alle Hinweise auf meine dummen Fehler wäre ich sehr dankbar ;)

von Ludolf Lustig (Gast)


Lesenswert?

Mglw. ist I(5) in der Simu immer 'U' (nicht initialisiert) und damit 
läuft die FSM nicht an.

von Spinne (Gast)


Lesenswert?

Danke, aber das sollte bei mir richtig sein. Ich definiere clk als Takt 
und ändere entsprechend I. Die beiden Signale sehe ich dann in der 
Simulation als richtig belegt. Aber test bleibt immer auf UUUU.

von Duke Scarring (Gast)


Lesenswert?

Spinne schrieb:
> nicht aber in der Simulation
Hast Du noch eine passende Testbench zu Deinem Code?
Damit können andere Forumsteilnehmer Deine Simulation nachvollziehen.

Duke

von Ludolf Lustig (Gast)


Lesenswert?

braucht es doch eine sensetivity list?
allo optimierungslevel abgeschaltet?

von Ludolf Lustig (Gast)


Lesenswert?

stimmen ports in component deklaration und Instanziierung?
code in die richtige Bibliothek kompiliert?

von Spinne (Gast)


Lesenswert?

Duke Scarring schrieb:
> Hast Du noch eine passende Testbench zu Deinem Code?
> Damit können andere Forumsteilnehmer Deine Simulation nachvollziehen.
>
> Duke

Nein, habe ich nicht. Ich mach es so, dass ich im ModelSim einfach auf 
den Signalname mit rechter Maustaste drücke und dann das Signal als Takt 
definiere oder einen Wert vorgebe (Force...). Bis jetzt funktionierte 
sowas immer richtig...

von Ludolf Lustig (Gast)


Lesenswert?

Spinne schrieb:
> Duke Scarring schrieb:
>> Hast Du noch eine passende Testbench zu Deinem Code?
>> Damit können andere Forumsteilnehmer Deine Simulation nachvollziehen.
>>
>> Duke
>
> Nein, habe ich nicht. Ich mach es so, dass ich im ModelSim einfach auf
> den Signalname mit rechter Maustaste drücke und dann das Signal als Takt
> definiere oder einen Wert vorgebe (Force...). Bis jetzt funktionierte
> sowas immer richtig...

force macht immer mal wieder Probleme:

 Beitrag "Modelsim Clock Signal erzeugen"

ein paar zeilen vhdl sind besser.

MfG

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


Lesenswert?

Spinne schrieb:
>> Hast Du noch eine passende Testbench zu Deinem Code?
> Nein, habe ich nicht.
Mach das doch. Das kostet dich bei diesem Projekt keine halbe Stunde. 
VHDL kannst du ja schon...

> (Force...). Bis jetzt funktionierte sowas immer richtig...
Ich bin froh, dass ich diesen Murks nie angefangen habe...  ;-)

Spinne schrieb:
> Ich benutze nur 1 32-Bit Multiplizierer (laut Syntesizer 3,7k LE), 3
> 37-Bit Addierer (ca.0,7k LE) und diverse Register für geschätzt 2,5k LE
> max. Alles zusammen also ca 7k LE. Mein Design ist laut Synthesizer 16k
> LE groß.
Was sind das für Zahlen? was ist eine "k LE"? Ich rechne meine Designs 
in einzelnen Flipflops (also nicht "kilo Flipflops") aus...


Dir sind die möglichen Probleme dieser Beschreibung bewusst?
1
  if I(5) = '0' then state <= init; end if;       -- Zuweisung an state
2
3
    case state is
4
      when  init  => 
5
          :
6
          if I(5) = '1' then state <= step1;      -- Zuweisung an state
7
          :
8
              when 50  =>
9
                state <= done;                    -- Zuweisung an state
10
          :
Stichwort: die letzte Zuweisung im Prozess "gewinnt"

von spinne (Gast)


Lesenswert?

Lothar Miller schrieb:
> Spinne schrieb:
>>> Hast Du noch eine passende Testbench zu Deinem Code?
>> Nein, habe ich nicht.
> Mach das doch. Das kostet dich bei diesem Projekt keine halbe Stunde.
> VHDL kannst du ja schon...

Ok, ich werde mich damit mehr beschäftigen.

Lothar Miller schrieb:
> Was sind das für Zahlen? was ist eine "k LE"? Ich rechne meine Designs
> in einzelnen Flipflops (also nicht "kilo Flipflops") aus...

Ja, ich habe mit "k" kilo gemeint. "LE" steht für Logik Elemente, aber 
ich weiß leider nicht auf 100%, was damit vom Hersteller gemeint war. 
Mein FPGA hat 6000 LEs und 250000 Gatter(das sind wahrscheinlich "reine" 
FFs), nach der Synthese wird mir den Logikverbrauch in LEs angezeigt. 
Aber es geht eigentlich nur darum, dass das Design zu groß ist, egal in 
welchen Einheiten.

Lothar Miller schrieb:
> Dir sind die möglichen Probleme dieser Beschreibung bewusst?  if I(5) =
> '0' then state <= init; end if;       -- Zuweisung an state
>
>     case state is
>       when  init  =>
>           :
>           if I(5) = '1' then state <= step1;      -- Zuweisung an state
>           :
>               when 50  =>
>                 state <= done;                    -- Zuweisung an state
>           :
> Stichwort: die letzte Zuweisung im Prozess "gewinnt"

Hmm... Nun verstehe ich gar nicht, über was die Rede ist... Was für 
Probleme kann es hier geben?.. Für eine Erklärung wäre ich sehr dankbar.

von spinne (Gast)


Lesenswert?

Ludolf Lustig schrieb:
> force macht immer mal wieder Probleme...

Mag sein, ich versuche morgen einen Testbench zu schreiben (hab früher 
noch nicht gemacht). Danke für die Hinweise!

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


Lesenswert?

spinne schrieb:
> Lothar Miller schrieb:
>> Dir sind die möglichen Probleme dieser Beschreibung bewusst?
>> Stichwort: die letzte Zuweisung im Prozess "gewinnt"
> Hmm... Nun verstehe ich gar nicht, über was die Rede ist... Was für
> Probleme kann es hier geben?.. Für eine Erklärung wäre ich sehr dankbar.
Du hast hier 2 Probleme:
1. Auch wenn du schon ganz am Anfang über I(5) dem dem state den Wert 
init zuweist, wird dieser Wert nur zwischengespeichert und der Prozess 
trotzdem mit dem alten Wert von state durchlaufen.

2. Während des Durchlaufens kann der Wert von state immmer wieder 
überschrieben werden. Erst am Ende des Prozesses wird der dann aktuelle 
Wert aus dem Zwischenspeicher auf das Signal abgebildet.

Du wirst hier für das Signal antwort also immer nur den Wert 42 zu 
sehen bekommen, weil "die letzte Zuweisung gewinnt":
1
   process begin
2
      wait until rising_edge(clk);
3
4
      antwort <= 8411;
5
6
      if nix then
7
          antwort <= 0815;
8
      elsif zero
9
          antwort <= 0;
10
      end if;
11
      
12
      antwort <= 42;
13
   end process;


Das bedeutet, dass du einen synchronen Reset am einfachsten am Ende 
eines Prozesses beschreibst:
1
   process begin
2
      wait until rising_edge(clk);
3
      -- normaler Ablauf
4
      if reset='1' then
5
         -- Resetbehandlung
6
      end if;
7
  end process;

Oder in der traditionellen Art mit einer zusätzlichen umschließenden 
if-Abfrage:
1
   process begin
2
      wait until rising_edge(clk);
3
      if reset='1' then
4
         -- Resetbehandlung
5
      else
6
         -- normaler Ablauf
7
      end if;
8
  end process;


> Mag sein, ich versuche morgen einen Testbench zu schreiben (hab früher
> noch nicht gemacht). Danke für die Hinweise!
Sieh dir das mal an:
http://www.lothar-miller.de/s9y/archives/89-BCD-nach-Binaer-wandeln.html
Eine einfache Aufgabe und die passende kleine Testbench dazu...

BTW: eine Testbench erkannt man daran, dass sie keine Ports hat. Die 
Deklaration der Entity sieht also so aus:
1
ENTITY meine_testbench IS
2
END meine_testbench;

: Bearbeitet durch Moderator
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.