Forum: FPGA, VHDL & Co. Xilinx ISE Mehrfach-Instanzierung Bug(?)


von stefan06 (Gast)


Angehängte Dateien:

Lesenswert?

Hi!

Habe mir vor Kurzem ein Eval-Board mit Spartan-6 von Digilent besorgt, 
nun hänge ich beim Synthesetool von Xilinx fest.
Ich würde gerne meinen Rs232-Receiver/Transmitter (bzw. eig. UART) 
testen, indem ich Daten vom PC aufs Board schicke, dort parallelisiere 
und seriell wieder zurückschicke. Receiver und Transmitter habe ich 
bereits getrennt verifiziert, und auf meinem Altera-Board läuft alles 
klaglos.

Scheinbar kann die ISE von Xilinx aber nicht mit meiner "doppelten" 
Instanzierung eines Strobe-Generators umgehen (siehe Screenshot). Beide 
Strobe-Gens werden immer mit den selben Parametern (in dem Fall 
Baudrate) instanziert. Ich benötige aber 2 verschiedene Strobe-Gens... 
einen für Rx, den anderen für Tx.

Erstelle ich nun eine exakte Kopie meiner entity "StrobeGen" und nenne 
sie "StrobeGen2", und instanziere 1x "StrobeGen" (z.b. im Tx-Pfad) und 
1x "StrobeGen2" (im Rx-Pfad), funktioniert alles tadellos.

Das Problem liegt jetzt also nicht am RxTx selbst, sondern an den 
instanzierten Strobe-Generatoren, die sich nicht mit unterschiedlichen 
Parametern (generics) instanzieren lassen.

Danke im Voraus,
Stefan

von wosnet (Gast)


Lesenswert?

Ich hab ISE bisher nur mit Verilog benutzt, und dort funktioniert das. 
Vielleicht ein VHDL-Problem?
Vielleicht irgendwas bei der Parameterübergabe falsch?

von stefan06 (Gast)


Angehängte Dateien:

Lesenswert?

Habe die entity und die beiden Instanzierungen mal raufgestellt... bei 
Altera funktionierts auf jeden Fall, die Simulation in ModelSim ist auch 
ohne Fehler.

von Omega (Gast)


Lesenswert?

Bei der Tx Instantierung fehlt iStart

Helfen würde auch, was du für Fehlermeldungen bekommst und was konkrett 
nicht funktioniert

von stefan06 (Gast)


Lesenswert?

iStart hat einen default-wert von '1', daher muss der nicht zugewiesen 
werden.
Fehlermeldungen und Warnings bekomme ich keine (irgendwie seltsam), das 
Problem besteht darin, dass der Tx-StrobeGen die selbe CycleTime wie der 
Rx-StrobeGen bekommt, obwohl ich 2 verschiedene Werte übergebe:
1 sec / (gBaudRate * 2) beim Rx,
1 sec / (gBaudRate) beim Tx.

Es handelt sich in meinen Augen aber eher um ein allgemeines Problem, 
das (bei mir) nur in der ISE auftritt.

P.S.: die zwei verschiedenen Parameter kommen daher, dass ich die 
Rx-Daten in der 'Mitte' des aktuellen Bits abtasten möchte, um die 
Fehleranfälligkeit zu minimieren. Bei Erkennung der fallenden Flanke im 
Rx (=StartBit) wird der Rx-StrobeGen angeworfen (R.StartStbGen = '1'), 
dann befindet sich jeder zweite Strobe in der Mitte des aktuellen Bits.

von Fpgakuechle K. (Gast)


Lesenswert?

IMHO weist du beiden den selben Wert zu
1
gClkFrequency     => gClkFrequency

das muss also gleich sein.

wolltest du  das eine mit
1
gClkFrequency     => 2 * gClkFrequency
schreiben?

Bei
1
gStrobeCycleTime   => 1 sec / (gBaudRate * 2)
könnte man  mal
1
gStrobeCycleTime   => 1.0 sec / (gBaudRate * 2.0)
antesten.

Es könnte sein das der compiler statt mit float mit integer rechnet und 
beides auf 0 rundet.

MfG

von Fpgakuechle K. (Gast)


Lesenswert?

Hab grad nachgelesen
http://eesun.free.fr/DOC/vhdlref/refguide/language_overview/objects__data_types_and_operators/understanding_types_and_subtypes.htm

versuch es mal statt mit 1 sec mit 1_000_000_000 ns zu rechnen, das 
dürfte Rundungsfehler ausschalten.

MfG,

von stefan06 (Gast)


Lesenswert?

Fpga Kuechle schrieb:
> IMHO weist du beiden den selben Wert zu
> gClkFrequency     => gClkFrequency
>
> das muss also gleich sein.
>
> wolltest du  das eine mit
> gClkFrequency     => 2 * gClkFrequency
> schreiben?


ClkFrequency ist Absicht, ich bewege mich ja nur in einer Clock-Domain 
(und die Frequenz wird in dem Fall nur für die Berechnung der 
Counter-Breite im StrobeGen verwendet).

