Hallo Forum!
Ich möchte hier jetzt keinen Glaubenskrieg hervorrufen, sondern
lediglich ein paar dritte Meinungen einholen.
Ich designe Logic jetzt schon seit ein paar Jahren und habe in der Zeit
viele verschiedene Sitle gesehen in denen man FSMs schreiben kann. Ganz
früher habe ich die Ein-Prozess-Schreibweise verwendet, da ich vorher
hauptsächlich in C++ programmiert habe. Das sah dann z.B. so aus:
1
state_selector:process(clk,reset)is
2
begin
3
ifreset='0'then
4
state<=r;
5
elsifrising_edge(clk)then
6
casestateis
7
wheny=>
8
state<=r;
9
red<='0';
10
yellow<='1';
11
green<='0';
12
wheng=>
13
state<=y;
14
red<='0';
15
yellow<='0';
16
green<='1';
17
whenry=>
18
state<=g;
19
red<='1';
20
yellow<='1';
21
green<='0';
22
whenr=>
23
state<=ry;
24
red<='1';
25
yellow<='0';
26
green<='0';
27
whenothers=>null;
28
endcase;
29
endif;
30
endprocessstate_selector;
Irgendwann fand ich das dann zu unübersichtlich und habe auf die
Zwei-Prozess-Schreibweise gewechselt:
1
state_selector:process(clk,reset)is
2
begin
3
ifreset='0'then
4
state<=r;
5
elsifrising_edge(clk)then
6
casestateis
7
wheny=>state<=r;
8
wheng=>state<=y;
9
whenry=>state<=g;
10
whenr=>state<=ry;
11
whenothers=>null;
12
endcase;
13
endif;
14
endprocessstate_selector;
15
16
output_generator:process(clk,reset)is
17
begin
18
ifreset='0'then
19
red<='1';
20
yellow<='0';
21
green<='0';
22
elsifclk'eventandclk='1'then-- rising clock edge
23
casestateis
24
whenr=>
25
red<='1';
26
yellow<='0';
27
green<='0';
28
wheny=>
29
red<='0';
30
yellow<='1';
31
green<='0';
32
wheng=>
33
red<='0';
34
yellow<='0';
35
green<='1';
36
whenry=>
37
red<='1';
38
yellow<='1';
39
green<='0';
40
whenothers=>null;
41
endcase;
42
endif;
43
endprocessoutput_generator;
Während der erste Prozess jetzt schön übersichtlich ist, gefiel mir der
zweite Prozess noch nicht wirklich. Vor allem, weil dort immer noch sehr
viele redundante Signal-Zuweisungen sind, die viel Schreibarbeit
bedeuten.
Also habe ich später den zweiten Prozess in ein conditional assignment
umgeformt:
1
state_selector:process(clk,reset)is
2
begin
3
ifreset='0'then
4
state<=r;
5
elsifrising_edge(clk)then
6
casestateis
7
wheny=>state<=r;
8
wheng=>state<=y;
9
whenry=>state<=g;
10
whenr=>state<=ry;
11
whenothers=>null;
12
endcase;
13
endif;
14
endprocessstate_selector;
15
16
red<='1'whenstate=rorstate=ryelse'0';
17
yellow<='1'whenstate=yorstate=ryelse'0';
18
green<='1'whenstate=gelse'0';
Das ist schon mal bedeutet kürzer und übersichtlicher. Jedoch nicht ohne
Nachteile: Zum einen sind die Ausgangssignale (red, yellow, green) nicht
mehr synchron, was bei komplizierteren whens eventuell ein Problem sein
könnte. Und zum anderen started die FSM nach dem Reset jetzt nicht mehr
im State r sondern im State y. Die Funktionalität ist also anders.
Zumindest letzteres ließ sich relativ einfach fixen, indem man die
Schreibweise für den zweiten Prozess auch für den ersten übernimmt:
1
state_transition:process(clk,reset)is
2
begin
3
ifrising_edge(clk)then
4
state<=next_state;
5
endif;
6
endprocessstate_transition;
7
8
next_state<=rwhenstate=yorreset='0'else
9
ywhenstate=gelse
10
gwhenstate=ryelse
11
rywhenstate=relse
12
state;
13
14
red<='1'whenstate=rorstate=ryelse'0';
15
yellow<='1'whenstate=yorstate=ryelse'0';
16
green<='1'whenstate=gelse'0';
die FSM startet jetzt wieder im State r und das ganze ist sogar noch mal
eine Zeile kürzer. Die Ausgänge sind aber leider immer noch nicht
synchron. Also habe ich hinter den zweiten Prozess noch ein paar
Register gehängt und frage next_state anstatt state ab:
ERROR:HDLCompiler:1690 - "fsmX.vhd" Line 25: This construct is only supported in VHDL 1076-2008
2
ERROR:HDLCompiler:1690 - "fsmX.vhd" Line 36: This construct is only supported in VHDL 1076-2008
3
ERROR:HDLCompiler:1690 - "fsmX.vhd" Line 37: This construct is only supported in VHDL 1076-2008
4
ERROR:HDLCompiler:1690 - "fsmX.vhd" Line 38: This construct is only supported in VHDL 1076-2008
5
ERROR:HDLCompiler:854 - "fsmX.vhd" Line 15: Unit <behav> ignored due to previous errors.
Schade, aber das kann man nichts machen. (Oder können die Xilinx Tools
VHDL 2008? Wenn ja, welche Command Line Switches brauche ich da?)
Naja, wie auch immer. Welche von den schreibweisen gefällt euch denn am
besten bzw. welche benutzt ihr meistens? Ich benutze momentan meistens
Schreibweise 4 oder 5, je nachdem ob es wichtig ist, dass die
Ausgangssignale synchron sein müssen oder nicht. Die Schreibweisen habe
ich bisher aber sonst nirgens gesehen. Woran könnte das liegen?
Grüße,
Sally
Sally schrieb:> Welche von den schreibweisen gefällt euch denn am> besten bzw. welche benutzt ihr meistens?
Die allererste. Weil da jeder auf Anhieb sofort sieht, was gemeint ist.
Alles Nachfolgende ist nur noch verwaschener und verbastelter. Und ganz
am Schluss kommen sogar 2 getaktete Prozesse raus... :-o
Sally schrieb:> Aber das geht wohl erst in VHDL 2008, meint fuse:
Ja, das ist eigentlich ein Concurrent Statement in einem Prozess. Man
kann ja Kraut und Rüben und Kohl und Kartoffeln mischen und mixen. Wenns
einem hinterher schmeckt...
Ich würde da anpacken, wo die meisten Zeilen anfallen: bei der
Farbengeschichte. Und dann sähe das so aus:
> Die allererste. Weil da jeder auf Anhieb sofort sieht, was gemeint ist.> Alles Nachfolgende ist nur noch verwaschener und verbastelter.> Und ganz am Schluss kommen sogar 2 getaktete Prozesse raus... :-o
Interessant. Ich finde es übersichtlicher, wenn alles schön säuberlich
getrennt ist. Und es sieht nicht mehr so nach prozedualem Code aus, was
VHDL ja nicht ist.
Du programmierst vermutlich mehr in C als in VHDL, oder? Das würde
deinen prozedualen Stil in VHDL erklären. ^^
> Ja, das ist eigentlich ein Concurrent Statement in einem Prozess. Man> kann ja Kraut und Rüben und Kohl und Kartoffeln mischen und mixen. Wenns> einem hinterher schmeckt...
Würde mir durchaus schmecken. Es ist deutlich kürzer und dadurch finde
ich es einfacher lesbar. Aber Xilinx kann ja leider kein VHDL 2008...
> Ich würde da anpacken, wo die meisten Zeilen anfallen: bei der> Farbengeschichte. Und dann sähe das so aus:> [...]> Und weil lamps synchron ist, sind auch die Ausgänge red, yellow> und green synchron.
Sehr hübsch und bei diesem einfachen Beispiel geht das auch ganz gut.
Wenn du aber mehrere unabhängige Signale hast, die alles etwas
unterschiedliches tun, wird das schnell sehr hässlich. ;)
Sally schrieb:> Du programmierst vermutlich mehr in C als in VHDL, oder?
Nein, ich "programmiere" gar nicht ind VHDL. Ich stelle mir meine
Schaltung vor und beschreibe die dann mit VHDL.
> Das würde deinen prozedualen Stil in VHDL erklären. ^^
Nein, ich habe quasi einen Synthesizer "im Kopf" (Übung), der mir diese
Verhaltensbeschreibung beim Schreiben in einen RTL-Plan umsetzt. Ich
kann mir also gut erklären, warum ich das genau so hingeschrieben habe.
> Sehr hübsch und bei diesem einfachen Beispiel geht das auch ganz gut.> Wenn du aber mehrere unabhängige Signale hast, die alles etwas> unterschiedliches tun, wird das schnell sehr hässlich. ;)
Ich kann dir das Gegenteil beweisen... ;-)
Schreib du mal, hmmm... naja, sagen wir eine serielle Schnittstelle mit
dieser Entity:
Moin,
haha, ein provokanter Klassiker.
Leider liegt's wie immer im Auge des Betrachters. Einige Kollegen sind
"harte Elektroniker" und lesen VHDL am leichtesten, wenn die 74XX-Logik
irgendwie dahinter erkennbar ist. Manche wiederum (wie meinereiner)
mögens's pragmatisch aufgeräumt und möglichst zentral verwaltet.
Persönlich ziehe ich es vor, ab einer gewissen Anzahl Dekodierungen die
aus den States erzeugten Signale aus dem Haupt-FSM-Prozess
herauszuziehen. Und zwar ab dem Zeitpunkt, wo der Process nicht mehr auf
eine Bildschirmseite geht.
Was Zweiprozess-Methode angeht: Die nutze ich nur, wenn einige Prozesse
vorausschauend auf den "next_state" reagieren müssen, oder Ereignisse
zwischen speziellen State-Übergängen decodiert werden sollen.
Kommt aber eher selten vor, genauer, solche fiesen Sachen waren nur bei
Hardwaredebugger-Implementationen nötig.
Generell gilt wohl: Alles was gut in LUTs passt, ist des FPGAs Freund
(wenig Resourcenverbrauch). Wenn man sich die Synthese-Logs diverser
Tools anschaut, findet man oft auch Hinweise, die zur vereinfachten
Codierung und Lesbarkeit beitragen...
Und ab einer gewissen Komplexität ist ein kleiner stupider Softcore
(Sequenzer) mit selbstdefinierten Opcodes die bessere State-Machine.
> Nein, ich "programmiere" gar nicht ind VHDL. Ich stelle mir meine> Schaltung vor und beschreibe die dann mit VHDL.
Ach komm schon, auf dieser Ebene müssen wir nicht streiten. Wir sind
doch beide Erwachsen, oder? Du weißt doch ganz genau, was ich meine. ;)
> Nein, ich habe quasi einen Synthesizer "eingebaut" (Übung), der mir> diese Verhaltensbeschreibung beim Schreiben in einen RTL-Plan umsetzt.> Ich kann mir also gut erklären, warum ich das genau so hingeschrieben> habe.
Das höre ich oft von Leuten, die noch nicht lange mit VHDL arbeiten.
Meistens ist das was man sich da vorstellt nicht sehr nahe am
Syntheseergebnis. ^^
> Ich kann dir das Gegenteil beweisen... ;-)> Schreib du mal, hmmm... naja, sagen wir eine serielle Schnittstelle mit> dieser Entity:
Danke, das habe ich schon hinter mir. Im Moment beschäftige ich mich mit
Ethernet Frames, das ist ein bisschen komplizierter. ;)
> Wenn du dir dazu dann mal Gedanken gemacht hast, darfst du auch meine> Lösung ansehen:> http://www.lothar-miller.de/s9y/categories/42-RS232
Wie von dir erwartet auch sehr prozedual gehalten. ^^
Wenn ich z.B. wissen möchte, wann sich txcnt ändert, muss ich den
gesamten Prozess absuchen, dabei könnte man das auch schön in einer
Zeile schreiben (wie in meinem Beispiel 3ff oben) Dann laufe ich auch
nicht Gefahr in einem Zweig mal eine Zuweisung zu vergessen und
generiere keine unerwünschten Latches, die bei komplizierteren FSMs zu
scheinbar unerklärlichem Verhalten führen.
Aber wenn du mit der prozedualen Schreibweise besser zurecht kommst, ist
das natürlich in Ordnung. Ich mache ja nur eine Meinungsumfrage. ;)
Andere Meinungen dazu?
> Generell gilt wohl: Alles was gut in LUTs passt, ist des FPGAs Freund> (wenig Resourcenverbrauch). Wenn man sich die Synthese-Logs diverser> Tools anschaut, findet man oft auch Hinweise, die zur vereinfachten> Codierung und Lesbarkeit beitragen...
Ja, das stimmt wohl. ^^ Ich sehe es leider zu oft bei Anfängern, dass
die ganzen nützlichen Warnungen ignoriert werden. ;)
Vielen Dank für deine Meinung! :)
Sally schrieb:> Wie von dir erwartet auch sehr prozedual gehalten. ^^
Klar. Warum nicht? Die Tools geben das her.
> Wenn ich z.B. wissen möchte, wann sich txcnt ändert
Dann suche ich nach txcnt. So oft kommt der ja nicht vor.
Und meist ist ja nicht die Frage, wann bzw. wo er sich ändert,
sondern wohin. Also: was ist der nächste Wert.
Und in einem zusätzlichen kombinatorischen Prozess, der txcnt_next
ausrechnet, habe ich auch wieder zig Stellen und ein zusätzliches
Signal.
> Aber wenn du mit der prozedualen Schreibweise besser zurecht kommst, ist> das natürlich in Ordnung. Ich mache ja nur eine Meinungsumfrage. ;)>> Andere Meinungen dazu?
Der ist gut... ;-)
BTW: mit der letzten (doppelt getakteten) Schreibweise bekommst du
leicht mal unverhofft einen Takt Latency.
Martin S. schrieb:> Und ab einer gewissen Komplexität ist ein kleiner stupider Softcore> (Sequenzer) mit selbstdefinierten Opcodes die bessere State-Machine.
Das würde mich näher interessieren. Meinst du mit Sequencer den
Picoblaze o.ä. oder gibt es für so etwas eine herstellerunabhängige
"Schablone"?
@ Sally (Gast)
>Zeile schreiben (wie in meinem Beispiel 3ff oben) Dann laufe ich auch>nicht Gefahr in einem Zweig mal eine Zuweisung zu vergessen und>generiere keine unerwünschten Latches, die bei komplizierteren FSMs zu>scheinbar unerklärlichem Verhalten führen.
Quark. Die Ein-Prozess Methode kann gar keine Latches erzeugen, weil
voll getaktet. Die Zwei-Prozess-Methode ist da das Problemkind. Naja,
ich sag da nur "Projektion".
Und Latches spuckt jeder Compiler als Warning aus, wer die ignoriert
muss halt noch etwas Lehrgeld zahlen ;-)
Falk Brunner schrieb:> Die Zwei-Prozess-Methode ist da das Problemkind
Meine Meinung und auch mein Senf dazu: Ich schreibe meistens
1-Prozess-Schreibweise, ganz selten 2-Prozess. Und wenn 2-Prozess dann
eigentlich immer den 'next_state' mit Concurrent-Anweisungen:
Uebersichtlicher und vermeidet fast automatisch die Latches. Und man
'ahnt' bei laenglichen statements, dass Place&Route damit einiges zu tun
haben.
Damit bin ich in ~15 Jahren VHDL und auch Verilog (mit Unterbrechungen)
immer ganz gut klar gekommen und auch das Timing lag in etwa im
erwarteten Bereich...
dito schrieb:> Martin S. schrieb:>> Und ab einer gewissen Komplexität ist ein kleiner stupider Softcore>> (Sequenzer) mit selbstdefinierten Opcodes die bessere State-Machine.>> Das würde mich näher interessieren. Meinst du mit Sequencer den> Picoblaze o.ä. oder gibt es für so etwas eine herstellerunabhängige> "Schablone"?
Nee, eher noch primitiver als Picoblaze, aber hängt auch wiederum von
der Aufgabe ab. Also gibt es auch nicht wirklich eine universelle
Schablone, sondern du passt dir deinen eigenen "Prozessor" der Aufgabe
an.
Nimm z.B. eine typische Multiply-Accumulate Unit, wie sie in praktisch
allen DSP steckt. Für gewisse Signalfilter brauchst du davon ev. ein
paar kaskadiert, aber auch "multiplexed", also eine Unit macht
Operationen für ev. mehrere Datenpfade zu unterschiedlicher Zeit.
Anstatt alles hart in eine FSM zu codieren, macht da ein "Programm" mit
selbstdefinierten Opcodes (Quelle, Operation[Modus], Ziel) mehr Sinn. Du
baust Dir also deine Verarbeitungsblöcke als Module und der Sequencer
bestimmt, wann welches unter gewissen Bedingungen drankommt.
Allerdings nutze ich auch einen fertigen CPU-Softcore als Front-End, um
den eigentlichen Microcode (also das "Programm") für die DSP-Pipeline
ggf. zu modifizieren und debuggen.
Nachteil ist, dass im ersten Design die opcodes meist recht lang werden
(wegen der plumpen Codierung einiger parallel arbeitender Units). Sobald
dann eine Verarbeitungs-Pipeline feststeht, kann man die fest in
Hardware codieren (Stichwort LUTs!) und das eigentliche Programm
schrittweise vereinfachen.
Meist hat sich dabei sogar herausgestellt, dass die längliche Version
weniger Resourcen kostet als eine komplizierte FSM, u.a. dadurch, dass
für das Programm auch BlockRAM genutzt wird.
Die Tools (zumindest die von Xilinx) sind nämlich ab einem gewissen
Punkt nicht mehr schlau genug, zu komplexe hart codierte FSM zu
vereinfachen und klauen dir dann eine Menge Logik-Resourcen auf dem FPGA
weg.
Grüsse,
- Strubi
Martin S. schrieb:> Anstatt alles hart in eine FSM zu codieren, macht da ein "Programm" mit> selbstdefinierten Opcodes (Quelle, Operation[Modus], Ziel) mehr Sinn.
Hatte ich auch schon. Zwar ohne DSP Funktionalitaet aber halt eine
bloede vielzyklische FSM (mit variabler Pipelinetiefe, dazu noch mehrere
Zugriffe auf BRAM-Daten): Sauber in einem Prozess hingeschrieben und da
haben die Tools doch wunderbar distributed RAM erkannt und verwendet.
Timing war danach ueberhaupt kein Problem mehr, auch bei
Erweiterungen/Aenderungen...
Und schoen kompakt war's dann auch...
Sally schrieb:> Du programmierst vermutlich mehr in C als in VHDL, oder? Das würde> deinen prozedualen Stil in VHDL erklären. ^^
Ja, genau so ist es. Der Loddar hat nämlich gar keine Ahnung von VHDL.
:D
*wer Ironie findet, darf die behalten... ;-)
Die Übersichtlichste Darstellung einer digitlanen Schaltung ist ein
Diagramm -> mit einer vollständigen Dokumentation erspart man sich alle
Verrenkungen im Code.
In diesem Zusamenhang sei auch auf die Möglichkeit verwiesen aus
FSM-Graphen automatisch Code zu erzogen, bspw. mit Mentor Graphics
HDL-Designer.
MfG
>Ich sehe es leider zu oft bei Anfängern, dass>die ganzen nützlichen Warnungen ignoriert werden. ;)
Allein die Tatsache, dass Sally sich mit solchen "Ich verschiebe mal den
Code in eine andere Schreibweise"-Lapalien beschäftigt, zeigt mir, dass
der Kreis der Anfänger doch größer ist als angenommen ;-)
Sally schrieb:> Du programmierst vermutlich mehr in C als in VHDL, oder? Das würde> deinen prozedualen Stil in VHDL erklären. ^^
Das was du hier machst ähnelt in etwa dem Spruch: "Hey Chuck Norris wie
läufts beim Ballet?"
Ich finde ebenfalls die erste Schreibweise am besten und kriege immer
die Krise, wenn ich sehe dass jemand eine FSM nach getaktetem und
kombinatorischem Teil trennt. Ich finde das irgendwie unintuitiv und
schlecht lesbar...
Was das damit zu tun haben soll, ob man vorher Software geschrieben hat,
ist mir nicht klar.
Philip schrieb:> Ich finde das irgendwie unintuitiv und schlecht lesbar...
Naja, das kommt aus der Automatentheorie mit getakteten Speichergliedern
und einer Logik/Rechenwerk für die Weiterschaltung.
Das ist in meinen Augen wie Assemblerprogrammierung:
Gut, wenn man die Erfahrung mal gemacht hat...
OT:
> unintuitiv
Was ist das Gegenteil von "ineffiziet"? Richtig: "effizient".
Was das Gegenteil von "intolerant"? Ja: "tolerant".
Und von "inakzeptabel"? Korrekt: "akzeptabel".
Was ist also logischerweise das Gegenteil von "intuitv"?
Ich finde z.B. die Bedienung von manchem Programm sehr tuitiv! ;-)
Philip schrieb:> Ich finde ebenfalls die erste Schreibweise am besten und kriege immer> die Krise, wenn ich sehe dass jemand eine FSM nach getaktetem und> kombinatorischem Teil trennt. Ich finde das irgendwie unintuitiv und> schlecht lesbar...
Nach etlichem hin und her bin ich aktuell meist bei der
2-Prozess-Darstellung, 1 Prozess getaktet, der Andere kombinatorisch.
Das liegt daran, dass ich immer mal wieder eine Latenz 0 benötige, bzw.
nur so die benötigte Performance bekomme (also Mealy-Automat). Ansonsten
nutze ich die 1-Prozess-Darstellung (Moore-Automat).
Bei der 2-Prozess-Darstellung versuche ich dann auch, die
State-Dekodierung nur an einer Stelle zu machen, was dann darauf
hinausläuft, dass der kombinatorische Prozess alles macht und der
getaktete Prozess die Signale nur speichert (soweit möglich, wegen
Latenz)
Wenn jetzt jemand meint, na dann mache ich eine 1-Prozess-Darstellung
und die Latenz-0-Signale per Concurrent-Statement (z.B. mit when oder
with), dann ist das für mich nur eine andere Form der
2-Prozess-Darstellung (eigentlich sogar noch mehr Prozesse, wenn man im
Simulator sieht, dass jede Concurrent-Anweisung in einem eigenen Prozess
dargestellt werden)
Daniel M. schrieb:> dass jede Concurrent-Anweisung in einem eigenen Prozess dargestellt
Eine Concurrent-Beschreibung ist ja nur ein degenerierter Prozess, bei
dem alle verwendeten Signale implizit in der Sensitivliste stehen.
> bin ich aktuell meist bei der 2-Prozess-Darstellung ...> Das liegt daran, dass ich immer mal wieder eine Latenz 0 benötige, bzw.> nur so die benötigte Performance bekomme (also Mealy-Automat)
Man muss auch mit der 1-Prozess-Schreibweise nicht immer unnötig einen
Takt vertrödeln...
DuArte schrieb:>>Das liegt daran, dass ich immer mal wieder eine Latenz 0 benötige>> Hast du mal ein kleines schnuckeliges Beispiel?
Weitergabe eines Read- oder Ready-Signals (z. B. an ein FIFO) in
Abhängigkeit vom State?
Ich verwende hier einen DDR3 mittels Xilinx MIG und benötige eine hohe
Bandbreite (Videoanwendung). Da gilt es, jede unnötige Latenz zwischen
app_en und app_rdy bzw. app_wdf_en und app_wdf_rdy zu vermeiden.
Als ein Beispiel.
Lothar Miller schrieb:> Man muss auch mit der 1-Prozess-Schreibweise nicht immer unnötig einen> Takt vertrödeln...
Die Frage ist, was ist unnötig?
Eine reine 1-Prozess-Darstellung hat die minimale Latenz 1. Frühestens
im nächsten Takt ist eine Reaktion auf ein Signal sichtbar.
Und das ist mir in speziellen Situationen bereits zu langsam.
Daniel M. schrieb:> Eine reine 1-Prozess-Darstellung hat die minimale Latenz 1. Frühestens> im nächsten Takt ist eine Reaktion auf ein Signal sichtbar.
Aber jetzt weißt du schon, was als nächstes kommen wird. Bei der
2-Prozess-Methode explizit, bei der 1-Prozess-Methode implizit...
Ich weiss es, aber das nützt nichts, wenn ich dazu ein Signal
benötige.
Beispiel:
Ein Modul generiert ein Read-Signal, welches bedeutet, im nächsten Takt
erwartet es Daten am Eingang (normales FIFO-Verhalten).
Jetzt wird dieses Modul nicht direkt angeschlossen sondern über eine
FSM. Bei einer reinen 1-Prozess-FSM bedeutet das für mich, die FSM sieht
das Read-Signal und veranlasst zb ein State-Wechsel zum Auslesen eines
FIFOs. Dies ist jedoch erst im nächsten Takt sichtbar. Und die Daten
kommen nochmal einen Takt später. Das heißt das Modul bekäme die Daten 1
Takt zu spät.
1
one_process:process(clk)
2
begin
3
ifrising_edge(clk)then
4
o_fifo_read<='0';
5
casestateis
6
whenST_WAITING=>
7
ifi_read='1'then
8
state<=ST_READ;
9
o_fifo_read<='1';
10
endif;
11
12
whenST_READ=>
13
(irgendwas)
14
15
endcase;
16
endif;
17
endprocess;
Latenz = 1!
oder sogar:
1
one_process:process(clk)
2
begin
3
ifrising_edge(clk)then
4
o_fifo_read<='0';
5
casestateis
6
whenST_WAITING=>
7
ifi_read='1'then
8
state<=ST_READ;
9
endif;
10
11
whenST_READ=>
12
o_fifo_read<='1';
13
(irgendwas)
14
15
endcase;
16
endif;
17
endprocess;
Latenz = 2!
Klar kann ich das kombinatorisch beschreiben:
1
o_fifo_read<=i_readwhenstate=ST_WAITINGelse'0';
Jedoch ist das für mich nichts anderes als die 2-Prozess-Darstellung in
anderer Form.
Moin,
es gibt da noch ein längeres schlagendes Argument für die
2-process-Methode, dem eigentlich nichts mehr hinzuzufügen ist:
http://www.gaisler.com/doc/structdes.pdf
Darauf kommt man aber auch, wenn man sich bei komplexen Projekten
einfach ganz akademisch befreit ein paar Gedanken zum Thema
Codeverwaltung macht - es kommt nämlich durchaus öfters vor, dass
mehrere Module von einer zentralen FSM abhängen und daraus Signale
dekodieren, z.B. ein Soft-Core mit einem optionalen Debug-Modul mit dem
typischen "1 clock Latenz ist zuviel"-Problem.
Daniel M. schrieb:> Klar kann ich das kombinatorisch beschreiben:> o_fifo_read <= i_read when state = ST_WAITING else '0';
Das kapiert wirklich jeder. Ohne lange Suche... ;-)
> Jedoch ist das für mich nichts anderes als die 2-Prozess-Darstellung in> anderer Form.
Für die Erzeugung solcher kombinatorischer Signale nehme ich natürlich
auch kombinatorische Beschreibungen, da ist ein zusätzliches Register,
das bei der purifizierten 1-Prozess-Schreibweise entstehen würde,
unnötig.
Nur: was hat dieses Signal mit der FSM zu tun? Die Weiterschaltung und
FSM-Verwaltung kannst du ja bedenkenlos in 1-Prozess machen.
Auch ich nehme die 2-Prozess (oder 1-Prozess + Concurrent) Methode, wenn
sie von Vorteil ist. Allerdings ist meine Defaulteinstellung auf FSM =
1-Prozess.
Strubi schrieb:> http://www.gaisler.com/doc/structdes.pdf
Der Prophet, der über (quasi globale) Variablen auch Softwareprogram-
mierern FPGAs näher bringen will.
Dem einen gefällts, der andere findet es zu aufwendig und verwirrend,
wie im Beitrag "Gaisler-Religion?" aufgeführt.
Sally schrieb:> Ich möchte hier jetzt keinen Glaubenskrieg hervorrufen...
Und schon haben wir ihn. Ist aber auch logisch, denn es ist
psychologisch gezeigt, dass der Mensch Negationen tendenziell ignoriert.
(Schon mal versucht nicht an einen rosaroten Elephanten zu denken?)
Wie auch immer: Soll jeder nach seiner Art glücklich werden. ;-)