Forum: FPGA, VHDL & Co. Dual-Port Ram mit externem SRAM


von Jens W. (jensw)



Lesenswert?

Hallo zusammen,

ich beschreibe mal um was es geht:
Ich habe ein kleines Board gebaut, auf dem ein Atxmega, ein FPGA und ein 
externes SRAM verbaut sind. Das ganze soll ein speichergekoppeltes 
System werden. Das SRAM wird also für den gemeinsamen Datenaustausch 
verwendet.

Ziel ist es nun, im FPGA einen Memory Controller zu implementieren, der 
aus dem SRAM ein Dual Port Ram macht. Bei einer Kollision wird gar nicht 
auf das RAM geschrieben und es wird ein error ausgegeben.

Ich will das Ganze verwenden, um mich einzuarbeiten in VHDL. Also 
brauche ich keinen fertigen Code. Es geht auch nicht um den 
Zustandsautomat, der die Signale (CE, OE, WE) für das SRAM erzeugt.
Das kommt alles später noch. Da muss ich Schritt für Schritt ran.

Das Projekt habe ich euch mit angehängt und auch ein Blockschaltbild wie 
das funktionieren soll.
Ich habe versucht die Daten und die Steuersignale voneinander zu 
trennen.
Die Daten vom uC kommen wie aus den Timings (wie angehängt). Da werden 
alle Signale in Hardware schon erzeugt.

Im Block "Datenlatch" werden die Daten auf den SRAM_DATEN-Bus und den 
SRAM_ADDRESS-Bus verteilt (auf die internen Signale).
Über den Block "Steuerwerk" werden die Steuersignale zum SRAM weiter 
geleitet. Die direkten Signale zum SRAM werden dabei aus den diskreten 
Signalen von uC und FPGA generiert. Einfach über eine Look-Up Tabelle 
(die habe ich in Excel für alle Kombinationen erstellt).
In erster Näherung betrachte ich nur die Daten vom uC. Daten aus dem 
FPGA kommen auch erst später.

Ich habe für alle Blöcke eigenen Testbenches erstellt und durchlaufen 
lassen. Die laufen soweit auch.
Wenn ich nun aber alles testen will (main), dann geht es aber nicht.
Die Daten für die SRAM-Addresse kann ich nicht vorgeben. Ich habe keine 
Idee woran das liegt. In ISim bleibt das Signal "U". Also undefiniert.
Sind die Signalzuweisungen vielleicht nicht richtig? Habe ich irgendwo 
einen Dreher drin?

Vielleicht findet jemand von euch was auffälliges.
Vielen Dank euch allen!

Grüße, Jens

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


Lesenswert?

Jens W. schrieb:
> In ISim bleibt das Signal "U". Also undefiniert.
Sieh nochmal nach: das 'U' bedeutet 'uninitialized' und das wiederum 
bedeutet  dass dem Signal nie ein Wert zugewiesen wurde.

Leider kann mein Handy nichts mit der rar-Datei anfangen...

von Jens W. (jensw)


Lesenswert?

Hallo Lothar,

ja, das ist mir bekannt.
In der Testbench steht das:
1
 -- insert stimulus here 
2
    uC_n_CE <= '0';    
3
    wait for 15ns;
4
    
5
    uC_Data_Address <= "00000001";
6
    wait for 15ns;
7
    uC_ALE_2 <= '1';
8
    wait for 15ns;
9
    uC_ALE_2 <= '0';
10
    wait for 15ns;
11
    
12
    uC_Data_Address <= "00000011";
13
    wait for 15ns;
14
    uC_ALE_1 <= '1';
15
    wait for 15ns;
16
    uC_ALE_1 <= '0';
17
    wait for 15ns;
18
    
19
    uC_Data_Address <= "10100101";
20
    wait for 15ns;
21
    uC_n_WE <= '0';
22
    wait for 15ns;
23
    uC_n_WE <= '1';
24
    wait for 15ns;
25
    
26
    uC_n_CE <= '1';
Und um das Signal von uC_Data_Address geht es. Ich weise den Wert direkt 
zu und trotzdem wird das nicht übernommen. Aber nur für die Addresse. 
Die dritte Zuweisung für die Daten funktioniert.
Das verstehe ich nicht!

Grüße, Jens

von Jens W. (jensw)


Lesenswert?

Vielleicht sollte man morgen nochmal in aller Frische drüber schauen. 
Ist ja schon spät.
Ich bin mir sicher, dass das irgend ein dämlicher Anfängerfehler ist!

