Hallo Jungens, ich möchte folgendes machen: auf einem Mikrocontrollerboard mit einem LPC2xxx Controller (Weiss noch nicht genau welchen ich verwenden möchte) soll ein FPGA mit drauf, der als Peripheriebaustein funktioniert. Nach aussen wird der FPGA viele SPI-Schnittstellen haben, und mehrere PWM-Kanäle. Das ansich ist auch nicht das PRoblem, sondern das folgende: der FPGA soll beim Mikrocontroller am externen Memory Interface angeschlossen werden, sodass er vom Controller wie ein SRAM angesprochen werden kann (memory mapped I/O). Könnt ihr mir vielleicht einen Tipp geben, wie ich die Register im FPGA realisieren kann und den Daten-/Adressbus, damit der Mikrocontroller damit zurechtkommt? Ich bin noch nicht so der Profi auf VHDL, aber ich will das jetzt lernen. Schematic ist nicht so dolle für solche Sachen ;-) Gruss Wolfgang
> Könnt ihr mir vielleicht einen Tipp geben, wie ich die Register im FPGA > realisieren kann und den Daten-/Adressbus, damit der Mikrocontroller > damit zurechtkommt? Am einfachsten dürfte hier die Verwendung eines Dual-Ported-RAM sein. So kannst du die beiden Taktdomänen uC <-> FPGA am einfachsten entkoppeln. > Ich bin noch nicht so der Profi auf VHDL, aber ich will das jetzt lernen. Dann solltest du aber vorerst die Aufgabe in einzelne kleine Häppchen aufteilen. Mach erst mal das asynchrone Interface zum uC mit LEDs und Tastern. Dann machst du dir Gedanken, wie du das Ganze auf den FPGA-Takt einsynchronisierst und verarbeitest.
Hi Lothar, Wie beschreibt man denn ein solches dual port RAM in VHDL? Ich will übrigens Quartus II von Altera verwenden, falls das eine Rolle spielt. > Dann solltest du aber vorerst die Aufgabe in einzelne kleine Häppchen > aufteilen. Mach erst mal das asynchrone Interface zum uC mit LEDs und > Tastern. Dann machst du dir Gedanken, wie du das Ganze auf den FPGA-Takt > einsynchronisierst und verarbeitest. so ähnlich dachte ich mir das schon. Am besten wäre wohl ein dual port RAM, auf der einen seite Taster, um den uC zu simulieren, auf der anderen LEDs um die einzelnen Bits im RAM zu sehen. Oder?
> Wie beschreibt man denn ein solches dual port RAM in VHDL? > ...Quartus II von Altera verwenden, falls das eine Rolle spielt. Tut es durchaus... Wie ein DPRAM beschrieben wird, damit fertige RAM-Bausteine verwendet werden, ist z.B. für Xilinx im Synthesis Guide XST.pdf beschrieben. Für Altera dürfte es sowas ähnliches auch geben.
Wie wäre es als Alternative, wenn Du den Takt für Dein FPGA aus dem Takt des µC beziehst? Da die Bussignale des µC höchstwahrscheinlich synchron zu seinem Takt sind, kannst Du Dir das Einsynchronisieren dann sparen. Intern kann das FPGA mit einem ganzzahligen Vielfachen des so vorgegebenen Takts arbeiten, wenn Du diesen schnelleren Takt per PLL aus dem externen Takt ableitest. Dann brauchst Du auch hier nichts zu synchronisieren...
Hi gonzo, das Problem dabei ist, dass mein uC einen Quarzoszillator von 4 MHz hat und den Takt dann intern auf 72 MHz vervielfacht. Leider lässt sich diese vielfache Frequenz nirgends ausgeben, ich hätte hächstens 4 MHz zur Verfügung...
Hallo, ich mach das mit einem LPC2294 Controller. Ist eigentlich ganz einfach, der LPC2294 hat ein externes Memory-Interface und an einem Pin kannst du den internen Takt ausgeben lassen, der nennt sich XCLK. Mit diesem Takte ich dann das FPGA Interface synchron zum LPC Daten-Adressbus. Du brauchst eigentlich nur den Datenbus, den Adressbus, das WE (BLS Signal beim LPC2294) und das CS. Im LPC mußt du die Register entsprechen setzen, und dann kannst du auf das FGPA mittels eines Memory-Befehls lesend und schreibend zugreifen. Den VHDL Code für das Interface ist eigentlich auch kein Hexenwerk. Gruß Ralf
Hi Ralf, kannst du mir mal ein bisschen von deinem VHDL-Code zeigen? Wie übernimmst du die Daten? Ich hab intern ein Signal definiert: signal data : std_logic_vector(7 downto 0); und dann process begin wait until rising_edge(clk); if we = '0' and ce = '0' and oe = '1' then data <= datenbus; end if; if we = '1' and ce = '0' and oe = '0' then datenbus <= data; end if; end process; wobei datenbus dann die 8 pins sind für 8 parallele Bits.
>Hi Ralf, >kannst du mir mal ein bisschen von deinem VHDL-Code zeigen? Aber nur weil du es bist ;-). Ich habe zwei prozesse. Einen für Register lesen und einen für Register schreiben. clk ist xclk vom LPC2294 cs ist cs(1) vom LPC2294 we ist bls(0) vom LPC2294 address ist der Datenbus vom LPC2294 datenbus ist der 8 bit breite Datenbus vom LPC2294 rst ist eine Resetsignal, kannst du aber auch weglassen
1 | signal data : std_logic_vector(7 downto 0); |
2 | |
3 | process (clk, rst) -- register schreiben |
4 | begin
|
5 | if (rst = RESET_ACTIVE) then |
6 | -- init something
|
7 | elsif rising_edge(clk) then |
8 | if (cs = '0' and we = '0') then |
9 | case address is |
10 | when x"00" => -- x"00" entspricht ADR x80000000 am LPC2294 |
11 | data <= datenbus; |
12 | |
13 | when others => |
14 | null; |
15 | end case; |
16 | end if; |
17 | end if; |
18 | end process; |
19 | |
20 | |
21 | process (clk, rst) -- register lesen |
22 | begin
|
23 | if (rst = RESET_ACTIVE) then |
24 | -- init something
|
25 | elsif rising_edge(clk) then |
26 | if (cs = '0' and we = '1') then |
27 | case address is |
28 | when x"00" => -- x"00" entspricht ADR x80000000 am LPC2294 |
29 | datenbus <= data; |
30 | |
31 | when others => |
32 | null; |
33 | end case; |
34 | end if; |
35 | end if; |
36 | end process; |
Mehr verrate ich nicht. Den Rest mußt du schon selbst rausfinden. Die größte Herausforderung besteht jetzt noch darin im LPC die Register entsprechend zu setzen. Gruß Ralf
Ups, ich habe noch vergessen: Im Toplevelfile teile ich den Datenbus in Data_in und Data_out auf, und setze den Datenbus hochohmig wenn oe = 0 und cs = 0 ist.
1 | signal data : std_logic_vector(7 downto 0); |
2 | |
3 | process (clk, rst) -- register schreiben |
4 | begin
|
5 | if (rst = RESET_ACTIVE) then |
6 | -- init something
|
7 | elsif rising_edge(clk) then |
8 | if (cs = '0' and we = '0') then |
9 | case address is |
10 | when x"00" => -- x"00" entspricht ADR x80000000 am LPC2294 |
11 | data <= data_in; |
12 | |
13 | when others => |
14 | null; |
15 | end case; |
16 | end if; |
17 | end if; |
18 | end process; |
19 | |
20 | |
21 | process (clk, rst) -- register lesen |
22 | begin
|
23 | if (rst = RESET_ACTIVE) then |
24 | -- init something
|
25 | elsif rising_edge(clk) then |
26 | if (cs = '0' and we = '1') then |
27 | case address is |
28 | when x"00" => -- x"00" entspricht ADR x80000000 am LPC2294 |
29 | data_out <= data; |
30 | |
31 | when others => |
32 | null; |
33 | end case; |
34 | end if; |
35 | end if; |
36 | end process; |
37 | |
38 | |
39 | -- Zuweisung Datenbus
|
40 | data <= data_out when (oe = '0' and cs = '0') else (others => 'Z'); |
41 | data_in <= data; |
Gruß Ralf
Hallo, > Aber nur weil du es bist ;-). cool, vielen Dank :-) Noch ne kleine Frage. Und zwar habe ich am FPGA auch noch ein EA DOGM128 Grafikdisplay dran, welches über SPI angesprochen wird. Im FPGA ist dann ein 1 kByte grosser Puffer, welcher das anzuzeigende Bild beinhaltet! Der FPGA gibt diesen Puffer über SPI dann periodisch an das Display aus. Jetzt möchte ich eine kleine hardwaremässige Grafikunterstützung realisieren: schreibt der Controller in ein spezielles Command Register einen Opcode, z.B. für "zeichne eine Linie", dann soll der FPGA in diesen 1k grossen Puffer selbständig die entsprechende Linie malen. Geht sowas, was mir da vorschwebt?
Gehen es natürlich tut, aber kompliziert es wird. Ich mir das nicht antun würde... ;-) Aber wie wäre es mit folgender einfach zu realisierender Optimierung: Da Du das RAM im FPGA sehr flexibel aufteilen kannst, könntest Du es dem Prozessor in einem zusätzlichen Adressbereich bitweise adressierbar präsentieren. Dann kannst Du ein Pixel durch eine einfache Schreiboperation setzen und sparst Dir ein Lesen und ein Odern. Die nächste Stufe wären dann Operationen auf rechteckigen Pixelblöcken im FPGA (Clear, Move, Copy etc.). Das sollte auch noch einfach zu realisieren sein. Ob es sich aber auch lohnt, mußt Du wissen. Ich würde das ganz am Ende der Entwicklung angehen. Falls Du Einfluß auf die Hardware nehmen kannst: Lege XCLK unbedingt auf einen Clock-Eingang des FPGA. Nur dann kannst Du die PLL-Lösung von oben implementieren.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.