Hallo Ich bins schon wieder und habe eine kleine Verständnisfrage. Angenommen ich habe einen Process, der auf den clock sensitiv ist. Nun ist dieser process jedoch etwas länger. Das heisst ja in der Zwischenzeit können mehrere clock - ticks auftreten - korrekt? Oder ist dann mit diesem langem Prozess meine maximale Taktfrequenz gegeben?
hallo tom, zu den "mehreren clock ticks" : nein. der prozess wird (um es mal softwaretechnisch zu sagen) über die clock angetriggert. wenn dein prozess "länger" braucht (bedenke das "nur" die gatterlaufzeiten deinen maximalen takt bestimmten) wird deine mögliche takt-frequenz niedriger. wenn es erforderlich ist das der prozess "wartet" lässt sich das nur durch zählen der takte machen. gruß rene
Hallo Thomas, soweit mir bekannt ist, wird nachdem ein Prozess mit clk aktiviert wurde, dieser solange sequentiell ausgeführt, bis der Prozess beendet ist. Weitere Clk´s während der Ausführungsdauer des Prozesses werden ignoriert, da es ein sequentieller Vorgang ist. MFG
jedesmal wenn sich das clock signal ÄNDERT wird der process angestartet und sofort komplett abgearbeitet. Zumindest tut der Simulator so. wobei abarbeiten meint; er berechnet für jede Zuweisung wann und welchen Wert diese erhält. dabei lässt er sich auch nicht von neuen Flanken stören, weil die treffen erst nach einem delta delay ein, genau solange braucht er für die Ausführung der zuweisungen. Also für die Simu heisst die Antwort Nein. In der (funktionalen) Simu kannst die taktfrequenz beleibig hochsetzen und der Simulator wird simulieren. Die "Warning: clock to fast" musst du selber in den VHDL code schreiben. In echt gibt es keine Processe und nix wird sofort abgearbeitet. Die taktfrequenz wird (grob) durch die zeit bestimmt die ein Signal vom FF output zum FF input braucht. Diese zeit wird durch die Logik und verdrahtung zw. den FF bestimmt. ein getakter process ist in Echt die Eingangsbeschaltung eines FF, also kann man aus den Zuweisungen innerhalb eines process schon abschätzen wie lang der Pfad zw. den FF ist und somit wie schnell der FPGA/ASIC getaktet werden kann. Also man kann schon einem Process ansehen wie schnell die Hardware ist. Des hat aber nix mit der Länge des Codes zu tun. Du kannst in einem Process mehr code als text in der Bibel steht reinschreiben und der synthetisierte FPGA läuft mit 300 MHZ. Und du kannst 5 zeil reinpacken und das design läuft nur mit 1.2345 MhZ. Also VHDL ist nicht Software, aus der Anzahl der Codezeilen kann nicht zwingend auf die geschwindigkeit der realisierung geschlossen werden. Bei Software in Assembler auf "ein Takt ein befehl Machienen" wie AVR ist das anders, (schleifen entsprechend beachtet).
>Also VHDL ist nicht Software VHDL ist schon Software, aber die digitale Hardware, die damit beschrieben wird, ist es nicht.
Hallo Thomas, > Hm? Kann es sein, dass sich die beiden Antworten widersprechen? Ja ... (scheint so ;-) > Angenommen ich habe einen Process, der auf den clock > sensitiv ist. Nun ist dieser process jedoch etwas > länger. Das heisst ja in der Zwischenzeit können > mehrere clock - ticks auftreten - korrekt? Oder ist > dann mit diesem langem Prozess meine maximale > Taktfrequenz gegeben? Es gibt in VHDL in einem Prozess 2 Arten, einen "zeitlichen" Ablauf zu spezifizieren: - Sensitivity List - Wait Statement Die Sensitivity List startet einen Prozess jedesmal, wenn sich ein Signal darin ändert. Danach wird der Prozess in Nullzeit ausgeführt und wartet wieder auf die nächste Änderung in der Sensitivity List. Im Prozess wird keine weitere Zeit "verbraucht". Der zeitliche Ablauf wird dabei im Prinzip über die Signale gesteuert, die in der Sensitivity List sind. Beschreibt man einen synchronen Prozess, hat man darin i.d.R. Clock und Reset. Mit "jeder" Clockflanke wird der Prozess erneut gestartet. Wievie Logik Du dann reinpackst ist dem Prozess egal (ist nur später wichtig, wenn Du eine Synthese für ein bestimmtes Device/Target Library machst und die Taktfrequenz festlegst, ob dies zusammenpasst). Wait statements: Alternativ dazu kannst Du in einem Prozess wait statements verwenden. Der Prozess läuft dann in Nullzeit bis zum nächsten Waitstatement und wartet, bis die Bedingung erfüllt ist (kann Event sein oder Abfrage eines Signalwertes oder feste Zeit). Ist diese erfüllt, läuft er bis zum nächsten Wait. Ist der Prozess am Ende angekommen, fängt er wieder von vorne an. Schreibst Du z.B. wait until Clock='1'; ... wait for 100 ns; ... wait until clock='1'; würde beim warten auf die 100 ns der Clock ignoriert. (Ich würde aber nicht so beschreiben.) In einem Prozess mit Sensitivity List dürfen KEINE wait statements vorkommen (und umgekehrt). Gruss, Alex
Also gut. Der Code soll später auch synthetisiert werden, daher ist die Simulation für mich mal zweitrangig. Ich würde schon gerne Code erzeugen der auch synthetisiert werden kann. @FpgaKüchle: Das mit der Anzahl an Codezeilen ist mir klar. Die beiden Extrema die ich mir vorstelle sind z.B. eine einfache Zuweisung oder 100 Zuweisungen (sehr kurz) und eine Art Register, das mehrmals verändert wird, weil hier die Anweisungen nicht parallel laufen können (korrekt?). Du stimmst also mit der Antwort von TheMason überein. Sehe ich das richtig? @Alex H.: Für mich ist besonders wichtig, dass der Code auch synthetisiert werden kann. Das mit dem wait for 100ns wusste ich, wobei ich noch nicht heraus gefunden habe, wie ich am besten eine (synthetisierbare) wartezeit von ... sagen wir mal 10 Sekunden basteln kann ... aber das bekomm ich sicher auch noch raus. Es geht bei mir natürlich nur um eine synchrone Schaltung. Im Prinzip stimmt deine Meinung also mit TheMason und FpgaKüchle überein? @Xenu: VHDL ist doch auch keine Software sondern nur eine Beschreibungssprache (oder Programmiersprache) ;)
Moin... bevor ihr da was versucht was nicht geht: "wait for .." ist eine Simulationsanweisung und kann NICHT synthetisiert werden! Feste Zeiten warten geht eigentlich nur über Zähler und bekannten Takt. -- SJ
Hallo Thomas, > Im Prinzip stimmt deine > Meinung also mit TheMason und FpgaKüchle überein? Ja. Meine Antwort hat sich mit FpgaKüchle überschnitten. > ... wird nachdem ein Prozess mit clk aktiviert wurde, > dieser solange sequentiell ausgeführt, bis der Prozess > beendet ist. Weitere Clk´s während der Ausführungsdauer > des Prozesses werden ignoriert, da es ein sequentieller > Vorgang ist. Hat der Prozess eine Sensitivity List, stimmt das so nicht. Dann werden alle Anweisungen im Prozess nach dem Starten des Prozesses in Nullzeit ausgeführt. > Das mit dem wait for 100ns wusste ich, > wobei ich noch nicht heraus gefunden habe, wie ich am > besten eine (synthetisierbare) wartezeit von ... sagen > wir mal 10 Sekunden basteln kann Das Prinzip ist anders. Wie Du schon sagtest, möchtest Du synchron arbeiten. D.h. Du hast irgendwo einen Takt, der eine bestimmte Taktfrequenz hat, z.B. 100 ns. Dazu implementierst zu z.B. in Deiner Testbench einen Prozess, der diesen erzeugt: process begin Clock <= '1'; wait for 50 ns; Clock <= '0'; wait for 50 ns; end process; Das ganze läuft nun immer im Kreis herum. Am besten noch nen reset, der zu Beginn aktiv ist und dann irgendwann mal inaktiv wird. In Deiner Schaltung beschreibst Du dann das, was Du machen möchtest, in einem Prozess, der von Clock und Reset abhängt: process (Clock, Reset) begin if Reset='1' then Ausgang <= '0'; -- Initialisierung elsif Clock'event and Clock='1' then -- nun kommt das was Du machen möchtest ... Ausgang <= ... ... end if; end process; Alles, was im Elsif-Zweig steht, wird in "einem" Taktzyklus ausgeführt. Willst Du hier komplexe Berechnungen machen, dann erreichst Du entweder nur eine niedrige Taktfrequenz, oder Du musst versuchen, nur einen Teil zu berechnen und in einem Register (FlipFlop) zwischenzuspeichern und im nächsten Takt den Rest zu berechnen. > 10 Sekunden warten ... Macht man über einen Timer. Rechne aus, wieviele Taktzyklen dies z.B. bei 100 ns Taktperiode sind (100 Mio) und beschreibe einen Timer, der mit einem Startsignal auf Null gesetzt wird und nach Ablauf der Zeit dann beispielsweise ein Triggersignal für den Rest der Schaltung erzeugt. Gruss, Alex
@SvenJohannes: Ja, ist klar :) @Alex H: Das mit dem Takt in der Testbench habe ich verstanden. Habe ich auch schonmal gemacht. Im Reset würde ich mal den Signalen fixe Werte zuweisen, sodass die Signale vom Start weg definiert sind (zumindest wurde es uns erklärt, dass dies auf jeden Fall nicht schlecht ist, für mich machts auch Sinn). Bzgl. Elsif - Zweig: Dann ist das also so wie ich es mir vorgestellt habe. Genau das wollte ich wissen. Das mit dem Timer habe ich mir auch schon überlegt. Mein Gedankengang war eben, dass der Timer (wenn abgelaufen) ein Signal ändert, welches in der Sensitivity List eines (anderen) Prozesses steht. Dieser würde dann die entsprechende Aktion vornehmen. Klingt für mich als könnte es funktionieren oder siehst du einen groben Denkfehler? Achja nochwas. Wie zähle ich denn am besten so weit hinauf .. da bräuchte ich ja einen 27 bit Zähler. Wird das in der Realität so gemacht?
Hallo Thomas, > Mein Gedankengang war eben, dass der Timer (wenn > abgelaufen) ein Signal ändert, welches in der > Sensitivity List eines (anderen) Prozesses steht. > Dieser würde dann die entsprechende Aktion > vornehmen. Nicht in der Sensitivity List. Die Sensitivity List von einem getakteten Prozess hat nur Clock und Reset :-) Wenn Du das Trigger-Signal erzeugt hast, dann frägst Du es innerhalb des elsif-Bereiches ab. Dort können beliebig (naja fast) viele Ifs und Cases usw. stehen. D.h. elsif Clock'event and Clock='1' then -- nun kommt das was Du machen möchtest ... if Trigger = '1' then Ausgang <= ... ... end if; > Achja nochwas. Wie zähle ich denn am besten so > weit hinauf .. da bräuchte ich ja einen 27 bit Zähler. > Wird das in der Realität so gemacht? Spricht nix dagegen ... (Musst nur schauen, dass Du das ganze noch auf Dein FPGA synthetisieren kannst. Bin kein FPGA-Experte, aber 27-Bit sollten noch machbar sein.) Gruss, Alex
-Nicht in der Sensitivity List. -Die Sensitivity List von einem getakteten Prozess -hat nur Clock und Reset :-) FF mit async. reset -> clk und rst in SensList FF mit sync. reset -> clk in SensList
Moment mal. Ich darf nur Prozesse haben, die auf Clock getriggert werden? Nicht oder? Dass der getaktete Prozess nur von clk/rst abhängig ist, ist mir klar. Dort starte ich dann auch den Timer, bzw. inkrementiere diesen. Darf nun der Prozess, der auf eine bestimmte Timerstellung wartet nun nicht sensitiv auf ein Signal "TimerHatOberesEndeErreicht" sein?
#Moment mal. Ich darf nur Prozesse haben, die auf Clock getriggert #werden? Nicht oder? Nein du kannst auch sogenannte konbinatorische Prozesse schreiben. Zum beispiel ein NAND: [vhdl] Process(nand_a,nand_b) begin if nand_a = '1' and nand_b = '1' then nand_res <= '0' else nand_res <= '1'; end if; end process; [\vhdl] FF werden synthetisiert, wenn der process auf clk getriggert wird. Also das taktnetzwerk am clk input des FF hängt. Man sollte nur ein Taktnetzwerk benutzen, aber falls man weiss was man tut kann man auch andere Signale auf 'event abfragen (z.B. ripple counter). Als Anfänger solltest du nur ein Signal auf Flanke ('event) testen, und da ist der Takt.
Also das verstehe ich jetzt nicht ganz. Obiger Code hat die beiden Operanden des Nand in der Sensitivity List - klar. Ändert sich einer, wird dieser Prozess getriggert und ausgeführt. Angenommen ich schreibe in meinem Code so etwas (bei dem signal ist mir noch nicht klar, was ich hier nehme, das muss ich noch nachschlagen): signal befehlsnummer : std_logic (7 downto 0) signal a : std_logic signal counter : std_logic_vector (27 downto 0) basic : Process (clk, rst) begin if clk'event and clk = '1' then if befehl = "0011" then -- opcode fuer wait counter <= counter + 1; -- Zuweisung erfolgt sowieso erst am Schluss if counter = "111111111111111..." then a <= "0"; elseif befehl = "0100" then -- Opcode für DEC befehlsnummer <= befehlsnummer + 1; akku <= akku - 1; ... end if end if end timertop : process (a) begin befehlsnummer <= befehlsnummer + 1; end Wäre das jetzt beispielsweise erlaubt? Konkret gehts darum, dass ich wenn ich in einem bestimmten State bin (wait), solange keinen anderen Befehl ausführe, bis der Timer abgelaufen ist. ich komme von der Softwareschiene und tue mir daher mit der Vorstellung noch etwas schwer. Ausserdem ist es mein erstes Projekt, daher bitte nicht auf den Code schauen ;)
Das ist dann schlecht ... dann werde ich die Idee mal kübeln. Ich hoffe auf der Uni-Bibliothek ist bald das (von dir?) empfohlene Buch verfügbar. Dann könnte ichs mir endlich mal ansehen. Werde mich wohlin der Zwischenzeit mal mit einem anderen Teilbereich beschäftigen. Aber durch den Thread wurde mir das eine oder andere schonmal deutlich klarer :) Ich danke daher derweil mal recht herzlich und wünsche euch schönen Urlaub ohne mich. Nutzt ihn, denn wenn wieder Fragen auftauchen, ist er zu Ende :)
@thomas so wie du es vor hast (ein prozess -> timer, anderer prozess -> befehlszähler) ist schon richtig, du mußt halt nur den takt im 2. prozess mit einbeziehen : -- timer process (clk,res) ... if clk'event and clk = '1' then ... if timer = "111111111111" then a <= '1'; else a <= '0'; end if; ... end if; ... -- befehlszähler process (clk,res) ... if clk'event and clk = '1' then ... if a = '1' then befehlscounter <= befehlscounter + '1'; end if; ... end if; ... was zu beachten ist (wie fpgaküchle schon meinte) : du darfst signale (z.b. befehlszähler) NICHT aus zwei prozessen gleichzeitig heraus verändern. (das funzt nicht) d.h. du kannst zwar aus jedem prozess jedes signal lesen, aber verändern nur aus einem prozess heraus. mache es über flags (wenn der ausdruck so passt) die du in einem prozess setzt und in einem anderen prozess abfragst. bsp : signal inkr_bef_zaehl : std_logic; signal res_bef_zaehl : std_logic; signal setze_bef_zaehl : std_logic; signal bef_zaehl : std_logic_vector (xx downto 0); signal timer_zaehl : std_logic_vector (xx downto 0); signal neu_bef_zaehl : std_logic_vector (xx downto 0); -- steuerung für befehlszähler process (clk,res) ... if res = '1' then inkr_bef_zaehl <= '0'; res_bef_zaehl <= '0'; elsif clk'event and clk = '1' then timer_zaehl <= timer_zaehl + '1'; if timer_zaehl = max_timer_wert then inkr_bef_zaehl <= '1'; else inkr_bef_zaehl <= '0'; end if; ... if irgendwas then neu_bef_zaehl <= "1010101010"; -- beispielsweise konstanter wert setze_bef_zaehl <= '1'; -- hier muß nur dafür gesorgt werden das im nächsten takt das setze_bef_zaehl zurückgenommen wird !!! end if; end if; ... -- befehlszähler selbst process (clk,res) ... if res = '1' then bef_zaehl <= (others => '0'); elsif clk'event and clk = '1' then -- wir können den befehlszähler resetten if res_bef_zaehl = '1' then bef_zaehl <= (others => '0'); end if; -- wir können den befehlszähler inkrementieren if inkr_bef_zaehl = '1' then bef_zaehl <= bef_zaehl + '1'; end if; -- wir können den befehlszähler auf festen wert setzen if setze_bef_zaehl = '1' then bef_zaehl <= neu_bef_zaehl; end if; end if; ... so würde es aussehen wenn du einen befehlszähler komplett unabhängig implementierst, und von einem anderen prozess heraus (über steuersignale) verändern kannst. du mußt nur dafür sorgen das wenn du signale, die in anderen prozessen werte verändern, setzt, diese auch wieder zurücknimmst. (wichtig, sonst sucht man sich nen wolf, und es klappt nichts. dann kommt man ums simulieren nicht drum herum) hoffe ich konnte dir was weiterhelfen gruß rene
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.