Forum: FPGA, VHDL & Co. zpu, data2mem, RAM layout bei der Xilinx 7 Series


von VHDL hotline (Gast)


Lesenswert?

Hallo,

ich mache derzeit Tests mit der ZPU auf Kintex7 FPGAs. Ich verwende noch 
ISE (14.5).

Ich kann über den ZPU/gcc-Toolflow c files kompilieren und den 
Maschinencode dann in die generische Programmspeicherbeschreibung 
kopieren (dort werden jeweils 32-Bit-DWORDs über INIT_XX... => 
zugewiesen). Nach Syn+PAR funktioniert es wie gewünscht.

Was nicht funktioniert ist ein Update des Programmspeichers mittels 
data2mem. Das ist ja z.B. hier 
http://www.mikrocontroller.net/articles/ZPU:_Softcore_Implementierung_auf_Spartan-3_FPGA 
für einen Spartan3 beschrieben. Dort ist es so, dass ein 
16Kbyte-Speicher aus einer Reihe von Block-RAMs zusammengesetzt wird, 
welche per bit lanes verschaltet sind, d.h. jeder BlockRAM bekommt die 
gleiche Adresse und hält jeweils nur einen Teil der Daten. Das 
Gesamtdatum wird dann aus den Teildaten zusammengesetzt.

Mein Problem scheint zu sein, dass xst/ngdbuild/map (oder wo auch immer 
das RAM-Layout aus Einzel-Block-RAMs erzeugt wird) eine mir unbekannte 
Aufteilung der Daten auf die Einzel-Block-RAMs vornehmen. Ich habe einen 
16Kbyte Programmspeicher, welcher aus 4 RAMB32 (je 4KByte) 
zusammengesetzt wird. Meine .bmm sieht dementsprechend so aus:
1
ADDRESS_SPACE mem0 RAMB32 [0x00000000:0x00003FFF]
2
  BUS_BLOCK
3
   path_to_mem/Mram_ram4 RAMB32 [31:24] [0:4095] PLACED=X0Y1;
4
   path_to_mem/Mram_ram4 RAMB32 [23:16] [0:4095] PLACED=X0Y2;;
5
   path_to_mem/Mram_ram4 RAMB32 [15:8]  [0:4095] PLACED=X0Y3;;
6
   path_to_mem/Mram_ram4 RAMB32 [7:0]   [0:4095] PLACED=X0Y4;;
7
  END_BUS_BLOCK;
8
END_ADDRESS_SPACE;

, in der Annahme, dass 4 Bit-Lanes vorhanden sind (4 Block-RAMs aus der 
generischen 16KByte RAM-beschreibung laut PlanAhead auf jeden Fall 
erzeugt). Erzeuge ich allerdings einen data2mem dump des bitfiles unter 
Verwendung dieser bmm, stimmen die Block-RAM-Belegungen nicht mit den 
Block-RAM-Belegungen für die Simualtion überein, die data2mem erzeugt. 
Daher meine Vermutung, dass die .bmm bzw. diese Speicheraufteilung eben 
nicht stimmt. Ich finde allerdings mit bloßem Auge auch kein anderes 
logisches Muster, wie die Daten aufgeteilt sein könnten. Ich würde ja in 
der bmm einfach mal ausprobieren, ob die 32-bit Daten gar nicht zerhackt 
und verteilt sind, kann das aber irgendwie syntaktisch nicht korrekt 
beschreiben. So funktioniert es syntaktisch schon mal nicht
1
ADDRESS_SPACE mem0 RAMB32 [0x00000000:0x00003FFF]
2
  BUS_BLOCK
3
   path_to_mem/Mram_ram4 RAMB32 [31:0] [3072:4095] PLACED=X0Y1;
4
   path_to_mem/Mram_ram4 RAMB32 [31:0] [2048:3071] PLACED=X0Y2;;
5
   path_to_mem/Mram_ram4 RAMB32 [31:0] [1024:2047] PLACED=X0Y3;;
6
   path_to_mem/Mram_ram4 RAMB32 [31:0] [0:1023]    PLACED=X0Y4;;
7
  END_BUS_BLOCK;
8
END_ADDRESS_SPACE;

Wie kann ich herausfinden, wie das Speicherlayout aussieht? Oder wie 
kann ich den Toolflow animieren, ein bestimmtes Layout zu verwenden? 
Oder wie komme ich an eine korrekte bmm? Evtl. gibt es andere Hinweise?

