Moin
Hab im SoPC Builder von Quartus leider nur SRAM Controller mit 32 Bits,
auf dem DE2 Board sitzt aber einer mit 16 Bits.
Nun will ich die Sache so verdrahten, dass die oberen 16 Bits in's Leere
gehen (ich weis, nicht besonders sauber, aber egal).
Die SoPC Komponente hat nun einen Eintrag ala
signal data_to_and_from_the_sram : INOUT STD_LOGIC_VECTOR (31 DOWNTO 0);
und mein DRAM
SRAM_DQ : inout std_logic_vector(15 downto 0);
Frage: Wie verdrahte ich das? Wäre es nur in oder nur out würde ich
nicht fragen, aber wie geht das mit inout?
Da wird das Synthesetool auch denken "nicht sauber" und dir massig
warnings um die Ohren hauen.
Soweit ich weiß müsste es reichen, die unteren 16 Bits zu verbinden und
zu den oberen 16 Bits tatsächlich gar nichts weiter anzugeben. Rein
formal (und in der Sim) schreibt der Core dann Z-Werte da rein und liest
sie wieder aus. In der Synthese wird es Warnings geben, dass du die
Signale zuweist aber nie verwendest. Wenn das Synthesetool gut genug
ist, dann optimiert es die oberen Signale weg (gibt ja auf den
allerwenigsten Chips on-Chip Tristate Buffer) und gut is. Wenn das Tool
schlecht ist, dann bricht es ab weil es nicht mehr weiter weiß, aber das
ist auf jeden Fall mal nen Versuch wert.
Ansonsten baust du halt einen Fake-Verbraucher für die oberen Signale
ein, z.B. ein 16er OR Gate, dessen Ergebnis du irgendwo abfragst, damit
das Tool zufrieden ist.
Mir ging es eher um die Syntax. Hab ergoogelt, dass es mit Signalnamen
im port map funktioniert, also etwa
CPU0 : nios2 port map ( ..., data_to_and_from_the_sram(15 downto
0)=>DRAM_DQ);
Aber geht das auch ohne Namen? Irgendwie muss es da ja eigentlich eine
elegante Möglichkeit geben, man hat ja nicht immer eine extra
Komponente. Wenn ich zB. 2 inout signale a und b mit unterschiedlichen
Dimensionen hab, und nur a(0) und b(0) direkt miteinander verbinden
will, muss das ja auch gehen.
Bei einem in und einem out Signal ginge ja einfach a(0) <= b(0), aber
das geht ja bei inout nicht.
In der Praxis hat das übrigens funktioniert, die oberen Bits waren auf
ffff festgenagelt, die unteren haben ihre Daten behalten. Ich glaub
Quartus zieht nicht benutzte Signale in der Standardeinstellung auf 1.
Ob da nochmal Warnungen gekommen sind weis ich nicht, der haut mir eh
schon 400+ um die Ohren, weil ich zB. keine Lastkapazitäten an den Pins
angegeben hab, die er aber für eine exakte Timing-Analyse braucht.
Morin wrote:
> Da wird das Synthesetool auch denken "nicht sauber" und dir massig> warnings um die Ohren hauen.>> Ansonsten baust du halt einen Fake-Verbraucher für die oberen Signale> ein, z.B. ein 16er OR Gate, dessen Ergebnis du irgendwo abfragst, damit> das Tool zufrieden ist.
Warnungen machen doch nichts, wenn der, der vor'm Computer sitzt sie mal
durchschaut und befindet, dass alles okay ist.
Stell mir grad vor, wie lustig das wäre, wenn ich einen extra-Pin am
FPGA hätte, bei dem das Ergebnis vom OR aus kA wieviel nutzlosen
Signalen herausgeführt werden würde, weil das Synthesewerkzeug das sonst
wegoptimieren würde und das Ganze nur, damit Warnungen nicht ausgegeben
werden ... vielleicht kann man da ja ein XOR bauen und eine LED
anschließen Grins
MfG
Thomas Pototschnig
Sinnvollerweise hängt man noch einen anderen Speicher dran (8MB SDRAM),
der volle 32 Bit breit ist und in dem dann libc und code landen.
Mir ging es nur mal um die Geschwindigkeit der verschiedenen Speicher.
Der SDRAM hat 10MB/s geschafft, der SRAM 16MB/s (trotz nur 16bit).
Onboard Speicher war genauso schnell wie SRAM, nur eben 32Bit breit und
daher 32MB/s.
> Warnungen machen doch nichts, wenn der, der vor'm Computer sitzt sie mal> durchschaut und befindet, dass alles okay ist.>> Stell mir grad vor, wie lustig das wäre, wenn ich einen extra-Pin am> FPGA hätte, bei dem das Ergebnis vom OR aus kA wieviel nutzlosen> Signalen herausgeführt werden würde, weil das Synthesewerkzeug das sonst> wegoptimieren würde und das Ganze nur, damit Warnungen nicht ausgegeben> werden
Du hast das nicht ganz richtig verstanden. Das mit dem Riesen-OR war als
Notlösung gedacht falls das Synthesetool nicht nur Warnungen ausgibt,
sondern abbricht wegen "geht nicht".
Und ja, ich traue diesen Tools inzwischen alles in der Richtung zu. Habe
z.B. schon erlebt, wie das XST ungefragt an der Schaltung
rum-"optimiert" hat und nachher seine eigenen Änderungen mit Fatal Error
angekreidet hat...
> Wenn ich zB. 2 inout signale a und b mit unterschiedlichen> Dimensionen hab, und nur a(0) und b(0) direkt miteinander verbinden> will, muss das ja auch gehen.
Hm, alles was mir dazu eingefallen ist hätte eine andere Bedeutung
gehabt als "a und b verbinden". Speziell sowas hier:
1
a(0)<=b(0);
2
b(0)<=a(0);
würde zumindest formal etwas anderes machen als die Signalzuweisung bei
Ports, und wäre für die Simulation untauglich (wie es mit der Synthese
aussieht weiß ich nicht).
Ich denke mal, die Erfinder von VHDL haben sich dabei gedacht, dass in
diesem Fall das Signal a(0) bzw. b(0) ja eigentlich nur ein Signal ist
und man deshalb gefäligst auch nur ein Signal hinschreiben soll.
Es gibt aliases. Man kann zB. schreiben
signal a : inout std_logic_vector(31 downto 0)
alias b : std_logic_vector(3 downto 0) is a(3 downto 0)
Das geht schon in die richtige Richtung, hilft mir aber bei meinem
Problem auch nicht weiter.
Das was du oben geschrieben hast, hab ich probiert. Synthesewerkzeug hat
aber gemäkelt (error) weil ich b auf sich selbst zuweise.
Aber eigentlich kann es doch nicht sein, dass sowas einfaches und
anschauliches nicht in VHDL gehen soll, oder? Ich konnte VHDL schon von
anfang an nicht leiden und hätte viel lieber Verilog genommen... aber so
schlecht kann VHDL ja nun eigentlich nicht sein, oder?
> Aber eigentlich kann es doch nicht sein, dass sowas einfaches und> anschauliches nicht in VHDL gehen soll, oder?
Wie gesagt, ich vermute stark dass "man" in VHDL ein einziges Signal
hinschreibt wenn nur eins gemeint ist.
> Ich konnte VHDL schon von anfang an nicht leiden und hätte viel> lieber Verilog genommen... aber so schlecht kann VHDL ja nun eigentlich> nicht sein, oder?
Wenn sich dieses Problem in Verilog ohne weiteres lösen lässt dann
schreib doch das eine Modul um das es geht in Verilog, dazu musst du ja
nicht gleich alles ändern was du schon fertig hast. Die
Synthesewerkzeuge können ja Verilog/VHDL durcheinander. Und wenn du mit
Verilog besser klarkommst dann benutz halt ab jetzt Verilog.
Ob VHDL nun gut oder schlecht ist spielt für mich praktisch keine Rolle.
Es ist halt der Standard, und gut is. Ändern kann ich es eh nicht.
Jedenfalls viel Glück bei deinem Problem!
> signal a : inout std_logic_vector(31 downto 0)> alias b : std_logic_vector(3 downto 0) is a(3 downto 0)
Es gibt keine inout Signale, sondern nur Signale, deshalb ist das
Beispiel falsch.
Nur die Ports einer Komponente können in, out oder inout sein.
In der Praxis entspricht dem inout Port ein Tri-state buffer. Hat eine
Komponente ein inout Port, so ist meist gedacht das dieses Signal direkt
an die Pins des FPGAs geht, denn nur dort befinden sich Tri-state
buffer.
Zwei Komponenten mit inout Ports innerhalb des FPGAs zu verschalten
(also wie ein interner Bus), ist unüblich, da die FPGAs meist keine
internen Tri-state Buffer haben.
Das ist kein Problem von VHDL, sondern von der zur Verfügung stehenden
Hardware.
Wenn in Deinen Beispiel die Signale
SRAM_DQ : inout std_logic_vector(15 downto 0);
die Pins vom externen SRAM sind und
data_to_and_from_the_sram dazu gedacht sind, an die externen Pins zu
gehen, dann ist
CPU0 : nios2 port map ( ..., data_to_and_from_the_sram(15 downto
0)=>DRAM_DQ);
richtig.
Ein Problem hätte man nur, wenn der Compiler nicht erlauben würde, nur
Teile des Vektors zu verbinden.
Stimmt, das inout gehört da nicht hin. Ist mir aus versehen
reingerutscht...
Wenn ich den SRAM auch im FPGA nachbilden will, beispielsweise um einen
SRAM Controller zu testen, brauch ich im FPGA 2 inout ports.
Mit einem alias ist es ja auch möglich die zu "verbinden", genau dafür
gibt es die Dinger. Nur funktioniert das halt nur von einem schmaleren
auf einen Teil eines breiteren vector, nicht umgekehrt... oder ich weis
nur nicht wie's umgekehrt geht (ok, ist ziemlich doof bei inout von
"von... auf" zu reden).
In C/C++ würd ich an der Stelle einfach einen Zeiger auf die Daten
nehmen. Dann kann jeder lesen und schreiben.
Du kannst das SRAM nicht "im FPGA nachbilden" da es im FPGA keine
bidirektionalen (inout) Signale gibt!
Ausserdem ist es auch logisch, dass man zwei inout-Ports nicht mit
einander verbinden kann. Um über einen inout-Port etwas sinnvolles (und
nicht nur das was man selbst treibt) zu lesen, muss er ja hochohmig
gemacht werden. Wenn du nun zwei inout-Ports verbindest, dann würde ja
jeder immer das treiben was am anderen anliegt. Die beiden Ports
hochohmig zu machen wäre nicht mehr möglich.
Da herrscht vielleicht ein bischen Verwirrung.
Ein inout Port ist nicht das selbe wie ein bidirektionales Signal und
muß auch nicht ein Tristate sein.
Ein inout Port einer Komponente treibt zuerst einmal das Signal, das an
die Komponente an diesem Port angeschlossen ist. Zusätzlich wird der
Wert, der sich AUSSEN an diesem Signal ergibt, in die Komponente
zurückgelesen.
Der Wert, der sich außerhalb der Komponente ergibt, muß nicht der selbe
sein, wie der den die Komponente selbst schreibt, weil eben mehrere
Komponenten das selbe Signal treiben können.
Da kommt ein Konzept von VDHL ins Spiel, das sich "resolved signals"
nennt.
Bei dem resolved signal Typ STD_LOGIC den man in der Praxis verwendet,
gibt die Kombination von 'Z' (hochohmig) und einem Wert von '1' wieder
'1'.
Das simuliert einen Bus mit 2 Komponenten, einer "treibt" hochohmig, der
andere '1' -> ergibt wieder '1'.
Da man in einem FPGA aber keine internen Tri-states zur Verfügung hat,
ist es unüblich, innerhalb eines FPGAs zwei Komponenten mit inout Ports
das selbe Signal treiben zu lassen. Das wäre dann ein interner Bus.
Was man aber macht, ist den inout Port einer Unterkomponente mit dem
inout Port (oder Signal) der sie umgebenden Komponente zu verbinden.
Dabei wird das Signal nur weitergereicht.
> Ein inout Port ist nicht das selbe wie ein bidirektionales Signal und> muß auch nicht ein Tristate sein.
In der Simulation mag das Stimmen. Für die Synthese macht ein inout-Port
nur Sinn, wenn das ganze auch als Tristate verwendet wird. Ansonsten ist
schwer zu hoffen, dass auch eine 1 anliegt, wenn man eine 1 treibt, da
alles andere einen Kurzschluss verursachen würde!
VHDL ist doch nicht nur auf synthetisierbare Sachen beschränkt. Wenn ich
zB. einen PCI Bus und eine eingesteckte PCI-X Karte simulieren will, hab
ich genau das selbe Problem, dann hängen 32 Datenleitungen in der Luft.
Wenn ich den Pins allen einzeln Namen gebe ist die Sache ja auch
überhaupt kein Problem, ich frag mich nur gerade ob VHDL wirklich die
Mittel fehlen das syntaktisch elegant auch für teile eines Vektors zu
machen.
Das ist ja weniger ein Problem ob ein VHDL Simulator/Assembler das vom
Prinzip her kann oder ob die Sprache das Konzept unterstützt, sondern ob
das auch mit teilen von Vektoren geht. Mit einzelnen Signalen ist es ja
mit alias ganz einfach.
Genau, die Frage ist eben, ob das auch port map und damit auch ohne
zusätzliche Komponente funktioniert. Für einzelne Signale und vektoren
kleiner oder gleich groß dem gegebenen inout funktioniert das per alias,
ich wüsste aber nicht wie man das mit einem größeren Signal macht.
Also:
So funktioniert die Sache problemlos, ohne das man auf das port map
angewiesen ist um das umzusetzen (muss ja nicht immer eine extra
Komponente sein).
Wenn nun aber SigC 16bits, und SigA 32bits breit sind funktioniert das
so nicht mehr. Lässt es sich dann wirklich ausschließlich über port map
realisieren?
Ich hab schon sowas probiert wie
> So funktioniert die Sache problemlos, ohne das man auf das port map> angewiesen ist um das umzusetzen (muss ja nicht immer eine extra> Komponente sein).
Dein Problem ist mir wirklich nicht klar. Geht es dir wirklich nur darum
dass Du ein Signal SigD konstruieren möchtest, damit Du
1
dummy:KompAportmap(SigD);
schreiben kannst anstelle von
1
dummy:KompA
2
portmap(
3
SigA(15downto0)=>SigC,
4
SigA(31downto16)=>SigD);
??
Das erste ist nur eine verkürzte Schreibweise, die sowieso nicht
empfehlenswert ist.
Mir geht es ganz allgemein darum, ob man ein Signal aus 2 anderen
Signalen konstruieren kann (ohne den krampfigen Umweg über port map und
eine extra Komponente).
Du hast falsche Vorstellungen von "inout".
Wie schon vorher geschrieben : es gibt keine inout Signale, Signale
haben keine Richtung !
Es geht nur darum wie man Ports einer Unterkomponente mit den Ports der
umgebenden Komponente verbindet.
Und die Beispiele hatten wir doch schon alle :
a) Port in Unterkompontente kürzer als außen :
Dein Beispiel von 14:43, auch wenn man auf SigD verzichten kann
und direkt schreiben kann
dummy : KompA port map (SigA => SigC(15 downto 0));
b) Port in Unterkomponente größer als in Hauptkomponente :
Mein Beispiel von 12:16
Willkommen im Forum: Jeder gibt seinen Senf dazu und keiner liest die
Frage, denn die ist ja nicht interessant ;)
Also: Wenn ich es richtig verstehe, dann ist gefragt, ob man bei zwei
Signalen
1
signala,b:std_logic;
die beiden so zusammenschließen kann, dass eine einzige Resolution
Function alle Treiber beider Signale zu einem Ergebnis verwurstelt
und dieses Ergebnis auf beiden Signalen zu sehen ist. Korrekt?
Ich bleibe allerdings nach wie vor bei meiner Vermutung, dass dies nicht
möglich ist und du von vornherein nur ein Signal definieren darfst wenn
nur eins gemeint ist. Klingt komisch, ist aber VHDL.
Thread lesen gehört auch dazu ;-). Es ist möglich, siehe oben "alias".
Aber alias geht nur wenn man einen Teil oder den ganzen Vektor abbildet,
den Vektor als Teil des Bildes zu benutzen geht dagegen nicht bzw. weis
ich nicht wie.
Wenn das wirklich absicht ist, bestätigt das nur meine Vorurteile gegen
VHDL ;).
> Thread lesen gehört auch dazu ;-). Es ist möglich, siehe oben "alias".
Hab ich, hab ich ;)
Alias definiert ja einen neuen Namen für ein schon vorhandenes Signal,
geht also nicht wenn schon zwei Signale vorhanden sind. Naja, immerhin
ein Teilproblem gelöst (nämlich den, dass du die Signaldefinition ändern
kannst).
> Aber alias geht nur wenn man einen Teil oder den ganzen Vektor abbildet,> den Vektor als Teil des Bildes zu benutzen geht dagegen nicht bzw. weis> ich nicht wie.
Das bringt mich aber auf eine andere Idee. Momentan definierst du einen
Vektor und willst ihn als Teil des Alias-Bildes verwenden, aber das geht
nicht. Könntest du statt dessen den Vektor "groß" definieren und einem
Teil davon per alias einen anderen Namen geben?
Also konkret das Signal als 32-Bit definieren, und dann ein alias für
die unteren 16 Bit, bzw. allgemein die "längste" Variante des Vektors
per "signal" und alle anderen per "alias" definieren.
> Wenn das wirklich absicht ist, bestätigt das nur meine Vorurteile gegen> VHDL ;).
Meine Meinung dazu steht übrigens noch: Wenn es mit Verilog einfacher
geht, dann mach es doch damit! "best tool for the job" und so weiter...
da hätte ich gar keine Hemmungen. Bin nur gar nicht so sicher, dass das
Problem da nicht auftritt.
Sorry für den Dreifachpost.
Langsam geb ich's auf ...
> Also: Wenn ich es richtig verstehe, dann ist gefragt, ob man bei zwei> Signalen>> signal a, b : std_logic;>> die beiden so zusammenschließen kann, dass eine einzige Resolution> Function alle Treiber beider Signale zu einem Ergebnis verwurstelt> und dieses Ergebnis auf beiden Signalen zu sehen ist. Korrekt?
Es geht niemals (und ganz, ganz sicher auch in Verilog nicht), dass man
die beiden Signale so verschaltet, dass alle Änderungen an b auf a
sichtbar sind und umgekehrt.
Man kann nur ein drittes Signal c erzeugen, das alle Änderungen
beinhaltet.
Das Beispiel mit Alias ist, wie oben geschrieben falsch. Alias ist nur
ein weiterer Name für (einen Teil) eines bestehenden signals; beide
Namen zeigen auf das selbe Signal. Da ist es klar dass einen Änderung
unter beiden Namen sichtbar ist.
> Wenn das wirklich absicht ist, bestätigt das nur meine Vorurteile> gegen VHDL ;).
Die Vorurteile kann ich Dir nicht nehmen, ich hab's probiert.
Ich kann Dir aber versichern, dass Du von VHDL falsche Vorstellungen
hast.
Deine Bemerkung mit dem Zeiger läßt vermuten, dass Du VHDL eher als
Programmiersprache siehst, was die Sache eben nicht ganz trifft.
Es geht letztlich nicht darum was elektrisch, sondern formal passiert.
Ob der Compiler das intern zum selben Signal auflöst oder ob man das
elektrisch zusammenschaltet ist äquivalent. Ich fang jetzt nicht damit
an, dass man VHDL auch für 'ne Touringmaschine oder einen
Kellerautomaten übersetzen könnte und dort Konzepte wie "elektrisch
zusammenschalten" garnicht existieren ;).
Wenn ich meinen eigenen VHDL Assembler anwerfe (den zwischen den Ohren)
könnte ich beim Übersetzen der Sprache ein Alias erstmal zu 2 Signalen
auflösen die ich dann elektrisch verbinde, weil es meine Zielhardware
kann.
> Das bringt mich aber auf eine andere Idee. Momentan definierst du einen> Vektor und willst ihn als Teil des Alias-Bildes verwenden, aber das geht> nicht. Könntest du statt dessen den Vektor "groß" definieren und einem> Teil davon per alias einen anderen Namen geben?> Also konkret das Signal als 32-Bit definieren, und dann ein alias für> die unteren 16 Bit, bzw. allgemein die "längste" Variante des Vektors> per "signal" und alle anderen per "alias" definieren.
Allerdings steht der Vektor vom DRAM ja schon oben in der Komponente
drinnen. Dann müsste ich dem eines der Aliase zuweisen. Vielleicht hab
ich's aber auch nicht richtig verstanden.
Meine Güte, ist es denn so schwer zu verstehen?
> Es geht niemals [..], dass man die beiden Signale so verschaltet ...
Ich hab nirgends 2 Signale vorrausgesetzt! Wenn es mit einem Alias geht,
ist mir das genauso recht, ein Alias ist kein Signal. Stell dir
meinentwegen ein Alias der Länge 32 vor, bei dem die ersten 16 Elemente
ein anderes Signal referenzieren als die letzten 16 Elemente.
> Es geht niemals (und ganz, ganz sicher auch in Verilog nicht), dass man> die beiden Signale so verschaltet, dass alle Änderungen an b auf a> sichtbar sind und umgekehrt.
1. Warum nicht? In Realität kann ich doch auch z.B. zwei an sich
getrennte Tristate-Busse einfach per Draht zusammenlöten, und dann
passiert genau das.
2. Wenn es mit zwei Signalen nicht geht, wie dann? Zwei Signale zu
verwenden war ja nur ein möglicher Lösungsansatz für das Problem.
> Das Beispiel mit Alias ist, wie oben geschrieben falsch. Alias ist nur> ein weiterer Name für (einen Teil) eines bestehenden signals; beide> Namen zeigen auf das selbe Signal. Da ist es klar dass einen Änderung> unter beiden Namen sichtbar ist.
Aber genau das ist doch gewünscht, nur wissen weder I_ H. noch ich, wie
man das Alias wie gewünscht definiert. Hilfreich wäre eine der beiden
folgenden Lösungen:
1. Den äußeren Port als 16 Bit, ein internes Dummy-Signal mit 16 Bit und
ein 32-Bit Alias, welches beide zusammenfaßt. Die innere Komponente wird
an das Alias angeschlossen.
2. Ein lokales 32-Bit-Signal, an welches die innere Komponente
angeschlossen wird. Ein äußerer 16-Bit-Port, welcher kein eigenes
Signal, sondern nur ein Alias für die unteren 16 Bits des internen
Signals ist.
> Die Vorurteile kann ich Dir nicht nehmen, ich hab's probiert.> Ich kann Dir aber versichern, dass Du von VHDL falsche Vorstellungen> hast.> Deine Bemerkung mit dem Zeiger läßt vermuten, dass Du VHDL eher als> Programmiersprache siehst, was die Sache eben nicht ganz trifft.
Wo hast du das denn rausgelesen? Ich sehe in der Bemerkung mit den
Zeigern einen Versuch, dir das Problem deutlich zu machen, welches du
scheinbar immer noch nicht verstanden hast. Gerade deshalb wäre es vllt.
angebracht, etwas weniger überheblich zu sein.
-----
@I_ H. : Ich würde an deiner Stelle nicht mehr weiter an dem Problem
rumkauen. Es sieht fast so aus, als hätte VHDL einfach keine "saubere"
Lösung parat. Ich würde statt dessen eine äußere "wrapper"-Entity bauen
(ist ja oben schon gesagt wie es damit geht) und gut is. Es lohnt sich
einfach nicht, da noch mehr Zeit reinzustecken. Wie von Klaus angedeutet
geht es mit Verilog wahrscheinlich auch nicht einfacher, aber probieren
kannst du es ja nochmal.