aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/control/synchronizer.v
blob: 6ac16012d9f596808876fc32839c5b22f16949ba (plain)
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
//
// Copyright 2021 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: synchronizer.v
//
// Description:
//
//   This is a double-synchronizer module. However, it can can implement a
//   synchronizer of any depth (double, triple, etc.) and width.
//
//   A double synchronizer is typically used to cross a single-bit glitch-free
//   signal from one clock domain to another.
//
//   *WARNING*: The input signal must be glitch-free. In other words, it should
//              be driven by a register and NOT combinational logic. Otherwise
//              you could capture a glitch instead of the intended signal.
//
//   *WARNING*: When WIDTH is not 1, the multiple bits are not guaranteed to be
//              coherent. In other words, they can arrive on the output at
//              different times. This module should not usually be used to
//              cross a multi-bit signal. Consider using the handshake module
//              instead.
//
//   When crossing between unrelated clock domains, we typically don't want the
//   timing analyzer to consider the path between clock domains. To make
//   writing this constraint easier, the FALSE_PATH_TO_IN parameter controls
//   the name of the synchronizer_impl instance. The following XDC constraint
//   is used to ignore all instances of this false path.
//
//     set_false_path -to [get_pins -hierarchical -filter \
//       {NAME =~ */synchronizer_false_path/stages[0].value_reg[0][*]/D}]
//
// Parameters:
//
//   WIDTH            : Width of the synchronizer (1 by default).
//   STAGES           : Number of synchronizer stages (2 by default, for a
//                      standard double-synchronizer).
//   INITIAL_VAL      : Initial value of the output register (0 by default).
//   FALSE_PATH_TO_IN : Set to 1 if the input should be considered a false path
//                      and ignored by the timing analyzer. Set to 0 to let the
//                      tool analyze this path.
//

module synchronizer #(
   parameter WIDTH            = 1,
   parameter STAGES           = 2,
   parameter INITIAL_VAL      = 0,
   parameter FALSE_PATH_TO_IN = 1
)(
   input              clk,
   input              rst,
   input  [WIDTH-1:0] in,
   output [WIDTH-1:0] out
);

   generate if (FALSE_PATH_TO_IN == 1) begin
      synchronizer_impl #(
        .WIDTH(WIDTH), .STAGES(STAGES), .INITIAL_VAL(INITIAL_VAL)
      ) synchronizer_false_path (
         .clk(clk), .rst(rst), .in(in), .out(out)
      );
   end else begin
      synchronizer_impl #(
        .WIDTH(WIDTH), .STAGES(STAGES), .INITIAL_VAL(INITIAL_VAL)
      ) synchronizer_constrained (
         .clk(clk), .rst(rst), .in(in), .out(out)
      );
   end endgenerate

endmodule   //synchronizer