> Bei
> gStrobeCycleTime   => 1 sec / (gBaudRate * 2)
> könnte man  mal
> gStrobeCycleTime   => 1.0 sec / (gBaudRate * 2.0)
> antesten.

Soeben versucht, ohne Erfolg (auch mit den 1_000_000_000 ns). Und wie 
gesagt, bei 2 verschieden benannten StrobeGens (entity StrobeGen1 und 
entity StrobeGen2, in den Dateien StrobeGen1.vhd und StrobeGen2.vhd) 
läufts tadellos.
Das Problem muss also mMn bei einer Einstellung in der Synthese bzw. 
beim Compiler liegen.

von Hmm (Gast)


Lesenswert?

Vermutlich liegt das Problem wie üblich in dem nicht gezeigten Code. 
Poste mal die Architektur.

von stefan06 (Gast)


Angehängte Dateien:

Lesenswert?

Hmm, wüsste nicht was da verkehrt sein könnte... bis auf ein paar 
Schönheitsfehler ;)

von Hmm (Gast)


Lesenswert?

Schau mal wieviel Bits die Zähler der beiden Instanzen haben.

Der Ausdruck:
  constant cClkCycPerStrobeCyc : natural :=
    gClkFrequency / (1 sec / gStrobeCycleTime);

wird eine wahnsinnig hohe Zahl geben, die vermutlich auf 32 Bit 
beschränkt wird.

Da:
    gClkFrequency    : natural := 100E6;
    gStrobeCycleTime  : time   := 256E3
ist

100E6 / (1 / 256E3)
100E6 * 256E3 = 1E8 * 256E3 ? 256E11

und das würde eigentlich 45 Bits erfordern.

Die Konstanten sind eigentlich nicht richtig in Bezug auf die Einheiten.
Mach das korrekt und dann überprüfe die Berechnung nochmal.

von Fpgakuechle K. (Gast)


Lesenswert?

Rechnet LogDualis so wie gewünscht?
MfG

von stefan06 (Gast)


Lesenswert?

Hoppla, da ist mir beim rumprobieren an den Sourcen was schiefgegangen, 
bevor ich sie hochgeladen habe (wollte den ursprünglichen Zustand 
wiederherstellen)...

    gClkFrequency    : natural := 100E6;
    gStrobeCycleTime  : time   := 256E3

kann ja gar nicht funktionieren, 'time' vs. 'natural' (256E3)...
da würde dann eigentlich

    gStrobeCycleTime  : time   := 1 sec / 256E3

hingehören, also wäre das Ergebnis für cClkCycPerStrobeCyc nicht

100E6 * 256E3 = 1E8 * 256E3 = 256E11, sondern
100E6 / 256E3 = 1E8 / 256E3 = 390,

daraus folgt der ClkCounter(9 downto 0) für die Standard-Generics.

Sorry, mein Fehler...

von stefan06 (Gast)


Lesenswert?

Fpga Kuechle schrieb:
> Rechnet LogDualis so wie gewünscht?
> MfG

Ja, LogDualis hab' ich überall in Verwendung - und wenn es nicht so 
wäre, würde der Lösungsansatz "StrobeGen1 und StrobeGen2" nichts daran 
ändern...

von Fpgakuechle K. (Gast)


Lesenswert?

VHDL ist für die Synthese nicht einheitlich umgesetzt oder definiert. 
Wenn es also bei Altera funktioniert, heisst es nich loange nicht, das 
das Xilinx auch so tut.

Type time gilt pauschal als nicht synthesefähig. Das kann man zwar von 
Fall zu fall unterschiedlich sehen, mit Vermeiden ist man aber auf der 
sicheren Seite. In Package zum Vergleich wäre noch der einzige Platz für 
sowas, aber nicht in Generics oder in berechnungen für bitbreiten.
Kann gut gehen, muss aber nicht.

Was in deinem Design passiert ist sollte dir der Synthese report 
verraten (*.syr). Insbesonders was für counter synthetisiert werden.

Als Alternative zu den den Unsigned counter kannst du auch integer 
counter mit range verwenden, das erspart den Logdualis zu berechnen der 
Bitbreite. 
(http://iweb.tntech.edu/oelkeelany/4110F10/lectures/ece4110_lecture_28.ppt 
p.8)

MfG,

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


Lesenswert?

Fpga Kuechle schrieb:
> Als Alternative zu den den Unsigned counter kannst du auch integer
> counter mit range verwenden
Das macht den Code auch erst so richtig schön lesbar. Und am besten die 
ganzen Zeiten aus der Berechnung rauslassen, weil es da bei der 
Umsetzung durchaus Unterschiede macht, ob mit ps, ns oder sec gerechnet 
wird!

Ich mache sowas einfach alles mit integer und nehme die Einheiten 
implizit an (als Kommentar):
http://www.lothar-miller.de/s9y/categories/42-RS232

von Fpgakuechle K. (Gast)


Lesenswert?

