Für Pulse verwenden wir Pulse-Synchronizer und für Level Signal verwenden wir 2-Flop-Synchronizer aber was ist, wenn das Signal Pulse oder Level Verhalten haben kann. Gibt es eine Möglichkeit, das zu synchronisieren?Clock Domain Crossing für Puls- und Pegelsignal
Antwort
Ja, Sie können, aber die Lösung muss auf der Breite des Eingangsimpulses relativ zum Ausgangstakt basieren.
Wenn der Ausgangstakt sehr langsam ist und Sie einen Impuls haben, müssen Sie einen Inline-Pulsstrecker hinzufügen, der in der Eingangstaktdomäne arbeitet. Die Dehnung ist durch die Bitbreite von stretch_out unten definiert und "MUSS" muss größer als ein Takt in der Ausgabe-CLK-Domäne sein.
reg [3:0] stretch_out;
always @ (posedge inclk)
begin
stretch_out <= in_signal ? 4'b1111 : {stretch_out[2:0],1'b0};
end
Jetzt können Sie einfach Ihren Doppel-Flop-Synchronizer verwenden.
reg [1:0] out_sync;
always @ (posedge outclk)
begin
out_sync <= {out_sync[0],stretch_out[3]};
end
Dies sollte eine Ebene und einen Impuls von einer schnellen Domäne in eine langsame Domäne synchronisieren.
Das einzige Problem ist, dass Sie mehr als nur Ihre üblichen zwei Flop-Latenz hinzufügen werden.
Sie könnten asynchron mit dem Signal in der Zieldomäne festlegen, mit Doppelflops synchronisieren und dann die steigende Flanke erkennen. Sollte sowohl für kurze Impulse als auch für lange Pegel funktionieren.
// Prevent DRC violations if using scan
wire in_signal_n = scan_mode ? 1'b1 : !signal_in;
// Following code creates a flop with both async setb and resetb
reg sig_n_async;
always @ (posedge outclk or negedge reset_n or negedge in_signal_n)
if (!reset_n)
sig_n_async <= 0;
else if (!in_signal_n)
sig_n_async <= 1;
else
sig_n_async <= 0;
// Synchronizer
reg [1:0] out_sync;
always @ (posedge outclk or negedge reset_n)
if (!reset_n)
out_sync <= 0;
else
out_sync <= {out_sync[0],sig_n_async};
// Rising edge
reg out_sync_del;
always @ (posedge outclk or negedge reset_n)
if (!reset_n)
out_sync_del <= 0;
else
out_sync_del <= out_sync[1];
wire signal_out = out_sync[1] & !out_sync_del;