Forum: FPGA, VHDL & Co. Verständnisprobleme synchron, asynchron


von Martin (Gast)


Lesenswert?

Hallo Leute!

Seit einiger Zeit beschäftige ich mich mit VHDL.
Es passiert jedoch immer wieder, dass das fertige Design in der
Hardware, dann oft etwas anders reagiert als man sich z.B. vorher
überlegt hat.

Z.B. habe ich einen Synchronen Prozess, der auf eine positive Flanke
eines Clock-Signals reagiert und der eine State-Machine beinhaltet.

Zusätzlich habe ich einen Prozess, der auf eine negative Flanke eines
Tasters reagiert. Ein Signal wird dadurch umgestellt und der synchrone
Prozess erkennt dies und die State-Machine im sysnchronen Prozess wird
gestartet.

Das besagte Erkennungssignal wird im synchronen Prozess nur einmal zu
Beginn im Status 0 abgefragt und dann erst wieder im letzt-möglichen
Statuszustand.

Das Lustige dabei ist, dass, wenn ich den Taster sehr oft und schnell
hintereinander drücke, es ab und zu vorkommt, dass das Ausgangssignal,
welches vom synchronen Prozess erzeugt wird, ab und zu verzerrt ist. So
als ob mitten unter der Signalausgabe von Vorne begonnen werden würde,
obwohl in höhergelegenen Statuszuständen diess asynchrone Signal nicht
abgefragt wird.

Wenn ich aber nun, jenen Prozess, der über die negative Taktflanke des
Tasters gesteuert wird so umschreibe, dass der Taster einfach nur immer
bei einer positiven Clock-Flanke abgetastet wird, dann funktioniert
alles einwandfrei.

Was muss hier zwischen verschiedenen Prozessen beachtet werden?

Ich hoffe meine Erklärungsversuche waren für euch nicht zu verwirrend.

Danke für eure Antorten.

Tschüss
Martin

von alex (Gast)


Lesenswert?

Ist etwas verwirrend... Quellcode wäre hilfreicher.

