1、程序框架
主要module有:
1)ad9253_lvds_top.v,顶层模块;
2)ad9253_lvds_iobuffer.v,IO缓冲模块;
3)ad9253_lvds_clock.v,采样clock生成模块;
4)ad9253_lvds_frame.v,帧同步模块;
5)ad9253_lvds_data.v,数据采集模块。
2、ISERDES2原语介绍
接之前博文所述,LVDS串行接口在FPGA中实际上要进行的就是并串转换,核心模块即为ISERDES2,下面该原语接口功能和配置进行简单介绍。
上图为ISERDES2使用时的原语框图,使用时可以在Vivado中获取原语模板如下图所示:
ISERDESE2 #(
.DATA_RATE("DDR"), // DDR, SDR
.DATA_WIDTH(4), // Parallel data width (2-8,10,14)
.DYN_CLKDIV_INV_EN("FALSE"), // Enable DYNCLKDIVINVSEL inversion (FALSE, TRUE)
.DYN_CLK_INV_EN("FALSE"), // Enable DYNCLKINVSEL inversion (FALSE, TRUE)
// INIT_Q1 - INIT_Q4: Initial value on the Q outputs (0/1)
.INIT_Q1(1'b0),
.INIT_Q2(1'b0),
.INIT_Q3(1'b0),
.INIT_Q4(1'b0),
.INTERFACE_TYPE("MEMORY"), // MEMORY, MEMORY_DDR3, MEMORY_QDR, NETWORKING, OVERSAMPLE
.IOBDELAY("NONE"), // NONE, BOTH, IBUF, IFD
.NUM_CE(2), // Number of clock enables (1,2)
.OFB_USED("FALSE"), // Select OFB path (FALSE, TRUE)
.SERDES_MODE("MASTER"), // MASTER, SLAVE
// SRVAL_Q1 - SRVAL_Q4: Q output values when SR is used (0/1)
.SRVAL_Q1(1'b0),
.SRVAL_Q2(1'b0),
.SRVAL_Q3(1'b0),
.SRVAL_Q4(1'b0)
)
ISERDESE2_inst (
.O(O), // 1-bit output: Combinatorial output
// Q1 - Q8: 1-bit (each) output: Registered data outputs
.Q1(Q1),
.Q2(Q2),
.Q3(Q3),
.Q4(Q4),
.Q5(Q5),
.Q6(Q6),
.Q7(Q7),
.Q8(Q8),
// SHIFTOUT1, SHIFTOUT2: 1-bit (each) output: Data width expansion output ports
.SHIFTOUT1(SHIFTOUT1),
.SHIFTOUT2(SHIFTOUT2),
.BITSLIP(BITSLIP), // 1-bit input: The BITSLIP pin performs a Bitslip operation synchronous to
// CLKDIV when asserted (active High). Subsequently, the data seen on the Q1
// to Q8 output ports will shift, as in a barrel-shifter operation, one
// position every time Bitslip is invoked (DDR operation is different from
// SDR).
// CE1, CE2: 1-bit (each) input: Data register clock enable inputs
.CE1(CE1),
.CE2(CE2),
.CLKDIVP(CLKDIVP), // 1-bit input: TBD
// Clocks: 1-bit (each) input: ISERDESE2 clock input ports
.CLK(CLK), // 1-bit input: High-speed clock
.CLKB(CLKB), // 1-bit input: High-speed secondary clock
.CLKDIV(CLKDIV), // 1-bit input: Divided clock
.OCLK(OCLK), // 1-bit input: High speed output clock used when INTERFACE_TYPE="MEMORY"
// Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock inversion pins to switch clock polarity
.DYNCLKDIVSEL(DYNCLKDIVSEL), // 1-bit input: Dynamic CLKDIV inversion
.DYNCLKSEL(DYNCLKSEL), // 1-bit input: Dynamic CLK/CLKB inversion
// Input Data: 1-bit (each) input: ISERDESE2 data input ports
.D(D), // 1-bit input: Data input
.DDLY(DDLY), // 1-bit input: Serial data from IDELAYE2
.OFB(OFB), // 1-bit input: Data feedback from OSERDESE2
.OCLKB(OCLKB), // 1-bit input: High speed negative edge output clock
.RST(RST), // 1-bit input: Active high asynchronous reset
// SHIFTIN1, SHIFTIN2: 1-bit (each) input: Data width expansion input ports
.SHIFTIN1(SHIFTIN1),
.SHIFTIN2(SHIFTIN2)
);
根据原语模板可以看到其应用需要分别配置端口和属性,下面进行简单介绍。
2.1、ISERDES2原语端口说明·
1、寄存器输出端Q1-Q8
输出端将串行输入数据并行输出,如图所示:
2、组合输出端口O
组合输出端输出可以直接输出输入端数据D或者来自IDELAY模块数据DDLY。
3、位宽扩展端口SHIFTOUT1和SHIFTOUT2,SHIFTIN1和SHIFTIN2
当输入串行数据位宽超过8Bit时,为了进行串并转换,可以通过将两个ISERDES2模块设置成主从方式并联起来,实现1:10位或1:14位(只适用于DDR模式),如下图所示:
两个模块通过位宽扩展端口进行连接。
4、串行数据输入端口D和DDLY
端口D输入的数据来自IOB,即为ADC数据引脚,端口DDLY输入的数据来自IDELAY模块进行延时后数据。
5、时钟输入端CLK和CLKB
随路时钟输入,一般为DCO经过IDELAY模块产生的IntBitclk,CLKB为其反相输入。
6、时钟使能端CE1和CE2
使能输入的CLK和CLKB。
7、复位引脚RST
复位ISERDES2模块,高电平使能。
8、分频时钟输入端CLKDIV和CLKDIVP
此时钟作为Frame信号,确定数据转换的起始位置,一般为IntBitclk分频而来的CLK。
9、高速时钟输入端OCLK和OCLKB
这个时钟来自Memory。
10、Bitslip引脚
对采样数据进行移位,从而实现数据对齐,经过IDELAY模块生成的BitClk_MonClkin和BitClk_RefClkin与DATA之间存在延时,为此通过采集FCO并进行移位消除延时影响。Bitslip操作在DDR和SDR模式下有区别,如下图所示:
在SDR模式中,每次Bitslip操作都会导致输出数据向左偏移一位,例如0x1001_0111_1011经过Bitslip变成0x0010_1111_0111;
在DDR模式中,每次Bitslip操作都会导致输出数据交替进行右移一位和左移三位,如下图所示:
11、反馈输入端OFB
来自OLOGIC2、OLOGIC3和OSERDES2的输出反馈脚
12、动态设置时钟反相端DYNCLKDIVSEL和DYNCLK
此端口可以对输入时钟进行反相操作。
2.2、ISERDES2原语属性说明·
1、数据速率属性DATA_RATE
可选择DDR模式或SDR模式
2、数据位宽属性DATA_WIDTH
数据位宽可设置如下表所示,当位宽超过8位时,需要进行ISERDESE2扩展
3、动态时钟反转使能属性DYN_CLK_INV_EN和DYN_CLKDIV_INV_EN
对时钟进行反转,可选择TRUE or FALSE
4、接口类型属性INTERFACE_TYPE
可选择存储器类型或NETWORKING,对于ADC信号应用的是NETWORKING
5、使能时钟数量NUM_EN
当选择1时,只需要输入CLK,当选择2时,输入CLK和CLKB
6、使能反馈路径OFB_USED
TRUE or FALSE
7、ISERDESE2模式属性SERDES_MODE
当使用扩展时,SERDES模块的属性可选择为主模式或从模式
8、采样初始值设置INIT_Q1,INIT_Q2,INIT_Q3,INIT_Q4;SRVAL_Q1,SRVAL_Q2,SRVAL_Q3,SRVAL_Q4
一般初始化为0
9、选择D或DDLY作为输入IOBDELAY
D和DDLY引脚是ISERDESE2的专用输入。D输入是直接连接到IOB,DDLY引脚直接连接到IDELAYE2。ADC数据输入由D进行输入。
3、采样clock程序设计
BitClk由DCO经IDELAY2模块而来,经IBUFIO缓冲作为采样clock,经BUFR进行分频得到同步clock
时序如下:
代码模块如下:
module ad9253_lvds_clock #(
parameter C_StatTaps = 5'd15
)
(
input SysRefClk,
input BitClk,
input BitClkRst,
input BitClk_MonClkIn,
input BitClk_RefClkIn,
output BitClkDone,
output BitClk_MonClkOut,
output BitClk_RefClkOut
);
wire IntBitClk;
wire [7:0] allign_word;
//IDELAY
(* IODELAY_GROUP = "DELAY1" *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL
IDELAYE2 #(
.CINVCTRL_SEL("FALSE"), // Enable dynamic clock inversion (FALSE, TRUE)
.DELAY_SRC("IDATAIN"), // Delay input (IDATAIN, DATAIN)
.HIGH_PERFORMANCE_MODE("TRUE"), // Reduced jitter ("TRUE"), Reduced power ("FALSE")
.IDELAY_TYPE("FIXED"), // FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE
.IDELAY_VALUE(C_StatTaps), // Input delay tap setting (0-31)
.PIPE_SEL("FALSE"), // Select pipelined mode, FALSE, TRUE
.REFCLK_FREQUENCY(200.0), // IDELAYCTRL clock input frequency in MHz (190.0-210.0, 290.0-310.0).
.SIGNAL_PATTERN("CLOCK") // DATA, CLOCK input signal
)
IDELAYE2_inst (
.CNTVALUEOUT(), // 5-bit output: Counter value output
.DATAOUT(IntBitClk), // 1-bit output: Delayed data output
.C(BitClk_RefClkOut), // 1-bit input: Clock input
.CE(1'b0), // 1-bit input: Active high enable increment/decrement input
.CINVCTRL(1'b0), // 1-bit input: Dynamic clock inversion input
.CNTVALUEIN(5'd0), // 5-bit input: Counter value input
.DATAIN(1'b0), // 1-bit input: Internal delay data input
.IDATAIN(BitClk), // 1-bit input: Data input from the I/O
.INC(1'b0), // 1-bit input: Increment / Decrement tap delay input
.LD(BitClkRst), // 1-bit input: Load IDELAY_VALUE input
.LDPIPEEN(1'b0), // 1-bit input: Enable PIPELINE register to load data input
.REGRST(BitClkRst) // 1-bit input: Active-high reset tap-delay input
);
BUFIO BUFIO_inst (
.O(BitClk_MonClkOut), // 1-bit output: Clock output (connect to I/O clock loads).
.I(IntBitClk) // 1-bit input: Clock input (connect to an IBUF or BUFMR).
);
BUFR #(
.BUFR_DIVIDE("3"), // Values: "BYPASS, 1, 2, 3, 4, 5, 6, 7, 8"
.SIM_DEVICE("7SERIES") // Must be set to "7SERIES"
)
BUFR_inst (
.O(BitClk_RefClkOut), // 1-bit output: Clock output port
.CE(1'b1), // 1-bit input: Active high, clock enable (Divided modes only)
.CLR(1'b0), // 1-bit input: Active high, asynchronous clear (Divided modes only)
.I(IntBitClk) // 1-bit input: Clock buffer input driven by an IBUF, MMCM or local interconnect
);
4、帧同步程序设计
帧同步目的在于对齐同步clock和FCO之间的延时,故通过采样clock对FCO进行采集,通过Bitslip操作,将延时进行对齐。ADC输出时序如下图所示:
通过BitClk对FCLK采样后,进行Bitslip操作,当结果等于pattern值时,表示BitClk_RefClkOut与FCO已对齐。下图为代码框架:
代码模块如下:
module ad9253_lvds_frame#(
parameter FrmPattern = 8'b11110000
)
(
input FrmClk,
input FrmClkDiv,
input FrmClk_p,
input FrmClkRst,
input FrmClkDone,
output FrmClkBitSlip_p,
output FrmAlignDone
);
wire [7:0] IntFrmSrdsOutp;
reg FrmClkBitSlip_pout;
//ISERDESE2
ISERDESE2 #(
.DATA_RATE ("DDR"), // DDR, SDR
.DATA_WIDTH (8), // Parallel data width (2-8,10,14)
.DYN_CLKDIV_INV_EN ("FALSE"), // Enable DYNCLKDIVINVSEL inversion (FALSE, TRUE)
.DYN_CLK_INV_EN ("FALSE"), // Enable DYNCLKINVSEL inversion (FALSE, TRUE)
// INIT_Q1 - INIT_Q4: Initial value on the Q outputs (0/1)
.INIT_Q1 (1'b0),
.INIT_Q2 (1'b0),
.INIT_Q3 (1'b0),
.INIT_Q4 (1'b0),
.INTERFACE_TYPE ("NETWORKING"), // MEMORY, MEMORY_DDR3, MEMORY_QDR, NETWORKING, OVERSAMPLE
.IOBDELAY ("NONE"), // NONE, BOTH, IBUF, IFD
.NUM_CE (2), // Number of clock enables (1,2)
.OFB_USED ("FALSE"), // Select OFB path (FALSE, TRUE)
.SERDES_MODE ("MASTER"), // MASTER, SLAVE
// SRVAL_Q1 - SRVAL_Q4: Q output values when SR is used (0/1)
.SRVAL_Q1 (1'b0),
.SRVAL_Q2 (1'b0),
.SRVAL_Q3 (1'b0),
.SRVAL_Q4 (1'b0)
)
ISERDESE2_inst1(
.O (), // 1-bit output: Combinatorial output
// Q1 - Q8: 1-bit (each) output: Registered data outputs
.Q1 (IntFrmSrdsOutp[0]),
.Q2 (IntFrmSrdsOutp[1]),
.Q3 (IntFrmSrdsOutp[2]),
.Q4 (IntFrmSrdsOutp[3]),
.Q5 (IntFrmSrdsOutp[4]),
.Q6 (IntFrmSrdsOutp[5]),
.Q7 (IntFrmSrdsOutp[6]),
.Q8 (IntFrmSrdsOutp[7]),
// SHIFTOUT1, SHIFTOUT2: 1-bit (each) output: Data width expansion output ports
.SHIFTOUT1 (),
.SHIFTOUT2 (),
.BITSLIP (FrmClkBitSlip_pout), // 1-bit input: The BITSLIP pin performs a Bitslip operation synchronous to
// CLKDIV when asserted (active High). Subsequently, the data seen on the Q1
// to Q8 output ports will shift, as in a barrel-shifter operation, one
// position every time Bitslip is invoked (DDR operation is different from
// SDR).
// CE1, CE2: 1-bit (each) input: Data register clock enable inputs
.CE1 (FrmClkDone),
.CE2 (1'b1),
.CLKDIVP (1'b0), // 1-bit input: TBD
// Clocks: 1-bit (each) input: ISERDESE2 clock input ports
.CLK (FrmClk), // 1-bit input: High-speed clock
.CLKB (~FrmClk), // 1-bit input: High-speed secondary clock
.CLKDIV (FrmClkDiv), // 1-bit input: Divided clock
.OCLK (1'b0), // 1-bit input: High speed output clock used when INTERFACE_TYPE="MEMORY"
// Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock inversion pins to switch clock polarity
.DYNCLKDIVSEL (1'b0), // 1-bit input: Dynamic CLKDIV inversion
.DYNCLKSEL (1'b0), // 1-bit input: Dynamic CLK/CLKB inversion
// Input Data: 1-bit (each) input: ISERDESE2 data input ports
.D (FrmClk_p), // 1-bit input: Data input
.DDLY (1'b0), // 1-bit input: Serial data from IDELAYE2
.OFB (1'b0), // 1-bit input: Data feedback from OSERDESE2
.OCLKB (1'b0), // 1-bit input: High speed negative edge output clock
.RST (~FrmClkRst), // 1-bit input: Active high asynchronous reset
// SHIFTIN1, SHIFTIN2: 1-bit (each) input: Data width expansion input ports
.SHIFTIN1 (1'b0),
.SHIFTIN2 (1'b0)
);
//Frame Alignment State Machine
always @(posedge FrmClkDiv or negedge FrmClkRst)
begin
if((!FrmClkRst) || (!FrmClkDone))
begin
FrmClkBitSlip_pout <= 1'b0;
rBitslipCnt <= 8'd0;
rFrmAlignDone <= 1'b0;
end
else
begin
if(IntFrmSrdsOutp == FrmPattern)
begin
rFrmAlignDone <= 1'b1;
end
else if((rBitslipCnt == 8'd255) && (IntFrmSrdsOutp != FrmPattern))
begin
FrmClkBitSlip_pout <= 1'b1;
rBitslipCnt <= 8'd1;
end
else if((IntFrmSrdsOutp != FrmPattern) && (rBitslipCnt < 8'd255))
begin
FrmClkBitSlip_pout <= 1'b0;
rBitslipCnt <= rBitslipCnt + 1'd1;
end
end
end
assign FrmClkBitSlip_p = FrmClkBitSlip_pout;
assign FrmAlignDone = rFrmAlignDone;
endmodule
5、数据采集程序设计
数据采集比较简单,通过已经对齐后的clock和ISERDESE2模块对两根data线进行串并转换即可,代码框架为:
代码模块如下:
module ad9253_lvds_data#(
parameter BITWISEorBYTEWISE = 1
)
(
input DatClk,
input DatClkDiv,
input DatRst,
input DatBitSlip_p,
input BitClkDone,
input FrmAlignDone,
input DatD0_p,
input DatD0_n,
input DatD1_p,
input DatD1_n,
output [13:0] DatOut
);
wire [7:0] DatSrdsout1; //Frame hign data1
wire [7:0] DatSrdsout2; //Frame low data2
//D0_P ISERDESE
ISERDESE2 #(
.DATA_RATE ("DDR"), // DDR, SDR
.DATA_WIDTH (8), // Parallel data width (2-8,10,14)
.DYN_CLKDIV_INV_EN ("FALSE"), // Enable DYNCLKDIVINVSEL inversion (FALSE, TRUE)
.DYN_CLK_INV_EN ("FALSE"), // Enable DYNCLKINVSEL inversion (FALSE, TRUE)
// INIT_Q1 - INIT_Q4: Initial value on the Q outputs (0/1)
.INIT_Q1 (1'b0),
.INIT_Q2 (1'b0),
.INIT_Q3 (1'b0),
.INIT_Q4 (1'b0),
.INTERFACE_TYPE ("NETWORKING"), // MEMORY, MEMORY_DDR3, MEMORY_QDR, NETWORKING, OVERSAMPLE
.IOBDELAY ("NONE"), // NONE, BOTH, IBUF, IFD
.NUM_CE (2), // Number of clock enables (1,2)
.OFB_USED ("FALSE"), // Select OFB path (FALSE, TRUE)
.SERDES_MODE ("MASTER"), // MASTER, SLAVE
// SRVAL_Q1 - SRVAL_Q4: Q output values when SR is used (0/1)
.SRVAL_Q1 (1'b0),
.SRVAL_Q2 (1'b0),
.SRVAL_Q3 (1'b0),
.SRVAL_Q4 (1'b0),
.IS_CLK_INVERTED (1'b0)
)
ISERDESE2_inst0(
.O (), // 1-bit output: Combinatorial output
// Q1 - Q8: 1-bit (each) output: Registered data outputs
.Q1 (DatSrdsout1[0]),
.Q2 (DatSrdsout1[1]),
.Q3 (DatSrdsout1[2]),
.Q4 (DatSrdsout1[3]),
.Q5 (DatSrdsout1[4]),
.Q6 (DatSrdsout1[5]),
.Q7 (DatSrdsout1[6]),
.Q8 (DatSrdsout1[7]),
// SHIFTOUT1, SHIFTOUT2: 1-bit (each) output: Data width expansion output ports
.SHIFTOUT1 (),
.SHIFTOUT2 (),
.BITSLIP (DatBitSlip_p), // 1-bit input: The BITSLIP pin performs a Bitslip operation synchronous to
// CLKDIV when asserted (active High). Subsequently, the data seen on the Q1
// to Q8 output ports will shift, as in a barrel-shifter operation, one
// position every time Bitslip is invoked (DDR operation is different from
// SDR).
// CE1, CE2: 1-bit (each) input: Data register clock enable inputs
.CE1 (BitClkDone&FrmAlignDone),
.CE2 (1'b1),
.CLKDIVP (1'b0), // 1-bit input: TBD
// Clocks: 1-bit (each) input: ISERDESE2 clock input ports
.CLK (DatClk), // 1-bit input: High-speed clock
.CLKB (~DatClk), // 1-bit input: High-speed secondary clock
.CLKDIV (DatClkDiv), // 1-bit input: Divided clock
.OCLK (1'b0), // 1-bit input: High speed output clock used when INTERFACE_TYPE="MEMORY"
// Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock inversion pins to switch clock polarity
.DYNCLKDIVSEL (1'b0), // 1-bit input: Dynamic CLKDIV inversion
.DYNCLKSEL (1'b0), // 1-bit input: Dynamic CLK/CLKB inversion
// Input Data: 1-bit (each) input: ISERDESE2 data input ports
.D (DatD0_p), // 1-bit input: Data input
.DDLY (1'b0), // 1-bit input: Serial data from IDELAYE2
.OFB (1'b0), // 1-bit input: Data feedback from OSERDESE2
.OCLKB (1'b0), // 1-bit input: High speed negative edge output clock
.RST (~DatRst), // 1-bit input: Active high asynchronous reset
// SHIFTIN1, SHIFTIN2: 1-bit (each) input: Data width expansion input ports
.SHIFTIN1 (1'b0),
.SHIFTIN2 (1'b0)
);
//D1_P ISERDESE
ISERDESE2 #(
.DATA_RATE ("DDR"), // DDR, SDR
.DATA_WIDTH (8), // Parallel data width (2-8,10,14)
.DYN_CLKDIV_INV_EN ("FALSE"), // Enable DYNCLKDIVINVSEL inversion (FALSE, TRUE)
.DYN_CLK_INV_EN ("FALSE"), // Enable DYNCLKINVSEL inversion (FALSE, TRUE)
// INIT_Q1 - INIT_Q4: Initial value on the Q outputs (0/1)
.INIT_Q1 (1'b0),
.INIT_Q2 (1'b0),
.INIT_Q3 (1'b0),
.INIT_Q4 (1'b0),
.INTERFACE_TYPE ("NETWORKING"), // MEMORY, MEMORY_DDR3, MEMORY_QDR, NETWORKING, OVERSAMPLE
.IOBDELAY ("NONE"), // NONE, BOTH, IBUF, IFD
.NUM_CE (2), // Number of clock enables (1,2)
.OFB_USED ("FALSE"), // Select OFB path (FALSE, TRUE)
.SERDES_MODE ("MASTER"), // MASTER, SLAVE
// SRVAL_Q1 - SRVAL_Q4: Q output values when SR is used (0/1)
.SRVAL_Q1 (1'b0),
.SRVAL_Q2 (1'b0),
.SRVAL_Q3 (1'b0),
.SRVAL_Q4 (1'b0)
)
ISERDESE2_inst2(
.O (), // 1-bit output: Combinatorial output
// Q1 - Q8: 1-bit (each) output: Registered data outputs
.Q1 (DatSrdsout2[0]),
.Q2 (DatSrdsout2[1]),
.Q3 (DatSrdsout2[2]),
.Q4 (DatSrdsout2[3]),
.Q5 (DatSrdsout2[4]),
.Q6 (DatSrdsout2[5]),
.Q7 (DatSrdsout2[6]),
.Q8 (DatSrdsout2[7]),
// SHIFTOUT1, SHIFTOUT2: 1-bit (each) output: Data width expansion output ports
.SHIFTOUT1 (),
.SHIFTOUT2 (),
.BITSLIP (DatBitSlip_p), // 1-bit input: The BITSLIP pin performs a Bitslip operation synchronous to
// CLKDIV when asserted (active High). Subsequently, the data seen on the Q1
// to Q8 output ports will shift, as in a barrel-shifter operation, one
// position every time Bitslip is invoked (DDR operation is different from
// SDR).
// CE1, CE2: 1-bit (each) input: Data register clock enable inputs
.CE1 (BitClkDone&FrmAlignDone),
.CE2 (1'b1),
.CLKDIVP (1'b0), // 1-bit input: TBD
// Clocks: 1-bit (each) input: ISERDESE2 clock input ports
.CLK (~DatClk), // 1-bit input: High-speed clock
.CLKB (DatClk), // 1-bit input: High-speed secondary clock
.CLKDIV (DatClkDiv), // 1-bit input: Divided clock
.OCLK (1'b0), // 1-bit input: High speed output clock used when INTERFACE_TYPE="MEMORY"
// Dynamic Clock Inversions: 1-bit (each) input: Dynamic clock inversion pins to switch clock polarity
.DYNCLKDIVSEL (1'b0), // 1-bit input: Dynamic CLKDIV inversion
.DYNCLKSEL (1'b0), // 1-bit input: Dynamic CLK/CLKB inversion
// Input Data: 1-bit (each) input: ISERDESE2 data input ports
.D (DatD1_p), // 1-bit input: Data input
.DDLY (1'b0), // 1-bit input: Serial data from IDELAYE2
.OFB (1'b0), // 1-bit input: Data feedback from OSERDESE2
.OCLKB (1'b0), // 1-bit input: High speed negative edge output clock
.RST (~DatRst), // 1-bit input: Active high asynchronous reset
// SHIFTIN1, SHIFTIN2: 1-bit (each) input: Data width expansion input ports
.SHIFTIN1 (1'b0),
.SHIFTIN2 (1'b0)
);
//Data Output
wire [13:0] DatOut_TEMP1, DatOut_TEMP2;
assign DatOut_TEMP1 = {DatSrdsout2, DatSrdsout1[7:2]};
assign DatOut_TEMP2 = {DatSrdsout2[7], DatSrdsout1[7], DatSrdsout2[6], DatSrdsout1[6],DatSrdsout2[5], DatSrdsout1[5],DatSrdsout2[4], DatSrdsout1[4],
DatSrdsout2[3], DatSrdsout1[3],DatSrdsout2[2], DatSrdsout1[2],DatSrdsout2[1], DatSrdsout1[1]};
assign DatOut = BITWISEorBYTEWISE?DatOut_TEMP1:DatOut_TEMP2;
endmodule
代码中,将两个LANE采集的数据进行了整合,对BYTEWISE和BITWISE模式进行了区分。至此通过ISERDESE对AD9253进行基本采集功能的驱动代码完成。
6、TestBench写LVDS时序及仿真结果
下一节给出一些TestBench编写技巧,对部分module进行仿真,通过仿真验证程序的正确性。