Forum: FPGA, VHDL & Co. VHDL Spartan 6 Problem


von Thorsten F. (tfol)


Angehängte Dateien:

Lesenswert?

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
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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
von P. K. (pek)


Lesenswert?

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.

von Thorsten F. (tfol)


Lesenswert?

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

von Thorsten F. (tfol)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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.

von Thorsten F. (tfol)


Lesenswert?

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
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.