von Martin (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute!

Hier ist mein Code. Es handelt sich um eine UART. Selbst geschrieben.
Der Clock-Pin wird mit 100MHZ getaktet.
Für den Anfang lässt sich noch keine Baudrate einstellen. Sie ist auf
115200 Baud fixiert, wenn mit 100MHZ getaktet wird.

Der serinx-Prozess, der ganz unten steht ist für mein jetziges Problem
völlig unwichtig. Dieser Prozess stellt die Empfangseinheit dar.

Wichtig sind der Prozess "seroutx" und "serstarten".
Wenn jetzt im Prozess serstarten der Event-TXenable eintritt, dann wird
dem Signal txstart eine 1 zugewiesen und der Prozess seroutx kann mit
dem Senden beginnen.
Im Status 3 wird dann entschieden, ob ein weiteres Byte gesendet werden
soll oder ob der Status 0 wieder eingenommen werden soll.

Das Problem:
Wenn ich nun zu Testzwecken das TXenable-Signal einem Button auf der
richtigen Hardware zuweise und das VHDL-Design in die Hardware flashe,
dann kann es passieren, wenn ich den Knopf oft und schnell betätige,
dass der 10-Bit-Frame nicht vollständig ist (1-Start 8-Daten 1-Stopp).
Es ist dann so, dass der Frame anscheinend mitten drunter unterbrochen
wird und anscheinend ein neues Start eingeleitet wird, obwohl das
Signal "txstart" immer erst am Beginn oder Ende des Frames abgefragt
wird.

Könnt ihr mir bitte helfen?
Was haltet ihr allgemein von meinem Quellcode?
Eure Meinung ist mir wichtig.
Danke für eure Antworten.

Tschüss,
Martin

von Kest (Gast)


Lesenswert?

Allgemein von Deinem Quellcode?

hab nur interessenshalber reingeschaut.
Was mir gleich aufgefallen ist sind die ganzen "+1" Addierer, die in
irgendwelchen Zuständen drinne sind. Ich frage mich, ob die Tools so
schlau sind und alles zu einem Addierer zusammenfassen und nicht
mehrere Addierer implementieren? :-o Hast Du RTL-Viewer angeschaut?

Besser wäre einen Signal zu setzen und irgendwo außerhalb der
Statemachine den zu überprüfen und eben dann zu zählen

Das war's erstmal :-)

Kest

von FPGA-User (Gast)


Lesenswert?

Hallo Martin,

habe mir mal Deinen Code angeschaut. Das Problem dürfte sein,
dass Du mit einem asynchronen Signal (txstart) in Deine
Statemachine reingehst. Das ist NICHT OK.
Du musst das Button-Signal mit dem Signal CLK einsynchronisieren,
d.h. über mindestens 2 - 3 FFs seriell einschieben und dann
z.B. auf FF2 und FF3 eine synchrone Flankenerkennung machen.
Wie das geht wurde hier schon mehrfach diskutiert.

Allgemein :
- Signalnamen : gut gewählt
- Formatierung : besch... Du musst ordentlich einrücken->Lesbarkeit
- Kommentare : zu wenig

und:
Du übergibst z.B. txstartbuffer an die Variable txsenden und
wählst dann die Bits über einen MUX aus. Das ist ineffizient.
Der Vorteil von serieller Logik besteht gerade darin, dass
man viel mit Schieberegistern arbeitet - da hätte ich hier auch eins
verwendet.
Warum ist counter2 eine Variable und kein Signal ?

Das inkrementieren des Counters in den States ist kein Problem,
hätte ich auch so gemacht.

von Kest (Gast)


Lesenswert?

Okay, das mit dem Counter schluckt Quartus. Es entsteht nur ein
Addierer.

Gut.
Kest

von Martin (Gast)


Lesenswert?

Hallo Leute!

Danke für eure Antworten, besonders dir FPGA-User.

Ich glaube, ich habe das Problem im Griff. Ich habe zwar diese
Flip-Flops noch nicht eingebaut, aber ich frage das Signal jetzt
Synchron ab und es funktioniert einwandfrei.

@FPGA-USER: Das Problem dürfte sein,
dass Du mit einem asynchronen Signal (txstart) in Deine
Statemachine reingehst. Das ist NICHT OK.

Was hat es damit auf sich, dass dies nicht funktioniert?


Ich habe noch ein kleines Problem.
Ich lese von einer Zeilenkamera 4096 Bytes ein. Diese sollen nun per
RS232 an den PC verschickt werden. Nach ein paar Sekunden erhält die
Kamera einen weiteren Trigger und sendet wieder 4096 Bytes an das
FPGA-Board. Und so geht das immer weiter.

Das mit dem Empfangen und Sende habe ich schon alles hinbekommen. Das
große Problem ist nur das Array. Es ist möglich das Feld kleiner zu
machen. Also z.B. nur 40 Zeichen, dann funktionert alles einwandfrei.
Aber wenn ich das Array auf die 4096 aufblase, dann wird das Ganze so
umfangreich, dass dieses Design keinen Platz mehr hat
(XC4VFX12-12FF668).

Gibt es hier Tricks? Man sollte doch den FPGA mit einem Feld von 4096
nicht überfordern oder? Wie wird soetwas dann in der Praxis gelöst?
Wäre der Quellcode hilfreich?

Danke, Gruß, Martin

von FPGA-User (Gast)


Lesenswert?

Hallo Martin,

zur Statemachine:

diese besteht aus Flip-Flops mit Kombinatorik drumrum. Grundregel:
Alle Signale, die in der FSM mit IF ... CASE ... usw. abgefragt
werden, müssen synchron zum Clock der FSM sein, d.h. mit demselben
Takt laufen. Sonst kann es zu Setup- und Hold-Zeit Verletzungen
kommen, was schlimmstenfalls in undefinierten States endet.
Außerdem können solche asynchronen Signale bei entspr.
Code direkt auf weitere Signale/Variablen wirken, was dann
extrem interessantes Verhalten ergibt. (Spikes ...)

Array:
4096 Bytes in einem FPGA sind "Kleinkram". Selbst wenn Du das
als Schieberegister aus einzelnen FFs aufbaust, sollte es kaum
Probleme geben, sofern das FPGA wenigstens die 32768 FFs hat.

Aber so ein Virtex hat doch bestimmt Block-RAMs, wo man Daten
super reinschieben kann. Eine RAM-Page 8bit breit und 4096
tief ist doch sicher machbar. Ich arbeite hier mit Quartus II
von ALTERA, da würde es 1 Minute dauern, so ein RAM zu generieren.

Oder hab ich da was falsch verstanden?

von Martin (Gast)


Angehängte Dateien:

Lesenswert?

Hallo!

Das hört sich gut an. Leider bin ich hier noch nicht ganz so
sattelfest. Aus diesem Grund versuche ich jetzt einige Informationen
loszuwerden.

Das Board selbst besitzt einen 64M-Byte DDR-SDRAM. Es ist auch jeder
Pin genau beschrieben. Aber ich weiß nicht, ob es schnell genug ist, da
eine Zeile mit 20MHZ-Clock-Frequenz ausgelesen wird.

Dann gibt es noch das FPGA-Datenblatt, wo folgende Werte stehen.
Device: XC4VFX12
Array Rowx Col: 64x24
Logic Cells: 12312
Slices: 5472
Max-Distributed RAM(kb):86
XtremeDSPSLICES: 32
Block RAM: 18KB blocks: 36
           MAX Block RAM(kb): 648
DCMs: 4
PMCDs: 0
PowerPC-Processor-Blocks: 1
Ethernet Macs: 2
RocketIO Transceiver-Blocks: N/A
Total I/O-Banks: 9
MAX-User-I/O: 320


So wie ich die Daten jetzt gesehen habe schließe ich daraus, dass der
FPGA-intern ein Blockram von 648kb besitzt, wobei anscheinend 36 Blocks
zu je 18kb bestehen.
Nur wie man dieses ansprich ist jetzt eine gute Frage.
Ich werde am Montag mal den Support quälen.

Zusätzlich habe ich das Log-File mitgesendet, vielleicht kann man
daraus etwas herauslesen, was ich selbst nicht gesehen habe.
Bei diesem Design habe ich das Feld auf 1024 gestellt und der FPGA war
zu klein.
Ich habe dabei folgendes Array angelegt:
generic(feldgr: integer range 0 to 4096:=1024);
..
..
type mem_type is array((feldgr-1) downto 0) of std_logic_vector(7
downto 0);
signal daten: mem_type;    -- Feld von Vektoren.


Danke Leute. Schönes Wochenende.

Gruß, Martin

von FPGAküchle (Gast)


Lesenswert?

Hm support quälen das trifft es.

Also das ist hardware, keine Software. Nix mit vector als memoryarray,
sondern wie auf einem Mother board: Speicherchip draufpacken, Strippen
zur Steuerlogik ziehen und die richtigen Signale im richtigen Moment
aktivieren. Dann wandern da auch Deine Daten rein und raus.

Auch ist es kein Sdram, sondorn dualport SRAM, 36 Blöcke a 18 kbit. Im
Virtex4 Hanbuch Kapitel 4 ist das beschrieben.

Du kannst es Dir etwas einfacher machen, wenn Du mit dem CoreGen (Tool
im xilinpacket) Dir einen passenden Ram zB. 32kx32bit single port aus
den Primitiven zusammenbastelst. CoreGen spuckt auch VHDL Beispiele
aus, die Du in deinem VHDL Code einbauen kannst.

Oder such dir bei Xilinx die Application Note XAPP463 raus. Die ist
zwar für Spartan3, aber die Block RAMS im Virtex4 werden auch nicht
gross anders angesteuert. Beispiele in VHDL hat die Application Note
auch.

von FPGAküchle (Gast)


Lesenswert?

Grübel, wie leicht ist die ISE 8.1 doch schlau und macht BRAMS aus
std_logic_vector ... schau mer mal in den synthesereport:



/INFO:Xst:738 - HDL ADVISOR - 8192 flip-flops were inferred for signal
<daten>. You may be trying to describe a RAM in a way that is
incompatible with block and distributed RAM resources available on
Xilinx devices, or with a specific template that is not supported.
Please review the Xilinx resources documentation and the XST user
manual for coding guidelines. Taking advantage of RAM resources will
lead to improved device usage and reduced synthesis time.

Na doch keine Wunder, XST wollte das Feld in FF packen, auch ne
Möglichkeit
Speicher zu basteln, aber register hat es halt nicht soviel.

Also wirst Du BRAM's auf die klassiche Art nehmen müssen, wie die XAPP
beschreibt. (Nein ich will nicht ärgern, es ist halt zuviel um es hier
ins Forum zu tippern).

von Martin (Gast)


Lesenswert?

Hmmm.
Das ist für mich noch ein bisschen verwirrend.

Was ich z.B. noch nicht verstehe ist, wenn vor der State-Machine auf
einen positiven CLK abgefragt wird,

if clk'event and clk='1'then

case statussenden is
 when 0 => if txstart='1' then    -- Warten auf Start und starten.
           serout<='0';
           statussenden<=1;

warum dann asynchrone Signale, die sich innerhalb der State-Machine
befinden und dort abgefragt werden etwas ausmachen können?

Dieses Bram von dem ihr hier redet, befindet sich das im FPGA oder ist
es extern auf dem Board?

Ich werde mich mal damit etwas beschäftigen.
Z.B. hätte ich nun versucht über die Language-Templates auf einen
grünen Zweig zu kommen. Aber da steht nur folgender Code:

process (<clock>)
begin
   if (<clock>'event and <clock> = '1') then
      if (<enableA> = '1') then
         if (<write_enableA> = '1') then
            <ram_name>(conv_integer(<addressA>)) <= <input_dataA>;
         end if;
         <ram_outputA> <= <ram_name>(conv_integer(<addressA>));
         <ram_outputB> <= <ram_name>(conv_integer(<addressB>));
      end if;
   end if;
end process;

So wie ich im User-Guide gelesen habe, sollte die Ansteuerung nicht so
einfach gehen, oder?

Danke, Leute.

Gruß, Martin

von T.M. (Gast)


Lesenswert?

1
if clk'event and clk='1'then
2
3
case statussenden is
4
 when 0 => if txstart='1' then    -- Warten auf Start und starten.
5
           serout<='0';
6
           statussenden<=1;
Das Problem dabei ist, wenn sich dein Signal txstart zum selben
Zeitpunkt ändert wie eine steigende Flanke auftritt, kommt es zu
metastabilen Zuständen. Es ist dabei nicht bestimmt, welchen Zustand
das FF nun einnimmt, da es eine gewissen "Ruhezeit" an dem
Dateneingang vor und nach der Taktflanke braucht.
Verhindern oder besser gesagt verringern kann man sowas durch
Synchronisation der Eingänge.

von Martin (Gast)


Lesenswert?

Hallo T.M.!

Das was du mir schreibst sehe ich ein. Es ist auch so, dass nach einer
Synchronisierung alles bestens funktioniert hat.

Nur verstehen tue ich das immer noch nicht ganz, weil:
Wennn sich jetzt das txstart-Signal zur selben Zeit ändert, wie das
CLK-Signal, dann gebe ich dir recht, dass der Zustand von txstart nicht
vorhersehbar ist. Aber das kann doch egal sein, denn wenn zu diesem
Zeitpunkt txstart noch als 0 angesehen wird, dann wird dieses Signal
eben beim nächsten Clock als 1 angesehen werden. Und wenn es beim
jetzigen Clock schon als 1 angesehen wird umso besser.


Entschuldigt bitte, dass ich hier so auf meine Meinung beharre, aber
ich möchte verstehen, warum das so ist, um in Zukunft in möglichst
wenig Fallen zu tappen.

Danke, Leute!
Gruß, Martin

von alex (Gast)


Lesenswert?

>warum dann asynchrone Signale, die sich innerhalb der State-Machine
>befinden und dort abgefragt werden etwas ausmachen können?

@Martin: Ich denke, es ist besser, du schreibst deine FSM im
Multiprocess-Stil, wie es in den meisten Schulbüchern steht: für die
Eingabelogik ein Prozess, für den Zustandsübergang einen weiteren
Prozess und für die Ausgabelogik einen dritten Prozess. Dann kannst du
auch besser erkennen, ob es sich um einen Mealy- oder Moor- oder was
auch immer-Automaten handelt und außerdem kannst du erkennen, welche
Signale man wo besser abfragen sollte (nämlich nur im Eingabeprozess
(!) oder vielleicht im Ausgabeprozess, abhängig davon ob Moor oder
Mealy, aber auf keinen Fall im Zustandsübergangsprozess...).

von FPGAküchle (Gast)


Lesenswert?

#Dieses Bram von dem ihr hier redet, befindet sich das im FPGA oder
#ist
#es extern auf dem Board?

ist im FPGA, Xilinx benennt den "Embedded RAM" also SRAM auf dem
FPGA
als Block RAM (BRAM), weil die im Silizium Blöcke zu 18k stück a 1 bit
von RAM-zellen haben. Es gibt noch weitere RAM-Felder auf dem FPGA,
z.B. den distributed RAM, aber der ist kleiner und frisst Logik.
(meint der Platz für das weitere design wird kleiner).



Ich werde mich mal damit etwas beschäftigen.
Z.B. hätte ich nun versucht über die Language-Templates auf einen
grünen Zweig zu kommen. Aber da steht nur folgender Code:

process (<clock>)
begin
   if (<clock>'event and <clock> = '1') then
      if (<enableA> = '1') then
         if (<write_enableA> = '1') then
            <ram_name>(conv_integer(<addressA>)) <= <input_dataA>;
         end if;
         <ram_outputA> <= <ram_name>(conv_integer(<addressA>));
         <ram_outputB> <= <ram_name>(conv_integer(<addressB>));
      end if;
   end if;
end process;

So wie ich im User-Guide gelesen habe, sollte die Ansteuerung nicht so
einfach gehen, oder?

Das Prinzip ist schon so einfach, (lese- und schreib enable und zwei
adressen), aber offensichtlich versteht das synthesetool nicht das
der vector <ram_name> auf BRAM gemappt werden soll. Bei dir mappt es es
auf FlipFlops. Warum das template nicht mit ergebnis und design-guide
übereinstimmt weiss ich auch nicht. Es könnte ein Attribut fehlen.
Der klassiche Weg ist eben BRAM Primitive per component und Port Map
einzubinden, ist auch nicht weiter schwierig wenn man in Hardware
denkt.

von FPGA-User (Gast)


Lesenswert?

Hallo Martin,

nochmal zum Thema asynchron / txstart :

das hat nicht nur was mit Metastabilen Zuständen zu tun
(s. T.M.), sondern vielmehr mit dem Timing !

"Aber das kann doch egal sein, denn wenn zu diesem
Zeitpunkt txstart noch als 0 angesehen wird, dann wird dieses Signal
eben beim nächsten Clock als 1 angesehen werden..."

Das ist schlichtweg falsch. Deine FSM besteht aus mehreren Flip-Flops,
alle D-Eingänge bekommen ein kombinatorisches Signal, das aus
dem aktuellen Zustand und den Inputs generiert wird.
Nun gibt es unterschiedliche Delays von txstart zu den einzelnen
FFs (es ist eben Hardware, keine Software!).
Damit kann es dazu kommen, dass eben das FF1 txstart schon als '1'
sieht, während FF2 noch die '0' hat (kurz danach ist die '1' auch
an FF2 "angekommen", aber da war die Taktflanke eben schon vorbei)
-> Folge: Deine FSM kann in einen Zustand kommen, den Du gar nicht
definiert hast, speziell bei onehot-Codierung (such mal danach).

Deshalb nochmal :
Alle Signale die in der FSM abgefragt werden, müssen mit demselben
Takt GENERIERT werden, den die FSM hat. Nur dann kann Dein Design
"bullet proof" werden.

von Kest (Gast)


Lesenswert?

@BRAM Templates:

HAbe auch solche Probleme gehabt, dass kein BRAM genommen wird.

Ich habe irgendwo oben sowas gelesen

type mem_type is array((feldgr-1) downto 0) of std_logic_vector(7
downto 0);
signal daten: mem_type;    -- Feld von Vektoren.

wenn Du die Richtung des Array änderst (also von 0 to (feldgr-1)), dann
sollte es gehen

Kest

von alex (Gast)


Lesenswert?

>Damit kann es dazu kommen, dass eben das FF1 txstart schon als '1'
>sieht, während FF2 noch die '0' hat (kurz danach ist die '1' auch
>an FF2 "angekommen", aber da war die Taktflanke eben schon vorbei)

... dann ist die FSM einfach übertaktet.

> Folge: Deine FSM kann in einen Zustand kommen, den Du gar nicht
> definiert hast, speziell bei onehot-Codierung (such mal danach).

Deshalb sollte man ein case-Zweig "when others => new_state <=
irgendein_state; -- z.B. fehlerstate" vorsehen.

von FPGA-User (Gast)


Lesenswert?

>Damit kann es dazu kommen, dass eben das FF1 txstart schon als '1'
>sieht, während FF2 noch die '0' hat (kurz danach ist die '1' auch
>an FF2 "angekommen", aber da war die Taktflanke eben schon vorbei)

... dann ist die FSM einfach übertaktet.

-> stimmt, aber nur wenn txstart synchron ist. So wie es von Martin
beschrieben wurde, konnte txstart zu jedem beliebigen Zeitpunkt
aktiv werden und damit war die Taktfrequenz der FSM bedeutungslos.

> Folge: Deine FSM kann in einen Zustand kommen, den Du gar nicht
> definiert hast, speziell bei onehot-Codierung (such mal danach).

Deshalb sollte man ein case-Zweig "when others => new_state <=
irgendein_state; -- z.B. fehlerstate" vorsehen.

-> Ja, hilft aber z.B. auch nix, wenn man durch ein asynchrones
Signal in einen gültigen State (der aber trotzdem falsch ist)
wechselt

von A. N. (netbandit)


Lesenswert?

@FPGA-Küchle:

>Deshalb nochmal :
>Alle Signale die in der FSM abgefragt werden, müssen mit demselben
>Takt GENERIERT werden, den die FSM hat. Nur dann kann Dein Design
>"bullet proof" werden.

Was natürlich nicht so einfach möglich ist, einer asyncronen
Signalquelle beizubringen im richtigen Takt zu schalten.
Daher könnte man das Eingangssignal bevor man es in der FSM anfragt bei
jedem Clock "puffern".

process (CLK, RESET)
begin
[...]
  if clk'event and clk = '0' then -- fallende Flanke
    Signal_S <= Signal;
  end if;
[...]
end process;

In der FSM fragt man dann anstatt Signal eben Signal_S ab und man kann
sich sicher sein, dass an jedem FF der FSM das Signal sicher anliegt
während der CLK kommt.
Hab ich das richtig verstanden?

Nachteil des ganzen ist, das man dafür ein FF verbraucht und das
umschalten des Signals erst einen Takt später bemerkt wird. Das mit dem
FF ist vor allem dann blöd wenn man einen CPLD benutzt, das mit der
Verzögerung ist auch beim FPGA eine blöde Sache. Was kann man dagegen
tun?

von FPGAküchle (Gast)


Lesenswert?

<In der FSM fragt man dann anstatt Signal eben Signal_S ab und man kann
<sich sicher sein, dass an jedem FF der FSM das Signal sicher anliegt
<während der CLK kommt.
<Hab ich das richtig verstanden?

Das Prinzip stimmt, man nimmt aber meist zwei FF und nennt das
two-level synchronizer stage.
 Falls Dich die Verzögerung stört kannst du ja mit einem ganzzahligen
Vielfachen des FSM Taktes die Eingangssignale einsynchronisieren. Dazu
brauchst Du allerdings eine Frequenzsynthetisierer (PLL/DLL/DCM) auf
dem FPGA. Und steile Flanken auf dem Eingangssignal.

Oder falls möglich klassiches Handshake, was natürlich verlangt, das es
ein zweites Signal gibt ,das anzeigt, das das eigentliche Eingangsignal
stabil ist.

Oder du machst in der FSM sowas wie die CPU's mit spekulativer
Sprungausführung. Hm weites Feld, Deine FSM setzt bestimmt abhängig
von
dem Eingangssignal irgendwelche FF (FSM Ausgangssignale). Wenn das
Eingangsignal jetzt als asynchrones CLEAR/PRESET des ausgangs-FF genutz
twird...

Naja tausendfach bewärt hat sich die old school mit dem Eintakten aller
Eingänge. Wenn die FF oder die Zeit fehlt, gehts eben net.

asynchroner SET/RESET

von A. N. (netbandit)


Lesenswert?

>Das Prinzip stimmt, man nimmt aber meist zwei FF und nennt das
>two-level synchronizer stage.

Was für ein Vorteil bringt dieses doppelte Einsyncronisieren?
Im Grund wirken sich matastabile Zustände am EingangsFF doch nicht
negativ auf die FSM aus. Denn entweder nimmt das eingetaktete Signal
den neuen Zustand an oder behält den alten und nimmt erst beim nächsten
Takt den neuen Zustand an. Also beide Varianten sind im Sinne der FSM
doch legal.
Das Eintakten soll nur verhindern, dass verschiedene FFs der FSM durch
Laufzeitverzögerung unterschiedliche Zustände annehmen. Durch das
EingangsFF ist dies nun nicht mehr möglich, trotz eines metastabilen
Zustandes des EingangsFF.
Oder habe ich da einen Fehler in meiner (Denk)logik?

> Falls Dich die Verzögerung stört kannst du ja mit einem ganzzahligen
>Vielfachen des FSM Taktes die Eingangssignale einsynchronisieren.
Dazu
>brauchst Du allerdings eine Frequenzsynthetisierer (PLL/DLL/DCM) auf
>dem FPGA. Und steile Flanken auf dem Eingangssignal.

Ich arbeite mit einem CPLD und bin bei 66MHz FSM-Takt, das nächste
Vielfache 132MHz ist zu schnell für den CPLD. Aber mit einem Takt
verzögerung kann ich noch leben.

>Oder falls möglich klassiches Handshake, was natürlich verlangt, das
>es ein zweites Signal gibt ,das anzeigt, das das eigentliche
>Eingangsignal stabil ist.
Handshakes scheines generell immer die bessere Methode zu sein, leider
geht es nicht immer...

>Oder du machst in der FSM sowas wie die CPU's mit spekulativer
>Sprungausführung. Hm weites Feld, Deine FSM setzt bestimmt abhängig
>von dem Eingangssignal irgendwelche FF (FSM Ausgangssignale). Wenn
>das Eingangsignal jetzt als asynchrones CLEAR/PRESET des ausgangs-FF
>genutz twird...
Ah ja das Prinzip der Mealy Struktur... Grundsätzlich eine gute Idee.
Doch die Eingangssignale beinflussen bei mir nicht nur die
Ausgangssignale sondern vor allem die Reihenfolge der Zustände der
FSM.
Aber für andere Projekte ist das sicher eine gute Idee.

>Naja tausendfach bewärt hat sich die old school mit dem Eintakten
>aller Eingänge. Wenn die FF oder die Zeit fehlt, gehts eben net.
Also 1 FF pro Signal habe ich noch übrig in meinem CPLD und einen Takt
kann ich auch noch warten.
Habe die SynchronFFs gerade in den Code eingebaut und werde mal einige
ModelSim Versuche starten.

Übrings wollte ich dir Danken für deine Geduld die du mit uns ganzen
Einsteigern aufbringst.
VHDL und eben programmierbare Logik ist ein sehr weites und
interessantes Feld... doch auch komplex. Das lernen des VHDL Syntax ist
innerhalb weniger Tage geschehen, aber das Verständnis für
Syntheseergebnisse und die dahinter stehende Hardware muss man sich
hart erkämpfen und aneignen.
VHDL-Synthese zu lernen ist wie ein Handwerk zu erlernen: Man muss
ständig üben, versuchen, scheitern, es neu versuchen und sich
verbessern. Dabei haben mir die Tips von dir schon oft geholfen und
vielleicht habe ich auch irgendwann den Durchblick ;)

von Tom (Gast)


Lesenswert?

@ Andre:

Da kann ich mich respektive der Zeit und Muße, die FPGAküchele für die
Newbees aufbringt, nur voll und ganz anschliessen....!!!!!!!!

@ FPGAküchele: vielen Dank nochmals für Deine Tipps und Mühen!!!!
Läuft mittlerweile schon gar nicht mal so schlecht....

Gruß
Tom

von Klaus F. (kfalser)


Lesenswert?

> Was für ein Vorteil bringt dieses doppelte Einsyncronisieren?
> Im Grund wirken sich matastabile Zustände am EingangsFF doch nicht
> negativ auf die FSM aus. Denn entweder nimmt das eingetaktete Signal
> den neuen Zustand an oder behält den alten und nimmt erst beim
> nächsten Takt den neuen Zustand an. Also beide Varianten sind im
> Sinne der FSM doch legal.

Es stimmt eben nicht, dass das eingetaktete Signal entweder den alten
Zustand behält oder den neuen annimmt, sondern der Ausgang des 1. FF
bleibt möglicherweise für "längere" Zeit zwischen dem alten und dem
neuen Pegel, eben "metastabil".
Weil der Ausgang des 1. FF üblicherweise über kombinatorische Logik an
mehrere Zustands-FF der FSM führt, knabbert diese Einschwingzeit an den
Setup-Zeiten und Durchlaufzeiten für die FF's.
Dadurch kann es vorkommen, dass ein Zustands-FF ein Signal noch zum
alten oder ungültigen Eingangspegel bekommt, und ein anderes
Zustands-FF Signale zum neuen Eingangssignal. Dadurch kommt die FSM
außer Tritt.

Wenn man das Ausgangssignal des 1. FF nur auf EIN weiteres FF führt,
und den Ausgang des 2. FF in die FSM einspeisst, erhöht sich die
Wahrscheinlichkeit beträchtlich, daß das 2. FF keinen metastabilen
Zustand eintakten muß, und deshalb am Ausgang selbst nicht metastabil
wird.

Wenn die ganze Schaltung nur sehr langsam läuft, und man in den
Setup-Zeiten genug Luft drinnen hat, um die "Einschwingzeit" des 1.
FF zu tolerieren, dann kann man eventuell auch auf das 2. FF
verzichten.

Von jedem Hersteller gibt es Informationen über die Metastabilität. Aus
diesen Diagrammen kann man ablesen, mit welcher Wahrscheinlichkeit ein
FF nach x Picosekunden noch metastabil, also noch nicht eingeschwungen
ist. Damit kann jeder selbst Abschätzen, ob er das 2. FF braucht.

Grüße
Klaus

von FPGAküchle (Gast)


Lesenswert?

Noch nen Trick: metastabile Zustände sind eher kurz als lang,
also ein FF das aus dem tritt kommt ist in x% nach m ns wieder normal
und in y% der Fälle braucht es n ns und x>>y und n > m. Sinn des
Gebrabels: Halte den Pfad zwischen den Synchroniser FF und/oder dem
letzten
Synchronisier-FF und allen FSM-states FF kurz, Das erhöht die
Wahrscheinlichkeit, das das nachfolgende FF NICHT von seinem Vorgänger
in den Metastabilen Zustand gerissen wird. Das erreichst du mit einem
timingconstraint (bei Xilinx FROM TO).

Weg bekommst du das Risiko der metastabilen Zustände beim Eintakten
asynchroner Signale nicht. deshalb werden auch immer mehr IC-Verbindung
synchron gefahren, heisst der takt wird mitgeliefert.
Und wenn man nie sicher vor ausflippenden FSM ist,s, dann baut man
Detektoren ein und startet das ganze neu. Also Fehlzustandserkennung
und -behebung. Dazu wurde z.B. der vom AVR bekannte Watchdog-Timer
erfunden. Also wenn die statemachiene nicht mindestens einmal aller
x msec sagt "Ich bin am Leben", wird sie per Reset neugestartet.

Ist ein grosses Thema, das  selten zu Ende gedacht wird. Sync-FF rein
und fertig. Nur die NASA macht in ausfallsichere FSM etc..

von Martin (Gast)


Lesenswert?

Hallo Leute!
Ich habe es jetzt geschafft was in den Block-Ram zu schreiben und
zu lesen. Dafür habe ich den Codgen verwendet und ein Fifo-Ram
angelegt.
Das Lesen ist absolut kein Problem, aber mit dem Schreiben habe ich
noch Probleme. Ich benutze ein 16-Bit weites und 4096-Bytes tiefes
Fifo.
Lesen und Schreiben hat jeweils einen eigenen Clock-Eingang, was
bedeutet, dass diese beiden Vorgänge nicht synchron erfolgen müssen.

Während die Kamera eine Zeile überträgt, wird diese in das Fifo
geschrieben. Die Zeile wird mit dem Clock der Kamera in das Fifo
geschrieben. Zur Zeit 20MHZ. Wenn dieser Vorgang abgeschlossen ist
(also LVAL=0 wird), beginnt die serielle Schnittstelle zu werkeln. Für
das Auslesen des Fifo-Speichers wird ein 100MHZ Quarz genommen. Dieser
beglückt auch gleichzeitig die serielle Schnittstelle.

Leider bin ich dahintergekommen, dass zwei Worte zuviel in das Fifo
geschrieben werden, also 2x16Bit. Es sind die ersten beiden Worte, die
keine Daten enthalten. Wenn ich bei einem Lesevorgang die ersten beiden
Worte wegwerfe, dann passen die Daten 100%ig.
Ich zeige hier einen kleinen Auszug aus dem Programm. Das Problem ist
nämlich, dass die Daten in derselben Geschwindigkeit wie die
Kameraclock geschrieben werden müssen.

begin
neu: process (clkkam,lval,var2)
begin
if lval='0' then  -- wenn lval=0 Kamera sendet nicht.
   if var2='1' then var1<='1'; --var1 zeigt an, dass das serielle
Senden beginnen muss.
  wr_en<='0';  -- Nach dem Emfpang Schreibvorgang deaktivieren.
  end if;

if status /= 0 then  -- Status /= 0 zeigt an, dass die Serielle sendet,
Signale werden zurückgesetzt.
var2<='0'; var1<='0';
end if;

else
if clkkam='1' and clkkam'event then
-- bei einem positiven Kameraclock wird das Fifo din mit Daten
gefüllt.
-- Es handelt sich um 12-Bit-Messwerte, es wird aber auf 16-Bit
aufgerundet.
   var2<='1';

  din<="0000"&kamungh&kamungl;
  wr_en<='1';
end if;
end if;
end process;

wr_clk<=not clkkam;  -- Der Schreib-Clock für das Fifo
-- ist invertiert zum Kameraclock.


Die Idee ist, dass nach einer positiven Kamera-Clock-Flanke, die Daten
an den Fifo-Eingang gelegt werden. CLKKAM wird im unteren Teil
invertiert wr_clk zugewiesen. Dies bedeutet, dass bei einem negativen
Kameraclock die Daten vom Fifo übernommen werden müssten.
Nun verstehe ich nicht, warum sich vor Beginn eines Schreibvorganges
immer zwei Datenworte 2x16 im Fifo fangen.

Vielleicht kann mir einer von euch Profis helfen.
Ich danke euch im Voraus.

Tschüss, Martin

von FPGA-User (Gast)


Lesenswert?

Hallo Martin,

1.) bist Du sicher, dass Dein FIFO leer ist, bevor Du
anfängst neue Daten einzuschreiben?

2.) Ist lval exakt immer dann aktiv, wenn die Kamera Daten
sendet oder kann es 2 Clocks davor oder danach noch aktiv sein?

