Ich mache einfach mal so einen thread auf, wo Anfänger wie ich einfach
kompakte, kleine und schnell zu beantwortende fragen reinstellen.
Soll ein zumüllen der Übersicht verhindern - kA obs klappt.
Fange also mal an: meine aktuelle Frage bezieht sich auf folgendes.
Sinnlose Ideen zu haben ist gar nicht so leicht, aber ich versuche mini
problemchen auszuprobieren. Vielleicht wachsen die ja mal zu einem
großen Projekt an.
Also der Versuch aus einer Adresse "A" ein Chipselect zu erzeugen. mehr
nicht. Sollen an 8 Adressen 2 Teilnehmer der Länge 7 hängen. na gut.
Syntax check gibt folgenden Fehler aus: "Enumerated value U is missing
in select.
Nun wenn ich statt "10" when '1' auf "10" when others gehe, gibts nichts
zu beanstanden.
Also Einleitende frage: was steckt hinter dem enum U?
Und korrektur der CS-Denkweise natürlich auch willkommen.
c ist ein Vektor aus 2 std_logic.
Was ist ein std_logic, welche Werte kann der haben?
Ein std_logic kann 9 Zustände annehmen:
{'1','0','H','L','X','U','W','Z','-'}
Du hast in deinem Original nur 2 der möglichen 81 Zustände
"11" ... "-U" ... "ZW" ... "1L" ... "--" dargestellt.
Du hast also die ganzen anderen Kombinationen ausser "01" und "10"
ignoriert.
> Und korrektur der CS-Denkweise natürlich auch willkommen.
So gehts kürzer:
Ach, übrigens:
> Du hast also die ganzen anderen Kombinationen ausser "01" und "10"> ignoriert.
Das war ein Lesefehler :-/
Richtig müsste es heißen:
A(7) kann 9 Zustände annehmen, du hast 7 davon ignoriert.
Komplett ausgeschrieben könnte deine Zuweisung so aussehen:
1
withA(7)select
2
C<="01"when'0',
3
"10"when'1',
4
"UU"when'H',
5
"UU"when'L',
6
"UU"when'W',
7
"UU"when'Z',
8
"UU"when'X',
9
"UU"when'U',
10
"UU"when'-';
Denn in den letzten 7 Fällen kannst du getrost von einem undefinierten
Ergebnis ausgehen. Damit sparst du dir das when others.
Aber in der Praxis gibt es nur die ersten beiden (zumindest innerhalb
des FPGAs) und deshalb kannst du die anderen in einem (1) when others
Fall zusammenfassen.
Du könntest also auch so schreiben:
1
withA(7)select
2
C<="01"when'0',
3
"10"when'1',
4
"UU"whenothers;
Das ist formal richtig, simuliert richtig und lässt sich synthetisieren.
Warum die Warnung : Line 23. = can not have such operands in this
context.
Außerdem Frage zum wait_until rising_edge. Das habe ich öfter als
Alternative zum if (rising_edge) gelesen. Hat es Vorteile? Und das darf
man anscheinend nur ohne sensitivitäts liste machen. Ist das dann ein
Problem falls ich irgendwann größeres Simulieren will?
> Außerdem Frage zum wait_until rising_edge. Hat es Vorteile?
Siehe:
http://www.lothar-miller.de/s9y/archives/16-Takt-im-Prozess.html> Ist das dann ein Problem falls ich irgendwann größeres Simulieren will?
Nein, es hat sogar den unschlagbaren Vorteil, dass die Simulation
garantiert richtig ist, weil keine Signale in der Sensitiv-Liste
fehlen können.
Oh mein Gott.... in der Tat. Vector ist natürlich Schwachsinn......
Ich fühle mich wie in den ersten c tagen. Ein Instikt was welche
Fehlermeldungen verursacht fehlt mir ja noch völlig. Und -nun ja- sehr
trickreich ist obiger Fehler ja nicht gerade. :-(
@Lothar. Ja danke. Deine ganze Seite ist doch intensiveres Studium wert.
Wenn man sich dann noch im entscheidenden Moment an die relevanten Infos
erinnert, steht sehr viel drin.
Eine Frage möchte ich direkt noch los werden weil ich sie auch in einem
Codefragment gesehen habe.
Ich habe ein internes Signal
1
signalxyz:STD_LOGIC_VECTOR(3downto0):="0000";
a) ist das "Initialilsieren" auch für synthetisierte Hardware gültig?
b) wie schreibe ich das in Abhängigkeit mit einem generic der die
Bitbreite definiert?
Ich sollte für heute abschalten und ein Bierchen trinken gehen - klar im
zweiten Beispiel hab ich den generic (breite -1 downto 0) verschlabbert.
Auch wenns euch sicher klar ist : wollte das der Vollständigkeit halber
noch korrigieren.
>> a) ist das "Initialilsieren" auch für synthetisierte Hardware gültig?
Bei Xilinx ja. Die Inistialisierung gehört zum "Programmiervorgang"
> b) wie schreibe ich das in Abhängigkeit mit einem generic der die
.
> klappte nicht. Ich hoffe da war nicht wieder ne Dummheit der Grund.
Ich habe eine Frage zur compoments; anbei ein Testprojekt an dem ich
gestern geübt habe und nun nciht mehr weiter komme.
Plan war: eine entity für eine 7-Segmentanzeige. Die dann (später) evtl.
in eine Entity Anzeige als Component(s) übernehmen. Diese Anzeige würde
ich dann ganz gern wenn ich mal Hardware besitze auch zum debuggen
nehmen. Vielleicht umschaltbar dezimal/hex.
Ok erste Frage: muss ich die Anzahl von components exakt angeben oder
kann ich irgendwie auch eine Art Array von compoments machen? Aus
folgendem grund. Wenn ich eine allgemeine Anzeige haben möchte ist die
Stellenzahl ja so was wie ein generic und für eine 16-Bit anzeige sind
entsprechend meh components notwendig.
Das ist aber eh noch Zukunftsmusik. Siehe Datei :-(
Um etwas zur Anzeige bringen zu können, wollte ich einen Impulsgeber
verwenden und der Einfachheit halber erst mal einen Zähler. Also die
Idee: eine Stelle der 7-Segment entity als component in den Zähler, und
den Zählstand an den Dateneingang. Fertig. Enttäuschung.
Wie mache ich das denn mit ALLEN Signalen. Müssen eine 'top' entity
definiert werden, in der alle externen Signale vorhanden sind? Wie oe
oder die Signale zu den Segmenten? Kann ich so eine Anzeige gar nciht
mal schnell mit einem counter verknüpfen?
Ich hoffe sehr ihr könnt mein Problem verstehen und mir einen Rat geben,
wie ich in dem Code vorgehen müsste. Der wird ja noch deutlich
komplexer.
Ach ja: und irgendwelche libraries muss ich noch nciht in den Kopf
nehmen? work ist immer das vhd file? Bzw. könnte ich die 7Segemnt Stelle
und ggf. daraus entstandene Anzeige in ein einzelnes file schreiben udn
einfach in ein Projekt hängen. Würde das gefunden?
danke
> Müssen eine 'top' entity> definiert werden, in der alle externen Signale vorhanden sind?
Es gibt nur 1 Top-Level, der letztlich nach aussen verbunden (an Pins
angeschlossen) werden kann. Und die Pinzuordnung ist sowieso mit
manueller Arbeit im UCF-File verbunden.
> Wenn ich eine allgemeine Anzeige haben möchte ist die> Stellenzahl ja so was wie ein generic und für eine 16-Bit anzeige sind> entsprechend meh components notwendig.
Was du suchst geht in die Richtung eines Generate zusammen mit einer
Loophttp://wwwlrh.fh-bielefeld.de/vhdl_vor/VHDL_V_B.htm> Ach ja: und irgendwelche libraries muss ich noch nciht in den Kopf> nehmen?
Nein.
BTW: Libraries....
Man kanns offenbar nicht oft genug sagen ;-)
Verwende statt der herstellerabhängigen
Ich häng mich hier auch mal mit rein :)
Habe versucht, anhand des Timing-Diagramms (S. 9 DB) mein erstes Modul
zu erstellen, das dazu dienen soll, Werte vom ADC in einen
(SRAM-)Speicher zu schreiben.
(HW wird das Spartan3E-Dev Board mit dem ADC von Linear.)
Bekomme jetzt den Fehler:
> line 71: Multi-source on Integers in Concurrent Assignment.
Offensichtlich ist die Prozess-Deklaration fehlerhaft - aber ich weiß
nich weiter.
Über etwas Nachhilfe würde ich mich sehr freuen.
1. laß bloß die "shared variable" weg - ganz schlecht !
2. "counter" wird in Zeile 35 UND 60/62 ein Wert zugewiesen
genauer: in zwei verschiedenen Prozessen
genau DAS is Dein Problem...
was soll denn die arme Hardware damit Deiner Meinung nach tun?
Danke für den Tip.
Ich habe dann versucht, es soweit umzustellen, dass ...
Naja - jetzt bekomme ich diesen Fehler, wenn auch erst in der
HDL-Analyse:
> line 47: Signal aclk cannot be synthesized, bad synchronous description.
Dann dachte ich, ok, versuch es eben mit mehreren kleinen Modulen, die
dann im toplevel-Teil verbunden werden ...
Habe also nur mal die Taktleitung mit enable als entity geschrieben und
übersetzt, mit dem Resultat:
1
Compiling vhdl file "S:/win/vhdl/sr_clk_route.vhdl" in Library MyStuff.
> HW wird das Spartan3E-Dev Board mit dem ADC von Linear.
Das hat Dual-Edge FFs nur in den IO-Zellen. Du kannst sowas nicht
machen:
1
if(cs='0')then
2
aclk<='0';
3
counter:=0;
4
elsif(run='1')then<-- eine etwas ungewöhnliche Clock-Enable Beschreibung
5
if(gclk'eventandgclk='1')then<--------- solche FFs gibts nicht
6
elsif(gclk'eventandgclk='0')then<--------- innerhalb des FPGAs
7
endif;
8
endif;
Am einfachsten könntest du den Takt gclk mit einem DCM verdoppeln und
dann nur mit der steigenden Flanke arbeiten.
Das hier ist eine ganz üble asynchrone Rücksetzerei und wird dich noch
einige Haare kosten:
1
if(cs='0')then
2
:
3
elsif(counter<3)then
4
:
5
elsif(counter=16orcounter=32)then
6
:
7
elsif(counter=17orcounter=33)then
8
:
9
elsif(counter=19orcounter=35)then
10
:
11
elsiffalling_edge(gclk)then
12
lpm_sr<=lpm_sr(14downto0)&adata;
13
endif;
Denn schon der kleinste Glitch beim Übergang von einem Zählerwert zum
nächsten kann recht unverhoffte Dinge hervorrufen. Wenn dein Zähler z.B.
gerade mal von 15 nach 16 zählt, dann könnte das so aussehen:
001111 -> 000000 -> 010000
Der Zählerwert 0 ist zwar nur ein Bruchteil einer ns zu sehen, aber er
ist da. Und wenn deine Abfrage (counter < 3) gut implementiert ist, dann
wird die zuschlagen :-o
Dann machs doch besser so:
1
iffalling_edge(gclk)then
2
if(cs='0')then
3
:
4
elsif(counter<3)then
5
:
6
elsif(counter=16orcounter=32)then
7
:
8
elsif(counter=17orcounter=33)then
9
:
10
elsif(counter=19orcounter=35)then
11
:
12
endif;
13
lpm_sr<=lpm_sr(14downto0)&adata;
14
endif;
Das ist synchron und Glitches können sich dadurch nicht auswirken.
Hallo Lothar,
danke für Deine Unterstützung!
Das mit dem Counter ist eine Unachtsamkeit. Du hattest es mir ja schon
mal geschrieben. Sorry - ich habe es noch nicht ganz verinnerlicht, aber
gelobe Besserung :)
Bei dem Takt habe ich vermutlich einen Denkfehler. Das 'sr_adc' sollte
ein Modul werden, welches ich später in einem neuen top-level verwenden
kann.
Für das Modul habe ich mir so vorgestellt, dass der Takt von außen (über
DCM oder wie auch immer) erzeugt wird, dass also quasi der Anwender von
sr_adc den Takt anhand der gewünschten Samplerate festlegt.
Innerhalb des Moduls wollte ich den Takt ein und ausschalten können -
eben nach Vorgabe des ADCs. Ich fände es jetzt extrem suboptimal, wenn
ich bei Verwendung des Moduls den doppelten Takt vorgeben, bzw. erzeugen
müsste.
Gibt es noch eine andere Möglichkeit, den Takt bedingt weiter zu
reichen, ohne ein Dual-Edge-FF verwenden zu müssen?
> Ich fände es jetzt extrem suboptimal,
Naja, wenn es nicht implementiert werden kann, ist es m.E. noch deutlich
suboptimaler :-/
> Gibt es noch eine andere Möglichkeit, den Takt bedingt weiter zu> reichen, ohne ein Dual-Edge-FF verwenden zu müssen?
Machs doch auf die harte Art mit einem Mux (Stichwort: Gated Clock). Das
mußt du dann zwar gut im Auge behalten, aber machen kann man das schon:
Puh, jetzt ist meine Verwirrung komplett :(
Ein Mux war für mich ein Selections-Element, um von mehreren Eingängen
einen auszuwählen, der dann den Ausgang treibt, bzw. darstellt.
Ein Element mit einem Eingang und einem Ausgang ist auch ein Mux?
Was ist dann bitte schön ein Mux?
... und gated clock - war das nicht etwas, was man vermeiden sollte?
Würdest Du mit halbiertem Takt arbeiten, oder wie würdest Du die
Aufgabenstellung angehen?
> Was ist dann bitte schön ein Mux?
Du hast die Antwort vor der Frage gegeben:
> Ein Mux war für mich ein Selections-Element, um von mehreren Eingängen> einen auszuwählen, der dann den Ausgang treibt, bzw. darstellt.
Also: Ein Mux ist ein Element mit mindestens 2 Eingängen, mindestens 1
Selektionseingang und genau 1 Ausgang.
> Ein Element mit einem Eingang und einem Ausgang ist auch ein Mux?
In meinem Beispiel wählt der Mux zwischen einem Signal gclk und einer
'0' aus. Also wie du schon beschrieben hast: es wird aus 2 Signalen
ausgewählt.
Du kannst jede kombinatorische Funktion mit einem Mux ausführen. Die
LUTs in einem Spartan 3 FPGA sind nichts anderes als ein 16:1 Mux. Und
die können jede logische Funktion mit bis zu 4 Eingängen abbilden.
> ... und gated clock - war das nicht etwas, was man vermeiden sollte?
Ja, schon. Schön ist das nicht...
Aber wenns irgendwann mal nicht anders geht ;-)
> Würdest Du mit halbiertem Takt arbeiten,
Ja.
> oder wie würdest Du die Aufgabenstellung angehen?
Oder den doppelten Takt (via DCM) einspeisen.
Anfänger schrieb:
> Hallo Lothar,>> danke für Deine Geduld!>> Nur um ganz sicher zu gehen, dass ich's auch verstanden habe:>
1
aclk<=gclkwhenrun='1'else'0';
>> Diese Anweisung ist also ein Mux und wird immer dann ausgeführt, wenn> sich gclk oder run ändert?
Das ist reine Kombinatorik, also einfach ein paar Gatter. Sauber kann
man sowas auch mit einem BUFGMUX machen, oder aber versuchen, zu
Umschiffen...muss denn der ACLK unbedingt abgeschaltet werden? Bei den
allermeisten SPI Slaves kann der duchlaufen...
Lothar Miller schrieb:
>> Bei den allermeisten SPI Slaves kann der duchlaufen...> Dann muß aber der SS zum richtigen Zeitpunkt kommen.
Natürlich. Bei den SPI-ADCs, die ich benutzt hab, startet die steigende
Flanke des CS die Wandlung, die fallende startet das Auslesen,
dazwischen ist die Wandlungszeit zu beachten. Lässt sich wunderbar über
einen durchlaufen Zähler machen...
Hallo Ihr beiden Supercracks :)
verzeiht, aber ich habe Eure Erfahrung net. Insofern habe ich auch keine
Ahnung, wie man sonst SPI-ADCs ansteuern würde. Freiwillig würde ich mir
kein SPI-ADC antun, insbesondere nicht in Zusammenhang mit einem FPGA -
aber es ist nunmal drauf, dann macht es sicher auch Sinn, es zu
verwenden ;)
Beim LTC1407 gibt es kein CS und ich kann nur sagen, dass ich das Modul
anhand des Timing-Diagramms erstellt habe.
Den Takt einfach durchlaufen zu lassen und auch intern zu verwenden habe
ich genausowenig hinbekommen, wie den Takt über den oder das MUX.
Deshalb hat die jetzige Variante also den Takthalbierer.
Die Synthese läuft durch, aber das Ergebnis ist alles andere als
berauschend. Gut, ich kann nicht beurteilen, ob und schon garnicht wie
es besser geht, aber das was rauskommt sieht für meine Begriffe grausig
aus.
Die Zeiten deuten auch auf eine eher suboptimale Lösung hin, denn max.
80 MHz würde zwar ausreichen, aber ich hätte mehr erwartet.
Der RTL-Viewer will ne Tapete erzeugen, die zum Tapezieren eines
Fußballstadions reichen würde ... :(
Deshalb meine Frage:
- So wie es aussieht, werden für die Variablen auch Logikelemente
erzeugt. Was ist dann der Sinn, eine Variable statt einem Signal zu
verwenden?
- Wie geht man da vor, um zu sehen, was zu optimieren geht?
- Gibt es dafür Regeln, oder ist das "nur" ein Bauchgefühl der alten
Hasen?
Ich habe im Moment nur die 11er ISE unter Windows am Laufen.
Was muss ich anstellen, um die Testbench (unter ISim?) simulieren zu
können?
In der ISE sehe ich nix mehr von wegen Simulation und um das Timing zu
bestimmen, reicht die Weblizenz nicht aus - das geht wohl nur in den
kostenpflichtigen Paketen.
Wäre für weitere Tips sehr dankbar.
> LTC1407> Den Takt einfach durchlaufen zu lassen
Das liegt bei diesem Baustein auf der Hand, so ist es ja auch im DB
eingezeichnet :-/
Und dann muß nur noch das conv gesetz werden, und gleichzeitig ein
langes Schieberegister (34 Bit) gestartet. In dieses Schieberegister
wird der ganze Datenstrom eingetaktet und anschliessend weitergereicht.
Das wars dann schon...
Hach :)
Altera ist etwas großzügiger zu Anfängern. Bei denen kam auf RTL was
brauchbares zu gucken :)
Meine Fragen dazu:
run ist eine Bit-Variable. Woher kommen die run~0 ... run~4 und was sind
das für Symbole? Ist das ein 2fach MUX?
addr ist 20Bit breit definiert. Wieso gibt es dann noch addr[41..21] und
addre[62..42] ??? Was habe ich da wieder nich berücksichtigt?
Sehe gerade eine Überschneidung der Postings ...
> Und dann muß nur noch das conv gesetz werden, und gleichzeitig ein> langes Schieberegister (34 Bit) gestartet. In dieses Schieberegister> wird der ganze Datenstrom eingetaktet und anschliessend weitergereicht.
Ein (über-)langes Schieberegister ist also besser, als 2mal ein
kleineres zu füllen?
> Ein (über-)langes Schieberegister ist also besser, als 2mal ein> kleineres zu füllen?
Ja, das was du zur Verwaltung der beiden kleinen SR zusätzlich brauchst,
kannst du genausogut in das längere SR stecken.
Zumal das in VHDL ja so schön geht. Beliebig langes SR und dann zur
Weiterverarbeitung die ensprechenden Teile des Vektors heraus picken.
Byte_0 <= SR(7 downto 0);
Byte_1 <= SR(15 downto 8);
Byte_2 <= SR(23 downto 16);
usw....
Hallo,
bin inzwischen etwas weiter gekommen. Ich muss sagen, dass mir Quartus
(bislang?) anfängerfreundlicher vorkommt.
Nur mit getakten Prozessen habe ich eine Variante ausprobiert, die ein
16Bit Schieberegister 2mal ausliest und eine andere, die ein 32Bit
Schieberegister nur einmal ausliest.
die erste Variante (16Bit SR):
67 LEs, 45 Combinationsfunktionen, 53 Logikregister und 59 Pins
Als maximale Frequenz gibt Altera 148 MHz an.
die zweite Variante (32Bit SR):
62 LEs, 42 Combinationsfunktionen, 50 Logikregister und 59 Pins
Als maximale Frequenz gibt Altera 170 MHz an.
Könnte von den Gurus mal jemand drüber schauen, ob bei gleicher
Funktionalität noch Optimierungspotential ist?
Im Voraus schon herzlichen Dank.
Ach ja:
Das Signal 'aconv' wird meines Wissens nur geschrieben. Wenn ich es
jedoch als 'out' anstatt 'inout' deklariere, brauche ich mehr
Combinatorik und mehr LEs. Kann mir das vielleicht jemand erklären?
Ich habe gleiches bei den restlichen 'out' Signalen auch probiert, dort
tritt der Effekt nicht auf - im Gegenteil, es sieht genau andersherum
aus.
> o_clock : ...; -- clock line to ADC, will be internal clock too
Das ist für ein FPGA sehr unschöne Designpraxis. Du kannst nicht
(einfach so) irgendwelche Signale als lokalen Takt nehmen...
Falls du es trotzdem tust, mußt du fest mit eigenartigen Problemen
rechnen. Im FPGA arbeitet man besser mit 1 Takt und
Clock-Enable-Signalen.
> Wenn ich es jedoch als 'out' anstatt 'inout' deklariere,> brauche ich mehr Combinatorik und mehr LEs.
Das sagt die Synthese. Lass da mal P&R drüber, dann sieht das
wahrscheinlich wieder besser aus...
Hallo Lothar,
> Das ist für ein FPGA sehr unschöne Designpraxis.
da habe ich Dich ein paar Beiträge früher wohl falsch verstanden.
Als es drum ging, dem Takt noch ein enable zu spendieren, was zu einer
Frequenzhalbierung führte. Du meintest doch, ich solle mit doppeltem
Takt reinkommen und diesen dann auf ein FF mit clock-enable führen.
So habe ich es jetzt umgesetzt, nur dass mein clock-enable eben das cs
des gesamten Modules ist. Sobald das Modul aktiv ist, läuft der Takt
immer.
Auch das hatte ich von Euch so verstanden.
Wenn es falsch ist, könntest Du mir bitte mal zeigen, wie es besser
wäre?
Denn die Taktleitung einfach fest mit dem Ausgang zu "verdrahten" hat ja
auch nicht geklappt.
>> Wenn ich es jedoch als 'out' anstatt 'inout' deklariere,>> brauche ich mehr Combinatorik und mehr LEs.> Das sagt die Synthese. Lass da mal P&R drüber, dann sieht das> wahrscheinlich wieder besser aus...
Was ist bitte schön P&R? - Ich kenne das Kürzel nur als "Park and Ride",
was ja hier wohl nicht weiter hilft ;)
> Wenn es falsch ist, könntest Du mir bitte mal zeigen, wie es besser wäre?
Werde ich dir morgen zeigen... ;-)
Als Tipp: der Takt wird parallel auf das FPGA und auf den AD-Wandler
gegeben. Dann wird einen Takt lang das conv-Signal aktiviert. Und nach
dem Einlesen der Daten in das lange SR die Daten wie von Christian
vorgeschlagen auseinandergepfriemelt...
> Was ist bitte schön P&R?
Place and Route
Lothar Miller schrieb:
>> Wenn es falsch ist, könntest Du mir bitte mal zeigen, wie es besser wäre?> Werde ich dir morgen zeigen... ;-)> Als Tipp: der Takt wird parallel auf das FPGA und auf den AD-Wandler> gegeben. Dann wird einen Takt lang das conv-Signal aktiviert. Und nach> dem Einlesen der Daten in das lange SR die Daten wie von Christian> vorgeschlagen auseinandergepfriemelt...
Genau. Der ADC gibt seine Daten zeitigstens 8ns nach der steigenden
Flanke des SCLK aus. Das heißt, du kannst die auf jeden Fall sicher mit
der nächsten steigenden Flanke in das SR im FPGA übernehmen, da das Bit
dann auf jeden Fall noch stabil anliegt. So wird das üblicherweise
gemacht. Und wieso sind dir eigentlich 170MHz zu langsam? Der ADC
verkraftet eh nur 50,4MHz als SCLK. Wenn ich mich recht erinnere, hab
ich den 1407A glaube sogar schon mal mit einem MachXO angesteuert nach
dem o.g. Prinzip mit 50MHz. Hat zuverlässig geklappt.
> Als Tipp: der Takt wird parallel auf das FPGA und auf den AD-Wandler> gegeben.
Zum einen will ich das nicht, zum anderen ist die Platine ja fertig, da
kann ich nix mehr dran ändern.
Ja und wollen will ich es nicht, weil das ADC max. 50 MHz verkraftet,
der FPGA aber vielleicht, bzw. ganz sicher noch andere Aufgaben bekommt.
Das ADC ist also nur ein Modul von ("meinem") Professor, das bei Bedarf
aktiviert wird.
Ich gehe davon aus, dass der externe Takt für den FPGA 125 MHz beträgt.
Wie ich dann zu einem Takt von 300 MHz komme ist mir noch nicht klar,
aber das ist mein Ziel. Intern will ich das ADC-Modul dann nur mit 50
MHz, bzw. jetzt eben mit 100 MHz ansteuern (so mein Plan - ob der
realisierbar ist, muss sich zeigen).
Der ADC-Takt soll also nur dann den FPGA verlassen, wenn in meinem
"Softcore" das ADC auch aktiviert wurde - ich will ja nicht unnötigen
Dreck auf den Leitungen produzieren.
> Das heißt, du kannst die auf jeden Fall sicher mit> der nächsten steigenden Flanke in das SR im FPGA übernehmen
Hm - ich habe das DB so interpretiert, dass der ADC min. 2 Takte
braucht, bis die Umwandlung fertig ist. Erst dann beginnt die Ausgabe
der Daten, also mit dem 3. Takt - und im DB des 1407 steht, dass die
Daten bei steigendem Clock wechseln, man also bei fallendem Clock das
Bit ins Latch übernehmen soll.
> Und wieso sind dir eigentlich 170MHz zu langsam?
Kann mich nicht entsinnen, das geschrieben zu haben. Als meine erste
Variante übersetzt wurde, kamen ca. 80MHz raus - dazu schrieb ich, dass
es wohl ausreichen würde, den ADC zu treiben, dass ich es aber als
Wertung für schlechtes Design ansehe.
Ich weiß, dass die Frequenzangabe eh nur eine theoretische Daumenpeilung
ist. Aber wenn der FPGA locker über 300 MHz verkraftet, sind 170 MHz für
mich die Aussage, dass mein Entwurf ungefär einer Schulnote 3-4
entspricht.
Das hat nix damit zu tun, dass es mir zu langsam ist, sondern einfach,
damit, dass man es (sicher) noch besser machen kann.
Anfänger schrieb:
>> Das heißt, du kannst die auf jeden Fall sicher mit>> der nächsten steigenden Flanke in das SR im FPGA übernehmen>> Hm - ich habe das DB so interpretiert, dass der ADC min. 2 Takte> braucht, bis die Umwandlung fertig ist. Erst dann beginnt die Ausgabe> der Daten, also mit dem 3. Takt - und im DB des 1407 steht, dass die> Daten bei steigendem Clock wechseln, man also bei fallendem Clock das> Bit ins Latch übernehmen soll.
Naja kann man machen, ist aber hier Unsinn. Denn die Ausgabe erfolgt
garantiert nach der Flanke. In Note 12 auf Seite 4 des Datenblattes
stehts extra drin, dass du die steigende Flanke zum Einsammeln nehmen
sollst.
Das einfachste ist ein synchroner Zähler mit synchroner(!) Rücksetzung,
der immer von 0 bis 33 durchläuft. Dessen Zählausgänge nimmst du dann
für die kombinatorische Erkennung des Zustandes, ob du das CONV ausgeben
musst oder Datenwort einlesen musst.
Wenn die HW fertig ist, ist das beste, den Takt einfach so auszugeben.
Da du ja aus deinen 125MHz die 50 erzegen willst, bist du ja eh hinter
einem DCM o.ä. da geht das problemlos. Wenn man bei der Ausgabe eines
Taktes die maximale Performance rausholen will, kann man auch ein
DDR-FlipFlop dafür einbauen, ist aber meist nicht nötig, und wenn dann
nur bei DDR-Verbindungen mit hohen Frequenzen.
> dass die Daten bei steigendem Clock wechseln ...
Die Daten wechseln nach dem steigenden Clock (bzw. wegen der
steigenden Flanke). Also ist genau diese Flanke diejenige, an der die
Daten vorher sicher stabil anstehen. Und damit sollten sie auch genau
mit dieser Flanke eingetaktet werden.
Zu deinem Design:
Der Ansatz ist nicht schlecht, aber die Sache mit dem
> if (cs = '0') then
würde ich doch ein wenig anders machen: erst mal den Zyklus komplett
fertig, und dann wieder den CS abfragen. Denn was wäre, wenn mitten im
Wandeln oder Schreiben einfach jemand kurz mal den CS wegnimmt?
Sieh dir mal meinen Ansatz an.
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.NUMERIC_STD.ALL;
4
5
entityLTC1407is
6
Port(clk50:inSTD_LOGIC;
7
cs:inSTD_LOGIC;-- chip-select: ADC starts with setting cs high
8
frc:inSTD_LOGIC;-- free running conversion (high) or single shot (low)
9
sck:outSTD_LOGIC;
10
conv:outSTD_LOGIC;
11
sdo:inSTD_LOGIC;
12
nWE:outSTD_LOGIC;-- negated write enable (memory)
13
oChA:outSTD_LOGIC_VECTOR(15downto0);-- channel A result data from ADC
14
oChB:outSTD_LOGIC_VECTOR(15downto0);-- channel B result data from ADC
15
oaddr:outSTD_LOGIC_VECTOR(19downto0));-- self incrementing memory address in free running mode
16
endLTC1407;
17
18
architectureBehavioralofLTC1407is
19
signalcnt:integerrange0to41:=41;
20
signalsr:std_logic_vector(27downto0);
21
signaldoADC:STD_LOGIC:='1';
22
SIGNALacnt:integerrange0to(2**20)-1;
23
begin
24
sck<=clk50;-- Takt durchreichen, mit constraints sicherstellen, dass das Timing passt
25
26
processbegin
27
waituntilrising_edge(clk50);
28
-- Wandlung läuft
29
if(cnt<41)then
30
cnt<=cnt+1;
31
endif;
32
-- Daten einfach durchschieben, werden bei Zählerstand 32 gespeichert
33
sr<=sr(sr'left-1downto0)&sdo;
34
-- Zustände auswerten
35
casecntis
36
when0=>conv<='1';
37
when1=>conv<='0';
38
when32=>oChA<=x"0"&sr(27downto16);
39
oChB<=x"0"&sr(11downto0);
40
oaddr<=std_logic_vector(to_unsigned(acnt,20));
41
when33=>nWE<='0';
42
when40=>nWE<='1';
43
doADC<=frc;
44
acnt<=acnt+1;-- Autoincrement
45
when41=>if(cs='1'anddoADC='1')then
46
cnt<=0;
47
endif;
48
if(cs='0')then
49
acnt<=0;
50
doADC<='1';-- nach steigender Flanke CS mindestens 1 Wandlung;
51
endif;
52
whenothers=>NULL;
53
endcase;
54
endprocess;
55
endBehavioral;
Möglich, dass die eine oder andere zahl noch angepasst werden muß. Es
geht mir um den Ansatz...
BTW:
Du könntest dir die Leerlaufzeit (cnt= 33..41) sparen, wenn du das
Speichern während der Wandlung machen würdest (Gedankenskizze im
Anhang).
> In Note 12 auf Seite 4 des Datenblattes> stehts extra drin, dass du die steigende Flanke zum Einsammeln nehmen> sollst.
Die ist mir vor Deinem Nasenstubser zwar raus, aber selbst jetzt würde
ich es nicht unbedingt so interpretieren ;) - aber Du hast ja trotzdem
recht!
> Wenn man bei der Ausgabe eines> Taktes die maximale Performance rausholen will, kann man auch ein> DDR-FlipFlop dafür einbauen, ist aber meist nicht nötig, und wenn dann> nur bei DDR-Verbindungen mit hohen Frequenzen.
Auch wenn das noch Zukunftsmusik ist, spätestens dann, wenn das Ethernet
tut, will ich in die Richtung. So wie ich Lothar verstanden habe, hat
der Spartan DDR-FFs nur an den IO-Ports. Wenn Du mir also einen Tipp
hättest, wie ich die trotzdem verwenden kann, wäre ich Dir sehr
verbunden!!!
> Zu deinem Design:> Der Ansatz ist nicht schlecht, aber die Sache mit dem>> if (cs = '0') then> würde ich doch ein wenig anders machen: erst mal den Zyklus komplett> fertig, und dann wieder den CS abfragen. Denn was wäre, wenn mitten im> Wandeln oder Schreiben einfach jemand kurz mal den CS wegnimmt?
Puh - jetzt gibst Du es mir aber!
Danke Dir Lothar, für die viele versteckten Tutorials! - Dein Beispiel
hat mir mehr gebracht, als stundenlanges Tutorial-Lesen :)
... und nach der Steilvorlage konnte ich mein Modul endlich variabel
gestalten. Herzlichen Dank für die viele unerwähnten Tips!
Deine Variante der cs-Behandlung war auch schwere Kost. Anfangs dachte
ich, Deine Variante hat ja garkein Reset und würde immer wandeln. Bis
dann der Herr Osram ein Einsehen hatte :)
Das war mir dann doch zu schwere Kost und ich dachte, ich versuche mal
die restlichen Deiner Tips umzusetzen und schau mal, was die Synthese
ausspuckt.
Vom Ergebnis war ich dann doch heftig überrascht.
Meine Variante braucht 2 FFs mehr, ist aber trotzdem schneller (288 MHz
zu 330 MHz) - und mit dem Wert, meiner Einschätzung nach, reif für die
Profiliga :)
Kann es sein, dass das 'wait' nicht so gut umgesetzt wird, wie die
Abfragen im getakteten 'if'?
> Du könntest dir die Leerlaufzeit (cnt= 33..41) sparen, wenn ...
Den Ansatz hatte ich schon mal verfolgt, aber ich war nicht zufrieden
mit dem Ergebnis. Genauso wie ich das mit dem Takt durchreichen auch
schon probiert hatte.
Weiß nicht, warum er es letztens mit "illegal synchronous ..." abgelehnt
hatte. Jetzt scheint es ja zu funzen.
Bei Altera gehört der P&R-Schritt mit zum Übersetzungsprozess - wird
also immer ausgeführt. Heute habe ich den in der ISE auch mal angestoßen
und - oh Schreck, oh Graus! - laut Fehlermeldung wird der 1600er vom
Spartan3E mit der Webpack-Lizenz nicht abgedeckt, d.h. ich kann den Chip
also garnicht beschreiben?!?
Das ist ja extrem ätzend! - Gibt es freie Alternativen, oder muss ich
das Board stornieren?
Hallo Chris,
danke für Deine Unterstützung!
> WebPack deckt alle Spartan 3e ab: ...
Sorry, mein Fehler. Habe mir gestern extra noch das Update auf 11.2
installiert, aber erst heute, als das Board kam und ich die Chipnummer
verglich, fiel mir auf, dass ich den falschen Spartan ausgewählt hatte.
Die Auswahl ist ja mehrstufig, also erst Spartan 3E - als Familie, dann
das Modell. Der erste 1600E war leider aus der automotive serie :(
Wenn man's weiß, kann man es auch am 2. Buchstaben erkennen.
Ich hatte den XA3S1600E ausgewählt, dabei ist auf dem Board ein
XC3S1600E (wenn das 'A' für automotive steht, dann steht 'C' ja wohl für
cute).
Hallo, ich beschäftige mich noch nicht sehr lange mit VHDL und wäre
deshalb froh, wenn mir jemand ein paar syntaktische Sachen erklären
könnte.
Bsp 1.
1
ifx>='0'andx<='10'then
2
...
der <= Operator ist normalerweise eine Zuweisung. Gibt es für "kleiner
gleich" einen speziellen Operator, oder sind während Bedingungen in VHDL
keine Zuweisungen erlaubt ? (in C/java etc. wäre if x=5 immer true und
x wird 5 zugewiesen)
Bsp 2 von oben:
> Gibt es für "kleiner gleich" einen speziellen Operator,
ja, das <=
> oder sind während Bedingungen in VHDL keine Zuweisungen erlaubt ?
Solche Schmutzprogrammierereien, wie sie in C möglich sind, werden in
VHDL ausgeschlossen. Wenn eine Bedingung abgefragt wird, kann nicht
gleichzeitig zugewiesen werden.
> when 0 => conv <= '1';
Das => folgt einfach auf ein when, wenn das when in einem case steht
;-)
Und das <= ist hier eine Zuweisung.
Es gibt einfach Syntaxvorschriften, die eingehalten werden müssen. Und
in VHDL werden die besonders rigide abgefragt und überwacht.
BTW:
Nochn Pfeil:
1
vect<=(others=>'0');
auch das
others => '0' ist einfach ein feststehender Begriff, der wie ein
others => '1' fix zusammengehört.
Man könnte in dem obigen Beispiel auch so schreiben:
1
vect<=(0=>'1',others=>'0');
Damit wäre dann das Bit 0 gesetzt, die anderen Bits zurückgesetzt.
Ich verzweifel gerade an der Ansteuerung einer Hex Anzeige:
1 Nibbel hat geklappt, weshalb ich den Zahlenbereich auf ein ganzen Byte
ausdehnen wollte - klappt aber nicht.
1
anzeigen:process(clk3k_int)
2
variablen:integerrange0to1;
3
begin
4
5
if(rising_edge(clk3k_int))then
6
n:=n+1;
7
--aktuelle Stelle auswählen
8
casenis
9
when0=>an<="1110";
10
when1=>an<="1101";
11
whenothers=>an<="1111";
12
endcase;
13
--case cnt_int(3 downto 0) is
14
casecnt_int((4*(n+1)-1)downto(4*n))is
15
when"0000"=>seg<="0000001";
16
when"0001"=>seg<="1001111";
17
when"0010"=>seg<="0010010";
18
when"0011"=>seg<="0000110";
19
when"0100"=>seg<="1001100";
20
when"0101"=>seg<="0100100";
21
when"0110"=>seg<="0100000";
22
when"0111"=>seg<="0001101";
23
when"1000"=>seg<="0000000";
24
when"1001"=>seg<="0000100";
25
when"1010"=>seg<="0001000";
26
when"1011"=>seg<="1100000";
27
when"1100"=>seg<="0110001";
28
when"1101"=>seg<="1000010";
29
when"1110"=>seg<="0110000";
30
when"1111"=>seg<="0111000";
31
whenothers=>seg<="0000000";
32
endcase;
33
endif;
34
endprocessanzeigen;
ist denke ich der relevante Teil. Der Fehler ensteht in der Zeile mit
dem dekodier switch einer Stelle: Selector (Slice name of type
std_logic_vector) is an unconstrained array.
Wie macht man das besser bzw richtiger? Oder denke ich insgesamt zu
c-mäßig? Bin bis eben ganz zufrieden gewesen mit mir :-( Und wenn ich
nicht versuche die Nibbel zu den Stellen auszuschneiden, bekomm ich auch
die 2 gewünschten Stellen - halt dann nur das selbe.
Außerdem die takt geschichte der clk3k_int wird aus einem taktteiler
genommen. Im anderen Thread wurde explizit davor gewarnt so etwas als
richtigen Takt zu benutzen. Ist das hier auch so? bei ca 3 kHz oder ist
das eine Prinzipfrage.
danke und gute Nacht
> Bin bis eben ganz zufrieden gewesen mit mir
Naja, na gut, na sowas:
1
variablen:integerrange0to1;-- n kann also nur 0 und 1 werden!
2
:
3
:
4
n:=n+1;-- was passiert, wenn n=1 ist?
5
-- der Überlauf ist nicht sauber abgefangen :-(
BTW:
1
ifrising_edge(clk3k_int)then
Das gibt mir ein wenig zu Denken...
Wieviele Takte hast du denn in deinem FPGA-Design?
> der clk3k_int wird aus einem taktteiler genommen.> wurde explizit davor gewarnt so etwas als Takt zu benutzen.> Ist das hier auch so? bei ca 3 kHz oder ist das eine Prinzipfrage.
Ja. Als und für Anfänger gilt die zwingende Regel:
Genau 1 Takt im ganzen Design.
In deinem Fall wäre das besser so gelöst:
Warum multiplext du deine 7 Segmente eigentlich mit 3 kHz? Da kommen ja
kaum die Transistoren hinterher. Hast du nicht irgendwelche Schatten,
Geistersegmente...?
Danke erst mal, werde mir alles wie gewohnt in Ruhe zu Gemüte führen.
Ja stimmt - es gibt nur 0 und 1 für die Stellen. Momentan. Ich dachte um
auf 4-stellig zu erweitern, wäre ein integer ganz gut schon eingeplant
zu sein. Und daß der Überlauf 'automatisch' korrekt wird, hatte ich auch
gedacht.
Ich habe in dem Design 3 Takte. Den 50 MHz Bordtakt, einen paar Hz
zähltakt...naja und einen willkührlichen 3 kHz Multiplextakt. Werde den
dann wohl auch schleunigst verringern. Danke für den Einwurf.
Warum ich mehrere takte habe und nicht einen fragst du dich. Nun das
liegt daran, daß ich versucht habe, alle modularisieren. Sprich auf ein
Display Modul hinzuarbeiten, was einfach einen Eingänge hat, die ich
nachher als component beliebig verdrahten kann. In anderen Designs.
Ich bin aber überzeugt, daß es besser ist auch die multiplexzeiten
direkt im Display Modul zu bestimmen. Mit Zähler und Systemtakt.
Ich bin um alle Kritik dankbar - ist ja auch nicht zu vermeiden. Es wird
ja gerne davon gesprochen, daß man als Anfänger eh durch alle Fallen
laufen muss und einige Fehlersuche wegstecken muss. Da habe ich halt das
Problem: kein Prof, keine Kollegen o.ä., die überhaupt erst mal um die
theoretischen Fehlerquellen und Gegenmaßnahmen wissen...sprich wenig
externen Input um techniken und potentielle Fehler, da ist das Forum
hier die einzige Quelle. :-) Naja zudem ist mein Gehirn ja auch nicht
mehr das jüngste so daß neue Denke..sagen wir mal langsamer
verinnerlicht wird.
Ach ja: anhand des Beispiels sehe ich, wie du mit nur einem Takt umgehst
und ich werde versuchen, das in meine Denkweise zu übernehmen. Wie
gesagt: ursprünglich dachte ich es wäre weise, jedem Einzelmodul einen
Takteingang zu verpassen, der dann beliebig einfach zugeführt wird.
Ich sehe das als ersten Lernschritt ;-) Denn Einsicht ist... Obwohl mir
nciht wirklich bildlich klar ist, was da schiefgeht.
Ich vermute sobald da eine Erleuchtung einsetzt kann man auch sagen, es
wären mehrere Takte handhabbar.
Besten Dank noch mal!
> Obwohl mir nciht wirklich bildlich klar ist, was da schiefgeht.
Wenn du diesen Takt mit einem DCM aus dem Haupttakt ableitest, geht das
gut. Wenn du den allerdings aus einem Zähler ableitest, dann hast du je
nach Platzierung auf dem FPGA unteschiedliche Laufzeiten der Takte
(Skew). Und die können sich mit jeder kleinen Änderung des Designs
mitändern. Das gibt dann so urige Fehlerbilder, dass ganz ein anderes
Modul von irgendeiner klitzekleinen Änderung betroffen ist :-o
Also bei obigem Ansatz handelt es sich ja dann um diese erwähnte clock
enable Geschichte. Werde das in zukunft erst mal so handhaben.
Aber einmal nachfragen müsst ich noch zum allgemeinen Verständnis der
fpga. Angenommen ich habe in einem Design dann mehrere Komponenten, die
einen stark geteilten Takt benötigen: dann wäre es auch angeraten, in
JEDER Komponente die teilung durchzuführen und den system takt allen
Komponenten einzuspeisen? Ich sehe da dann im Prinzip unnötig viele
flipflops die dann benutzt werden. Denn jede Teilung verschlingt ja
einige. (hatte mir gedacht von Anfang an möglichst viel als Komponenten
zur Verfügung zu haben um die dann in neuen test Designs einfach
verschalten zu können) Ist das erst mal egal und das fpga muss sonst
einfach größer werden? klar das ist erst mal egal, aber ich meine jetzt
auch mittelfristig und theoretisch gerechnet :-) Hätten so viele Teiler
FFs auch schlechten Einfluss auf timings bei großen designs, weil alles
'weiter' auseinander gerät?
Wie gesagt: mehr prinzipiell und auf Zukunft gerechnet, daß ich derzeit
andere Probleme habe ist ja klar.
> dann wäre es auch angeraten, in JEDER Komponente die teilung> durchzuführen und den system takt allen Komponenten einzuspeisen?
Es wird (um den Syntax gleich richtig zu verwenden) kein Takt geteilt,
sondern ein Enable erzeugt. Dieses Enable-Signal ist immer nur 1
Taktzyklus lang.
> Ich sehe da dann im Prinzip unnötig viele> flipflops die dann benutzt werden.
Natürlich könntest du einen Enable-Generator bauen, und die Enables
jedem Modul zuführen. Aber i.A. hat es sich bei mir bewährt, den Takt
dort zu verwalten, wo er gebraucht wird.
BTW: Du hast im FPGA so viele Flipflops, dass du niemals alle verwenden
kannst ;-)
> Hätten so viele Teiler FFs auch schlechten Einfluss auf timings> bei großen designs, weil alles 'weiter' auseinander gerät?
Solche Laufzeit-Fragen werden über Timing-Constraints geregelt ;-)
Wenn nötig, werden irgendwelche FFs von der Toolchain verdoppelt,
bzw. wenn möglich zusammengefasst.
ok noch ein verzweifelter Versuch dann muss ich mir glaub ich
eingestehen dafür vielleicht einfach nicht tauglich zu sein....
Warum funktinoiert das nicht? Rein synthaktisch schon nicht bei der
unteren Zuweisung wo ich gern die Richtung anpassen würde gibt es
irgendwas illegales. Unexpected LE.
das kann doch an sich nicht so schwer sein dachte ich. OK vielleicht
unnötig kompliziert, aber nach der Starthilfe hatte ich den Anspruch die
Schnipsel zu etwas vermeindlich leichtem zusammenfügen zu können :-(
Ich habe das jetzt so hingedengelt. Es macht was es soll, ich bin
dennoch recht enttäuscht nicht der Kapitän im Boot zu sein.
Wie erschlage ich das Problem sinnvoll? Woher kam obige Meldung, denn
die habe ich nicht wegbekommen.
und: ist das normal oder sollte ich doch lieber etwas anderes machen
statt mich ohne zu müssen mit dieser Materie auseinander zu setzen?
Wissenshunger kann böse nagen, wenn man ihn nicht stillen kann....
Sowas sollte man nicht machen, wenn man nicht genau weiß, was man da
tut. Das gibt ein Latch!!!
Und hinter einem Latch!!! stehen immer ein paar Ausrufezeichen...
Denn wenn das Steuersignal (leds_int(0 bzw. 7)) eines Latches!!! einen
Spike enthält, na gut, dann schlägt das Ding zu, oder auch nicht :-o
Zudem ist das Ding nur zu sich selbst synchron.
Beschreib das deine Richtungsumschaltung getaktet in einem Prozess, das
ist der richtige Weg (so ähnlich, wie du es gemacht hast):
1
process(clk)begin
2
if(rising_edge(mclk))then
3
if(leds_int(7)='1')thenupdown<='1';
4
elsif(leds_int(0)='1')thenupdown<='0';
5
endif;
6
endif;
7
endprocess;
Das wäre die direkte Umsetzung deines originalen Codes.
Aber du hast doch auch eine Lösung gefunden, ist doch gut ;-)
Nur hast du in deinem Code einen ganzen Shift-Clock Latency mit drin:
> if(leds_int(6)='1') then> if(leds_int(1)='1') then
Alternativ könnte man es auch so schreiben, wenn man den "funktionalen"
Ansatz nicht mag:
1
module led_shifter(
2
output reg [LED_BITS-1:0] leds,
3
input clk,
4
input reset);
5
6
parameter CLK_DIV = 5;
7
parameter DIV_BITS = 3;
8
parameter LED_BITS = 8;
9
10
reg [DIV_BITS-1:0] counter;
11
reg up_down;
12
reg [LED_BITS-1:0] next_leds;
13
reg next_up_down, step;
14
15
always @(*)
16
if (counter == CLK_DIV)
17
step = 1;
18
else
19
step = 0;
20
21
always @(*)
22
if (leds[0])
23
next_up_down = 1;
24
else if (leds[LED_BITS-1])
25
next_up_down = 0;
26
else
27
next_up_down = up_down;
28
29
always @(*)
30
if (next_up_down)
31
next_leds = leds << 1;
32
else
33
next_leds = leds >> 1;
34
35
always @(posedge clk)
36
if (reset || step)
37
counter <= 0;
38
else
39
counter <= counter + 1;
40
41
always @(posedge clk)
42
if (reset) begin
43
leds <= 1;
44
up_down <= 1;
45
end else if (step) begin
46
leds <= next_leds;
47
up_down <= next_up_down;
48
end
49
50
endmodule
Ich hab mich noch nicht entschieden, was mir besser gefällt. Die erste
Veriante gerantiert, dass man keine Latches baut. Die zweite Veriante
scheint weiter verbreitet zu sein, oder?
gemach, gemach...
du kannst die ADA Programmierer hier nicht mit deinem C-Code
(==portierbarer Assembler) ueberfallen :o)
Die erste Variante ist definitiv besser zu verstehen, auch wenn du bei
den 'assign' schon in die Trickkiste greifst. Unter VHDL ist das alles
deutlich langatmiger zu beschreiben, hat aber den Vorteil, dass es auch
nach Jahren noch sofort verstaendlich wird. Bei Verilog muss man sich
dann schon gaaaanz genau den Code anschauen. Aber ich mag' Verilog auch,
hat schon was....
> Ich hab mich noch nicht entschieden, was mir besser gefällt. Die erste> Veriante gerantiert, dass man keine Latches baut. Die zweite Veriante> scheint weiter verbreitet zu sein, oder?
Welche Lösung braucht weniger Ressourcen?
> ...Veri-ante...
Kommt das von Vari-log?
Korrekt wäre: Variante, Verilog ;-)
> Die erste Variante ist definitiv besser zu verstehen, auch wenn du> bei den 'assign' schon in die Trickkiste greifst.
Naja, Du meinst, meistens wird einfach
1
wire foobar = ...;
anstatt
1
wire foobar;
2
3
...
4
5
assign foobar = ...;
geschrieben?
Ansonsten finde ich das nicht sonderlich "trickreich". Vielleicht liegt
es daran, dass ich schon einiges in funktionalen Sprachen geschrieben
habe und "assign" einfach als "Bindungs-Operator" verstehe. Verilog mach
ich aber erst seit 3 Wochen.
> Welche Lösung braucht weniger Ressourcen?
Beide Lösungen sind (bis auf einen kleinen Fehler, wer findet ihn?)
absolut identisch.
Ich reihe mich mal ein:
Ist es möglich 2 Pins gleichzeitig in einer IF- oder Select-Anweisung
abzufragen? Habe iwie kein passendes Bsp im Netz gefunden.
habs schonmal mit
if(pin1='1' & pin2='1') then
und
if(pin1='1' and pin2='1') then
probiert, funzt aber nicht....
die Pins sind als "inout" deklariert....
Jey Soon schrieb:> Ist es möglich 2 Pins gleichzeitig in einer IF- oder Select-Anweisung> abzufragen?
Ja. Dein Problem liegt irgendwo anders.
> if(pin1='1' & pin2='1') then
Das geht nicht, weil das & der Verknüpfungsoperator ist.
So ginge es wieder:
> if(pin1&pin2 = "11") then> die Pins sind als "inout" deklariert....
Wozu das?
Ist es wirklich ein IO-Port?
Oder bist du nur schreibfaul?
sry,
es sind natürlich reine IN-Ports, ich möchte sie als Hand-Signal für ein
Handshake benutzen
und: Danke für die Antwort
sry für Doppelpost, mein Browser hat sich wohl verhaspelt
Mir fällt rückblickend auf das Beispiel mit dem spi ADC oben auf, daß
Lothar Miller wieder super geholfen hat.
Ich frage mich nun aber, warum dort nun cs als externes Signal keine
Eintaktung erfahren muss. Sdo kommt ja in ein Schieberegister rein, das
leuchtet mir da noch ein, aber weshalb darf cs einfach so abgefragt
werden?
danke!
Clemens M. schrieb:> aber weshalb darf cs einfach so abgefragt werden?
Bezogen auf den Beitrag "Re: Der vhdl-Schnipsel-Anfängerfragen Thread"
Sollte/dürfte eigentlich nicht so sein... :-/
Aber ehrlich gesagt war der Code da so verwurstelt, dass mir das nicht
aufgefallen ist... ;-)
> aber weshalb darf cs einfach so abgefragt werden?
Nur, wenn es als Takt verwendet wird ;-)
Denn dann muß dort vom Hardware-Design eine brauchbare Signalqualität
garantiert werden, und dann ist es zu sich selber garantiert synchron...
;-)
Hallo,
ich hoffe dies ist der richtige Thread um eine Anfängerfrage zu stellen
:)
Wenn ich in einem VHDL-Modul mit einem niedrigeren Takt arbeiten möchte,
z.B. um etwas für das Auge sichtbar zu machen, ist es dann korrekt, wenn
ich so vorgehe?
- Mein Modul erhält als Eingang Clock, also Boardtakt
- Im Modul erzeuge ich mir ein "Clock-Enable", dass die richtige
Frequenz hat
- Ich gucke im entsprechenden Process, ob:
1
process (Clock)
2
begin
3
if rising_edge(Clock) then
4
if Clock_Enable = '1' then
5
tu was...
6
end if;
7
end if;
Wenn ich nun zwei verschiedene langsame Takte brauche, ist es dann ok,
wenn ich in einem Modul zwei verschiedene Clock_Enable habe?
Hallo,
gleich noch eine zweite Frage in diese Richtung:
Wenn ich zwei VHDL-Module hintereinander habe. Das Erste liest Daten mit
einer hohen Frequenz ein und stellt sie am Ausgang bereit, z.B. nach
Mittelwertbildung. Das zweite Modul holt sich die Daten mit niedrigerer
Frequenz ab und gibt sie z.B. aus.
Wie schaffe ich es, dass die Module synchron sind, obwohl sind mit
unterschiedlichen Frequenzen arbeiten?
- Kann ich beiden den Systemclock geben und im zweiten füge ich
Clock_Enable ein, sodass immer noch die steigende Flanke vom Systemclock
detektiert wird, aber die Ausgabe nur läuft, wenn auch das langsamere
Clock_Enable ansteht?
Sry für die vielleicht blöden Fragen, aber ich komme eher aus der
Programmierungsecke...
Danke :)
Torben S. schrieb:> odass immer noch die steigende Flanke vom Systemclock detektiert wird
Du hast die falsche Vorstellung davon, wie deine VHDL Beschreibung in
Hardware umgesetzt wird. Eine Taktflanke wird nicht irgendwie
"detektiert", sondern der Takt geht an Takteingänge von D-Flipflops.
Du musst dir klar machen, dass es im FPGA zur Umsetzung deiner
Beschreibung genau 2 Bauteile gibt: LUTs für die Logik und Flipflops als
Speicherelemente.
Such mal hier im Forum nach meinen Postulaten. Das Wichtigste daran ist,
dass ein Anfängerdesign nur 1 Takt hat und der Rest wie von dir
beschrieben mit Clock-Enables gemacht wird.