mikrocontroller.net

Forum: FPGA, VHDL & Co. FPGA z1013 mit halber Taktfrequenz


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.
Autor: Peter S. (petersieg)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Hallo.

Es geht um folgendes Projekt:
https://www.mikrocontroller.net/articles/Retrocomputing_auf_FPGA
-> Siehe Kapitel Takt.

Dort wird aus 50MHz Boardtakt mittels eines DCM 40MHz für VGA und 
3.125MHz als CPU Takt (cpu_clk) der internen T80 (Z80) CPU, Ram, Rom, 
PIO etc. erzeugt.

Wie häufig, bei alten Spielen, sind die 3.125MHz aber zu schnell und 
Spiele
sind dadurch quasi 'unspielbar'.

Jetzt meine Frage:
Wie kann ich anstatt 3.125MHz die synthetisierten z1013 Komponenten mit 
z.B. der Hälfte=1.5625MHz laufen lassen?
--Input:  50     MHz Startekit
--Output, used: 40     MHz for VGA 600x800@60
--               3.125 MHz for CPU (the lowest what the dcm  can madefrom 50 MHz)
--              50     MHz (out of DCM for 7seg etc)
--              Status (for debug)
--40MHz pixel clock
--Design Name: dcm_sys
--Device: xc3s200-ft256-5
--4 BUFG; 1 IBUFG; DCM

library ieee;
use ieee.std_logic_1164.ALL;
use ieee.numeric_std.ALL;
library UNISIM;
use UNISIM.Vcomponents.ALL;

entity dcm_sys is
   port ( CLKIN_IN        : in    std_logic;  --incoming from pcb 
          CLKDV_OUT       : out   std_logic; 
          CLKFX_OUT       : out   std_logic; 
          CLKIN_IBUFG_OUT : out   std_logic; 
          CLK0_OUT        : out   std_logic; 
          CLK180_OUT      : out   std_logic;
          status_o        : out   std_logic_vector(7 downto 0));