3.) das Design ist asynchron, da sind solche Probleme
vorprogrammiert...

von Martin (Gast)


Lesenswert?

Hallo!

1. Ja der Fifo müsste leer sein. Man kann in reseten. Zu Beginn mache
ich das zwar nicht, aber nach der ersten seriellen Übertragung wird er
für die Dauer von 10ns geresetet - Enstsprechend den 100MHZ-Quarz und
er ist dann leer, weil das Empty-Flag auf ein Led geht.

2.
Ich habe es am oszi gesehen. LVAL schaltet bei einer negativen
Kamera-Clock-Flanke auf 1. Die positiven Clock-Flanken der Kamera
belaufein sich in diesem Bereich, wo LVAL 1 ist, auf genau 2048, da es
sich um 2048 Bildpunkte handelt. Diese 2048 habe ich mir auf einen Port
ausgeben lassen und gemessen.

Ich bin mit meinem Latein am Ende. Der Simulator hat bis vor wenigen
Minuten auch nicht funktioniert. Dort teste ich es jetzt.

Danke.

Gruß, Martin

von A. N. (netbandit)


Lesenswert?

Ah je, an die Länge eines metastabilen Zustandes habe ich gar nicht
gedacht. Da hat man es schon mit Digitaltechnik zu tun und muß
Zwischenwerte bedenken... das ist gar nicht so leicht für ein dual
denkendes Hirn ;)

