AD9371 系列快速入口
AD9371+ZCU102 移植到 ZCU106 : AD9371 官方例程构建及单音信号收发
ad9371_tx_jesd -->util_ad9371_xcvr接口映射: AD9371 官方例程之 tx_jesd 与 xcvr接口映射
AD9371 官方例程 时钟间的关系与生成 : AD9371 官方例程HDL详解之JESD204B TX侧时钟生成(一)
JESD204B相关IP端口信号 : AD9371 官方例程HDL JESD204B相关IP端口信号
裸机程序配置 AD9528、AD9371、FPGA IP 和主函数梳理: AD9371 官方例程裸机SW 和 HDL配置概述(一)
文章目录
- 前言
- clkgen
- tx_jesd/axi 、rx_jesd/axi 配置 链路层 IP
- tx_xcvr 和 rx_xcvr 配置 物理层 xcvr
- tpl_core 传输层
- axi_ad9371_tx_xcvr 物理层配置
前言
SDK或者vitis 裸机程序需要配置 AD9528、AD9371、FPGA相关IP等,根据自己项目需求,可以通过 MATLAB Profile Generator 和 Transceiver Evaluation Software 生成所需的 myk.c, myk.h and myk_ad9528init.c 文件来替换, FPGA中 ip核相应配置和SW中的设置也需相应修改
clkgen
struct axi_clkgen_init rx_clkgen_init = {
"rx_clkgen",
RX_CLKGEN_BASEADDR,
clockAD9528_device->outputSettings->outFrequency_Hz[1]
};
struct axi_clkgen_init tx_clkgen_init = {
"tx_clkgen",
TX_CLKGEN_BASEADDR,
clockAD9528_device->outputSettings->outFrequency_Hz[1]
};
struct axi_clkgen_init rx_os_clkgen_init = {
"rx_os_clkgen",
RX_OS_CLKGEN_BASEADDR,
clockAD9528_device->outputSettings->outFrequency_Hz[1]
};
后续生成目标时钟(link clk)频率,9528 OUT1( outFrequency_Hz[1] )接入FPGA
axi_clkgen_init(&tx_clkgen, &tx_clkgen_init);
axi_clkgen_set_rate(tx_clkgen, tx_div40_rate_hz);
根据采样率,M ,L, 计算 lane rate ,生成 LINK 时钟
tx_lane_rate_khz = iqRate_kHz *M * (20 / L)
tx_div40_rate_hz = tx_lane_rate_khz * (1000 / 40);
tx_jesd/axi 、rx_jesd/axi 配置 链路层 IP
2T2R,RX中,F=4,K=32;
struct jesd204_rx_init rx_jesd_init = {
"rx_jesd",
RX_JESD_BASEADDR,
4,
32,
1,
rx_div40_rate_hz / 1000,
rx_lane_rate_khz
};
struct jesd204_tx_init tx_jesd_init = {
"tx_jesd",
TX_JESD_BASEADDR,
2,
32,
4,
14,
16,
false,
2,
1,
tx_div40_rate_hz / 1000,
tx_lane_rate_khz
};
2T2R,TX中,F=2,K=32,M=4, N=14 (后续未传递给FPGA 寄存器使用) ,NP=16 ,HD=0, CS=2
tx_xcvr 和 rx_xcvr 配置 物理层 xcvr
struct adxcvr_init rx_adxcvr_init = {
.name = "rx_adxcvr",
.base = RX_XCVR_BASEADDR,
.sys_clk_sel = ADXCVR_SYS_CLK_CPLL,
.out_clk_sel = ADXCVR_REFCLK,
.lpm_enable = 1,
.lane_rate_khz = rx_lane_rate_khz,
.ref_rate_khz = mykDevice.clocks->deviceClock_kHz,
};
struct adxcvr_init tx_adxcvr_init = {
.name = "tx_adxcvr",
.base = TX_XCVR_BASEADDR,
// TXPLLCLKSEL; TXSYSCLKSEL (tx_sys_clk_sel[1] == 0) ? 2'b00 : {1'b1,~up_tx_sys_clk_sel[0]};
.sys_clk_sel = ADXCVR_SYS_CLK_QPLL0,
// TXOUTCLKSEL
.out_clk_sel = ADXCVR_REFCLK,
.lpm_enable = 0,
.lane_rate_khz = tx_lane_rate_khz,
.ref_rate_khz = mykDevice.clocks->deviceClock_kHz,
};
SYS_CLK 和 OUT_CLK 选择如下表所示,TX选择QPLL0提供高速串行时钟,RX均衡模式选取 LPM
tpl_core 传输层
SW
struct axi_dac_init tx_dac_init = {
"tx_dac",
TX_CORE_BASEADDR,
4,
NULL,
3
};
struct axi_adc_init rx_adc_init = {
"rx_adc",
RX_CORE_BASEADDR,
4
};
4,num_channels,M
3,3未用到,2T2R,rate = 32 * L / M / NP = 2; 后续通过 axi_dac_read(dac, AXI_DAC_REG_CLK_RATIO, &ratio) 获得,dac->clock_hz = freq * ratio。 100M 时钟基准计数 2^16,得到 link clk的计数值 freq,DAC CLK = ratio * LINK CLK
LINK clock_hz = freq * 100M / 2^16 = freq *390625/ 2^8 = freq * 1525.8789,dac->clock_hz = LINK clock_hz *ratio
freq基于100Mhz axi_clk测量,有一定的抖动,会有一些误差,只是为了调试目的。
FPGA
HDL 传输层 TX 配置为 L=4, M=4, N=16 (DAC 14 BIT, 设置16,高14位有效,tx_jesd_init 中是14,但后续驱动未配置到链路层 ip中,以传输层HDL配置为准), NP=16, S=1, OCTETS_PER_BEAT= 4 或 8 ,8b/10b 为 4, RX 和 RX_OS 与TX类似
axi_ad9371_tx_xcvr 物理层配置
复位时赋的初始值,后续给到 Channel 和 COMMON 端口
if (up_rstn == 0) begin
up_lpm_dfe_n <= LPM_OR_DFE_N;
up_rate <= RATE;
up_sys_clk_sel <= SYS_CLK_SEL;
up_out_clk_sel <= OUT_CLK_SEL;
up_tx_diffctrl <= TX_DIFFCTRL;
up_tx_postcursor <= TX_POSTCURSOR;
up_tx_precursor <= TX_PRECURSOR;
end else begin
if ((up_wreq == 1'b1) && (up_waddr == 10'h008)) begin
up_lpm_dfe_n <= up_wdata[12];
up_rate <= up_wdata[10:8];
up_sys_clk_sel <= up_wdata[5:4];
up_out_clk_sel <= up_wdata[2:0];
end
。。。。
struct adxcvr_init tx_adxcvr_init = {
.name = "tx_adxcvr",
.base = TX_XCVR_BASEADDR,
// TXPLLCLKSEL; TXSYSCLKSEL (tx_sys_clk_sel[1] == 0) ? 2'b00 : {1'b1,~up_tx_sys_clk_sel[0]};
.sys_clk_sel = ADXCVR_SYS_CLK_QPLL0,
// TXOUTCLKSEL
.out_clk_sel = ADXCVR_REFCLK,
.lpm_enable = 0,
.lane_rate_khz = tx_lane_rate_khz,
.ref_rate_khz = mykDevice.clocks->deviceClock_kHz,
};
可以通过 adxcvr_init(&tx_adxcvr, &tx_adxcvr_init) ,使用 tx_adxcvr_init 更改sys_clk_sel 等配置,最终通过信号up_ch_sys_clk_sel 传递给 物理层 util_ad9371_xcvr IP, RX 和 RX_OS 类似
LPM_OR_DFE_N :1, LPM ; 0, DFE,RX有效,配置均衡模式。
OUT_CLK_SEL : 选择 TXOUTCLK 来源
SYS_CLK_SEL :选择TXPLL参考时钟来源
QPLL_ENABLE :1 使能,在QUAD中使用QPLL
RATE :设置TXRATE,配置 GTH原语.TXRATE (tx_rate_m2),通过 TXOUT_DIV 和 TXRATE 可以控制 D divider的值 ,例程采用 通过设置 Attribute 方案,需要把 TXRATE 绑定到 3’b000,可知在IP核配置和SW驱动中,TXRATE 都设置成 3’b000,D divider 通过 DRP 配置 TXOUT_DIV 参数修改,SW驱动使用 xilinx_xcvr_drp_update(xcvr, drp_port, 0x7c, 0x700,xilinx_xcvr_out_div_to_val(tx_out_div) << 8);
TX_OR_RX_N : 1 配置链路为TX ,0 配置为 RX
TX_DIFFCTRL :Driver Swing Control, 配置 GTH原语 .TXDIFFCTRL ({up_tx_diffctrl, 1’b0}),TXDIFFCTRL[0]不用
TX_POSTCURSOR :5’b00000,post-cursor ,配置 GTH原语 .TXPOSTCURSOR (up_tx_postcursor)
TX_PRECURSOR :5’b00000,pre-cursor ,配置 GTH原语 .TXPRECURSOR (up_tx_precursor)
XCVR_TYPE:GT类型,ZCU106 是 GTHE4
TX Configurable Driver
• Differential voltage control
• Pre-cursor and post-cursor transmit pre-emphasis
TX_POSTCURSOR 、TX_PRECURSOR 、TX_DIFFCTRL 属于GTH TX Configurable Driver ,例程使用IP默认的初始配置,未在SW驱动中修改这几个配置端口,使用具体配置 详见 UG576 第三章 TX Configurable Driver
util_ad9371_xcvr 见下一节