Trotzdem schonmal danke Lothar!

Grüße, Jens

von C. A. Rotwang (Gast)


Angehängte Dateien:

Lesenswert?

Schau dir mal das synthesereport file (*.syr) an (habs aus dem archive 
hier angehangen). Da sind IMHO zuviele Signale sourceless (ohne 
Treiber), interne Tristates sind auch ein Indiz für gering durchdachte 
Hardware etc.. Da lohnt sich ein Aufräumen sicher.

Das Pining sollte man sich auch frühzeitig anschauen (ist als 
Excel-screenshot auch dabei). Hier sollte immer darauf geachtete werden, 
das alle Signale die FF in den Pad's nutzen. (begründetet 
Einzelausnahmen kann es natürlich auch geben). Das scheint bei dir beim 
Datenbus etc noch nicht der fall zu sein. Das kann dann im Real life zu 
Problemen führen, die in der Verhaltens-simu untentdeckt bleiben.


Auf die schnelle würde ich derzeit auf ein Problem mit Clock/Reset in 
der Testbench tippen.

von Jens W. (jensw)


Angehängte Dateien:

Lesenswert?

Hallo,

danke für den Hinweis.
Ist das aber nicht so, weil ich das so vorgebe? Das sind ja die Signale, 
die ans SRAM gehen. Die sind als "inout" definiert. Und solange ich die 
nicht brauche schalte ich die in tristate, damit nichts passiert. Dann 
ist es egal, ob das SRAM was auf den Bus legt oder nicht. Die Treiber 
vom FPGA gehen nicht kaputt.

Ich habe ein Bild vom konkreten Problem angehängt. Es geht um das Signal 
"uC_Data_Address(7 downto 0)". Das ist der Bus, der zum Mikrocontroller 
geht. Da werden die Adresse und die Daten vom uC an das FPGA übergeben. 
Die Adresse wird über zwei Latches gespeichert. Der Latch-Enable ist 
hier "uC_ALE_1" und "uC_ALE_2".

Der Code aus der Testbench ist oben schon gepostet.
Was ich nicht verstehe ist, dass bei der Übergabe der Adresse das Signal 
auf "undefined" bleibt (rote Kreise). Dieses "undefined" wird richtig an 
die SRAM-Adresse übergeben (auch rote Kreise).
Wenn ich die Daten auf diesen Bus lege funktioniert es und die werden 
richtig an das SRAM übergeben.
Das ist der gleiche Bus/das gleiche Signal.
Warum kann ich einmal keine Daten da drauf legen und einmal schon?

Das hat doch mit dem Ausgangstreiber erstmal nichts zu tun, oder?

Das Signal "SRAM_Address_Bus(18 downto 0)" ist als "out" definiert und 
"SRAM_Data_Bus(7 downto 0) als "inout". Kann das damit zu tun haben?

Grüße, Jens

von Jens W. (jensw)


Lesenswert?

Ich sehe gerade, dass die Daten, die ans SRAM gehen sollen, nicht auf 
den Bus gelegt werden. Da geht das Signal von "Z" auf "U".
Also doch irgendwas mit der Verdrahtung.
Das muss ein trivialer Anfängerfehler sein, aber ich finde ihn nicht...

von S. R. (svenska)


Lesenswert?

Jens W. schrieb:
> Das muss ein trivialer Anfängerfehler sein, aber ich finde ihn nicht...

Wenn man versehentlich zwei Eingänge miteinander verbindet, dann 
passiert nämlich genau das. Die Synthese schmeißt die Signale dann (mit 
Warnung) auch raus. Verbindet man zwei Ausgänge miteinander, bekommt man 
X in der Simulation.

Ich würde spontan mal sagen: "Prüfe alle Richtungen aller Signale" und 
"Synthetisiere mal durch und untersuche sämtliche Warnungen". Hab mir 
deinen Code aber nicht angeschaut, daher nur ins Blaue geraten.

von Jens W. (jensw)


Lesenswert?

Hallo,

das Datalatch geht mit seinem Ausgang auf ein internes Signal. Und das 
interne Signal verwende ich am Eingang von Data_Selector. Liegt das 
daran?
Darf man das nicht machen?
Die Signale sind alle im main (Top Entity) miteinander verschalten.
In main mache ich also nur noch die Verschaltung der Signale. Die 
Funktionalität findet in den einzelnen Unterblöcken statt. So war 
zumindest die Idee.

Gruß, Jens

von Jens W. (jensw)