Aber gut also im Zweifelsfall zwei FFs ansonsten mit Timing Constraints
versuchen das ganze im Rahmen zu halten. Hmm Timing Constraints, da
hatte ich doch mal was zu diesem Thema... ja da gibt es wohl noch viel
zu lernen. :)

von FPGAküchle (Gast)


Lesenswert?

@ Andre:

<Da kann ich mich respektive der Zeit und Muße, die FPGAküchele für
die
<Newbees aufbringt, nur voll und ganz anschliessen....!!!!!!!!

<@ FPGAküchele: vielen Dank nochmals für Deine Tipps und Mühen!!!!
<Läuft mittlerweile schon gar nicht mal so schlecht....

Danke, danke für die Blumen! Na mir hats auch einiges gebracht, so
learning by teaching.

Vielleicht will ja jemand eine Zusammenfassung schreiben, in der
FPGA-Küche (http://wikihost.org/wikis/fpgakueche/) ist noch jede Menge
Platz. Einfach auf eine Diskussionsseite tippern (z.B.
http://wikihost.org/wikis/fpgakueche/programm/gebo.prg?name=unsorted_disc)
ich schiebs dann zurecht.

von A. N. (netbandit)


Lesenswert?

Ja das finde ich eine gute Idee. Es gibt leider kaum deutschsprachige
Infos zum Thema CPLD und FPGA im Netz. Eine Infobase ist da genau das
richtige.

Mal sehen ob ich da was zu beisteuern kann...

von FPGA-User (Gast)


Lesenswert?

Hallo Martin,

ja, mach erstmal eine Simulation. Bei den FIFOs gibts
ja auch verschiedene Typen, welche wo das Datenwort
gleich nach dem Einschreiben da ist und welche, wo es
erst nach einem Read-Strobe am Ausgang erscheint. Da kann
man sich schonmal um 1 Clock verhauen.

Was steht in den ersten beiden Datenworten drin?
Sind die 0 oder identisch mit dem 1. korrekten Datenwort
oder ... ?

von Martin (Gast)


Lesenswert?

Es sind zwei Nullen.
Beginnt jedoch der zweite Schreibvorgang, dann steht das zuletzt
geschriebene Datenwort, welches durch den Lesevorgang auch abgeholt
wurde, zweimal am Anfang drinnen.
Beim ersten Mal lesen z.B.:
0000 0000 ABCD 1234 ...... .... ... FA72 FB83

Beim zeiten Mal lesen:
FB83 FB83 ..... .....

Das Eigenartige ist, dass selbst der Simulator damit ein Problem zu
haben scheint.
Zudem habe ich ein ganz kurzes VHDL-Design erstellt, bei dem der
Simulator alles korrekt macht.

Gruß, Martin

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Ihr könnt auch gerne das Wiki hier auf mikrocontroller.net verwenden.
Hat einen höheren Bekanntheitsgrad, ist frei von Werbung, auch ohne
Anmeldung benutzbar, die Seiten sind direkt im Forum verlinkbar
(FPGA), und es wird sowieso regelmäßig auf Spam/Vandalismus
überwacht.

von FPGA-User (Gast)


Lesenswert?

"...dann steht das zuletzt
geschriebene Datenwort, welches durch den Lesevorgang auch abgeholt
wurde, zweimal am Anfang drinnen."

dann machst Du m.E. einen Fehler beim Lesen des FIFOs.
Du liest noch die alten Daten ein, das FIFO hat zu dem
Zeitpunkt offenbar die neuen Daten noch gar nicht rausgelegt.

Clever wäre es, wenn Dein FIFO genau so tief wäre wie die Daten
von der Kamera benötigen. Dann kann man am Verhalten der
FULL und EMPTY-Flags prima debuggen.

Schau Dir mal das Datenblatt des FIFOs genau an (Timing),
vielleicht hast Du aus Versehen auch eins mit zusätzlichen
Pipeline-Registern generiert?!?

von Martin (Gast)


Lesenswert?

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAh!

Entschuldigt bitte meinen Gefühlsausbruch Leute, aber ich habe es
geschafft. Ich weiß jetzt warum es nicht funktioniert hat.

Die Pins WR_CLK und RD_CLK müssten ständig getoogled werden, was
bedeutet, dass man diese Pins fix an eine Clock-Quelle hängen muss. Tut
man das nicht, dann kommt es zum beschriebenen Phänomen.
Den Pin RD_CLK toogelte ich nur, wenn ich in brauchte und das darf man
nicht.
Ich möchte mich aber hier zum Schluss noch recht herzlich für eure
tolle Hilfe bedanken. Alleine durch eure Antworten habe ich wieder viel
gelernt. Eine grundsätzliche Frage habe ich aber noch und bitte auch
darum, mir diese zu beantworten, ob ich das richtig sehe:

pr1: process (CLK, RESET)
begin
[...]
  if clk'event and clk = '1' then -- steigende Flanke
    Signal_S <= Signal;
  end if;
[...]
end process;

pr2: process (CLK, RESET)
begin
[...]
  if clk'event and clk = '1' then -- steigende Flanke
    [State Machine - Signal_S wird abgefragt.]
  end if;
[...]
end process;


Ich habe hier zwei Prozesse. Jeder von beiden reagiert auf eine
positive Flanke. In Prozess 1 wird das asynchrone Signal abgefragt und
dem Signal_S zugewiesen.
Prozess 2 besteht aus einer State-Machine, wo das Signal_S wiederum
abgefragt wird.

Ich wollte fragen, ob dies so in Ordnung ist, da ja jetzt bei einer
positiven Flanke das asynchrone Signal abgefragt wird und gleichzeitig
im anderen Prozess das Signal_S auch abgefragt wird.

Wäre es nicht besser den Prozess 1 auf eine negative Flanke
auszurichten?
Denn dann würde eine negative Flanke die Zuweisung auf Signal_S
bewirken und eine positive Flanke eine Abfrage des Signal_S in der
State-Machine.

Oder sind beide Varianten problemlos möglich?

Danke nochmals

Tschüss, Martin

von A. N. (netbandit)


Lesenswert?

>Wäre es nicht besser den Prozess 1 auf eine negative Flanke
>auszurichten?
>Bebewirken und eine positive Flanke eine Abfrage des Signal_S in der
>State-Machine.
>Oder sind beide Varianten problemlos möglich?

Klar wäre so eine zwei Flanken Logik besser :) Aber soetwas ist unter
normalen Umständen nicht synthesefähig. Wenn du in einem process die
positive und in einem anderen die negative Flanke abfragst bekommst du
eine Fehlermeldung.
Es gibt soweit ich gelesen habe für DDR-SDRAM eine Lösung mit zwei
Flanken gesteuerten FFs. Doch muß der FPGA dies ausdrücklich
unterstützen und soweit ich weiß ist das auch nur für diese spezielle
Anwendung gedacht.

von FPGA-User (Gast)


Lesenswert?

Hallo Martin,

aus Deiner Frage lese ich heraus, dass Du noch nicht verstanden hast,
welche Hardware aus dem VHDL-Code generiert wird.

Die Idee mit den 2 Flanken bringt hier gar nichts - im Gegenteil.

Zeichne mal die Schaltung auf, dann wirst Du sehen was ich meine.
Wenns immer noch nicht klar ist, poste die Schaltung hier und frage.

von A. N. (netbandit)


Lesenswert?

@FPGA-User

wenn es theoretisch klappen würde beide Flanken zu nutzen würde das
einem Verhalten entsprechen wo die CLK für die FSN um 180°
Phasenverschoben zum CLK der EingangsFFs arbeitet.

Bei steigender Flanke wird das Signal in die EingangsFFs übernommen und
steht kurze Zeit später der kombinatorischen Logik vor den FSM-FFs zur
verfügung.
180° später übernehmen die FSM-FFs das Signal... wenn man den CLK den
Laufzeiten der kombinatoren Logik anpasst sehe ich da an sich kein
Problem. Hab ich was übersehen?

Allerdings ist das ja Hardwaretechnisch nicht ohne weiteres möglich
beie Flanken abzufragen.

von FPGAküchle (Gast)


Lesenswert?

<Ihr könnt auch gerne das Wiki hier auf mikrocontroller.net verwenden.
<Hat einen höheren Bekanntheitsgrad, ist frei von Werbung, auch ohne
<Anmeldung benutzbar, die Seiten sind direkt im Forum verlinkbar
<(FPGA), und es wird sowieso regelmäßig auf Spam/Vandalismus
<überwacht.

Hm, jetzt habe ich auf wikihost.org angefangen... Na schon mer mal
jedenfalls
Dank für den Hinweis

von Martin (Gast)


Angehängte Dateien:

Lesenswert?

Hallo FPGA-USER.

Ich habe deinen Rat befolgt und zwei verschiedene VHDL-Codes generiert.
Siehe hier:

-- Erster Code
pr1: process (CLK)
begin
  if clk'event and clk = '1' then -- steigende Flanke
    signal_s <= signalin;
  end if;
end process;

pr2: process (CLK)
begin
  if clk'event and clk = '1' then -- steigende Flanke
    if signal_s='0' then
   signalout2<='0';
   else
   signalout2<='1';
   end if;
  end if;
end process;



-- Zweiter Code
pr1: process (CLK)
begin
  if clk'event and clk = '0' then -- fallende Flanke
    signal_s <= signalin;
  end if;
end process;

pr2: process (CLK)
begin
  if clk'event and clk = '1' then -- steigende Flanke
    if signal_s='0' then
   signalout2<='0';
   else
   signalout2<='1';
   end if;
  end if;
end process;

Ich habe die State-Machine mal weggelassen, weil ich dachte, dass es
nur ums Prinzip geht. Also das asynchrone Port-Signal "signalin" wird
im ersten Prozess dem Signal "signal_s" zugewiesen, um das Ganze zu
synchronisieren.
Im ersten Code wird diese Signalzuweisung bei einer steigenden Flanke
vorgenommen und im zweiten Code bei einer fallenden. Ich habe mir
daraufhin RTL-Schematic und Technology-Schematic angesehen und bin zu
folgendem Schluss gekommen. Bitte korrigiert mich falls ich falsch
liege. Zusätzlich habe ich euch die entworfenen Schaltungen angehängt.

Im ersten Code:
Das erste Flip-Flop schaltet bei einer steigenden Clock-Flanke den Port
"signalin" durch. Aber gleichzeitig schaltet das zweite Flip-Flop auf
"signalout2" durch. Meiner Meinung nach könnte es hier zu Problemen
kommen. Nun weiß man aber nicht, ob der alte oder der neue Wert vom
zweiten Flip-Flop übernommen wird. Anscheinend ist diese Lösung nicht
besonders eindeutig.

Zweiter Code:
Das erste Flip-Flop schaltet bei einer negativen Clock-Flanke den Wert
aus "signalin" durch. Bei einer positiven Flanke wird dieser
ausgegebene Wert von zweiten Flip-Flop übernommen und auf
"signalout2" ausgegeben.
Meiner Meinung nach ist diese zweite Variante wesentlich
unempfindlicher gegen Fehler.


Was meint ihr?

Gruß, Martin

von Klaus F. (kfalser)


Lesenswert?

Beide Lösungen sind 100 % eindeutig, welche besser ist, hängt von deinen
Taktfrequenzen ab.
Bei der 1. Version verlierst Du einen vollen Taktzyklus, bei der 2.
Version einen halben.
Bei der 2. Version hat das 1. FF im Falle einer Metastabilität nur halb
so viel Zeit um einen stabilen Zustand zu erreichen, ansonsten macht das
2. FF auch einen Fehler.
Bei den aktuellen Bausteinen und bei nicht zu hohen Taktfrequenzen ist
die Wahrscheinlichkeit eines Fehlers des 2. FF aber sehr gering.
Es ist also die 2. Variante im Prinzip empfindlicher gegen Fehler.

Du bezeichnest die 1. Version als nicht eindeutig, aber das stimmt
nicht.  Wenn die aufsteigende Taktflanke kommt, übernehmen beide FF die
ALTEN Werte for der Taktflanke am Eingang, also signal_s wird zu
signalin und signalout2 wird zum alten Wert von signal_s.
Wenn das nicht so wäre könnte man nicht einmal einen Zähler
realisieren, bei dem wird ja auch der Wert nach der Taktflanke zu alten
Wert + 1.

Grüße
Klaus

von FPGA-User (Gast)


Lesenswert?

Hallo Martin,

OK, jetzt weiss ich, wo Dein Problem liegt. Angenommen Du baust
eine Kette aus 4 D-Flip-Flops. Die Takteingänge sind alle
verbunden und der Q-Ausgang des vorherigen FFs ist immer mit dem
D-Eingang des nachfolgenden verbunden.
Alle FFs stehen zunächst auf '0'.
Du legst jetzt an den Eingang des 1. FF eine 1 an und gibst eine
pos. Taktflanke an alle FFs. Was passiert ?

Alle FFs übernehmen den Logikpegel, der VOR der Taktflanke am
D-Eingang vorhanden war und speichern diesen Zustand. Es wird
also ein Schieberegister realisiert, das nach 4 Takten die 1 am
Ausgang des 4. FFs übernommen hat.

Nichts anderes ist Dein VHDL-Code oben.

Die 1.Variante ist die bessere und nicht die 2.
Warum ?
Bei der ersten Variante kannst Du die Funktion prinzipiell mit
einem einzigen Clock-Constraint gewährleisten. Und wie Klaus
schon bemerkt hat, bei Metastabilen Zuständen ist eine ganze
Clockperiode Zeit bis zum nächsten Takt.
Bei Variante 2 halbiert sich die "Reservezeit" und Du musst
entweder darauf hoffen, dass der Timing-Analyzer intelligent
genug ist und sieht, dass der Pfad von signal_s zu signalout2
nur TCLK/2 Delay haben darf oder selbst ein zusätzliches
Constraint setzen.

von alex (Gast)


Lesenswert?

@Martin:
So könnte es auch gehen:

-- Erster Code
pr1: process (CLK, signalin, signal_s)
begin
  if clk'event and clk = '1' then -- steigende Flanke
    signal_s <= signalin;
    signalout2 <= signal_s;
  end if;
end process;

-- Zweiter Code
pr1: process (CLK, signalin)
begin
    if clk'event and clk = '0' then
        signal_s <= signalin;
    end if;
end process;

pr2: process (CLK)
begin
    if clk'event and clk = '1' then
        signalout2 <= signal_s;
    end if;
end process;

von alex (Gast)


Lesenswert?

ups, im Prozess pr2 process(clk, signal_s) vergessen...

von Andreas Kratzsch (Gast)


Lesenswert?

Hallo,

"ups, im Prozess pr2 process(clk, signal_s) vergessen..."

wieso ?

Der Process soll doch nur etwas tun wenn clock sich ändert,
wozu sollen die anderen Signale in die Liste ?
Bei den anderen Processen im Beispiel trifft das gleiche zu.

Andreas

von Martin (Gast)


Lesenswert?

Hallo.

Das Problem besteht darin, dass jedes Signal, welches in einem Prozess
abgefragt wird normalerweise in dieser Empfindlichkeitsliste stehen
muss.
Steht ein Signal nicht drinnen wird es automatisch von Werkzeug
eingefügt. Warum das so ist habe ich bis heute auch noch nicht ganz
verstanden.

Gruß, Martin

von T.M. (Gast)


Lesenswert?

Bei einem getakteten Prozess muss nur der Clock und eventuelle
asynchrone Reset/Preset Signale in der Sens.-Liste stehen. Eben weil
der Prozess nur "aktiviert" wird, wenn sich der Clock ändert.

Also hat Andreas recht.

von alex (Gast)


Lesenswert?

>Der Process soll doch nur etwas tun wenn clock sich ändert,
>wozu sollen die anderen Signale in die Liste ?
>

Nicht angegebene Signale in der Liste führen soweit ich weiß zum
unerwünschten "Gedächtnis" - ungetaktete Flipflops.
Aber vielleicht bin ich nicht auf dem aktuellen Stand...

von Andreas Kratzsch (Gast)


Lesenswert?

Hallo,

ich denke was Du meinst sind Variablen denen nicht immer
ein Wert zugewiesen wird, die erzeugen Latches ?

Das wird aber auch deutlich als Warnung angezeigt,
zumindest im Xilinx Webpack 7.1.

Andreas

von alex (Gast)


Lesenswert?

nein, im meine genau die Signale in der "sensitivity list".
In der Quartus-Entwicklungsumgebung werden die fehlenden Signale als
Warnung angezeigt, man muß dann in der Liste alle Signale angeben, die
im betroffenen Prozess gelesen werden.

von T.M. (Gast)


Lesenswert?

Aber in einem auf Flanken getakteten Prozess werden eben keine Latches
erzeugt, sondern FF.
Nur bei einer Taktzustandsbeschreibung kommt es zu einem Latch, oder
bei einem kombinatorischen Prozess, bei dem was in der Sens.liste
fehlt.

von alex (Gast)


Lesenswert?

Ich würde trotzdem alle Signale in der Liste angeben.

>Aber in einem auf Flanken getakteten Prozess werden eben keine
Latches
>erzeugt, sondern FF.

Wenn das so wäre, wozu bräuchte man dann überhaupt die "sensitivity
list"? Man könnte die Liste überhaupt weglassen und dem Synthesizer
oder dem Simulationstool die Arbeit überlassen, die sollen dann
erkennen, ob der Prozess getaktet oder nicht getaktet, kombinatorisch
oder was auch immer ist.
Ich behaupte nicht, dass die Latches immer erzeugt werden, aber da die
Möglichkeit besteht, sollte man die Maßnahme ergreifen.

von T.M. (Gast)


Lesenswert?

Sorry, aber nach dem Lesen von 3 Büchern wo das so drin stand, gehe ich
davon aus, dass es so ist. Wenn ein
1
clk'event and clk='1'
in einem prozess steht, dann wird
1. ein FF synthetisiert
2. kommt nur das clk und ein eventueller asynchr. Reset/Preset in die
Liste
Alleine das oben genannte Codeschnipsel inferiert schon ein FF. Latches
werden bei unvollständiger Beschreibung von Taktzustandsgesteuerten
Prozessen erzeugt, oder wenn ein Signal in einem komb. Prozess zuerst
gelesen, und erst danach zugewiesen bekommt. So kenne ich das.
Nachzulesen auch in dem Buch 'VHDL-Synthese'

von Kest (Gast)


Lesenswert?

Leute, T.M. hat vollkommen Recht

Und die Sensitivitätsliste braucht wer? Na der Simulator! ;-)
Dem Synthesewerkzeug soll es egal sein, was da in der Liste steht. Er
warnt zwar, aber mir doch egal :-o ;-)
Wenn man ein oder anderes Signal vergisst, wird die richtige Hardware
trotzdem generiert.
Bei der Simulation aber könnte es zu problemen führen