Danke für jede Hilfe!

von Duke Scarring (Gast)


Lesenswert?

Bei mir gibt es zwei bmm-Dateien:

1. memlayout.bmm enthält die Speicherblöcke ohne Plazierung
Das könnte bei Dir z.B. so aussehen:
1
ADDRESS_SPACE memory 
2
    RAMB32 [0x00000000:0x00003fff]
3
    BUS_BLOCK 
4
        inst_memory/Mram_ram4 [31:24];
5
        inst_memory/Mram_ram3 [23:16];
6
        inst_memory/Mram_ram2 [15: 8];
7
        inst_memory/Mram_ram1 [ 7: 0];
8
    END_BUS_BLOCK;
9
END_ADDRESS_SPACE;

Bei translate/ngdbuild wird diese Datei mit übergeben:
1
ngdbuild ... -bm memlayout.bmm ...

Dann wird von den Tools automatisch ein zweites bmm-File erzeugt:
2. memlayout_bd.bmm

Dieses wird dann bei data2mem verwendet:
1
data2mem -bm memlayout_bd.bmm -bd software.elf ...

Die Hauptschwierigkeit besteht m.E. darin, das erste bmm-File richtig zu 
beschreiben.

Duke

von VHDL hotline (Gast)


Lesenswert?

Hallo Duke,

ja, das was ich da gepostet habe ist schon die _bd.bmm . Die .bmm sieht 
bei mir so aus, wie von dir beschrieben. Ich übergebe dies bei ngbuild 
und bitgen erzeugt die _bd.bmm .

Duke Scarring schrieb:
> Die Hauptschwierigkeit besteht m.E. darin, das erste bmm-File richtig zu
> beschreiben.

Das ist das Problem. Woher weiß ich, wie der Speicher organisiert ist?

VH

von Duke Scarring (Gast)


Lesenswert?

Ich hab für den Spartan6 bmm-Files von 16k bis 128k (bei 32 Bit 
Datenbreite).

VHDL hotline schrieb im Beitrag #4064625:
> Woher weiß ich, wie der Speicher organisiert ist?
Relevant ist die Zahl hinter Mram_ramxx, die Reihenfolge der Zeilen und 
natürlich, welche Bits genutzt werden.
Das meiste hab ich durch probieren rausgefunden (binary diff auf's 
Bitfile vor und nach data2mem).
Die Xilinx-Doku ist da erbärmlich.

Ich verwende auch nicht die Speichermakros aus dem Library Guide, 
sondern eine allgemeine VHDL-Beschreibung für den Speicher. Daher gibt 
es bei mir auch kein INIT_XX am Speicher.

> ja, das was ich da gepostet habe ist schon die _bd.bmm
Komisch. Warum steht da 4 mal Mram_ram4?

Wenn Du ein funktionierendes _bd.bmm-File hast, würde ich davon ein 
'normales' bmm-File erzeugen ([0:4095] und PLACED löschen) und dann die 
Finger davon lassen.

Duke

von VHDL hotline (Gast)


Lesenswert?

Hallo Duke,

danke für deine Hinweise.

Duke Scarring schrieb:
> Relevant ist die Zahl hinter Mram_ramxx

Bei mir geht es von Mram_ram1 bis Mram_ram4.

Duke Scarring schrieb:
>> ja, das was ich da gepostet habe ist schon die _bd.bmm
> Komisch. Warum steht da 4 mal Mram_ram4?

CopyPaste-Fehler, da vom Entwicklungsrechner abgeschrieben. Soll 1-4 
sein.

Duke Scarring schrieb:
> Ich verwende auch nicht die Speichermakros aus dem Library Guide,
> sondern eine allgemeine VHDL-Beschreibung für den Speicher. Daher gibt
> es bei mir auch kein INIT_XX am Speicher.

Das ist ein Missverständnis. Ich verwende ebenfalls einen generischen 
Speicher. Im zpu-Ableger zealot ist der generische Speicher ebenfalls 
per INIT_XX initialisiert.


Ich habe jetzt mittels des COMBINED statements in der .bmm mal 
verschiedene Varianten für die bit lanes durchgespielt (das war das, was 
ich im ersten Post nocht nicht syntaktisch fassen konnte; Datenbreite 
der RAMB32 8/16/32 Bit). Leider führte keine zum Erfolg. Ich werde es 
nun mal mit manueller Instanziierung der RAMB32 probieren.

