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:
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.
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:
Der obere ist für einen Active-Low-Reset.
Der untere ist für einen Active-High-Reset.
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
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?
Chris Stratton