So weit von mir,

Kest

von alex (Gast)


Lesenswert?

Von welchem Autor ist das Buch? Gibt es da ein Kapitel über
unvolständige Empfindlichkeitsliste o.ä.?
Ich kenne eins (allerdings ein älteres, 1996 oder 98), wo ein ganzes
Kapitel dem Thema "unvollständige Sensitivity Liste" gewidmet ist,
"Abstrakte Modellierung digitaler Schaltungen" von ten Hagen. Weiss
nicht, ob eine neue Auflage erschienen ist, vielleicht hat sich
inzwischen was geändert...
Das ist richtig, dass bei "clk'event and clk='1'" ein FF entsteht.
Aber die Frage ist, wie ist denn das allgemein, wenn in der Liste ein
Signal vergessen wird. Was macht Synthesizer oder Simulationstool
damit? Bei der Simulation ist es denkbar, dass der betroffene Prozess
gar nicht aktiviert wird, egal wie oft sich das Signal ändert (das
Signal steht ja nicht in der Liste). Was passiert dann, wird der alte
Wert des Signals beibehalten oder verworfen? Wenn beibehalten, dann ist
klar, ein Flipflop entsteht. Wenn nicht, dann ist vielleicht gut so.

von T.M. (Gast)


Lesenswert?

Bei kombinatorischen Prozessen gehören alle gelesenen Signale in die
Sens.liste. Bei sequentiellen Prozessen nur das Clocksignal. Weil der
Prozess halt nur "aktiviert" wird, wenn sich ein Signal aus der Liate
ändert. Da das bei komb. Logik bei jdem Eingangssignal passieren soll,
müssen alle in die Liste. Bei sequentiueller Logik soll das FF ja nur
schalten, wenn eine Clockflanke anliegt, deshalb nur der Clock in der
Liste...Ich glaube, die Synthesewerkzeuge erkennen auch, dass Signale
in der Liste fehlen und fügen diese dann automatischn ein, ob das aber
immer funzt weiß ich auch ni.