Hier übrigens ein ähnliches Problem:
http://208.74.204.60/t5/Design-Tools-Others/Updating-a-ROM-in-a-bit-file/m-p/328027

von VHDL hotline (Gast)


Lesenswert?

Mit der direkten Instanziierung von 4 RAM macros (und damit des 
Selbstbaus der bitlanes) funktioniert es mit der schon geposteten .bmm. 
Das spricht dafür, dass xst/ngdbuild/map eine andere 
Speicherorganisation implementiert (allerdings auch 4 RAMB36 nutzt), die 
ich leider nicht herausgefunden habe. Ich habe sowohl generischen 
Speicher als auch durch coregen erzeugten probiert, beides mal dasselbe 
Problem.

Falls jemand an der Stelle noch weitere Infos darüber hat, wie bei der 
Kombination ISE14.5/Kintex7 generischer Speicher, der größer ist als ein 
BlockRAM, organisiert wird oder wie man das beeinflußen/herausfinden 
kann, kann er sie gern posten.

Für meine Zwecke habe ich jetzt erstmal den workaround mit den RAM 
macros.

von Fpgakuechle K. (Gast)


Lesenswert?

VHDL hotline schrieb im Beitrag #4065020:

> Falls jemand an der Stelle noch weitere Infos darüber hat, wie bei der
> Kombination ISE14.5/Kintex7 generischer Speicher, der größer ist als ein
> BlockRAM, organisiert wird oder wie man das beeinflußen/herausfinden
> kann, kann er sie gern posten.

Also bei microblaze mce auf spartan und ISE hat der fpgaeditor 
weitergeholfen. In diesem alle BRAMS anzeigen lassen und die korekten 
Pfade ins BMM kopieren. Bei mir lag das Problem das ich bei Verwendung 
des coregen den Instanzname nicht korrekt angab:
http://www.mikrocontroller.net/articles/Xilinx_Microblaze_MCS_Workflow#FPGA-Implementierung_und_SoftCore-Generierung

Aber das kann bei 7-serie und Vivado anders sein.

Am besten mal mit der Fehlermeldung googeln das findet manchmal den 
passenden Answerrecord bei Xilinx:
http://www.mikrocontroller.net/articles/Xilinx_Microblaze_MCS_Workflow#Fehlersuche

MfG,

von VHDL hotline (Gast)


Lesenswert?

Fpga Kuechle schrieb:
> Also bei microblaze mce auf spartan und ISE hat der fpgaeditor
> weitergeholfen. In diesem alle BRAMS anzeigen lassen und die korekten
> Pfade ins BMM kopieren.

Fpga Kuechle schrieb:
> Am besten mal mit der Fehlermeldung googeln

Mein Problem ist kein Fehler mit einer Fehlermeldung. Mein Problem ist 
das Mapping von logischen Address/Datenbeziehungen auf physikalische 
BRAM Adress/Datenbeziehungen. Diese Beziehung wird ja in der bmm 
beschrieben. Wenn man dort die falschen physikalischen Beziehungen 
einträgt funktionieren das Tool data2mem zum Beschreiben der BRAM zwar 
fehlerlos, allerdings wird es as logischer Sicht falsch beschrieben.

Ich beschreibe das mal etwas ausführlicher, falls noch jemand eine Idee 
dazu hat, evtl. habe ich auch irgendwo einen Denkfehler.

Beispiel: Ich habe logisch gesehen einen (Dual-Port) 16KByte RAM und 
greife darauf als 4096x32 Bit zu. Physikalisch passen in einen RAMB36 
der 7 Series 4 Kbyte (+Parity). Die Synthese "inferred" (wie sagt man 
deutsch?) aus der generischen RAM-Beschreibung (array(0 to 4095) of 
std_logic_vector(31 downto 0)) einen RAM (+ Konfiguration + 
Ansteuerung), der aus 4 RAMB36 besteht. Das sehe ich im FPGA-Editor bzw. 
PlanAhead und kann mir dort die Pfade herkopieren. Das array kann ich in 
VHDL initialisieren, also z.B. mem(0)(31 downto 0) = x"01020304"; . Dann 
habe ich an der logischen Adresse 0 des 16KByte RAM die 0x01020304 
stehen.

