9 | | == Hardware == |
| 7 | == Overview == |
| 8 | |
| 9 | Clock configuration in a WARP v3 FPGA design occurs in three stages: |
| 10 | 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 |
| 11 | 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 |
| 12 | 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 |
| 13 | |
| 14 | The sections below describe these three stages in detail. |
| 15 | |
| 16 | === Pre-Boot Configuration === |
| 17 | |
| 18 | In a typical FPGA design for WARP v3 most of the FPGA logic is clocked synchronous to the digital I/Q signals for the RF interfaces. This is true for both the [wiki:802.11 802.11 Reference Design] and [wiki:WARPLab 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. |
| 19 | |
| 20 | PicoBlaze pseudo code: |
| 21 | {{{#!C |
| 22 | main() { |
| 23 | |
| 24 | if(no_clock_module_mounted) { |
| 25 | load_configuration(CFG_NOCM) |
| 26 | config_complete() |
| 27 | } |
| 28 | |
| 29 | if(cm_mmcx_mounted) { |
| 30 | sw = read_cm_mmcx_sip_sw() //Read SIP switch |
| 31 | |
| 32 | if(sw == off_off) { |
| 33 | //Up-Up switches -> ignore clock module |
| 34 | load_configuration(CFG_NOCM) |
| 35 | } else if(sw == off_on) { |
| 36 | //Up-Down switches -> Config A |
| 37 | load_configuration(CFG_CMMMCX_A) |
| 38 | } else if(sw == on_off) { |
| 39 | //Down-Up switches -> Config B |
| 40 | load_configuration(CFG_CMMMCX_B) |
| 41 | } else if(sw == on_on) { |
| 42 | //Down-Up switches -> Config C |
| 43 | load_configuration(CFG_CMMMCX_C) |
| 44 | } |
| 45 | |
| 46 | config_complete() |
| 47 | } |
| 48 | |
| 49 | if(cm_pll_mounted) { |
| 50 | sw = read_cm_pll_dip_sw() //Read 2 LSB of DIP switch |
| 51 | |
| 52 | if(sw == off_off) { |
| 53 | //Down-Down switches -> ignore clock module |
| 54 | load_configuration(CFG_NOCM) |
| 55 | config_complete() |
| 56 | } |
| 57 | |
| 58 | wait_for_pll_refclk() |
| 59 | |
| 60 | if(sw == off_on) { |
| 61 | //Down-Up switches -> Config A |
| 62 | load_configuration(CFG_CMPLL_A) |
| 63 | } else if(sw == on_off) { |
| 64 | //Up-Down switches -> Config B |
| 65 | load_configuration(CFG_CMPLL_B) |
| 66 | } else if(sw == on_on) { |
| 67 | //Up-Up switches -> Config C |
| 68 | load_configuration(CFG_CMPLL_C) |
| 69 | } |
| 70 | |
| 71 | wait_for_pll_lock() |
| 72 | |
| 73 | config_complete() |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | wait_for_pll_refclk() { |
| 78 | while(read_pll_refclk_status != TOGGLING) {} |
| 79 | } |
| 80 | |
| 81 | wait_for_pll_lock() { |
| 82 | while(read_pll_lock_status != LOCKED) {} |
| 83 | } |
| 84 | |
| 85 | config_complete() { |
| 86 | clear_mmcm_reset() //Starts clocks to FPGA, allows MicroBlaze subsystem to boot |
| 87 | halt() |
| 88 | } |
| 89 | |
| 90 | }}} |
| 91 | |
| 92 | == Post-Configuration == |