end dcm_sys;
architecture arch of sk_top is
  component dcm_sys
    port (
      CLKIN_IN        : in  std_logic;
      CLKDV_OUT       : out std_logic; -- wird mit cpu_clk verbunden
      CLKFX_OUT       : out std_logic;
      CLKIN_IBUFG_OUT : out std_logic;
      CLK0_OUT        : out std_logic;
      CLK180_OUT      : out std_logic;
      STATUS_O        : out std_logic_vector(7 downto 0));
  end component;


  component redz0mb1e
    port (
      video_clk    : in  std_logic;
      cpu_clk      : in  std_logic;
      clk_50m      : in  std_logic;
      keys_in      : in  std_logic_vector(2 downto 0);
      --
...
  dcm_sys_1 : dcm_sys
    port map (
      CLKIN_IN        => sys_clk,       --incoming clock before BUFG
      CLKDV_OUT       => cpu_clk,       --divided for Z80 clk
      CLKFX_OUT       => video_clk,
      CLKIN_IBUFG_OUT => open,          --incoming clock behind BUFG
      CLK0_OUT        => clk_50m,       --clock after DCM
      CLK180_OUT      => open,
      status_o        => open);


Also quasi zwischen dcm output (alter cpu_clk (*2)) einen Teiler/2 
dazwischen schalten um damit dann alle anderen Komponenten zu takten.

Peter

Autor: Tim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
da du wahrscheinlich nicht das ganze Design auf Clock_enable umschreiben 
willst, empfehle ich einfach den Takt nach der DCM per Flipflop zu 
teilen. Für die Frequenz sollte das gut machbar sein.

Danach den Ausgang noch auf ein BUFG schalten.

In etwa so (bufg nochmal nachschauen):
signal cpu_clk_div2 : std_logic := '0';

if rising_edge(cpu_clk)
   cpu_clk_div2 <= not cpu_clk_div2;
end

bufg_i : bufg
port map (
 CLKIN => cpu_clk_div2
 CLKOUT => cpu_clk_bufg );

Autor: Bildverarbeiter (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Tim schrieb:
> Danach den Ausgang noch auf ein BUFG schalten.

Genau soetwas war zu erwarten!

Wenn schon, dann bitte einen weiteren DCM nehmen und diesen 
eleganterweise davor einsetzen, der bereits den eingehenden Takt "teilt" 
und am Ausgang einen ordentlichen, berechenbaren Takt ermöglicht. Die 
Dinger kann man bedenkenlos kaskadieren, sogar über nicht dediziertes 
Taktrouting. Das ist zehnmal besser, als einen verhackstückten Takt.

Autor: Robert P. (fpgazumspass) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei einer CPU reicht es oft nur den Einstieg(erste Stage in der Kette) 
per Clock enable zu versehen.
Das hat zudem den Vorteil, das man schneller Takten kann, wenn 
erwünscht.
(Turbomode).

Habe ich bei meinem Z80 Nachbau(siehe Gameboy Thread bei den Projekten) 
so gemacht.
So läuft die CPU mit 4/8 Mhz, wie im Original, auf Tastendruck gibt es 
kurzzeitig 100Mhz + Frameskip, z.b. um Ladezeiten zu überspringen.

: Bearbeitet durch User
Autor: Gustl B. (-gb-)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei Xilinx haben die aber eine untere Grenze. Zumindest im Wizard. Da 
muss der Eingangstakt 10 MHz oder mehr sein und als Ausgang sind 
irgendwas zwischen 4,xxx und 800 MHz erlaubt.

Was spricht denn gegen das Teilen mit einem FF wenn das dann nur an 
einer Stelle auf ein Taktnetz geht? Das wäre doch dann so wie wenn man 
extern einen Takt teilt und über einen Clock Pin dem FPGA zuführt.

Autor: Sigi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie Oben zT ja schon geschrieben kannst du eine
gated Clock erzeugen (z.B. per DDS oder einfach
per simplen Counter). Das gilt zwar unter
FPGA-Entwicklern als NoGo, da die Frequenz aber
"extrem" klein ist (ein paar MHz), ist das für
dein Ziel absolut akzeptabel. Denn du hast ja
z.B. bei 1MHz eine Signallaufzeit von 1000ns.
Und ob du da über BUFGs gehst oder direkte
Verbindungen wählst ist absolut irrelevant.
Relevant wird es aber, sobald IO-Bausteine ins
Spiel kommen, wie z.B.VGA. Hier müssen dann
alle Signale entsprechend auf eine Non-Gated
Clockdomaine gehievt werden. Das sollte aber
kein Problem sein.

Das ganze habe ich schon bei zig Retro-Nachbauten
gemacht, lief immer problemlos. Allerdings hatte
eine VGA-Ausgabe der gated Clockdomain oft einen
Pixelversatz, aber per Einsyncronisation lies
sich das immer problemlos beheben.

Autor: Gustl B. (-gb-)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sigi schrieb:
> Und ob du da über BUFGs gehst oder direkte
> Verbindungen wählst ist absolut irrelevant.

Bei dem geringen Takt vielleicht. Aber eigentlich kommt es doch vor 
allem bei hohen Frequenzen drauf an, dass der Takt möglichst zeitgleich 
überall ankommt. Und das passiert doch wenn das über ein Taktnetz geht.

Ob der Takt dann intern durch ein FF erzeugt wurde oder extern von einem 
Oszillator kommt ist dann doch eigentlich egal?! Ja, das hat dann 
vielleicht mehr Jitter, aber zu jedem Takt erreicht die Flanke 
einigermaßen zeitgleich alle Ziele.

Ich hatte damit bisher nur Probleme wenn ich kein Taktnetz verwendet 
habe. Wenn man den Code aber sowieso selbst neu schreibt sind Clock 
Enables sinnvoller, dann kann man intern den normalen Takt verwenden.

Autor: Sigi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gustl B. schrieb:
> Bei dem geringen Takt vielleicht. Aber eigentlich kommt es doch vor
> allem bei hohen Frequenzen drauf an, dass der Takt möglichst zeitgleich
> überall ankommt. Und das passiert doch wenn das über ein Taktnetz geht.

Es kommt immer darauf an, dass alle FFs "möglichst gleichzeitig"
den Takt bekommen, egal ob niedrige oder hohe Tahtrate! Denn
sonst könnte ja ein FF A den Takt deutlich nach FF B bekommen,
aber von B lesen. In dieser Situation liest also A den nächsten
Wert von B und nicht den eigentlich aktuellen Wert. Und bei
deiner Bemerkung fällt mir gerade auf, dass ich vergessen habe,
bei direkter Verbindung der Clock die From-To-Constraints zu
erwähnen. Ohne die passiert eben genau dies. Im Prinzip hast
du natürlich recht, dass ein Einspeisen ins Clock-Netzwerk
besser und unkomplizierter ist. (aber nur so als Nebenbemerkung:
bei einigen Familien gibt es evtl. keine Möglichkeit, ein komb.
oder FF-Signal ins Clock-Netz einzuspeisen oder umgekehrt ein
Komb./FF-Signal direkt als Clock-Signal zu verwenden, von daher
habe ich mir vor langer Zeit beide Möglichkeiten ausgedacht)

Gustl B. schrieb:
> Ob der Takt dann intern durch ein FF erzeugt wurde oder extern von einem
> Oszillator kommt ist dann doch eigentlich egal?!

Wenn's nur um die internen Abläufe geht, da hast du recht.
Aber z.B. bei VGA-Signalen kann durch eigene Logik erzeugte
Taktsignale das Jittern so gross sein, dass sich je nach
Zeile die Pixels um eine Position nach Hintern verschieben
können.

Autor: J. S. (engineer) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gustl B. schrieb:
> Bei Xilinx haben die aber eine untere Grenze. Zumindest im Wizard. Da
> muss der Eingangstakt 10 MHz oder mehr sein und als Ausgang sind
> irgendwas zwischen 4,xxx und 800 MHz erlaubt.

Ja, wobei:

Hier geht es ja konkret um den Spartan 3. Der kann auch niedriger 
getaktet werden, wenn man die PLL-Funktion mit phase lock nicht 
verwendet. Dann liegt die untere GF bei glaube ich 5MHz.

Gustl B. schrieb:
> Ja, das hat dann
> vielleicht mehr Jitter, aber zu jedem Takt erreicht die Flanke
> einigermaßen zeitgleich alle Ziele.

Weil die Möglichkeit besteht, von einem nicht-Taktnetz über einen BUFG 
doch wieder in eine Taktnetz zu gelangen. Gleichwohl ist das nicht so 
ideal, weil von der heute angewendeten timing driven synthesis nicht 
(gut) zu berechnen. Das konnte man bei "langsamen" FPGAs unter 100MHz 
und ISE machen.

Ich würde einen Clock-Buffer mit Teiler 1:2 nehmen, um die Frequenz an 
den DCM zu kriegen.

ISE kann übrigens doppelte DCMs konfigurieren.

Autor: Sigi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jürgen S. schrieb:
> Weil die Möglichkeit besteht, von einem nicht-Taktnetz über einen BUFG
> doch wieder in eine Taktnetz zu gelangen. Gleichwohl ist das nicht so
> ideal, weil von der heute angewendeten timing driven synthesis nicht
> (gut) zu berechnen.

Bei den für Retro-Systeme üblichen Frequenzen sind
alle Timing-Berechnungen idR komplett überflüssig,
denn wo hat man schon mal eine z.B. Kombinatorik
einer Beschreibung, die mehr als 1000ns Laufzeit
braucht. Selbst 100ns (=> 10MHz) sind relativ egal.

Autor: Gustl B. (-gb-)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sigi schrieb:
> Aber z.B. bei VGA-Signalen kann durch eigene Logik erzeugte
> Taktsignale das Jittern so gross sein, dass sich je nach
> Zeile die Pixels um eine Position nach Hintern verschieben
> können.

Gut wenn man das MSB eines großen Akkus wie bei der DDFS als neuen Takt 
verwendet hat man natürlich massiv Jitter.
Aber wenn ich durch eine Zweierpotenz teilen will dann sollte das recht 
gut klappen. Auch ganzzahlige feste Teiler sind doch ok weil dann nimmt 
man eben einen Zähler der bis zu einem bestimmten Wert zählt. Dann hat 
der neue Takt zwar oft kein 50:50 Tastverhältnis, aber er hat eine feste 
Periodendauer.

Jürgen S. schrieb:
> Gleichwohl ist das nicht so
> ideal, weil von der heute angewendeten timing driven synthesis nicht
> (gut) zu berechnen.

Erkennt die Synthese das als neuen Takt, wenn ich einen Takt mit einem 
FF teile, in ein Taktnetz einspeise?

Erkennt die Synthese feste Clock-Enables im Sinne von "alle n Takte ist 
das Enable für einen Takt aktiv"?
Für manche Rechnungen habe ich diese Multi-cycle-constraints gesetzt. Da 
wäre es schon schick, wenn man das "langsamer" mit Clock-Enables bauen 
könnte. Nicht wirklich langsamer, weil der Takt ja gleich hoch bleibt, 
aber das Ergebnis wird eben erst zum nächsten Clock-Enable ein paar 
Takte später erwartet.

Autor: Fpga K. (fpgakuechle) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich mich erinnere, gab es damals xilinxspezif. Gründe warum ich das 
Design nicht auf 1MHz setzte. Ich schlage daher einen Alternativen Weg 
zum Abbremsen vor: Der Z80-Cpu sollte man Wartezeiten aufzwingen können, 
indem man bspw. ihr Bus per BUSRQ entzieht . Dann könnte man den Takt 
belassen wo er ist.
So ein Modul hatte ich mal angefangen, es könnte sich aber aus 
beruflichen Gründen (grad beim Selbstständigmachen) noch Monate 
hinziehen.

Autor: Peter S. (petersieg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok. Ich habe es nicht eilig ;-)

Peter

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter S. schrieb:
> Wie häufig, bei alten Spielen, sind die 3.125MHz aber zu schnell und
> Spiele sind dadurch quasi 'unspielbar'.
Original liefen die ersten Z1013 meines Wissens nach mit 1 MHz 
Taktfrequenz, später dann mit 2 MHz.
Die 3.125 MHz (oder die Hälfte davon) haben mit dem Original nicht viel 
zu tun.


Peter S. schrieb:
> dcm_sys_1 : dcm_sys
>     port map (
>       CLKIN_IN        => sys_clk,       --incoming clock before BUFG
>       CLKDV_OUT       => cpu_clk,       --divided for Z80 clk
>       CLKFX_OUT       => video_clk,
>       CLKIN_IBUFG_OUT => open,          --incoming clock behind BUFG
>       CLK0_OUT        => clk_50m,       --clock after DCM
>       CLK180_OUT      => open,
>       status_o        => open);

Wird CLK0_OUT noch irgendwo verwendet oder kann das weg?

Bei CLKFX und CLK0 bzw. CLK180 liegt die Mindestfrequenz bei 5 MHz 
(CLK2X0 -> 10 MHz). Also geht nur CLKDV.

Die möglichen Teiler für CLKDV liegen zwischen 1.5 und 16. Du bräuchtest 
einen Teiler von 25 um von 50 MHz auf 2 MHz zu kommen.

Ich würde auch mit zwei DCMs arbeiten und jeweils die Frequenz durch 5 
teilen.
    dcm_sp_1st_instance: dcm_sp
    generic map (
        clkin_divide_by_2 => false,
        clkdv_divide      => 5.0,
        clk_feedback      => "1x"
    )
    port map (
        clkin => sys_clk,
        clk0  => clk0,
        clkdv => clkdv0,
        clkfb => clk_fb0
    );
    clk_fb0   <= clk0;
       
    dcm_sp_2nd_instance: dcm_sp
    generic map (
        startup_wait      => true,
        clkdv_divide      => 5.0,
        clk_feedback      => "1x"
    )
    port map (
        clkin => clkdv0,
        clk0  => clk1,
        clkdv => cpu_clk,
        clkfb => clk_fb1
    );
    clk_fb1   <= clk1;
Der erhöhte Jitter dürfte hier keine Rolle spielen, sondern eher zum 
Retrofeeling beitragen...

Duke

Autor: J. S. (engineer) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sigi schrieb:
> Bei den für Retro-Systeme üblichen Frequenzen sind
> alle Timing-Berechnungen idR komplett überflüssig,
> denn wo hat man schon mal eine z.B. Kombinatorik
> einer Beschreibung, die mehr als 1000ns Laufzeit

Auf den ersten Blick mag die Betrachtung stimmen, aber die 
Retro-FPGA-Systeme sind wie im Beispiel oben auch gerne mit einem 
Retro-FPGA bestückt, für die 100MHz utopisch sind. Man darf auch die 
Anforderungen der Chips nicht unterschätzen: Einen Grafik-Controller 
oder Sound-Chip wie den SID emuliert man nicht 1:1 mit FPGA-Silizum. Es 
kann durchaus nötig sein, gewisse Verzögerungen zwischen Komponenten 
fein aufzulösen, was entsprechende Taktraten erfordert und bei 20MHz 
sind an anderer Stelle 50ns schnell aufgebraucht, z.B. für 2 verkettete 
Multiplier.

Duke Scarring schrieb:
> Der erhöhte Jitter dürfte hier keine Rolle spielen, sondern eher zum
> Retrofeeling beitragen...

Den Jitter wird man kaum merken, aber dessen Berücksichtigung erschwert 
das Abschließen des Timings durch die Synthese.
Ok, bei dem Design mag das eine untergeordnete Rolle spielen.

: Bearbeitet durch User
Autor: Sigi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jürgen S. schrieb:
> Einen Grafik-Controller
> oder Sound-Chip wie den SID emuliert man nicht 1:1 mit FPGA-Silizum.

Da hast du natürlich recht, z.B. muss für den VIC
wesentlich mehr an MHz investiert werden, für den
VIC-II reicht aber eine Schaltung mit 8MHz.
Beim SID wiederum ist der Digitalteil überhaupt
nicht kritisch, da reichen sub-sub-MHze.
Kritisch sind die Filter. Die habe ich aber komplett
durchgemessen (z.B. mit Terasic-NEEK, denn hast
du ja auch, hier ist der Wolfson-Audio-Chip zum
Samplen und Ausgeben interessant, in Verbindung mit
dem FPGA ideal zum systematischen!! Durchmessen),
eine HDL-Simulation aller Komponenten habe ich auch
schon gemacht., nur noch nicht komplett zu einem
SID zusammengefasst. Selbst da sind nur kleine
MHz-Bereiche ausreichend (meine Beobachtung/Messung
bis jetzt, du bist aber Audio-Profi -- ich Laie! --
und wirst bei meinen Ansätzen sicherlich noch
Fehler finden).
Ebenso beim Amiga. Und da sind Frequenzen bis
8 bzw. 16 MHz. Und auch da: Timing-Constrainst
irrelavant.
Und schnellere Retro-Geschichten wie z.B.
Playstation 1 oder Gar N64 kann man wohl vergessen.
(da sind dann Timings sehr schnell kritisch)

Autor: Peter S. (petersieg)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Ich (als VHDL noob) habe es jetzt erst einmal so 'gelöst' (soll heißen, 
es scheint zu funktionieren = synthetisiert und Spiel läuft etwas 
langsamer):

in sk_wrapper.vhd:
...
  component clk_div
    port (
      CLK_IN       : in  std_logic;
      CLK_OUT      : out std_logic);
  end component;
...
  signal clk_50m                  : std_logic;
  signal video_clk                : std_logic;
  signal cpu_clk                  : std_logic; 
  signal cpu_clk2                 : std_logic; -- new
...
---
  dcm_sys_1 : dcm_sys
    port map (
      CLKIN_IN        => sys_clk,       --incoming clock before BUFG
      CLKDV_OUT       => cpu_clk2,      --3.125MHz divided for Z80 clk
      CLKFX_OUT       => video_clk,
      CLKIN_IBUFG_OUT => open,          --incoming clock behind BUFG
      CLK0_OUT        => clk_50m,       --clock after DCM
      CLK180_OUT      => open,
      status_o        => open);

  clk_div_1 : clk_div
    port map (
      CLK_IN        => cpu_clk2,        --3.125MHz from dcm
      CLK_OUT       => cpu_clk);        --1.5625 divided for Z80 clk

...


Plus neue Datei clk_div.vhd unter kleinkram inkludiert:
-- clk divider/2

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity clk_div is
  port(
    clk_in  : in  std_logic;
    clk_out : out std_logic);
end entity clk_div;

architecture Behavioral of clk_div is

signal clk_sig : std_logic := '0';

begin
  Process (clk_in) 
  begin
    if (rising_edge(clk_in)) then
      clk_sig <= not (clk_sig);
    end if;
  end Process;
  clk_out <= clk_sig;
end Behavioral;

Peter

: Bearbeitet durch User

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.