How to initialize PLL block on ECP5 FPGA using 'ecppll'.

A phase-locked loop or phase lock loop (PLL) is a control system that generates an output signal whose phase is fixed relative to the phase of an input signal. Keeping the input and output phase in lockstep also implies keeping the input and output frequencies the same, thus a phase-locked loop can also track an input frequency. And by incorporating a frequency divider, a PLL can generate a stable frequency that is a multiple of the input frequency.

In context of Computer Architecture, PLLs are used to generate a stable, high-frequency clock signal from a lower-frequency reference clock and is crucial for microprocessors and other digital circuits that require high-speed operation. Xilinx FPGAs have their own Clocking Wizard IP to get the output signal with required frequency and phase difference. However this is not the case with Lattice FPGAs

In this blog post, I will document what I did to intialize the PLL block on ECP5 FPGA and verified the output on the DSO (Digital Signal Oscilloscope) with instructions for Debian-based linux distros ( I am an Arch user but I feel most of them use Ubuntu/Debian so I have documented the blog for those users. Arch users can install directly the below packages through AUR ) . I am using the onboard PLL block on ECP5 FPGA to generate a 100Mhz clock signal from 12Mhz clock signal on iCEBreaker++ FPGA, initialised by ‘ecppll’ tool.

Step 1: Software Setup

As we are working with the ECP5 FPGA fabric, we need to install Yosys suite and nextpnr-ecp5 tools to program the fabric.

  • To install Yosys, follow the steps provided here (I prefer building from source, there are other ways to install yosys and you are free to try it). You can verify the installation by executing yosys --help or yosys -p "help".

  • nextpnr-ecp5 relies on Project Trellis. Install it with following commands :-

git clone --recursive https://github.com/YosysHQ/prjtrellis
cd prjtrellis/libtrellis
cmake -DCMAKE_INSTALL_PREFIX=/usr/local .
make
sudo make install

After this, we have to clone the nextpnr repository and follow the given steps:-

cd nextpnr/
cmake . -DARCH=ecp5 -DTRELLIS_INSTALL_PREFIX=/usr/local
make -j$(nproc)
sudo make install

Step 2: Generate PLL module in Verilog

Now we are done with installations, Let’s start with generating PLL module using ecppll tool. This tool is included in Project Trellis and you can verify the installation by executing ecppll --help. Now the board I am using, iCEBreaker++ has internal 12Mhz crystal oscillator to generate the clock and I want 100Mhz clock as output. So, my ecppll command will be to generate 100Mhz clock from 12Mhz clock will be :-

ecppll -f test.v -n test -i 12 -o 100
  • ‘-f’ argument is used to generate a verilog file containing the instantation named as “test.v”.
  • ‘-n’ argument is used to name the module i.e “test”.
  • ‘-i’ argument is used to specify the input frequency in Mhz.
  • ‘-o’ argument is used to specify the output frequency in Mhz.

You can find more arguments and understand their uses by executing ecppll --help or by following this documentation.

Although the tool won’t echo a message of verilog file generation, you can verify yourself using ls command and see that the file (named as test.v in my case) has been generated in your directory.

Note:- If you already have a file with the same name, the contents of the file will get overwritten by the tool. So make sure you give a unique file name for your instantation if you do not want your previous contents to get overwritten.

Step 3: Programming the FPGA

The only way to observe whether the PLL output is correct or not, is by programming the FPGA and use a DSO (Digital Signal Oscilloscope) to verify it. Use a text editor to create a .pcf file which maps your device pins with input and output of your Verilog file (I mapped it to PMOD pins on my board, as they can work as GPIO pins to observe the output). Here’s an example that I followed. You might have to refer the schematic of your board to find the pin number which you want to map.

Here’s the Makefile that I used to synthesize, generate bitstream and flash it on the board -

PROJ=test

all: ${PROJ}.bit

%.json: %.v
	yosys -p "synth_ecp5 -json $@" $<

%_out.config: %.json
	nextpnr-ecp5 --json $< --textcfg $@ --12k --package CABGA256 --lpf ${PROJ}.pcf

%.bit: %_out.config
	ecppack --compress $< $@

prog: ${PROJ}.bit
	ecpprog -S ${PROJ}.bit

flash: ${PROJ}.bit
	ecpprog ${PROJ}.bit

clean:
	$(RM) -f ${PROJ}.bit ${PROJ}_out.config ${PROJ}.json 

.PHONY: prog clean

Use a text editor and copy above Makefile in the same directory. execute it and connect your output pin with DSO’s probes to see the output.

Acknowledgements