Hi,
das ist eine Anfängerfrage, trotzdem krieg ich es nicht raus.
Ich habe eine statemachine und in der toggle ich einen pin:
irgendwann:
spimiso <= outdata_sulv(0);
später
spimiso <= outdata_sulv(1);
mit
signal outdata_sulv : std_logic_vector(15 downto 0) ;
outdata_sulv <= "1001010101010010";
spimiso : out std_logic;
Der toggelt da munter vor sich hin, alles gut, erwartungskonform.
Jetz ändere ich das folgendermassen;
i1 <= 1;
spimiso <= outdata_sulv(i1);
später
i1 <= 0;
spimiso <= outdata_sulv(i1);
mit
signal i1 : natural range 0 to (2**32)-1;
Ich greife also nicht direkt auf das Element zu sondern über den Index
i1.
Dann geht das nicht mehr, Syntax ok, aber toggeln tut nichts.
Danke für einen Hinweis.
Kompletter Code hängt dran.
Cheers
Detlef
Detlef _. schrieb:> signal i1 : natural range 0 to (2**32)-1;
Weil ein natural nur ein Subtype eines integer ist, kann es keinen
größeren positiven Wertebereich als ein integer haben.
1
subtypeNATURALisintegerrange0tointeger'high;
2
subtypePOSITIVEisintegerrange1tointeger'high;
Ein integer hat aber nur einen Wertebereich von -2**31 bis +(2**31)-1
Mich wundert sehr, dass du dafür keine Warnung bekommst.
Und ich bin mir (noch ohne die Beschreibung angeschaut zu haben) völlig
sicher, dass du garatniert kein Array hast, das so einen mächtigen Index
braucht.
Deshalb solltest du den Wertebereich des Index bei der Deklaration so
eingrenzen, dass er nicht über das Array hinaus zugreifen kann. Nur dann
kann dir der Simulator auf die Finger klopfen, wenn was nicht passt und
dein Index Amok läuft...
In deinem Fall muss also eine formell korrekte Deklaration samt
Initialisierung so aussehen:
1
signali1:integerrange0to15:=0;
Alles andere gibt Minuspunkte, weil es schlicht falsch ist.
So, nun zum Code:
1
Port{
2
:
3
spiclk:instd_logic;
4
:
5
};
6
:
7
:
8
elsif(clk'event)and(clk='1')then
9
:
10
casefsmis
11
whenidle=>
12
ifspiclk='1'then
13
:
Niemals darfst du asynchrone externe Signale ohne
Eintakten/Einsynchronisieren in FSM verwenden. Dein Design wird dann und
wann eigenartige Fehler bringen und die FSM wilde Sprünge machen.
Mehr dazu dort:
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.htmlhttp://www.lothar-miller.de/s9y/archives/41-Einsynchronisieren-von-asynchronen-Signalen.html
Ein Wort zu deinem "Programmierstil", der hier die Ursache allen Übels
ist: VHDL ist keine Programmiersprache sondern, wie es der Name schon
sagt, eine Beschreibungssprache. Deshalb solltest du das sequentielle
"Top-Down" Programmieren von C oder Java oder sonstwelchen
Programmiersprachen gleich mal vergessen.
Du musst dir auch unbedingt das Verhalten von Signalen in Prozessen
näher ansehen!
Denn ein Signal ändert seinen Wert während eines Prozessdurchlaufs
nicht!
Neu zugewiesene Werte werden lediglich "gemerkt" und vom Signal dann
beim Prozessende oder beim nächsten wait übernommen. Dabei "gewinnt"
jeweils die letzte Zuweisung:
1
:
2
:
3
-- mal angenommen, i1 hat bisher den Wert 0
4
-- und dann kommt diese Zuweisung:
5
i1<=1;
6
-- jetzt merkt sich der Synthesizer, dass beim NÄCHSTEN wait
7
-- bzw. am Prozessense i1 den Wert 1 annehmen soll
8
-- i1 bleibt aber weiterhin 0!
9
-- und deshalb wird hier auf den Index 0 zugegriffen:
10
spimiso<=outdata_sulv(i1);
11
:
12
:
13
endif;
14
-- erst jetzt, beim Prozessende, übernimmt das Signal i1 den Wert 1
15
endprocess;
Das Stichwort dazu heißt Latency.
Und (nur, falls es dir jetzt dann in den Sinn kommt): Nein, du brauchst
für diese simple Aufgabe keine Variablen.
BTW: wenn man dieses Verhalten von Signalen mal kapiert hat, kann man
damit nette Beschreibungen formulieren.
Zu dieser Zeile auch noch ein Wort:
1
-- geht nich warumnurwarum signal outdata_sulv : std_ulogic_vector(15 downto 0) := "16#deadbeef#";
Das geht nicht, weil 16#deadbeef# eben kein Vektor aus std_logic,
sondern eine integer Zahl zur Basis 16 und VHDL eine streng typisierte
Beschreibungssprache ist. Da kann man nicht einfach so ein Bitmuster
"1010111010100101" mit einer Hexzahl AEA5 vergleichen oder eine integer
Zahl einem Vektor mit völlig anderem Typ zuweisen. Es muss dazwischen
eine Umwandlung passieren. Die numeric_std bietet dafür Casts und
Umwandlungsfunktionen an:
http://www.lothar-miller.de/s9y/categories/16-Numeric_StdDetlef _. schrieb:> Hab nen board. Messe mit nem scope.
Falsche Vorgehensweise für so eine simple Beschreibung.
Simuliere dein Design!
Der Simulator ist der Debugger für VHDL. Dann kannst du ganz leicht
sehen, dass deine Signale immer "irgendwie einen Takt versetzt" sind.
Lothar M. schrieb:>> Hab nen board. Messe mit nem scope.> Falsche Vorgehensweise für so eine simple Beschreibung.> Simuliere dein Design!> Der Simulator ist der Debugger für VHDL. Dann kannst du ganz leicht> sehen, dass deine Signale immer "irgendwie einen Takt versetzt" sind.
Hinzu kommt, das das Synthesetool nur einen Teil des VHDL kennt, kleiner
als das was der Simulator kennt. Und Das Synthesetool ignoriert für ihn
unbekannten Teil des VHDL-Syntaxes und setzt damit nicht in das
Konfigurationsfile des FPGA um.
Dazu sollte sich dann aber ne Meldung im Synthese-log finden lassen,
Etwa "VHDL index Opeartion not supported, signal wille be pruned to GND"
.
Wie eins drüber gesagt, VHDL ist keine Programmiersprache. In C lassen
sich Indexoperationen auf Assembler umsetzen, in HDL ist das
offensichtlich nicht selbstverständlich.
Hi, vielen Dank für die Hinweise.
Ich lernte:
Auf Warnungen achten.
Indizierung muss nicht gehen, in die Logs schauen.
Das externe Signal einsynchronisieren.
In die Simulation einfummeln.
Die strenge Typisierung kenne ich inzwischen.
Die Zuweisung von Signalen am Ende des Process ist mir allerdings
bekannt. Wenn ich dem index 1 zuweise und dann zugreife benutze ich den
'alten' Wert des Index., das war die 0. Das Toggeln muss aber trotzdem
gehen .?????!!!!!!.
Bin am Anfang einer steilen Lernkurve. Vielen Dank, kenne Euch und weiß
dass Ihr es drauf habt.
Cheers
Detlef
Detlef S. schrieb:> Ich lernte:> Auf Warnungen achten.> Indizierung muss nicht gehen, in die Logs schauen.> Das externe Signal einsynchronisieren.> In die Simulation einfummeln.Detlef S. schrieb:> Das Toggeln muss aber trotzdem> gehen .?????!!!!!!.
Dann hast Du den letzten Punkt deiner "Lernliste" noch nicht ausreichend
beackert: Simulation. Das ist das Erste was Du angehen mußt, um wirklich
zu verinnerlichen, was Du da tust.
Im übrigen "geht" Indizierung. Immer.
Nur vielleicht nicht so, wie Du's intuitiv erwartest (s.o.).
Abgesehen davon (aber das ist meine persönliche Meinung) kann ich mit
der "Verteufelung" von Variablen nicht viel anfangen. Variablen sind ein
(wichtiges) Sprachelement von VHDL und sind dazu gedacht, daß man sie
benutzt.
Natürlich muß man wissen, was man tut, aber das ist ja immer und bei
allem eine gute Idee.
Markus F. schrieb:> kann ich mit der "Verteufelung" von Variablen nicht viel anfangen.
Zum Glück wenigstens mit Anführungszeichen.
> Variablen sind ein (wichtiges) Sprachelement von VHDL und sind dazu> gedacht, daß man sie benutzt.
Klar, es ist auch gut, wenn man sie kennt und an der richtigen Stelle
benutzt. Aber Variablen dafür zu nutzen, damit man wie mit C oder sonst
einer sequentiellen Programmiersprache "von oben nach unten
programmieren" kann, dafür sind die nicht gedacht.
Und wenn Variablen dann speicherndes Verhalten aufweisen, zwickts mich
ganz gewaltig am Auge und ich trau dem "VHDL-Programmierer" ab da alles
zu. 😉
Lothar M. schrieb:> Und wenn Variablen dann speicherndes Verhalten aufweisen, zwickts mich> ganz gewaltig am Auge und ich trau dem "VHDL-Programmierer" ab da alles> zu. 😉
Hmmm, Xilinx empfiehlt im XST User Guide sogar shared Variablen zu
nutzen um BRAM zu instanzieren. ;-)
Tobias B. schrieb:> Hmmm, Xilinx empfiehlt im XST User Guide sogar shared Variablen zu> nutzen um BRAM zu instanzieren. ;-)
Das ist ja der entscheidende Punkt. Wenn du weist, das man da BRAM
braucht dann kannst du shared variable verwenden, aber auch nur genauso
wie im template wie im Synthesize-Guidbeschrieben.
Aber nicht anders rum, variable verwenden und hoffen&beten das XST da
was passendes auf Lager hat und einbaut.
Synthesis Style Guide ist eben Pflichtlektüre, die Kenntnis der
vHDL-Syntax Definition nach IEEE Standardisierungskomission reicht
nicht.
Und die 'Schreibweise' mit arrays um sich eine explizite
BRAM-Instanzierung (oder auch was aus dem Coregenerator) zu sparen, hat
auch ihre Nachteile:
-passt nicht bei allen speicherport-Varianten, beispielsweise sollte die
bitbreite beider Ports gleich sein
-ist nicht besonders gut auf andere Architekturen (bspw. Asic
übertragbar). dafür muss der Speicher wieder als extra componente
gekapselt werden.
Da gebe ich dir in allen Punken recht. Mein Kommentar ist auch nur im
Kontext des Zitats zu betrachten und das man nicht das eben nicht
verallgemeinern kann. Dazu ist das ganze auch nicht mit einem ;-)
versehen und sollte nicht so ernst genommen werden. ;-)
Das mit der
Tobias B. schrieb:> shared Variable
kenne ich, ist aber seltsam weil das bei Intel auch anders funktioniert.
Das ist eigentlich eher traurig, dass die Synthesetools recht
unterschiedlich sind. Auch in Puncto guter VHDL2008 Unterstützung die es
für den Max10 nie geben wird.
Gustl B. schrieb:> Auch in Puncto guter VHDL2008 Unterstützung
Na gut, nachdem der Synthesizer sowieso bestenfalls mit 5% des
Sprachumfangs von VHDL was anfangen kann (nicht mal ein simples LED <=
not LED after 500ms; bekommt er in Hardware gebacken ;-), ist das meist
nur eine theoretische Einschränkung.
Gustl B. schrieb:> Das mit der>> Tobias B. schrieb:>> shared Variable>> kenne ich, ist aber seltsam weil das bei Intel auch anders funktioniert.
Ist generell die Frage, ob das mit der Shared Variable so schlau (von
Xilinx) war: funktioniert nicht mit VHDL 2008, weil shared variables da
(richtigerweise) protected sein müssen. Und protected shared variables
sind wiederum nicht synthetisierbar...
Lothar M. schrieb:> ist das meist> nur eine theoretische Einschränkung.
Naja generic Packages kann man schon gebrauchen, Case mit don't care,
shift Operationen für unsigned/signed, ?? Operator, ...
Markus F. schrieb:> funktioniert nicht mit VHDL 2008, weil shared variables da> (richtigerweise) protected sein müssen. Und protected shared variables> sind wiederum nicht synthetisierbar...
Genau, zum Glück geht das aber auch bei Xilinx ganz ohne Variablen.
Hi,
Eure guten Ratschläge werde ich beherzigen, die meisten jedenfalls. Das
ist der langfristige Prozess der Lernkurve.
Kurzfristig würde ich gerne verstehen warum der nicht toggelt.
Signaltzuweisungszeitpunkt habe ich drauf.
Cheers
Detlef
Ich bin etwas später dazu gekommen.
Mal abgesehen davon, dass das Toggeln von "logikpegel" auskommentiert
ist: mit dem Zähler passiert doch gar nichts. Bleibt der überhaupt
drinnen? Guck doch mal nach im rtl viewer.
Nein, debugleiche. Vivado optimiert den dann weg. Ich muss aber auch
nicht sparen, die ganze Nummer nimmt 51 von ungefähr 64000 LUTs :)
afair.Ich benötige nur die ca. 200 GPIOs, die innere Logik bleibt
weitgehend ungenutzt.
Cheers
Detlef
gästchen schrieb:> mit dem Zähler passiert doch gar nichts.
Dann blinkt halt auch nichts... ;-)
Und wenn was blinken würde, dann haben wir hier das berühmte
"off-by-one" Problem: der Zähler zählt nämlich 10000000+1 Takte, weil er
ja die 0 auch noch zählt.
Na gut, ich gebe zu, bei 10000000 Takten fällt das nicht arg auf, aber
wenn man das mit 10 macht, dann wird diese "off-by-one" Thematik schon
besser sichtbar.
Und dann immer noch das hier:
1
signalfsmcnt:naturalrange0to(2**31)-1:=0;
Mal abgesehen, dass du da auch gleich so schreiben könntest (weil
"natural" sowieso nur den "range 0 to (2**31)-1" hat):
1
signalfsmcnt:natural:=0;
Der Witz an all diesen Deklarationen ist das, was ich schon geschrieben
habe:
der fsmcnt läuft eben nicht und niemals bis 2147483647! Warum definierst
du ihn dann so? Genau z.B. wegen des "off-by-one" Fehlers und wegen
sonstigen amoklaufenden Zählern solltest du selber Wertebereiche
sinnvoll einschränken. Und das eben nicht irgendwelchen
Optimierungsschritten überlassen.
Es gilt was
ich schrieb:> Deshalb solltest du den Wertebereich des Index bei der Deklaration so> eingrenzen, dass er nicht über das Array hinaus zugreifen kann. Nur dann> kann dir der Simulator auf die Finger klopfen, wenn was nicht passt und> dein Index Amok läuft...
Optisch sieht auch dieser fsmcnt ziemlich "unsauber" aus. Irgendwann so
um etwa 1001 (also nach 1002 Takten) herum schlägt der zu. Für mich ist
das "irgendwie so geworden", aber sicher nicht "genau so geplant".
Das hier
1
signalindcnt:naturalrange0to32:=0;
sieht auch seltsam aus. Es ruft geradezu: "mit mir wirst du noch mal
Probleme haben".
Und spätestens hier kommt dann auch der Flachmann ins Grübeln:
1
indata_slv(15-(indcnt-1))<=spimosisyn2;
Das sieht aus wie: "Durch ausgiebiges Ausprobieren haben wir
festgestellt, dass..."
Noch ein Wort dazu:
1
indata_slv(15-(indcnt-1))<=spimosisyn2;
Mit ein wenig Nachdenken merkst du, dass du den MOSI nicht
einsynchronisieren musst, weil der nämlich zu diesem Zeitpunkt, an dem
du ihn einliest, völlig stabil dasteht. Und auch schon im Takt davor und
auch dahinter. Der Master ändert den Pegel das MOSI erst bei der
fallenden SCLK Flanke (wenn er sich SPI-konform verhält und bei der
steigenden Flanke einliest).
Vielen Dank für die Begutachtung, sie fällt milde aus, ne 3 vllt. .
Lothar M. schrieb:> gästchen schrieb:> der fsmcnt läuft eben nicht und niemals bis 2147483647! Warum definierst> du ihn dann so? Genau z.B. wegen des "off-by-one" Fehlers und wegen
off-by-one hat mich schon viele Tage gekostet, kennick. Auf die
notwendigen Bereiche der Zähler habe ich nicht geschaut, die hab ich so
großzügig gewählt, dass nichts anbrennen kann. Dass man dann Fehler
schwerer findet ist mir bewußt, war aber alles grün.
> Optisch sieht auch dieser fsmcnt ziemlich "unsauber" aus. Irgendwann so> um etwa 1001 (also nach 1002 Takten) herum schlägt der zu. Für mich ist> das "irgendwie so geworden", aber sicher nicht "genau so geplant".
Doch doch, geplant, nach 50mal clk muss die spiclk kommen, sonst ist was
schief, das ist nen timeout, da hab ich ne glatte Zahl >50 gewählt.
>> Das hier>
1
>signalindcnt:naturalrange0to32:=0;
2
>
> sieht auch seltsam aus. Es ruft geradezu: "mit mir wirst du noch mal> Probleme haben".
Unfertig, da kommen mal irgendwann ~200 GPIOs ran, das wird geändert,
kein Fehler. Und ich weiß auch, dass das 33 Werte sind, kein off-by-one.
> Und spätestens hier kommt dann auch der Flachmann ins Grübeln:>
1
>indata_slv(15-(indcnt-1))<=spimosisyn2;
2
>
> Das sieht aus wie: "Durch ausgiebiges Ausprobieren haben wir> festgestellt, dass..."
Nein, das steht da so und nicht 16-indcnt damit ich das verstehe, wenn
ich mir das in 2 Wochen anschaue, Eigenpädagogik, führt manchmal zu
etwas komischer source.
>> Noch ein Wort dazu:>
1
>indata_slv(15-(indcnt-1))<=spimosisyn2;
2
>
> Mit ein wenig Nachdenken merkst du, dass du den MOSI nicht> einsynchronisieren musst, weil der nämlich zu diesem Zeitpunkt, an dem> du ihn einliest, völlig stabil dasteht. Und auch schon im Takt davor und> auch dahinter. Der Master ändert den Pegel das MOSI erst bei der> fallenden SCLK Flanke (wenn er sich SPI-konform verhält und bei der> steigenden Flanke einliest).
Ja, stimmt, der kann sich nicht ändern, die spiclk muss
einsynchronisiert werden, mosi nicht. Ich war durch deine klare Ansage
'Niemals darfst du ....' da ein wenig gepolt :)).
Wieder was dabeigelernt, THX
Cheers
Detlef