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
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
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
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.
Okay, das mit dem Counter schluckt Quartus. Es entsteht nur ein Addierer. Gut. Kest
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
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?
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
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.
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).
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
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.
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
>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...).
#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.
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.
@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
>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.
>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
@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?
<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
>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 ;)
@ 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
> 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
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..
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
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...
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
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. :)
@ 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.
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...
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 ... ?
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
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.
"...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?!?
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
>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.
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.
@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.
<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
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
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
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.
@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;
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
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
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.
>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...
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
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.
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.
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.
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'
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 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.
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.
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
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, ... ;-)))
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.