高速FPGA串并收发器SERDES实现ADS6445的AD转换
在使用TI公司四通道、14Bit、最大速率125M的ADS6445。利用Xilinx V5系列器件的串行收发控制器ISERDES的原语来实现数据的接收。
(1)ADS6445基础知识和配置
ADS6445是一款很强大的AD转换芯片。最高支持125M采样速率,共有四个采样通道,模拟输入支持LVCMOS, LVPECL, LVDS时钟输入。芯片输入差分时钟作为芯片的主时钟。通过芯片内部PLL进行倍频输出数据时钟和帧时钟。模拟参考电压VCM作为模数转换的基准。
芯片的结构框图如下图所示。
ADS6445有多种输出模式,需要对芯片寄存器进行配置。根据系统需要我配置为DDR输出2-Wire Interface 16×Serialization模式输出。配置寄存器如下图所示。
由于单个芯片需要八路串转并,并且单路输入位宽为8位,所有每路需要2个ISERDES并联使用组成一个8位位宽的串并转换,并且四路模拟信号需要同步,因此实现ADS6445芯片的数据采集需要充分的了解ISERDES。
(2)SERDES原语的基础知识
SERDES是高速串行转换器。分为ISERDES和OSERDES。下面以ISERDES原语为例进行说明。
genvar i ;
generate for(i=0;i<8;i=i+1)begin:iserdes_data
ISERDES #(
.BITSLIP_ENABLE(“TRUE”), // “TRUE”/“FALSE”
to enable bitslip controller
// Must be"FALSE" if INTERFACE_TYPE set to "MEMORY"
.DATA_RATE(“DDR”), // Specify data rate of “DDR” or"SDR"
.DATA_WIDTH(8), // Specify data width - for DDR 4,6,8, or 10
// for SDR 2,3,4,5,6,7, or 8
.INTERFACE_TYPE(“NETWORKING”), //Use model-“MEMORY"or"NETWORKING”
.IOBDELAY(“NONE”), // Specify outputs where delay chain will be applied
// “NONE”, “IBUF”, “IFD”, or “BOTH”
.IOBDELAY_TYPE(“DEFAULT”), //Set tap delay"DEFAULT", “FIXED”, or “VARIABLE”
.IOBDELAY_VALUE(0), // Set initial tap delay to an integer from 0 to 63
.NUM_CE(2), // Define number or clock enables to an integer of 1 or 2
.SERDES_MODE(“MASTER”) // Set SERDES mode to “MASTER” or “SLAVE”
)
ISERDES_a_master (
.O(), // 1-bit combinatorial output
.Q1(data_chan_l[8*i+0]), // 1-bit registered output
.Q2(data_chan_l[8*i+1]), // 1-bit registered output
.Q3(data_chan_l[8*i+2]), // 1-bit registered output
.Q4(data_chan_l[8*i+3]), // 1-bit registered output
.Q5(data_chan_l[8*i+4]), // 1-bit registered output
.Q6(data_chan_l[8*i+5]), // 1-bit registered output
.SHIFTOUT1(shiftout1[i]), // 1-bit carry output
.SHIFTOUT2(shiftout2[i]), // 1-bit carry output
.BITSLIP(data_bit_slip), // 1-bit Bitslip input
.CE1(1’b1), // 1-bit clockenable input
.CE2(1’b1), // 1-bit clock enable input
.CLK(data_clk_buf), //1-bit clock input
.CLKDIV(clk_div), // 1-bitdivided clock input
.D(data_pin[i]), // 1-bit serial data input
.DLYCE(1’b0), // 1-bit delay chain enable input
.DLYINC(1’b0), // 1-bit delay increment/decrement input
.DLYRST(1’b0), // 1-bit delay chain reset input
.OCLK(1’b0), // 1-bit high-speed clock input
.REV(1’b0), // Must be tied to logic zero
.SHIFTIN1(1’b0), // 1-bit carry input
.SHIFTIN2(1’b0), // 1-bit carry input
.SR(~cfg_done_r) // 1-bit set/reset input
);
ISERDES #(
.BITSLIP_ENABLE(“TRUE”), // “TRUE”/“FALSE” to enable bitslip controller
//Must be"FALSE"if INTERFACE_TYPE set to "MEMORY"
.DATA_RATE(“DDR”), // Specify data rate of “DDR” or"SDR"
.DATA_WIDTH(8), // Specify data width - for DDR 4,6,8, or 10
// for SDR 2,3,4,5,6,7, or 8
.INTERFACE_TYPE(“NETWORKING”), // Use model -“MEMORY” or “NETWORKING”
.IOBDELAY(“NONE”), // Specify outputs where delay chain will be applied
// "NONE", "IBUF", "IFD", or "BOTH"
.IOBDELAY_TYPE(“DEFAULT”), // Set tap delay
“DEFAULT”, “FIXED”, or “VARIABLE”
.IOBDELAY_VALUE(0), // Set initial tap delay to an integer from 0 to 63
.NUM_CE(2), // Define number or clock enables to an integer of 1 or 2
.SERDES_MODE(“SLAVE”) // Set SERDES mode to “MASTER” or “SLAVE”
)
ISERDES_a_slave (
.O(), // 1-bit combinatorial output
.Q1(), // 1-bit registered output
.Q2(), // 1-bit registered output
.Q3(data_chan_l[8*i+6]), // 1-bit registered output
.Q4(data_chan_l[8*i+7]), // 1-bit registered output
.Q5(), // 1-bit registered output
.Q6(), // 1-bit registered output
.SHIFTOUT1(), // 1-bit carry output
.SHIFTOUT2(), // 1-bit carry output
.BITSLIP(data_bit_slip), // 1-bit Bitslip input
.CE1(1’b1), // 1-bit clock enable input
.CE2(1’b1), // 1-bit clock enable input
.CLK(data_clk_buf), //1-bit clock input
.CLKDIV(clk_div), // 1-bit divided clock input
.D(), // 1-bit serial data input
.DLYCE(1’b0), // 1-bit delay chain enable input
.DLYINC(1’b0), // 1-bit delay increment/decrement input
.DLYRST(1’b0), // 1-bit delay chain reset input
.OCLK(1’b0), // 1-bit high-speed clock input
.REV(1’b0), // Must be tied to logic zero
.SHIFTIN1(shiftout1[i]), // 1-bit carry input
.SHIFTIN2(shiftout2[i]), // 1-bit carry input
.SR(~cfg_done_r) // 1-bit set/reset input
);
end
endgenerate
两块ISERDES进行级联时原语使用如上面代码。而ISERDES基元框图如下图所示:
在了解了这些基础的ISERDES结构和各个端口的含义后需要特别注意的就是ISERDES的时钟输入和输出处理。ADS6445的时钟输出分为帧时钟和数据时钟,输出时序如下图:
利用FPGA的差分IO作为时钟的输入端,这里利用输入的数据时钟通过IBUFDS把差分时钟转为单端时钟输出,然后利用缓冲BUFIO来对输入时钟进行一级缓冲,然后作为作为ISERDES的CLK时钟,由于ADS6445输出的帧时钟与数据时钟存在着相位差,因此利用数据时钟通过BUFR来4分频作为CLKDIV的时钟,CLK和CLKDIV的输入相位必须是严格对齐的,CLK和OCLK之间不要求相位关系。这样一片ADC的四路模拟信号的16个ISERDES模块就有了相同的时钟。
由于采用4路模拟信号同时进行采用,这里ISERDES并行使用种需要做到同步,数据同步调整是通过Bitslip位来进行的,若超过N次Bitslip依然同步失败,则表示数据异常。而Bitslip位同步是利用ADS6445输出的帧时钟来进行的。把帧时钟作为ISERDES的数据输入,通过判断输出是否为8’hf0来判断信号是否同步,如果同步置Bitslip位为0,如果不同步置Bitslip位1,若超过N次Bitslip依然同步失败,则表示数据异常。然后通过复位ADS6445芯片的时钟,重新配置芯片,然后继续配置同步,直至同步为止。