Hallo zusammen, da ich glaubte VHDL etwas mehr verstanden zu habe, hatte ich mir gedacht das ich mal einen Verilog Code versuche in VHDL umzusetzen. Gleichzeitig wollte ich dort die benutzen Latches in ein synchrones Design umstellen, weil jeder erzählt das Latches "böse" sind. Leider bekomme ich folgende Fehlermeldung von ISE WebPack 11.3: >Cpld:892 - Cannot place signal im_reg_l<6>. Consider reducing the collapsing >input limit or the product term limit to prevent the fitter from creating high >input and/or high product term functions. Benutzt wird ein XC95144XL-10-TQ144 Das CPLD ist aus dem OpenSource Projekt Ethernut, Infos zum CPLD gibt es hier: http://www.ethernut.de/en/hardware/enut3/memory.html Ich dachte, sind ja nur einige Register, das kann ja nicht so schwer sein. Im Moment habe ich Probleme mit den Interrupt Registern. Für die Erkennung einer Flanke habe ich den Source von Lothar Miller genommen. (Danke für die Hilfe bei meinen ersten Gehversuchen mit VHDL). Hier soll ein Interrupt (Flanke low => high, oder high => low) erkannt werden, und die Info im Latch Register gespeichert. Mit dem Clear Register kann dann diese Information wieder gelöscht werden. Später wird das Latch Register mit dem Mask Register verundet und hierdurch der Interrupt ausgelöst. Dies ist auch ein etwas längeres Konstrukt, ab Zeile 430: P9 <= '0' when ( ((sl_reg_l(0) = '1') and (im_reg_l(0) ='1')) or usw. usw.... Geht das noch einfacher? OK, genug geschrieben, anbei nun der neue VHDL Source und die originalen Verilog Quellen. Da man besonders gut aus Fehlern lernen kann, bin ich mal gespannt auf Eure Anregungen wie man das Problem lösen, bzw. besser machen kann. Viele Grüße, Michael
Ohne direkt das eigentliche Problem aufzugreifen: > -- Shift register for the edge detection > signal ccts_sr : std_logic_vector(3 downto 0); > : > : Du hast in einem CPLD wesentlich weniger FFs... Auf jeden Fall reichen garantiert auch 3. Dann ist jede Metastabilität weg. Ich würde die Flankenerkennung nur 2 FFs lang machen. Das sollte auch gehen. In einem FPGA habe ich mit der Länge der Schieberegisterkette kein Problem, die wird in diesem Fall sowieso in eine LUT abgebildet. Auf einem CPLD sind FFs extrem wertvoll. Insgesamt zähle ich in dem Design schon fast 130 Speicherglieder, und das bei nur 144 Makrozellen/FFs. Das muss knapp werden... :-/
Hallo Lothar, >Ich würde die Flankenerkennung nur 2 FFs lang machen Das habe ich jetzt umgesetzt und konnte etwas weiter arbeiten. Nun bin ich am MMC Teile, d.h. es wird hier versucht eine SPI Schnittstelle nachzubilden. Und schon platzt das CPLD wieder aus allen Nähten: >Cpld:886 - Function block FB8 was too congested to route successfully. >This occurs due to excessive (>= 50) product term input fanins to this >function block. Consider moving output signals in this function block to >less congested function blocks, buffering output signals that must remain >in this function block, or selecting a larger package. Von den FFs sieht es noch gut aus: Macrocells Used: 129/144 Pterms Used: 460/720 Registers Used: 95/144 Pins Used: 83/117 Function Block Inputs Used: 309/432 Der Source ist wieder im Anhang, hast Du noch eine Idee wie man den MMC Teil platzsparender umsetzen könnte? So gut sieht das auch noch nicht aus weil hier kein Clock Pin benutzt wird, sondern der Clock wird selber erzeugt. Ich weis nicht ob ich hier noch Platz für eine StateMachine habe. Viele Grüße, Michael
>weil jeder erzählt das Latches "böse" sind.
Latches an sich sind ganz feine Bauteile, die, richtig verwendet, einem
viele spezielle Schaltungsrealisierungen ermöglichen.
Das Problem ist meist, das in einem geplanten vollsynchronen Design
Latches auf Schwächen in diesem Hinweisen. Meist bedingt durch nicht
vollständig beschriebene kombinatorische Logik. Daher kommt wohl die
Latchparanoia.
Aber wenn man wirklich ein Latch verwenden will ist wirklich nix
schlimmes dran. Man muß nur wissen was man tut.
Der Besucher
Was passiert eigentlich, wenn du das Original-Verilog-Design mit ISE WebPack 11.3 synthetisierst ? Passt das Design denn dann in den von dir genannten Baustein ? SuperWilly
Hallo "SuperWilly", das Original-Verilog-Design kann mit ISE 11.3 übersetzt werden. Aber es sieht so aus als wenn hier ein Signal weg optimiert wird was eigentlich auch gebraucht wird. Gruß, Michael
Hallo zusammen, ich habe jetzt noch mal einen Tip bekommen, und dadurch konnte dann das Problem behoben werden. Folgender Source: ccts_falling_test : process (CPLD_CLK, reset0_irq, sl_reg_l, ccts_sr, CCTS) begin -- Check for reset if (reset0_irq(0) = '0') then sl_reg_l(0) <= '0'; ccts_sr <= "11"; else -- edge detection sl_reg_l(0) <= not ccts_sr(0) and ccts_sr(1); -- read the input into the shift register if CPLD_CLK = '1' and CPLD_CLK'event then -- but only if no edge was detected before if (sl_reg_l(0) = '0') then ccts_sr <= ccts_sr(0) & CCTS; end if; end if; end if; end process ccts_falling_test; wurde geändert in: ccts_falling_test : process (CPLD_CLK, reset0_irq) begin -- Check for reset if (reset0_irq(0) = '0') then sl_reg_l(0) <= '0'; ccts_sr <= "11"; elsif CPLD_CLK = '1' and CPLD_CLK'event then -- read the input into the shift register -- but only if no edge was detected before if (sl_reg_l(0) = '0') then -- edge detection sl_reg_l(0) <= not ccts_sr(0) and ccts_sr(1); ccts_sr <= ccts_sr(0) & CCTS; end if; end if; end process ccts_falling_test; Warum das jetzt kleiner geworden ist kann ich nicht sagen. Als nächstes geht es nun an die Simulation... Viele Grüße, Michael
Hallo, wäre es nicht noch einfacher, die Flankenerkennung ohne if-Abfrage zu beschreiben ?
1 | ccts_falling_test : process (CPLD_CLK, reset0_irq) |
2 | begin
|
3 | -- Check for reset
|
4 | if (reset0_irq(0) = '0') then |
5 | sl_reg_l(0) <= '0'; |
6 | ccts_sr <= "11"; |
7 | elsif rising_edge(CPLD_CLK) then |
8 | |
9 | -- edge detection
|
10 | sl_reg_l(0) <= not ccts_sr(0) and ccts_sr(1); |
11 | |
12 | -- read the input into the shift register
|
13 | -- but only if no edge was detected before
|
14 | if (sl_reg_l(0) = '0') then |
15 | ccts_sr <= ccts_sr(0) & CCTS; |
16 | end if; |
17 | end if; |
18 | end process ccts_falling_test; |
Gruß, SuperWilly
Hallo SuperWilly, ich habe jetzt ein Latch benutzt: ccts_falling_test : process (CCTS, reset0_irq) begin -- Check for reset if (reset0_irq(0) = '0') then sl_reg_l(0) <= '0'; elsif CCTS = '0' and CCTS'event then -- but only if no edge was detected before if (sl_reg_l(0) = '0') then sl_reg_l(0) <= '1'; end if; end if; end process ccts_falling_test; Gruß, Michael
Das ist kein Latch ;-) sl_reg_l ist ein lokales FF, das synchron zurückgesetzt wird. So ähnlich wie mein Impulsmerker: http://www.lothar-miller.de/s9y/archives/19-Kurzer-Spike-in-Puls-umgewandelt.html BTW: Das solltest du dir nochmal genauer überlegen:
1 | -- but only if no edge was detected before
|
2 | if (sl_reg_l(0) = '0') then |
3 | sl_reg_l(0) <= '1'; |
4 | end if; |
Meiner Meinung nach kannst du das funktionsgleich ersetzen durch:
1 | -- but only if no edge was detected before
|
2 | sl_reg_l(0) <= '1'; |
Am Rande: Du hast es jetzt mit 2 Taktdomänen zu tun. Wundere dich nicht, wenn sich das Design ab und zu (ich meine damit Stunden oder Tage) eigenartig verhält. Z.B. synchronisierst du sl_reg_l(0) nicht auf CPLD_CLK ein...
Hallo Lothar, >Am Rande: >Du hast es jetzt mit 2 Taktdomänen zu tun. Wundere dich nicht, wenn sich >das Design ab und zu (ich meine damit Stunden oder Tage) eigenartig >verhält. Z.B. synchronisierst du sl_reg_l(0) nicht auf CPLD_CLK ein... Danke für den Hinweis, gr%#&... Ich hatte es erst mit dem CPLD_CLK und den zwei FF, danach war aber kein Platz mehr für das MMC Interface (Nachbildung SPI) vorhanden. Außerdem gab es ein Problem bei der ersten Lösung das wenn man ein Signal auf steigende und fallende Flanke hin überwachen möchte. Wenn die Ruhelage High war, wurde mir gleich eine steigende Flanke gemeldet, war die Ruhelage Low, eine fallende Flanke. Das IF-Statement kann raus, denn wenn sl_reg_l schon 1 ist, ist es nicht schlimm wenn es weiterhin auf 1 gesetzt wird. Dann werde ich mir noch mal den Spikedetector anschauen. FFs habe ich noch genug über. Das Problem waren irgendwelche internen Verbindungen. Viele Grüße, Michael
Hallo Lothar, was hältst Du nun von folgender Version? -- Merker-FF process (reset0_irq, CCTS) begin if (reset0_irq(0) = '0') then merkin <= '0'; elsif CCTS = '0' and CCTS'event then merkin <= '1'; end if; end process; -- Asynchrones Merker-FF eintakten process (reset0_irq, CPLD_CLK) begin if (reset0_irq(0) = '0') then sr0 <= '0'; sr1 <= '0'; elsif CPLD_CLK= '1' and CPLD_CLK'event then sr0 <= merkin; sr1 <= sr0; end if; end process; sl_reg_l(0) <= sr1; Gruß, Michael
Hallo zusammen, mir fehlt gerade eine Macrocell: ERROR:Cpld:837 - Insufficient number of macrocells. The design needs at least 145 but only 144 left after allocating other resources. Device 95144XL144TQ was disqualified. ERROR:Cpld:868 - Cannot fit the design into any of the specified devices with the selected implementation options. Ich habe schon mit den Werten für Imput Limit und Pterm Limit gespielt, und das beste Ergebnis bekomme ich bei folgende Werten: Input Limit 21 Pterm Limit 20 Hat noch jemand eine Idee wo ich im Source was sparen kann? Viele Grüße, Michael
Hallo zusammen, habe nun noch einige Macrocells gefunden. Das Schieberegister im MMC Teil für die Ausgabe wurde nun durch einen Multiplexer ersetzt. Ich hoffe mal das es ein Multiplexer ist :o) Die Post-Fit Simulation geht immer noch. case mmc_creg is when "0000" => mmc_doreg <= mmc_mosi_reg(7); when "0001" => mmc_doreg <= mmc_mosi_reg(6); when "0010" => mmc_doreg <= mmc_mosi_reg(5); when "0011" => mmc_doreg <= mmc_mosi_reg(4); when "0100" => mmc_doreg <= mmc_mosi_reg(3); when "0101" => mmc_doreg <= mmc_mosi_reg(2); when "0110" => mmc_doreg <= mmc_mosi_reg(1); when others => mmc_doreg <= mmc_mosi_reg(0); end case; Gruß, Michael
> Das Schieberegister im MMC Teil für die Ausgabe wurde nun durch einen > Multiplexer ersetzt. Das ist eine gute Lösung für CPLDs. Die haben mit ihren Makrozellen mächtige Kombinatorik, sind also ideal für Multiplexer.
Guten Morgen Lothar, Du hattest etwas weiter oben folgendes geschrieben: >Am Rande: >Du hast es jetzt mit 2 Taktdomänen zu tun. Wie erkennt dies eigentlich ein Anfänger, gibt es hier irgendwelche Tips? Wo ist denn dort der Unterschied zu einem einfachen CPU Interface? Beim CPU Interface benutzt man doch auch die steigende Flanke von nWE um die Daten zu übernehmen. Wenn ich von einem CPU Interface mit folgenden Signalen ausgehe, A, D, nWE, nCS: if (nWE = '1') and (nWE 'event) then if (A = X) and (nCS = '0') then daten <= D; end if; end if; Hier schiebt man die Daten "daten" doch auch nicht über eine zweite FF-Stufe. Der einzige Unterschied den ich hier sehe ist das nWE auf einen Clock Eingang liegen sollte. Und nun zurück zu meiner ersten Flankenerkennung für das Signal X und den Ausgang Q. Nehmen wir an es soll eine steigende Flanke erkannt werden: if (nRESET = '0') then Q <= '0'; elsif (X = '1') and (X 'event) then Q <= '1'; end if; Wo mache ich den Denkfehler? Viele Grüße, Michael
> Wie erkennt dies eigentlich ein Anfänger... Genauso wie es auch ein Profi erkennt ;-) Unterschiedliche Takte im Design sind ein Indiz. Externe Signale sind generell verdächtig. Diese externen Signale können zu sich selber durchaus synchron sein (Speicherinterface mit nWE, SPI mit SCLK...), zum CPLD/FPGA-Takt sind sie idR. asynchron. > Wenn ich von einem CPU Interface mit folgenden Signalen ausgehe... Dann ist die erste Aufgabe, die Daten zu übernehmen. Das kann durchaus mit einem lokalen Takt (nWE) geschehen. Aber für die Weiterverarbeitung muß dann das Validierungssignal nWE einsynchronisiert werden, damit sichergestellt ist, dass die Daten bei der Verwendung stabil und gültig sind. Es muß also nicht jedes Signal einsynchronisiert werden, sondern "nur" das signal, das die Gültigkeit der Daten anzeigt. Beim SPI z.B. sind die unkritischsten Signale MOSI und MISO. Augenmerk muß auf SCLK und auch SS gelegt werden. > Und nun zurück zu meiner ersten Flankenerkennung ... Das ist hier so beschrieben, die Flanke wird erkannt und gespeichert. Das Problem liegt nicht in diesem Stück Code, sondern im Übergang zur weiteren Verarbeitung. Die erkannte Flanke wird zu beliebiger Zeit in Q gespeichert. Wenn jetzt irgendwas dieses Q verwendet und dabei einen anderen Takt hat, dann hast du wieder Probleme, die tsu und th der nachfolgenden FF einzuhalten.
Hallo Lothar, ich versuche das noch mal von einer anderen Sichtweise zu betrachten und mit einem C-Beispiel zu vergleichen. Nehmen wir eine 8-Bit CPU die auf ein 32 Bit Wert lesend zugreift der im Interrupt verändert werden kann. Hier kann es passieren das der Lesezugriff der CPU durch den Interrupt unterbrochen wird (die CPU benötigt 4 Zugriffe und kann den Wert nicht auf einmal lesen), dieser den Wert verändert, und die CPU dann nur noch Unsinn ausliest. Am einfachsten kann man nun das Problem lösen indem man beim Zugriff auf die Variable außerhalb des Interrupts die Interrupts selber sperrt und nach dem Zugriff wieder freigibt. Somit ist sichergestellt das die Variable nicht verändert werden kann wenn man außerhalb des Interrupts lesend darauf zugreift. Zurück zur Hardware. Hier kann man ja nicht die Interrupts sperren, also muß man sicherstellen das sich der Wert nicht ändert, oder stabil anliegt, wenn man einen Zugriff macht. Dies kann nur dadurch erreicht werden das man das Signal durch zwei FF schiebt. sr0 <= In sr1 <= sr0 Und dann die "Variable" sr1 benutzt. Hier ändert sich sr1 nicht wenn schon eine Änderung an In auftritt. Gruß, Michael
Das Problem unsynchronisierter Eingänge bei Hardware ist eher folgendes: Wenn ein Eingang mehrfach in einer Statemachine zum Weiterschalten von zuständen verwendet wird, dann kann es ohne Einsynchronisierung zu fehlerhaftem Verhalten dieser SM kommen, weil aufgrund unterschiedlicher Laufzeiten zu den FFs ein unterschiedlicher Pegel des Eingangs erkannt wird. Es wird dann z.B. nicht der Folgezustand angesprungen, sondern ein x-beliebiger. Allein das Eintakten auf ein Speicherregister ist relativ ungefährlich. Metastabile Zustände treten signifikant erst bei Frequenzen um 300MHz auf (ich lasse hier gerade einen Versuch laufen). Die heutigen FFs in FPGAs (und vermutlich auch CPLDs) sind so schnell, dass bei "handelsüblichen" Frequenzen Metastabilität keine Rolle spielt.
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.