mikrocontroller.net

Forum: FPGA, VHDL & Co. VHDL Grundlagen mininal CPU auf Spartan 6


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von chris (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Da ich ein günstiges Spartan 6 Board bekommen habe

Beitrag "XC6SLX16 Spartan 6 Entwicklungsboard"

möchte ich zur Übung die minimalistische CPU von Tim implementieren

https://github.com/cpldcpu/MCPU

Als erstes brauche ich aber ein Blockram als Modul. Lothar Miller hat 
hier eine sehr schöne Erkärung

http://www.lothar-miller.de/s9y/archives/20-RAM.html#extended

aber es fehlt leider die Testbench.

Hat jemand eine Testbench für das SRAM?

von Ale (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ein testbench für das RAM ?.... warum ? warum nicht ein testbench für 
CPU+RAM/ROM ?

was ich normalerweise mache ist folgendes, ich schreibe ein Testprogramm 
mit dem Befehlen die ich testen will und dann lasse den Takt laufen... 
dann gucke mir die Signalen mit dem GTKview.

für ein Sync RAM würde ich so was machen:
   wait for 10ns;
   we <= '1';
   data <= X"A5";
   wait for 10ns;
   we <= '0';

und dann die Signalen mit GTKWave anschauen... könntest du auch die 
Werte vergleichen und dann mit dem textio Modul was auf die Console 
schreiben...

von chris (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi Ale,

da ich nach ein paar Monaten immer den Syntax vergesse, wenn ich länger 
nichts mehr gemacht habe, brauche ich ein paar einfach VHDL Beispiele.
Deshalb wollte ich mit einem einfachen RAM und der zugehörigen Testbench 
anfangen.

Ich brauche erst mal 3 Module: Ein RAM, die CPU und einen Clk-Teiler für 
die CPU, damit ich sie runter bremsen kann und ein einfaches blinky 
läuft.

von Gustl B. (-gb-)


Bewertung
0 lesenswert
nicht lesenswert
Du willst für 64 Bytes ein ganzen BRAM opfern? Bei Xilinx passen da 2 
kBytes rein.
Und wieso willst du asynchron lesen? Bei Xilinx wird automatisch ein 
BRAM verwendet wenn die Leseadresse getaktet ist.

process(clk, we, a, d)

d und we sind da überflüssig. Weil ja noch nichts passiert wenn sich 
diese ändern, sondern erst zur Taktflanke.

Ich würde aber trotzdem versuchen wenn möglich alles getaktet zu bauen 
und zwar mit nur einem Takt.
    CLOCK_CLK : process
    begin
      WAIT FOR TbPeriod;
      a<="000000";
      d<="00000000";
      we<='1';
      WAIT FOR TbPeriod;
      reset <= '0';
      WAIT FOR TbPeriod;
      reset <= '1';
      WAIT FOR TbPeriod;
      a<="000000";
      d<="00000000";
      we<='0';
      WAIT FOR TbPeriod;
      we<='1';
      WAIT FOR TbPeriod;
      a<="000000";
      d<="01010101";
      we<='0';
      WAIT FOR TbPeriod;
      we<='1';

    end process;

Wo hast du das denn her? Such dir mal eine andere Quelle.

a wird dreimal exakt der gleiche Wert zugewiesen. Dann gibt es viele 
Signale ohne Defaultwerte. Gerade in der Testbench würde ich 
Defaultwerte verwenden. Z. B. für dein reset. Oh, was macht der Reset 
überhaupt?

: Bearbeitet durch User
von chris (Gast)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
>Du willst für 64 Bytes ein ganzen BRAM opfern? Bei Xilinx passen da 2
>kBytes rein.

Naja, die CPU hat nur 64 Bytes Addresraum ( Bild ). Ich habe mal den 
Datenpfad von inout auf getrennte Datenpfade umgestellt.

>Ich würde aber trotzdem versuchen wenn möglich alles getaktet zu bauen
>und zwar mit nur einem Takt.

Zeig mal ein Beispiel.

>Wo hast du das denn her? Such dir mal eine andere Quelle.

Der Reset ist noch ein Überbleibsel des Autogenerators:
http://vhdl.lapinoo.net

von Alexander D. (abadu)


Bewertung
0 lesenswert
nicht lesenswert
Der bei der MCPU verwendete Speicher ist ein distributed SRAM ohne Takt. 
Wenn man das durch ein Block-RAM ersetzt, dann kommen die Daten beim 
Lesezugriff erst einen Takt später und nicht sofort, wie bei distributed 
RAM. Entweder die CPU selbst muss geändert werden (mehr States) oder man 
nimmt beim RAM die negative Taktflanke zum Zugriff. Das funktioniert 
zwar in diesem Fall, da die Laufzeiten in der CPU sehr kurz sind, ist 
aber kein schönes Design. Wenn man die CPU umbaut, so dass man ein 
Block-RAM verwenden kann, gibt es das nächste Problem. In der 
State-Machine werden die einzelnen States so codiert, dass Fetch und die 
einzelnen Befehle die jeweiligen States sind. Ich finde die 
State_Machine bei der MCPU etwas unübersichtlich, das ist aber nur meine 
Meinung und wenn Du damit zurechtkommst, dann lasse das so. Wenn man das 
sauber machen will (Fetch/WaitForMemory/Execute), dann wird die MCPU 
deutlich größer. Alternativ kann man für das Warten aus den Speicher ein 
FF nehmen, was weniger Aufwand ist.

Also: Im ersten Schritt würde ich das fertige Modul sram64k8.vhd nehmen, 
Das kann man leicht ändern, so dass nur 64 Speicherplätze verwendet 
werden. Im nächsten Schritt würde ich eine Eingabe über Schalter und 
eine Ausgabe über Leds einbauen. Dazu kann man eine Speicheradresse 
(z.B. 63) zweckentfremden. Sobald das funktioniert, kann man an den 
Einbau eines Block-RAMs denken.

Wenn man mehr Speicher oder Befehle braucht, dann kann man die 
Wortbreite von 8 Bit auf z.B. 12 Bit erhöhen.

Viel Spass dabei!

LG
Alexander

von Gustl B. (-gb-)


Bewertung
0 lesenswert
nicht lesenswert
Zitat von hier 
https://forums.xilinx.com/t5/Virtex-Family-FPGAs-Archived/Using-asynchronous-Addr-and-Din-Block-RAM-inputs/td-p/43068

The BlockRAM is 100% synchronous, the only input timing parameters that 
must be met is the setup and hold times relative to the CLK pin.  If you 
want to connect a write enable to the CLK pin you can do it, but this 
doesn't make it an asynschronous RAM.  All of the addr and data pins 
still need to meet the same setup and hold times to the CLK pin 
regardless of what net is driving it.

Und weiter unten:

The BlockRAM will not perform a read or a write operation unless there 
is a rising transition on the CLK pin.

Also verwende einen BlockRAM und schreibe die CPU so um, dass sie da 
getaktet daraus liest.
Oder verwende keinen BlockRAM. Bei 64 Bytes würde ich distributed RAM 
verwenden, der geht ohne Takt.

: Bearbeitet durch User
von Carl (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für eure Antworten.
Eigentlich wollte ich in der finalen Version das Ram einfach als Block 
gegen das On-Board-Ram

Beitrag "Re: XC6SLX16 Spartan 6 Entwicklungsboard"

austauschen.

>von Alexander D. (abadu)
>27.12.2019 10:45

>Der bei der MCPU verwendete Speicher ist ein distributed SRAM ohne Takt.
>Wenn man das durch ein Block-RAM ersetzt, dann kommen die Daten beim
>Lesezugriff erst einen Takt später und nicht sofort, wie bei distributed
>RAM. Entweder die CPU selbst muss geändert werden (mehr States) oder man
>nimmt beim RAM die negative Taktflanke zum Zugriff.

Die einfachste Lösung wäre vielleicht, die CPU einfach mit dem halben 
Takt des Ram zu versorgen.

Bei 50MHz würde ich dann eine Befehlsfrequenz von 50MHz/4 erwarten.

von Ale (Gast)


Bewertung
0 lesenswert
nicht lesenswert
>> Die einfachste Lösung wäre vielleicht, die CPU einfach mit dem halben
>> Takt des Ram zu versorgen.

>> Bei 50MHz würde ich dann eine Befehlsfrequenz von 50MHz/4 erwarten.

... in anderen Wörter, könntest du eine Zustandsmachine mit 2 Zustände 
realisieren, dann wäre es Übersichtlicher:

- Adresse für Fetch
- Fetch & Decode & Execute, und neuer PC Berechnung oder Speicher 
Lese/Schreiben

von Alexander D. (abadu)


Bewertung
0 lesenswert
nicht lesenswert
Carl schrieb:
> Eigentlich wollte ich in der finalen Version das Ram einfach als Block
> gegen das On-Board-Ram
>
> Beitrag "Re: XC6SLX16 Spartan 6 Entwicklungsboard"
>
> austauschen.

Dein Board hat den SDRAM-Speicher MT48LC16M16A2. Google sagt, dass ISE 
nur DDR-Speicher über den fertigen IP-Core ansprechen kann, aber ich 
kann das momentan nicht überprüfen, da ich ISE nicht installiert habe. 
Auch mit fertiger IP ist das Ansteuern des SDRAMs deutlich komplexer als 
die Verwendung von distributed Ram oder Block-Ram.

Carl schrieb:
> Die einfachste Lösung wäre vielleicht, die CPU einfach mit dem halben
> Takt des Ram zu versorgen.

Wie willst Du diese zwei Takte generieren? Ein Clock-Teiler führt nur zu 
Problemen und die Erzeugung über eine PLL ist auch deutlich aufwendiger. 
Wenn Du das unbedingt machen willst, dann kannst Du die CPU bei der 
steigende Taktflanke loslaufen lassen und das Block-Ram bei der 
fallenden Flanke. Allerdings würde ich das nicht machen, da das kein 
sauberes Design ist. Bei Opencores findet man das Projekt pdp8l, dort 
wird der Speicherzugriff so gemacht.

Fang deshalb mit dem distributed Ram an und wenn das sauber läuft, 
kannst Du mit dem Block-Ram beginnen und danach mit dem SDRAM 
weitermachen.

LG
Alexander

Geändert: Ug388 sagt, dass nur DDR/DDR2/DDR3/LPDDR Speicher über den MIG 
angesprochen werden kann.

: Bearbeitet durch User
von Gustl B. (gustl_b)


Bewertung
0 lesenswert
nicht lesenswert
Man kann RAM natürlich auch ohne MIG verwenden. Bei SRAM geht das sehr 
einfach, bei DRAM muss man sich um viele Dinge kümmern und wenn es dann 
noch schnell werden soll sollte möglichst in bursts lesen und schreiben.

Aber es passt eben nicht, dass er jetzt einen asynchronen RAM ohne Takt 
haben will und dann auf SDRAM der überhaupt nicht asynchron ist wechseln 
will. Auch einen BRAM durch einen SDRAM ersetzen geht nicht so einfach. 
Auf einen BRAM kann man zugreifen wann immer man will. Ein SDRAM braucht 
Pausen für Refresh.

von chris (Gast)


Bewertung
1 lesenswert
nicht lesenswert
von Alexander D. (abadu)
>Dein Board hat den SDRAM-Speicher MT48LC16M16A2. Google sagt, dass ISE
>nur DDR-Speicher über den fertigen IP-Core ansprechen kann, aber ich
>kann das momentan nicht überprüfen, da ich ISE nicht installiert habe.
>Auch mit fertiger IP ist das Ansteuern des SDRAMs deutlich komplexer als
>die Verwendung von distributed Ram oder Block-Ram.

Ich glaube, es geht ganz ohne den IP-Core von Xilinx. Das Beispiel 
befindet sich hier:
Beitrag "Re: XC6SLX16 Spartan 6 Entwicklungsboard"

Das Interface dieses RAM-Controllers hat leider noch ein paar 
Ready-Synchronisationssignale für das Schreiben und Lesen, was mir die 
Sache zu verkomplizieren scheint.

Um VHDL-Code zu schreiben, der zwischen den Herstellern austauschbar 
ist, nimmt man wahrscheinlich am besten diesen Controller.
Vielleicht würde es Sinn machen, ein kleines Blockram hinter diesem 
Interface zu verstecken, damit man den Code auf Boards ohne externes 
SDRAM auch ausprobieren kann.

von Alexander D. (abadu)


Bewertung
0 lesenswert
nicht lesenswert
chris schrieb:
> Ich glaube, es geht ganz ohne den IP-Core von Xilinx. Das Beispiel
> befindet sich hier:
> Beitrag "Re: XC6SLX16 Spartan 6 Entwicklungsboard"

Der RAM-Controller schaut wirklich einfach aus. Wieder etwas gelernt.

LG
Alexander

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.