@@ -54,6 +54,8 @@ struct secondary_params{
5454
5555 float freq;
5656 float phase;
57+ float phase_vco_step;
58+ float phase_div_step;
5759};
5860
5961struct pll_params {
@@ -62,6 +64,10 @@ struct pll_params{
6264 int feedback_div;
6365 int output_div;
6466 int primary_cphase;
67+ int primary_fphase;
68+ float primary_phase_vco_step;
69+ float primary_phase_div_step;
70+
6571 string clkin_name;
6672 string clkout0_name;
6773 int dynamic;
@@ -85,6 +91,8 @@ struct pll_params{
8591 }
8692};
8793
94+ float calc_vco_phase_step (int fphase, int div);
95+ float calc_div_phase_step (int cphase, int div);
8896void calc_pll_params (pll_params ¶ms, float input, float output);
8997void calc_pll_params_highres (pll_params ¶ms, float input, float output);
9098void generate_secondary_output (pll_params ¶ms, int channel, string name, float frequency, float phase);
@@ -245,22 +253,38 @@ int main(int argc, char** argv){
245253 cout << " Feedback divisor: " << params.feedback_div << endl;
246254 cout << " clkout0 divisor: " << params.output_div << " " << endl;
247255 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+ }
248260 if (params.secondary [0 ].enabled ){
249261 cout << " clkout1 divisor: " << params.secondary [0 ].div << endl;
250262 cout << " clkout1 frequency: " << params.secondary [0 ].freq << " MHz" << endl;
251263 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+ }
252268 }
253269 if (params.secondary [1 ].enabled ){
254270 cout << " clkout2 divisor: " << params.secondary [1 ].div << endl;
255271 cout << " clkout2 frequency: " << params.secondary [1 ].freq << " MHz" << endl;
256272 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+ }
257277 }
258278 if (params.secondary [2 ].enabled ){
259279 cout << " clkout3 divisor: " << params.secondary [2 ].div << endl;
260280 cout << " clkout3 frequency: " << params.secondary [2 ].freq << " MHz" << endl;
261281 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+ }
262286 }
263- cout << " VCO frequency: " << params.fvco << endl;
287+ cout << " VCO frequency: " << params.fvco << " Mhz " << endl;
264288 if (vm.count (" file" )){
265289 ofstream f;
266290 f.open (vm[" file" ].as <string>().c_str ());
@@ -269,6 +293,14 @@ int main(int argc, char** argv){
269293 }
270294}
271295
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+
272304void calc_pll_params (pll_params ¶ms, float input, float output){
273305 float error = std::numeric_limits<float >::max ();
274306 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){
294326 params.fvco = fvco;
295327 // shift the primary by 180 degrees. Lattice seems to do this
296328 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 );
298335 }
299336 }
300337 }
@@ -331,6 +368,15 @@ void calc_pll_params_highres(pll_params ¶ms, float input, float output){
331368 params.secondary [0 ].freq = fout;
332369 params.fout = fout;
333370 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 );
334380 }
335381 }
336382 }
@@ -359,6 +405,8 @@ void generate_secondary_output(pll_params ¶ms, int channel, string name, flo
359405 params.secondary [channel].cphase = cphase + params.primary_cphase ;
360406 params.secondary [channel].fphase = fphase;
361407 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);
362410}
363411
364412void 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
376424 {
377425 file << " input [1:0] phasesel, // clkout[] index affected by dynamic phase shift (except clkfb), 5 ns min before apply\n " ;
378426 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 " ;
381451 }
382452 file << " input " << params.clkin_name << " , // " << params.clkin_frequency << " MHz, 0 deg\n " ;
383453 file << " output " << params.clkout0_name << " , // " << params.fout << " MHz, 0 deg\n " ;
0 commit comments