Ich versuche schon seit ein paar Stunden flankengesteuert ein FF zu setzen und zurückzusetzen: Kommt eine High-Low Flanke von Signal A, soll dass FF gesetzt werden, kommt eine Low-High Flanke von Signal B, soll es zurückgesetzt werden. Aber leider komme ich mit der Triggerung auf die beiden Flanken nicht weiter...
if a'event and a='1' then q <='1'; elsif b'event and b='0' then q <='0'; end if; ? Ist das das, was Du suchst? Kest
Ja, so habe ich es auch: if ale='0' and ale'event then ras <= '1'; elsif En='1' and En'event then ras <= '0'; end if; Allerdings kommt dann ein Fehler: Signal ras cannot be synthesized, bad synchronous description.
Ich vermute mal, dass da noch ein ELSE-Zeweig fehlt if ale='0' and ale'event then ras <= '1'; elsif En='1' and En'event then ras <= '0'; else ras <= 'Z'; -- oder so? end if; Kest
Auch nicht: Signal ras cannot be synthesized, bad synchronous description.
Womit synthetisierst Du? Vielleicht doch 'event umschreiben? So wie: if ale_old='1' and ale='0' then ale_old='0'; ras <='1'; und so weiter? Sonst weis ich auch nicht. Eigentlich sollte daraus etwas Kombinatorik entstehen, aber damit kommt doch heutzutage jede Software klar, oder etwa doch nicht? :-o Kest
Ich verwende Xilinx ISE 6.3i und versuche das ganze in einen XC9536 zu packen.
Okay, etwas wird mir klar, Benedikt. Ist zwar nur eine Vermutung, aber ich denke, ich bin da schon ziemlich nahe an der Lösung: und zwar guck Dir die Struktur der Macrozellen an. Meistens haben sie nur einen CLOCK Eingang. Man kann also nur ein Mal 'event nehmen... keine Ahnung, ob ich mich jetzt verständlich ausdrücke. Versuch' mal ohne Else, sondern einfach mit if's zu schreiben if ale='0' and ale'event then ras <= '1'; end if; if En='1' and En'event then ras <= '0'; end if; vielleicht klappt es so? Kest
Nein, so geht es auch nicht. Alle Ideen die ich hatte, verstoßen gegen irgendeine VHDL Regel. - 2 Events in einer if Schelife funktionieren nicht, da die Latches nur 1 Clock Eingang haben. - 2 getrennte ifs gehen nicht, da man nicht einem Signal an zwei getrennten Stellen einen Wert zuweisen kann. Die Software weiß nämlich nicht, ob nicht beide ifs gleichzeitig wahr sein können. - Das mit dem Hilfssignal läuft auf eine der beiden zuvor genannten Verstöße zu, denn ale_old muss irgendwie auch wieder auf 1 gesetzt werden. Wenn ich solch eine Schaltung per Hand aufbauen würde, würde ich ein RS-FF nehmen, und die beiden Signale differenzieren, um kurze Peaks zu erzeugen mit denen das FF gesetzt bzw. zurückgesetzt wird. Aber leider geht das hier nicht so einfach, und ein digitales Monoflop das mit Hilfe einem Takt einen Peak erzeugt wäre etwas aufwenig...
In einem Prozess darf nur 1 Clock signal mit 'Event abgefragt werden.Alles andere führt zu obiger Fehlermeldung.
1 | process(B) |
2 | begin
|
3 | if B'event and B ='0' then |
4 | B_intern <= '1' |
5 | end if; |
6 | end process; |
7 | |
8 | process(A, B_intern) |
9 | begin
|
10 | if B_intern = '1' then |
11 | ras <= '0'; |
12 | elsif A'event and A = '1' then |
13 | ras <= '1'; |
14 | end if; |
15 | end process; |
probier es mal so
@Benedikt FFs die auf 2 Taktflanken arbeiten, gibts nur im CoolRunner II. Versuch doch mal stattdessen die Funktion so zu beschreiben, dass Du mit 1 Flanke und einem asynchronen Set- oder Reset-Signal auskommst - geht das ? Ansonsten wird nichts übrigbleiben, als die Signale einzutakten und die übliche Flankenerkennung mit 2 FFs zu machen.
Man kann das nicht synthetisieren, weil man sich für die steigende oder fallende Flanke entscheiden muß! Ein (einzelnes) FF das auf beide Flanken reagiert gibt es auch nicht zu kaufen. Da musst man sich schon eine etwas komplexere Logik einfallen lassen. Im Anhang findest du die Schematik eines Vorschlags von mir. Aber ACHTUNG: Diese Schaltung könnte sehr STÖRANFÄLLIG sein, da sie gezielt Laufzeiten von Gattern ausnutzt! Ich empfehle dir Einschränkungen bei deinen Anforderungen zu machen und etwas "stabileres" zu programmieren! Ich würde die Schltung NICHT einsetzen. [VHDL] entity SFF is Port ( A : in std_logic; B : in std_logic; Q : out std_logic ); end SFF; architecture Behavioral of SFF is Signal va :std_logic; Signal vb :std_logic; Signal res_vab :std_logic; begin Main: Process (A,B, va, vb, res_vab) begin if (res_vab='0') then if (A='0' and A'event) then va<='1' ; end if; else va<='0'; end if; if (res_vab='0') then if (B='1' and B'event) then vb<='1'; end if; else vb<='0'; end if; res_vab<=vb; Q<=va; end Process Main; end Behavioral; [\VHDL] Gruss Henrik
Mein Quelltext oben ist natürlich Quark. B_intern wird ja nie mehr zurückgesetzt. Zu so später Stunde sollte ich wohl mein Gehirn nicht mehr quälen ;-) Aber ich schliesse mich dem Vorschlag vom FPGA-User an, dein Design so umzustellen, dass ein normales D-FF mit asynchr. Reset eingesetzt werden kann. Lässt sich am besten handeln. Grüße T.M.
Ich hätte dann doch ne Frage: Ich dachte immer, in einem Prozess ist nur 1 clocksignal erlaubt? Hendriks Code lässt sich aber einwandfrei synthetisieren mit ISE... Hab ich da nen Verständnisproblem? Grüße T.M.
>Ich dachte immer, in einem Prozess ist nur 1 clocksignal erlaubt?
Erlaubt sind meherere, man sollte aber nur eines verwenden, da es
offiziell nicht funktionieren muss, es kann aber.
Icb bechreibe mal für was ich das ganze brauche, vielleicht fällt jemandem eine Lösung ein: Das ganze ist ein DRAM Controller für einen AVR: ALE dient als RAS Signal, aber leider bleibt dieses bis zum nächsten Lesevorgang auf Low (was aber nicht sein darf, wegen dem precharge Timing). Jedenfalls möchte ich den Cyclus mit der Low High Flanke von RD\ oder WR\ (bei mir schon als Enable zusammengefasst) wieder beenden. Ich hab es auch nochmal als Bild angehängt: Das schwarze habe ich, das rote suche ich.
@Benedikt warum nimmst Du nicht eine Statemachine, in der alle benötigten Signale synchron vom Takt abgeleitet werden ? Bei den asynchronen Tricksereien handelst Du Dir Ärger ein, wenn nicht alles 100 Pro durchdacht ist (Timing bei versch. Temp. ...)
@FPGA-User Wenn ich alles synchron mache, geht mir Wertvolle Zeit verloren. Das Timing ist schon kritisch genug. Daher würde ich den Takt gerne auf das ALE Signal beziehen, denn das gibt die Startbedingung vor und sollte so schnell wie möglich verarbeitet werden. Da ALE aus dem Takt abgeleitet wird, ist es leicht verzögert. Wenn ich das jetzt wiederum mit dem takt synchronisiere habe ich zumindest eine halbe Taktperiode veroren, (wodurch mir dann 25ns fehlen würden).
@T.M. : Das in einem Prozess nur ein clock-Signal erleubt ist, kenne ich nur indem Zusammenhang, dass es bei der Simulation Probleme geben kann, nicht aber bei der Hardware. Vielleicht ist das für eine Simulation besser geeignet:
1 | entity SFF is |
2 | Port ( A : in std_logic; |
3 | B : in std_logic; |
4 | Q : out std_logic |
5 | );
|
6 | end SFF; |
7 | |
8 | architecture Behavioral of SFF is |
9 | begin
|
10 | |
11 | Main: Process (A,B) |
12 | variable res_vab : std_logic; |
13 | variable va : std_logic; |
14 | variable vb : std_logic; |
15 | begin
|
16 | |
17 | if (res_vab='0') then |
18 | if (A='0' and A'event) then |
19 | va:='1' ; |
20 | end if; |
21 | else
|
22 | va:='0'; |
23 | end if; |
24 | |
25 | if (res_vab='0') then |
26 | if (B='1' and B'event) then |
27 | vb:='1'; |
28 | end if; |
29 | else
|
30 | vb:='0'; |
31 | end if; |
32 | |
33 | res_vab:=vb; |
34 | |
35 | Q<=va; |
36 | |
37 | end Process Main; |
38 | |
39 | |
40 | end Behavioral; |
(wird auf das Gleiche synthetisiert wie oben) Wie schon gesagt: Weil die Funktion durch die Laufzeiten von Gattern funktioniert, würde ich diesen Code NICHT verwenden. Gruss Henrik
@Henrik würde ich auch nicht einsetzen, res_vab ist ein Spike, bei dem nicht sicher ist ob er ausreicht, um va wirklich rückzusetzen. Folgende Idee : Das Reset-Signal für vb wird nicht aus dem eigenen Ausgang Q sondern von va abgeleitet ! d.h.: - der Ausgang von vb geht auf den Clear-Eingang von va - der Ausgang von va geht auf den Clear-Eingang von vb (jetzt aber Lo-Aktiv) Ziel ist, dass vb selbst erst asynchron zurückgesetzt wird, wenn va ebenfalls zurückgesetzt wurde .
Ich habe jetzt noch etwas rumprobiert, und kam zu diesem Code, der zumindest in der Simulation das macht, was ich möchte: if ale='1' then state<='0'; elsif iclk='1' and iclk'event then state <= '1'; end if; if (state='1') then transfer <= '1'; elsif ale='0' and ale'event then transfer <= '0'; end if; Dabei sind iclk und ale die Eingangssignale und transfer der Ausgang.
In der Praxis funktioniert es auch, aber leider hat das Ausgangssignal etwa 20ns Verzögerung gegenüber einem anderen (das ebenfalls mit ale geschaltet wird). Kann man irgendwie im CPLD diese 20ns verschwenden ?
Ich würde es so probieren: if iclk='0' and iclk'event then ras_a <= NOT ale; end if; if iclk='1' and iclk'event then ras_b <= ras_a; end if; ras <= ras_a AND ras_b; Kann sein, daß ich die VHDL-Syntax nicht richtig getroffen habe weil ich meistens in AHDL arbeite. Spikes dürften nicht auftreten, denn L in ras_a und ras_b überlappen immerhin einen halben Takt.
oder besser so: Ich würde es so probieren: if iclk='1' and iclk'event then ras_a <= NOT ale; ras_b <= ras_a AND NOT ale; end if; ras <= ale AND ras_b;
if iclk='1' and iclk'event then ras_a <= NOT ale; ras_b <= ras_a AND NOT ale; end if; ras <= ale OR ras_b; ^^ Noch ein Fehler: hier muß OR statt AND stehen!
Ich versuche gerade irgendwie 10-20ns an Verzögerung in das 11bit breite Adressensignal zu bekommen. Dem FAQ von Xilinx nach geht das, aber bei mir irgendwie nicht... http://www.xilinx.com/xlnx/xil_ans_display.jsp?iLanguageID=1&getPagePath=7595&BV_SessionID=@@@@0135735048.1125336611@@@@&BV_EngineID=ccchaddfidjdffgcefeceihdffhdfjf.0 Hier mein Code: attribute KEEP : string; attribute KEEP of adress0, adress1, adress2 : signal is "TRUE"; --keep buffer from being optimized out process (adress0) begin --Adress Mux Delay adress1 <=adress0; adress2 <=adress1; adress <=adress2; end process; Was mache ich falsch ? Was hat das :string bei dem ersten attribute zu bedeuten ?
@Benedikt schreib erstmal alle Signale in die Sensitivity-List Deines Prozesses: process(adress0, adress1, adress2) oder vergiss besser die asynchrone Variante, erst war die synchrone 20 ns zu langsam, jetzt willst Du wieder 20 ns Verzögerung reinbringen. Glaub mir, das sind genau die Designs, die irgendwann funktionieren, und wenn mal die Temperatur steigt oder ein SDRAM andere Parameter hat dann gibts bei 3 von hundert Zugriffen Bitfehler - wie willst Du das in den Griff bekommen ?
Wenn ich ein SDRAM ansteuern würde, wäre das ganze einfach, aber leider steure ich ein normales DRAM an, und das ist leider asynchron... Wenn ich es schaffe, alle Adressignale um mindestens 10ns zu verzögern, dann liege ich mit dem Timing laut Datenblatt im grünen Bereich. Abgesehen vom Beginn des RAS Signals (und der entsprechenden Adressen) ist der Rest eigentlich unkritisch. Mittlerweile habe ich es irgendwie geschafft die Buffer einzubauen. Seltsamerweise hat ein Signal (Adress6) eine andere Verzögerung als der Rest, obwohl es bei der Belegung (Makrozelle usw.) keine Besonderheiten hat. Ohne Buffer hat jedes Signal 25ns. Destination Pad ale Clock (edge) to Pad adress<0> 42.000 adress<10> 42.000 adress<1> 42.000 adress<2> 42.000 adress<3> 42.000 adress<4> 42.000 adress<5> 42.000 adress<7> 42.000 adress<8> 42.000 adress<9> 42.000 adress<6> 34.500 ras 25.000 Für jedes Signal habe ich einen Buffer eingebaut: my_buf : buf port map ( i => adress0(0), o => adress(0));
Mit einem Design, das auf Laufzeiten aufbaut, wirst du unweigerlich scheitern. Erhöhe deinen Grundtakt und leite davon deine nötigen Takte ab. MfG Holger
Ich muss jediglich ein Signal etwas verzögern, um die CPLD Laufzeiten zu kompensieren und die erforderlichen 10ns Hold Zeit erreichen. Der Rest vom Timing ist fest vorgegeben. Mit einer Handvoll TTL ICs (Adressmultiplexer, Refreshzähler usw.) und einer Delayline wurde sowas früher oft aufgebaut.
@Benedikt Nix für ungut, aber Holger hat recht, das Ding geht in die Hose wenn Du Dich auf irgendwelche Delays verlässt. Ich habe schone einige Memory-Interfaces gemacht, u.a. für NAND- Flash, asyncrone RAMs, DDR-RAM, MMC/SD-Cards usw., aber immer die Adressen, Daten und Strobes synchron von einem Takt abgeleitet, das hat sich super bewährt. Du kannst das Timing genau nachvollziehen und der Timing-Analyzer in der FPGA-Software liefert die richtigen Werte. Außerdem ist dann garantiert, dass die Geschichte im ges. Temp-Bereich und Betriebsspannungsbereich funktioniert.
OK, ich habe jetzt einen größeren CPLD genommen, bin daher mit den Pins etwas flexibler (beim kleinen hatte ich keine freien Pins mehr, weshalb ein externer Takt unmöglich war). Damit versuche icht jetzt noch ein letzes mal die asynchrone Version, wenn das nix wird stelle ich auf synchron um.
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.