aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/top/n3xx/dboards/rh/db_ifc/RadioClocking.vhd
blob: 69a15d49ab2576d5e414e3c27977a8258bc51b6d (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
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
-------------------------------------------------------------------------------
--
-- File: RadioClocking.vhd
-- Author: Daniel Jepson
-- Original Project: N310
-- Date: 22 February 2016
--
-------------------------------------------------------------------------------
-- Copyright 2016-2018 Ettus Research, A National Instruments Company
-- SPDX-License-Identifier: LGPL-3.0
-------------------------------------------------------------------------------
--
-- Purpose:
--
-- Instantiates a MMCM to produce 1x, 2x, and 3x versions of the Radio Clock
-- coming from the FPGA input pin. Handles all the buffering for the input clock.
-- Additionally allows the clocks to be turned on and off, and phase shifted.
--
-- NOTE: This module hard-codes the MMCM settings for a SPECIFIC clock rate!
--
-------------------------------------------------------------------------------

library ieee;
  use ieee.std_logic_1164.all;

library unisim;
  use unisim.vcomponents.all;


entity RadioClocking is
  port (
    -- Async reset. Can be tied low if desired.
    aReset                 : in  boolean;
    -- Sync reset... used in the same places as the async one.
    bReset                 : in  boolean;

    -- Should be a always-on clock
    BusClk                 : in  std_logic;

    -- Sync reset to the RadioClkMmcm.
    bRadioClkMmcmReset     : in  std_logic;

    -- Locked indication from the RadioClkMmcm in BusClk and aReset domains.
    bRadioClksValid        : out std_logic;

    bRadioClk1xEnabled     : in  std_logic;
    bRadioClk2xEnabled     : in  std_logic;
    bRadioClk3xEnabled     : in  std_logic;

    -- Phase shift interface for the RadioClkMmcm. PsClk must be <= 200 MHz.
    pPsInc                 : in  std_logic;
    pPsEn                  : in  std_logic;
    PsClk                  : in  std_logic;
    pPsDone                : out std_logic;

    -- Straight from pins. Buffer included in here.
    FpgaClk_n              : in  std_logic;
    FpgaClk_p              : in  std_logic;

    RadioClk1x             : out std_logic;
    RadioClk2x             : out std_logic;
    RadioClk3x             : out std_logic

  );
end RadioClocking;


architecture rtl of RadioClocking is

  --vhook_sigstart
  signal RadioClk1xLcl: std_logic;
  signal RadioClk1xPll: std_logic;
  signal RadioClk2xLcl: std_logic;
  signal RadioClk2xPll: std_logic;
  signal RadioClk3xLcl: std_logic;
  signal RadioClk3xPll: std_logic;
  --vhook_sigend

  signal RadioClkMmcmFeedbackIn,
         RadioClkMmcmFeedbackOut,
         FpgaClkSE,
         aRadioClkMmcmLocked : std_logic;

  signal bRadioClkMmcmLocked_ms,
         bRadioClkMmcmLocked,
         bEnableRadioClkBufgOutputs,
         bEnableRadioClk1xBufgOutput,
         bEnableRadioClk2xBufgOutput,
         bEnableRadioClk3xBufgOutput : std_logic := '0';

  signal aRadioClkMmcmResetInternal  : std_logic := '1';

  attribute ASYNC_REG : string;
  attribute ASYNC_REG of bRadioClkMmcmLocked_ms : signal is "true";
  attribute ASYNC_REG of bRadioClkMmcmLocked    : signal is "true";

begin

  -- Radio Clock Buffering : ------------------------------------------------------------
  --
  -- ------------------------------------------------------------------------------------
  --vhook_i IBUFDS FpgaClkIbufg hidegeneric=true
  --vhook_a I  FpgaClk_p
  --vhook_a IB FpgaClk_n
  --vhook_a O  FpgaClkSE
  FpgaClkIbufg: IBUFDS
    port map (
      O  => FpgaClkSE,  --out std_ulogic
      I  => FpgaClk_p,  --in  std_ulogic
      IB => FpgaClk_n); --in  std_ulogic
 

  ResetDelay : process(aReset, BusClk)
  begin
    if aReset then
      aRadioClkMmcmResetInternal   <= '1';
    elsif rising_edge(BusClk) then
      if bReset then
        aRadioClkMmcmResetInternal   <= '1';
      else
        -- Delay by 1 to allow the BUFGs to turn off before the MMCM is reset.
        aRadioClkMmcmResetInternal <= bRadioClkMmcmReset;
      end if;
    end if;
  end process ResetDelay;


  RadioClkMmcm: MMCME2_ADV
    generic map(
      COMPENSATION         => "ZHOLD",
      BANDWIDTH            => "OPTIMIZED",
      CLKFBOUT_MULT_F      => 4.000,    -- Feedback
      CLKOUT0_DIVIDE_F     => 4.000,    -- Data Clock 1x, RadioClk1xPll
      CLKOUT1_DIVIDE       => 2,        -- Data Clock 2x, RadioClk2xPll
      CLKOUT2_DIVIDE       => 2,        -- Data Clock 3x, RadioClk3xPll
      CLKOUT3_DIVIDE       => 1,        -- unused
      CLKOUT4_DIVIDE       => 1,        -- unused
      CLKOUT5_DIVIDE       => 1,        -- unused
      CLKOUT6_DIVIDE       => 1,        -- unused
      CLKFBOUT_PHASE       => 0.000,    -- Feedback
      CLKOUT0_PHASE        => 0.000,    -- Data Clock 1x
      CLKOUT1_PHASE        => 0.000,    -- Data Clock 2x
      CLKOUT2_PHASE        => 0.000,    -- Data Clock 3x
      CLKOUT3_PHASE        => 0.000,    -- unused
      CLKOUT4_PHASE        => 0.000,    -- unused
      CLKOUT5_PHASE        => 0.000,    -- unused
      CLKOUT6_PHASE        => 0.000,    -- unused
      CLKOUT0_DUTY_CYCLE   => 0.500,
      CLKOUT1_DUTY_CYCLE   => 0.500,
      CLKOUT2_DUTY_CYCLE   => 0.500,
      CLKOUT3_DUTY_CYCLE   => 0.500,
      CLKOUT4_DUTY_CYCLE   => 0.500,
      CLKOUT5_DUTY_CYCLE   => 0.500,
      CLKOUT6_DUTY_CYCLE   => 0.500,
      DIVCLK_DIVIDE        => 1,
      REF_JITTER1          => 0.010,
      CLKIN1_PERIOD        => 4.069,    -- 245.76 MHz max
      CLKFBOUT_USE_FINE_PS => true,
      CLKOUT0_USE_FINE_PS  => false,
      CLKOUT1_USE_FINE_PS  => false,
      CLKOUT2_USE_FINE_PS  => false,
      CLKOUT3_USE_FINE_PS  => false,
      CLKOUT4_USE_FINE_PS  => false,
      CLKOUT5_USE_FINE_PS  => false,
      CLKOUT6_USE_FINE_PS  => false,
      STARTUP_WAIT         => false,
      CLKOUT4_CASCADE      => false)
    port map (
      CLKINSEL     => '1',
      CLKIN1       => FpgaClkSE,
      CLKIN2       => '0',
      CLKFBIN      => RadioClkMmcmFeedbackIn,
      RST          => aRadioClkMmcmResetInternal,
      PWRDWN       => '0',
      DADDR        => (others => '0'),
      DI           => (others => '0'),
      DWE          => '0',
      DEN          => '0',
      DCLK         => '0',
      DO           => open,
      DRDY         => open,
      PSINCDEC     => pPsInc,
      PSEN         => pPsEn,
      PSCLK        => PsClk,
      PSDONE       => pPsDone,
      CLKOUT0      => RadioClk1xPll,
      CLKOUT0B     => open,
      CLKOUT1      => RadioClk2xPll,
      CLKOUT1B     => open,
      CLKOUT2      => RadioClk3xPll,
      CLKOUT2B     => open,
      CLKOUT3      => open,
      CLKOUT3B     => open,
      CLKOUT4      => open,
      CLKOUT5      => open,
      CLKOUT6      => open,
      CLKFBOUT     => RadioClkMmcmFeedbackOut,
      CLKFBOUTB    => open,
      LOCKED       => aRadioClkMmcmLocked,
      CLKINSTOPPED => open,
      CLKFBSTOPPED => open);

  RadioClkMmcmFeedbackBufg: BUFG
    port map (
      I => RadioClkMmcmFeedbackOut,
      O => RadioClkMmcmFeedbackIn
    );


  -- Only enable the WRAPBUFGs when the MMCM is locked. If the MMCM is ever placed in
  -- reset, we turn off the clocks one cycle before the asynchronous version
  -- (aRadioClkMmcmResetInternal) reaches the MMCM inputs in order to prevent
  -- output glitches.
  CombineEnablesForBuffers : process(aReset, BusClk)
  begin
    if aReset then
      bRadioClkMmcmLocked_ms <= '0';
      bRadioClkMmcmLocked    <= '0';
      bEnableRadioClk1xBufgOutput <= '0';
      bEnableRadioClk2xBufgOutput <= '0';
      bEnableRadioClk3xBufgOutput <= '0';
      bEnableRadioClkBufgOutputs  <= '0';
    elsif rising_edge(BusClk) then
      if bReset then
        bRadioClkMmcmLocked_ms <= '0';
        bRadioClkMmcmLocked    <= '0';
        bEnableRadioClk1xBufgOutput <= '0';
        bEnableRadioClk2xBufgOutput <= '0';
        bEnableRadioClk3xBufgOutput <= '0';
        bEnableRadioClkBufgOutputs  <= '0';
      else
        bRadioClkMmcmLocked_ms <= aRadioClkMmcmLocked;
        bRadioClkMmcmLocked    <= bRadioClkMmcmLocked_ms;

        bEnableRadioClkBufgOutputs <= bRadioClkMmcmLocked and
                                      not bRadioClkMmcmReset;
        bEnableRadioClk1xBufgOutput <= bRadioClk1xEnabled and bEnableRadioClkBufgOutputs;
        bEnableRadioClk2xBufgOutput <= bRadioClk2xEnabled and bEnableRadioClkBufgOutputs;
        bEnableRadioClk3xBufgOutput <= bRadioClk3xEnabled and bEnableRadioClkBufgOutputs;
      end if;
    end if;
  end process CombineEnablesForBuffers;

  bRadioClksValid <= bEnableRadioClkBufgOutputs;

  --vhook_e WrapBufg         RadioClk1xBuf
  --vhook_a kEnableByDefault false
  --vhook_a kIgnore          false
  --vhook_a kEnableIsAsync   true
  --vhook_a ClkIn            RadioClk1xPll
  --vhook_a aCe              bEnableRadioClk1xBufgOutput
  --vhook_a ClkOut           RadioClk1xLcl
  RadioClk1xBuf: entity work.WrapBufg (rtl)
    generic map (
      kEnableByDefault => false,  --boolean:=false
      kIgnore          => false,  --boolean:=false
      kEnableIsAsync   => true)   --boolean:=false
    port map (
      ClkIn  => RadioClk1xPll,                --in  std_logic
      aCe    => bEnableRadioClk1xBufgOutput,  --in  std_logic
      ClkOut => RadioClk1xLcl);               --out std_logic

  --vhook_e WrapBufg         RadioClk2xBuf
  --vhook_a kEnableByDefault false
  --vhook_a kIgnore          false
  --vhook_a kEnableIsAsync   true
  --vhook_a ClkIn            RadioClk2xPll
  --vhook_a aCe              bEnableRadioClk2xBufgOutput
  --vhook_a ClkOut           RadioClk2xLcl
  RadioClk2xBuf: entity work.WrapBufg (rtl)
    generic map (
      kEnableByDefault => false,  --boolean:=false
      kIgnore          => false,  --boolean:=false
      kEnableIsAsync   => true)   --boolean:=false
    port map (
      ClkIn  => RadioClk2xPll,                --in  std_logic
      aCe    => bEnableRadioClk2xBufgOutput,  --in  std_logic
      ClkOut => RadioClk2xLcl);               --out std_logic

  --vhook_e WrapBufg         RadioClk3xBuf
  --vhook_a kEnableByDefault false
  --vhook_a kIgnore          false
  --vhook_a kEnableIsAsync   true
  --vhook_a ClkIn            RadioClk3xPll
  --vhook_a aCe              bEnableRadioClk3xBufgOutput
  --vhook_a ClkOut           RadioClk3xLcl
  RadioClk3xBuf: entity work.WrapBufg (rtl)
    generic map (
      kEnableByDefault => false,  --boolean:=false
      kIgnore          => false,  --boolean:=false
      kEnableIsAsync   => true)   --boolean:=false
    port map (
      ClkIn  => RadioClk3xPll,                --in  std_logic
      aCe    => bEnableRadioClk3xBufgOutput,  --in  std_logic
      ClkOut => RadioClk3xLcl);               --out std_logic


  -- Assign outputs from locals.
  RadioClk1x   <= RadioClk1xLcl;
  RadioClk2x   <= RadioClk2xLcl;
  RadioClk3x   <= RadioClk3xLcl;



end rtl;