Lothar Miller schrieb:
> Fpga Kuechle schrieb:
>> Als Alternative zu den den Unsigned counter kannst du auch integer
>> counter mit range verwenden
> Das macht den Code auch erst so richtig schön lesbar. Und am besten die
> ganzen Zeiten aus der Berechnung rauslassen, weil es da bei der
> Umsetzung durchaus Unterschiede macht, ob mit ps, ns oder sec gerechnet
> wird!
>
> Ich mache sowas einfach alles mit integer und nehme die Einheiten
> implizit an (als Kommentar):
> http://www.lothar-miller.de/s9y/categories/42-RS232

Gutes beispiel. Persönlich definiere ich für den integercounter einen 
eigenen typ und verwende für den Grenzwert 'high und 'low statt nackter 
Zahlen.

Also
1
subtype t_rxbitcnt is integer range 0 to 9;
2
signal rxbitcnt : t_rxbitcnt := t_rxbitcnt'high;
3
4
--..
5
6
if rxbitcnt = t_rxbitcnt'high then
7
   rxbitcnt <= t_rxbitcnt'low;
8
--..

Um den Zähler zu verlängern/verkürzen muss dann der Code nur an einer 
Stelle (der typedef) angefasst werden.


MfG,

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


Lesenswert?

Fpga Kuechle schrieb:
> Um den Zähler zu verlängern/verkürzen muss dann der Code nur an einer
> Stelle (der typedef) angefasst werden.
Hmmm, sieht elegant aus, hat mir aber schon fast eine zu starke Tendenz 
in Richtung "implizite Annahme"...

Denn genau an dieser Stelle
1
   if (txcnt<(Quarz_Taktfrequenz/Baudrate)-1) then
liest sich der explizite Einfluss der Taktfrequenz und der Baudrate auf 
den Zählerstand irgendwie beruhigender als die Annahme, dass der 'high 
schon richtig gesetzt sein wird:
1
   if (txcnt<txcnt'high) then


Und spätestens beim recht klaren
1
   rxcnt   <= ((Quarz_Taktfrequenz/Baudrate)-1)/2;
wirds dann doch undurchsichtig
1
   rxcnt   <= rxcnt'high/2;
Da ist dann schon einiges an Systemkenntnis nötig, damit man da nicht 
wieder nachschauen muss, was denn so erreicht wird.

Fpga Kuechle schrieb:
> Um den Zähler zu verlängern/verkürzen muss dann der Code nur an einer
> Stelle (der typedef) angefasst werden.
Das ist auch bei meiner "ausführlichen" Version so (Anpassung der 
Generics oder der Konstanten), aber ich finde die Verwendung der 
Attribute 'low und 'high auf diese Art auch recht elegant. Ich hatte das 
bisher hauptsächlich in generischen Funktionen gemacht, weil man die ja 
"nur" einmal richtig zum Laufen bringen muss und dann nicht mehr 
anschaut... ;-)

von Fpgakuechle K. (Gast)


Lesenswert?

Lothar Miller schrieb:
> Fpga Kuechle schrieb:

> liest sich der explizite Einfluss der Taktfrequenz und der Baudrate auf
> den Zählerstand irgendwie beruhigender als die Annahme, dass der 'high
> schon richtig gesetzt sein wird:
>
1
>    if (txcnt<txcnt'high) then
2
>
>
>
> Und spätestens beim recht klaren
>
1
>    rxcnt   <= ((Quarz_Taktfrequenz/Baudrate)-1)/2;
2
>
> wirds dann doch undurchsichtig
>
1
>    rxcnt   <= rxcnt'high/2;
2
>
> Da ist dann schon einiges an Systemkenntnis nötig, damit man da nicht
> wieder nachschauen muss, was denn so erreicht wird.

Ja man muss die Parameter schon kennen. Oder schnell nachschauen können 
-> die Typdef ins package und diese ausdrucken und an den Moni hängen.
Oder mehr info in den typ namen packen: t_txcnt_SysClk_per_Baud.

Oder Kommentar schreiben. Kollege hatte mal den Anspruch, das auch ein 
Project-Manager anhand des VHDL-Codes das System verstehen kann...

MfG,

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


Lesenswert?

Fpga Kuechle schrieb:
> Oder Kommentar schreiben.
Nichts ist veralteter als ein eben hingeschriebener Kommentar... ;-)

> Kollege hatte mal den Anspruch, das auch ein Project-Manager anhand
> des VHDL-Codes das System verstehen kann...
An diesem Tag lernte ich alles, was man über das Scheitern wissen muss.

von stefan06 (Gast)


Lesenswert?

Fpga Kuechle schrieb:
> Type time gilt pauschal als nicht synthesefähig. Das kann man zwar von
> Fall zu fall unterschiedlich sehen, mit Vermeiden ist man aber auf der
> sicheren Seite. In Package zum Vergleich wäre noch der einzige Platz für
> sowas, aber nicht in Generics oder in berechnungen für bitbreiten.
> Kann gut gehen, muss aber nicht.

Das war also das Problem... der Datentyp 'time' wird anscheinend einfach 
ignoriert, deshalb wurde 2 mal der selbe StrobeGen instanziert...
und mehr wars auch schon gar nicht :)

Vielen Dank an alle für eure Mühe!

Liebe Grüße,
Stefan

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.