1/////////////////////////////////////////////////////////////////////
2//
3// Copyright 2017 Ettus Research, A National Instruments Company
4// SPDX-License-Identifier: LGPL-3.0-or-later
5//
6// Module: n3xx_clocking.v
7//
8// Purpose:
9//
10// First, instantiate clock input buffers on all clocks to provide termination
11// for the PCB traces. This file also includes the MMCM for generating meas_clk at
12// specific rates and a global buffer for the reference clock to be able to use it
13// directly within and outside of this module.
14//
15// Second, PPS inputs from the back panel (called external) and the GPSDO are captured by
16// the Reference Clock. Selection is performed amongst these and the internally-generated
17// options.
18//
19// NOTE: BUFGs are NOT instantiated on the following clocks, denoted by the _buf suffix:
20//   wr_refclk_buf, netclk_buf, gige_refclk_buf, xgige_refclk_buf
21//
22//////////////////////////////////////////////////////////////////////
23
24module n3xx_clocking (
25  // Input buffers for clocks
26  input  enable_ref_clk_async, // enables the ref_clk BUFG (driven async to ref_clk)
27  input  FPGA_REFCLK_P, FPGA_REFCLK_N,
28  output ref_clk,
29
30  input  WB_20MHz_P, WB_20MHz_N,
31  output wr_refclk_buf,
32
33  input  NETCLK_REF_P, NETCLK_REF_N,
34  output netclk_buf,
35
36  input  NETCLK_P, NETCLK_N,
37  output gige_refclk_buf,
38
39  input  MGT156MHZ_CLK1_P, MGT156MHZ_CLK1_N,
40  output xgige_refclk_buf,
41
42  // Measurement Clock Generation
43  input  misc_clks_ref,
44  output meas_clk,
45  output ddr3_dma_clk,
46  input  misc_clks_reset,
47  output misc_clks_locked,
48
49  // PPS Capture & Selection
50  input       ext_pps_from_pin,
51  input       gps_pps_from_pin,
52  input [3:0] pps_select,
53  output reg  pps_refclk
54  );
55
56  // Clock Buffering and Generation : ///////////////////////////////////////////////////
57  //
58  // Manually instantiate input buffers on all clocks, and a global buffer on the
59  // Reference Clock for use in the rest of the design. All other clocks must have
60  // global buffers other places, since the declarations here are for SI purposes.
61  //
62  ///////////////////////////////////////////////////////////////////////////////////////
63
64  wire ref_clk_buf;
65
66  // FPGA Reference Clock Buffering
67  //
68  // Only require an IBUF and BUFG here, since an MMCM is (thankfully) not needed
69  // to meet timing with the PPS signal.
70  IBUFGDS ref_clk_ibuf (
71    .O(ref_clk_buf),
72    .I(FPGA_REFCLK_P),
73    .IB(FPGA_REFCLK_N)
74  );
75
76  // BUFG ref_clk_bufg (
77    // .I(ref_clk_buf),
78    // .O(ref_clk)
79  // );
80  WrapBufg #(
81     .kEnableIsAsync(1'b1)
82  ) ref_clk_bufg (
83     .ClkIn(ref_clk_buf),
84     .aCe(enable_ref_clk_async),
85     .ClkOut(ref_clk)
86  );
87
88  // Buffers for SI Purposes
89  //
90  // Instantiate buffers on each of these differential clock inputs with DONT_TOUCH
91  // attributes in order to preserve the internal termination regardless of whether
92  // these clocks are used in the design.  The lack of termination would place the
93  // voltage swings for these pins outside the acceptable range for the FPGA inputs.
94  (* dont_touch = "true" *) IBUFGDS wr_refclk_ibuf (
95    .I (WB_20MHz_P),
96    .IB(WB_20MHz_N),
97    .O (wr_refclk_buf)
98  );
99
100  (* dont_touch = "true" *) IBUFGDS netclk_ref_ibuf (
101    .I (NETCLK_REF_P),
102    .IB(NETCLK_REF_N),
103    .O (netclk_buf)
104  );
105
106  // Same deal for the MGT reference clock buffers.
107  (* dont_touch = "true" *) IBUFDS_GTE2 gige_refclk_ibuf (
108    .ODIV2(),
109    .CEB  (1'b0),
110    .I (NETCLK_P),
111    .IB(NETCLK_N),
112    .O (gige_refclk_buf)
113  );
114
115  (* dont_touch = "true" *) IBUFDS_GTE2 ten_gige_refclk_ibuf (
116    .ODIV2(),
117    .CEB  (1'b0),
118    .I (MGT156MHZ_CLK1_P),
119    .IB(MGT156MHZ_CLK1_N),
120    .O (xgige_refclk_buf)
121  );
122
123  // Measurement Clock MMCM Instantiation
124  //
125  // This must be an MMCM to hit the weird rates we need for meas_clk. It takes the
126  // 166.6667 MHz clock from the PS and provides the correct meas_clk rate for the TDC.
127  // BUFG is embedded in the MMCM files.
128  //----------------------------------------------------------------------------
129  //  Output     Output      Phase    Duty Cycle   Pk-to-Pk     Phase
130  //   Clock     Freq (MHz)  (degrees)    (%)     Jitter (ps)  Error (ps)
131  //----------------------------------------------------------------------------
132  // CLK_OUT1___170.543______0.000______50.0______105.052_____94.905 (meas_clk)
133  // CLK_OUT2___305.556______0.000______50.0_______93.867_____94.905 (ddr3_dma_clk)
134  //
135  //----------------------------------------------------------------------------
136  // Input Clock   Freq (MHz)    Input Jitter (UI)
137  //----------------------------------------------------------------------------
138  // __primary________166.666667____________0.010
139
140  misc_clock_gen misc_clock_gen_i (
141    .clk_in       (misc_clks_ref),
142    .meas_clk     (meas_clk),
143    .ddr3_dma_clk (ddr3_dma_clk),
144    .reset        (misc_clks_reset),
145    .locked       (misc_clks_locked)
146  );
147
148
149  // PPS Capture and Generation : ///////////////////////////////////////////////////////
150  //
151  // The following shows the support matrix for PPS with respect to the
152  // reference clock source and rate.
153  //               _______________________________
154  //  ____________|              PPS              |
155  // |   Clocks   | External | FPGA  | GPSDO | WR |
156  // |--------------------------------------------|
157  // |External 10 |    x     |  x    |       |    |
158  // |Internal 25 |          |  x    |       | x  |
159  // |GPSDO    20 |          |       |   x   |    |
160  // |--------------------------------------------|
161  //
162  ///////////////////////////////////////////////////////////////////////////////////////
163
164  wire pps_ext_refclk;
165  wire pps_gps_refclk;
166  wire [3:0] pps_select_refclk;
167
168  // Generate two internal PPS signals, each with a 25% duty cycle, based on
169  // 10 MHz and 25 MHz Reference Clock rates. Only one will be used at a time.
170  wire int_pps_10mhz_refclk;
171  pps_generator #(
172     .CLK_FREQ(32'd10_000_000), .DUTY_CYCLE(25)
173  ) pps_gen_10 (
174     .clk(ref_clk), .reset(1'b0), .pps(int_pps_10mhz_refclk)
175  );
176  wire int_pps_25mhz_refclk;
177  pps_generator #(
178     .CLK_FREQ(32'd25_000_000), .DUTY_CYCLE(25)
179  ) pps_gen_25 (
180     .clk(ref_clk), .reset(1'b0), .pps(int_pps_25mhz_refclk)
181  );
182
183  // Capture the external PPSs with a FF before sending them to the mux. To be safe,
184  // we double-synchronize the external signals. If we meet timing (which we should)
185  // then this is a two-cycle delay. If we don't meet timing, then it's 1-2 cycles
186  // and our system timing is thrown off--but at least our downstream logic doesn't
187  // go metastable!
188  synchronizer #(
189    .FALSE_PATH_TO_IN(0)
190  ) ext_pps_dsync (
191    .clk(ref_clk), .rst(1'b0), .in(ext_pps_from_pin), .out(pps_ext_refclk)
192  );
193  // Same deal with the GPSDO PPS input. Double-sync, then use it.
194  synchronizer #(
195    .FALSE_PATH_TO_IN(0)
196  ) gps_pps_dsync (
197    .clk(ref_clk), .rst(1'b0), .in(gps_pps_from_pin), .out(pps_gps_refclk)
198  );
199
200  // Synchronize the select bits over to the reference clock as well. Note that this is
201  // a vector, so we could have some non-one-hot values creep through when changing.
202  // See the note below as to why this is safe.
203  synchronizer #(
204    .FALSE_PATH_TO_IN(1),
205    .WIDTH(4)
206  ) pps_select_dsync (
207    .clk(ref_clk), .rst(1'b0), .in(pps_select), .out(pps_select_refclk)
208  );
209
210  // Bit locations for the pps_select vector.
211  localparam BIT_PPS_SEL_INT_10 = 0;
212  localparam BIT_PPS_SEL_INT_25 = 1;
213  localparam BIT_PPS_SEL_EXT    = 2;
214  localparam BIT_PPS_SEL_GPSDO  = 3;
215
216  // PPS MUX - selects internal or external PPS.
217  always @(posedge ref_clk) begin
218
219    // Encoding is one-hot on these bits. It is possible when the vector is being double-
220    // synchronized to the reference clock domain that there could be multiple bits
221    // asserted simultaneously. This is not problematic because the order of operations
222    // in the following selection mux should take over and only one PPS should win.
223    // This could result in glitches, but that is expected during ANY PPS switchover
224    // since the switch is performed asynchronously to the PPS signal.
225    if (pps_select_refclk[BIT_PPS_SEL_INT_10])
226      pps_refclk <= int_pps_10mhz_refclk;
227    else if (pps_select_refclk[BIT_PPS_SEL_INT_25])
228      pps_refclk <= int_pps_25mhz_refclk;
229    else if (pps_select_refclk[BIT_PPS_SEL_EXT])
230      pps_refclk <= pps_ext_refclk;
231    else if (pps_select_refclk[BIT_PPS_SEL_GPSDO])
232      pps_refclk <= pps_gps_refclk;
233    else
234      pps_refclk <= pps_ext_refclk; // Compatibility with old SW stacks, pps_select_refclk = 0 = external
235
236  end
237
238endmodule
239