mmcme2_drp.v 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  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 = 13,
  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 = 2,
  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. // input [7:0] ClkDiv1_i,
  290. // input [7:0] ClkDiv2_i,
  291. // input [7:0] ClkDiv3_i,
  292. // input [7:0] ClkDiv4_i,
  293. // input [7:0] ClkDiv5_i,
  294. // input [7:0] ClkDiv6_i,
  295. // input [7:0] ClkDiv7_i,
  296. //
  297. // These signals are to be connected to the MMCM_ADV by port name.
  298. // Their use matches the MMCM port description in the Device User Guide.
  299. input [15:0] DO,
  300. input DRDY,
  301. input LOCK_REG_CLK_IN,
  302. input LOCKED_IN,
  303. output reg DWE,
  304. output reg DEN,
  305. output reg [6:0] DADDR,
  306. output reg [15:0] DI,
  307. output DCLK,
  308. output reg RST_MMCM,
  309. output LOCKED_OUT
  310. );
  311. //----------------------------------------------------------------------------------------
  312. //
  313. wire IntLocked;
  314. wire IntRstMmcm;
  315. wire [15:0] clkVal;
  316. wire [15:0] fracPart;
  317. assign clkVal = 16'h208;
  318. //
  319. // 100 ps delay for behavioral simulations
  320. localparam TCQ = 100;
  321. // Make sure the memory is implemented as distributed
  322. (* rom_style = "distributed" *)
  323. //
  324. // ROM of: 39 bit word 64 words deep
  325. reg [38:0] rom [63:0];
  326. reg [5:0] rom_addr;
  327. reg [38:0] rom_do;
  328. reg next_srdy;
  329. reg [5:0] next_rom_addr;
  330. reg [6:0] next_daddr;
  331. reg next_dwe;
  332. reg next_den;
  333. reg next_rst_mmcm;
  334. reg [15:0] next_di;
  335. //
  336. // Insert a register in LOCKED or not depending on the value given to the parameters
  337. // REGISTER_LOCKED. When REGISTER_LOCKED is set to "Reg" insert a register, when set
  338. // to "NoReg" don't insert a register but just pass the LOCKED signal from input to
  339. // output.
  340. // Use or not, under USE_REG_LOCKED parameter control, the registered version of the
  341. // LOCKED signal for the DRP state machine.
  342. // Possible/allowed combinations of the two LOCKED related parameters:
  343. //
  344. // | REGISTER_LOCKED | USE_REG_LOCKED | |
  345. // |-----------------|----------------|--------------------------------------------|
  346. // | "NoReg" | "No" | LOCKED is just passed through mmcme3_drp |
  347. // | | | and is used as is with the state machine |
  348. // | "NoReg" | "Yes" | NOT ALLOWED |
  349. // | "Reg" | "No" | LOCKED is registered but the unregistered |
  350. // | | | version is used for the state machine. |
  351. // | "Reg" | "Yes" | LOCKED is registered and the registered |
  352. // | | | version is also used by the state machine. |
  353. //
  354. generate
  355. if (REGISTER_LOCKED == "NoReg" && USE_REG_LOCKED == "No") begin
  356. assign LOCKED_OUT = LOCKED_IN;
  357. assign IntLocked = LOCKED_IN;
  358. end else if (REGISTER_LOCKED == "Reg" && USE_REG_LOCKED == "No") begin
  359. FDRE #(
  360. .INIT (0),
  361. .IS_C_INVERTED (0),
  362. .IS_D_INVERTED (0),
  363. .IS_R_INVERTED (0)
  364. ) mmcme3_drp_I_Fdrp (
  365. .D (LOCKED_IN),
  366. .CE (1'b1),
  367. .R (IntRstMmcm),
  368. .C (LOCK_REG_CLK_IN),
  369. .Q (LOCKED_OUT)
  370. );
  371. //
  372. assign IntLocked = LOCKED_IN;
  373. end else if (REGISTER_LOCKED == "Reg" && USE_REG_LOCKED == "Yes") begin
  374. FDRE #(
  375. .INIT (0),
  376. .IS_C_INVERTED (0),
  377. .IS_D_INVERTED (0),
  378. .IS_R_INVERTED (0)
  379. ) mmcme3_drp_I_Fdrp (
  380. .D (LOCKED_IN),
  381. .CE (1'b1),
  382. .R (IntRstMmcm),
  383. .C (LOCK_REG_CLK_IN),
  384. .Q (LOCKED_OUT)
  385. );
  386. //
  387. assign IntLocked = LOCKED_OUT;
  388. end
  389. endgenerate
  390. // Integer used to initialize remainder of unused ROM
  391. integer ii;
  392. // Pass SCLK to DCLK for the MMCM
  393. assign DCLK = SCLK;
  394. assign IntRstMmcm = RST_MMCM;
  395. // Include the MMCM reconfiguration functions. This contains the constant
  396. // functions that are used in the calculations below. This file is
  397. // required.
  398. `include "mmcme2_drp_func.h"
  399. //**************************************************************************
  400. // State 1 Calculations
  401. //**************************************************************************
  402. // Please see header for information.
  403. localparam [37:0] S1_CLKFBOUT =
  404. mmcm_count_calc(S1_CLKFBOUT_MULT, S1_CLKFBOUT_PHASE, 50000);
  405. localparam [37:0] S1_CLKFBOUT_FRAC_CALC =
  406. mmcm_frac_count_calc(S1_CLKFBOUT_MULT, S1_CLKFBOUT_PHASE, 50000, S1_CLKFBOUT_FRAC);
  407. localparam [9:0] S1_DIGITAL_FILT =
  408. mmcm_filter_lookup(S1_CLKFBOUT_MULT, S1_BANDWIDTH);
  409. localparam [39:0] S1_LOCK =
  410. mmcm_lock_lookup(S1_CLKFBOUT_MULT);
  411. localparam [37:0] S1_DIVCLK =
  412. mmcm_count_calc(S1_DIVCLK_DIVIDE, 0, 50000);
  413. localparam [37:0] S1_CLKOUT0 =
  414. mmcm_count_calc(S1_CLKOUT0_DIVIDE, S1_CLKOUT0_PHASE, S1_CLKOUT0_DUTY);
  415. localparam [15:0] S1_CLKOUT0_REG1 = S1_CLKOUT0[15:0]; //See log file for 16 bit reporting of the register
  416. localparam [15:0] S1_CLKOUT0_REG2 = S1_CLKOUT0[31:16]; //See log file for 16 bit reporting of the register
  417. localparam [37:0] S1_CLKOUT0_FRAC_CALC =
  418. mmcm_frac_count_calc(S1_CLKOUT0_DIVIDE, S1_CLKOUT0_PHASE, 50000, S1_CLKOUT0_FRAC);
  419. localparam [15:0] S1_CLKOUT0_FRAC_REG1 = S1_CLKOUT0_FRAC_CALC[15:0]; //See log file for 16 bit reporting of the register
  420. localparam [15:0] S1_CLKOUT0_FRAC_REG2 = S1_CLKOUT0_FRAC_CALC[31:16]; //See log file for 16 bit reporting of the register
  421. localparam [5:0] S1_CLKOUT0_FRAC_REGSHARED = S1_CLKOUT0_FRAC_CALC[37:32]; //See log file for 16 bit reporting of the register
  422. localparam [37:0] S1_CLKOUT1 =
  423. mmcm_count_calc(S1_CLKOUT1_DIVIDE, S1_CLKOUT1_PHASE, S1_CLKOUT1_DUTY);
  424. localparam [15:0] S1_CLKOUT1_REG1 = S1_CLKOUT1[15:0]; //See log file for 16 bit reporting of the register
  425. localparam [15:0] S1_CLKOUT1_REG2 = S1_CLKOUT1[31:16]; //See log file for 16 bit reporting of the register
  426. localparam [37:0] S1_CLKOUT2 =
  427. mmcm_count_calc(S1_CLKOUT2_DIVIDE, S1_CLKOUT2_PHASE, S1_CLKOUT2_DUTY);
  428. localparam [15:0] S1_CLKOUT2_REG1 = S1_CLKOUT2[15:0]; //See log file for 16 bit reporting of the register
  429. localparam [15:0] S1_CLKOUT2_REG2 = S1_CLKOUT2[31:16]; //See log file for 16 bit reporting of the register
  430. localparam [37:0] S1_CLKOUT3 =
  431. mmcm_count_calc(S1_CLKOUT3_DIVIDE, S1_CLKOUT3_PHASE, S1_CLKOUT3_DUTY);
  432. localparam [15:0] S1_CLKOUT3_REG1 = S1_CLKOUT3[15:0]; //See log file for 16 bit reporting of the register
  433. localparam [15:0] S1_CLKOUT3_REG2 = S1_CLKOUT3[31:16]; //See log file for 16 bit reporting of the register
  434. localparam [37:0] S1_CLKOUT4 =
  435. mmcm_count_calc(S1_CLKOUT4_DIVIDE, S1_CLKOUT4_PHASE, S1_CLKOUT4_DUTY);
  436. localparam [15:0] S1_CLKOUT4_REG1 = S1_CLKOUT4[15:0]; //See log file for 16 bit reporting of the register
  437. localparam [15:0] S1_CLKOUT4_REG2 = S1_CLKOUT4[31:16]; //See log file for 16 bit reporting of the register
  438. localparam [37:0] S1_CLKOUT5 =
  439. mmcm_count_calc(S1_CLKOUT5_DIVIDE, S1_CLKOUT5_PHASE, S1_CLKOUT5_DUTY);
  440. localparam [15:0] S1_CLKOUT5_REG1 = S1_CLKOUT5[15:0]; //See log file for 16 bit reporting of the register
  441. localparam [15:0] S1_CLKOUT5_REG2 = S1_CLKOUT5[31:16]; //See log file for 16 bit reporting of the register
  442. localparam [37:0] S1_CLKOUT6 =
  443. mmcm_count_calc(S1_CLKOUT6_DIVIDE, S1_CLKOUT6_PHASE, S1_CLKOUT6_DUTY);
  444. localparam [15:0] S1_CLKOUT6_REG1 = S1_CLKOUT6[15:0]; //See log file for 16 bit reporting of the register
  445. localparam [15:0] S1_CLKOUT6_REG2 = S1_CLKOUT6[31:16]; //See log file for 16 bit reporting of the register
  446. //**************************************************************************
  447. // State 2 Calculations
  448. //**************************************************************************
  449. localparam [37:0] S2_CLKFBOUT =
  450. mmcm_count_calc(S2_CLKFBOUT_MULT, S2_CLKFBOUT_PHASE, 50000);
  451. localparam [37:0] S2_CLKFBOUT_FRAC_CALC =
  452. mmcm_frac_count_calc(S2_CLKFBOUT_MULT, S2_CLKFBOUT_PHASE, 50000, S2_CLKFBOUT_FRAC);
  453. localparam [9:0] S2_DIGITAL_FILT =
  454. mmcm_filter_lookup(S2_CLKFBOUT_MULT, S2_BANDWIDTH);
  455. localparam [39:0] S2_LOCK =
  456. mmcm_lock_lookup(S2_CLKFBOUT_MULT);
  457. localparam [37:0] S2_DIVCLK =
  458. mmcm_count_calc(S2_DIVCLK_DIVIDE, 0, 50000);
  459. localparam [37:0] S2_CLKOUT0 =
  460. mmcm_count_calc(S2_CLKOUT0_DIVIDE, S2_CLKOUT0_PHASE, S2_CLKOUT0_DUTY);
  461. localparam [15:0] S2_CLKOUT0_REG1 = S2_CLKOUT0[15:0]; //See log file for 16 bit reporting of the register
  462. localparam [15:0] S2_CLKOUT0_REG2 = S2_CLKOUT0[31:16]; //See log file for 16 bit reporting of the register
  463. localparam [37:0] S2_CLKOUT0_FRAC_CALC =
  464. mmcm_frac_count_calc(S2_CLKOUT0_DIVIDE, S2_CLKOUT0_PHASE, 50000, S2_CLKOUT0_FRAC);
  465. localparam [15:0] S2_CLKOUT0_FRAC_CALC_REG1 = S2_CLKOUT0_FRAC_CALC[15:0]; //See log file for 16 bit reporting of the register
  466. localparam [15:0] S2_CLKOUT0_FRAC_CALC_REG2 = S2_CLKOUT0_FRAC_CALC[31:16]; //See log file for 16 bit reporting of the register
  467. localparam [15:0] S2_CLKOUT0_FRAC_CALC_REGSHARED = S2_CLKOUT0_FRAC_CALC[31:16]; //See log file for 16 bit reporting of the register
  468. localparam [37:0] S2_CLKOUT1 =
  469. mmcm_count_calc(S2_CLKOUT1_DIVIDE, S2_CLKOUT1_PHASE, S2_CLKOUT1_DUTY);
  470. localparam [15:0] S2_CLKOUT1_REG1 = S2_CLKOUT1[15:0]; //See log file for 16 bit reporting of the register
  471. localparam [15:0] S2_CLKOUT1_REG2 = S2_CLKOUT1[31:16]; //See log file for 16 bit reporting of the register
  472. localparam [37:0] S2_CLKOUT2 =
  473. mmcm_count_calc(S2_CLKOUT2_DIVIDE, S2_CLKOUT2_PHASE, S2_CLKOUT2_DUTY);
  474. localparam [15:0] S2_CLKOUT2_REG1 = S2_CLKOUT2[15:0]; //See log file for 16 bit reporting of the register
  475. localparam [15:0] S2_CLKOUT2_REG2 = S2_CLKOUT2[31:16]; //See log file for 16 bit reporting of the register
  476. localparam [37:0] S2_CLKOUT3 =
  477. mmcm_count_calc(S2_CLKOUT3_DIVIDE, S2_CLKOUT3_PHASE, S2_CLKOUT3_DUTY);
  478. localparam [15:0] S2_CLKOUT3_REG1 = S2_CLKOUT3[15:0]; //See log file for 16 bit reporting of the register
  479. localparam [15:0] S2_CLKOUT3_REG2 = S2_CLKOUT3[31:16]; //See log file for 16 bit reporting of the register
  480. localparam [37:0] S2_CLKOUT4 =
  481. mmcm_count_calc(S2_CLKOUT4_DIVIDE, S2_CLKOUT4_PHASE, S2_CLKOUT4_DUTY);
  482. localparam [15:0] S2_CLKOUT4_REG1 = S2_CLKOUT4[15:0]; //See log file for 16 bit reporting of the register
  483. localparam [15:0] S2_CLKOUT4_REG2 = S2_CLKOUT4[31:16]; //See log file for 16 bit reporting of the register
  484. localparam [37:0] S2_CLKOUT5 =
  485. mmcm_count_calc(S2_CLKOUT5_DIVIDE, S2_CLKOUT5_PHASE, S2_CLKOUT5_DUTY);
  486. localparam [15:0] S2_CLKOUT5_REG1 = S2_CLKOUT5[15:0]; //See log file for 16 bit reporting of the register
  487. localparam [15:0] S2_CLKOUT5_REG2 = S2_CLKOUT5[31:16]; //See log file for 16 bit reporting of the register
  488. localparam [37:0] S2_CLKOUT6 =
  489. mmcm_count_calc(S2_CLKOUT6_DIVIDE, S2_CLKOUT6_PHASE, S2_CLKOUT6_DUTY);
  490. localparam [15:0] S2_CLKOUT6_REG1 = S2_CLKOUT6[15:0]; //See log file for 16 bit reporting of the register
  491. localparam [15:0] S2_CLKOUT6_REG2 = S2_CLKOUT6[31:16]; //See log file for 16 bit reporting of the register
  492. initial begin
  493. // rom entries contain (in order) the address, a bitmask, and a bitset
  494. //***********************************************************************
  495. // State 1 Initialization
  496. //***********************************************************************
  497. // Store the power bits
  498. rom[0] = {7'h28, 16'h0000, 16'hFFFF};
  499. // Store CLKOUT0 divide and phase
  500. rom[1] = (S1_CLKOUT0_FRAC_EN == 0) ?
  501. {7'h09, 16'h8000, 16'h0480}:
  502. {7'h09, 16'h8000, 16'h0480};
  503. rom[2] = (S1_CLKOUT0_FRAC_EN == 0) ?
  504. {7'h08, 16'h1000, clkVal}:
  505. {7'h08, 16'h1000, clkVal};
  506. // Store CLKOUT1 divide and phase
  507. rom[3] = {7'h0A, 16'h1000, S1_CLKOUT1[15:0]};
  508. rom[4] = {7'h0B, 16'hFC00, S1_CLKOUT1[31:16]};
  509. // Store CLKOUT2 divide and phase
  510. rom[5] = {7'h0C, 16'h1000, S1_CLKOUT2[15:0]};
  511. rom[6] = {7'h0D, 16'hFC00, S1_CLKOUT2[31:16]};
  512. // Store CLKOUT3 divide and phase
  513. rom[7] = {7'h0E, 16'h1000, S1_CLKOUT3[15:0]};
  514. rom[8] = {7'h0F, 16'hFC00, S1_CLKOUT3[31:16]};
  515. // Store CLKOUT4 divide and phase
  516. rom[9] = {7'h10, 16'h1000, S1_CLKOUT4[15:0]};
  517. rom[10] = {7'h11, 16'hFC00, S1_CLKOUT4[31:16]};
  518. // Store CLKOUT5 divide and phase
  519. rom[11] = {7'h06, 16'h1000, S1_CLKOUT5[15:0]};
  520. rom[12] = (S1_CLKOUT0_FRAC_EN == 0) ?
  521. {7'h07, 16'hC000, S1_CLKOUT5[31:16]}:
  522. {7'h07, 16'hC000, S1_CLKOUT5[31:30], S1_CLKOUT0_FRAC_CALC[35:32],S1_CLKOUT5[25:16]};
  523. // Store CLKOUT6 divide and phase
  524. rom[13] = {7'h12, 16'h1000, S1_CLKOUT6[15:0]};
  525. rom[14] = (S1_CLKFBOUT_FRAC_EN == 0) ?
  526. {7'h13, 16'hC000, S1_CLKOUT6[31:16]}:
  527. {7'h13, 16'hC000, S1_CLKOUT6[31:30], S1_CLKFBOUT_FRAC_CALC[35:32],S1_CLKOUT6[25:16]};
  528. // Store the input divider
  529. rom[15] = {7'h16, 16'hC000, {2'h0, S1_DIVCLK[23:22], S1_DIVCLK[11:0]} };
  530. // Store the feedback divide and phase
  531. rom[16] = (S1_CLKFBOUT_FRAC_EN == 0) ?
  532. {7'h14, 16'h1000, S1_CLKFBOUT[15:0]}:
  533. {7'h14, 16'h1000, S1_CLKFBOUT_FRAC_CALC[15:0]};
  534. rom[17] = (S1_CLKFBOUT_FRAC_EN == 0) ?
  535. {7'h15, 16'h8000, S1_CLKFBOUT[31:16]}:
  536. {7'h15, 16'h8000, S1_CLKFBOUT_FRAC_CALC[31:16]};
  537. // Store the lock settings
  538. rom[18] = {7'h18, 16'hFC00, {6'h00, S1_LOCK[29:20]} };
  539. rom[19] = {7'h19, 16'h8000, {1'b0 , S1_LOCK[34:30], S1_LOCK[9:0]} };
  540. rom[20] = {7'h1A, 16'h8000, {1'b0 , S1_LOCK[39:35], S1_LOCK[19:10]} };
  541. // Store the filter settings
  542. rom[21] = {7'h4E, 16'h66FF,
  543. S1_DIGITAL_FILT[9], 2'h0, S1_DIGITAL_FILT[8:7], 2'h0,
  544. S1_DIGITAL_FILT[6], 8'h00 };
  545. rom[22] = {7'h4F, 16'h666F,
  546. S1_DIGITAL_FILT[5], 2'h0, S1_DIGITAL_FILT[4:3], 2'h0,
  547. S1_DIGITAL_FILT[2:1], 2'h0, S1_DIGITAL_FILT[0], 4'h0 };
  548. //***********************************************************************
  549. // State 2 Initialization
  550. //***********************************************************************
  551. // Store the power bits
  552. rom[23] = {7'h28, 16'h0000, 16'hFFFF};
  553. // Store CLKOUT0 divide and phase
  554. rom[24] = (S2_CLKOUT0_FRAC_EN == 0) ?
  555. {7'h09, 16'h8000, 16'h0480}:
  556. {7'h09, 16'h8000, 16'h0480};
  557. rom[25] = (S2_CLKOUT0_FRAC_EN == 0) ?
  558. {7'h08, 16'h1000, clkVal}:
  559. {7'h08, 16'h1000, clkVal};
  560. // Store CLKOUT1 divide and phase
  561. rom[26] = {7'h0A, 16'h1000, S2_CLKOUT1[15:0]};
  562. rom[27] = {7'h0B, 16'hFC00, S2_CLKOUT1[31:16]};
  563. // Store CLKOUT2 divide and phase
  564. rom[28] = {7'h0C, 16'h1000, S2_CLKOUT2[15:0]};
  565. rom[29] = {7'h0D, 16'hFC00, S2_CLKOUT2[31:16]};
  566. // Store CLKOUT3 divide and phase
  567. rom[30] = {7'h0E, 16'h1000, S2_CLKOUT3[15:0]};
  568. rom[31] = {7'h0F, 16'hFC00, S2_CLKOUT3[31:16]};
  569. // Store CLKOUT4 divide and phase
  570. rom[32] = {7'h10, 16'h1000, S2_CLKOUT4[15:0]};
  571. rom[33] = {7'h11, 16'hFC00, S2_CLKOUT4[31:16]};
  572. // Store CLKOUT5 divide and phase
  573. rom[34] = {7'h06, 16'h1000, S2_CLKOUT5[15:0]};
  574. rom[35] = (S2_CLKOUT0_FRAC_EN == 0) ?
  575. {7'h07, 16'hC000, S2_CLKOUT5[31:16]}:
  576. {7'h07, 16'hC000, S2_CLKOUT5[31:30], S2_CLKOUT0_FRAC_CALC[35:32],S2_CLKOUT5[25:16]};
  577. // Store CLKOUT6 divide and phase
  578. rom[36] = {7'h12, 16'h1000, S2_CLKOUT6[15:0]};
  579. rom[37] = (S2_CLKFBOUT_FRAC_EN == 0) ?
  580. {7'h13, 16'hC000, S2_CLKOUT6[31:16]}:
  581. {7'h13, 16'hC000, S2_CLKOUT6[31:30], S2_CLKFBOUT_FRAC_CALC[35:32],S2_CLKOUT6[25:16]};
  582. // Store the input divider
  583. rom[38] = {7'h16, 16'hC000, {2'h0, S2_DIVCLK[23:22], S2_DIVCLK[11:0]} };
  584. // Store the feedback divide and phase
  585. rom[39] = (S2_CLKFBOUT_FRAC_EN == 0) ?
  586. {7'h14, 16'h1000, S2_CLKFBOUT[15:0]}:
  587. {7'h14, 16'h1000, S2_CLKFBOUT_FRAC_CALC[15:0]};
  588. rom[40] = (S2_CLKFBOUT_FRAC_EN == 0) ?
  589. {7'h15, 16'h8000, S2_CLKFBOUT[31:16]}:
  590. {7'h15, 16'h8000, S2_CLKFBOUT_FRAC_CALC[31:16]};
  591. // Store the lock settings
  592. rom[41] = {7'h18, 16'hFC00, {6'h00, S2_LOCK[29:20]} };
  593. rom[42] = {7'h19, 16'h8000, {1'b0 , S2_LOCK[34:30], S2_LOCK[9:0]} };
  594. rom[43] = {7'h1A, 16'h8000, {1'b0 , S2_LOCK[39:35], S2_LOCK[19:10]} };
  595. // Store the filter settings
  596. rom[44] = {7'h4E, 16'h66FF,
  597. S2_DIGITAL_FILT[9], 2'h0, S2_DIGITAL_FILT[8:7], 2'h0,
  598. S2_DIGITAL_FILT[6], 8'h00 };
  599. rom[45] = {7'h4F, 16'h666F,
  600. S2_DIGITAL_FILT[5], 2'h0, S2_DIGITAL_FILT[4:3], 2'h0,
  601. S2_DIGITAL_FILT[2:1], 2'h0, S2_DIGITAL_FILT[0], 4'h0 };
  602. // Initialize the rest of the ROM
  603. rom[46] = {7'h28,32'h0000_0000};
  604. for(ii = 47; ii < 64; ii = ii +1) begin
  605. rom[ii] = 0;
  606. end
  607. end
  608. // Output the initialized rom value based on rom_addr each clock cycle
  609. always @(posedge SCLK) begin
  610. rom_do<= #TCQ rom[rom_addr];
  611. end
  612. //**************************************************************************
  613. // Everything below is associated whith the state machine that is used to
  614. // Read/Modify/Write to the MMCM.
  615. //**************************************************************************
  616. // State Definitions
  617. localparam RESTART = 4'h1;
  618. localparam WAIT_LOCK = 4'h2;
  619. localparam WAIT_SEN = 4'h3;
  620. localparam ADDRESS = 4'h4;
  621. localparam WAIT_A_DRDY = 4'h5;
  622. localparam BITMASK = 4'h6;
  623. localparam BITSET = 4'h7;
  624. localparam WRITE = 4'h8;
  625. localparam WAIT_DRDY = 4'h9;
  626. // State sync
  627. reg [3:0] current_state = RESTART;
  628. reg [3:0] next_state = RESTART;
  629. // These variables are used to keep track of the number of iterations that
  630. // each state takes to reconfigure.
  631. // STATE_COUNT_CONST is used to reset the counters and should match the
  632. // number of registers necessary to reconfigure each state.
  633. localparam STATE_COUNT_CONST = 4;
  634. reg [4:0] state_count = STATE_COUNT_CONST;
  635. reg [4:0] next_state_count = STATE_COUNT_CONST;
  636. // This block assigns the next register value from the state machine below
  637. always @(posedge SCLK) begin
  638. DADDR <= #TCQ next_daddr;
  639. DWE <= #TCQ next_dwe;
  640. DEN <= #TCQ next_den;
  641. RST_MMCM <= #TCQ next_rst_mmcm;
  642. DI <= #TCQ next_di;
  643. SRDY <= #TCQ next_srdy;
  644. rom_addr <= #TCQ next_rom_addr;
  645. state_count <= #TCQ next_state_count;
  646. end
  647. // This block assigns the next state, reset is syncronous.
  648. always @(posedge SCLK) begin
  649. if(RST) begin
  650. current_state <= #TCQ RESTART;
  651. end else begin
  652. current_state <= #TCQ next_state;
  653. end
  654. end
  655. always @* begin
  656. // Setup the default values
  657. next_srdy = 1'b0;
  658. next_daddr = DADDR;
  659. next_dwe = 1'b0;
  660. next_den = 1'b0;
  661. next_rst_mmcm = RST_MMCM;
  662. next_di = DI;
  663. next_rom_addr = rom_addr;
  664. next_state_count = state_count;
  665. case (current_state)
  666. // If RST is asserted reset the machine
  667. RESTART: begin
  668. next_daddr = 7'h00;
  669. next_di = 16'h0000;
  670. next_rom_addr = 6'h00;
  671. next_rst_mmcm = 1'b1;
  672. next_state = WAIT_LOCK;
  673. end
  674. // Waits for the MMCM to assert IntLocked - once it does asserts SRDY
  675. WAIT_LOCK: begin
  676. // Make sure reset is de-asserted
  677. next_rst_mmcm = 1'b0;
  678. // Reset the number of registers left to write for the next
  679. // reconfiguration event.
  680. next_state_count = STATE_COUNT_CONST ;
  681. next_rom_addr = SADDR ? STATE_COUNT_CONST : 8'h00;
  682. if(IntLocked) begin
  683. // MMCM is IntLocked, go on to wait for the SEN signal
  684. next_state = WAIT_SEN;
  685. // Assert SRDY to indicate that the reconfiguration module is
  686. // ready
  687. next_srdy = 1'b1;
  688. end else begin
  689. // Keep waiting, IntLocked has not asserted yet
  690. next_state = WAIT_LOCK;
  691. end
  692. end
  693. // Wait for the next SEN pulse and set the ROM addr appropriately
  694. // based on SADDR
  695. WAIT_SEN: begin
  696. next_rom_addr = SADDR ? STATE_COUNT_CONST : 8'h00;
  697. if (SEN) begin
  698. next_rom_addr = SADDR ? STATE_COUNT_CONST : 8'h00;
  699. // Go on to address the MMCM
  700. next_state = ADDRESS;
  701. end else begin
  702. // Keep waiting for SEN to be asserted
  703. next_state = WAIT_SEN;
  704. end
  705. end
  706. // Set the address on the MMCM and assert DEN to read the value
  707. ADDRESS: begin
  708. // Reset the DCM through the reconfiguration
  709. next_rst_mmcm = 1'b1;
  710. // Enable a read from the MMCM and set the MMCM address
  711. next_den = 1'b1;
  712. next_daddr = rom_do[38:32];
  713. // Wait for the data to be ready
  714. next_state = WAIT_A_DRDY;
  715. end
  716. // Wait for DRDY to assert after addressing the MMCM
  717. WAIT_A_DRDY: begin
  718. if (DRDY) begin
  719. // Data is ready, mask out the bits to save
  720. next_state = BITMASK;
  721. end else begin
  722. // Keep waiting till data is ready
  723. next_state = WAIT_A_DRDY;
  724. end
  725. end
  726. // Zero out the bits that are not set in the mask stored in rom
  727. BITMASK: begin
  728. // Do the mask
  729. next_di = rom_do[31:16] & DO;
  730. // Go on to set the bits
  731. next_state = BITSET;
  732. end
  733. // After the input is masked, OR the bits with calculated value in rom
  734. BITSET: begin
  735. // Set the bits that need to be assigned
  736. next_di = rom_do[15:0] | DI;
  737. // Set the next address to read from ROM
  738. next_rom_addr = rom_addr + 1'b1;
  739. // Go on to write the data to the MMCM
  740. next_state = WRITE;
  741. end
  742. // DI is setup so assert DWE, DEN, and RST_MMCM. Subtract one from the
  743. // state count and go to wait for DRDY.
  744. WRITE: begin
  745. // Set WE and EN on MMCM
  746. next_dwe = 1'b1;
  747. next_den = 1'b1;
  748. // Decrement the number of registers left to write
  749. next_state_count = state_count - 1'b1;
  750. // Wait for the write to complete
  751. next_state = WAIT_DRDY;
  752. end
  753. // Wait for DRDY to assert from the MMCM. If the state count is not 0
  754. // jump to ADDRESS (continue reconfiguration). If state count is
  755. // 0 wait for lock.
  756. WAIT_DRDY: begin
  757. if(DRDY) begin
  758. // Write is complete
  759. if(state_count > 0) begin
  760. // If there are more registers to write keep going
  761. next_state = ADDRESS;
  762. end else begin
  763. // There are no more registers to write so wait for the MMCM
  764. // to lock
  765. next_state = WAIT_LOCK;
  766. end
  767. end else begin
  768. // Keep waiting for write to complete
  769. next_state = WAIT_DRDY;
  770. end
  771. end
  772. // If in an unknown state reset the machine
  773. default: begin
  774. next_state = RESTART;
  775. end
  776. endcase
  777. end
  778. endmodule