Physikalisch scheint die 0x01020304 allerdings über die 4 BRAMs verteilt 
zu sein, d.h. dieses Datum steht nicht als 32-Bit DWORD an Adresse 0 des 
ersten BRAM. In der .bmm-Datei wird daher beschrieben, wie die Daten 
aufgeteilt sind. Diese Mapping wird benötigt, damit data2mem weiß, wie 
es die logischen DWORDs physikalisch auf die BRAMs verteilt. Die 
Konfiguration + Ansteuerung, die die Synthese um die 4 BRAMs baut, wird 
dort also wiedergegeben.

Im Beispiel mit dem Spartan3 ( 
http://www.mikrocontroller.net/articles/ZPU:_Softcore_Implementierung_auf_Spartan-3_FPGA 
) sind die 32-Bit Daten z.B. byteweise über die RAMS verteilt (dorts 
sind es 8 kleinere). Für meine Beispiel heißt das die 0x01 steht an 
Adresse 0 in BRAM1, die 0x02 an Adresse 0 in BRAM2, die 0x03 an Adresse 
0 in BRAM3 und die 0x04 an Adresse 0 in BRAM4. Das nächste logische 
32-Bit Datenwort steht an Adresse 1 aller 4 RAMS. Die _bd.bmm dazu sieht 
so aus, unter der Annahme, dass RAMB32 (ohne Parity) genutzt wird:
1
ADDRESS_SPACE mem0 RAMB32 [0x00000000:0x00003FFF]  //logischer Adressraum in Bytes -> 16KByte
2
  BUS_BLOCK
3
   //bit lanes
4
   path_to_mem/Mram_ram1 RAMB32 [31:24] [0:4095] PLACED=X0Y1;  //höchstes Byte steht in BRAM1
5
   path_to_mem/Mram_ram2 RAMB32 [23:16] [0:4095] PLACED=X0Y2;  //nächstes Byte in BRAM2
6
   path_to_mem/Mram_ram3 RAMB32 [15:8]  [0:4095] PLACED=X0Y3;  //nächstes Byte in BRAM3
7
   path_to_mem/Mram_ram4 RAMB32 [7:0]   [0:4095] PLACED=X0Y4;  //unterstes Byte in BRAM4
8
  END_BUS_BLOCK;
9
END_ADDRESS_SPACE;

Leider ist das Resultat von data2mem mit dieser .bmm aus logischer 
Adress/Datensicht nicht korrekt. Ob das nur für die 7 Series unter 
ISE14.5 so ist, kann ich erstmal nur vermuten.
Das korrekte Mapping ist allerdings nirgends ersichtlich, soweit mir bis 
jetzt bekannt, kann man da nur raten. In PlanAhead sehe ich nur, dass es 
4 RAMB36E1 sind. Es könnte also auch sein, dass die 32-Bit physikalisch 
linear wie die logischen Beziehungen einfach hintereinander in den BRAMs 
stehen. Die _bd.bmm dafür würde so aussehen:
1
ADDRESS_SPACE mem0 COMBINED [0x00000000:0x00003FFF]  //logischer Adressraum in Bytes -> 16KByte
2
  ADRESS_RANGE_RAMB32
3
    BUS_BLOCK    
4
     path_to_mem/Mram_ram1 RAMB32 [31:0] [0:1023] PLACED=X0Y1;  //logische Bytes [0x00000000:0x00000FFF]
5
    END_BUS_BLOCK;
6
  END_ADDRESS_RANGE;
7
  ADRESS_RANGE_RAMB32
8
    BUS_BLOCK    
9
     path_to_mem/Mram_ram2 RAMB32 [31:0] [0:1023] PLACED=X0Y1;  //logische Bytes [0x00001000:0x00001FFF]
10
    END_BUS_BLOCK;
11
  END_ADDRESS_RANGE;
12
  ADRESS_RANGE_RAMB32
13
    BUS_BLOCK    
14
     path_to_mem/Mram_ram3 RAMB32 [31:0] [0:1023] PLACED=X0Y1;  //logische Bytes [0x00002000:0x00002FFF]
15
    END_BUS_BLOCK;
16
  END_ADDRESS_RANGE;
17
  ADRESS_RANGE_RAMB32
18
    BUS_BLOCK    
19
     path_to_mem/Mram_ram4 RAMB32 [31:0] [0:1023] PLACED=X0Y1;  //logische Bytes [0x00003000:0x00003FFF]
20
    END_BUS_BLOCK;
21
  END_ADDRESS_RANGE;
22
END_ADDRESS_SPACE;