Lesenswert?

Hallo an alle,

also ich glaube ich weiß wo der Fehler liegt.
Ich habe nochmal das Grundlagenbuch zu Rate gezogen. Es scheint so zu 
sein, dass es tatsächlich an dem internen Signal liegt.

Signale dürfen nicht dazu verwendet werden um zwischen Entities Daten 
auszutauschen. So verwende ich es aber im Moment. Ich habe das so wie im 
Blockschaltbild gemacht. Der Ausgang von "DatenLatch" geht auf ein 
Signal und das ist wiederum der Eingang von "DataSelector". Das ist aber 
verboten.
Da wird kein Fehler ausgegeben beim Synthetisieren. Aber gut. Das ist 
halt so.

Jetzt habe ich auch gelesen, dass man das als buffer machen könnte, aber 
das ist wohl verpönt. Das könnte wieder andere Probleme geben.
Auch inout wird hin und wieder bemängelt.
Man soll wohl die Daten eindeutig auf in und out definieren für einen 
eindeutigen Signalfluss.

Würde einer von euch mir helfen mein Blockschaltbild soweit auf Stand zu 
bringen, dass es diesen "allgemeinen" Designregeln genügt. Dann kann ich 
die einzelnen Blöcke überarbeiten und das Ganze wieder zusammen fassen.

Für mich ist es sehr schwer, das Denken umzustellen in VHDL. Wenn man 
aus der reinen µC Programmierung kommt, dann ist das doch sehr anders.
War das bei euch auch so?

Danke euch!

Grüße, Jens

von Schlumpf (Gast)


Lesenswert?

Jens W. schrieb:
> Signale dürfen nicht dazu verwendet werden um zwischen Entities Daten
> auszutauschen. So verwende ich es aber im Moment. Ich habe das so wie im
> Blockschaltbild gemacht. Der Ausgang von "DatenLatch" geht auf ein
> Signal und das ist wiederum der Eingang von "DataSelector". Das ist aber
> verboten.

Wo hast du denn das gelesen?

von S. R. (svenska)


Lesenswert?

Jens W. schrieb:
> Signale dürfen nicht dazu verwendet werden um zwischen Entities Daten
> auszutauschen. So verwende ich es aber im Moment.

Genau dafür verwendet man die aber. Des einen Ausgang wird mit des 
anderen Eingang über ein Signal verbunden...

Wie gesagt, ich würde darauf tippen, dass du in deiner 
Entity-Deklaration (also den Port-Definitionen) einen Richtungsfehler 
drin hast, und im Top zwei Eingänge miteinander verbunden sind.

Mit inout habe ich noch nicht gearbeitet, aber man sollte die 
ausschließlich für die Pins benutzen, aber nicht zwischen Entities.

von Jens W. (jensw)


Lesenswert?

Hallo,

das habe ich aus dem Buch "VHDL-Synthese" von Reichardt und Schwarz (5. 
Auflage). Das dürfte geläufig sein. Das kennt sicher der eine oder 
andere.
Steht auf Seite 10.

Ja das stimmt schon so, wie ich es geschrieben habe. Man darf Signale 
nicht verwenden um zwischen Entities Daten auszutauschen. Man darf die 
nur innerhalb einer architecture verwenden um Blöcke und 
Funktionselementen zu verbinden.

Aber das war auch nicht das Problem.
Ich befinde mich in meiner main ja innerhalb einer architcture. Also 
darf ich die lokalen Signale so verwenden.

Das Problem war, dass ich in Modul "DataLatch" einen else-Zweig nicht 
definiert habe, wo die Adressen eingelatched werden.
Das habe ich ergänzt und schon funktioniert auch die Testbench.

Trotzdem vielen Dank an alle!

Grüße, Jens

von Schlumpf (Gast)


Lesenswert?

Jens W. schrieb:
> Ja das stimmt schon so, wie ich es geschrieben habe. Man darf Signale
> nicht verwenden um zwischen Entities Daten auszutauschen. Man darf die
> nur innerhalb einer architecture verwenden um Blöcke und
> Funktionselementen zu verbinden.

Na wenn du das sagst, dann wird das schon so sein.
Offenbar weisst du da mehr, als wir.

von S. R. (svenska)


Lesenswert?

Schlumpf schrieb:
> Na wenn du das sagst, dann wird das schon so sein.

Naja, streng genommen hat er schon Recht.

