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