Hallo Forum,
ich habe momentan ein "kleines" Problem damit, Zugriff auf den
OnBoardspeicher des Nexys 2 Boards zu bekommen.
Ich will den RAM als einfachen RAM nutzen und habe mir zu erst mit dem
Core Generator ein BlockRAM erstellt. (siehe Bild CoreGen.PNG)
Als nächstes habe ich mir den View HDL Functional Model-Code aus dem
CoreGen kopiert und unter dem passenden Entitynamen "newBlockRam.vhd"
abgespeichert.
Dessen Code sieht folgendermaßen aus:
-- COMP_TAG_END ------ End COMPONENT Declaration ------------
63
typestate_typeis(
64
do,
65
commit
66
);
67
signalmystate:state_type;
68
signaladdra:std_logic_vector(12downto0);
69
signaldina:std_logic_vector(15downto0);
70
signaldouta:std_logic_vector(15downto0);
71
72
73
begin
74
75
------------- Begin Cut here for INSTANTIATION Template ----- INST_TAG
76
myRam:newBlockRam
77
portmap(
78
clka=>clk,
79
wea=>wea,
80
addra=>addra,
81
dina=>dina,
82
douta=>douta);
83
-- INST_TAG_END ------ End INSTANTIATION Template ------------
84
85
myRamProcess:process
86
begin
87
waituntilclk'eventandclk='1';
88
ifreset='1'then
89
mystate<=do;
90
dataValid<='0';
91
else
92
--Wenn der nicht Ram angesprochen werden soll
93
ifactive='0'then
94
mystate<=do;
95
dataValid<='0';
96
-- Wenn der RAM angesprochen werden soll
97
else
98
casemyStateis
99
--do soll dem Ram die Befehle schicken
100
whendo=>
101
dataValid<='0';
102
--Adresse setzen, hier nur 13 Bit!
103
addra<=AddrMidByte(4downto0)&AddrLowByte;
104
-- Zu schreibende Daten an den Ram-Eingang legen
105
ifwea="1"then
106
dina<=DataIN;
107
endif;
108
myState<=commit;
109
--commit soll dem Aufrufenden ein Valid-Signal geben
110
whencommit=>
111
ifwea="0"then
112
--Vom RAM gelesene Daten an den Ausgang dieser Comp legen
113
DataOUT<=douta;
114
endif;
115
--Der übergeordneten Stelle die Bereitschaft der Daten ausgeben
116
dataValid<='1';
117
endcase;
118
endif;
119
120
endif;
121
endprocess;
122
endBehavioral;
Wie man sieht habe ich zur Instanziierung des newBlockRam das Template
des CoreGens verwendet.
Diese Entity wird wieder in einem Controller instanziiert:
--Der Prozessor will lesen, der Controller schaut auf welchem Port
39
elsifcpu_read_strobe='1'then-- Falls die CPU lesen will
40
BCD_links(3downto0)<="0001";
41
caseport_idis
42
when"00000100"=>
43
rs232_readstrobe<='1';
44
cpu_in_port_valid<='0';
45
when"00010000"=>
46
ramAddrLow<=cpu_port_out;
47
cpu_in_port_valid<='1';
48
when"00010001"=>
49
ramAddrMid<=cpu_port_out;
50
cpu_in_port_valid<='1';
51
when"00010011"=>
52
--Hier wird der eigentlich Lesevorgang ausgeführt
53
iframValid='1'then
54
--fertig gelesen
55
cpu_port_in<=ramOutGesamt(7downto0);
56
cpu_in_port_valid<='1';
57
else
58
--muss noch lesen
59
ramActivate<='1';
60
ramWEA<="0";
61
cpu_in_port_valid<='0';
62
endif;
63
....
64
--Falls die CPU schreiben will, wird hier geschaut auf welchen Port
65
elsifcpu_write_strobe='1'then--Falls die CPU schreiben will
66
BCD_links(7downto4)<="0001";
67
caseport_idis
68
when"00000100"=>
69
rs232_data_in<=cpu_port_out;
70
rs232_writestrobe<='1';
71
cpu_out_port_ready<='0';
72
when"00010000"=>
73
ramAddrLow<=cpu_port_out;
74
cpu_out_port_ready<='1';
75
when"00010001"=>
76
ramAddrMid<=cpu_port_out;
77
cpu_out_port_ready<='1';
78
--Hier soll nun auf den RAM geschrieben werden
79
when"00010011"=>
80
iframValid='1'then
81
--fertig geschrieben
82
BCD_links<=cpu_port_out;
83
84
--cpu_out_port_ready <= '1';
85
else
86
--muss noch schreiben
87
ramActivate<='1';
88
ramWEA<="1";
89
cpu_out_port_ready<='0';
90
91
ramInGesamt<="00000000"&cpu_port_out;
92
endif;
93
....
RS232 etc funktionieren, also sollte es nicht am Controller direkt
liegen (außer in den geposteten Abschnitten versteht sich).
Dazu stellen sich mir mehrere Fragen:
Muss ich die Pins noch manuell zuweisen? Falls ja:
Wie mache ich das ohne die Ports bis in den Controller durchzuschleifen?
Kann ich also irgendwie ein ucf-File für eine untergeordnete Instanz
erstellen?
Falls Nein:
Was mache ich falsch mit meinem Code? Ich sehe es wirklich nicht. Das
ganze kompiliert durch, das Board läuft auch, nur leider bekomme ich nur
0 aus dem RAM rausgelesen, nachdem ich ihn beschreiben wollte.
Zur Übersicht befindet sich im Anhang noch die Projektstruktur unter
strukt.PNG.
Der RAM auf deinem Board ist ein SDRAM. Das heißt er ist relativ
kompliziert anzusteuern, weil man ihn refreshen muss und so. Schau dir
mal den englischen Wikipedia-Artikel zu SDRAM an, da steht bisschen was
über die Ansteuerung. Ich glaube du hast einen SDR SDRAM, oder? Ich habe
auf meinem Spartan3E Board einen DDR SDRAM und plane in naher zukunft
mal einen Memory Controller dafür zu schreiben. Ich glaube der Core
generator bietet keine Option dafür. Um auf den externen SDRAM
zuzugreifen hast du also nur die IOs am FPGA, die mit dem RAM verbunden
sind, den rest musst du selber nehmen.
Im FPGA ist auch ein s.g. Blockram verbaut, den kannst du mit dem Core
Generator nutzen (aber auch noch viel einfacher mit Arrays). Der
Blockram ist sehr schnell, statisch und kann dual port ansteuerung,
dafür ists eben nicht so viel RAM wie der externe. Schau ins Datenblatt
deines FPGAs um zu sehen wie viel drinn ist.
Hi
Der Ram auf dem Board ist ein PSRam, entweder du sprichst in an die ein
70ns schnellen SRAM oder wie ein 80 Mhz SRAM mit Takt und Bursts usw.
Aber das Datenblatt ist echt gut, vllt. sollte man das mal Lesen . . .
Gruß Johny
Johny schrieb:> Der Ram auf dem Board ist ein PSRam, entweder du sprichst in an die ein> 70ns schnellen SRAM oder wie ein 80 Mhz SRAM mit Takt und Bursts usw.> Aber das Datenblatt ist echt gut, vllt. sollte man das mal Lesen . . .
Ja, richtig, sorry, habe nur kurz die Beschreibung überflogen, da stand
SDRAM, im handbuch steht PSRAM. Der ist natürlich genauso einfach
anzusteuern wie SRAM, kein Problem.
TokyoDrift schrieb:> Ja, richtig, sorry, habe nur kurz die Beschreibung überflogen, da stand> SDRAM, im handbuch steht PSRAM. Der ist natürlich genauso einfach> anzusteuern wie SRAM, kein Problem.
Aber nicht mit dem Core Generator, der ausschließlich für den
FPGA-internen BlockRAM gedacht ist. Das war der Fehler im ursprünglichen
Post.