mmcme2_drp.v 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849
  1. //-------------------------------------------------------------------------------------------
  2. // ____ ____
  3. // / /\/ /
  4. // /___/ \ /
  5. // \ \ \/ � Copyright 2019 Xilinx, Inc. All rights reserved.
  6. // \ \ This file contains confidential and proprietary information of Xilinx, Inc.
  7. // / / and is protected under U.S. and international copyright and other
  8. // /___/ /\ intellectual property laws.
  9. // \ \ / \
  10. // \___\/\___\
  11. //
  12. //-------------------------------------------------------------------------------------------
  13. // Device: 7_Series
  14. // Author: Tatsukawa, Kruger, Ribbing, Defossez
  15. // Entity Name: mmcme2_drp
  16. // Purpose: This calls the DRP register calculation functions and
  17. // provides a state machine to perform MMCM reconfiguration
  18. // based on the calculated values stored in a initialized
  19. // ROM.
  20. // 7-Series MMCM is called: MMCME2
  21. // Ultrascale MMCM is called: MMCME3
  22. // UltrascalePlus MMCM is called: MMCME4
  23. // MMCME3 attributes
  24. // CLKINx_PERIOD: 0.968 to 100.000 (x = 1 or 2)
  25. // REF_JITTERx: 0.001 to 0.999 (x = 1 or 2)
  26. // BANDWIDTH: LOW, HIGH, OPTIMIZED and POSTCRC
  27. // COMPENSATION: AUTO, ZHOLD, EXTERNAL, INTERNAL and BUF_IN
  28. // DIVCLK_DIVIDE: 1 to 106
  29. // CLKFBOUT_MULT_F: 2 to 64
  30. // CLKFBOUT_PHASE: -360 to 360
  31. // CLKOUTn_DIVIDE: 1 to 128 (n = 0 to 6)
  32. // CLKOUTn_PHASE: -360 to 360 (n = 0 to 6)
  33. // CLKOUTn_DUTY_CYCLE: 0.01 to 0.99 (n = 0 to 6)
  34. //
  35. // Tools: Vivado_2019.1 or newer
  36. // Limitations: None
  37. //
  38. // Vendor: Xilinx Inc.
  39. // Version: 1.40
  40. // Filename: mmcme3_drp.v
  41. // Date Created: 22-Oct-2014
  42. // Date Last Modified: 25-Jun-2019
  43. //-------------------------------------------------------------------------------------------
  44. // Disclaimer:
  45. // This disclaimer is not a license and does not grant any rights to the materials
  46. // distributed herewith. Except as otherwise provided in a valid license issued to you
  47. // by Xilinx, and to the maximum extent permitted by applicable law: (1) THESE MATERIALS
  48. // ARE MADE AVAILABLE "AS IS" AND WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL
  49. // WARRANTIES AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED
  50. // TO WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR
  51. // PURPOSE; and (2) Xilinx shall not be liable (whether in contract or tort, including
  52. // negligence, or under any other theory of liability) for any loss or damage of any
  53. // kind or nature related to, arising under or in connection with these materials,
  54. // including for any direct, or any indirect, special, incidental, or consequential
  55. // loss or damage (including loss of data, profits, goodwill, or any type of loss or
  56. // damage suffered as a result of any action brought by a third party) even if such
  57. // damage or loss was reasonably foreseeable or Xilinx had been advised of the
  58. // possibility of the same.
  59. //
  60. // CRITICAL APPLICATIONS
  61. // Xilinx products are not designed or intended to be fail-safe, or for use in any
  62. // application requiring fail-safe performance, such as life-support or safety devices
  63. // or systems, Class III medical devices, nuclear facilities, applications related to
  64. // the deployment of airbags, or any other applications that could lead to death,
  65. // personal injury, or severe property or environmental damage (individually and
  66. // collectively, "Critical Applications"). Customer assumes the sole risk and
  67. // liability of any use of Xilinx products in Critical Applications, subject only to
  68. // applicable laws and regulations governing limitations on product liability.
  69. //
  70. // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE AT ALL TIMES.
  71. //
  72. // Contact: e-mail hotline@xilinx.com phone + 1 800 255 7778
  73. //-------------------------------------------------------------------------------------------
  74. // Revision History:
  75. // Rev: 13-Jan-2011 - Tatsukawa
  76. // Updated ROM[18,41] LOCKED bitmask to 16'HFC00
  77. // Rev: 30-May-2013 - Tatsukawa
  78. // Adding Fractional support for CLKFBOUT_MULT_F, CLKOUT0_DIVIDE_F
  79. // Rev: 30-Apr-2014 - Tatsukawa
  80. // For fractional multiply changed order to enable fractional
  81. // before the multiply is applied to prevent false VCO DRCs
  82. // (e.g. DADDR 7'h15 must be set before updating 7'h14)
  83. // Rev: 24-Oct-2014 - Ribbing
  84. // Parameters have been added to clarify Reg1/Reg2/Shared registers
  85. // Rev: 08-Jun-2015 - Kruger
  86. // WAIT_LOCK update
  87. // Rev: 02-May-2016 - Kruger
  88. // Reordering FRAC_EN bits DADDR(7'h09, 7'h15)
  89. // Registers before frac settings (7'h08, 7'h14)
  90. // Rev: 19-Sep-2018 - Defossez
  91. // Updated comments of BANDWIDTH.
  92. // Corrected some typos.
  93. // Rev: 25-Jun-2019 - Defossez
  94. // Adding registering possibility for LOCKE signal.
  95. //-------------------------------------------------------------------------------------------
  96. //
  97. `timescale 1ps/1ps
  98. //
  99. module mmcme2_drp
  100. #(
  101. // Register the LOCKED signal with teh MMCME3_ADV input clock.
  102. // The LOCKED_IN (LOCKED from the MMCME3_ADV) is fed into a register and then
  103. // passed the LOCKED_OUT when REGISTER_LOCKED is set to "Reg" or when set to
  104. // "NoReg" LOCKED_IN is just passed on to LOCKED_OUT without being registered.
  105. parameter REGISTER_LOCKED = "Reg",
  106. // Use the registered LOCKED signal from the MMCME3 also for the DRP state machine.
  107. parameter USE_REG_LOCKED = "No",
  108. // Possible/allowed combinations of above two parameters:
  109. // | REGISTER_LOCKED | USE_REG_LOCKED | |
  110. // |-----------------|----------------|--------------------------------------------|
  111. // | "NoReg" | "No" | LOCKED is just passed through mmcme3_drp |
  112. // | | | and is used as is with the state machine |
  113. // | "NoReg" | "Yes" | NOT ALLOWED |
  114. // | "Reg" | "No" | LOCKED is registered but the unregistered |
  115. // | | | version is used for the state machine. |
  116. // | "Reg" | "Yes" | LOCKED is registered and the registered |
  117. // | | | version is also used by the state machine. |
  118. //
  119. //***********************************************************************
  120. // State 1 Parameters - These are for the first reconfiguration state.
  121. //***********************************************************************
  122. //
  123. // These parameters have an effect on the feedback path. A change on
  124. // these parameters will effect all of the clock outputs.
  125. //
  126. // The parameters are composed of:
  127. // _MULT: This can be from 2 to 64. It has an effect on the VCO
  128. // frequency which consequently, effects all of the clock
  129. // outputs.
  130. // _PHASE: This is the phase multiplied by 1000. For example if
  131. // a phase of 24.567 deg was desired the input value would be
  132. // 24567. The range for the phase is from -360000 to 360000.
  133. // _FRAC: This can be from 0 to 875. This represents the fractional
  134. // divide multiplied by 1000.
  135. // M = _MULT + _FRAC / 1000
  136. // e.g. M=8.125
  137. // _MULT = 8
  138. // _FRAC = 125
  139. // _FRAC_EN: This indicates fractional divide has been enabled. If 1
  140. // then the fractional divide algorithm will be used to calculate
  141. // register settings. If 0 then default calculation to be used.
  142. parameter S1_CLKFBOUT_MULT = 5,
  143. parameter S1_CLKFBOUT_PHASE = 0,
  144. parameter S1_CLKFBOUT_FRAC = 125,
  145. parameter S1_CLKFBOUT_FRAC_EN = 1,
  146. //
  147. // The bandwidth parameter effects the phase error and the jitter filter
  148. // capability of the MMCM. For more information on this parameter see the
  149. // Device user guide.
  150. // Possible values are: "LOW", "LOW_SS", "HIGH" and "OPTIMIZED"
  151. parameter S1_BANDWIDTH = "LOW",
  152. //
  153. // The divclk parameter allows the input clock to be divided before it
  154. // reaches the phase and frequency comparator. This can be set between
  155. // 1 and 128.
  156. parameter S1_DIVCLK_DIVIDE = 1,
  157. // The following parameters describe the configuration that each clock
  158. // output should have once the reconfiguration for state one has
  159. // completed.
  160. //
  161. // The parameters are composed of:
  162. // _DIVIDE: This can be from 1 to 128
  163. // _PHASE: This is the phase multiplied by 1000. For example if
  164. // a phase of 24.567 deg was desired the input value would be
  165. // 24567. The range for the phase is from -360000 to 360000.
  166. // _DUTY: This is the duty cycle multiplied by 100,000. For example if
  167. // a duty cycle of .24567 was desired the input would be
  168. // 24567.
  169. //
  170. parameter S1_CLKOUT0_DIVIDE = 1,
  171. parameter S1_CLKOUT0_PHASE = 0,
  172. parameter S1_CLKOUT0_DUTY = 50000,
  173. parameter S1_CLKOUT0_FRAC = 125,
  174. parameter S1_CLKOUT0_FRAC_EN = 1,
  175. //
  176. parameter S1_CLKOUT1_DIVIDE = 1,
  177. parameter S1_CLKOUT1_PHASE = 0,
  178. parameter S1_CLKOUT1_DUTY = 50000,
  179. //
  180. parameter S1_CLKOUT2_DIVIDE = 1,
  181. parameter S1_CLKOUT2_PHASE = 0,
  182. parameter S1_CLKOUT2_DUTY = 50000,
  183. //
  184. parameter S1_CLKOUT3_DIVIDE = 1,
  185. parameter S1_CLKOUT3_PHASE = 0,
  186. parameter S1_CLKOUT3_DUTY = 50000,
  187. //
  188. parameter S1_CLKOUT4_DIVIDE = 1,
  189. parameter S1_CLKOUT4_PHASE = 0,
  190. parameter S1_CLKOUT4_DUTY = 50000,
  191. //
  192. parameter S1_CLKOUT5_DIVIDE = 1,
  193. parameter S1_CLKOUT5_PHASE = 0,
  194. parameter S1_CLKOUT5_DUTY = 50000,
  195. //
  196. parameter S1_CLKOUT6_DIVIDE = 1,
  197. parameter S1_CLKOUT6_PHASE = 0,
  198. parameter S1_CLKOUT6_DUTY = 50000,
  199. //
  200. //***********************************************************************
  201. // State 2 Parameters - These are for the second reconfiguration state.
  202. //***********************************************************************
  203. //
  204. // These parameters have an effect on the feedback path. A change on
  205. // these parameters will effect all of the clock outputs.
  206. //
  207. // The parameters are composed of:
  208. // _MULT: This can be from 2 to 64. It has an effect on the VCO
  209. // frequency which consequently, effects all of the clock
  210. // outputs.
  211. // _PHASE: This is the phase multiplied by 1000. For example if
  212. // a phase of 24.567 deg was desired the input value would be
  213. // 24567. The range for the phase is from -360000 to 360000.
  214. // _FRAC: This can be from 0 to 875. This represents the fractional
  215. // divide multiplied by 1000.
  216. // M = _MULT + _FRAC / 1000
  217. // e.g. M=8.125
  218. // _MULT = 8
  219. // _FRAC = 125
  220. // _FRAC_EN: This indicates fractional divide has been enabled. If 1
  221. // then the fractional divide algorithm will be used to calculate
  222. // register settings. If 0 then default calculation to be used.
  223. parameter S2_CLKFBOUT_MULT = 1,
  224. parameter S2_CLKFBOUT_PHASE = 0,
  225. parameter S2_CLKFBOUT_FRAC = 125,
  226. parameter S2_CLKFBOUT_FRAC_EN = 1,
  227. //
  228. // The bandwidth parameter effects the phase error and the jitter filter
  229. // capability of the MMCM. For more information on this parameter see the
  230. // Device user guide.
  231. // Possible values are: "LOW", "LOW_SS", "HIGH" and "OPTIMIZED"
  232. parameter S2_BANDWIDTH = "LOW",
  233. //
  234. // The divclk parameter allows the input clock to be divided before it
  235. // reaches the phase and frequency comparator. This can be set between
  236. // 1 and 128.
  237. parameter S2_DIVCLK_DIVIDE = 1,
  238. //
  239. // The following parameters describe the configuration that each clock
  240. // output should have once the reconfiguration for state one has
  241. // completed.
  242. //
  243. // The parameters are composed of:
  244. // _DIVIDE: This can be from 1 to 128
  245. // _PHASE: This is the phase multiplied by 1000. For example if
  246. // a phase of 24.567 deg was desired the input value would be
  247. // 24567. The range for the phase is from -360000 to 360000
  248. // _DUTY: This is the duty cycle multiplied by 100,000. For example if
  249. // a duty cycle of .24567 was desired the input would be
  250. // 24567.
  251. //
  252. parameter S2_CLKOUT0_DIVIDE = 1,
  253. parameter S2_CLKOUT0_PHASE = 0,
  254. parameter S2_CLKOUT0_DUTY = 50000,
  255. parameter S2_CLKOUT0_FRAC = 125,
  256. parameter S2_CLKOUT0_FRAC_EN = 1,
  257. //
  258. parameter S2_CLKOUT1_DIVIDE = 2,
  259. parameter S2_CLKOUT1_PHASE = 0,
  260. parameter S2_CLKOUT1_DUTY = 50000,
  261. //
  262. parameter S2_CLKOUT2_DIVIDE = 3,
  263. parameter S2_CLKOUT2_PHASE = 0,
  264. parameter S2_CLKOUT2_DUTY = 50000,
  265. //
  266. parameter S2_CLKOUT3_DIVIDE = 4,
  267. parameter S2_CLKOUT3_PHASE = 0,
  268. parameter S2_CLKOUT3_DUTY = 50000,
  269. //
  270. parameter S2_CLKOUT4_DIVIDE = 5,
  271. parameter S2_CLKOUT4_PHASE = 0,
  272. parameter S2_CLKOUT4_DUTY = 50000,
  273. //
  274. parameter S2_CLKOUT5_DIVIDE = 5,
  275. parameter S2_CLKOUT5_PHASE = 0,
  276. parameter S2_CLKOUT5_DUTY = 50000,
  277. //
  278. parameter S2_CLKOUT6_DIVIDE = 5,
  279. parameter S2_CLKOUT6_PHASE = -90,
  280. parameter S2_CLKOUT6_DUTY = 50000
  281. ) (
  282. // These signals are controlled by user logic interface and are covered
  283. // in more detail within the XAPP.
  284. input SADDR,
  285. input SEN,
  286. input SCLK,
  287. input RST,
  288. output reg SRDY,
  289. //
  290. // These signals are to be connected to the MMCM_ADV by port name.
  291. // Their use matches the MMCM port description in the Device User Guide.
  292. input [15:0] DO,
  293. input DRDY,
  294. input LOCK_REG_CLK_IN,
  295. input LOCKED_IN,
  296. output reg DWE,
  297. output reg DEN,
  298. output reg [6:0] DADDR,
  299. output reg [15:0] DI,
  300. output DCLK,
  301. output reg RST_MMCM,
  302. output LOCKED_OUT
  303. );
  304. //----------------------------------------------------------------------------------------
  305. //
  306. wire IntLocked;
  307. wire IntRstMmcm;
  308. //
  309. // 100 ps delay for behavioral simulations
  310. localparam TCQ = 100;
  311. // Make sure the memory is implemented as distributed
  312. (* rom_style = "distributed" *)
  313. //
  314. // ROM of: 39 bit word 64 words deep
  315. reg [38:0] rom [63:0];
  316. reg [5:0] rom_addr;
  317. reg [38:0] rom_do;
  318. reg next_srdy;
  319. reg [5:0] next_rom_addr;
  320. reg [6:0] next_daddr;
  321. reg next_dwe;
  322. reg next_den;
  323. reg next_rst_mmcm;
  324. reg [15:0] next_di;
  325. //
  326. // Insert a register in LOCKED or not depending on the value given to the parameters
  327. // REGISTER_LOCKED. When REGISTER_LOCKED is set to "Reg" insert a register, when set
  328. // to "NoReg" don't insert a register but just pass the LOCKED signal from input to
  329. // output.
  330. // Use or not, under USE_REG_LOCKED parameter control, the registered version of the
  331. // LOCKED signal for the DRP state machine.
  332. // Possible/allowed combinations of the two LOCKED related parameters:
  333. //
  334. // | REGISTER_LOCKED | USE_REG_LOCKED | |
  335. // |-----------------|----------------|--------------------------------------------|
  336. // | "NoReg" | "No" | LOCKED is just passed through mmcme3_drp |
  337. // | | | and is used as is with the state machine |
  338. // | "NoReg" | "Yes" | NOT ALLOWED |
  339. // | "Reg" | "No" | LOCKED is registered but the unregistered |
  340. // | | | version is used for the state machine. |
  341. // | "Reg" | "Yes" | LOCKED is registered and the registered |
  342. // | | | version is also used by the state machine. |
  343. //
  344. generate
  345. if (REGISTER_LOCKED == "NoReg" && USE_REG_LOCKED == "No") begin
  346. assign LOCKED_OUT = LOCKED_IN;
  347. assign IntLocked = LOCKED_IN;
  348. end else if (REGISTER_LOCKED == "Reg" && USE_REG_LOCKED == "No") begin
  349. FDRE #(
  350. .INIT (0),
  351. .IS_C_INVERTED (0),
  352. .IS_D_INVERTED (0),
  353. .IS_R_INVERTED (0)
  354. ) mmcme3_drp_I_Fdrp (
  355. .D (LOCKED_IN),
  356. .CE (1'b1),
  357. .R (IntRstMmcm),
  358. .C (LOCK_REG_CLK_IN),
  359. .Q (LOCKED_OUT)
  360. );
  361. //
  362. assign IntLocked = LOCKED_IN;
  363. end else if (REGISTER_LOCKED == "Reg" && USE_REG_LOCKED == "Yes") begin
  364. FDRE #(
  365. .INIT (0),
  366. .IS_C_INVERTED (0),
  367. .IS_D_INVERTED (0),
  368. .IS_R_INVERTED (0)
  369. ) mmcme3_drp_I_Fdrp (
  370. .D (LOCKED_IN),
  371. .CE (1'b1),
  372. .R (IntRstMmcm),
  373. .C (LOCK_REG_CLK_IN),
  374. .Q (LOCKED_OUT)
  375. );
  376. //
  377. assign IntLocked = LOCKED_OUT;
  378. end
  379. endgenerate
  380. // Integer used to initialize remainder of unused ROM
  381. integer ii;
  382. // Pass SCLK to DCLK for the MMCM
  383. assign DCLK = SCLK;
  384. assign IntRstMmcm = RST_MMCM;
  385. // Include the MMCM reconfiguration functions. This contains the constant
  386. // functions that are used in the calculations below. This file is
  387. // required.
  388. `include "mmcme2_drp_func.h"
  389. //**************************************************************************
  390. // State 1 Calculations
  391. //**************************************************************************
  392. // Please see header for information.
  393. localparam [37:0] S1_CLKFBOUT =
  394. mmcm_count_calc(S1_CLKFBOUT_MULT, S1_CLKFBOUT_PHASE, 50000);
  395. localparam [37:0] S1_CLKFBOUT_FRAC_CALC =
  396. mmcm_frac_count_calc(S1_CLKFBOUT_MULT, S1_CLKFBOUT_PHASE, 50000, S1_CLKFBOUT_FRAC);
  397. localparam [9:0] S1_DIGITAL_FILT =
  398. mmcm_filter_lookup(S1_CLKFBOUT_MULT, S1_BANDWIDTH);
  399. localparam [39:0] S1_LOCK =
  400. mmcm_lock_lookup(S1_CLKFBOUT_MULT);
  401. localparam [37:0] S1_DIVCLK =
  402. mmcm_count_calc(S1_DIVCLK_DIVIDE, 0, 50000);
  403. localparam [37:0] S1_CLKOUT0 =
  404. mmcm_count_calc(S1_CLKOUT0_DIVIDE, S1_CLKOUT0_PHASE, S1_CLKOUT0_DUTY);
  405. localparam [15:0] S1_CLKOUT0_REG1 = S1_CLKOUT0[15:0]; //See log file for 16 bit reporting of the register
  406. localparam [15:0] S1_CLKOUT0_REG2 = S1_CLKOUT0[31:16]; //See log file for 16 bit reporting of the register
  407. localparam [37:0] S1_CLKOUT0_FRAC_CALC =
  408. mmcm_frac_count_calc(S1_CLKOUT0_DIVIDE, S1_CLKOUT0_PHASE, 50000, S1_CLKOUT0_FRAC);
  409. localparam [15:0] S1_CLKOUT0_FRAC_REG1 = S1_CLKOUT0_FRAC_CALC[15:0]; //See log file for 16 bit reporting of the register
  410. localparam [15:0] S1_CLKOUT0_FRAC_REG2 = S1_CLKOUT0_FRAC_CALC[31:16]; //See log file for 16 bit reporting of the register
  411. localparam [5:0] S1_CLKOUT0_FRAC_REGSHARED = S1_CLKOUT0_FRAC_CALC[37:32]; //See log file for 16 bit reporting of the register
  412. localparam [37:0] S1_CLKOUT1 =
  413. mmcm_count_calc(S1_CLKOUT1_DIVIDE, S1_CLKOUT1_PHASE, S1_CLKOUT1_DUTY);
  414. localparam [15:0] S1_CLKOUT1_REG1 = S1_CLKOUT1[15:0]; //See log file for 16 bit reporting of the register
  415. localparam [15:0] S1_CLKOUT1_REG2 = S1_CLKOUT1[31:16]; //See log file for 16 bit reporting of the register
  416. localparam [37:0] S1_CLKOUT2 =
  417. mmcm_count_calc(S1_CLKOUT2_DIVIDE, S1_CLKOUT2_PHASE, S1_CLKOUT2_DUTY);
  418. localparam [15:0] S1_CLKOUT2_REG1 = S1_CLKOUT2[15:0]; //See log file for 16 bit reporting of the register
  419. localparam [15:0] S1_CLKOUT2_REG2 = S1_CLKOUT2[31:16]; //See log file for 16 bit reporting of the register
  420. localparam [37:0] S1_CLKOUT3 =
  421. mmcm_count_calc(S1_CLKOUT3_DIVIDE, S1_CLKOUT3_PHASE, S1_CLKOUT3_DUTY);
  422. localparam [15:0] S1_CLKOUT3_REG1 = S1_CLKOUT3[15:0]; //See log file for 16 bit reporting of the register
  423. localparam [15:0] S1_CLKOUT3_REG2 = S1_CLKOUT3[31:16]; //See log file for 16 bit reporting of the register
  424. localparam [37:0] S1_CLKOUT4 =
  425. mmcm_count_calc(S1_CLKOUT4_DIVIDE, S1_CLKOUT4_PHASE, S1_CLKOUT4_DUTY);
  426. localparam [15:0] S1_CLKOUT4_REG1 = S1_CLKOUT4[15:0]; //See log file for 16 bit reporting of the register
  427. localparam [15:0] S1_CLKOUT4_REG2 = S1_CLKOUT4[31:16]; //See log file for 16 bit reporting of the register
  428. localparam [37:0] S1_CLKOUT5 =
  429. mmcm_count_calc(S1_CLKOUT5_DIVIDE, S1_CLKOUT5_PHASE, S1_CLKOUT5_DUTY);
  430. localparam [15:0] S1_CLKOUT5_REG1 = S1_CLKOUT5[15:0]; //See log file for 16 bit reporting of the register
  431. localparam [15:0] S1_CLKOUT5_REG2 = S1_CLKOUT5[31:16]; //See log file for 16 bit reporting of the register
  432. localparam [37:0] S1_CLKOUT6 =
  433. mmcm_count_calc(S1_CLKOUT6_DIVIDE, S1_CLKOUT6_PHASE, S1_CLKOUT6_DUTY);
  434. localparam [15:0] S1_CLKOUT6_REG1 = S1_CLKOUT6[15:0]; //See log file for 16 bit reporting of the register
  435. localparam [15:0] S1_CLKOUT6_REG2 = S1_CLKOUT6[31:16]; //See log file for 16 bit reporting of the register
  436. //**************************************************************************
  437. // State 2 Calculations
  438. //**************************************************************************
  439. localparam [37:0] S2_CLKFBOUT =
  440. mmcm_count_calc(S2_CLKFBOUT_MULT, S2_CLKFBOUT_PHASE, 50000);
  441. localparam [37:0] S2_CLKFBOUT_FRAC_CALC =
  442. mmcm_frac_count_calc(S2_CLKFBOUT_MULT, S2_CLKFBOUT_PHASE, 50000, S2_CLKFBOUT_FRAC);
  443. localparam [9:0] S2_DIGITAL_FILT =
  444. mmcm_filter_lookup(S2_CLKFBOUT_MULT, S2_BANDWIDTH);
  445. localparam [39:0] S2_LOCK =
  446. mmcm_lock_lookup(S2_CLKFBOUT_MULT);
  447. localparam [37:0] S2_DIVCLK =
  448. mmcm_count_calc(S2_DIVCLK_DIVIDE, 0, 50000);
  449. localparam [37:0] S2_CLKOUT0 =
  450. mmcm_count_calc(S2_CLKOUT0_DIVIDE, S2_CLKOUT0_PHASE, S2_CLKOUT0_DUTY);
  451. localparam [15:0] S2_CLKOUT0_REG1 = S2_CLKOUT0[15:0]; //See log file for 16 bit reporting of the register
  452. localparam [15:0] S2_CLKOUT0_REG2 = S2_CLKOUT0[31:16]; //See log file for 16 bit reporting of the register
  453. localparam [37:0] S2_CLKOUT0_FRAC_CALC =
  454. mmcm_frac_count_calc(S2_CLKOUT0_DIVIDE, S2_CLKOUT0_PHASE, 50000, S2_CLKOUT0_FRAC);
  455. localparam [15:0] S2_CLKOUT0_FRAC_CALC_REG1 = S2_CLKOUT0_FRAC_CALC[15:0]; //See log file for 16 bit reporting of the register
  456. localparam [15:0] S2_CLKOUT0_FRAC_CALC_REG2 = S2_CLKOUT0_FRAC_CALC[31:16]; //See log file for 16 bit reporting of the register
  457. localparam [15:0] S2_CLKOUT0_FRAC_CALC_REGSHARED = S2_CLKOUT0_FRAC_CALC[31:16]; //See log file for 16 bit reporting of the register
  458. localparam [37:0] S2_CLKOUT1 =
  459. mmcm_count_calc(S2_CLKOUT1_DIVIDE, S2_CLKOUT1_PHASE, S2_CLKOUT1_DUTY);
  460. localparam [15:0] S2_CLKOUT1_REG1 = S2_CLKOUT1[15:0]; //See log file for 16 bit reporting of the register
  461. localparam [15:0] S2_CLKOUT1_REG2 = S2_CLKOUT1[31:16]; //See log file for 16 bit reporting of the register
  462. localparam [37:0] S2_CLKOUT2 =
  463. mmcm_count_calc(S2_CLKOUT2_DIVIDE, S2_CLKOUT2_PHASE, S2_CLKOUT2_DUTY);
  464. localparam [15:0] S2_CLKOUT2_REG1 = S2_CLKOUT2[15:0]; //See log file for 16 bit reporting of the register
  465. localparam [15:0] S2_CLKOUT2_REG2 = S2_CLKOUT2[31:16]; //See log file for 16 bit reporting of the register
  466. localparam [37:0] S2_CLKOUT3 =
  467. mmcm_count_calc(S2_CLKOUT3_DIVIDE, S2_CLKOUT3_PHASE, S2_CLKOUT3_DUTY);
  468. localparam [15:0] S2_CLKOUT3_REG1 = S2_CLKOUT3[15:0]; //See log file for 16 bit reporting of the register
  469. localparam [15:0] S2_CLKOUT3_REG2 = S2_CLKOUT3[31:16]; //See log file for 16 bit reporting of the register
  470. localparam [37:0] S2_CLKOUT4 =
  471. mmcm_count_calc(S2_CLKOUT4_DIVIDE, S2_CLKOUT4_PHASE, S2_CLKOUT4_DUTY);
  472. localparam [15:0] S2_CLKOUT4_REG1 = S2_CLKOUT4[15:0]; //See log file for 16 bit reporting of the register
  473. localparam [15:0] S2_CLKOUT4_REG2 = S2_CLKOUT4[31:16]; //See log file for 16 bit reporting of the register
  474. localparam [37:0] S2_CLKOUT5 =
  475. mmcm_count_calc(S2_CLKOUT5_DIVIDE, S2_CLKOUT5_PHASE, S2_CLKOUT5_DUTY);
  476. localparam [15:0] S2_CLKOUT5_REG1 = S2_CLKOUT5[15:0]; //See log file for 16 bit reporting of the register
  477. localparam [15:0] S2_CLKOUT5_REG2 = S2_CLKOUT5[31:16]; //See log file for 16 bit reporting of the register
  478. localparam [37:0] S2_CLKOUT6 =
  479. mmcm_count_calc(S2_CLKOUT6_DIVIDE, S2_CLKOUT6_PHASE, S2_CLKOUT6_DUTY);
  480. localparam [15:0] S2_CLKOUT6_REG1 = S2_CLKOUT6[15:0]; //See log file for 16 bit reporting of the register
  481. localparam [15:0] S2_CLKOUT6_REG2 = S2_CLKOUT6[31:16]; //See log file for 16 bit reporting of the register
  482. initial begin
  483. // rom entries contain (in order) the address, a bitmask, and a bitset
  484. //***********************************************************************
  485. // State 1 Initialization
  486. //***********************************************************************
  487. // Store the power bits
  488. rom[0] = {7'h28, 16'h0000, 16'hFFFF};
  489. // Store CLKOUT0 divide and phase
  490. rom[1] = (S1_CLKOUT0_FRAC_EN == 0) ?
  491. {7'h09, 16'h8000, S1_CLKOUT0[31:16]}:
  492. {7'h09, 16'h8000, S1_CLKOUT0_FRAC_CALC[31:16]};
  493. rom[2] = (S1_CLKOUT0_FRAC_EN == 0) ?
  494. {7'h08, 16'h1000, S1_CLKOUT0[15:0]}:
  495. {7'h08, 16'h1000, S1_CLKOUT0_FRAC_CALC[15:0]};
  496. // Store CLKOUT1 divide and phase
  497. rom[3] = {7'h0A, 16'h1000, S1_CLKOUT1[15:0]};
  498. rom[4] = {7'h0B, 16'hFC00, S1_CLKOUT1[31:16]};
  499. // Store CLKOUT2 divide and phase
  500. rom[5] = {7'h0C, 16'h1000, S1_CLKOUT2[15:0]};
  501. rom[6] = {7'h0D, 16'hFC00, S1_CLKOUT2[31:16]};
  502. // Store CLKOUT3 divide and phase
  503. rom[7] = {7'h0E, 16'h1000, S1_CLKOUT3[15:0]};
  504. rom[8] = {7'h0F, 16'hFC00, S1_CLKOUT3[31:16]};
  505. // Store CLKOUT4 divide and phase
  506. rom[9] = {7'h10, 16'h1000, S1_CLKOUT4[15:0]};
  507. rom[10] = {7'h11, 16'hFC00, S1_CLKOUT4[31:16]};
  508. // Store CLKOUT5 divide and phase
  509. rom[11] = {7'h06, 16'h1000, S1_CLKOUT5[15:0]};
  510. rom[12] = (S1_CLKOUT0_FRAC_EN == 0) ?
  511. {7'h07, 16'hC000, S1_CLKOUT5[31:16]}:
  512. {7'h07, 16'hC000, S1_CLKOUT5[31:30], S1_CLKOUT0_FRAC_CALC[35:32],S1_CLKOUT5[25:16]};
  513. // Store CLKOUT6 divide and phase
  514. rom[13] = {7'h12, 16'h1000, S1_CLKOUT6[15:0]};
  515. rom[14] = (S1_CLKFBOUT_FRAC_EN == 0) ?
  516. {7'h13, 16'hC000, S1_CLKOUT6[31:16]}:
  517. {7'h13, 16'hC000, S1_CLKOUT6[31:30], S1_CLKFBOUT_FRAC_CALC[35:32],S1_CLKOUT6[25:16]};
  518. // Store the input divider
  519. rom[15] = {7'h16, 16'hC000, {2'h0, S1_DIVCLK[23:22], S1_DIVCLK[11:0]} };
  520. // Store the feedback divide and phase
  521. rom[16] = (S1_CLKFBOUT_FRAC_EN == 0) ?
  522. {7'h14, 16'h1000, S1_CLKFBOUT[15:0]}:
  523. {7'h14, 16'h1000, S1_CLKFBOUT_FRAC_CALC[15:0]};
  524. rom[17] = (S1_CLKFBOUT_FRAC_EN == 0) ?
  525. {7'h15, 16'h8000, S1_CLKFBOUT[31:16]}:
  526. {7'h15, 16'h8000, S1_CLKFBOUT_FRAC_CALC[31:16]};
  527. // Store the lock settings
  528. rom[18] = {7'h18, 16'hFC00, {6'h00, S1_LOCK[29:20]} };
  529. rom[19] = {7'h19, 16'h8000, {1'b0 , S1_LOCK[34:30], S1_LOCK[9:0]} };
  530. rom[20] = {7'h1A, 16'h8000, {1'b0 , S1_LOCK[39:35], S1_LOCK[19:10]} };
  531. // Store the filter settings
  532. rom[21] = {7'h4E, 16'h66FF,
  533. S1_DIGITAL_FILT[9], 2'h0, S1_DIGITAL_FILT[8:7], 2'h0,
  534. S1_DIGITAL_FILT[6], 8'h00 };
  535. rom[22] = {7'h4F, 16'h666F,
  536. S1_DIGITAL_FILT[5], 2'h0, S1_DIGITAL_FILT[4:3], 2'h0,
  537. S1_DIGITAL_FILT[2:1], 2'h0, S1_DIGITAL_FILT[0], 4'h0 };
  538. //***********************************************************************
  539. // State 2 Initialization
  540. //***********************************************************************
  541. // Store the power bits
  542. rom[23] = {7'h28, 16'h0000, 16'hFFFF};
  543. // Store CLKOUT0 divide and phase
  544. rom[24] = (S2_CLKOUT0_FRAC_EN == 0) ?
  545. {7'h09, 16'h8000, S2_CLKOUT0[31:16]}:
  546. {7'h09, 16'h8000, S2_CLKOUT0_FRAC_CALC[31:16]};
  547. rom[25] = (S2_CLKOUT0_FRAC_EN == 0) ?
  548. {7'h08, 16'h1000, S2_CLKOUT0[15:0]}:
  549. {7'h08, 16'h1000, S2_CLKOUT0_FRAC_CALC[15:0]};
  550. // Store CLKOUT1 divide and phase
  551. rom[26] = {7'h0A, 16'h1000, S2_CLKOUT1[15:0]};
  552. rom[27] = {7'h0B, 16'hFC00, S2_CLKOUT1[31:16]};
  553. // Store CLKOUT2 divide and phase
  554. rom[28] = {7'h0C, 16'h1000, S2_CLKOUT2[15:0]};
  555. rom[29] = {7'h0D, 16'hFC00, S2_CLKOUT2[31:16]};
  556. // Store CLKOUT3 divide and phase
  557. rom[30] = {7'h0E, 16'h1000, S2_CLKOUT3[15:0]};
  558. rom[31] = {7'h0F, 16'hFC00, S2_CLKOUT3[31:16]};
  559. // Store CLKOUT4 divide and phase
  560. rom[32] = {7'h10, 16'h1000, S2_CLKOUT4[15:0]};
  561. rom[33] = {7'h11, 16'hFC00, S2_CLKOUT4[31:16]};
  562. // Store CLKOUT5 divide and phase
  563. rom[34] = {7'h06, 16'h1000, S2_CLKOUT5[15:0]};
  564. rom[35] = (S2_CLKOUT0_FRAC_EN == 0) ?
  565. {7'h07, 16'hC000, S2_CLKOUT5[31:16]}:
  566. {7'h07, 16'hC000, S2_CLKOUT5[31:30], S2_CLKOUT0_FRAC_CALC[35:32],S2_CLKOUT5[25:16]};
  567. // Store CLKOUT6 divide and phase
  568. rom[36] = {7'h12, 16'h1000, S2_CLKOUT6[15:0]};
  569. rom[37] = (S2_CLKFBOUT_FRAC_EN == 0) ?
  570. {7'h13, 16'hC000, S2_CLKOUT6[31:16]}:
  571. {7'h13, 16'hC000, S2_CLKOUT6[31:30], S2_CLKFBOUT_FRAC_CALC[35:32],S2_CLKOUT6[25:16]};
  572. // Store the input divider
  573. rom[38] = {7'h16, 16'hC000, {2'h0, S2_DIVCLK[23:22], S2_DIVCLK[11:0]} };
  574. // Store the feedback divide and phase
  575. rom[39] = (S2_CLKFBOUT_FRAC_EN == 0) ?
  576. {7'h14, 16'h1000, S2_CLKFBOUT[15:0]}:
  577. {7'h14, 16'h1000, S2_CLKFBOUT_FRAC_CALC[15:0]};
  578. rom[40] = (S2_CLKFBOUT_FRAC_EN == 0) ?
  579. {7'h15, 16'h8000, S2_CLKFBOUT[31:16]}:
  580. {7'h15, 16'h8000, S2_CLKFBOUT_FRAC_CALC[31:16]};
  581. // Store the lock settings
  582. rom[41] = {7'h18, 16'hFC00, {6'h00, S2_LOCK[29:20]} };
  583. rom[42] = {7'h19, 16'h8000, {1'b0 , S2_LOCK[34:30], S2_LOCK[9:0]} };
  584. rom[43] = {7'h1A, 16'h8000, {1'b0 , S2_LOCK[39:35], S2_LOCK[19:10]} };
  585. // Store the filter settings
  586. rom[44] = {7'h4E, 16'h66FF,
  587. S2_DIGITAL_FILT[9], 2'h0, S2_DIGITAL_FILT[8:7], 2'h0,
  588. S2_DIGITAL_FILT[6], 8'h00 };
  589. rom[45] = {7'h4F, 16'h666F,
  590. S2_DIGITAL_FILT[5], 2'h0, S2_DIGITAL_FILT[4:3], 2'h0,
  591. S2_DIGITAL_FILT[2:1], 2'h0, S2_DIGITAL_FILT[0], 4'h0 };
  592. // Initialize the rest of the ROM
  593. rom[46] = {7'h28,32'h0000_0000};
  594. for(ii = 47; ii < 64; ii = ii +1) begin
  595. rom[ii] = 0;
  596. end
  597. end
  598. // Output the initialized rom value based on rom_addr each clock cycle
  599. always @(posedge SCLK) begin
  600. rom_do<= #TCQ rom[rom_addr];
  601. end
  602. //**************************************************************************
  603. // Everything below is associated whith the state machine that is used to
  604. // Read/Modify/Write to the MMCM.
  605. //**************************************************************************
  606. // State Definitions
  607. localparam RESTART = 4'h1;
  608. localparam WAIT_LOCK = 4'h2;
  609. localparam WAIT_SEN = 4'h3;
  610. localparam ADDRESS = 4'h4;
  611. localparam WAIT_A_DRDY = 4'h5;
  612. localparam BITMASK = 4'h6;
  613. localparam BITSET = 4'h7;
  614. localparam WRITE = 4'h8;
  615. localparam WAIT_DRDY = 4'h9;
  616. // State sync
  617. reg [3:0] current_state = RESTART;
  618. reg [3:0] next_state = RESTART;
  619. // These variables are used to keep track of the number of iterations that
  620. // each state takes to reconfigure.
  621. // STATE_COUNT_CONST is used to reset the counters and should match the
  622. // number of registers necessary to reconfigure each state.
  623. localparam STATE_COUNT_CONST = 23;
  624. reg [4:0] state_count = STATE_COUNT_CONST;
  625. reg [4:0] next_state_count = STATE_COUNT_CONST;
  626. // This block assigns the next register value from the state machine below
  627. always @(posedge SCLK) begin
  628. DADDR <= #TCQ next_daddr;
  629. DWE <= #TCQ next_dwe;
  630. DEN <= #TCQ next_den;
  631. RST_MMCM <= #TCQ next_rst_mmcm;
  632. DI <= #TCQ next_di;
  633. SRDY <= #TCQ next_srdy;
  634. rom_addr <= #TCQ next_rom_addr;
  635. state_count <= #TCQ next_state_count;
  636. end
  637. // This block assigns the next state, reset is syncronous.
  638. always @(posedge SCLK) begin
  639. if(RST) begin
  640. current_state <= #TCQ RESTART;
  641. end else begin
  642. current_state <= #TCQ next_state;
  643. end
  644. end
  645. always @* begin
  646. // Setup the default values
  647. next_srdy = 1'b0;
  648. next_daddr = DADDR;
  649. next_dwe = 1'b0;
  650. next_den = 1'b0;
  651. next_rst_mmcm = RST_MMCM;
  652. next_di = DI;
  653. next_rom_addr = rom_addr;
  654. next_state_count = state_count;
  655. case (current_state)
  656. // If RST is asserted reset the machine
  657. RESTART: begin
  658. next_daddr = 7'h00;
  659. next_di = 16'h0000;
  660. next_rom_addr = 6'h00;
  661. next_rst_mmcm = 1'b1;
  662. next_state = WAIT_LOCK;
  663. end
  664. // Waits for the MMCM to assert IntLocked - once it does asserts SRDY
  665. WAIT_LOCK: begin
  666. // Make sure reset is de-asserted
  667. next_rst_mmcm = 1'b0;
  668. // Reset the number of registers left to write for the next
  669. // reconfiguration event.
  670. next_state_count = STATE_COUNT_CONST ;
  671. next_rom_addr = SADDR ? STATE_COUNT_CONST : 8'h00;
  672. if(IntLocked) begin
  673. // MMCM is IntLocked, go on to wait for the SEN signal
  674. next_state = WAIT_SEN;
  675. // Assert SRDY to indicate that the reconfiguration module is
  676. // ready
  677. next_srdy = 1'b1;
  678. end else begin
  679. // Keep waiting, IntLocked has not asserted yet
  680. next_state = WAIT_LOCK;
  681. end
  682. end
  683. // Wait for the next SEN pulse and set the ROM addr appropriately
  684. // based on SADDR
  685. WAIT_SEN: begin
  686. next_rom_addr = SADDR ? STATE_COUNT_CONST : 8'h00;
  687. if (SEN) begin
  688. next_rom_addr = SADDR ? STATE_COUNT_CONST : 8'h00;
  689. // Go on to address the MMCM
  690. next_state = ADDRESS;
  691. end else begin
  692. // Keep waiting for SEN to be asserted
  693. next_state = WAIT_SEN;
  694. end
  695. end
  696. // Set the address on the MMCM and assert DEN to read the value
  697. ADDRESS: begin
  698. // Reset the DCM through the reconfiguration
  699. next_rst_mmcm = 1'b1;
  700. // Enable a read from the MMCM and set the MMCM address
  701. next_den = 1'b1;
  702. next_daddr = rom_do[38:32];
  703. // Wait for the data to be ready
  704. next_state = WAIT_A_DRDY;
  705. end
  706. // Wait for DRDY to assert after addressing the MMCM
  707. WAIT_A_DRDY: begin
  708. if (DRDY) begin
  709. // Data is ready, mask out the bits to save
  710. next_state = BITMASK;
  711. end else begin
  712. // Keep waiting till data is ready
  713. next_state = WAIT_A_DRDY;
  714. end
  715. end
  716. // Zero out the bits that are not set in the mask stored in rom
  717. BITMASK: begin
  718. // Do the mask
  719. next_di = rom_do[31:16] & DO;
  720. // Go on to set the bits
  721. next_state = BITSET;
  722. end
  723. // After the input is masked, OR the bits with calculated value in rom
  724. BITSET: begin
  725. // Set the bits that need to be assigned
  726. next_di = rom_do[15:0] | DI;
  727. // Set the next address to read from ROM
  728. next_rom_addr = rom_addr + 1'b1;
  729. // Go on to write the data to the MMCM
  730. next_state = WRITE;
  731. end
  732. // DI is setup so assert DWE, DEN, and RST_MMCM. Subtract one from the
  733. // state count and go to wait for DRDY.
  734. WRITE: begin
  735. // Set WE and EN on MMCM
  736. next_dwe = 1'b1;
  737. next_den = 1'b1;
  738. // Decrement the number of registers left to write
  739. next_state_count = state_count - 1'b1;
  740. // Wait for the write to complete
  741. next_state = WAIT_DRDY;
  742. end
  743. // Wait for DRDY to assert from the MMCM. If the state count is not 0
  744. // jump to ADDRESS (continue reconfiguration). If state count is
  745. // 0 wait for lock.
  746. WAIT_DRDY: begin
  747. if(DRDY) begin
  748. // Write is complete
  749. if(state_count > 0) begin
  750. // If there are more registers to write keep going
  751. next_state = ADDRESS;
  752. end else begin
  753. // There are no more registers to write so wait for the MMCM
  754. // to lock
  755. next_state = WAIT_LOCK;
  756. end
  757. end else begin
  758. // Keep waiting for write to complete
  759. next_state = WAIT_DRDY;
  760. end
  761. end
  762. // If in an unknown state reset the machine
  763. default: begin
  764. next_state = RESTART;
  765. end
  766. endcase
  767. end
  768. endmodule