Signale existieren nur innerhalb einer Entity.
Die Verbindungen zwischen Entities sind natürlich auch Signale, aber 
durch die Hierarchie in VHDL müssen sie immer auch innerhalb einer 
größeren Entity definiert sein.

Ist aber eher esoterisch-akademisch.

von Jens W. (jensw)


Lesenswert?

Hallo,

ja. Aber das war ja auch nicht das Problem.
Da habe ich mich vertan. Ich dachte, dass es an den Signalen liegt. War 
aber nicht. Viel schlimmer war, dass ich bei einer bedingten Zuweisung 
den else-Pfad nicht definiert hatte. Das habe ich ausgebessert und schon 
lief es.
Dann waren noch zwei Kleinigkeiten drin. Einmal eine zusätzliche 
Verzögerung von zwei Signalen die ich weg optimiert habe und zum Zweiten 
waren die Bedingungen für read_write vertauscht. Also ging das Schreiben 
zum SRAM-Bus nicht.

Ich habe noch nicht alles getestet. Es könnten also noch weitere 
Kleinigkeiten drin sein.

Ich hätte eine weitere Frage:
Kann man das Ganze nun so kapseln, dass ich das in neune Designs ganz 
leicht als Block rein nehmen kann? Also als ein komplettes Modul/Lib 
oder so etwas?

Ich möchte ja eigentlich Berechnungen im FPGA machen. Und wenn ich den 
SRAM-Zugriff nun immer so wie oben mit den verschiedenen Blöcken wie im 
Blockschaltbild rein nehmen muss, dann wird das Design 
unübersichtlicher.
Das hätte ich gerne überschaubarer gelöst.
Oder ist das unüblich?

Gruß, Jens

von S. R. (svenska)


Lesenswert?

Du kannst einen "IP-Block" draus machen. Damit hab ich aber keine 
Erfahrung, und ob sich der Aufwand lohnt, kann ich nicht einschätzen.

Wenn du dein Interface sauber definiert hast, dann kannst du aber auch 
einfach die VHDL-Datei in das neue Projekt kopieren, im Top verdrahten 
und gut ist.

von Schlumpf (Gast)


Lesenswert?

S. R. schrieb:
> Naja, streng genommen hat er schon Recht.

Wenn man es wirklich ganz genau nimmt, dann existieren Signale nur 
innerhalb einer Component,  welche aus Entity und Architecture besteht.

Components kann man in der Architecture einer übergeordneten Component 
mittels Signale verbinden.

Aber wie du schon sagst, dann wird es akademisch-esotherisch oder 
einfach korinthenkackerisch :)

Aber die Schlüsse, die der TO aus dem Buch zog, waren einfach falsch. 
Und darum ging es.
Aber wenn er den tatsächlichen Fehler gefunden hat, ist es ja gut.

@Jens:
Dein Design ist bereits eine Comonent, die du innerhalb deines 
übergeordneten Designs beliebig oft instanziieren kannst.

Um sie in ganz anderen Designs zu nutzen, kannst du sie entweder in dein 
Design kopieren und dann dort wieder instanziieren oder eine Library mit 
der Component erzeugen, die du dann einbinden kannst und dann Instanzen 
davon erzeugen kannst.

Wie das genau geht, findest du bestimmt mit den genannten Begriffen in 
dem Buch.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Jens W. schrieb:
> Ziel ist es nun, im FPGA einen Memory Controller zu implementieren, der
> aus dem SRAM ein Dual Port Ram macht. Bei einer Kollision wird gar nicht
> auf das RAM geschrieben und es wird ein error ausgegeben.

Ich hatte das vor ein paar Jahren mal für eine PAL-Grafikkarte gebaut.

War aber dann kein Dual-Port-RAM, sondern ein "Cycle-Shared-RAM".

Es gab zwei parallele Busse @ 15MHz und eine Statemaschine hat 
abwechselnd beide Busse auf ein SRAM (quasi) gelegt, das dann mit 60MHz 
betrieben wurde.

Beide Busse liefen komplett unabhängig und Kollisionen konnte es so 
keine geben.

: Bearbeitet durch User
von Jens W. (jensw)


Lesenswert?

@Schlumpf:
Ja du hast Recht: Die Schlüsse, die ich gezogen hatte, waren nicht 
richtig.
Die Aussagen stimmen nur für sich, aber nicht im Gesamten.
(Der Fehler war ja auch wo anders)

Ich versuche das mal mit einer Library zu kapseln.
Das hört sich so an als sei es das was ich mir vorstelle.

Danke dir!

Grüße, Jens

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.