February 28, 2023

EBAZ4205 - Zynq PL fabric clocks

The Zynq PL receives 4 "fabric clocks" from the PS. In the default setup, these run at 50, 10, 10, and 10 Mhz. The frequencies are set by some initialization that takes place in the boot process. Various sources say this is done by the FSBL (first stage boot loader).

In Vivado, you can pull the Zynq processing system block into a model, double click on it, and then find the clocks in the configuration screen that this gives you. When I do this, I see the first clock "enabled" at set at 50, the other clocks are disabled and set to 10. Enabling seems to simply mean that an output pin is presented on the block diagram. This configuration screen allows you to change the frequencies of the clocks, or at least to request that the frequencies be changed. Somehow this must communicate the desired values to the SDK or Vitis, because in my case this accomplishes nothing.

An upper limit of 250 Mhz is imposed by the configuration dialog. Comments I have read online indicate that values of 100 or 125 Mhz work with no problem, but values of 250 or even 200 are met with skepticism. I will have to perform my own experiments. Unfortunately what is likely to happen is that some designs will work with faster clocks and others will not. We will see.

PS side control of the clocks

The Zynq technical reference manual covers clocks in 25 and on page 699 discusses PL clocks. The four control registers are:
FPGA0_CLK_CTRL
FPGA1_CLK_CTRL
FPGA2_CLK_CTRL
FPGA3_CLK_CTRL
These registers have a mux field to select from one of 3 sources (ARM, IO, or DDR clock), followed by two 6-bit programmable divisors. There is in addition a trigger register FCLKCLKTRIGxN that selects whether the clock runs continuously or for a specified number of cycles. There is also a "throttle register", slcr.FPGAx_THR_CTRL that can be used to cancel the clock.

These are apparently "sclr" registers (system level control registers) which are listed on pages 1571 and on. The sclr base address is 0xF8000000. Each PL clock gets 4 registers:

FPGAx_CLK_CTRL
FPGAx_THR_CTRL
FPGAx_THR_CNT
FPGAx_THR_STA

Dealing with the slcr

This has a special protocol that requires it to be unlocked and locked. Looking at the Petalinux sources, I see a routine zynq_slcr_unlock() in:
Petalinux/u-boot-xlnx/arch/arm/mach-zynq/slcr.c
It works like this:
#define SLCR_LOCK_MAGIC         0x767B
#define SLCR_UNLOCK_MAGIC       0xDF0D
writel(SLCR_LOCK_MAGIC, &slcr_base->slcr_lock);
writel(SLCR_UNLOCK_MAGIC, &slcr_base->slcr_unlock);
A side note - a facility to reset the CPU is here:
	zynq_slcr_unlock();

        /*
         * Clear 0x0F000000 bits of reboot status register to workaround
         * the FSBL not loading the bitstream after soft-reboot
         * This is a temporary solution until we know more.
         */
        clrbits_le32(&slcr_base->reboot_status, 0xF000000);

        writel(1, &slcr_base->pss_rst_ctrl);

What the heck is the FSBL

I thought that this was part of U-Boot but it may or may not be. Note the statement "U-boot SPL is a full replacement for the FSBL".
Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org