前面讲到每个profile由16个8bit寄存器组成,TX和RX的定义是一样的,下面列出RX profile每个寄存器的定义:
REG0 ~ REG4以及REG12[3:0]实际上是3个参数,lo_int( Integer Word),lo_frac(Fractional Word),lo_div(VCO Divider),射频频率计算公式如下:
freq=REF_PLL*(lo_int+lo_frac/8388593)/(2**(lo_div+1))
其中freq指工作的射频频率,REF_PLL指PLL的参考时钟(并非芯片输入时钟),REF_PLL确定后,lo_int和lo_frac决定VCO的频率,而射频工作频率由VCO/lo_div而来。另外一个约束条件是,VCO的工作频率必须在6G~12G之间,根据以上约束条件,一旦知道了射频频率,就可以计算出所有参数。
除REG12[3:0]和VCO_Varactor_Reference_Tcf(固定设置为7就可以了)以外,REG5 ~ REG13的其他参数都是通过查表获得。表中一共有53行,每行对应一个最佳性能的VCO Freqency。当你的VCO Frequency大于某行的VCO Frequency而小于上一行的VCO Frequency时,当前这行就是你要用的参数行。拿到参数后,按照寄存器定义,将参数填到这些寄存器对应的位置即可。
REG14,REG15是VCO校准的结果,当校准完成后,芯片会自动将校准结果填到这两个寄存器中。下面提供一个python程序,根据射频频率(起始频率,步进,结束频率),自动计算出每个频点应该设置的寄存器值
#!python3
import sys
import os
import shutil
import re
import openpyxl
#you should modify parameters below according to your design
#############################################################
START_FREQ=500000000 #hop start freqeuncy
END_FREQ=600000000 #hop end freqeuncy
STEP_FREQ=10000000 #hop resolution
REFIN=40000000 #clock input to chip pin
REFSCALE=2 #Ref Divider,only 1,0.5,0.25,2 allowd
sheet_name='FDD_80M'
REFCLK=REFIN*REFSCALE
#############################################################
#function definition
def freq_param_get(refclk,freq):
lo_div=0
lo_int=0
lo_frac=0
if freq>6000000000 or freq<46875000:
return None
freq_tmp=freq
while freq_tmp<6000000000:
freq_tmp=freq_tmp*2
lo_div=lo_div+1
lo_div=lo_div-1;
mult_int_result=freq_tmp*int(2**64/refclk)
lo_int=int(mult_int_result/(2**64))
lo_frac=int(8388593*(freq_tmp/refclk-lo_int)+0.5)#4舍5入
if lo_frac>=8388593:
lo_frac=lo_frac-8388593
lo_int=lo_int+1
lo_freq=int(refclk*(lo_int+lo_frac/8388593)/(2**(lo_div+1))+0.5)
vco_freq=int(lo_freq*(2**(lo_div+1))+0.5)
return [lo_div,lo_int,lo_frac,lo_freq,vco_freq]
def loop_param_get(freq_param,loop_refer):
vco_freq=freq_param[4]
for i in range(len(loop_refer)):
if vco_freq<loop_refer[i][4] and vco_freq>=loop_refer[i+1][4]:
loop_param_index=loop_refer[i+1][3]-1
loop_param=loop_refer[loop_param_index]
return loop_param
###############################################################
#读取参数文件,将参数文件的内容转换为列表
workbook=openpyxl.load_workbook('ad9361_loop_reference_v3.xlsx')
sheet=workbook[sheet_name]
loop_refer=[]
for row in range(2,55):
tmp_list=[]
for column in range(1,19):
tmp_list.append(sheet.cell(row=row,column=column).value)
loop_refer.append(tmp_list)
freq=START_FREQ
while freq<=END_FREQ:
freq_param=freq_param_get(REFCLK,freq)
lo_div=freq_param[0]
lo_int=freq_param[1]
lo_frac=freq_param[2]
lo_freq=freq_param[3]
vco_freq=freq_param[4]
loop_param=loop_param_get(freq_param,loop_refer)
VCO_Bias_Ref=loop_param[8]
VCO_Varactor=loop_param[7]
VCO_Bias_Tcf=loop_param[9]
Charge_Pump_Current=loop_param[12]
Charge_Pump_Current_Init=Charge_Pump_Current
Loop_Filter_R3=loop_param[17]
Loop_Filter_R3_Init=Loop_Filter_R3
Loop_Filter_C3=loop_param[16]
Loop_Filter_C3_Init=Loop_Filter_C3
Loop_Filter_C1=loop_param[14]
Loop_Filter_C2=loop_param[13]
Loop_Filter_R1=loop_param[15]
Loop_Filter_R1_Init=Loop_Filter_R1
VCO_Varactor_Reference_Tcf=7
Rx_VCO_Divider=lo_div
VCO_Cal_Offset=loop_param[10]
VCO_Varactor_Reference=loop_param[11]
REG0=lo_int&0xff
REG1=(lo_div>>8)&0xff
REG2=lo_frac&0xff
REG3=(lo_frac>>8)&0xff
REG4=(lo_frac>>16)&0xff
REG5=(VCO_Bias_Ref<<4)+VCO_Varactor
REG6=(VCO_Bias_Tcf<<6)+Charge_Pump_Current_Init
REG7=Charge_Pump_Current
REG8=(Loop_Filter_R3<<4)+Loop_Filter_R3_Init
REG9=(Loop_Filter_C3<<4)+Loop_Filter_C3_Init
REG10=(Loop_Filter_C1<<4)+Loop_Filter_C2
REG11=(Loop_Filter_R1<<4)+Loop_Filter_R1_Init
REG12=(VCO_Varactor_Reference_Tcf<<4)+Rx_VCO_Divider
REG13=(VCO_Cal_Offset<<4)+VCO_Varactor_Reference
REG14=0x00
REG15=0x00
reg_map=[REG0,REG1,REG2,REG3,REG4,REG5,REG6,REG7,REG8,REG9,REG10,REG11,REG12,REG13,REG14,REG15]
print_result=1
if print_result:
reg_map.reverse()
for i in reg_map:
print('%02X'%i,end='')
print('')
reg_map.reverse()
freq=freq+STEP_FREQ
sys.exit()
打印的结果是这样的,一共128bit,用16进制显示。
注意下,我这里是将SynthLUT_80_FDD_v3.txt等6个txt文件写到excel表格中方便python程序调用。
上面的python代码需要有对应的verilog代码才能在FPGA上实现,读者可以根据python的流程自己写一下。下章节讲解如何具体将这些寄存器写到芯片,并开启校准获得校准结果