@@ -54,6 +54,8 @@ struct secondary_params{
54
54
55
55
float freq;
56
56
float phase;
57
+ float phase_vco_step;
58
+ float phase_div_step;
57
59
};
58
60
59
61
struct pll_params {
@@ -62,6 +64,10 @@ struct pll_params{
62
64
int feedback_div;
63
65
int output_div;
64
66
int primary_cphase;
67
+ int primary_fphase;
68
+ float primary_phase_vco_step;
69
+ float primary_phase_div_step;
70
+
65
71
string clkin_name;
66
72
string clkout0_name;
67
73
int dynamic;
@@ -85,6 +91,8 @@ struct pll_params{
85
91
}
86
92
};
87
93
94
+ float calc_vco_phase_step (int fphase, int div);
95
+ float calc_div_phase_step (int cphase, int div);
88
96
void calc_pll_params (pll_params ¶ms, float input, float output);
89
97
void calc_pll_params_highres (pll_params ¶ms, float input, float output);
90
98
void generate_secondary_output (pll_params ¶ms, int channel, string name, float frequency, float phase);
@@ -245,22 +253,38 @@ int main(int argc, char** argv){
245
253
cout << " Feedback divisor: " << params.feedback_div << endl;
246
254
cout << " clkout0 divisor: " << params.output_div << " " << endl;
247
255
cout << " clkout0 frequency: " << params.fout << " MHz" << endl;
256
+ if (params.dynamic ){
257
+ cout << " clkout0 vco step: " << params.primary_phase_vco_step << " degrees" << endl;
258
+ cout << " clkout0 div step: " << params.primary_phase_div_step << " degrees" << endl;
259
+ }
248
260
if (params.secondary [0 ].enabled ){
249
261
cout << " clkout1 divisor: " << params.secondary [0 ].div << endl;
250
262
cout << " clkout1 frequency: " << params.secondary [0 ].freq << " MHz" << endl;
251
263
cout << " clkout1 phase shift: " << params.secondary [0 ].phase << " degrees" << endl;
264
+ if (params.dynamic ){
265
+ cout << " clkout1 vco step: " << params.secondary [0 ].phase_vco_step << " degrees" << endl;
266
+ cout << " clkout1 div step: " << params.secondary [0 ].phase_div_step << " degrees" << endl;
267
+ }
252
268
}
253
269
if (params.secondary [1 ].enabled ){
254
270
cout << " clkout2 divisor: " << params.secondary [1 ].div << endl;
255
271
cout << " clkout2 frequency: " << params.secondary [1 ].freq << " MHz" << endl;
256
272
cout << " clkout2 phase shift: " << params.secondary [1 ].phase << " degrees" << endl;
273
+ if (params.dynamic ){
274
+ cout << " clkout2 vco step: " << params.secondary [1 ].phase_vco_step << " degrees" << endl;
275
+ cout << " clkout2 div step: " << params.secondary [1 ].phase_div_step << " degrees" << endl;
276
+ }
257
277
}
258
278
if (params.secondary [2 ].enabled ){
259
279
cout << " clkout3 divisor: " << params.secondary [2 ].div << endl;
260
280
cout << " clkout3 frequency: " << params.secondary [2 ].freq << " MHz" << endl;
261
281
cout << " clkout3 phase shift: " << params.secondary [2 ].phase << " degrees" << endl;
282
+ if (params.dynamic ){
283
+ cout << " clkout3 vco step: " << params.secondary [2 ].phase_vco_step << " degrees" << endl;
284
+ cout << " clkout3 div step: " << params.secondary [2 ].phase_div_step << " degrees" << endl;
285
+ }
262
286
}
263
- cout << " VCO frequency: " << params.fvco << endl;
287
+ cout << " VCO frequency: " << params.fvco << " Mhz " << endl;
264
288
if (vm.count (" file" )){
265
289
ofstream f;
266
290
f.open (vm[" file" ].as <string>().c_str ());
@@ -269,6 +293,14 @@ int main(int argc, char** argv){
269
293
}
270
294
}
271
295
296
+ float calc_vco_phase_step (int fphase, int div){
297
+ return (360 .f * (float )fphase) / (8 .f * (float )div);
298
+ }
299
+
300
+ float calc_div_phase_step (int cphase, int div){
301
+ return (360 .f * ((float )cphase - (float )div)) / (1 .f + (float )div);
302
+ }
303
+
272
304
void calc_pll_params (pll_params ¶ms, float input, float output){
273
305
float error = std::numeric_limits<float >::max ();
274
306
for (int input_div=1 ;input_div <= 128 ; input_div++){
@@ -294,7 +326,12 @@ void calc_pll_params(pll_params ¶ms, float input, float output){
294
326
params.fvco = fvco;
295
327
// shift the primary by 180 degrees. Lattice seems to do this
296
328
float ns_phase = 1 /(fout * 1e6 ) * 0.5 ;
297
- params.primary_cphase = ns_phase * (fvco * 1e6 );
329
+ float phase_count = ns_phase * (fvco * 1e6 );
330
+ params.primary_cphase = phase_count;
331
+ int cphase = (int ) phase_count;
332
+ params.primary_fphase = (int ) ((phase_count - cphase) * 8 );
333
+ params.primary_phase_vco_step = calc_vco_phase_step (params.primary_fphase , params.output_div );
334
+ params.primary_phase_div_step = calc_div_phase_step (params.primary_cphase , params.output_div );
298
335
}
299
336
}
300
337
}
@@ -331,6 +368,15 @@ void calc_pll_params_highres(pll_params ¶ms, float input, float output){
331
368
params.secondary [0 ].freq = fout;
332
369
params.fout = fout;
333
370
params.fvco = fvco;
371
+
372
+ // Is this correct for highres mode?
373
+ float ns_phase = 1 /(fout * 1e6 ) * 0.5 ;
374
+ float phase_count = ns_phase * (fvco * 1e6 );
375
+ params.primary_cphase = phase_count;
376
+ int cphase = (int ) phase_count;
377
+ params.primary_fphase = (int ) ((phase_count - cphase) * 8 );
378
+ params.primary_phase_vco_step = calc_vco_phase_step (params.primary_fphase , params.output_div );
379
+ params.primary_phase_div_step = calc_div_phase_step (params.primary_cphase , params.output_div );
334
380
}
335
381
}
336
382
}
@@ -359,6 +405,8 @@ void generate_secondary_output(pll_params ¶ms, int channel, string name, flo
359
405
params.secondary [channel].cphase = cphase + params.primary_cphase ;
360
406
params.secondary [channel].fphase = fphase;
361
407
params.secondary [channel].name = name;
408
+ params.secondary [channel].phase_vco_step = calc_vco_phase_step (fphase, div);
409
+ params.secondary [channel].phase_div_step = calc_div_phase_step (params.secondary [channel].cphase , div);
362
410
}
363
411
364
412
void write_pll_config (const pll_params & params, const string &name, ofstream& file)
@@ -376,8 +424,30 @@ void write_pll_config(const pll_params & params, const string &name, ofstream& f
376
424
{
377
425
file << " input [1:0] phasesel, // clkout[] index affected by dynamic phase shift (except clkfb), 5 ns min before apply\n " ;
378
426
file << " input phasedir, // 0:delayed (lagging), 1:advence (leading), 5 ns min before apply\n " ;
379
- file << " input phasestep, // 45 deg step, high for 5 ns min, falling edge = apply\n " ;
380
- file << " input phaseloadreg, // high for 10 ns min, falling edge = apply\n " ;
427
+ file << " // high for 5 ns min, falling edge = apply\n " ;
428
+ file << " // " << params.primary_phase_vco_step << " deg step for " << params.clkout0_name << " \n " ;
429
+ if (params.secondary [0 ].enabled ){
430
+ file << " // " << params.secondary [0 ].phase_vco_step << " deg step for " << params.secondary [0 ].name << " \n " ;
431
+ }
432
+ if (params.secondary [1 ].enabled ){
433
+ file << " // " << params.secondary [1 ].phase_vco_step << " deg step for " << params.secondary [1 ].name << " \n " ;
434
+ }
435
+ if (params.secondary [2 ].enabled ){
436
+ file << " // " << params.secondary [2 ].phase_vco_step << " deg step for " << params.secondary [2 ].name << " \n " ;
437
+ }
438
+ file << " input phasestep,\n " ;
439
+ file << " // high for 10 ns min, falling edge = apply\n " ;
440
+ file << " // " << params.primary_phase_div_step << " deg step for " << params.clkout0_name << " \n " ;
441
+ if (params.secondary [0 ].enabled ){
442
+ file << " // " << params.secondary [0 ].phase_div_step << " deg step for " << params.secondary [0 ].name << " \n " ;
443
+ }
444
+ if (params.secondary [1 ].enabled ){
445
+ file << " // " << params.secondary [1 ].phase_div_step << " deg step for " << params.secondary [1 ].name << " \n " ;
446
+ }
447
+ if (params.secondary [2 ].enabled ){
448
+ file << " // " << params.secondary [2 ].phase_div_step << " deg step for " << params.secondary [2 ].name << " \n " ;
449
+ }
450
+ file << " input phaseloadreg,\n " ;
381
451
}
382
452
file << " input " << params.clkin_name << " , // " << params.clkin_frequency << " MHz, 0 deg\n " ;
383
453
file << " output " << params.clkout0_name << " , // " << params.fout << " MHz, 0 deg\n " ;
0 commit comments