Hi @ all Ich möchte mein Programm auf Speed optimieren. Bis jetzt läuft die Schaltung mit ca. 86MHz. Da es eine recht kleine logische SChaltung ist, möchte ich gern 120 bis 150 MHz erreichen. Als FPGA benutze ich eine Xilinx VirtexE 300. Noch ein paar Hinweise zum Verstehen des Quellcodes: Es wird ein AD-Wandler angesteuert. Die Daten, die der AD-Wandler erzeugt, werden über den Input "DATA_ADC" an den FPGA seriell übertragen und im Signal "S_SPEICHER_A" gespeichert. Da der AD-Wandler 4 führende Nullen erzeugt, die mich nicht interessieren, fange ich erst mit dem Schieben des Registers "S_SPEICHER_A" an, wenn das Signal "S_SHIFT_SPEICHER_A" 1 ist. Damit die Logik bei der Synthese nicht wegoptimiert wird, lege ich eine belibiege Speicherzelle des Registers "S_Speicher_A" an den Ausgang "OUTPUT". Das gesamte Timing habe ich über das Ringregister "S_REG_A" erzeugt. In diesem Ringregister befindet sich eine "1" sonst nur Nullen. Die "1" benutze ich als Enable-Leitung für viele meiner Prozesse. Somit kann ich das Timing für die CS-Leitung des AD-Wandlers erzeugen und Strukturen erzeugen die nacheinander abgearbeitet werden. (ich denke mal dies ist eine gute Lösung, da ich nicht ständig eine Zähler abfragen muss) Das CLR und GATE-Signal wird über ein anderes Modul erzeugt (siehe Schaltplan im Anhang) Bis jetzt habe ich noch keine Constraint-Optimierung vorgenommen, da ich mich damit noch nicht so auskenne. Ich bin für jeden Verbesserungsvorschlag dankbar. MfG Michael
Zumindest passt der schaltplan zum source :-) aber die 2 FF sollten doch möglich sein oder ? :-))))
Hallo Michael, ich habe gesehen, dass du in deinem Design manche FF mit der steigenden und andere FF mit der fallenden Flanke von clk betreibst. Probier mal alle FF in deiner Schaltung nur mit der steigenden Flanke zu betreiben. Ich hab den AD_Converter für einen Spartan2 durch die ISE gejagt. Deine Version: 113 Mhz Alle FF mit steigender Flanke : 216 Mhz, allerdings ohne Gewähr, dass die Schaltung noch richtig funktionert. Gruß Jörn
Ich gebe Jörn recht, immer Clock auf einer der beiden Flanken abfragen. In den meisten Fällen in denen ich Clock's auf beiden Flanken abfragte halbierte sich die max. Taktfrequenz des kompletten Designs. Du fragts Clock auf beiden Flanken ab um das Design synchron zu halten. Habe ich auch immer so gehalten bis mir ein Licht aufging das dies absolut unnötig mit einem guten synchronen Design ist. Du mußt nur immer schön "parallel" denken ;) Die asynchronen Reset/Clear Signale sollten ebenfalls immer nur auf ein und den selben Pegel abgefragt werden. Sprich Low-Active-Reset immer auf '0' abfragen. Diese "Faustformel" ist aber nicht so strikt wie die der Clocks da ein NOT Gatter ja nicht die Welt untergehen lässt, aber denoch immer ein Delay haben wird ;) Gruß Hagen
hmmmm grübel, also der anhang beinhaltet bei mir lediglich den source synchroner_clr.vhd und sonst nichts.... kein schaltplan etc...
Erst einmal Danke für Eure Mühe. Das mit der Clock-Flanke habe ich auch schon überlegt. Ich wollte nur immer auf Sicherheit arbeiten, damit es auch wirklich funktioniert. Wenn ich das Ringregister mit der ansteigenden Clock-Flanke schiebe und gleichzeitig mit der ansteigenden Clock-Flanke den Zustand der '1' abfrage, dann habe ich das immer für sehr unsicher gehalten. Deshalb benutze ich zwei unterschiedliche Flanken. Kann es dabei zu Fehlern kommen? Grüsse Michael
Moin... ohauerha.... warum machst du dir übernahupo die Mühe sensitivity Listen zu schreiben? Dein Design ist ja zu 100% asynchron. Die Software kann da nichts optimieren und vermutlich auch keinerlei Ausagen übe die Geschwindigkeit machen. Alles Zeiten müssen gegen drei mögliche "Takte" gesprüft werden und raus kommt der Worst-Case. Baue das Ding mal komplett in ein synchrones Design um, das wird automatisch schneller, wenn der Chip das kann. -- Sven Johannes
HAHAHA selten so gelacht. Bevor man so einen Komentar schreibt sollte man besser erst mal den Quellcode lesen. Ich benutze nur CLK-Flanken um Ereignisse auszulösungen und das ist in meinen Augen ein synchrones Design oder habe ich da was falsch verstanden? Der Reset wird auch synchron ausgeführt (siehe Datei synchroner CLR) Wenn Du meinst das es immer noch ein asynchrones Design, dann kannste ja mal einen Vorschlag für ein synchrones Design machen. Grüsse Michael
Moin... Bitte leiser lachen. Deine sens Listen beinhalten nicht nur CLK => die Software MUSS also die anderen Signale berücksichtigen => wie hats du die Constraints gesetzt? process (CLR,CLK,GATE) begin if (CLR = '1' or GATE = '0') then CS_ADC <= '1'; elsif (CLK'event and CLK = '1') then CS_ADC <= S_REGA(0); end if; end process; Das ist der Reset in deinem Steurteil. Der ist nun 100%ig async. Warum dröselst du DAVOR noch eine Instanz die das sysnchronisieren soll? Oder interpretiere ich das jetzt nicht im Sinne des Erfinders? Die Synthese Software weiß davon nichts und muss hier vom "worst-Case" ausgehen. Ich bin sicher das da einiges an Geschwindigkeit liegenbleibt. Nebenbei: rising_edge(clk) ist eigentlich die Abfrage für die steigende Flanke es Taktes wenn std_logic verarbeitet wird. Das Ding mit event und =1 ist zwar verbreitet und funktioniert zu 99%, aber da schreibt Einer vom Anderen ab. -- Sven Johannes
@Sven: >Nebenbei: rising_edge(clk) ist eigentlich die Abfrage für die > steigende Flanke es Taktes wenn std_logic verarbeitet wird. > Das Ding mit event und =1 ist zwar verbreitet und funktioniert > zu 99%, aber da schreibt Einer vom Anderen ab. Kannst du dies bitte genauer ausführen ? Nach meinen Informationen sollte man rising_edge() eben nicht benutzen da das nur für die Simulation taugen soll und eben nicht für die Synthese. Das liegt daran das einige Bibliotheken innerhalb von rising_edge() zusätzlich noch Clock'Last_Event abfragen und das ist nicht synthetisierbar. Bitte um Aufklärung. Gruß Hagen
rising_edge(clk) / falling_edge(clk) funktioniert bei mir immer für die Synthese, m.E. ist das VHDL-93, clk'EVENT und clk='1' ist VHDL-87 - oder liege ich da falsch?
es gibt aber Implementierungen die so lauten clk'EVENT und clk='1' and clk'LAST_VALUE = '0' siehe in PACKAGE std_logic_1164 FUNCTION rising_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN IS BEGIN RETURN (s'EVENT AND (To_X01(s) = '1') AND (To_X01(s'LAST_VALUE) = '0')); END; und irgendwo habe ich gelesen das s'LAST_VALUE nicht synthetisierbar sein soll. Ich frage ja gerade deshalb weil sich anscheinend die Meinungen unterscheiden ? Gruß Hagen
Moin... Hatte auch noch nie Probleme, die Definition von VHDL87 kenne ich allerdings nicht genau. Die Abfrage von clk_event und =1 produziert immer dann Murks wenn der Wechsel zum Beispiel von X,U oder Z nach 1 erfolgt. Ok, bei Takten ist das seltener aber viele Leute fragen ja auch Signale ab. -- Sven Johannes
Hallo Warum soll LAST_VALUE nicht synthesefähig sein? Hier mal 3Versionen, die alle mit Quartus II synthetisiert worden sind.
1 | library ieee; |
2 | use ieee.std_logic_1164.all; |
3 | use ieee.std_logic_unsigned.all; |
4 | |
5 | entity Test_Con is |
6 | port( CLK1, CLK2, CLK3 : in std_logic; |
7 | RES1, RES2, RES3 : in std_logic; |
8 | Q1: out std_logic_vector (15 downto 0); |
9 | Q2: out std_logic_vector (15 downto 0); |
10 | Q3: out std_logic_vector (15 downto 0)); |
11 | end Test_Con; |
12 | |
13 | architecture verhalten of Test_Con is |
14 | signal QINT1: std_logic_vector (15 downto 0); |
15 | signal QINT2: std_logic_vector (15 downto 0); |
16 | signal QINT3: std_logic_vector (15 downto 0); |
17 | begin
|
18 | |
19 | -- 1. Version:
|
20 | process(CLK1, RES1) |
21 | begin
|
22 | if RES1 = '1' then |
23 | QINT1 <= (others => '0'); |
24 | elsif CLK1'event and CLK1 = '1' then |
25 | QINT1 <= QINT1 +1; |
26 | end if; |
27 | end process; |
28 | |
29 | -- 2. Version:
|
30 | process(CLK2, RES2) |
31 | begin
|
32 | if RES2 = '1' then |
33 | QINT2 <= (others => '0'); |
34 | elsif CLK2'event and CLK2'last_value = '0' then |
35 | QINT2 <= QINT2 +1; |
36 | end if; |
37 | end process; |
38 | |
39 | -- 3. Version:
|
40 | process(CLK3, RES3) |
41 | begin
|
42 | if RES3 = '1' then |
43 | QINT3 <= (others => '0'); |
44 | elsif CLK3'event and CLK3 = '1' and CLK3'last_value = '0' |
45 | then
|
46 | QINT3 <= QINT3 +1; |
47 | end if; |
48 | end process; |
49 | |
50 | Q1 <= QINT1; |
51 | Q2 <= QINT2; |
52 | Q3 <= QINT3; |
53 | |
54 | end verhalten; |
MfG Holger
XST scheint Probleme mit 'LAST_VALUE zu haben, offenbar aber nicht mit rising_edge(), falling_edge() : (von der XILINX Web-Seite) Problem Description: Keywords: compile, constant Urgency: Standard General Description: XST creates incorrect logic when using the 'last_value VHDL attribute: if H02'event and (H02='1') and (H02'LAST_VALUE = '0') then The sample design is in the bugcases directory, which is an FF, but compiled incorrectly as constant logic. Solution 1: The work around is to use the rising_edge function instead: if rising_edge(H02) then This problem has been fixed in the latest 7.1i Service Pack available at: http://support.xilinx.com/xlnx/xil_sw_updates_home.jsp The first service pack containing the fix is 7.1i Service Pack 2.
das Standard Package "std_logic_1164" von Altera und Xilinx benutzt aber rising_edge() auf std_ulogic Datentypen so wie oben gepostet 'LAST_VALUE. Ich kann mich nur dunkel errinnern das ich damit Probleme hatte und auf der Suche nach dem Fehler stieß ich auf eine Bemerkung (glaube OpenCores.org) das man rising_edge() nicht benutzen sollte. Jetzt wissen wir's ja ganz genau, danke FPGA_User. Gruß Hagen
Ich habe schon immer "CLK'event and CLK = '1'" benutzt und bis jetzt noch keine Probleme damit gehabt. Die Funktion "rising_edge(...)" macht doch auch nichts anderes als das Signal mit dem CLK-Eingang des Logikelements zu verbinden. Soll ich denn nun "rising_edge" benutzten und ist damit ein Riskio verbunden? Ich habe jetzt alles auf eine CLK-Flanke angepasst. Siehe da ich kann 198MHz als maximale Frequenz benutzen. Jetzt muss ich nur noch mal eine Simulation mach und alles überprüfen. Ich habe jetzt mal die sensitivity Listen abgeändert und "rising_edge" verwendet. Den Reset ist jetzt in jeden Prozess sync. Dies hat aber keinen Geschwindigkeitsvorteil gebracht. Ich persönlich finde, dass der async. Reset von der programmierweise und lesbarkeit wesentlich übersichtlicher ist. -- sync. Reset process (CLR,CLK,GATE) begin if(rising_edge(CLK))then if(CLR = '1' or GATE = '0')then S_SHIFT_SPEICHER_A <= '0'; elsif(S_REGA(5) = '1' or S_REGA(17) = '1')then S_SHIFT_SPEICHER_A <= NOT S_SHIFT_SPEICHER_A; end if; end if; end process; -- async. Reset process (CLR,CLK,GATE) begin if(CLR = '1' or GATE = '0')then S_SHIFT_SPEICHER_A <= '0'; elsif(rising_edge(CLK))then if(S_REGA(5) = '1' or S_REGA(17) = '1')then S_SHIFT_SPEICHER_A <= NOT S_SHIFT_SPEICHER_A; end if; end if; end process; Ist denn meine sync. Variante überhaupt richtig? Grüsse Michael
Moin... Na bitte. Ist die Geschwindigkeit nach P&R ermittelt oder irgendwo davor. Die Angaben nach Synthese oder Map sind nur ANhaltspunkte. Der synchrone Reset sollte so funktionieren, ich würde wohl noch die anderen Signale aus der Sens. Liste nehmen -- Sven Johannes
@Michael kann sein, dass es mit dem async. Reset für Dich besser lesbar ist, aber Fakt ist, es kommen unterschiedliche Ergebnisse dabei raus . Nehmen wir mal Dein Bespiel : 2 Signale GATE und CLR sind die Ausgänge von 2 FFs, die am CLK hängen. Bis dahin ist alles synchron. Die Signale GATE und CLR werden nun log. verknüpft und führen zum async. Reset eine Registers von sagen wir mal 10 bit Breite. Aufgrund des Routings wird dieses Reset-Signal an jedem der 10 Flip-Flops zu einem anderen Zeitpunkt ankommen (Differenz vielleicht 1 ns max.) Ich würde bezweifeln, dass diese Pfade beim XST durch ein einfaches Clock-Constraint abgedeckt sind. Möglicherweise ist das Reset-Signal gerade aktiv, wenn der Registerinhalt irgendwo anders gespeichert werden soll -> Datenmüll. Wenn mit GATE und CLR ein sync. Reset realisiert wird, bist Du auf der sicheren Seite, da die Signale jetzt auf den Daten-Eingang des FFs wirken und nun ein simples Clock-Constraint von z.B. 100 MHz sicherstellt, dass die Schaltung bei 100 MHz eben immer funktioniert.
OK habe jetzt nur noch die CLK Leitung in der sensitivity Liste, da jetzt ja nur noch die Clock-Leitung Einfluss auf den Prozess hat. So jetzt habe ich mal eine härtere Nuss gepostet. Ziel des ganzen ist es eine Übereinstimmung eines Musters in einem Register zu finden. "S_MAX_ANZ_EINSEN_A" gibt an wie viele Übereinstimmungen zwischen den gesuchten Muster und dem Register gefunden wurden. Während Gate '1' wird die Analyse durchgeführt. Ist Gate = '0' dann wird das Ergebnis über eine RS232-Interface an den PC übertragen. Deshalb darf das Signal "Valid_Peak_A" nicht mit dem Gate zurückgesetzt werden. Dadurch entsteht ein sehr unangenehme Situation. 1. Hat jemand einen Verbesserungsvorschlag wie das ganze vereinfacht oder optimiert werden kann? 2. Wie kann ich die Enable-Leitung der Logikelemente "elsif(S_REGD(8) = '1' and S_STOP_SEARCH_A = '0' and S_STOP ='0')then" weiter optimieren? process (CLK) begin if(rising_edge(CLK))then if(CLR = '1' or GATE = '0')then if(CLR = '1')then S_MAX_ANZ_EINSEN_A <= "000011"; FIRST_POS <= (others => '0'); S_FIRST_PASS <= '0'; VALID_PEAK_A <= '0'; S_STOP <= '0'; elsif(GATE = '0')then S_MAX_ANZ_EINSEN_A <= "000011"; S_FIRST_PASS <= '0'; S_STOP <= '0'; end if; elsif(S_FIRST_PASS = '0')then VALID_PEAK_A <= '0'; S_FIRST_PASS <= '1'; end if; elsif(S_REGD(8) = '1' and S_STOP_SEARCH_A = '0' and S_STOP ='0')then if(S_EINSEN_GESAMT_A >= S_MAX_ANZ_EINSEN_A)then S_MAX_ANZ_EINSEN_A <= S_EINSEN_GESAMT_A; FIRST_POS <= POSITION - "000000010100"; VALID_PEAK_A <= '1'; S_STOP <= '1'; end if; end if; end process; Grüsse Michael
Verstehe ich dich richtig, Vektor A = "1011" und B = "0001", rauskommen sollte 1 ? Dann ist BitCount(A and B) deine Antwort, hier im Forum gibts eine BitCount() die mit 56 LE's kombinatorisch arbeitet, ca. 10ns Delay. Thread "Eines im Vektor zählen". Gruß Hagen
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.