Hi Leute, ich bin gerade beim Einstieg in VHDL um CPLD's zu programmieren. Nutzen tue ich dafür Quartus von Altera. Bei meinem derzeitigen Übungsprojekt wird der CPLD an einen Address-/Datenbus angeschlossen. Der CPLD bekommt insgesamt 32 Bytes an Daten gesendet die dieser intern in einer Matrix a 8*32 Bit speichern soll. Das Einlesen dieser Matrix muß also über die Addresse (Range 0 to 31) als Index immer 8 Bits in dieser Speichermatrix abspeichern. Bei auslesen aber müssen nun die Zeilen a 32 Bits an einem 32Bit breiten Port des CPLD angelegt werden. Mein bisheriger Source "codiert" das manuell und verbraucht über 500 Makrozellen, ist also unzumutbar. Meine Frage ist also wie man in VHDL sowas programmieren muß. Im WEB hatte ich schon gesucht und leider nichts gefunden. Nachfolgend mal eine verkürzte Version. Gruß Hagen entity Test is port( -- Addresseingänge A0-A5 A: in std_logic_vector(5 downto 0); -- Datenbus D: in std_logic_vector(7 downto 0); -- Clock, Chipselect, WR CLK,CS,WR: in std_logic; ROWS: out std_logic_vector(31 downto 0); ); end LED; architecture behavioral of Test is signal M0: std_logic_vector(31 downto 0); signal M1: std_logic_vector(31 downto 0); signal M2: std_logic_vector(31 downto 0); signal M3: std_logic_vector(31 downto 0); signal M4: std_logic_vector(31 downto 0); signal M5: std_logic_vector(31 downto 0); signal M6: std_logic_vector(31 downto 0); signal M7: std_logic_vector(31 downto 0); begin process(CLK, CS, WR, A, D) begin if CS = '1' and WR = '0' then if A(5) = '0' then case A(4 downto 0) is when "00000" => M0(0) <= D(0); M1(0) <= D(1); M2(0) <= D(2); M3(0) <= D(3); M4(0) <= D(4); M5(0) <= D(5); M6(0) <= D(6); M7(0) <= D(7); when "00001" => M0(1) <= D(0); M1(1) <= D(1); M2(1) <= D(2); M3(1) <= D(3); M4(1) <= D(4); M5(1) <= D(5); M6(1) <= D(6); M7(1) <= D(7); when "00010" => M0(2) <= D(0); M1(2) <= D(1); M2(2) <= D(2); M3(2) <= D(3); M4(2) <= D(4); M5(2) <= D(5); M6(2) <= D(6); M7(2) <= D(7); usw. usw. bis "11111" end case; end if; end if; end process; end behavioral; Später wollte ich mit zB. ROWS <= M0; die Bits umsortiert wieder ausgeben.
Hi allein für die Speicherung der 256 Bit wirst du 256 Makrozellen brauchen. CPLDs und FPGAs sind, aufgrund ihres internen Aufbaus, denkbar ungeeignet zur Speicherung von Daten da dafür ein FF erforderlich ist und die sind sowohl in FPGAs als auch in CPLDs immer knapp. FPGAs habe deshalb z.T. Block-RAMs über den Chip verteilt. Das sind spezielle Blöcke die nur Daten speichern können aber ansonsten nicht zur Programierung geeignet sind (Evtl. noch als Look-Up Tabelle) Matthias
ich würde das mit einem ram lösen: ram initialisieren: type RAM_32_8 is array(31 downto 0) of std_logic(7 downto 0); signal MEM: RAM_32_8; schreiben: WRITE_RAM: process(CS) if CS'event and CS = '1' then if Wr = '0' then MEM(adresse) <= daten; end if; end if; end process WRITE_RAM; gruss tobias
Danke, auf eine ähnliche syndaktische Lösung bin ich heute nacht auch gekommen: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity test is port( A: in integer range 0 to 31; C: in integer range 0 to 7; D: in std_logic_vector(7 downto 0); CS,WR: std_logic; ROWS: buffer std_logic_vector(31 downto 0) ); end test; architecture behavioral of test is type RAM is array(integer range 0 to 7) of std_logic_vector(31 downto 0); signal Pixel: RAM; begin process(CS, WR, A, D, C) begin if CS = '1' and WR = '0' then Pixel(0)(A) <= D(0); Pixel(1)(A) <= D(1); Pixel(2)(A) <= D(2); Pixel(3)(A) <= D(3); Pixel(4)(A) <= D(4); Pixel(5)(A) <= D(5); Pixel(6)(A) <= D(6); Pixel(7)(A) <= D(7); else ROWS <= Pixel(C); end if; end process; end behavioral; es sind aber eben 256 FF's nötig, und beide Entwicklungsumgebungen Quartus und Xilinx ISP können mit dem VHDL nichts anfangen. Quartus bricht ab mit der Meldung das es kein entsprechende Device findet, das mehr als 352 Makrozellen unterstützt. Xilinx ISP meint das diese Design mindestens 577 Makrozellen benötigen würde. Erst mit der Deklartion von, type RAM is array(integer range 0 to 7) of std_logic_vector(11 downto 0); signal Pixel: RAM; also ein Bit Vector bei weitem zu klein für mich, reichen die Makrozellen aus. Das ist das erste Problem -> mein Design ist zu komplex weil es zu viele FF's benötigt und eben weil es die daten "überkreuz" ein-/auslesen will was dazu führt das für jedes Bit ein 1-Bit Latch benötigt wird. Soweit glaube ich die Sache verstanden zu haben, vielleicht irre ich mich ja !? Das zweite Problem entsteht dann im fertigen VHDL, das diese daten sozusagen als gemultiplexte PWM mit einem externen Takt an den Ausgängen anlegen sollte. Der obige VHDL Source ist also nur eine gestutzte Version die sich auf die "RAM" Zellen konzentriert. Wird aber mit der getakteten Version gearbeitet wollen beide Programme garnicht mehr compilieren. Gruß Hagen
Die Frage ist nun ob es denoch irgend ein Weg gibt das hinzubekommen. Ich hatte schon daran gedacht einen Mini-SRAM von 512 Bits anzuschließen, nur finde ich da nichts passendes. Gruß Hagen
Hallo Hast du schon eine Lösung für dieses Problem schon gefunden? Ich sitze an einem ähnlichen Problem. MFG Martin
Ja, ich arbeite an einer externen SRAM Ansteuerung. Der CPLD wird dabei mit 64 MHz getaktet. Teilt das runter mit 4 um für den AVR den 16MHz Talt zuliefern. Der AVR liegt mit AD0-AD7,A8-A15, WR\, RD\, ALE am CPLD an. Der externe SRAM, 128Kb, liegt ebenfalls mit IO0-IO7, A0-A16, OE, WR\, CS am CPLD an. Der SRAM ist ein 10-15ns Typ. Soweit die Hardware. Der CPLD steuert nun den Zugriff auf den SRAM. Ein SRAM Zugriff benötigt 1 kompletten CPLD Takt, also ca. 15ns. Der AVR greift innerhalb von 3 MCU Takten über sein XMEM Interface auf den CPLD zu. D.h. ein "LD Register, Addresse" benötigt 3 MCU Takte. Aber davon wird nur 1 MCU Takt lang tatsächlich die WR\ oder RD\ Leitung angesteuert. Der AVR benötigt also, asynchron zum Takt, minimal 63ns, wovon aber nur 21ns tatsächlicher Schreib-/Lesezugriff darstellt. Der Rest von 42ns wird für die ALE + Addresslatch benötigt. Der CPLD kann aber mit 15ns zugreifen und teilt somit die 21ns des AVR's in zwei teile auf. Insgesamt ergibt sich dadurch ein Ratio von 1 zu 5. D.h. inder gleichen Zeit wo der AVR eine SRAM Adresse ausliest kann der CPLD 5mal Speicheradressendddressen auslesen oder schreiben. Im Worstcase kann sich dies auf 2/3 reduzieren. Im Grunde wird daraus dann ein "Dual Port SRAM" bei dem der AVR und der CPLD gemultiplext in 50% der AVR Zugriffszeit auf den SRAM zugreifen. Der CPLD packt also in 1 AVR-MCU Takt = 1 Takt WR\, RD\ == Low Pegel insgesammt 2 Speicherzugriffe rein. Einen für den AVR und einen für den CPLD. Deshalb benötige ich 10-15ns SRAM, der aber leicht zu beschaffen ist. Für einen 32MHz CPLD Takt mit 1/3 Ratio habe ich schon ein VHDL fertig unter Quartus II simuliert. Aber ganz gefällt mir dies noch nicht da bei der Timing-Analyse einige Steuerleitungen nicht korrekt zu den Daten- Addressleitungen interagieren. Deshalb binich auch auf 64MHz CPLD höher gegangen. Nun, Hintergrund der ganzen Sache ist ein "Display-Controller" zu Ansteuerung von LEDs. Der CPLD und der AVR teilen sich einen SRAM der in Teilen den Display-RAM enthält. Desweiteren muß der CPLD nun dieses Display an die LEDs ausgeben. Dies erfordert ein Multiplexingund auch Farbdekodierung der Pixelwerte um die RGB-LEDs anzusteuern. Den Gedanken im CPLD selber die RAM Zellen zu integrieren habe ich komplett verworfen. Gruß Hagen
Ach mann, ich bin da mit den Timings durcheinander gekommen. 1 MCU Takt ist bei 16 Mhz natürlich 62ns lang. Bei Zugriff über XMEM auf erxterne Geräte fallen 3 Takte an. 2 Takte für den externen Addresslatch und 1 Takt zum realen lesen oder schreiben ins SRAM. Somit benötigt ein "LD register, Addresse" 186ns Zeit. Der CPLD greift mit 30ns auf den SRAM zu,und kann so in 1 AVR MCU Takt a 62ns zwei komplette SRAM Zugriffe reinpacken. Einer dieser Zugriff befriedigt die Lese/Schreibanforderung des AVRs und der andere steht dem CPLD zur Verfügung. Da der AVR aber 3 MCU Takte benötigt heist die das im Normalfalle der CPLD 5 mal öffter als der AVR aus dem SRAM lesen/schreiben kann. Dieses Sharing muss man beim AVR benutzen weil laut Atmels Datenblättern das XMEM Interface asynchron zum AVR Takt ist. D.h. durch Temperatur-/Spanungsdrifts verändern sich die Slopes und es gibt laut Atmel keine Möglichkeit über einen externen synchronen Takt verschiedene externe Geräte mit dem AVR XMEM Interface zu synchronisieren. In kurz: die Lese-/Screibanforderungen des AVR's an den CPLD kann zum CPLD Takt asynchron erfolgen. Damit der CPLD wieder "synchron" zur Anforderung des AVRs wird muß dessen Timing also 2 mal größer als das des AVR's sein. Gruß Hagen
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.