Synchroner Reset im Multi-Clock-FPGA-Design

Ich möchte damit beginnen, Sync-Reset in meinen FPGA-Designs zu verwenden, und ich bin neu im Xilinx FPGA-Design.

Normalerweise habe ich 5-6 Takte in jedem Design, und das Zurücksetzen wird vom Druckknopf auf der Platine gesteuert.

Was ist eine bewährte Vorgehensweise, um dieses asynchrone Signal, das zu meinem FPGA kommt, als synchrones Zurücksetzen aller Uhren in meinem FPGA-Design zu verwenden?

Ich dachte nur daran, dasselbe asynchrone Drucktastensignal mit jeder Uhr auf der Platine parallel zu synchronisieren, wie das Blockdiagramm, das ich hier zeichne:

Geben Sie hier die Bildbeschreibung ein

Der Top-Level-Code für Uhren und Reset-Generierung:

`Zeitskala 1 ns / 1 ps

module top_test1 (

    input  wire       clk_200mhz_p,     // external clock 200 MHz - p
    input  wire       clk_200mhz_n,     // external clock 200 MHz - n
    input  wire       reset             // reset push button
);

//*--------------------------------
//* Clock and reset
//*--------------------------------
// Internal 200 MHz clock - System
wire clk_200mhz_ibufg;  // internal 200 MHz clock
wire rst_200mhz_int;    // internal 200 MHz synchronous reset

// Internal 125 MHz clock - Ethernet
wire clk_mmcm_out;      // mmcm clk out - 125 MHz
wire clk_125mhz_int;    // internal 125 MHz clock
wire rst_125mhz_int;    // internal 125 MHz synchronous reset

// Internal 50 MHz clock - DSP
wire clk_bufr_out_50mhz;    // bufr 50mhz clock -> 200 MHz / 4 = 50 MHz
wire clk_50mhz_int;         // internal 50 MHz clk
wire rst_50mhz_int;         // internal 50 MHz synchronous reset


wire mmcm_rst = reset;
wire mmcm_locked;
wire mmcm_clkfb;

IBUFGDS
clk_200mhz_ibufgds_inst(
    .I    (clk_200mhz_p),
    .IB   (clk_200mhz_n),
    .O    (clk_200mhz_ibufg)
);

sync_reset #(
    .N        (4)
)
sync_reset_inst_200mhz (
    .clk    (clk_200mhz_ibufg),
    .rst    (reset),
    .out    (rst_200mhz_int)
);

MMCME2_BASE #(
    .BANDWIDTH           ("OPTIMIZED"),
    .CLKOUT0_DIVIDE_F    (8),
    .CLKOUT0_DUTY_CYCLE  (0.5),
    .CLKOUT0_PHASE       (0),
    .CLKOUT1_DIVIDE      (8),
    .CLKOUT1_DUTY_CYCLE  (0.5),
    .CLKOUT1_PHASE       (0),
    .CLKOUT2_DIVIDE      (1),
    .CLKOUT2_DUTY_CYCLE  (0.5),
    .CLKOUT2_PHASE       (0),
    .CLKOUT3_DIVIDE      (1),
    .CLKOUT3_DUTY_CYCLE  (0.5),
    .CLKOUT3_PHASE       (0),
    .CLKOUT4_DIVIDE      (1),
    .CLKOUT4_DUTY_CYCLE  (0.5),
    .CLKOUT4_PHASE       (0),
    .CLKOUT5_DIVIDE      (1),
    .CLKOUT5_DUTY_CYCLE  (0.5),
    .CLKOUT5_PHASE       (0),
    .CLKOUT6_DIVIDE      (1),
    .CLKOUT6_DUTY_CYCLE  (0.5),
    .CLKOUT6_PHASE       (0),
    .CLKFBOUT_MULT_F     (5),
    .CLKFBOUT_PHASE      (0),
    .DIVCLK_DIVIDE       (1),
    .REF_JITTER1         (0.010),
    .CLKIN1_PERIOD       (5.0),
    .STARTUP_WAIT        ("FALSE"),
    .CLKOUT4_CASCADE     ("FALSE")
)
clk_mmcm_inst (
    .CLKIN1              (clk_200mhz_ibufg),
    .CLKFBIN             (mmcm_clkfb),
    .RST                 (mmcm_rst),
    .PWRDWN              (1'b0),
    .CLKOUT0             (clk_mmcm_out),
    .CLKOUT0B            (),
    .CLKOUT1             (),
    .CLKOUT1B            (),
    .CLKOUT2             (),
    .CLKOUT2B            (),
    .CLKOUT3             (),
    .CLKOUT3B            (),
    .CLKOUT4             (),
    .CLKOUT5             (),
    .CLKOUT6             (),
    .CLKFBOUT            (mmcm_clkfb),
    .CLKFBOUTB           (),
    .LOCKED              (mmcm_locked)
);

BUFG clk_bufg_inst_125mhz (
    .I    (clk_mmcm_out),
    .O    (clk_125mhz_int)
);

sync_reset #(
    .N        (4)
)
sync_reset_inst_125mhz (
    .clk    (clk_125mhz_int),
    .rst    (reset),
    .out    (rst_125mhz_int)
);

BUFR #(
    .BUFR_DIVIDE("4"),      // Values: "BYPASS, 1, 2, 3, 4, 5, 6, 7, 8"
    .SIM_DEVICE("7SERIES")  // Must be set to "7SERIES"
)
BUFR_inst_50mhz (
    .O      (clk_bufr_out_50mhz),   // Clock output port
    .CE     (1'b1),                 // Active high, clock enable (Divided modes only)
    .CLR    (rst_int),              // Active high, asynchronous clear (Divided modes only)
    .I      (clk_200mhz_ibufg)      // Clock buffer input..
                                    // ..driven by an IBUF, MMCM or local interconnect
);

BUFG clk_bufg_inst_50mhz (
    .I    (clk_bufr_out_50mhz),
    .O    (clk_50mhz_int)
);

sync_reset #(
    .N        (4)
)
sync_reset_inst_50mhz (
    .clk    (clk_50mhz_int),
    .rst    (reset),
    .out    (rst_50mhz_int)
);

endmodule

Das "sync_reset"-Modul ist nur eine Pipeline von N Registern. Ist es also eine gute Möglichkeit, alle Synchronisierungsrücksetzungen zu erstellen, die ich für mein Design benötige?

Ich möchte nur sicher sein.

Sie möchten wahrscheinlich etwas bauen, das alles andere zurücksetzt. Beachten Sie insbesondere, dass Sie für alle DLL-basierten Uhren die getaktete Logik zurückgesetzt halten müssen, bis die Uhr gut ist - andernfalls sehen Sie möglicherweise überraschende Ergebnisse, zum Beispiel kann das FPGA-"ROM" beschädigte Inhalte sehen, wenn das Lesetiming verletzt wird !

Antworten (4)

Es sieht gut aus. Normalerweise reicht ein 2-Flop-Synchronizer für die von Ihnen angestrebten Taktfrequenzen aus. Das habe ich mit Push-Button-Resets auf FPGA-Boards verwendet. Aber ein 4-Flop-Synchronizer liefert immer noch eine bessere MTBF. Da Ihr Design synchrones Zurücksetzen verwendet, müssen und werden sowohl die Aktivierung als auch die Freigabe des "asynchronen Zurücksetzens auf Knopfdruck" von dieser Kette von Flip-Flops mit den jeweiligen Taktdomänen synchronisiert.

Da Sie Ihre eigene Synchronizer-Kette entworfen haben, ist es ratsam, die Eigenschaft ASYNC_REG (Seite Nr. 9 im Dokument) auf den Zielflops anzugeben . Vivado sagt -

Die Angabe von ASYNC_REG wirkt sich auch auf die Optimierung, Platzierung und das Routing aus, um die mittlere Zeit vor dem Ausfall (MTBF) für Register zu verbessern, die möglicherweise metastabil werden. Wenn ASYNC_REG angewendet wird, stellt der Placer sicher, dass die Flip-Flops in einer Synchronisationskette eng platziert sind, um MTBF zu maximieren

Sie können auch erwägen, dem Pfad einen Entpreller hinzuzufügen, um fehlerhafte Zurücksetzungen zu vermeiden. Damit Ihre Schaltung nicht zurückgesetzt wird, wenn die Reset-Impulsbreite nicht "lang genug" ist, sagen wir vier Taktzyklen.

Beispiel:

Geben Sie hier die Bildbeschreibung ein

Der obere ist für einen Active-Low-Reset.

Der untere ist für einen Active-High-Reset.

Dafür gibt es ein Bibliothekselement. Siehe meine Antwort.

Im Allgemeinen möchten Sie, dass die Reset-Freigabe mit der Uhr des Blocks synchronisiert wird. Sie möchten auch sicherstellen, dass in diesem Fall tatsächlich eine laufende Uhr vorhanden ist und dass sie lange genug gelaufen ist, damit das Zurücksetzen vollständig wirksam wird.

Die Xilinx-Bibliothek enthält einen konfigurierbaren Reset-Block, der dies für Sie erledigt. Link: https://www.xilinx.com/products/intellectual-property/proc_sys_reset.html

Du sprichst hier einen guten Punkt an. Was meinst du mit "lang genug"? Genug, damit das Zurücksetzen durch nicht zurückgesetzte Pipeline-Stufen läuft? Damit die PLL stabil ist (stabile Taktperiode) ...? (einer benötigt einen Zähler, der andere ein Lock-Signal etc...)
Beide PLL stabil und lange genug danach, damit alle Sync-Resets durchgehen können.
Danke, und würden Sie das Lock/Stable-Signal als synchron oder asynchron betrachten? Einige Handbücher behaupten, dass der Sperrausgang ihres Geräts mit einer der Uhren synchronisiert ist, aber es stellt sich heraus, dass es immer noch klappern kann ...
Ich würde eine stabile Sperre als asynchron betrachten und müsste selbst in die Zieldomäne neu synchronisiert werden.
Einverstanden. Danke. Stört es Sie, wenn ich Ihre Kommentare in der Antwort bearbeite? Oder Sie könnten es natürlich selbst tun, da es wertvoller Input ist.
Es ist gut, wie es ist, danke. Interessierte Nutzer können unsere Diskussion hier einsehen.
Für mich natürlich in Ordnung, aber Kommentare werden im Laufe der Zeit gelöscht und von Google nicht indiziert.

Hier ist ein Beispiel eines FPGA-Designs mit zwei Taktdomänen. Eines ist eine 33-MHz-PCI-Schnittstelle und zugehörige Schaltkreise, das andere ist für einen 50-MHz-Block. Hinweis - der Schlüssel hier ist, wie andere gesagt haben, das Zurücksetzen synchron zur Domänenuhr freizugeben.

Geben Sie hier die Bildbeschreibung ein

Tatsächlich verwendet OP in seinem Design ein synchrones Zurücksetzen, aber das Zurücksetzen der Drucktaste, das er auf der Platine einstellt, ist ein asynchrones Signal. Also müssen SOWOHL die Behauptung als auch die Freigabe dieses "asynchronen Zurücksetzens" mit der Uhr synchronisiert werden. Wenn das OP in seinem Design ein asynchrones Zurücksetzen verwendet, muss nur die Freigabe synchronisiert werden.
Wo würdest du "und" es mit dem PLL-Lock/Takt stabilen Signal? Vor den RST / _RST_N Eingängen oder nach den Creset Ausgängen?

Idealerweise wird ein Reset asynchron durch einen „entprellten“ aktiven Low-Zustand initialisiert und bleibt dann in diesem Zustand, bis er freigegeben wird, was mit einem einzigen Flip-Flop mit der Systemuhr synchronisiert wird.

Die Auslösung erfolgt nicht nur mechanisch, sondern wird durch einen Kondensator niedrig gehalten, dessen RC-Zeitkonstante länger ist als die Prellzeit eines alten, verschlissenen Knopfschalters oder 15 ms oder mehr bei einem Schmitt- Trigger .

  • Es wird erwartet, dass Tastenschalter im Bereich von 1 bis 5 ms und 1-A-Kippschalter 10 bis 25 ms prellen.

    : Empfehlung

  • Alles, was Sie brauchen, ist eine Kappe, ein Schmitt-Trigger-Gate und eine D FF-Systemuhr mit einem Knopfschalter gegen Masse und natürlich Ihren 10-kΩ-auf-1-MΩ-Pullup.

Habe es?

  • Die Idee ist, dass der erste Tastenkontakt auflädt und die Reset-Niedrigspannung hält, und wenn die Freigabe abprallt, bleibt der Kondensator trotzdem lange genug niedrig, um mehrere Flanken zu verhindern.

  • Stellen Sie einfach sicher, dass Sie in Ihrem Design einen „zustandsgesteuerten“ Reset und keinen „flankengesteuerten“ Reset haben, es sei denn, diese Schaltung synchronisiert sich selbst oder muss nicht synchron sein.

Muss ich das zeichnen?

Dies beantwortet nicht die Frage, wie damit in einem mehrfach getakteten FPGA-Design umzugehen ist.
Alle Takte sind in der Frequenz synchron, können aber in der Latenz variieren. Meine Antwort gilt also immer noch. Sie synchronisieren alle Uhren auf 1 Hauptuhr-Reset-Entfernung. Also widerspreche ich stark @Graham