Das Buch vom ten Hagen hab ich auch, müsst ich dann mal reinschauen.
Das VHDL-Synthese Buch haben 2 Profs von ner Hochschule in Hamburg
geschrieben.

von Klaus F. (kfalser)


Lesenswert?

Eine korrekte Sensitivity List ist wichtig, und wenn man VHDL
programmiert sollte man sich auch bemühen zu verstehen was passiert.

Daß sich einige Synthese-Werkzeuge mit falschen oder unvollständigen
Listen abfinden und nur eine Warnung generieren ist eine unglückliche
Wahl und tut meiner Meinung nach dem Benutzer letztendlich keinen
Gefallen, weil man kleine, gemeine Fehler machen kann.

Wie wichtig die Liste ist zeigt das folgende Beispiel :

bsp1 : process(g, d) is
begin
if (G = '1')
    Q <= D;
end process;

bsp2 : process(g) is
begin
if (G = '1')
    Q <= D;
end process;

bsp1 beschreibt ein Latch. Wenn G auf '1' steht, kann sich D noch
ändern und Q ändert sich mit.

bsp2 beschreibt ein FF. Wenn G auf 1 geht, wird D nach Q übernommen.
Ein nachträgliches Ändern von D ändert Q nicht mehr, eben ein FF.

bsp2 entspricht aber nicht der Struktur wie ein Synthese-Compiler die
Beschreibung eines FF erwartet weil das if rising_edge() fehlt.
bsp2 ähnelt bsp1, welches eine gültige Beschreibung für ein Latch ist.
Wenn der Compiler nun automatisch 'd' in die Liste einfügt, und dann
ein Latch erzeugt, entspricht das nicht mehr dem ursprünglichen Kode
und das Ergebnis stimmt mit der Simulation nicht überein.

