Hi, ich habe einen Pulsgenerator mit Xilinx ISE in VHDL zusammen gestellt, der seine Daten vom AVR über SPI erhält. Es werden bis zu 16 unterschiedliche Pulsewerte und Pulspausenwerte übermittelt und diese dann nacheinander ausgegeben. Es funktioniert auch alles, nur bekomme ich Warnungen von der ISE und würde die gerne abschalten. Der Code ist im Anhang. und hier die Warnungen: WARNING:Xst:3002 - This design contains one or more registers/latches that are directly incompatible with the Spartan6 architecture. The two primary causes of this is either a register or latch described with both an asynchronous set and asynchronous reset, or a register or latch described with an asynchronous set or reset which however has an initialization value of the opposite polarity (i.e. asynchronous reset with an initialization value of 1). WARNING:PhysDesignRules:372 - Gated clock. Clock net sclkCS[1]_DST[20]_AND_36_o is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop. WARNING:PhysDesignRules:372 - Gated clock. Clock net sclkCS[1]_DST[18]_AND_40_o is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop. WARNING:PhysDesignRules:372 - Gated clock. Clock net sclkCS[1]_DST[19]_AND_38_o is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop. WARNING:PhysDesignRules:372 - Gated clock. Clock net sclkCS[1]_DST[17]_AND_42_o is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop. kann man da noch was machen? Ich bin mit meinen Latein am Ende. Gruß Thorsten
:
Bearbeitet durch User
Thorsten F. schrieb: > The two primary causes of this is ... a register or > latch described with ... reset which however has an > initialization value of the opposite polarity Die eigentliche Ursache mal deutlich herausgestellt. Mehr dazu unten... >> Pulse.txt Das nächste Mal nennst du am Besten deine VHDL-Datei auch *.vhdl Dann gibts Syntax-Highlighting gratis... Und verwende Leerzeichen statt Tabs, dann bleibt die Formatierung und zerlegt sich nicht in alle Richtungen... > use IEEE.NUMERIC_STD.ALL; > use IEEE.STD_LOGIC_UNSIGNED.ALL; Niemals beide zusammen! Sonst hast du doppelte Typdefinitionen, die zu seltsamen Effekten führen können... Mein Vorschlag: nimm statt > signal PulseZaehler: std_logic_vector(11 downto 0):= (others=>'0'); für Zähler einen (eingeschränkten) Integer > signal PulseZaehler: integer range 0 to 1023 := 0; > signal LEDCounter: integer range 0 to 19999999 := 0; Dann kannst du ganz natürlichsprachig lesen, wo der gerade steht. Statt > if LEDCounter < "1 0011 0001 0010 1101 0000 0000" then heißt es dann if LEDCounter < 20000000 then Und damit siehst du SOFORT, dass dein Zähler um einen Schritt zu WEIT zählt. Denn wieviel Takte zählt ein Zähler, der von 0 bis 3 zählt? Richtig: 4 Takte. Und wieviel zählt damit ein Zähler, der von 0 bis 20000000 zählt? Richtig: 20000001 Takte... :-o Fazit: if LEDCounter < 20000000 then Das hier:
1 | if sclkCS="01" then -- steigende Flanke am CS |
2 | if DST(n-1) = '1' then |
3 | --- Pulsedaten
|
4 | Pulsenr <= to_integer(unsigned(DST(n-2 downto n-5))); |
5 | Pulse(Pulsenr) <= DST(n-11 downto 0) ; |
6 | else
|
7 | --- Pulsepausedaten
|
8 | pulsenr <= to_integer(unsigned(DST(n-2 downto n-5))); |
9 | PulsePause(Pulsenr) <= DST(n-6 downto 0) ; |
10 | end if; |
11 | end if; |
optimiert der Synthesizer logischerweise zu dem hier:
1 | if sclkCS="01" then -- steigende Flanke am CS |
2 | --- Pulsedaten
|
3 | Pulsenr <= to_integer(unsigned(DST(n-2 downto n-5))); |
4 | if DST(n-1) = '1' then |
5 | Pulse(Pulsenr) <= DST(n-11 downto 0) ; |
6 | else
|
7 | PulsePause(Pulsenr) <= DST(n-6 downto 0) ; |
8 | end if; |
9 | end if; |
Dir ist übrigens hoffentlich schon klar, dass die Beschreibung oben genau funktionsgleich mit der hier ist:
1 | if sclkCS="01" then -- steigende Flanke am CS |
2 | if DST(n-1) = '1' then |
3 | Pulse(Pulsenr) <= DST(n-11 downto 0) ; |
4 | else
|
5 | PulsePause(Pulsenr) <= DST(n-6 downto 0) ; |
6 | end if; |
7 | --- Pulsedaten
|
8 | Pulsenr <= to_integer(unsigned(DST(n-2 downto n-5))); |
9 | end if; |
Die Pulsenr wird also vom vorhergehenden Taktzyklus genommen! Thorsten F. schrieb: > kann man da noch was machen? Nein. Man kann sie zur Kenntnis nehmen und damit leben... Vergiss die "Null Warning" Mentalität der C-Programmierung. Du wirst kein halbwegs größeres Design ohne Warnungen durchbekommen. In deinem Fall verwendest du einen Reset auf 0, und weist dem Register später einen anderen Wert zu. Das kann das Reset-Netzwerk des S6 nicht abbilden und dafür gibts die Warnung. Ich habe hier die Pulsenr in Verdacht, die auf 0 initialisiert wird und später einen variablen Wert zugewiesen bekommt... BTW: mir gefällt die Beschreibung mit dem einen einzigen mehrmals getakteten Monsterprozess nicht. Diese Beschreibungsart ist extrem unüblich...
:
Bearbeitet durch Moderator
Du hast in Deinem Prozess nicht weniger als 3(!) Statements des Typs
> if rising_edge(USER_CLOCK) then
was (sicher zumindest teilweise) die Ursache Deiner Probleme ist. Pro
Register(bank)/sequentiellen Block gibt es genau einen Clock.
Hallo Lothar, danke das du dich meinem Problem angenommen hast. Freut mich. Lothar Miller schrieb: >>> Pulse.txt > Das nächste Mal nennst du am Besten deine VHDL-Datei auch *.vhdl > Dann gibts Syntax-Highlighting gratis... > > Und verwende Leerzeichen statt Tabs, dann bleibt die Formatierung und > zerlegt sich nicht in alle Richtungen... > Danke, versuche mich zu bessern. >> use IEEE.NUMERIC_STD.ALL; >> use IEEE.STD_LOGIC_UNSIGNED.ALL; > Niemals beide zusammen! Sonst hast du doppelte Typdefinitionen, die zu > seltsamen Effekten führen können... Welche der Beiden macht denn mehr Sinn? Ich muss ja sowieso einiges Anpassen wenn ich eins entferne. > Mein Vorschlag: nimm statt >> signal PulseZaehler: std_logic_vector(11 downto 0):= (others=>'0'); > für Zähler einen (eingeschränkten) Integer >> signal PulseZaehler: integer range 0 to 1023 := 0; >> signal LEDCounter: integer range 0 to 19999999 := 0; > Dann kannst du ganz natürlichsprachig lesen, wo der gerade steht. Statt >> if LEDCounter < "1 0011 0001 0010 1101 0000 0000" then > heißt es dann > if LEDCounter < 20000000 then > > Und damit siehst du SOFORT, dass dein Zähler um einen Schritt zu WEIT > zählt. Denn wieviel Takte zählt ein Zähler, der von 0 bis 3 zählt? > Richtig: 4 Takte. Und wieviel zählt damit ein Zähler, der von 0 bis > 20000000 zählt? Richtig: 20000001 Takte... :-o > Fazit: > if LEDCounter < 20000000 then Danke, habe ich übernommen und werde es mir für die Zukunft merken. > Dir ist übrigens hoffentlich schon klar, dass die Beschreibung oben > genau funktionsgleich mit der hier ist: >
1 | > if sclkCS="01" then -- steigende Flanke am |
2 | > CS |
3 | > if DST(n-1) = '1' then |
4 | > Pulse(Pulsenr) <= DST(n-11 downto 0) ; |
5 | > else |
6 | > PulsePause(Pulsenr) <= DST(n-6 downto 0) ; |
7 | > end if; |
8 | > --- Pulsedaten |
9 | > Pulsenr <= to_integer(unsigned(DST(n-2 downto n-5))); |
10 | > end if; |
11 | >
|
> Die Pulsenr wird also vom vorhergehenden Taktzyklus genommen! Die Pulsenummer ist ja in dem übertragenen Wert enthalten, d.h. ich analysiere den Wert. Vorne 1 ist ein Puls, eine 0 eine Pulspause. Danach kommt die Pulsnummer von 0-15 und dann der zu speichernde Wert. Wie schaffe ich es denn das erst die Pulsenr übernommen wird und dann erst die Werte geschrieben werden. Stehe da auf dem Schlauch. > > Thorsten F. schrieb: >> kann man da noch was machen? > Nein. Man kann sie zur Kenntnis nehmen und damit leben... > Vergiss die "Null Warning" Mentalität der C-Programmierung. Du wirst > kein halbwegs größeres Design ohne Warnungen durchbekommen. In deinem > Fall verwendest du einen Reset auf 0, und weist dem Register später > einen anderen Wert zu. Das kann das Reset-Netzwerk des S6 nicht abbilden > und dafür gibts die Warnung. Ich habe hier die Pulsenr in Verdacht, die > auf 0 initialisiert wird und später einen variablen Wert zugewiesen > bekommt... Danke für die Analyse. Werde das dann so lassen. > > > BTW: mir gefällt die Beschreibung mit dem einen einzigen mehrmals > getakteten Monsterprozess nicht. Diese Beschreibungsart ist extrem > unüblich... Ja, es ist halt gewachsen. Versuche mich auch da zu bessern. ;) Gruß Thorsten
P. K. schrieb: > Du hast in Deinem Prozess nicht weniger als 3(!) Statements des Typs > >> if rising_edge(USER_CLOCK) then > > was (sicher zumindest teilweise) die Ursache Deiner Probleme ist. Pro > Register(bank)/sequentiellen Block gibt es genau einen Clock. Ich habe jetzt nur noch 1 * "if rising_edge(USER_CLOCK) then" drin und die Warnungen sind jetzt tatsächlich raus. Danke.
Thorsten F. schrieb: >>> use IEEE.NUMERIC_STD.ALL; >>> use IEEE.STD_LOGIC_UNSIGNED.ALL; >> Niemals beide zusammen! > Welche der Beiden macht denn mehr Sinn? Nimm die numeric_std: http://www.lothar-miller.de/s9y/categories/16-Numeric_Std Die reicht zum Leben und hat Alles, was man braucht. Man kann dann eben nicht mehr mit uneingeschränkten Vektoren (std_logic) rechnen. Aber das ist auch unnötig. > Wie schaffe ich es denn das erst die Pulsenr übernommen wird und dann > erst die Werte geschrieben werden. Du könntest dir mit einer Variable Sand in die Augen streuen. Variablen ü+bernehmen den Wert "sofort" und werden deshalb gern von prozeduralen C-Programmierern verwendet. Richtig und konsequent wäre aber diese Vorgehensweise:
1 | if DST(n-1) = '1' then |
2 | --- Pulsedaten
|
3 | Pulsenr <= to_integer(unsigned(DST(n-2 downto n-5))); |
4 | Pulse( to_integer(unsigned(DST(n-2 downto n-5)))) <= DST(n-11 downto 0) ; |
5 | else
|
6 | --- Pulsepausedaten
|
7 | pulsenr <= to_integer(unsigned(DST(n-2 downto n-5))); |
8 | PulsePause(to_integer(unsigned(DST(n-2 downto n-5)))) <= DST(n-6 downto 0); |
9 | end if; |
Ist zwar langatmig, macht aber klar und stellt sicher, dass jeweils Daten aus dem aktuellen DST verwendet werden.
Lothar Miller schrieb: > Vorgehensweise: >
1 | > if DST(n-1) = '1' then |
2 | > --- Pulsedaten |
3 | > Pulsenr <= to_integer(unsigned(DST(n-2 downto n-5))); |
4 | > Pulse( to_integer(unsigned(DST(n-2 downto n-5)))) <= |
5 | > DST(n-11 downto 0) ; |
6 | > else |
7 | > --- Pulsepausedaten |
8 | > pulsenr <= to_integer(unsigned(DST(n-2 downto n-5))); |
9 | > PulsePause(to_integer(unsigned(DST(n-2 downto n-5)))) <= DST(n-6 |
10 | > downto 0); |
11 | > end if; |
12 | >
|
> Ist zwar langatmig, macht aber klar und stellt sicher, dass jeweils > Daten aus dem aktuellen DST verwendet werden. Geil, geil, geil. Jetzt klappt es richtig gut. Sind zwar viele Klammern aber klar, beides zusammen zuordnen. Theoretisch bräuchte ich die Zeile mit der Pulsenr gar nicht, da ich den Wert wo anders nicht benötige. DANKE :) Gruß Thorsten
:
Bearbeitet durch User
Thorsten F. schrieb: > Theoretisch bräuchte ich die Zeile mit der Pulsenr gar nicht, da ich den > Wert wo anders nicht benötige. Das war auch der Grund, warum du nicht gemerkt hast, dass du da immer einen CS-Zyklus falsch gelegen hast... > DANKE :) Keine Ursache.
:
Bearbeitet durch Moderator
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.