Andere Mappings wären noch, dass z.B. jeweils 2 Bytes in den BRAMs 
stehen. Außerdem könnte es natürlich sein, dass der Parity-Bereich der 
RAMB36E1 genutzt wird, dann wäre die Aufteilung (bzw. auch der 
Adressbereich) nochmal anders.

Ich habe verschiedene .bmm Mappings probiert, aber bisher mit keiner 
Erfolg gehabt, dass das Ergebnis von data2mem mir die korrekten 
logischen Adress/Datenbeziehungen erzeugt. Ich finde in keinem Report 
(Synthese, ngdbuild, map) einen Hinweis darauf, wie der logische RAM 
physikalisch organisiert wurde. In PlanAhead sehe ich nur, DASS es 4 
RAMB36E1 sind, aber nicht, wie diese konfiguriert sind.

Instanziiere ich hingegen 4 BRAM_TDB_MACROs und verteile die Daten 
selbst (bestimme also selbst das Mapping von logischen auf physikalische 
Adress/Datenbeziehungen), klappt es mit der entsprechenden .bmm .

Daher bleibt die Frage, wie ich entweder das Mapping (ich meine nicht 
LOC, sondern die Speicherorganisation) bei generischen Speichern 
beeinflußen kann, so dass es mir nachher bekannt ist oder wie ich an 
Informationen über das Mapping komme, wenn ich es nicht beeinflußen 
kann.

von Duke Scarring (Gast)


Lesenswert?

Versuch mal folgendes:
1
ADDRESS_SPACE mem0 RAMB32 [0x00000000:0x00003FFF]
2
  BUS_BLOCK
3
   path_to_mem/Mram_ram4 RAMB32 [31:24];
4
   path_to_mem/Mram_ram3 RAMB32 [23:16];
5
   path_to_mem/Mram_ram2 RAMB32 [15: 8];
6
   path_to_mem/Mram_ram1 RAMB32 [ 7: 0];
7
  END_BUS_BLOCK;
8
END_ADDRESS_SPACE;

Duke

von VHDL hotline (Gast)


Lesenswert?

Duke Scarring schrieb:
> Versuch mal folgendes:ADDRESS_SPACE mem0 RAMB32 [0x00000000:0x00003FFF]
>   BUS_BLOCK
>    path_to_mem/Mram_ram4 RAMB32 [31:24];
>    path_to_mem/Mram_ram3 RAMB32 [23:16];
>    path_to_mem/Mram_ram2 RAMB32 [15: 8];
>    path_to_mem/Mram_ram1 RAMB32 [ 7: 0];
>   END_BUS_BLOCK;
> END_ADDRESS_SPACE;

Du meinst das Umkehren der Reihenfolge der BRAMs? Das habe ich schon 
probiert, in verschiedensten Reihenfolgen.
Die Sache ist, wenn ich einen data2mem dump des bitfiles mache mittels

data2mem -bm memory_bd.bmm -bt design.bit -d > dump.txt

, sollte ich in den entsprechenden Mram Speicherbereichen ja zumindest 
(an welchen Stellen auch immer) das wiederfinden, was ich per VHDL 
initialization an der logischen Adresse 0 vorgegeben habe. Testweise 
habe ich mal wirklich nur Adresse 0 mit 0x01020304 initialisiert, 
restliche Adressen mit 0 (In HW funktioniert das auslesen.). Damit 
müsste mit deiner bmm 0x01 im Mram4 (oder halt im 1. mit meiner 
geposteten bmm), 0x02 im Mram3 usw. stehen. Allerdings steht dort 
absolut nicht das, was ich initialisiert habe und ich erkenne aus dem 
was da steht auch keine Bitverteilung. Nicht mal die Anzahl der 1-Bits 
stimmt:

Mram4: 00 00 00 04 Rest 00
Mram3: 00 00 00 01 Rest 00
Mram2: 00 00 00 40 Rest 00
Mram1: 00 00 00 00 Rest 00

Mache ich dann ein data2mem auf diesem bitfile und auf dem neuen 
Resultat einen dump, ist der dump zwar so wie erwartet, funktioniert 
dann aber in HW nicht (da die bmm eben anscheinend nicht die korrekte 
logische Verknüpfung widerspiegelt).

von Fpgakuechle K. (Gast)


Lesenswert?

VHDL hotline schrieb im Beitrag #4066181:
> Ich finde in keinem Report
> (Synthese, ngdbuild, map) einen Hinweis darauf, wie der logische RAM
> physikalisch organisiert wurde. In PlanAhead sehe ich nur, DASS es 4
> RAMB36E1 sind, aber nicht, wie diese konfiguriert sind.