Übrigens eine Bitte an alle :
schreibt doch "rising_edge(clk)" anstelle von
"clk'event and clk = '1'".
Das ist besser verständlich und alle heutigen Synthesewerkzeuge
verstehen es.

Grüße
Klaus

von FPGA-User (Gast)


Lesenswert?

sehr gut, die Beispiele, aber wenn man die Warnungen der
Synthese aufmerksam liest, ergeben sich kaum Probleme:

für Bsp. 1 generiert Quartus die folgende korrekte Warnung :

Warning (10631): VHDL Process Statement warning at senstest.vhd(17):
signal or variable "q" may not be assigned a new value in every
possible path through the Process Statement. Signal or variable "q"
holds its previous value in every path with no new value assignment,
which may create a combinational loop in the current design.

und für Bsp. 2 die ebenfalls korrekte Warnung :

Warning: Found pins functioning as undefined clocks and/or memory
enables
  Info: Assuming node "g" is an undefined clock

Besser wäre es aus meiner Sicht auch, wenn die Synthese Bsp 2
mit einem Error abbrechen würde.

@Klaus
deine 2 Beispiele sind genau das, was man in VHDL nicht machen
sollte: gemischte Groß- / Kleinschreibung, nicht compilierbar,
... ;-)))

von Klaus F. (kfalser)


Lesenswert?

Uh, für die nicht kompilierbaren Beispiele entschuldige ich mich
natürlich sofort.
Das kommt daher, daß mir Xemacs die Syntax abnimmt und ich ohne Xemacs
eigentlich verloren bin.

T'schuldigung
Klaus

von Andreas Kratzsch (Gast)


Lesenswert?

Hallo,

die Sensitivity List ist eigentlich nur ein wait am Ende des Processes,

also gehören auch nur die Signale rein die den Process aktivieren
sollen .
Das ist hier auch so beschrieben:

http://mikro.e-technik.uni-ulm.de/vhdl/anl-deut.vhd/html/node30.html

Andreas

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.