Jun 19, 2015

Controlling Zynq PL clock from CPU

Zynq is a wonderful device: I can run Linux AND bare metal, hard-real-time code on its dual-core ARM Cortex A9 processors, and create custom FPGA logic to process incoming data within HW (example here).  I can also generate a clock to drive other ICs, either by instantiating clocking IP modules supplied by Xilinx, or enabling one of the 4 PL clocks the Zynq processor comes with (called FCLK_CLK{0~3} in Zynq documentation).  Of these options, the FCLK_CLK route is more flexible because the clocks can be controlled from SW (through memory mapped registers).  Of course, the clocking modules in FPGA can also expose the control registers through AXI (Lite) bus, but as you can see in my earlier blog entry, you have to jump through a lot of hoops to pull that off.  In contrast, the FCLK_CLK registers are already mapped to the CPU's address space.  FCLK_CLK2 control register, for example, is at 0xF8000190, according to the Zynq TRM.  To control the clock divisor (to produce a different clock frequency), you just have to write different divisor values into that register.

Here is a use case: while bringing up an image sensor, I kept running into corrupted output signal from the sensor.  Initially, I only suspected the signal being emitted from the sensor, so I tried changing the clock divider within the image sensor.  But when I got nowhere with it, I tried slowing down the input clock into the sensor.  I originally planned to operate the sensor at 48 MHz (as the sensor datasheet claimed to support), but I had to slow down the input clock to 25 MHz before the signal integrity problem disappeared.  In the scope trace below, channel 1 is the input clock, and channel 2 is the pixclk from the sensor.