Du willst doch wissen wie die datenleitungen an die CPU geführt sind? 
dann musst du doch nur der Verdrahtung vom Bram folgen!
A) FPGA-editor mit ngc file nach P&R einfach die pins am bram anklicken 
und dem roten Drähtchen folgen
B) EDIFF netzliste generieren und mit texteditor nachfolgen. Zum 
erzeugen der Netzliste braucht man netgen 
(http://www.xilinx.com/support/documentation/sw_manuals/xilinx14_1/devref.pdf)
C) mit timinganalyze sollte man die Pfade auch finden können. Einfach 
ein FROM TO constraint von bram_data[*]  zu cpu_data[*] und dann schauen 
welche Pfade gefunden worden
D)Post-Place&Route simu könnte auch Licht ins dunkel bringen

Log-files helfen da nur bedingt weiter, in netzlisten musst du suchen.

Xilinx hat ein Dokument bezüglich data2mem debugging:

http://www.xilinx.com/Attachment/Xilinx_Answer_46945_Data2Mem_Usage_and_Debugging_Guide.pdf

Normalerweise steht im Synthese style guide etc. genau aus welcher 
RAM-array Beschreibung was erzeugt wird.
Vielleicht ergibst sich ja daraus ein Hinweis. Wobei man das 
automatische Einbauen (infer) von FPGA-Makroblocken aus
Hochsprachen-Beschreibungen als Comfort-Funktion verstehen sollte. Wenn 
es mit der Instanziierung aus Blöcken
funktioniert, dann ist gut. Bspw bei DPRAMS mit unterschiedlen 
datenbusbreiten ist das der IMHO sichere weg als das setzen
von synthesetool-spezifischen Attribute.


Im Library guide 
http://www.xilinx.com/support/documentation/sw_manuals/xilinx13_4/7series_hdl.pdf 
auf S.28 steht übrigens dass true bpram nicht inferable ist.

Wenn ich BRAM's die als VHDL-Array beschrieben sind, initialisiere dann 
mache ich das indem ich dem Array bei der signaldeklaration
eine const als start-wert zuweise. Mit .coe oder inti oder was auch 
immer gabs gern schererein das war schon bei picoblaze so.
Ist natürlich immens unhandlicher als data2mem beim "Firmware"-update

Der FPGA-Editor dürfte auch mehr verraten wenn man den BRAM block 
anklickt. jedenfalls bei slices klappt dann ein detail-windo auf in dem
sich die ganzen properties wie resettype async/sync etc. finden lassen.


MfG,

von Duke Scarring (Gast)


Lesenswert?

VHDL hotline schrieb im Beitrag #4066922:
> sollte ich in den entsprechenden Mram Speicherbereichen ja zumindest
> (an welchen Stellen auch immer) das wiederfinden, was ich per VHDL
> initialization an der logischen Adresse 0 vorgegeben habe.
Nein, vergiss es. Die Zuordnung von Speicherinhalten zu 
Konfigurationsbits folgt einer höheren Logik. Ich habe da noch nie 
bekannte Muster wiedergefunden. Der Vorschlag, die Leitungen im 
FPGA-Editor auszuklingeln scheint mir da vielversprechender zu sein.

Duke

von VHDL hotline (Gast)


Lesenswert?

Fpga Kuechle schrieb:
> A) FPGA-editor mit ngc file nach P&R einfach die pins am bram anklicken
> und dem roten Drähtchen folgen
> B) EDIFF netzliste generieren und mit texteditor nachfolgen. Zum
> erzeugen der Netzliste braucht man netgen
> (http://www.xilinx.com/support/documentation/sw_manuals/xilinx14_1/devref.pdf)
> C) mit timinganalyze sollte man die Pfade auch finden können. Einfach
> ein FROM TO constraint von bram_data[*]  zu cpu_data[*] und dann schauen
> welche Pfade gefunden worden
> D)Post-Place&Route simu könnte auch Licht ins dunkel bringen

Gute Vorschläge, danke. Probiere ich aus, muss aber gerade hinten 
anstehen, da ich jetzt erstmal mit meinem instanziierten Macro-RAM die 
eigentliche Aufgabe mit der ZPU angehe.

Fpga Kuechle schrieb:
> Xilinx hat ein Dokument bezüglich data2mem debugging:
>
> 
http://www.xilinx.com/Attachment/Xilinx_Answer_46945_Data2Mem_Usage_and_Debugging_Guide.pdf

