Hallo an Alle,
ich gerade dabei einen eigenen IP Core zu erstellen, der mit mehr als
einem Microblaze per FSL kommunizieren können soll.
Mehrere FSL Busse habe ich inzwischen in den IP Core reinbekommen, sogar
so, dass man die Anzahl per GUI einstellen kann.
Der nächste Schritt wäre nun Block RAM zu verwenden.
Um Block Ram zu instanzieren habe ich folgendes gemacht:
type bram_type is array ((2**bram_addr_width)-1 downto 0) of
std_logic_vector(bram_data_width-1 downto 0);
signal BRAM : bram_type;
Bevor ich das Block Ram nun benutze würde ich dieses gerne
initialisieren. Das Problem dabei: Ich möchte es nicht beim Laden des
FPGA's mit initialisieren, sondern immer dann, wenn das reset-Signal
meines IP-Cores auf '1' geht. Da tut sich mir die Frage auf, ob das
überhaupt möglich ist, da es ja eine bestimmte Zeit dauern würde, bis
das BRam komplett initialisiert ist und ich nicht sicherstellen kann,
dass das reset-Signal mindestens diese Zeit auf '1' bleibt.
Für die Initialisierung habe ich folgendes versucht:
The_SW_accelerator : process (FSL_Clk) is
begin -- process The_SW_accelerator
if FSL_Clk'event and FSL_Clk = '1' then
if FSL_Rst = '1' then
for i in 0 to (2**mbx_addr_width)-1 loop
BRAM(to_integer(unsigned(i))) <= i;
end loop;
end if;
end if;
end process;
Dies ist ein verkürzter Abschnitt des VHDL-Codes. Leider kommt dabei
folgender Fehler, der sich auf die zeile des BRam Zugriffs bezieht:
ERROR:HDLParsers:854 - The expression can not be converted to type
unsigned.
Mache ich da etwas falsch? Ich verstehe das Problem an der Stelle nicht
so ganz.
Ist es überhaupt möglich per reset-Signal das BRam mit 0, 1, 2, 3, 4...
usw. zu belegen?
Wenn es da eine Möglichkeit gibt wäre ich euch sehr dankbar, mir ein
paar Tips zu geben.
lg,
ChrisB
> Da tut sich mir die Frage auf, ob das> überhaupt möglich ist, da es ja eine bestimmte Zeit dauern würde, bis> das BRam komplett initialisiert ist und ich nicht sicherstellen kann,> dass das reset-Signal mindestens diese Zeit auf '1' bleibt.
Dann mußt du hergehen und mit dem Reset die Initialisierung starten.
allerdings solltest du erst dann auf das BRAM zugreifen, wenn di
Initialisierung beendet ist. Wie willst du übrigens dann später mal
irgendwas anderes in das BRAM bekommen?
> The expression can not be converted to type unsigned.
Ja, klar: i ist ein integer....
Du solltest es also eher so machen:
BRAM(i) <= std_logic_vector(to_unsigned(i,bram_data_width));
> Ist es überhaupt möglich per reset-Signal das BRam mit 0, 1, 2, 3, 4...> usw. zu belegen?
Nicht so ohne weiteres, du mußt jede Zelle per Handschlag auf den Wert
setzen.
Eine Möglichkeit wäre eine komplette Neuinitialisierung des FPGAs (via
PROG_B) und die Verwendung von Defaultwerten (wie dort in der
Sinus-Tabelle: http://www.lothar-miller.de/s9y/categories/31-DDFS).
Danke für deine Antwort.
Ja, so habe ich es auch gerade gelöst. Mit dem Reset wird die
Initialisierung gestartet und nach Fertigstellung setze ich ein Signal,
welches ich nach außen führe, auf '1'. An Hand dieses Signals wissen die
angeschlossenen Microblazes dann, ab wann diese auf meinen IP Core
zugreifen dürfen.
Wie meinst du das, wie ich später mal was anderes ins BRam bekommen
will?
Nach der Initialisierung soll dann per FSL was ins BRam geschrieben
werden können. Sollte doch gehen oder?
> Wie meinst du das, wie ich später mal was anderes ins BRam bekommen will?
Du hast derzeit einen "Reset-Schreibzugriff":
BRAM(i) <= std_logic_vector(to_unsigned(i,bram_data_width));
Hier mußt du noch eine Möglichkeit einbauen, um mit deiner Adresse und
deinen Daten an das BRAM zu kommen.
Ja, ich hatte vor dass der weitere Zugriff in einer State-Machine
abläuft, sobald das reset-Signal auf '0' ist und die Initialisierung
abgeschlossen ist.
Zunächst möchte ich dann (aus der Sicht meines IP Cores) die über den
Slave empfangenen Daten als Adresse des BRams verwenden und den Inhalt
des BRams an den Master FSL raus zu schicken.
Das wäre so mein erster Test um zu gucken, ob ich das BRam auslesen
kann.
Danach würde ich versuchen auch auf das BRam zu schreiben, aber das ist
erst der nächste Schritt.
Leider habe ich folgendes Problem bezüglich meines IP Cores:
Der angeschlossene Microblaze macht immer ein put-Befehl, um die Adresse
zu übermitteln, wartet bis fsl_isinvalid '0' liefert, macht dann solange
get-Befehle bis fsl_isinvalid '0' liefert.
Das Ganze mache ich in einer Schleife mit nem Delay von ner halben
Sekunde und gebe dem put-Befehl einen Zählerwert mit.
Leider kommt beim Get Befehl 16 mal 0 zurück und danach hängt er sich
auf, da fsl_isinvalid nicht mehr 0 wird.
Vermutlich ist nach 16 Put-Befehlen der 16-stufige Fifo voll, mein IP
Core arbeitet nicht richtig, da die Daten nicht abgeholt werden.
Hat jemand eine Idee, was falsch sein könnte?
FSL_READ und FSL_WRITE müssen bedient werden damit der FSL Bus "weiss"
das was geschrieben/gelesen werden soll/kann... da muß man nix
signalisieren oder so...
Ja wird das denn nicht an folgender Stelle gemacht:
[vhdl]
FSL0_S_Read <= FSL0_S_Exists when state = Read_Inputs else '0';
FSL0_M_Write <= not FSL0_M_Full when state = Write_Outputs else '0';
[\vhdl]
Das habe ich aus dem Beispiel übernommen, das Xilinx generiert, wenn man
den Coprocessor-Wizard benutzt.
Im übrigen muss ich mich korrigieren. Hatte nen kleinen Fehler im
C-Code. Es ist so, dass ich den put-Befehl mache, daraufhin dne
get-Befehl wie oben beschrieben, aber dass sich schon beim ersten
Durchlauf nichts mehr tut, da das fsl_isinvalid liefert nach dem
get-Befehl immer eine '1'. Also siehts so aus, als würde mein IP Core
nichts auf den bus schreiben...
Ich glaube das Problem hat sich gerade gelöst... es lag an der falsch
polarisierten Reset-Leitung, auf die man extra achten sollte. Trotzdem
danke für eure Hilfe.
ChrisB schrieb:
> C-Code. Es ist so, dass ich den put-Befehl mache, daraufhin den
Zeig mal den Code... wichtig ist u.A. das du erst einmal was schreibst
und dann liest, sonst lauft deine Statemachine nicht weiter.
Das invalid, ist mein ich auch nur bei non_blocking interessant.
Ich würde auch erstmal konstante Werte geben nicht das das Problem an
deinem BRAM Code liegt...
Ja, das war mein erster Fehler... Jetzt läuft alles rund. Ich lege eine
Adresse mit put an und mit get bekomme ich den vorinitialisierten Wert
aus dem BRam.
Soweit so gut, dann kanns jetzt weitergehn.
Danke nochmal!
Gruß
auf das BRam zugreifen, da bram_num vom Typ std_logic_vector ist.
Welches der beiden Möglichkeiten ist die bessere, bzw. eventuell
einfacher und platzsparender im Design? Hat die Konvertierung von
std_logic_vector zu integer überhaupt einfluss auf das Design?
Gibt es eine Möglichkeit das BRam direkt durch einen std_logic_vector zu
adressieren, anstatt eines integers?
Alles klar, danke.
Noch eine andere Frage die sich mir gerade auftut: Im EDK sehe ich in
der Design Summary, dass für mein coprozessor ein Haufen FlipFlops und
LUT's benutzt werden, jedoch kein BRam.
Wird mein bram aus dem obigen Beispiel tatsächlich aus FlipFlop's und
LUT's aufgebaut anstatt aus wirklichem BRam?
Lies das im XST.pdf nach.
Als Tipp: die Leseadresse muß registriert werden.
> Wird mein bram aus dem obigen Beispiel tatsächlich aus FlipFlop's und> LUT's aufgebaut anstatt aus wirklichem BRam?
Ja, sowas nennt sich Distributed RAM.
Meinst du damit, dass ich die Leseadresse bei einem Takt erst in ein
Register schreiben muss und erst beim nächsten Takt mit der Adresse aus
diesem Register auf das BRam zugreifen kann?
Muss das beim Schreiben nicht gemacht werden?
Auf das Lesen kommt es an. Dort siehst du die Unterschiede:
http://www.lothar-miller.de/s9y/archives/20-RAM.html
EDIT:
> Meinst du damit, dass ich die Leseadresse bei einem Takt erst in ein> Register schreiben muss und erst beim nächsten Takt mit der Adresse aus> diesem Register auf das BRam zugreifen kann?
Richtig.
> Muss das beim Schreiben nicht gemacht werden?
Nein, das Schreiben ist sowieso schon synchron.