wiki:cores/w3_clock_controller

Version 9 (modified by murphpo, 9 years ago) (diff)

--

WARP v3 Clock Controller (w3_clock_controller_axi)

This core implements an SPI master for reading/writing registers in the AD9512 clock buffers on the WARP v3 board. For details about how these buffers are connected to the FPGA and RF interfaces, refer to the WARP v3 User Guide Clocking section. This core also manages the interfaces on the CM-MMCX and CM-PLL clock modules for WARP v3.

The w3_clock_controller_axi core is packaged as a pcore which can instantiated in an XPS project. The design has been tested in hardware using Xilinx ISE 14.4.

Overview

Clock configuration in a WARP v3 FPGA design occurs in three stages:

  1. Pre-boot: the minimum set of registers are written directly by the w3_clock_controller_axi HDL to achieve an 80MHz clock from the sampling clock buffer to the FPGA. All FPGA logic clocked by the sampling clock
  2. Driver initialization: the w3_clock_controller_axi driver clk_init() function writes additional registers in the sampling and RF reference clock buffers, establishing a default configuration suitable for most applications
  3. Software application: the user application running in the MicroBlaze calls other functions in the w3_clock_controller_axi driver to customize the clock configuration

The sections below describe these three stages in detail.

Pre-Boot Configuration

In a typical FPGA design for WARP v3 most of the FPGA logic is clocked synchronous to the RF interface digital I/Q signals. This is true for both the 802.11 Reference Design and WARPLab Reference Design, which use an 80MHz master clock sourced from the sampling clock buffer. In these designs the sampling clock signal is fed into clock management circuits in the FPGA (IBUFG, MMCM, etc) and is distributed across the chip. These circuits must be held in reset until a valid sampling clock is present at the FPGA input pins.

Establishing a stable 80MHz clock from the sampling clock buffer requires:

  1. Configuring the divider and logic level of the buffer's output to the FPGA
  2. Selecting (and possibly configuring) the clock source for the sampling clock buffer

These steps require writing registers in the AD9512 buffer via its SPI interface. However the primary SPI master in the w3_clock_controller_axi core is part of logic attached to the AXI interconnected, clocked by the (not yet running) master clock. Thus the w3_clock_controller_axi HDL integrates a secondary SPI controller to perform initial setup of the clock circuits.

The w3_clock_controller_axi HDL also supports run-time selection of various clock configurations using the switches on the CM-PLL and CM-MMCX clock modules. The core implements 7 configurations by default:

Clock Module

Switches

Config

Default Settings

None

---

---

  • Select WARP v3 80MHz TCXO as sampling clock source
  • Set output to FPGA as LVDS, bypass divider

CM-PLL

CM_PLL_A

  • Configure RF reference clock buffer to output 10MHz to clock module
  • Set PLL reference clock frequency to 10MHz
  • Select clock module (CM-PLL 80MHz VCXO) as sampling clock source
  • Set output to FPGA as LVDS, bypass divider

CM_PLL_B

  • Set PLL reference clock frequency to 10MHz
  • Select clock module (CM-PLL 80MHz VCXO) as sampling clock source
  • Set output to FPGA as LVDS, bypass divider

CM_PLL_C

  • Set PLL reference clock frequency to 80MHz
  • Select clock module (CM-PLL 80MHz VCXO) as sampling clock source
  • Set output to FPGA as LVDS, bypass divider

CM-MMCX

CM_MMCX_A

  • Select WARP v3 80MHz TCXO as sampling clock source
  • Set output to FPGA as LVDS, bypass divider

CM_MMCX_B

  • Select clock module (MMCX Jack "Samp In") as sampling clock source
  • Set output to FPGA as LVDS, bypass divider

CM_MMCX_C

  • Select clock module (MMCX Jack "Samp In") as sampling clock source
  • Set output to FPGA as LVDS, bypass divider

Xilinx PicoBlaze documentation

Xilinx PicoBlaze source and tools - w3_clock_controller_axi HDL uses PicoBlaze version 6 (KCPSM6) Rev 9

PicoBlaze pseudo code - see prog_clk_config_boot.psm for actual assembly code:

main() {

    if(no_clock_module_mounted) {
      load_configuration(CFG_NOCM)
      config_complete()
    }

    if(cm_mmcx_mounted) {
      sw = read_cm_mmcx_sip_sw() //Read SIP switch
  
        if(sw == off_off) {
            //Up-Up switches -> ignore clock module
            load_configuration(CFG_NOCM)
        } else if(sw == off_on) {
            //Up-Down switches -> Config A
            load_configuration(CFG_CMMMCX_A)
        } else if(sw == on_off) {
            //Down-Up switches -> Config B
            load_configuration(CFG_CMMMCX_B)
        } else if(sw == on_on) {
            //Down-Up switches -> Config C
            load_configuration(CFG_CMMMCX_C)
        }
  
      config_complete()
    }

    if(cm_pll_mounted) {
        sw = read_cm_pll_dip_sw() //Read 2 LSB of DIP switch

        if(sw == off_off) {
            //Down-Down switches -> ignore clock module
            load_configuration(CFG_NOCM)
            config_complete()
        }
    
        wait_for_pll_refclk()
    
        if(sw == off_on) {
            //Down-Up switches -> Config A
            load_configuration(CFG_CMPLL_A)
        } else if(sw == on_off) {
            //Up-Down switches -> Config B
            load_configuration(CFG_CMPLL_B)
        } else if(sw == on_on) {
            //Up-Up switches -> Config C
            load_configuration(CFG_CMPLL_C)
        }

        wait_for_pll_lock()

        config_complete()
    }
}