Das hatte ich schon gelesen, da steht aber auch nichts zu diesem Problem 
drin.

Fpga Kuechle schrieb:
> Im Library guide
> 
http://www.xilinx.com/support/documentation/sw_manuals/xilinx13_4/7series_hdl.pdf
> auf S.28 steht übrigens dass true bpram nicht inferable ist.

Stimmt, das ist merkwürdig. Das initiale Design mit dem true DP-Ram wird 
ja gebaut und funktioniert, nur das BRAM-Update geht nicht.

Fpga Kuechle schrieb:
> Wenn ich BRAM's die als VHDL-Array beschrieben sind, initialisiere dann
> mache ich das indem ich dem Array bei der signaldeklaration
> eine const als start-wert zuweise.

Ja, so ähnliche habe ich das hier auch und das CPU-Programm aus diesem 
initialisierten Speicher funktioniert wie gesagt nach dem initialen 
Bauen. Hier ist übrigens der Speicher, der Probleme macht:
http://repo.or.cz/w/zpu.git/blob/refs/heads/master:/zpu/hdl/zealot/roms/hello_dbram.vhdl

Duke Scarring schrieb:
> Nein, vergiss es. Die Zuordnung von Speicherinhalten zu
> Konfigurationsbits folgt einer höheren Logik. Ich habe da noch nie
> bekannte Muster wiedergefunden.

Okay, das spricht dafür, dass ich da vielleicht das falsche erwartet 
habe. Bei dem dump mit dem selbst instanziierten Makro finde ich die 
Inhalte aber im dump wieder.

Danke erstmal euch beiden.

von Duke Scarring (Gast)


Lesenswert?

Da ich gerade ebenfalls auf die 7er-Serie umsteige und das Problem mit 
dem nachträglichen Update des Softcorespeichers habe, hier des Rästels 
Lösung:

VHDL hotline schrieb im Beitrag #4063875:
> ADDRESS_SPACE mem0 RAMB32 [0x00000000:0x00003FFF]
>   BUS_BLOCK
>    path_to_mem/Mram_ram4 RAMB32 [31:24] [0:4095] PLACED=X0Y1;
>    path_to_mem/Mram_ram4 RAMB32 [23:16] [0:4095] PLACED=X0Y2;;
>    path_to_mem/Mram_ram4 RAMB32 [15:8]  [0:4095] PLACED=X0Y3;;
>    path_to_mem/Mram_ram4 RAMB32 [7:0]   [0:4095] PLACED=X0Y4;;
>   END_BUS_BLOCK;
> END_ADDRESS_SPACE;

Bei den Speicherlayouts 1kx32, 2kx32 und 4kx32 verwendet Vivado (wie 
auch ISE) auch die Paritybits. Da werden statt RAMB32 einfach mal 
RAMB36-Blöcke verwendet.

Bei Dir müsste das entsprechende .bmm-File dann so aussehen:
1
ADDRESS_SPACE mem0 RAMB36 WORD_ADDRESSING [0x000000:0x003FFF]
2
  BUS_BLOCK
3
    path_to_mem/Mram_ram4 [35:27] PLACED=X0Y1;
4
    path_to_mem/Mram_ram3 [26:18] PLACED=X0Y2;
5
    path_to_mem/Mram_ram2 [17: 9] PLACED=X0Y3;
6
    path_to_mem/Mram_ram1 [ 8: 0] PLACED=X0Y4;
7
  END_BUS_BLOCK;
8
END_ADDRESS_SPACE;

Mein Vivado (2014.4) verwendet stattdessen die Instanznamen 
ram_reg_3...ram_reg_0, aber das dürfte nichts zur Sache tun.

Wichtig ist das Schlüsselwort 'WORD_ADDRESSING'!

Der nächste Punkt ist data2mem. Bei Vivado ist das Tool ins SDK 
gewandert. Mit WORD_ADDRESSING und den RAMB36 kann data2mem die 
.elf-Dateien nicht mehr richtig verwursten.

