PLL: Computing the Multiply/Divide frequencies automatically


Recommended Posts

Hi guys,

 

I just wrote a small C++ application (text-mode) that can compute the two primary configuration values for PLL (multiply and divide), given an input clock speed and the required speed. Since some of these are not possible directly using a single PLL, the application also scans for a dual-chained PLL approach, where the output from the first PLL is fed into the input of the second PLL.

 

These two parameters are enough for you to get a working PLL with your desired frequency.

 

pllwindows.png

 

Source code and prebuilt windows .exe available at:

 

http://alvie.com/zpuino/downloads/pllscan/

 

Enjoy :)

 

Alvie



This post has been promoted to an article
Link to comment
Share on other sites

Interesting.

BTW, for an exact match, a systematic approach is

- multiply source and target frequency with a common factor so that both are integer (i.e. shift the decimal point)

- factorize

- cancel common factors

- distribute the remaining factors among the stages.

This may be obvious, or then maybe it's not.

Link to comment
Share on other sites

offroad: there are some other factors to take into account, which are specific to each FPGA familly:

 

a) MUL and DIV are limited (this one is fairly obvious)

B) fOSC must stay withing the allowed VCO range (fOSC is fIN*MUL). For Spartan6 PLL, this is between 400MHz and 1GHz.

c) There are limitations on the max. frequency you can interconnect the PLL. I don't have a figure for this, so I capped at 400MHz.

 

Due to these limitations, I decided a brute-force approach.

 

The app is not fast - this is because it will evolve to support more than one clock output (for example, you might want a 100MHz clock, a 22.345MHz clock and a 8.80MHz), so currently it loads all of the valid PLL configurations and sorts them by error.

Link to comment
Share on other sites

Nice work. I had a go at this before too and Hamster nicely posted it on his site. BUt the two chained plls works better than mine.

- http://hamsterworks.co.nz/mediawiki/index.php/Papilio_Plus/Clock

I also used a brute force method of calculating all possible ratios then sorting the list. Worked quite well and you get to see all possible implementation choices.

I wrote it in python but I did not do the two chained timer approach. I need to make an update. :)

 

Mine was specifically for the Papillio so my max div ratio is 32 not 40. (I may have read the datasheet wrong, or new device is faster :))

Of course it all depends on the chipset you're using. I wonder if its worth trying to factor in these per-device limitations ?

 

I'll work on it some more and post a newer version...

[..Update..] Latest version here: https://github.com/Neon22/papilio-clock

 

Sample output:

Desired Frequency = 22.5792975 clocks evaluatedFor 22.0689655172 MHz. Error = 0.510234   mult1/mult2 = CLKFX, CLKFX180 / CLKFX_MUL/CLKFX_DIV = 2 / 29.For 22.8571428571 MHz. Error = 0.277943   mult1/mult2 = CLKDV / CLKDV_DIV = 14.For 22.8571428571 MHz. Error = 0.277943   mult1/mult2 = CLKDV / CLKDV_DIV = 7 (+CLKIN_DIV_BY_2).For 22.8571428571 MHz. Error = 0.277943   mult1/mult2 = CLKFX, CLKFX180 / CLKFX_MUL/CLKFX_DIV = 2 / 28.
Desired Frequency = 224975 clocks evaluatedFor 222.608695652 MHz. Error = 1.391304   mult1/mult2 = CLKFX, CLKFX180 / CLKFX_MUL/CLKFX_DIV = 16 / 23 . Possible (>200MHz internal speedgrade-2).For 224.0 MHz. Error = 0.000000   mult1/mult2 = CLKFX, CLKFX180 / CLKFX_MUL/CLKFX_DIV = 14 / 20 . Possible (>200MHz internal speedgrade-2).For 224.0 MHz. Error = 0.000000   mult1/mult2 = CLKFX, CLKFX180 / CLKFX_MUL/CLKFX_DIV = 21 / 30 . Possible (>200MHz internal speedgrade-2).For 224.0 MHz. Error = 0.000000   mult1/mult2 = CLKFX, CLKFX180 / CLKFX_MUL/CLKFX_DIV = 7 / 10 . Possible (>200MHz internal speedgrade-2).
Link to comment
Share on other sites

Updated to cascade DCMs. Not using any PLLs. That's a bit harder.

Shows different ways a clock can be generated.

E.g. for the above mentioned 12.288 and 24.576

Desired Frequency = 12.288For 12.288 MHz. Exact.  Use: CLKFX, CLKFX180. For 12.288 MHz: CLKFX_MUL/CLKFX_DIV = 2 / 25 from 153.600000 MHz.    For 153.6 MHz. Exact.  Use: CLKFX, CLKFX180. For 153.6 MHz: CLKFX_MUL/CLKFX_DIV = 12 / 25.For 12.288 MHz. Exact.  Use: CLKFX, CLKFX180. For 12.288 MHz: CLKFX_MUL/CLKFX_DIV = 4 / 25 from 76.800000 MHz.    For 76.8 MHz. Exact.  Use: CLKFX, CLKFX180. For 76.8 MHz: CLKFX_MUL/CLKFX_DIV = 6 / 25.For 12.288 MHz. Exact.  Use: CLKFX, CLKFX180. For 12.288 MHz: CLKFX_MUL/CLKFX_DIV = 8 / 25 from 38.400000 MHz.    For 38.4 MHz. Exact.  Use: CLKFX, CLKFX180. For 38.4 MHz: CLKFX_MUL/CLKFX_DIV = 3 / 25.
Desired Frequency = 24.576For 24.576 MHz. Exact.  Use: CLKFX, CLKFX180. For 24.576 MHz: CLKFX_MUL/CLKFX_DIV = 16 / 25 from 38.400000 MHz.    For 38.4 MHz. Exact.  Use: CLKFX, CLKFX180. For 38.4 MHz: CLKFX_MUL/CLKFX_DIV = 3 / 25.For 24.576 MHz. Exact.  Use: CLKFX, CLKFX180. For 24.576 MHz: CLKFX_MUL/CLKFX_DIV = 2 / 25 from 307.200000 MHz.    For 307.2 MHz. Exact.  Use: CLKFX, CLKFX180. For 307.2 MHz: CLKFX_MUL/CLKFX_DIV = 24 / 25 -Unlikely. (>250MHz. Needs chip speedgrade-2).For 24.576 MHz. Exact.  Use: CLKFX, CLKFX180. For 24.576 MHz: CLKFX_MUL/CLKFX_DIV = 4 / 25 from 153.600000 MHz.    For 153.6 MHz. Exact.  Use: CLKFX, CLKFX180. For 153.6 MHz: CLKFX_MUL/CLKFX_DIV = 12 / 25.For 24.576 MHz. Exact.  Use: CLKFX, CLKFX180. For 24.576 MHz: CLKFX_MUL/CLKFX_DIV = 8 / 25 from 76.800000 MHz.    For 76.8 MHz. Exact.  Use: CLKFX, CLKFX180. For 76.8 MHz: CLKFX_MUL/CLKFX_DIV = 6 / 25.

 - don't type in 32MHz - the listing is very long :)

 

I recall now I stopped working on this because the vendor had a special clock helper in the IDE. Other people are better situated to comment on its effectiveness.

 

https://github.com/Neon22/papilio-clock

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.