-
Notifications
You must be signed in to change notification settings - Fork 43
/
CDC_Bit_Synchronizer.html
161 lines (142 loc) · 7.18 KB
/
CDC_Bit_Synchronizer.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
<html>
<head>
<link rel="shortcut icon" href="./favicon.ico">
<link rel="stylesheet" type="text/css" href="./style.css">
<link rel="canonical" href="./CDC_Bit_Synchronizer.html">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Use a synchronizer to convert changes in a signal in one clock domain into changes which are synchronous to another clock domain, while reducing the probability of metastable events propagating.">
<title>CDC Bit Synchronizer</title>
</head>
<body>
<p class="inline bordered"><b><a href="./CDC_Bit_Synchronizer.v">Source</a></b></p>
<p class="inline bordered"><b><a href="./legal.html">License</a></b></p>
<p class="inline bordered"><b><a href="./index.html">Index</a></b></p>
<h1>Clock Domain Crossing (CDC) Bit Synchronizer</h1>
<p>Use a synchronizer to convert changes in a signal in one clock domain into
changes which are synchronous to another clock domain, while reducing the
probability of metastable events propagating.</p>
<h2>A Warning</h2>
<p>A synchronizer is a trivial circuit, but it breaks the conventions of
synchronous logic while doing its best to contain the consequences. Thus,
it is very easy to use a synchronizer incorrectly, leading to worse timing
closure at best, or at worst intermittent circuit malfunctions which won't
be visible (or even reproducible!) in simulations. We go over the necessary
subtleties in the text and code below.</p>
<h2>Relative Clock Frequency Constraints</h2>
<p>This synchronizer is the fundamental building block of all other CDC
circuits, and it must be used under one major constraint to operate
properly: Any change on the input signal must hold steady for a <strong>minimum</strong>
of 1.5x longer than the period of the receiving clock to guarantee enough
time for three receiving clock edges (posedge/negedge/posedge, or
negedge/posedge/negedge) to pass, which guarantees that the input signal
will be properly sampled by a posedge.</p>
<p>Any less time, and the input signal could change back before it was sampled
by the receiving clock. In other words, assuming single-cycle changes
(pulses), the receiving clock domain can have a clock frequency of at most
0.66x that of the sending clock domain. For any higher receiving clock
freqency, you must guarantee that the change on the input signal will last
enough input clock cycles to be seen by at least three consecutive
receiving clock edges.</p>
<p>If you cannot guarantee the duration of a pulse and/or have no knowledge of
the relative clock domain frequencies, use a <a href="./CDC_Pulse_Synchronizer_2phase.html">Pulse
Synchronizer</a>.</p>
<p>Similarly, if the rise/fall time of the input signal is longer than the
receiving clock period, the receiving clock will sample the transistion
multiple times, which will show up as possibly multiple pulses at the
output. In these cases, use a <a href="./Debouncer_Low_Latency.html">Debouncer</a>.</p>
<h2>Single-Bit Synchronization Only</h2>
<p>Also, for reasons explained in <a href="./cdc.html">A Primer on Clock Domain Crossing
Theory</a>, the latency of a CDC Synchronizer can vary between
1 and 3 cycles, depending on clock phase and metastability events, and so
<strong>only one signal may be synchronized at each clock domain crossing</strong>.
Using multiple CDC Synchronizers in parallel is <strong>not deterministic</strong> as
there is no guarantee they will all have the same latency.</p>
<p>If you need to pass multiple signals (e.g.: a bus), synchronize one signal
in each direction as a ready/valid handshake, and capture the other signals
(held steady during synchronization) directly in the receiving clock domain
once the one signal has synchronized. Remember to constrain and check the
delay on the other signals. The <a href="./CDC_Word_Synchronizer.html">CDC Data
Synchronizer</a> implements this approach, and
the <a href="./CDC_Pulse_Synchronizer_2phase.html">CDC Pulse Synchronizer</a> can also
be used to build similar CDC circuits.</p>
<h2>Avoid Logic Glitches</h2>
<p><strong>You must feed a CDC Synchronizer directly from a register</strong>, with no
logic between it and the synchronizer. Otherwise, it's possible that
multiple logic paths will converge to the synchronizer, and convergent
logic can glitch when signals change state (we're not getting into that
theory here). Normally, a subsequent register will filter out such
glitches since they settle long before the next clock edge. However,
a synchronizer's unrelated and asynchronous receiving clock may just happen
to sample the input when a glitch occurs, transforming that glitch into
a real, and completely wrong, logic pulse in the receiving clock domain!
Alternately, a high signal may glitch early to low and be missed by the
receiving clock.</p>
<h2>Not Usable as I/O Registers</h2>
<p>On an FPGA, you should not use an I/O register as one of the stages of
a synchronizer: they are too far from the main logic fabric, and
synchronizer registers must be as close together as possible (see <a href="./cdc.html">A Primer
on Clock Domain Crossing Theory</a>). Thus, your input or output
must connect to a dedicated I/O register synchronous to the I/O clock,
which in turn connects to a CDC synchronizer driven by the internal clock.
<strong>This extra I/O register also filters out any input glitches, as outlined
above.</strong></p>
<pre>
`default_nettype none
module <a href="./CDC_Bit_Synchronizer.html">CDC_Bit_Synchronizer</a>
#(
parameter EXTRA_DEPTH = 0 // Must be 0 or greater
)
(
input wire receiving_clock,
input wire bit_in,
output reg bit_out
);
</pre>
<p>The minimum valid synchronizer depth is 2. Add more stages if the design
requires it. This usually happens near the highest operating frequencies.
Consult your device datasheets.</p>
<pre>
localparam DEPTH = 2 + EXTRA_DEPTH;
</pre>
<p>For Vivado, we must specify that the synchronizer registers should be
placed close together (see: UG912), and to show up as part of MTBF reports.</p>
<p>For Quartus, specify that these register must not be optimized (e.g. moved
into the input register of a DSP or BRAM) and to mark them as composing
a synchronizer (and so be placed close together).</p>
<p>In both cases, we also specify that the registers must not be placed in I/O
register locations.</p>
<pre>
// Vivado
(* IOB = "false" *)
(* ASYNC_REG = "TRUE" *)
// Quartus
(* useioff = 0 *)
(* PRESERVE *)
(* altera_attribute = "-name SYNCHRONIZER_IDENTIFICATION \"FORCED IF ASYNCHRONOUS\"" *)
reg sync_reg [DEPTH-1:0];
integer i;
initial begin
for(i=0; i < DEPTH; i=i+1) begin
sync_reg [i] = 1'b0;
end
end
</pre>
<p>Pass the bit through DEPTH registers into the receiving clock domain.
Peel out the first iteration to avoid a -1 index.</p>
<pre>
always @(posedge receiving_clock) begin
sync_reg [0] <= bit_in;
for(i = 1; i < DEPTH; i = i+1) begin: cdc_stages
sync_reg [i] <= sync_reg [i-1];
end
end
always @(*) begin
bit_out = sync_reg [DEPTH-1];
end
endmodule
</pre>
<hr>
<p><a href="./index.html">Back to FPGA Design Elements</a>
<center><a href="https://fpgacpu.ca/">fpgacpu.ca</a></center>
</body>
</html>