Als Workaround konvertiere ich Binärdaten selbst in das .mem-Format. 
Dabei müssen je nach Speicherlayout die Bits richtig mit den Paritybits 
verheiratet werden. Eine einfache 1-zu-1 Kopie geht erst bei 
Speicherlayouts ab 8kx32. Bei den anderen Formaten muß auf 36 Bit 
aufgefüllt werden:
1
Bits aus Binärdaten:
2
3322 2222 2222 1111 1111 1100 0000 0000
3
1098 7654 3210 9876 5432 1098 7654 3210
4
5
Bits in .mem-Datei (4kx36):
6
P332 22P2 2222 2211 P111 1111 10P0 0000 0000
7
 109 87 6 5432 1098  765 4321 09 8 7654 3210
8
9
Bits in .mem-Datei (2kx36):
10
PP33 2222 2222 2211 PP11 1111 1100 0000 0000
11
  10 9876 5432 1098   76 5432 1098 7654 3210
12
13
Bits in .mem-Datei (1kx36):
14
PPPP 3322 2222 2222 1111 1111 1100 0000 0000
15
     1098 7654 3210 9876 5432 1098 7654 3210
Die Stellen mit 'P' sind auf '0' zu setzen, bzw. werden angeblich 
ignoriert.
Ein Beispiel für das 2kx36-Layout: Wenn im Binärfile '1E 46 FB 2B' 
steht, muss im .mem-File eine '07912FB2B' landen.

Das Debugging der Bitzuordnung in den BRAM-Daten hat mit data2mem im 
Debug-Modus (-d) ganz gut funktioniert:
1
# bram update
2
data2mem -bm test.bmm -bd data.mem -bt synthesize.bit -o b update.bit
3
4
# prepare compare
5
data2mem -bm test.bmm -bt synthesize.bit -d > synthesize.txt
6
data2mem -bm test.bmm -bt update.bit     -d > update.txt
7
8
# do compare
9
diff synthesize.txt update.txt
Ich kann daher meine Aussgae in 
Beitrag "Re: zpu, data2mem, RAM layout bei der Xilinx 7 Series"
revidieren: Mit 'data2mem -d' findet man seine Nutzdaten auch im 
Textfile wieder.

Duke

von VHDL hotline (Gast)


Lesenswert?

Hallo Duke,

danke, dass du deine Erkentnisse dazu geteilt hast.


Ich bin vor einer Weile auch auf Vivado umgestiegen und verfolge 
mittlerweile folgenden Ansatz:

1. BRAMs selbst instanziieren und verdrahten, so dass das Speicherlayout 
klar ist.

2. Nach PAR die Instanznamen der BRAM im Layout finden.

3. Mit dem tcl-Kommando
1
set_property INIT_00 256'h000000...0 [get_cells{<<path_to_BRAM_instance>>}]

(bis INIT_7F bei 4K BRAM) kann man gezielt einzelne Speicherzellen 
updaten.

Den uC-Code oder anderes per Skript entsprechend aufteilen und mit dem 
tcl-Kommando verwursten.


Das hört sich erstmal unflexibel an, ist es aber nicht unbedingt. Die 
BRAM-Makros kann man generisch erzeugen, um verschiedene Speichergrößen 
zu erzeugen. Ein generisches Skript für die Aufteilung auf die Zellen 
(also quasi ein eigenes data2mem, bei der die bmm durch die eigene 
Verdrahtung des Speichers schon gegeben ist) schreibt man auch nur 
einmal. Das einzige, was man für ein neues Design einmal ändern muss, 
ist der Pfad zu den BRAMs. Der path_to_BRAM_instance enthält dabei nicht 
die Plazierung der Speicher, die muss man also nicht fix setzen.


Aber schön, dass wir jetzt mehrere Möglichkeiten haben ;-) .

von Duke Scarring (Gast)


Lesenswert?

VHDL hotline schrieb im Beitrag #4911406:
> 1. BRAMs selbst instanziieren und verdrahten, so dass das Speicherlayout
> klar ist.
Machen kann man das, aber ich mag das nicht. Damit ist der Code nicht 
mehr portabel :-(

> Das einzige, was man für ein neues Design einmal ändern muss,
> ist der Pfad zu den BRAMs.
Dafür kommt demnächst eine tcl-Lösung im Nachbarthread...

> Aber schön, dass wir jetzt mehrere Möglichkeiten haben ;-) .
Jepp.

Duke

von VHDL hotline (Gast)


Lesenswert?

Duke Scarring schrieb:
> Machen kann man das, aber ich mag das nicht. Damit ist der Code nicht
> mehr portabel :-(

Ich inferiere Speicher auch lieber aber in dem Fall ist ja noch einiges 
mehr nicht so ohne weitere portabel (data2mem+bmm).

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.