Hallo, ich habe auf meine Bastelplatine auch einen RAM mit HyperBus Interface gelötet. https://www.mouser.de/datasheet/2/198/66-67WVH8M8ALL-BLL-938852.pdf Das habe ich getan weil der nur wenige FPGA IOs benötigt und doch recht groß und schnell ist. Das ist jetzt der letzte Bausteion auf dem Board den ich in Betrieb nehme und dazu habe ich ein paar Fragen zwecks Herangehensweise: Der Stein kann ziemlich viel, lineare Bursts, wrapped Bursts, aber immer Bursts, die Burstlänge ist einstellbar und wenn man nur einzelne Bytes/Adressen schreiben will muss man eben während der restlichen Adressen im Burst das Mask Bit RWDS setzen damit die Daten nicht geschrieben werden. Aber vieles brauche ich auch nicht. Ich will eigentlich nur linear lesen und schreiben. Daten vom ADC in das RAM und dann wieder vom RAM um es über USB zu schaufeln. Ich denke daher an ein Interface zu meinem zu schreibenden Controller das gleich 32Byte breit ist, ein paar Handshaking Signale hat und noch die Startadresse des Bursts/Pageadresse übergibt. Macht das Sinn oder vielleicht als generelle Frage: Sollte man sehr breite Interfaces im FPGA vermeiden und die Daten lieber seriell übertragen? Als Alternative könnte ich auch einen kleinen Speicher einbauen. Dann wird immer gewartet bis der voll ist, dann wird das in den RAM geschrieben und wieder gewartet. Und dann ist mir die Speicherorganisation noch etwas unklar. Es gibt die Bits 44-16 das ist Row & Upper Column Address. Dann gibt es noch die Bits 2-0, Lower Column Address. Lower Column component of the target address: System word address bits A2-0 selecting the starting word within a half-page. Und die Fußnoten: 1. A Row is a group of words relevant to the internal memory array structure and additional latency may be inserted by RWDS when crossing Row boundaries - this is device dependent behavior, refer to each HyperBus device data sheet for additional information. Also, the number of Rows may be used in the calculation of a distributed refresh interval for HyperRAM memory. 2. A Page is a 16-word (32-byte) length and aligned unit of device internal read or write access and additional latency may be inserted by RWDS when crossing Page boundaries - this is device dependent behavior, refer to each HyperBus device data sheet for additional information. 3. The Column address selects the burst transaction starting word location within a Row. The Column address is split into an upper and lower portion. The upper portion selects an 8-word (16-byte) Half-page and the lower portion selects the word within a Half-page where a read or write transaction burst starts. 4. The initial read access time starts when the Row and Upper Column (Half-page) address bits are captured by a slave interface. Continuous linear read burst is enabledby memory devices internally interleaving access to 16 byte half-pages. Wenn also ein Burst 32 Bytes lang ist, dann sind das 16 Words. Da hätte ich jetzt 4 Bits erwartet als Adresse und nicht nur 3. Ich würde gerne die LSBs immer auf 0000 lassen und so nur ganze Pages schreiben. Macht das Sinn? Und noch eine Frage: Habt ihr so einen Stein schon mal verwendet? Zusatz: Ja, ich weiß dass es IP dazu gibt. Diese will ich aber nicht verwenden weil ich das selber machen möchte und weil ich mir auch keinen Prozessor oder sonst wie AXI ins System holen möchte. Wie machen das eigentlich richtige Speichercontroller mit dem Management? Ich stelle mir das schwierig vor wenn das System dem Controller nur Adressen und Daten zum Schreiben oder Lesen gibt. Ich stelle mir das so vor, dass der Controller Adressen und Daten zusammen in eine Cue packt und dort dann so umsortiert, dass er möglichst viele Daten zusammenhängend in Bursts lesen kann. Das hat dann aber das Problem, dass der Controller ja nicht ewig warten kann. Wenn also noch ein paar Adressen zu lesen sind die nicht zu einem Burst passen muss er das trotzdem tun irgendwann. Und dann ist noch das Problem, dass das System die Daten nicht in der Reihenfolge zurückbekommt in der es die Leseanfragen an den Controller gegeben hat. Vermutlich ist das eine ganze Wissenschaft für sich. Danke!
Gustl B. schrieb: > Sollte man sehr breite Interfaces im FPGA vermeiden und die Daten lieber > seriell übertragen? Als Alternative könnte ich auch einen kleinen > Speicher einbauen. Dann wird immer gewartet bis der voll ist, dann wird > das in den RAM geschrieben und wieder gewartet. Noe, da kannst du ruhig zulangen. Wenn du Speicher Controller hast, dann hast du ziemlich oft breite Datenbusse (z.B. 320 bit sind da keine Seltenheit). Wenn das einigermassen vernuenftig gemacht ist, kommt man da auch auf ein paar 100 MHz Taktrate ohne Probleme zu bekommen. Gustl B. schrieb: > Wie machen das eigentlich richtige Speichercontroller mit dem > Management? Ich stelle mir das schwierig vor wenn das System dem > Controller nur Adressen und Daten zum Schreiben oder Lesen gibt. Ich > stelle mir das so vor, dass der Controller Adressen und Daten zusammen > in eine Cue packt und dort dann so umsortiert, dass er möglichst viele > Daten zusammenhängend in Bursts lesen kann. Das hat dann aber das > Problem, dass der Controller ja nicht ewig warten kann. Wenn also noch > ein paar Adressen zu lesen sind die nicht zu einem Burst passen muss er > das trotzdem tun irgendwann. Und dann ist noch das Problem, dass das > System die Daten nicht in der Reihenfolge zurückbekommt in der es die > Leseanfragen an den Controller gegeben hat. Vermutlich ist das eine > ganze Wissenschaft für sich. Gute Controller machen das auch. Kannst ja mal die Doku zum Xilinx MIG durchlesen um dir Inspiration zu holen.
:
Bearbeitet durch User
OK, ja mein Problem ist eher zu entscheiden welche Features alles rein sollen und welche nicht. Wenn ich jetzt auch Zugriffe auf einzelne Adressen, unterstützen möchte, dann muss ich die anderen Bytes im Burst maskieren. Und dann muss ich entweder den Controller schlauer machen (was ich nicht will) oder das System muss dem Controller sagen können ob jetzt eine einzelne Adresse oder eine Page gelesen werden soll. Edit: Oder ist das vielleicht sogar üblich, dass das Betriebsystem sagt ob es jetzt eine Adresse oder eine Page lesen möchte? Die andere Frage hat sich geklärt: During linear transactions, accesses start at a selected location and continue in a sequential manner until the transaction is terminated when CS# returns High. Das ist schön, ich kann mir also eine Länge aussuchen. Eher zwei Längen. Ich werde vermutlich das Lesen/Schreiben von einzelnen Words und von Bursts mit 16 Words(=Page) bauen. Dann habe ich noch den hier gefunden: https://github.com/gtjennings1/HyperBUS Der hat input [31:0] i_mem_wdata, output [31:0] o_mem_rdata, 32 Bit Daten. Das macht an der Stelle vermutlich Sinn weil das für einen 32 Bit RiscV gedacht ist, aber das ist auch recht langsam. Das sind nur zwei Takte für die Datenübertragung, aber mindestens sechs Takte für Command und Warten. Naja ... war vermutlich ein Kompromiss weil man sonst eben einen schlaueren Controller bräuchte der Bursts kann und so.
:
Bearbeitet durch User
Willst du dir das wirklich antun, einen eigenen Hyperbuscontroller zu schreiben? Da kann man eine ganze Menge Zeit drin versenken. Wir haben diesen Controller verwendet : https://www.cypress.com/documentation/software-and-drivers/hyperbus-master-interface-controller-ip-intellectual-property Der ist als Verilog-Code verfügbar und kostet nix, außer der Registrierung bei Cypress. Im Nachfolgedesign werden wir diesen einsetzen: https://github.com/pulp-platform/udma_hyperbus/tree/master/rtl Das ist im Prinzip eine komplette Neuimplementierung in SystemVerilog und funktional dem Cypress-Core weitgehend identisch, aber vollständig OpenSource. Kann aber sein, dass der Richtung RISCV-Systeme optimiert ist.
Vancouver schrieb: > Willst du dir das wirklich antun, einen eigenen Hyperbuscontroller zu > schreiben? Da kann man eine ganze Menge Zeit drin versenken. Ja schon, ist nur zu Lernzwecken. Vancouver schrieb: > SystemVerilog Das kann ich (noch) nicht. Und kann daher nicht beurteilen ob der Controller Bursts unterstützt oder nur 32Bit Transaktionen. Ich brauche auf jeden Fall Bursts wenn ich 100 MBytes/s wegschreiben können will. Der Cypress IP, welchen Anschluss hat der intern? Ist das AXI? Kann man den auch ohne CPU bedienen oder würde das extrem umständlich? Ich habe mit dem Microblaze bisher nur sehr wenig gemacht. Zur Rechenleistung gibt es schon Angaben im Netz, aber wie sieht es beim Datendurchsatz aus? Schafft der es die 100 MBytes/s vom ADC zum RAM zu schaufeln?
Gustl B. schrieb: > Ich habe mit dem Microblaze bisher nur sehr wenig gemacht. Zur > Rechenleistung gibt es schon Angaben im Netz, aber wie sieht es beim > Datendurchsatz aus? Schafft der es die 100 MBytes/s vom ADC zum RAM zu > schaufeln? Unwahrscheinlich. Aber sowas würde ich eine DMA-Engine, die direkt am Speichercontroller hängt machen lassen. Duke
Duke Scarring schrieb: > DMA-Engine Genau sowas gibt es. Das ist auch fein wenn immer neue Daten nachkommen, aber ich habe da wieder so eine Angst die mich dann Dinge selbst schreiben lässt: Z. B. kann man ich ja bei Xilinx einen FIFO generieren lassen als IP. Ich verwende den auch in manchen Projekten. Wie ist das wenn ich nur eine Bestimmte endliche Datenmenge übertragen möchte, z. B. 16 Bytes. Dann will ich am Ziel auch genau diese 16 Bytes haben - und zwar vollständig. Der FIFO hat aber die Einstellung, dass der das Empty Flag schon setzt wenn noch Daten drinnen sind. Bei einem kontinuierlichen Datenstrom ist das OK, auch sonst könnte man die Daten die man haben will durch zusätzliche Daten "durchspülen". Das sind so Dinge die ich bei einem AXI System aus der Hand gebe. Wenn ich so einem DMA IP dann eine Anzahl an Bytes gebe, landen die alle im RAM auch wenn das kein kontinuierlicher Datenstrom ist? Ich müsste mir das mal zusammenklicken und gucken ... habe ich noch nicht gemacht.
Ist dieser Hyper-RAM so gestrickt wie ein Cellular-RAM? Z.B. Micron MT45W4MW16BCGB?
Teilweise. Also ja, das ist ebenfalls pseudostatisch, aber du hast keine getrennten Daten und Adressleitungen. Sondern man hat nur 8 Leitungen (+Clock und so) und darüber wird zuerst in ein paar Takten ein Kommando übertragen, dann folgt eine Wartephase und dann werden da die Daten übertragen, DDR. Das ist also beim Burst schön schnell (333 MByte/s maximal), aber wenn nur einzelne Bytes an zufällige Adressen geschrieben werden sollen, dann bricht die Transferrate auch sehr stark ein. Das ist eben ein DRAM und das Übertragen vom Kommando kostet bei Einzelzugriffen schon mehr Zeit als die Datenübertragung selbst. Bei mir ist das egal, ich will das nur als Samplespeicher verwenden. Da werden in großen Bursts 100 MByte/s hingeschrieben bis das RAM voll ist oder eben die Zahl der aufzunehmenden Samples, und dann wird langsam daraus gelesen und zum PC übertragen. Oben hatte ich ein PDF verlinkt, da kann man das Timing schön sehen. Das ist also eher ein serielles Interface wie SPI, nur eben OctaSPI mit DDR und Wartephasen und bidirektionalen Leitungen.
Gustl B. schrieb: > Ja schon, ist nur zu Lernzwecken. Das ist ein Argument, aber wie gesagt, der Aufwand ist nicht zu unterschätzen. Gustl B. schrieb: > Der Cypress IP, welchen Anschluss hat der intern? Ist das AXI? Ja, AXI3 und AXI4. Gustl B. schrieb: > Kann man > den auch ohne CPU bedienen oder würde das extrem umständlich? Der Controller hat einige interne Register, die gesetzt werden müssen. Z.B, gibt es ein Setting, das ein Timing feingranular verschiebt, danmit es passt. Das muss sogar im laufenden Betrieb hin und wieder gemacht werden, wenn die Temperatur das Timing verändert. Du brauchst auf jeden Fall einen Controller, der das alles macht. Ob der Aufand ohne CPU zu groß ist, liegt in Deinem Ermessen. Wir betreiben den Controller an einem DMA mit einem RISCV. Gustl B. schrieb: > aber wie sieht es beim > Datendurchsatz aus? Schafft der es die 100 MBytes/s vom ADC zum RAM zu > schaufeln? Ohne DMA wird das sportlich, zumindest, wenn der MB noch andere Dinge tun soll. Gustl B. schrieb: > Wenn > ich so einem DMA IP dann eine Anzahl an Bytes gebe, landen die alle im > RAM auch wenn das kein kontinuierlicher Datenstrom ist? Aber natürlich. DMA hätte keinen Sinn, wenn die letzten Bytes irgendwo hängen bleiben. Ein DMA-Controller erzeugt erst einen Interrupt, wenn alle Daten übertragen wurden. Gustl B. schrieb: >> SystemVerilog > > Das kann ich (noch) nicht. Und kann daher nicht beurteilen ob der > Controller Bursts unterstützt oder nur 32Bit Transaktionen. Dazu müsste ich nochmal Kolleggah interviewen, aber soweit ich weiß, haben wir den Controller ausgewählt, weil der die HB-Spec vollständig umsetzt. Wenn du VHDL kannst, sollte es aber kein allzu großes Problem sein, den SV-Code zumindest in groben Zügen zu verstehen. Learning by reading :-) Nach fast 15 Jahren VHDL habe ich SV ziemlich schnell gelernt, auch wenn ich noch längst nicht alle Details kenne.
Vancouver schrieb: > unterschätzen Kann ich, hab ich schon mal gemacht. Vancouver schrieb: > AXI3 und AXI4. Habe ich ebenfalls schon mal gemacht, ohne CPU. Da habe ich den XADC und mal den UARTlite von Xilinx bedient. Quasi einen billigen AXI Master gespielt. War nicht irre schwer. Vancouver schrieb: > Der Controller hat einige interne Register, die gesetzt werden müssen. > Z.B, gibt es ein Setting, das ein Timing feingranular verschiebt, danmit > es passt. Also dass ich im RAM vielleicht die Configregister beschreiben muss ist OK, aber das Timing nachträglich korrigieren und die Temperatur überwachen? Nein. Da gehe ich lieber mit dem Takt runter. Mir reichen ja 100 MBytes/s. Bei 1,8 V kann das RAM 166 MHz, ich betreibe den Rest im FPGA großteils mit 100 MHz und wollte das auch mit dem RAM machen. Also 200 MHz DDR. Das sollte entspannt funktionieren. Vancouver schrieb: > Aber natürlich. DMA hätte keinen Sinn, wenn die letzten Bytes irgendwo > hängen bleiben. Ein DMA-Controller erzeugt erst einen Interrupt, wenn > alle Daten übertragen wurden. Danke! Vancouver schrieb: > Learning by reading :-) So mache ich das auch oft, ob man wirklich alle Details kennen sollte weiß ich nicht. Ich komme auch ganz gut mit einem Teil aus VHDL zurecht. Aber man kann immer was dazulernen.
So, ich laufe gerade in einige Fragen hinein: Dieser HyperBus verlangt, dass bei der Übertragung vom FPGA zum RAM die Daten so anliegen, dass die Taktflanke mittig in den Daten liegt. Das muss ich also beim Übertragen der 6 Bytes für das Command und beim Schreiben in das RAM einhalten. Wenn ich aus dem RAM lese, dann treibt der RAM das RWDS Signal und legt die Daten passend dazu an, und zwar wieder so, dass die RWDS Flanken schön mittig in den Daten liegen. Meine Fragen sind jetzt welche Hardwareblöcke ich verwenden sollte. Biesher habe ich jetzt den SelectIO Wizard verwendet, und ein bidirektionales DDR Interface erzeugt. Da kann ich aber die ausgegebenen Daten nicht gegenüber dem ausgegebenen Takt verzögern. Es kommt also sowas raus wie in Screenshot, da liegt die Flanke nicht mittig in den Daten. Wäre es vernünftiger Datenausgabe, Dateneinlesen und Clock komplett getrennt zu machen, also nicht über einen SelectIP IP? Z. B. einen IP oder so zum einlesen der DDR Daten mit RWDS und einen IP zur Datenausgabe und noch einen IP/ODDR zur Taktausgabe. Und noch einen ODDR zur Taktausgabe für die phasenverschobene Clock PSC. Das Tristate würde ich dann in der Toplevel VHDL machen. Dann möchte ich das schön einfach halten und "nur" die 100 MHz verwenden die synchron zum Rest des Systems sind. Ist das der richtige Weg, oder wäre es sinnvoll da 200 MHz verwenden damit ich die Daten bei 100 MHz um einen halben Takt verschoben ausgeben kann? Dann könnte ich auch den Takt quasi manuell ausgeben.
:
Bearbeitet durch User
So, ODELAY gibt es in HR Bänken nicht ... und der Spartan hier hat nur HR Bänke. Naja, gut. Ich könnte jetzt mit 4 Takten arbeiten: 1. Der 100 MHz Takt zu dem ich die Daten mit dem SelectIO IP als DDR ausgebe. 2. Ein um 90° verschobener 100 MHz Takt den ich dann differentiell als CK und CK# ausgebe. 3. Ein weiterer gegebüber 1. um 180° verschobener 100 MHz Takt den ich als PSCK und PSCK# ausgebe. 4. Beim Lesen treibt der RAM Stein das Signal RWDS, das ist dann also auch ein Takt mit dem ich die DDR Daten übernehme. Würde man die Verschiebung von 2. und 3. mit Constraints lösen? Also dass 2. um 2.5 ns nach 1. oder nach den Daten anliegt und dass 3. noch mal 2.5 ns später ausgegeben wird?
So, jetzt mit passenden Takten. Die kommen jetzt aber alle aus einem MMCM und werden je über ein OBUFDS ausgegeben.
Hast du mal die Setup und Hold Zeiten als Constraints in deiner XDc angegeben? Jenachdem wie kritisch die sind, brauchst du da nicht von Hand an der Phase rumfummeln. Wie klein/gross sind den Setup & Hold?
Tobias B. schrieb: > Hast du mal die Setup und Hold Zeiten als Constraints in deiner XDc > angegeben? Bisher noch nicht. Tobias B. schrieb: > Jenachdem wie kritisch die sind, brauchst du da nicht von > Hand an der Phase rumfummeln. Ja, was wird denn dann durch Routingdelay verschoben? Der Takt nach hinten? Tobias B. schrieb: > Wie klein/gross sind den Setup & Hold? Bei 100 MHz ist das jeweils 1 ns. Im Datenblatt steht center aligned drinnen, und daran wollte ich mich halten. Bei 100 MHz liegen die Daten maximal 5 ns an. Davon müssen sie 2 na stabil sein, also 1 ns vor der Taktflanke und 1 ns nach der Taktflanke. Ich finde das ist recht entspannt. Selbst bei maximalem Takt von 166 MHz sind Setup und Hold nur 0,6 ns. Da ist also eine Periode 6 ns, eine halbe Periode also 3 ns die die Daten maximal anliegen könnten und davon genügen 1,2 ns um die Taktflanke herum.
So, da bin ich wieder ... meine Testbench macht schon den Schreibevorgang wie im Datenblatt, aber ob das wirklich passt und um auch aus dem RAM zu lesen brauche ich jetzt das RAM in der Simulation. Und das gibt es auch, aber es verwendet Dinge die mein Vivado nicht kennt:
1 | LIBRARY IEEE; |
2 | USE IEEE.std_logic_1164.ALL; |
3 | USE IEEE.VITAL_timing.ALL; |
4 | USE IEEE.VITAL_primitives.ALL; |
5 | USE STD.textio.ALL; |
6 | |
7 | LIBRARY FMF; |
8 | USE FMF.gen_utils.all; |
9 | USE FMF.conversions.all; |
Tja was kann ich da machen? Wenn ich das nicht simulieren kann würde ich mir selber eine Testbench schreiben die RAM spielt. Und wenn das passt würde ich eben auf der Hardware testen. In dem .zip hier https://www.cypress.com/verilog/s27kl0641-verilog ist auch das VHDL Modell und eine Testbench drinnen.
Modelsim müsste die notwendigen VITAL2000-Libraries mitbringen. Den Rest gibt's da, wo Du das model her hast. [edit: nö, da: https://freemodelfoundry.com/packages.php]
:
Bearbeitet durch User
Markus F. schrieb: > Modelsim müsste die notwendigen VITAL2000-Libraries mitbringen. GHDL auch. Evtl. muss man da aber mit dem -frelaxed-rules Switch arbeiten.
OK, danke. Für dieses Projekt würde ich schon gerne bei dem Vivado Simulator bleiben. Wie ist das "draußen", welcher Simulator hat da grob welche Marktdurchdringung?
Gustl B. schrieb: > Wie ist das "draußen", welcher Simulator hat da grob welche > Marktdurchdringung? Das kann man so pauschal nicht sagen. Haengt stark vom Projekt, der Sicherheitsklasse, den Prozessen und letztendlich auch vom Budget ab.
Gustl B. schrieb: > OK, danke. Für dieses Projekt würde ich schon gerne bei dem Vivado > Simulator bleiben. Hat keiner gesagt, dass Du den Simulator wechseln sollst...
@ Tobias B.: Es gibt also keinen "Industriestandard"? Nun, die Tipps hier haben waren Modelsim und GHDL, das klingt für mich danach, dass ich nicht den Vivado Simulator nutzen sollte.
Gustl B. schrieb: > Nun, die Tipps hier haben waren Modelsim und GHDL, das klingt für mich > danach, dass ich nicht den Vivado Simulator nutzen sollte. Beide genannten Pakete enthalten die VITAL2000 Quellen
OK, ich habe noch nicht wirklich verstanden was die VITAL2000 Teile sind. Ist das sowas wie das IEEE das ich in einen Ordner kopieren muss damit es vom Simulator gefunden werden kann?
Gustl B. schrieb: > @ Tobias B.: Es gibt also keinen "Industriestandard"? > > Nun, die Tipps hier haben waren Modelsim und GHDL, das klingt für mich > danach, dass ich nicht den Vivado Simulator nutzen sollte. Jeder nutzt das womit er glaubt seine Ziele zu den geringsten Kosten zu erreichen. Ich kenne keinen Standard oder Norm welche vorschreibt dass dieser oder jener Simulator verwendet werden muss. Die Questa Produktfamilie von Mentor hat zum Beispiel eine ISO 26262 Zertifizierung, siehe z.B.: https://www.mentor.com/company/news/mentor-achieves-iso-26262-cert-questa-product-tool-qualification-report D.h. aber noch lange nicht, dass ich nur mit ISO 26262 zertifizierten Tools entsprechend entwickeln darf. (Falls das falsch sein sollte, bitte jemand korrigieren, ich komme aus der Medizin und hab mit Automotive nicht viel am Hut.) Eine Uebersicht findest du hier https://en.wikipedia.org/wiki/List_of_HDL_simulators inkl. einer MArkierung der "Big 3". Wobei auch die Big 3 relativ sind, stark Branchen abhaengig und nicht wirklich auf empirischen Daten beruhend (dazu kommt noch dass diese auch den ASIC Markt beherrschen). Was ma jedoch ziemlich sicher sagen kann: Die Big 3 sind auch die Top 3 unter den Preisen. ;-)
:
Bearbeitet durch User
Danke! Ich habe mir aber jetzt selber einen RAM Baustein geschrieben für die Simulation. Funktioniert auch schon alles wunderbar in der Simulation. Ich habe mich jetzt entschieden, dass ich einzelne 2 Byte (das ist ein Takt und 1 Word) Transfers und lineare Bursts mit 64 Bytes unterstütze. Beides lesend und schreibend. Tja warum 64 Bytes? Nun wenn ich die Config Register im RAM nicht anfasse, dann hat das 6 Takte Latenz und immer die zweifache Latenz (RWDS = '1'). Wenn ich einen 32 Byte Burst mache, dann brauche ich dafür 1+2+2*6+16+1+1 = 33 Takte, Damit liege ich bei 100 MHz unter den angepeilten 100 MBytes/s. In den Config Registern könnte ich die Latenz auf 4 Takte runtersetzen bei 100 MHz, aber ... wenn ich das nicht muss lass ich das. Bei 64 Byte Bursts brauche ich 1+2+2*6+32+1+1 = 49 Takte, also 490 ns bei 100 MHz. Das macht dann 64Bytes*1s/490ns macht 130,6 MBytes in einer Sekunde. Aber: Das sind jetzt echt viele Bits/Leitungen im FPGA. 512 hin und 512 zurück ... mal gucken ob das auch auf Hardware funktioniert.
So, ... es baut nicht. [Route 35-54] Net: HyperRAM_RWDS_IOBUF_inst/O is not completely routed. [Route 35-7] Design has 1 unroutable pin, potentially caused by placement issues. Ja was ist das? Nun, beim HyperBus ist es so, dass es ein RWDS Signal gibt. Wenn man in den RAM schreibt, dann kann man mit dem RWDS die Daten maskieren. Wenn man aus dem RAM liest, dann ist das RWDS der Takt mit dem man die Daten vom RAM eintaktet. Ich habe mir also mit dem SelectIO IP das bauen lassen:
1 | component HyperBus_IN generic( |
2 | SYS_W: integer := 8; |
3 | DEV_W: integer := 16); |
4 | port( |
5 | data_in_from_pins : in std_logic_vector(SYS_W-1 downto 0); |
6 | data_in_to_device : out std_logic_vector(DEV_W-1 downto 0); |
7 | delay_locked : out std_logic; |
8 | ref_clock : in std_logic; |
9 | clk_in : in std_logic; |
10 | clk_out : out std_logic; |
11 | io_reset : in std_logic); |
12 | end component; |
Und verwende das so:
1 | HB_IN: HyperBus_IN port map( |
2 | data_in_from_pins => DQ_IN, |
3 | data_in_to_device => RX_Data, |
4 | delay_locked => open, |
5 | ref_clock => MMCMCLK200, |
6 | clk_in => RWDS_IN, |
7 | clk_out => DQ_IN_CLK, |
8 | io_reset => '0'); |
RWDS ist natürlich ein inout, also habe ich den als Tristate beschrieben:
1 | RWDS <= RWDS_OUT when RWDS_tristate = '0' else 'Z'; |
2 | RWDS_IN <= RWDS; |
Weil ich nicht weiß wie ich das korrekt löse, wäre mein nächster Ansatz, den RWDS nicht als inout, sondern nur noch als in zu beschreiben, aber mit Pulldown. Ja, dann kann ich keine Bits maskieren, aber das habe ich sowieso nicht vor. Gibt es eine bessere Lösung?
Ja "Fehler" gefunden. Und zwar habe ich RWDS_IN nicht nur an den IP Block gegeben, sondern auch zusätzlich noch an einer Stelle verwendet. Aber das muss ich ja auch machen, denn am Anfang der Transaktion ist RWDS noch keine Clock oder Maskierung, sondern zeigt an ob das RAM einfache oder doppelte Latenz für die Daten benötigt. Ich habe jetzt RWDS nur als in mit Pulldown beschrieben und das baut. Edit: Jetzt wieder als inout, aber bei dem IP habe ich nicht external sondern internal Clock angegeben und verwende dort das RWDS_IN.
:
Bearbeitet durch User
Tobias B. schrieb: > Jeder nutzt das womit er glaubt seine Ziele zu den geringsten Kosten zu > erreichen. "Wir sparen, egal was es kostet" ist ein beliebtes Sprichwort hier unter den Ingenieuren. Nichts kaufen (Softwaretools, Schulungen, Bücher, Busanalyzer, Messgeräte, Build-Server, Rapid-Prototyping Systeme...), dafür mehr Personenstunden ist bei Schweizerlöhnen vielleicht nicht die Variante mit den geringsten Kosten...
Ja, das ist nicht optimal. Wahrschenlich fallen entsprechende Firmen bei noch mehr Punkten im Joel Test durch. ;-) Aber zum Glueck arbeiten nicht alle so.
Tobias B. schrieb: > Ja, das ist nicht optimal. Wahrschenlich fallen entsprechende Firmen bei > noch mehr Punkten im Joel Test durch. ;-) In einer früheren Firma hatte ich den Joel Test mal in der Kaffeeecke aufgehängt (Die war gerade von 3 auf 4 Punkte raufgeklettert durch einführen von Versionskontrolle). Leider keine Reaktion... Was auch Spass macht, ist den Joel Test VOR einem Bewerbungsgespräch zur Beantwortung einzusenden.
1. Do you use source control? 2. Can you make a build in one step? 3. Do you make daily builds? 4. Do you have a bug database? 5. Do you fix bugs before writing new code? 6. Do you have an up-to-date schedule? 7. Do you have a spec? 8. Do programmers have quiet working conditions? 9. Do you use the best tools money can buy? 10. Do you have testers? 11. Do new candidates write code during their interview? 12. Do you do hallway usability testing? Bei 2.: Was ist denn überhaupt ein "build"? Man kann immer den letzten Schritt einer langen vielschritten Kette als den "build" definieren und der läuft dann auch in einem Schritt. Oder ist das Starten eines Skripts ein Schritt? Bei 3.: Was für ein Blödsinn, es reicht neu zu bauen wenn man auch was am Code geändert hat. Bei 5.: Einige Bugfixes SIND neuer Code. Bei 6.: Es gibt nichts was immer aktuell ist. Die Frage ist wie schnell es aktualisiert wird. Bei 9.: Total sinnlos weil das oft eine Abwägung ist. Ja, eine kleine Firma könnte sich das weltbeste Tool kaufen dass dann noch ein klein wenig besser ist als das was sie derzeit nutzen, aber danach ist die Firma eben pleite. Und wieso überhaupt kaufen? Da zählen also Clang und GCC schon mal nicht zu Tools die verwendet werden dürfen. Ja, sind gute Punkte dabei, aber wirkt wenig durchdacht. Edit: Mit wenig durchdacht meine ich vor allem die Formulierung. Bei 5. z. B. hätte man schreiben können und auch sollen: 5. Do you fix bugs before implementing new features.
:
Bearbeitet durch User
Christoph Z. schrieb: > In einer früheren Firma hatte ich den Joel Test mal in der Kaffeeecke > aufgehängt (Die war gerade von 3 auf 4 Punkte raufgeklettert durch > einführen von Versionskontrolle). Leider keine Reaktion... Dann hilft nur das Weite zu suchen. Nix ist schlimmer als eine Firma die ihre Probleme kennt, aber egal sind. Christoph Z. schrieb: > Was auch Spass macht, ist den Joel Test VOR einem Bewerbungsgespräch zur > Beantwortung einzusenden. Das haette ich mich damals nach der Uni nicht getraut und jetzt wo ich selbststaendig bin gibts keine Gelegenheit mehr. Aber den Tipp geb ich auf jedenfall weiter! :-) @Gustl B. Was der Joel Test beschreibt sind CI Prozesse in einfachen Fragen, diese sollte man als Experte nicht allzu woertlich nehmen, wir verstehen aber deren Kern sehr wohl. Da du noch sehr weit davon entfernt bist das zu verstehen, solltest du eine Bewertung des Joel Tests eher vermeiden. Das wuerde man dir als Mangel von Expertise auslegen und eher peinlich enden. Was man evtl. schon anmerken kann ist, dass der Test knapp 20 Jahre alt ist, und seiner damaligen Zeit extrem vorraus war. Heute wuerde man den Test vll. ein bisschen zeitgemaesser machen, was den natuerlich eher strenger macht. Kleiner Edit: Hier https://www.joelonsoftware.com/2000/08/09/the-joel-test-12-steps-to-better-code/ sidn auch die Anmerkungen vom Autor selbst. An sich ist die ganze Seite sehr interessant und mit vielen inspirierenden Geschichten.
:
Bearbeitet durch User
Natürlich verstehe ich den Hintergrund der Fragen, aber ich finde Fragen sinnfrei die entweder schlecht gestellt sind oder nicht zu ernst genommen werden sollen. Was ist das eigentlich ausser Kompexitätsmanagement? Das läuft schon lange so, dass die Komplexität immer weiter wächst und statt dass man dann auf den UNIX Ansatz geht versucht man die Komplexität in den Griff zu bekommen indem man aussen noch was dranbaut. Das macht dann jeder so und plötzlich ist es "Industriestandard". Nur weil eine Mehrheit etwas so macht bedeutet das nicht, dass es gut ist. Man kann sich mal gut angucken wie die Größe von quasi allem gestiegen ist. Irre fette Websites (https://player.vimeo.com/video/147806338 ), fette "Apps", ... und was kann es? Nicht wirklich mehr als vor 20 Jahren (2004 hatte ich ein Smartphone MPX200 mit Windows, Office, Browser, Spielen, Paint, Explorer, Outlook, Telefon/SMS und Musikplayer - in 32 MByte Flash). Aber weil es jetzt so fett ist ist es schlechter wartbar. Statt das zu beheben, also das Problem mal an der Wurzel zu packen hat man oben noch ein wenig Komplexität draufgeworfen um die Komplexität drunter besser verwalten zu können. Und wenn das dann so irre komplex ist, dass das System nurnoch auf genau dem System läuft auf dem es gebaut wurde dann ... packt man das einfach in eine VM/Qube/Cabinet/Container und liefert es einfach komplett aus (-: Tolle Welt, aber nicht das was ich will. Sollte ich je nach einem Job in der Wirtschaft suchen dann ganz bestimmt nicht als Komplexitätsverwalter.
:
Bearbeitet durch User
Gustl B. schrieb: > Bei 2.: Was ist denn überhaupt ein "build"? Man kann immer den letzten > Schritt einer langen vielschritten Kette als den "build" definieren und > der läuft dann auch in einem Schritt. Oder ist das Starten eines Skripts > ein Schritt?
1 | git clone |
2 | make all |
Mehr soll nicht nötig sein (natürlich sind andere build Systeme erlaubt) Also das Gegenteil von (alles schon durchgemacht, nicht gerade alles so auf einmal): 1 Code vom Server kopieren (weil keine Versionskontrolle) 2 Projekt in IDE erstellen oder alle Pfade korrigieren (weil IDE zu doof und absolute Pfade benutzt) 3 Projekt Einstellungen setzen gemäss README (oder Word Dokument...) 4 Alle nötigen Schritte in der IDE/mehreren Tools ausführen bis eine Datei da ist, die man aufs Target laden kann (oder Windows Installer, Debian Packet, zip Datei mit Gerber Daten,...) 5 Programmiersoftware starten und gemäss Word Dokument alles richtig anklicken 6 Nach Hause gehen, weil der Arbeitstag schon vorbei ist. Punkt 4 ist z. B. mit Vivado und Vivado SDK besonders lustig für Leute die das nur alle paar Wochen machen. Die verlieren bei uns jedesmal ein paar Stunden bis es wieder klappt. Gustl B. schrieb: > Bei 9.: Total sinnlos weil das oft eine Abwägung ist. Ja, eine kleine > Firma könnte sich das weltbeste Tool kaufen dass dann noch ein klein > wenig besser ist als das was sie derzeit nutzen, aber danach ist die > Firma eben pleite. Und wieso überhaupt kaufen? Da zählen also Clang und > GCC schon mal nicht zu Tools die verwendet werden dürfen. Punkt 9 wird immer gerne kontrovers diskutiert. Ist auch provokativ formuliert, wohl bewusst. "A fool with a tool is still a fool", freie Software ist nicht Gratis. Bücher, Schulungen, Support mit kurzen Reaktionszeiten kosten oder die Firma zahlt mehr Einarbeitungszeit. Ist eine Abwägung. Ach ja, aktuelle Firma läuft bei 5 Punkten...
:
Bearbeitet durch User
Christoph Z. schrieb: > Punkt 9 wird immer gerne kontrovers diskutiert. Ist auch provokativ > formuliert, wohl bewusst. > > "A fool with a tool is still a fool", freie Software ist nicht Gratis. > Bücher, Schulungen, Support mit kurzen Reaktionszeiten kosten oder die > Firma zahlt mehr Einarbeitungszeit. Ist eine Abwägung. Ich denke der Punkt war Anno 2000 schon noch korrekt. Heutzutage muesste es wohl eher heissen: Do you use the best tools available? Wobei im FPGA Bereich es weiterhin keine Alternative zu den wirklich teuren Flagschiffen gibt. Ich kenne z.B. kein Tool dass mir z.B. Functional Coverage und Code Coverage (soviel Line als auch Branch Coverage) bietet. Und da mittlerweile die Designs riesig sind, besteht nicht nur Bedarf an Functional sondern auch an Formal Verification um die Testzeiten endlich zu halten. Wenn ich mir da z.B. anschaue was Mentor mit Questa Prime bietet, dann finde ich da nicht ansatzweise in der freien Software Gemeinde etwas was da ran kommt. Anderseits kann man mit GHDL in nemm Docker Container und z.B. noch mit VUnit schon richtig viel erreichen. Ist halt alles eine Frage der Anforderungen.
Tobias B. schrieb: > Und da mittlerweile die Designs riesig sind, ...[] Für mich als Laie sieht das teilweise sehr so aus wie in der Softwarebranche. Es soll möglichst schnell ein Produkt entstehen und dann baut man das mit Methoden die genau das versprechen. Dabei ist völlig egal ob das dann noch wartbar ist oder welche Abhängigkeiten von sonstwo man sich ins Haus holt. Und weil man das dann so gemacht hat braucht man auch mächtigere Werkzeuge die einem helfen irgendwie den Überblick zu behalten. Ja, ist schön, dass man heutzutage so entwickeln kann, aber das ist dann nicht unbedingt robust. Bei FPGAs noch eher, da kann man immer das verwenden was man schon hat (ausser die Lizenz einer Mietsoftware läuft aus), aber im Webbereich wo gnadenlos externe Dinge eingebunden werden funktioniert das auch nur so lange wie diese auch vorhanden sind. Leftpad hätte eigentlich mal ein Umdenken lostreten können, hat es aber nicht. Weil es den Kunden/Enduser nicht interessiert. Und Firmen die ein Produkt verkaufen interessiert es im Consumerbereich auch immer weniger ob das lange beim Kunden funktioniert. Die Halbwärtszeit von Fernsehern z. B. ist krass gesunken und andere Geräte und auch Software "Apps" haben von hause aus oft nur eine kurze Lebenszeit. Und dann kann man ja heute fast überall nachpatchen. Wird ein Bug bekannt der kritisch ist für den Verdienst der Firma, dann behebt man den nachträglich. Da kann man schön abwägen ob es sich überhaupt rechnet einen Bug zu patchen oder ob man dem Kunden lieber ein neues Produkt verkauft oder einem die Kunden einfach egal sind. Aber alles egal, jetzt gibt es Essen.
Hm, nun, der HyperRAM will nicht. Aus purer Dummheit habe ich mir aber die Debuggingmöglichkeiten etwas stark eingeschränkt. Ich habe den RAM IC direkt neben das FPGA gesetzt und komme so nur an manche Signale - an die, die durch ein Via geführt werden. Die kann ich schön angucken denn der dünne Fädeldraht passt ziemlich perfekt in ein Via. Sehen kann ich so RWDS, CK, PSCK, und ein paar der Bits. #Reset und #CS kann ich nicht angucken. So, jedenfalls sehen CK und PSCK und die Daten (ich gucke mir DQ(0) an) gut aus vom Timing her. Allerdings hapert es beim Lesen, da bekomme ich einfach keine Daten. Für mich sieht das bisher nach einem Problem mit RWDS aus. Wenn ich das im FPGA auf 'Z' lege, dann bekommt es einen High Pegel - aber nie einen Low Pegel. Und zwar auch wenn ich im .xdc einen Pulldown für den Pin einbauen. Das sieht also so aus als würde der RAM RWDS immer treiben?! So recht kann ich das nicht glauben und dem Vivado vertraue ich auch nicht mehr. Normalerweise kann man ja die Simulation und so neu starten in der GUI und das verwendet dann die aktuellen Quellcode Dateien. Aber das ist leider nicht immer der Fall. Manchmal musste ich Vivado schließen, händisch die generierten Dateien löschen und dann Vivado neu starten. Dann wurde alles neu gebaut und die Simulation war wieder aktuell. Seltsam. Daher die Frage: Wenn ich einen Pin wie RWDS als Tristate mache UND da noch einen Pullup hinhänge, wo hängt der Pullup? Hängt der Pullup zwischen Pad und Tristate oder hängt der Pullup am Ausgangstreiber, also zwischen FPGA Logik und Tristate? Zusatzfrage 1: Ich schaffe das nicht 4 Oszi Tastköpfe mit Massefeder gleichzeitig zu halten. Gibt es dafür eine elegante Lösung? Zusatzfrage 2: Ich gebe die Daten DQ mit den Takten CK/#CK und PSCK/#PSCK aus. Der Xilinx IP kann Clock forwarding. Das würde ich gerne nutzen und gleich eine differentielle Clock ausgeben. Aber welchen IO-Standard sollte ich da auswählen um den korrekten vollen 1,8 V Pegel zu bekommen? Vielen Dank!
Gustl B. schrieb: > Ich schaffe das nicht 4 Oszi Tastköpfe mit Massefeder gleichzeitig zu > halten. Gibt es dafür eine elegante Lösung? Ich auch nicht ;-) In ganz teuer: https://www.packetmicro.com/Products/positioners-manipulator.html In nur teuer: http://www.pmk.de/de/products/3d_positionierer In übertuert: https://www.conrad.de/de/p/sks-hirschmann-tko-pos-2-positionierer-tko-pos-2-gruen-129043.html In günstig, siehe Bild... Duke
Duke Scarring schrieb: > In günstig, siehe Bild... Ja, so etwas (oder PMK 2-Fuss) sollte jeder in der Nähe haben. PMK hat noch mehr nette Sachen, SKID, modulares System um Sonden und Leiterplatten beim Testen zusammen zu halten: http://www.pmk.de/de/skid Zu teuer für zu Hause aber in einer Firma kann sich das schon rentieren. Ein anderer Ansatz ist, sich bei den Chemikern mit Stativmaterial einzudecken, da kann man sich dann beliebig komplizierte Messsetups zusammenschrauben. Und das Chemikermaterial ist viel günstiger als das überteuerte Messgerätezubehör. Ich habe keine Verbindung mit dieser Firma, einfach der erstbeste Link aus der Suchmaschine: http://www.laborhandel24.de/allgemeiner-laborbedarf/stativmaterial.html?p=1 Es gibt auch Klammern mit Schwanenhals, die sind dann wieder eher teuer: http://www.laborhandel24.de/allgemeiner-laborbedarf/stativmaterial/b08309658-de
OK, ja der Tipp mit den Stativen ist schon sinnvoll, sowas habe ich hier. Aber das braucht dann doch recht viel Platz und ich muss die Platine fixieren. Gibt es günstige Lötlösungen? Vor einiger Zeit habe ich mal einen Oszi Tastkopf zerlegt. Da war nicht viel drinnen, drei Widerstände und ein Kondensator. Das könnte man doch auch in sehr klein und leicht bauen. Dann hinten ein dünnes Koax dran oder noch besser eine Buchse für SMA/UF.L und vorne zwei dünne drähte die ich direkt auf die Platine löten kann. Ich habe mir das gebaut, aber eben nur mit billigen Tastköpfen. Die teureren mit 300 MHz Bandbreite will ich ungerne schlachten. Gibt es sowas vielleicht schon fertig zu kaufen?
Ja, kann man kaufen. Die Listenpreise willst du eigentlich gar nicht wissen :-) Bei schnellen (> 1 GHz) Aktiv-/Differenzproben von Keysight werden Einlötanschlüsse gleich mitgeliefert. Das sieht z. B. so aus (Preis ist nur für den Adapter, ohne Vorverstärker): https://www.ebay.com/itm/Agilent-N5381A-InfiniiMax-II-12-GHz-differential-solder-in-probe-head/283427132692
:
Bearbeitet durch User
Genau sowas suche ich. Nur eben reichen bis so grob 300 MHz. Aber egal, ich habe jetzt die Platine mit Klebemand auf einer Platte befestigt, die Tastköpfe drauf gelegt und ebenfalls festgeklebt und die Signale über sehr kurzen Draht angelötet. Im Anhang sind jetzt ein paar Bildchen, die zeigen wie folgt: - Gelb: RWDS - Cyan: CK - Magenta: PSC - Blau: DQ(0) Hyper_LSB_XXX zeigen, wo die Bits beim Kommanto sitzen. Man kann sehen, dass die zur jeweiligen Flanke anliegen. Hyper_Write zeigt einen Schreibvorgang an die Adresse 9. Geschrieben wird ein Wort. Saltsam ist, dass der RAM IC scheinbar immer RWDS treibt. Beim Schreiben geht das nicht ganz runter, da treibt der FPGA und vermutlich der RAM IC das Signal obwohl beim Schreiben nach der Command Phase nurnoch der Master RWDS treiben darf. Dann habe ich noch nicht verstanden wozu ich PSC brauche. Ja, anscheinend braucht das der RAM IC, aber wann genau? Laut Datenblatt kann ich das beim Schreiben auch statisch high oder low setzten. Aber beim Lesen brauche ich das wohl zwingend?! und muss da einen Takt mehr ausgeben als ich lesen will?! Im Timingdiagramm https://www.mouser.de/datasheet/2/198/66-67WVH8M8ALL-BLL-938852.pdf Seite 43 werden 4 Bytes gelesen (2 Takte mehr auf CK und zwei Takte auf RWDS) aber 6 Flanken über PSC ausgegeben. Ja und dann ist noch minimal unklar wie viele Takte ich überhaupt warten muss als Latency. Default besitzt der RAM IC immer doppelte Latenz und die Latenz ist auf 6 Takte eingestellt (Config Register 0, Seite 20). Das bedeutet, dass ich am Anfang zwei Takte von CK ausgebe und danach die doppelte Latenz von 6 Takten, also 12 Takte habe bis ich tatsächlich schreiben oder lesen darf. Nach 14 Takten beginnt dann also der Burst. In den Screenshots will ich nur ein Wort übertragen, also einen Takt. Dann müsste das stimmen mit den insgesammt 15 Takten.
Und das kann ich mir nicht erklären: Ich habe RWDS als inout. Daran hängt ein Tristate. RWDS <= RWDS_OUT when RWDS_tristate = '0' else 'Z'; RWDS_IN <= RWDS; Und jetzt kann ich aber (warum auch immer) problemlos RWDS_IN im FPGA in den Takteingang des DDR IPs geben und gleichzeitig noch in eine Bedingung schreiben (if RWDS_IN = '1' then ...). Und das obwohl ich für den Takteingang des IPs external Clock gewählt habe. Jetzt versuche ich den RWDS statt inout nur auf in umzubauen und einen Pulldown im XDC einzubauen. Also Tristate raus, und zwar nur die obere Zeile entfernt: RWDS_IN <= RWDS; RWDS_IN geht weiterhin an den Takteingang des IPs und in die if Bedingung. Tja und da meckert die Implementation, dass ich das Signal nicht an zwei verschiedenen Zielen verwenden darf. [Synth 8-5535] port <HyperRAM_RWDS> has illegal connections. It is illegal to have a port connected to an input buffer and other components. The following are the port connections : Input Buffer: Port I of instance ibuf_clk_inst(IBUF) in module <HyperBus_IN_selectio_wiz> Other Components: Port I3 of instance i_817(LUT6) in module Spartan7_revc_ram_test Wieso ist das so, der Ausgang vom Tristate (also der Eingang in Richtung FPGA) sollte doch äquivalent zu dem Signal ohne Tristate sein wenn dieses ein in ist. Ich stelle mir das so vor, dass jetzt nur der Tristate umgangen wird, aber das ist anscheinend nicht so. Edit: Ich muss RWDS am Anfang der Transaktion auswerten, und danach muss ich mit RWDS die Daten übernehmen wenn gelesen wird, dann ist das also ein Takt wenn ich das richtig sehe. Wie gerade beschrieben kann ich beides gleichzeitig machen wenn ich da ein Tristate an den Eingang setze. Wenn ich das weglasse und das nur als Eingang verwende geht es nicht. Wie kann ich das denn sonst lösen? Gut, weil ich die Default Einstellungen im RAM nutze, habe ich immer doppelte Latenz und müsste RWDS am Anfang nicht auswerten. Aber eigentlich will ich meine Beschreibung so bauen, dass ich später auch von den Defaulteinstellungen abweichen kann um den Durchsatz zu erhöhen.
:
Bearbeitet durch User
So, jetzt ist RWDS nur ein Eingang mit Pulldown. Aber der ist wohl zu schwach? Selbst dann wenn der RAM IC RWDS nicht treiben dürfte bleibt es high. Der Pulldown ist aber da, denn man kann am Oszi schön sehen, dass RWDS "langsam" (ca. 500 ns) nach Masse geht wenn #CS am Ende wieder High ist. Hm, damit bin ich jedenfalls unzufrieden, aber das Problem ist wohl nicht RWDS, sondern dass der IC das treibt, also nicht erkennt, dass ich lesen oder schreiben will. Vielleicht hängt der ja in einem komischen Zustand oder die Hardware hat einen Fehler. Versorgungsspannung ist da, aber ob alle Lötbällchen Kontakt haben kann ich nicht sehen.
Hallo warum verwendest du Pin PCS/PCS# das ist doch nur bei Ram mit DDR Center Aligned Read Strobe (DCARS) funktion welchen hast du denn?
Guter Punkt! Ich habe einen IS66WVH8M8ALL-166B1LI und laut Ordering Information braucht der kein PSC/#PSC. Gut, ich hatte das Datenblatt The PSC/PSC# differential clock is used only in HyperBus devices with 1.8 V nominal core and I/O voltage. HyperBus devices with 3 V nominal core and I/O voltage use only PSC as a single-ended clock. So verstanden, dass alle 1.8 V Chips das haben. Aber ist wohl nicht so. Gut, was habe ich jetzt gewonnen? Wenn ich mir die Pinbelegungen angucke, dann sind die bis auf PSC/#PSC identisch. Es müsste also genügen wenn ich PSC/#PSC abschalten und hochohmig mache. Aber ich vermute, dass ich dann noch nicht weiter bin.
Vielen Dank Michael K. ich war aber auch tatsächlich doof. Ich hatte die ganze Zeit versucht von Cypress die VHDL Datei zu verwenden, aber die braucht diese VITAL 2000 Teile. Aber es gibt auch eine Verilog Datei (Anhang) und die funktioniert ohne VITAL auch mit VIVADO. Aber ob die fehlerfrei ist weiß ich nicht. Naja, jetzt kann ich jedenfalls versuchen das Verilog zu verstehen (das ist gar nicht so schwer) und so meinen Controller ans Laufen zu bringen. Immerhin habe ich in der Simulation das gleiche Verhalten wie auf der Hardware. Ist zwar nicht schön, aber ein Hardwarefehler wäre schlimmer. Edit: Ist irgendwie komisch. Manche Signale wie ca_in ändern sich schön mit den ersten 6 Flanken von CK, aber es werden nur 00 übernommen. Obwohl auf DQ ganz klar etwas anderes steht. Ja, da ist wieder ein Tristate, aber das habe ich nicht so ganz verstanden wie man den in Verilog schreibt oder wie der hier beschrieben ist. Im Anhang ein Bildchen aus der Simulation und hier die Codestellen: Die Ports wie eine Entity in VHDL:
1 | module s27kl0641 |
2 | (
|
3 | DQ7 , |
4 | DQ6 , |
5 | DQ5 , |
6 | DQ4 , |
7 | DQ3 , |
8 | DQ2 , |
9 | DQ1 , |
10 | DQ0 , |
11 | RWDS , |
12 | |
13 | CSNeg , |
14 | CK , |
15 | RESETNeg
|
16 | );
|
Dann gibt es Wires:
1 | wire DQ7_ipd; |
2 | wire DQ6_ipd; |
3 | wire DQ5_ipd; |
4 | wire DQ4_ipd; |
5 | wire DQ3_ipd; |
6 | wire DQ2_ipd; |
7 | wire DQ1_ipd; |
8 | wire DQ0_ipd; |
Die werden dem Signal Din zugewiesen:
1 | wire [7:0] Din; |
2 | assign Din = { DQ7_ipd, |
3 | DQ6_ipd, |
4 | DQ5_ipd, |
5 | DQ4_ipd, |
6 | DQ3_ipd, |
7 | DQ2_ipd, |
8 | DQ1_ipd, |
9 | DQ0_ipd}; |
Und so sind die Wires DQX_ipd mit DQ verbunden:
1 | buf (DQ7_ipd , DQ7 ); |
2 | buf (DQ6_ipd , DQ6 ); |
3 | buf (DQ5_ipd , DQ5 ); |
4 | buf (DQ4_ipd , DQ4 ); |
5 | buf (DQ3_ipd , DQ3 ); |
6 | buf (DQ2_ipd , DQ2 ); |
7 | buf (DQ1_ipd , DQ1 ); |
8 | buf (DQ0_ipd , DQ0 ); |
Das bedeutet doch, dass Din direkt DQ entspricht oder?! Und hier:
1 | CA_BITS: |
2 | begin
|
3 | if (!CSNeg && |
4 | (rising_edge_CKDiff || falling_edge_CKDiff)) |
5 | begin
|
6 | for(i=1;i<=8;i=i+1) |
7 | ca_in[ca_cnt-i] = Din[8-i]; |
8 | ca_cnt = ca_cnt - 8; |
Werden die Daten in ca_in geschrieben. Habe ich das bis hierhin richtig verstanden?
:
Bearbeitet durch User
OK, Sorry, das war ein Fehler von mir ... Aber dadurch wird es noch nicht viel besser. Die CA Daten werden korrekt übernommen, Adresse=9, RW=0 (Write), Target=0 (Memory). Aber was ist RD_MODE?
1 | parameter LINEAR = 4'd0; |
2 | parameter CONTINUOUS = 4'd1; |
3 | reg [1:0] RD_MODE = CONTINUOUS; |
Im Datenblatt gibt es nicht LINEAR und CONTINUOUS, sondern linear und wrapped. Ist also CONTINUOUS = wrapped Burst? Im Datenblatt bedeutet eine 1 linear, hier ist es genau umgekehrt. Gibt es da irgendwelche Bedingungen dass ein Burst stattfinden darf? Ich meine sowas wie die Adresse muss der Anfang einer Page sein oder so. Seltsamerweise zählt data_cycle nicht. Jetzt mal nur den Code für die steigende Flanke von CK:
1 | DATA_BITS: |
2 | begin
|
3 | if (rising_edge_CKDiff && !CSNeg) |
4 | begin
|
5 | if (Target==1'b1 && RW==1'b0) |
6 | begin
|
7 | Data_in[15:8] = Din; |
8 | data_cycle = data_cycle + 1; |
9 | end
|
10 | else
|
11 | if (BurstDelay==0 && !PO_in) |
12 | begin
|
13 | RdWrStart = 1'b0; |
14 | if (RW == 1) // read |
15 | begin
|
16 | glitch_rwds = 1'b1; |
17 | glitch_rwdsR = 1'b1; |
18 | RWDSout_zd_tmp = 1'b1; |
19 | if (Target == 0) // mem |
20 | begin
|
21 | if (Mem[Address][15:8]==-1) |
22 | Dout_zd_tmp = 8'bxxxxxxxx; |
23 | else
|
24 | Dout_zd_tmp=Mem[Address][15:8]; |
25 | end
|
26 | else // reg |
27 | Dout_zd_tmp = Config_reg[15:8]; |
28 | end
|
29 | else // (RW == 0) write |
30 | begin
|
31 | Data_in[15:8] = Din; |
32 | data_cycle = data_cycle + 1; |
33 | UByteMask = RWDS; |
34 | end
|
35 | end
|
36 | end
|
Ich schreibe (RW=0) in den Speicher (Target=0). Ich gehe also in den ersten else Zeig und da wird auf BurstDelay=0 geprüft, was es aber nicht ist. Das behält den Wert 6. BurstDelay wird aber nur verringert wenn REFCOLL_ACTIV 0 ist. Und das wird nur dann 0 gesetzt wenn !REF_in gegeben ist. Und das wiederum wird 0 gesetzt wenn rising_edge_REF_out gegeben ist. Und das findet statt bei always @(posedge REF_out). Das hängt dann aber wieder von REF_in ab?!
1 | // Refresh Collision Time |
2 | always @(posedge REF_in) |
3 | begin:REFr |
4 | if (SPEED100) |
5 | #tdevice_REF100 REF_out = REF_in; |
6 | end
|
7 | always @(negedge REF_in) |
8 | begin:REFf |
9 | #1 REF_out = REF_in; |
Kann das dann überhaupt jemals eintreten? Ich hänge nochmal die Verilogdatei an ...
:
Bearbeitet durch User
So, letztes Update für diese Nacht: Ich habe ein Minimalprojekt geschrieben. Das macht nach 200 us einen Reset und danach eine Schreibtransaktion auf Adresse 9 und darauf eine Lesetransaktion von Adresse 9. Ja, das ist jetzt nur stumpf hingeschrieben, aber es ist das gleiche Timing das mein HyperBusController hat. Man kann also schön gucken was hier in dem RAM IC abgeht und warum was nicht funktioniert - das ist genau die Stelle die ich nicht verstehe.
Du hast RWDS nicht auf High bei dem Daten cycle also werden die Bytes nicht übernommen
Christoph Z. schrieb: > git clone > make all > > Mehr soll nicht nötig sein (natürlich sind andere build Systeme erlaubt) Zählt das auch, wenn dieser Schritt zwischendurch Daten aus dem Netzwerk nachlädt, diverse Debian-Pakete baut, durch ein systemspezifisches Tool (nicht Teil des Buildsystems!) jagt, daraus einen Haufen Images baut, diese dann wieder auseinandernimmt und neu zusammenknotet, um am Ende eine ZIP-Datei auszuwerfen? :-) In dem Test liegen wir bei 7~8, wobei einige grenzwertig sind (z.B. "Gibt es eine Spec?" - "Darf man sie auch ignorieren/ständig anpassen?").
Das war ein guter Tipp Michael. Dann verstehe ich aber Seite 15 unten Fußnote 5 nicht. https://www.mouser.de/datasheet/2/198/66-67WVH8M8ALL-BLL-938852.pdf The figure shows RWDS masking byte A0 and byte B1 to perform an unaligned word write to bytes B0 and A1. Wenn da B0 und A1 geschrieben wird, dann wird doch genau das geschrieben bei dem RWDS 0 ist. Werde ich daheim ausprobieren, aber ich glaube mittlerweile, dass RWDS 0 sein muss damit die Daten geschrieben werden.
:
Bearbeitet durch User
So, ausprobiert, hat nichts verändert, kann man auch am Verilog sehen, da wird RWDS nicht abgefragt wenn es um Data_in geht.
Noch ein Zitat zu RWDS beim Schreiben: During the write data transfers, RWDS is driven by the host master interface as a data mask. When data is being written and RWDS is High the byte will be masked and the array will not be altered. When data is being written and RWDS is Low the data will be placed into the array. Seite 14 im Datenblatt.
Hallo Gustl, ja ist richtig RWDS muss low sein. Das Simulation Problem ist in der Datei s27kl0641.v parameter TimingModel = "DefaultTimingModel"; ändere das mal auf parameter TimingModel = "S27KL0641DABHI020"; Gruss, Michael
Edit, doch ändert was. Danke! In der Simulation funktionieren jetzt meine Bursts mit 1 und 32 Worten ohne Fehler.
:
Bearbeitet durch User
S. R. schrieb: > Christoph Z. schrieb: >> git clone >> make all >> >> Mehr soll nicht nötig sein (natürlich sind andere build Systeme erlaubt) > > Zählt das auch, wenn dieser Schritt zwischendurch Daten aus dem Netzwerk > nachlädt, diverse Debian-Pakete baut, durch ein systemspezifisches Tool > (nicht Teil des Buildsystems!) jagt, daraus einen Haufen Images baut, > diese dann wieder auseinandernimmt und neu zusammenknotet, um am Ende > eine ZIP-Datei auszuwerfen? :-) Genau um solche Beispiele geht es! :-) Ohne Build Automatisierung bekommt man von drei Ingenieuren vier verschiedene Ergebnisse... > In dem Test liegen wir bei 7~8, wobei einige grenzwertig sind (z.B. > "Gibt es eine Spec?" - "Darf man sie auch ignorieren/ständig > anpassen?"). Living Specs sind ja ein altes Problem. Genau aus dieser Erkenntnis kommen ja die ganzen Agilen Methoden, weil Teile des V-Modells nicht mit der Realität zusammenpassen. Und genau da liegen auch viele Fehlinterpretationen. Agil bedeutet genau gar nicht, das keine Spec da ist. Die Spec muss am Ende eines Sprints mit dem Release zusammenpassen (Hat hier jemand Self-documenting code oder executable Spec gesagt?), sonst ist der Sprint nicht abgeschlossen und wie sollten dann auch die Tests geschrieben werden und der nächste Sprint geplant werden.
So, Simulation funktioniert mit TimingModel = "S27KL0641DABHI020", aber meine Hardware ist ja ein IS66WVH8M8ALL-166B1LI und mit dem funktioniert es nicht (auf der Hardware). Daher erstmal: Das ist ja ein 166 MHz RAM, ist das trotzdem OK wenn ich den nur mit 100 MHz betreibe? Meine Vermutung ist, dass das baugleiche ICs sind die selektiert werden. Die besseren werden als 166 verkauft, die schlechteren als 100. Sehe ich das richtig, dass dieser Verilog Code der TimingModel auswertet nur darauf guckt ob in dem String ein "A" enthalten ist?
1 | begin: InitTimingModel |
2 | integer i; |
3 | integer j; |
4 | //assumptions: |
5 | //1. TimingModel has format as S27KL0641XXXXXXXX |
6 | //it is important that 11-th character from first one is "G" or "P" |
7 | //2. TimingModel does not have more then 24 characters |
8 | tmp_timing = TimingModel;//copy of TimingModel |
9 | |
10 | i = 23; |
11 | while ((i >= 0) && (found != 1'b1))//search for first non null character |
12 | begin //i keeps position of first non null character |
13 | j = 7; |
14 | while ((j >= 0) && (found != 1'b1)) |
15 | begin
|
16 | if (tmp_timing[i*8+j] != 1'd0) |
17 | found = 1'b1; |
18 | else
|
19 | j = j-1; |
20 | end
|
21 | i = i - 1; |
22 | end
|
23 | i = i +1; |
24 | if (found)//if non null character is found |
25 | begin
|
26 | for (j=0;j<=7;j=j+1) |
27 | begin
|
28 | //Speed is 11. |
29 | tmp_char1[j] = TimingModel[(i-10)*8+j]; |
30 | end
|
31 | end
|
32 | if (tmp_char1 == "A") |
33 | SPEED100 = 1; |
34 | end
|
Ja und dann finde ich von ISSI leider keine (V)HDL Beschreibungen. Müsste der ISSI Stein wie der Cypress Stein funktionieren weil ja HyperBus oder könnte es trotzdem sein, dass ich irgendetwas ansers machen muss? Wäre zwar etwas Aufwand, aber ich könnte mir auch den S27KS0641DPBHI020 kaufen und damit den ISSI Stein ersetzen.
:
Bearbeitet durch User
Am besten mal die simulation mit dem s27ks0641.v model machen das auch DDR 166mhz unterstützt.
Danke! Auch damit funktioniert die Simulation wunderbar. Bei TimingModel habe ich S27KS0641DPBHI020 geschrieben. Nun ... ich werde auf meiner nächsten Platine dann einen S27KS0641DPBHI020 verbauen und alle Signale auf Testpads routen.
So, ich habe bei Terasic sehr versteckt ein Modell für einen ISSI STein gefunden. Ebenfalls in Verilog. Und zwar kann man da einige Dinge per ifdef einstellen. Kommentar im Code:
1 | * Running Options |
2 | * +S10 : Set AC timing parameter for -10(100MHz ) |
3 | * +S75 : Set AC timing parameter for -75(133MHz ) |
4 | * +S60 : Set AC timing parameter for -60(166MHz ) |
5 | * +VERBOSE : Display internal operation status |
6 | * +OFF_ST : Phase Shifted Clock enabled |
7 | * (default : Phase Shifted Clock disable) |
Und so sieht das Verilog mit den Ports und den Ifdefs aus:
1 | module IS66WVH16M8ALL (ck, ckb, psc, pscb, csb, dq, rwds,resetb); |
2 | |
3 | parameter ROW_BITS = 14; |
4 | parameter COL_BITS = 9; |
5 | parameter DQ_BITS = 8; |
6 | parameter mem_cnt = 23; |
7 | parameter mem_width = 8; |
8 | parameter mem_sizes = 8388607; |
9 | parameter VT = 1; |
10 | |
11 | // Timing Parameter -10 PC100 |
12 | |
13 | `ifdef S10 |
14 | |
15 | parameter tCK = 10; |
16 | parameter tRFH = 40; |
17 | parameter tPO = 40; |
18 | parameter tDSS = 0.8; |
19 | parameter tDSH = 0.8; |
20 | parameter tIS = 1.0; |
21 | parameter tIH = 1.0; |
22 | parameter tRWR = 40; |
23 | parameter tCSHI = 10; |
24 | parameter tCK2RWDS = 3.0; |
25 | parameter SS = 1; |
26 | `endif |
27 | |
28 | // Timing Parameter -75 PC133 |
29 | |
30 | `ifdef S75 |
31 | |
32 | parameter tCK = 7.5; |
33 | parameter tRFH = 37.5; |
34 | parameter tPO = 37.5; |
35 | parameter tDSS = 0.6; |
36 | parameter tDSH = 0.6; |
37 | parameter tIS = 0.9; |
38 | parameter tIH = 0.9; |
39 | parameter tRWR = 37.5; |
40 | parameter tCSHI = 7.5; |
41 | parameter tCK2RWDS = 3.0; |
42 | parameter SS = 1; |
43 | `endif |
44 | |
45 | // Timing Parameter -60 PC166 |
46 | |
47 | `ifdef S60 |
48 | |
49 | parameter tCK = 6; |
50 | parameter tRFH = 36; |
51 | parameter tPO = 36; |
52 | parameter tDSS = 0.45; |
53 | parameter tDSH = 0.45; |
54 | parameter tIS = 0.8; |
55 | parameter tIH = 0.8; |
56 | parameter tRWR = 36; |
57 | parameter tCSHI = 6; |
58 | parameter tCK2RWDS = 3.0; |
59 | parameter SS = 1; |
60 | |
61 | |
62 | `endif |
63 | parameter MEM_INIT_EN = 0; |
64 | |
65 | // Timing Parameter |
66 | |
67 | parameter tCSS = 3.0; |
68 | parameter tCSM = 4e3; |
69 | parameter tRP = 200; |
70 | parameter tRH = 200; |
71 | parameter tRPH = 400; |
72 | `ifdef SPEEDSIM |
73 | parameter tVCS = 10e3; |
74 | `else |
75 | parameter tVCS = 150e3; |
76 | `endif |
77 | parameter tDPDIN = 10e3; |
78 | parameter tDPDOUT = 150e3; |
79 | parameter tDPDCSL = 200; |
80 | parameter tCKDS = 2.78; |
81 | |
82 | |
83 | |
84 | `define MAX_BITS (ROW_BITS+COL_BITS-1) |
85 | |
86 | |
87 | |
88 | // ports |
89 | input ck; |
90 | input ckb; |
91 | input psc; |
92 | input pscb; |
93 | input csb; |
94 | input resetb; |
95 | inout [DQ_BITS-1:0] dq; |
96 | inout rwds; |
97 | |
98 | `protect |
99 | |
100 | `ifdef VERBOSE |
101 | wire Debug = 1'b1; |
102 | `else |
103 | wire Debug = 1'b0; |
104 | `endif |
105 | |
106 | |
107 | `ifdef OFF_ST |
108 | wire IDR_Off_st = (SS==1)? 1'b1: 1'b0; |
109 | `else |
110 | wire IDR_Off_st = 1'b0; |
111 | `endif |
Wie kann ich das in meine VHDL Testbench einbinden? Die Inputs sind mir klar, aber die ifdefs, sind das Generics? Bedeutet z. B. `ifdef S10 dass es ein Generic mit dem Namen "S10" gibt und wenn das '1' ist ist das gesetzt und bei '0' nicht gesetzt/erfüllt? Und welchen Typ hat das Generic? Edit: Generics wie
1 | component IS66WVH16M8ALL is |
2 | generic( |
3 | S10: boolean; |
4 | S75: boolean; |
5 | S60: boolean; |
6 | SPEEDSIM: boolean; |
7 | VERBOSE: boolean; |
8 | OFF_ST: boolean); |
9 | port( |
10 | ck: in std_logic; |
11 | ckb: in std_logic; |
12 | psc: in std_logic; |
13 | pscb: in std_logic; |
14 | csb: in std_logic; |
15 | resetb: in std_logic; |
16 | dq: inout std_logic_vector(7 downto 0); |
17 | rwds: inout std_logic); |
18 | end component; |
funktionieren leider nicht. Und noch ein Edit: Ich habe jetzt das Verilog so editiert, dass die Parameter einfach fest sind ohne Ifdefs. Und siehe da, die Simulation funktioniert auch hier ... hm ... sieht tatsächlich nach einem Hardwareproblem aus. Im Anhang noch das Verilogmodell von Terasic, dort ist es in dem ZIP https://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English&CategoryNo=253&No=1140&PartNo=3 enthalten. Edit2: Edit3: Edit2 entfernt^^ Simulation läuft problemlos ohne Fehlermeldung im Verbose Modus mit den 166 MHz Timings im Verilogmodell aber nur 100 MHz CK/#CK. Vielen Dank!
:
Bearbeitet durch User
Es war die Hardware. Erhitzen hat nicht geholfen, also habe ich den IC getauscht gegen einen baugleichen (ISSI). Jetzt funktioniert das wunderhybsch. Im Anhang das Projekt für die Simulation mit den Verilogmodellen die ich finden konnte. Mit dabei ist mein "HyperBus Master". Den habe ich möglichst einfach gehalten:
1 | entity HyperBus is Port( |
2 | clk100: in std_logic; |
3 | start: in std_logic; |
4 | mem_regs: in std_logic; --0: Mem, 1: Regs |
5 | burstlength: in std_logic; --0: 2Bytes, 1:64Bytes |
6 | adr: in std_logic_vector(21 downto 0); -- 21 ... 9: 8192 Rows, 8 ... 0: 512 Words in 1 Row. (2 ... 0: 8 Words = 1 Half Page) |
7 | snd_rcv: in std_logic; --0: send/write, 1: receive/read |
8 | ready: out std_logic; |
9 | --- SND ---
|
10 | data_snd: in std_logic_vector(64*8-1 downto 0); |
11 | --- RCV --
|
12 | data_rcv_valid: out std_logic; |
13 | data_rcv: out std_logic_vector(64*8-1 downto 0); |
14 | --- RAM ---
|
15 | nReset: out std_logic; |
16 | nCS: out std_logic; |
17 | CK: out std_logic; |
18 | nCK: out std_logic; |
19 | PSC: out std_logic; |
20 | nPSC: out std_logic; |
21 | RWDS: inout std_logic; |
22 | DQ: inout std_logic_vector(7 downto 0)); |
23 | end HyperBus; |
clk100 ist der Systemtakt, start sagt dass es losgehen soll und Daten/Adresse anliegt. mem_regs sagt ob aus dem RAM oder dessen Registern gelesen werden soll (Schreiben der Register ist nicht unterstützt!). burstlength sagt ob 1 Wort oder 32 Worte gelesen/geschrieben werden sollen. adr ist die adresse. snd_rcv sagt ob geschrieben oder gelesen werden soll. ready sagt ob die Komponente bereit ist. data_snd sind die zu schreibenden Daten, data_rcv_valid sagt ob die gelesenen Daten data_rcv aktuell sind. Dabei ist aber data_rcv_valid nur für genau einen Takt lang '1' nach einem Lesevorgang. Die restlichen Anschlüsse betreffen die Hardware. Dabei wird PSC/nPSC jetzt mit 'Z' belegt weil ich das angeschlossen habe. Aber der im Projekt enthaltene MMCM erzeugt auch PSC. Man kann also mit der Beschreibung auch HyperRAM Steine betreiben die PSC benötigen. In diesem MMCM kann man auch schön CK/nCK gegenüber DQ verschieben (über die Phase) damit die Taktflanke dann wirklich mittig in den Daten liegt. In der Simulation geschieht bei grob 650 us ein Reset (den mach mein HyperBus Controller immer wenn er losläuft, kann man auch rauslöschen). Dann bei 660 us gibt es einen 32 Wort Schreibvorgang und bei 662 us einen 32 Wort Lesevorgang. Ein 32 Wort Burst dauert 480 ns, dann muss nCS noch für mindestens einen Takt '1' sein, macht zusammen 490 ns für 64 Bytes. Und (1/490ns)*64Bytes = 130,6 MBytes/s. Damit liegt das jetzt knapp über meinem Ziel, ich wollte auf jeden Fall die Daten meiner ADCs wegschreiben können (100 MByte/s) und als "nett zu haben" auch noch schneller sein als Gigabit Ethernet falls ich das mal verwende mit dem FPGA. Ja, sonst ... darf gerne verwendet und modifiziert werden. Bei Fragen einfach fragen.
Nachtrag: Ich suche gerade nach einem Hyperram IC der bei 3.3 V funktioniert. Solche gibt es von Cypress, ISSI und Winbond. Die Datenblätter sehen sich jeweils sehr ähnlich und die ICs funktionieren bis 3.6 V. Aber: Die von Cypress und ISSI gehen in der 3 V Version nur bis maximal 100 MHz (bei 1.8 V bis 166 MHz). http://www.issi.com/WW/pdf/66-67WVH8M8ALL-BLL.pdf https://www.cypress.com/file/183506/download/001-97964_S27KL0641_S27KS0641_S70KL1281_S70KS1281_3.0_V_1.8_V_64_Mb_8_MB_128_Mb_16_MB_HyperRAM_TM_Self-Refresh_DRAM.pdf Bei Winbond hingegen sind die ICs noch ganz frisch, das Datenblatt stammt von letztem Herbst und dort gehen die ICs bei 1.8 V und 3.3 V bis 200 MHz. https://www.mouser.de/datasheet/2/949/W956x8MBYA_64Mb_HyperBus_pSRAM_TFBGA24_datasheet_A-1760356.pdf Ich werde also zwei der Winbond ICs in meiner nächsten Schaltung einplanen. Ob ich diese Geschwindigkeit benötige weiß ich nicht, das hängt davon ab was ich über USB3 mit dem FT600 an Durchsatz hinbekomme. Theoretisch gehen 200 MByte/s und da würden mir die 100 MHz am RAM nicht mehr ausreichen.
Und noch was: Ich sehe gerade, dass es auch Flash ICs gibt die einen HyperBus verwenden. Das sieht auch nicht so irre kompliziert aus. Hat hier jemand schon mal einen solchen HyperFlash IC verwendet? Ein Datenblatt: https://www.mouser.de/datasheet/2/100/512_MBIT_256_MBIT_128_MBIT_HYPERFLASH_FAMILY_Datas-957657.pdf
Gustl B. schrieb: > Theoretisch gehen 200 MByte/s und da würden mir > die 100 MHz am RAM nicht mehr ausreichen. Du kannst auch zwei RAM-Chips nehmen und parallel ansteuern...
Das ist auch der Plan. Aber ich weiß noch nicht genau was sonst noch auf die Platine soll. Ich würde gerne was mit SerDes machen. Da bieten sich schnelle ADCs oder DACs an. HDMI ginge auch. Aber da Laufe ich dann vermutlich in das Problem, dass HDMI ja LVDS out ist und ich dafür die Bank am FPGA auf 2.5 V legen muss. Damit geht dann an dieser Bank kein HyperRAM. Schneller ADC ginge, aber da werde ich mehrere RAMs brauchen. Wenn ich 1 GByte/s in den Samplespeicher schreiben will reichen mir 4 RAMs mit je 250 MByte/s. Und die bekomme ich bei 166 MHz und mindestens 128 Byte langen Bursts oder auch mit 200 MHz und 64 Byte Bursts. Statt ADC könnte ich auch zwei weitere USB-C Buchsen verbauen. Das wären dann 8 LVDS Pärchen. Mit einem LVDS fähigen schnellem Komparator am anderen Ende des USB-C Kabels könnte ich so einen schnellen Logikanalysator bauen. Wenn du weiter Ideen für ein Bastel-lernprojekt hast immer her damit. Hauptsächlich will ich einmal USB-C mit USB3 gemacht haben. Aber da bleiben eben noch einige IOs übrig. Leider sieht aktuell die Verfügbarkeit von ICs, z. B. dem HyperRAM echt mies aus. Die 3 V Variante bekommt man gar nicht. Und 1.8 V gehen nicht weil an der Bank auch das Konfigurationsflash hängt und das mag 3.3 V. Alles nicht so einfach, aber Luxusprobleme.
Aber wenn ich schon beim Planen bin, sollte ich lieber den 1.8 V oder den 3.0 V RAM verwenden (beides 200 MHz RAMs)? Strom und Kosten sind mir an der Stelle egal, mir geht es drum bei welcher Spannung ich "problemloser" den höheren/maximal möglichen Takt erreiche.
Hm, eigentlich nicht wirklich, aber: - Ich habe nur zwei halbe Bänke - geht das? Und welche Bankspannungen sind erlaubt? - Da muss ich wohl AXI verwenden?! - Ich habe das jetzt mal mit dem MIG bauen lassen und zähle 36 IOs die das braucht. Das ist weniger wie 4x HyperRAM. Wobei ... bei 4x Hyperram könnte ich doch CK (die wohl lieber nicht), CS# und Reset# untereinander verbinden und bin dann 39 IOs für alle 4. Hm ... Hm ... - Das könnte vom Layout her ziemlich fies werden, wäre aber eine neue Herausforderung nachdem HyperRAM jetzt abgehakt ist (-: Edit: Kann man einen DDR2/3 auch langsamer betreiben wenn das Layout nicht für den hohen Takt gut genug ist? Beim HyperRAM geht das recht problemlos. Ich habe gerne Dinge die zur Not zumindest noch ein bischen funktionieren ...
:
Bearbeitet durch User
Gustl B. schrieb: > Kann man einen DDR2/3 auch langsamer betreiben wenn das Layout nicht für > den hohen Takt gut genug ist? Beim HyperRAM geht das recht problemlos. > Ich habe gerne Dinge die zur Not zumindest noch ein bischen > funktionieren ... Nicht mit dem Xilinx MIG. Der braucht einen Mindestakt damit er bei der Kalibrierung zumindest ein komplettes Datenauge samplen kann.
Gustl B. schrieb: > - Ich habe nur zwei halbe Bänke - geht das? Und welche Bankspannungen > sind erlaubt? Der MIG meckert bei zwei halben Bänken ... aber gut, dann muss ich eben andere Dinge umplanen. DDR3 braucht 1.5 V und wäre auch sonst recht schick. Aber was mache ich dann mit den restlichen IOs an der Bank? Für 1.5 V gibt es leider kaum ICs die ich noch verbauen könnte. DDR2 geht mit 1.8 V, das ist schon feiner. Gustl B. schrieb: > - Da muss ich wohl AXI verwenden?! Muss man nicht. Auch schick! Hach ... Tobias B. schrieb: > Nicht mit dem Xilinx MIG. Der braucht einen Mindestakt damit er bei der > Kalibrierung zumindest ein komplettes Datenauge samplen kann. OK, aber kann ich da einen DDR2 800 verwenden und den MIG erstmal für einen DDR2 400 konfigurieren und mich dann langsam an die 800 MHz rantasten? Und dann möchte ich noch die tatsächliche Datenrate abschätzen können. Bei Wikipedia steht z. B. 3.2 GB/s für den DDR2 400 und 64 Bit Breite. Ist klar, 8 Bytes * 400 M = 3.2 GByte. Aber das ist doch dann nur die Maximaldatenrate während eines Bursts. Was schafft denn der RAM im zeitlichen Mittel? Bei 8 Bit Datenbus sind das dann 400 MByte/s beim Burst. Beim HyperRAM mit 200 MHz werden auch die 400 MByte/s angegeben, aber das ist leider auch nur Burst und nicht Durchschnitt. Beim HyperRAM geht aber nicht mehr wie 200 MHz IO Takt, beim DDR2 schon, da geht es mit 200 MHz erst los und geht bis 533 MHz.
Gustl B. schrieb: > Aber das ist doch dann nur die Maximaldatenrate während eines Bursts. Ja. > Was schafft denn der RAM im zeitlichen Mittel? Das hängt von Deinem Zugriffsmuster ab. Wenn aus jedem Burst nur ein Byte rausgeholt wird, geht die Rate deutlich in den Keller. Duke
Noch ein paar Überlegungen zur Datenrate je FPGA IO: Der HyperRAM macht bei mir bei 100 MHz und 64 Byte Bursts 130.6 MByte/s. Dafür werden 13 FPGA IOs benötigt. Macht also grob 10 MByte/IO. Bei 200 MHz und 256 Byte langen Bursts macht der RAM 353.1 MByte/s im Schnitt. Das sind grob 27 MByte/s im zeitlichen Mittel. DDR2 mit 8 Bit Datenbus benötigt 35 IOs und schafft. Bei DDR2_400 400 MByte/s. Das sind dann 11.4 MByte/ IO. Bei DDR2_800 sind es also 22 MByte/IO. Und leider kann mein Spartan7 sogar nur DDR2 bis 667 MHz. Und in diesem Vergleich haben wir die durchschnittliche Datenrate beim HyperRAM und die Burst Datenrate vom DDR2 verglichen. Mit 3 HyperRAM ICs komme ich bei den 200 MHz und den längeren Bursts im Schnitt auf über 1 GByte/s, bei DDR2_800 nicht. Die 3 HyperRAMs breichen 39 IOs, der DDR2 35. Bei den HyperRAMs gibt es auch welche die nur eine single-ended Clock haben, das ist dann 1 IO weniger je IC und ich könnte auch die Resets untereinander verbinden. Eigentlich reichen mir auch 2 HyperRAMs. Ich muss halt die 200 MByte vom FT600 wegschreiben können und ich würde gerne HDMI machen. Da der Spartan7 sowieso keine irre schnellen SerDes hat lange ich bei einer Pixelclock vermutlich unter 100 MHz. Das sind dann 300 MByte/s bei RGB maximal. Ja, ich verwe jetzt nochmal HyperRAM verbauen und meinen Controller umbauen dass der ein FIFO Interface hat und einen höheren Takt kann. Vielleicht per Generic einstellbar welches HyperRAM Modell man bei welchem Takt verwenden will.
:
Bearbeitet durch User
Gustl B. schrieb: > Bei 200 MHz und 256 Byte langen Bursts macht der RAM 353.1 MByte/s im > Schnitt. Das sind grob 27 MByte/s im zeitlichen Mittel. Geht noch etwas mehr??? Ich bin da bwegen meiner Workstation auch gerade dran und hatte schon probiert full HD auszulesen, um einen echten frame buffer zu haben, in den man auch offline zeichnen kann. Müssten netto rund 356MB/s sein - siehe Tabelle. Für den Audio-Betrieb wird es bei mir aber wohl nur die halbe Auflösung bei 12 Bit werden, damit ich mehr Bilder reinbekomme. Mein RAM hat nur 64Mbit. Zudem werden es gfs nur 30Hz. Der RAM-Baustein ist aber prima, für solche Anwendungen, weil er nicht so arg viele PINs verschluckt.
Tja ausprobieren. Etwas mehr Takt geht sicher und sonst kannst du einfach noch einen Baustein parallel anbinden. Kostet nur weitere 12 IOs.
Werde es demnächst mal wieder anpacken und schauen, ob es geht. Für den Controller gibt es ein update. Mehr Pins geht nicht, da nicht vorhanden. Das PCB ist fix designed. Mit einem Baustein.
Keine Ahnung ob sich bei dir was getan hat, aber Winbond nennt hier im Datenblatt https://www.mouser.de/datasheet/2/949/W958D8NBYA_256Mb_HyperRAM_TFBGA24_SDP_85C_datashee-3073409.pdf jetzt einen Maximaltakt von 250 MHz und somit 500 MBit/s je Datenpin. Ich hatte das damals so gemacht Beitrag "HyperBus Ideen"
:
Bearbeitet durch User
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.