wait_for_pll_refclk() {
    while(read_pll_refclk_status != TOGGLING) {}
}

wait_for_pll_lock() {
    while(read_pll_lock_status != LOCKED) {}
}

config_complete() {
  clear_mmcm_reset() //Starts clocks to FPGA, allows MicroBlaze subsystem to boot
  halt()
}

Post-Configuration

The WARP v3 board uses two AD9512 clock buffers:

  • Sampling clock buffer: distributes the sampling clock to the RF interfaces, FPGA, clock module header, and FMC slot
  • RF reference clock buffer: distributes the RF reference clock to the RF interfaces, clock module header, and FMC slot

These buffers are configured via on-boar registers accessible via an SPI interface. The SPI pins for both buffers are tied to dedicated I/O pins on the v3 FPGA.

The CM-PLL clock module uses one AD9511 PLL/buffer. When a CM-PLL module is mounted on the WARP v3 board the AD9511 SPI interface is also connected to dedicated FPGA pins.

Driver

The w3_clock_controller pcore includes a C driver to facilitate control of the AD9512s from user code. Refer to the w3_clock_controller driver documentation for more details.

All driver functions require the base memory address of the w3_clock_controller pcore. This address is set in your XPS project. The EDK tools copy this address into a macro in the xparameters.h file when you generate a BSP. The auto-generated macro should be named XPAR_W3_CLOCK_CONTROLLER_0_BASEADDR (assuming your pcore instance is named w3_CLOCK_controller_0, as in our reference projects).

//Define our own macro, in case EDK changes its naming scheme in the future
// Assumes pcore instance is named w3_ad_controller_0; confirm in xparameters.h
#define CLOCK_BASEADDR XPAR_W3_CLOCK_CONTROLLER_0_BASEADDR

Sampling Clock Source

Many user designs for WARP v3 use the sampling clock reference as the master clock for FPGA logic. Our WARP v3 Template Projects do this, for example. One implication of this approach is the sampling clock source must be stable before the FPGA logic attempts to use it. When the on-board clock is used, this is straightforward. When an off-board clock source is used (via a Clock Module) the FPGA logic must be held in reset until the sampling clock buffer can switch to the external cock source.

The w3_clock_controller contains a small block to handle this "at boot" clock selection. Immediately after the FPGA is configured this block writes a handful of registers in the sampling clock buffer to configure the sampling clock input. The block asserts an "invalid" output to hold the rest of the FPGA design in reset until its register writes are complete. The "at boot" logic uses the 200MHz oscillator on WARP v3, which is always available (even when the rest of the FPGA design uses an off-board clock).

The w3_clock_controller at boot logic uses the two switches on the CM-MMCX to select the clock mode. When both switches are down (logic 0) the off-board sampling clock will be selected. All other switch settings will use the on-board sampling clock. User software can interpret the other switch states as desired (i.e. to select on/off board RF reference clock, to en/disable CM-MMCX clock outputs, etc.).

Usage

An important factor in configuring the WARP v3 clock buffers is whether the FPGA logic implementing the w3_clock_controller core is itself clocked by the sampling clock. If so, it is critical the properties of the AD9512->FPGA clock are not changed by user code at run-time. All other outputs from the AD9512 buffers can be changed as needed by user code.

The w3_clock_controller driver provides functions to configure the AD9512 output dividers, thereby configuring the frequency of the clocks feeding the RF interface AD9963 chips (the ADC/DAC chips). It is critical that the AD9512->AD9963 clock frequency be consistent with all other rates in the FPGA->DAC and ADC->FPGA interfaces. The combination of AD9963 clock settings (DLL state, ADC/DAC clock source, etc.), AD9963 filter settings (interpolation/decimation rates), AD9512 dividers and internal FPGA->w3_ad_bridge clock connections must all agree. Refer to the WARP v3 User Guide RF section for more details and examples of valid AD9512/AD9963/FPGA configurations.

The MHS snippet below shows a typical use of the w3_clock_controller (taken from the OnBoardPeriphs template project).

BEGIN w3_clock_controller
 PARAMETER INSTANCE = w3_clock_controller_0
 PARAMETER HW_VER = 3.01.b
 PARAMETER C_BASEADDR = 0xc0400000
 PARAMETER C_HIGHADDR = 0xc040ffff
 BUS_INTERFACE SPLB = plb_primary
#AD9512 SPI pins
 PORT rfref_spi_cs_n = clk_rfref_spi_cs_n
 PORT samp_spi_cs_n = clk_samp_spi_cs_n
 PORT samp_spi_mosi = clk_samp_spi_mosi
 PORT rfref_spi_mosi = clk_rfref_spi_mosi
 PORT samp_spi_sclk = clk_samp_spi_sclk
 PORT rfref_spi_sclk = clk_rfref_spi_sclk
 PORT samp_spi_miso = clk_samp_spi_miso
 PORT rfref_spi_miso = clk_rfref_spi_miso
#At boot ports
 PORT at_boot_clk_in = clk_200MHz #always-running clock
 PORT at_boot_clk_in_valid = clk_gen_1_locked #valid indicator for at_boot_clk_in (when sourced from MMCM)
 PORT at_boot_config_sw = cm_mmcx_sw #CM-MMCX SIP switches
 PORT at_boot_clkbuf_clocks_invalid = mmcm_inputs_invalid #reset output
#Software-readable input for user applications
 PORT usr_status = net_gnd
END

Source

The full hardware and software source code is available in the repository: PlatformSupport/CustomPeripherals/pcores/w3_clock_controller_v3_01_b. The VHDL, Verilog and C source code are made available under the WARP license.

Attachments (8)

Download all attachments as: .zip