How can we drive the PLL?

The board has two 16MHz clocks, is one of them available as a PLL reference frequency? I have some code that runs on a Mach X02 at 13.1 MHz and it would be easiest to just generate that via the PLL.


EDIT: Looking at the icestorm docs for the iCE40UP series, it looks like the PLL isn’t supported. So it’s off to Plan B for me !


I will put an example on the website to use the PLL. I have used it many times to generate different clocks. 13.1MHz may be difficult to derive from 16MHz, or the internal oscillators. However you can likely can get close to that frequency.


1 Like

The icepll utility suggests that you can get 26.0 using either 16 or 48 MHz reference clocks, and you can then divide by 2 to get 13.0. 13.1 is apparently not possible given the limited number of divisors available in the ICE40 PLL.

The current top-of-tree version of yosys/nextpnr do appear to have support for the SB16_PLL block, and I’ve synthesized one such design (but haven’t run it on the board yet so I don’ t know if it really works).

1 Like

I can make it work on 13. It’s yet another Neopixel driver :slight_smile:

I added am example verilog file on the website showing how to include the PLL.


I need to make it more parameterized, but right now it is fixed at 48MHz in 16MHz out. Also there are few variations on the PLL, whether the input source is internal or an external to the FPGA, will need examples of those as well.

Picking the divisors can be tricky. However there is a open source tool to help with that. I think it would be good to create a frontend web page to allow a user to put in the input and desired output frequencies and display the results. The tool does this but needs to be run on the user side. Then these divisors will just be parameters into the PLL instance.

The example for now is just to show the PLL feature. Users can play with the dividers and see how the output changes.


@mick.jacobs thanks!

I found icepll and it should be easy enough to adapt for running in a web client (either via Emscripten and a service worker or by cross-compiling to WebAssembly.)


That is the tool I was referring too. That would be great to have it in WebAssembly.


Any chance we can use the 16MHz crystal oscillator as a reference source?

I just tried that today (using icestorm) and got it to work.

Try something like this:

.DIVR(4’b0000), // DIVR = 0
.DIVF(7’b0110011), // DIVF = 51
.DIVQ(3’b101), // DIVQ = 5
) uut (

You must instantiate the special PLL block which expects to take its reference input directly from a pin… the simpler SBB_PLL40_CORE won’t work in this case.

1 Like