接口协议(1)

您所在的位置:网站首页 fpga的ip核 接口协议(1)

接口协议(1)

2024-01-21 21:29| 来源: 网络整理| 查看: 265

接口协议(1)----在xilinx 7 系列FPGA上配置LVDS 1.0 背景2.0 xilinx 7系列里的lvds2.1 传输模式2.2 模式选择 3.0 lvds 接收端3.1 时钟处理3.2 数据处理3.2.1 ISERDES3.2.2 IDDR3.2.3 数据对齐 4.0 lvds 发送端4.1 OSERDES4.2 ODDR 5.0 视频传输格式6.0 参考文献

1.0 背景

LVDS(Low-Voltage Differential Signaling ,低电压差分信号)是美国国家半导体(National Semiconductor, NS,现TI)于1994年提出的一种信号传输模式的电平标准,它采用极低的电压摆幅高速差动传输数据,可以实现点对点或一点对多点的连接,具有低功耗、低误码率、低串扰和低辐射等优点,已经被广泛应用于串行高速数据通讯场合当,如高速背板、电缆和板到板数据传输与时钟分配,以及单个PCB内的通信链路。

每对LVDS信号是一个差分信号对,一个信号用两个相反的p,n信号线表示,通过差值 [公式] 传输数据,这样可以有效减小共模噪声的干扰,信号线传输如下图: 在这里插入图片描述

2.0 xilinx 7系列里的lvds

Xilinx 7系列fpga包含ISERDES和OSERDES原语,这些原语使得serdes电路的设计非常简单,并且当使用逐位deskew时,根据使用的系列和速度等级,允许以415 Mb/s到1200 Mb/s的速度进行更高的操作。较低的操作速度使用静态数据对齐。 以下图为例子 在这里插入图片描述

在XAPP585里有这么一张图,我觉得很好用,received clock是输入得时钟,从图上可以看到,他的占空比为3:4,一个时钟周期每条线传7个bit得数据,对比正常得信号传输,一个clock 只能传一个bit得数据,所以又称lvds为高速串行接口。

2.1 传输模式

lvds有两种传输模式,一种是SDR(Single Data Rate),一种是DDR(Double Data Rate),通过一组图片就可以看到SDR和DDR的区别: SDR 在这里插入图片描述 上图中,FB_CLK是在第一章里得Received CLK倍频之后得到得时钟,虽然说一个时钟传输7个bit数据,但实际上还是需要将大时钟经过倍频之后得时钟沿去传输,每个小时钟传一个或者两个得数据。 上图一是SDR模式,每个clk传输1个bit数据。 上图二是DDR模式,每个clk传输2个bit数据,上升沿和下降沿触发。

2.2 模式选择

SDR和DDR模式选择是有条件的:

当所需的比特率小于所选时钟网络在所需设备和速度等级中所支持的最大时钟时,应该使用SDR技术。在这个速度以上可以使用DDR技术,在这种情况下可实现的最大比特率受到锁相环或MMCM的最大输出频率的限制。

使用SDR技术的优点是所需的一般互连逻辑少得多,并且与时钟的占空比失真无关。 然而使用DDR技术,在对数据采样的时候就有可能发生时钟偏移,采样到错的数据。

3.0 lvds 接收端

在这里插入图片描述 在这里插入图片描述

3.1 时钟处理

在第一章节有提到,lvds的信号线都是差分信号,需要使用FPGA的buffer原语将其转换成需要使用的单信号线。

IBUFGDS_DIFF_OUT #( .DIFF_TERM (DIFF_TERM), .IBUF_LOW_PWR ("FALSE")) iob_clk_in ( .I (clkin_p), .IB (clkin_n), .O (rx_clk_in_p), .OB (rx_clk_in_n));

经过BUF之后的时钟才是我们可以使用的时钟,当然转换之后有一步是必须要做的,就是delay一下

用这个时钟做被频,生成三个时钟,rxpllmmcm_x1,rxpllmmcm_xs,rxpllmmcm_d4

MMCME2_ADV #( .BANDWIDTH ("OPTIMIZED"), .CLKFBOUT_MULT_F (7*MMCM_MODE), .CLKFBOUT_PHASE (0.0), .CLKIN1_PERIOD (CLKIN_PERIOD), .CLKIN2_PERIOD (CLKIN_PERIOD), .CLKOUT0_DIVIDE_F (2*MMCM_MODE), .CLKOUT0_DUTY_CYCLE (0.5), .CLKOUT0_PHASE (0.0), .CLKOUT0_USE_FINE_PS ("FALSE"), .CLKOUT1_PHASE (11.25), .CLKOUT1_DIVIDE (4*MMCM_MODE), .CLKOUT1_DUTY_CYCLE (0.5), .CLKOUT1_USE_FINE_PS ("FALSE"), .COMPENSATION ("ZHOLD"), .DIVCLK_DIVIDE (1), .REF_JITTER1 (0.100)) rx_mmcm_adv_inst ( .CLKFBOUT (rxpllmmcm_x1), .CLKFBOUTB (), .CLKFBSTOPPED (), .CLKINSTOPPED (), .CLKOUT0 (rxpllmmcm_xs), .CLKOUT0B (), .CLKOUT1 (rxpllmmcm_d4), .PSCLK (1'b0), .PSEN (1'b0), .PSINCDEC (1'b0), .PWRDWN (1'b0), .LOCKED (mmcm_locked), .CLKFBIN (pixel_clk), .CLKIN1 (rx_clkin_p_d), .CLKIN2 (1'b0), .CLKINSEL (1'b1), .DADDR (7'h00), .DCLK (1'b0), .DEN (1'b0), .DI (16'h0000), .DWE (1'b0), .RST (reset)) ;

其中时钟的传输是有限制的,在xilinx xapp585 中提出SDR时钟需要两个时钟缓冲区,DDR时钟需要三个。其他没有列出的方案要么是不支持,要么是不推荐。 这里采用DDR模式,上面生成的3个时钟分别经过时clock buffer,生成pixel_clk,rx_clk,rx_clk_d4.

parameter SAMPL_CLOCK = "BUFIO" ; // Parameter to set sampling clock buffer type, BUFIO, BUF_H, BUF_G parameter INTER_CLOCK = "BUF_R" ; // Parameter to set intermediate clock buffer type, BUFR, BUF_H, BUF_G parameter PIXEL_CLOCK = "BUF_G" ; // Parameter to set final pixel buffer type, BUF_R, BUF_H, BUF_G if (PIXEL_CLOCK == "BUF_G") begin // Final clock selection BUFG bufg_mmcm_x1 (.I(rxpllmmcm_x1), .O(pixel_clk)) ; assign status[1:0] = 2'b00 ; end else if (PIXEL_CLOCK == "BUF_R") begin BUFR #(.BUFR_DIVIDE("1"),.SIM_DEVICE("7SERIES"))bufr_mmcm_x1 (.I(rxpllmmcm_x1),.CE(1'b1),.O(pixel_clk),.CLR(1'b0)) ; assign status[1:0] = 2'b01 ; end else begin BUFH bufh_mmcm_x1 (.I(rxpllmmcm_x1), .O(pixel_clk)) ; assign status[1:0] = 2'b10 ; end if (INTER_CLOCK == "BUF_G") begin // Intermediate clock selection BUFG bufg_mmcm_d4 (.I(rxpllmmcm_d4), .O(rxclk_d4)) ; assign status[3:2] = 2'b00 ; end else if (INTER_CLOCK == "BUF_R") begin BUFR #(.BUFR_DIVIDE("2"),.SIM_DEVICE("7SERIES"))bufr_mmcm_d4 (.I(rxpllmmcm_xs),.CE(1'b1),.O(rxclk_d4),.CLR(1'b0)) ; assign status[3:2] = 2'b01 ; end else begin BUFH bufh_mmcm_d4 (.I(rxpllmmcm_d4), .O(rxclk_d4)) ; assign status[3:2] = 2'b10 ; end if (SAMPL_CLOCK == "BUF_G") begin // Sample clock selection BUFG bufg_mmcm_xn (.I(rxpllmmcm_xs), .O(rxclk)) ; assign status[5:4] = 2'b00 ; end else if (SAMPL_CLOCK == "BUFIO") begin BUFIO bufio_mmcm_xn (.I (rxpllmmcm_xs), .O(rxclk)) ; assign status[5:4] = 2'b11 ; end else begin BUFH bufh_mmcm_xn (.I(rxpllmmcm_xs), .O(rxclk)) ; assign status[5:4] = 2'b10 ; end

可以实现的方案如下: 在这里插入图片描述在这里插入图片描述 在这里插入图片描述 时钟的仿真如下: 在这里插入图片描述 原来的rxclk是一个占空比为3:4的波形,因为他们都要经过idelay,所以rx_clk_in_p_d延迟了一点时间,经MMCM调频之后,输出一个7倍频的时钟,一个4倍频的时钟,还有一个原来的时钟。

3.2 数据处理

官方给出了两种设计方案,其中当以相同像素时钟速率运行的多个通道被接收时,它们可以被放置在相同的I/O bank中,并且所有的时钟选项都是可用的,或者它们可以被放置在不同的bank中,并且只有BUFG时钟可以被使用。

使用SDR采样时钟时,ISERDES直接以1:7模式使用。ISERDES支持的唯一时钟元素组合是两个BUFGs、两个BUFHs或一个BUFIO和一个BUFR。使用BUFG的优点是并行数据可以在覆盖整个设备的时钟上使用。使用BUFR或BUFH,数据在只覆盖当前时钟区域的时钟上可用。 当使用DDR采样时钟时,ISERDES以1:4模式使用,然后1:7模式使用基于分布式RAM的gear box进行。这种方法需要三个时钟域。采样时钟,采样时钟除以4,采样时钟除以7,等于原始输入像素时钟。 其中gear box的作用就是取两次4bit数据,然后拼接成7bit的数据。 在这里插入图片描述 参考ISERDES的参数,可以看到,在SDR模式下,可以取7位数据,但是在DDR模式下,他只能取偶数位,不能直接取七位,所以官方给出的方案就是取4位数据,然后经过gear box将4位数据转成7位。 当然还有一种方案就是将ISERDES串联,然后取14位数据,就是相当于取了2个像素点的数据。 在这里插入图片描述

// // Copyright (c) 2012-2015 Xilinx, Inc. // This design is confidential and proprietary of Xilinx, All Rights Reserved. // // ____ ____ // / /\/ / // /___/ \ / Vendor: Xilinx // \ \ \/ Version: 1.2 // \ \ Filename: gearbox_4_to_7.v // / / Date Last Modified: 21JAN2015 // /___/ /\ Date Created: 5MAR2010 // \ \ / \ // \___\/\___\ // //Device: 7 Series //Purpose: multiple 4 to 7 bit gearbox // //Reference: XAPP585 // //Revision History: // Rev 1.0 - First created (nicks) // Rev 1.1 - reset outputs added // Rev 1.2 - Updated format (brandond) // // // // Disclaimer: // // This disclaimer is not a license and does not grant any rights to the materials // distributed herewith. Except as otherwise provided in a valid license issued to you // by Xilinx, and to the maximum extent permitted by applicable law: // (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL FAULTS, // AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, // INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, OR // FITNESS FOR ANY PARTICULAR PURPOSE; and (2) Xilinx shall not be liable (whether in contract // or tort, including negligence, or under any other theory of liability) for any loss or damage // of any kind or nature related to, arising under or in connection with these materials, // including for any direct, or any indirect, special, incidental, or consequential loss // or damage (including loss of data, profits, goodwill, or any type of loss or damage suffered // as a result of any action brought by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the possibility of the same. // // Critical Applications: // // Xilinx products are not designed or intended to be fail-safe, or for use in any application // requiring fail-safe performance, such as life-support or safety devices or systems, // Class III medical devices, nuclear facilities, applications related to the deployment of airbags, // or any other applications that could lead to death, personal injury, or severe property or // environmental damage (individually and collectively, "Critical Applications"). Customer assumes // the sole risk and liability of any use of Xilinx products in Critical Applications, subject only // to applicable laws and regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE AT ALL TIMES. // // `timescale 1ps/1ps module gearbox_4_to_7 (input_clock, output_clock, datain, reset, jog, reset_out, dataout) ; parameter integer D = 8 ; // Parameter to set the number of data lines input input_clock ; // high speed clock input input output_clock ; // low speed clock input input [D*4-1:0] datain ; // data inputs input reset ; // Reset line input jog ; // jog input, slips by 4 bits output reg [1:0] reset_out ; // reset out signal output reg [D*7-1:0] dataout ; // data outputs reg [3:0] read_addra ; reg [3:0] read_addrb ; reg [3:0] read_addrc ; reg [3:0] write_addr ; reg read_enable ; reg read_enable_dom_ch ; wire [D*4-1:0] ramouta ; wire [D*4-1:0] ramoutb ; wire [D*4-1:0] ramoutc ; reg local_reset ; reg local_reset_dom_ch ; reg [1:0] mux ; wire [D*4-1:0] dummy ; reg jog_int ; reg rst_int ; genvar i ; always @ (posedge input_clock) begin // generate local sync reset if (reset == 1'b1) begin local_reset ramoutc[4*i+1:4*i+0], ramoutb[4*i+3:4*i+0], ramouta[4*i+3]} ; 2'h2 : dataout[7*i+6:7*i] ramoutb[4*i+3:4*i+0], ramouta[4*i+3:4*i+1]} ; endcase end end endgenerate // Data gearboxes generate for (i = 0 ; i 1'b0, read_addrb}), .ADDRC ({1'b0, read_addrc}), .ADDRD ({1'b0, write_addr}), .DIA (datain[2*i+1:2*i]), .DIB (datain[2*i+1:2*i]), .DIC (datain[2*i+1:2*i]), .DID (dummy[2*i+1:2*i]), .WE (1'b1), .WCLK (input_clock)); end endgenerate endmodule 3.2.1 ISERDES

在这里插入图片描述 xilinx 7系列的原语之一,作用就是将串行信号转化为并行信号,

// ISERDESE2: Input SERial/DESerializer with Bitslip // 7 Series // Xilinx HDL Libraries Guide, version 14.7 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) ); // End of ISERDESE2_inst instantiation

比较重要的参数设置:

DATAWIDTH ,决定输出数据的宽度(Q1-Q8) 在这里插入图片描述INTERFACE_TYPE,决定DATA width的可选范围,也决定了输出输出的路径 当定义为NETWROKING时 在这里插入图片描述 Iserdes就只需要两个时钟输入,一个倍频之后的时钟,一个原来的时钟,这两个时钟要么一个经过BUFIO,一个经过BUFR,和上图一样,否则,就需要经过MMCM或者PLL产生,其他都是不允许的。 在这里插入图片描述

因为在LVDS里只用这个选项,其他选项就不多赘述,可以参考ug471了解。

IOBDELAY,决定数据从哪个端口输出。 在这里插入图片描述

端口说明

Q1-Q8 数据输出,可以理解为Q[8:1]

在这里插入图片描述

BITSLIP 移位信号,没发生一次脉冲,就会使采样数据左移一位。 在这里插入图片描述 在这里插入图片描述

使用这个端口可以更好的找到数据的边界。 其他的端口注释讲的很明白,对于DDR模式,建议使用2个Iserdes级联使用

3.2.2 IDDR

对于DDR模式,还有一个可选的方案就是使用IDDR原语,这也是一个串行转并行的器件,与ISERDES不同的是,IDDR只有两个输出端口,q1,q2,,也没有bilislip,无法进行数据对齐,想比较之下,使用IDDR没有使用Iserdes方便。 在这里插入图片描述 波形图整上: 在这里插入图片描述

3.2.3 数据对齐

数据在发送端送出的时候,可能是对齐的,但是在传输的过程中,可能会有各种乱七八糟的因素导致数据和时钟不对齐,偏差一二三四等等位,这时候怎么办,刚刚的bitslip就是用来做这个的,通过调整BITSLIP,找到数据的边界,然后解出正确的值。 在这里插入图片描述 在这里插入图片描述

如何确定bitslip,在本章的开头里,有给出一个方案,因为一个时钟周期是传送7个bit数据,所以他要么是4:3,要么是3:4,往往在发送端,会给出时钟的pattern,一般是7‘b1100011或者7’b1100001,基本除了这两种也不会有其他的,所以可以把时钟信号delay一下,然后给他解串,如果解串的数据是7‘b1100011或者7’b1100001,就说明数据对齐,如果没有,那就发送一个脉冲,直到对齐为止。

4.0 lvds 发送端

在这里插入图片描述 时钟方面,和接收端的时钟配置是一样的,一个大时钟,一个小时钟。

/// // Copyright (c) 2012-2015 Xilinx, Inc. // This design is confidential and proprietary of Xilinx, All Rights Reserved. /// // ____ ____ // / /\/ / // /___/ \ / Vendor: Xilinx // \ \ \/ Version: 1.2 // \ \ Filename: clock_generator_pll_7_to_1_diff_ddr.v // / / Date Last Modified: 21JAN2015 // /___/ /\ Date Created: 5JAN2010 // \ \ / \ // \___\/\___\ // //Device: 7 Series //Purpose: DDR MMCM or PLL based clock generator. Takes in a differential clock and multiplies it // appropriately //Reference: XAPP585 // //Revision History: // Rev 1.0 - First created (nicks) // Rev 1.1 - Some net names changed to make more sense in Vivado // Rev 1.2 - Updated format (brandond) // /// // // Disclaimer: // // This disclaimer is not a license and does not grant any rights to the materials // distributed herewith. Except as otherwise provided in a valid license issued to you // by Xilinx, and to the maximum extent permitted by applicable law: // (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL FAULTS, // AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, // INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, OR // FITNESS FOR ANY PARTICULAR PURPOSE; and (2) Xilinx shall not be liable (whether in contract // or tort, including negligence, or under any other theory of liability) for any loss or damage // of any kind or nature related to, arising under or in connection with these materials, // including for any direct, or any indirect, special, incidental, or consequential loss // or damage (including loss of data, profits, goodwill, or any type of loss or damage suffered // as a result of any action brought by a third party) even if such damage or loss was // reasonably foreseeable or Xilinx had been advised of the possibility of the same. // // Critical Applications: // // Xilinx products are not designed or intended to be fail-safe, or for use in any application // requiring fail-safe performance, such as life-support or safety devices or systems, // Class III medical devices, nuclear facilities, applications related to the deployment of airbags, // or any other applications that could lead to death, personal injury, or severe property or // environmental damage (individually and collectively, "Critical Applications"). Customer assumes // the sole risk and liability of any use of Xilinx products in Critical Applications, subject only // to applicable laws and regulations governing limitations on product liability. // // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE AT ALL TIMES. // // `timescale 1ps/1ps module clock_generator_pll_7_to_1_diff_ddr (clkin_p, clkin_n, txclk, reset, pixel_clk, txclk_div, mmcm_lckd, status) ; parameter real CLKIN_PERIOD = 6.000 ; // clock period (ns) of input clock on clkin_p parameter DIFF_TERM = "FALSE" ; // Parameter to enable internal differential termination parameter integer MMCM_MODE = 1 ; // Parameter to set multiplier for MMCM to get VCO in correct operating range. 1 multiplies input clock by 7, 2 multiplies clock by 14, etc parameter TX_CLOCK = "BUFIO" ; // Parameter to set transmission clock buffer type, BUFIO, BUF_H, BUF_G parameter INTER_CLOCK = "BUF_R" ; // Parameter to set intermediate clock buffer type, BUFR, BUF_H, BUF_G parameter PIXEL_CLOCK = "BUF_G" ; // Parameter to set final clock buffer type, BUF_R, BUF_H, BUF_G parameter USE_PLL = "FALSE" ; // Parameter to enable PLL use rather than MMCM use, note, PLL does not support BUFIO and BUFR input reset ; // reset (active high) input clkin_p, clkin_n ; // differential clock inputs output txclk ; // CLK for serdes output pixel_clk ; // Pixel clock output output txclk_div ; // CLKDIV for serdes, and gearbox output = pixel clock / 2 output mmcm_lckd ; // Locked output from BUFPLL output [6:0] status ; // clock status wire clkint ; // clock input from pin wire txpllmmcm_x1 ; // pll generated x1 clock wire txpllmmcm_xn ; // pll generated xn clock IBUFGDS #( .DIFF_TERM (DIFF_TERM)) clk_iob_in ( .I (clkin_p), .IB (clkin_n), .O (clkint)); generate if (USE_PLL == "FALSE") begin : loop8 // use an MMCM assign status[6] = 1'b1 ; MMCME2_ADV #( .BANDWIDTH ("OPTIMIZED"), .CLKFBOUT_MULT_F (7*MMCM_MODE), .CLKFBOUT_PHASE (0.0), .CLKIN1_PERIOD (CLKIN_PERIOD), .CLKIN2_PERIOD (CLKIN_PERIOD), .CLKOUT0_DIVIDE_F (2*MMCM_MODE), .CLKOUT0_DUTY_CYCLE (0.5), .CLKOUT0_PHASE (0.0), .CLKOUT1_DIVIDE (14*MMCM_MODE), .CLKOUT1_DUTY_CYCLE (0.5), .CLKOUT1_PHASE (0.0), .CLKOUT2_DIVIDE (7*MMCM_MODE), .CLKOUT2_DUTY_CYCLE (0.5), .CLKOUT2_PHASE (0.0), .CLKOUT3_DIVIDE (8), .CLKOUT3_DUTY_CYCLE (0.5), .CLKOUT3_PHASE (0.0), .CLKOUT4_DIVIDE (8), .CLKOUT4_DUTY_CYCLE (0.5), .CLKOUT4_PHASE (0.0), .CLKOUT5_DIVIDE (8), .CLKOUT5_DUTY_CYCLE (0.5), .CLKOUT5_PHASE (0.0), .COMPENSATION ("ZHOLD"), .DIVCLK_DIVIDE (1), .REF_JITTER1 (0.100)) tx_mmcme2_adv_inst ( .CLKFBOUT (txpllmmcm_x1), .CLKFBOUTB (), .CLKFBSTOPPED (), .CLKINSTOPPED (), .CLKOUT0 (txpllmmcm_xn), .CLKOUT0B (), .CLKOUT1 (txpllmmcm_d2), .CLKOUT1B (), .CLKOUT2 (), .CLKOUT2B (), .CLKOUT3 (), .CLKOUT3B (), .CLKOUT4 (), .CLKOUT5 (), .CLKOUT6 (), .DO (), .DRDY (), .PSDONE (), .PSCLK (1'b0), .PSEN (1'b0), .PSINCDEC (1'b0), .PWRDWN (1'b0), .LOCKED (mmcm_lckd), .CLKFBIN (pixel_clk), .CLKIN1 (clkint), .CLKIN2 (1'b0), .CLKINSEL (1'b1), .DADDR (7'h00), .DCLK (1'b0), .DEN (1'b0), .DI (16'h0000), .DWE (1'b0), .RST (reset)) ; if (PIXEL_CLOCK == "BUF_G") begin // Final clock selection BUFG bufg_mmcm_x1 (.I(txpllmmcm_x1), .O(pixel_clk)) ; assign status[1:0] = 2'b00 ; end else if (PIXEL_CLOCK == "BUF_R") begin BUFR #(.BUFR_DIVIDE("1"),.SIM_DEVICE("7SERIES"))bufr_mmcm_x1 (.I(txpllmmcm_x1),.CE(1'b1),.O(pixel_clk),.CLR(1'b0)) ; assign status[1:0] = 2'b01 ; end else begin BUFH bufh_mmcm_x1 (.I(txpllmmcm_x1), .O(pixel_clk)) ; assign status[1:0] = 2'b10 ; end if (INTER_CLOCK == "BUF_G") begin // Intermediate clock selection BUFG bufg_mmcm_d2 (.I(txpllmmcm_d2), .O(txclk_div)) ; assign status[3:2] = 2'b00 ; end else if (INTER_CLOCK == "BUF_R") begin BUFR #(.BUFR_DIVIDE("1"),.SIM_DEVICE("7SERIES"))bufr_mmcm_d2 (.I(txpllmmcm_d2),.CE(1'b1),.O(txclk_div),.CLR(1'b0)) ; assign status[3:2] = 2'b01 ; end else begin BUFH bufh_mmcm_d2 (.I(txpllmmcm_d2), .O(txclk_div)) ; assign status[3:2] = 2'b10 ; end if (TX_CLOCK == "BUF_G") begin // Sample clock selection BUFG bufg_mmcm_xn (.I(txpllmmcm_xn), .O(txclk)) ; assign status[5:4] = 2'b00 ; end else if (TX_CLOCK == "BUFIO") begin BUFIO bufio_mmcm_xn (.I (txpllmmcm_xn), .O(txclk)) ; assign status[5:4] = 2'b11 ; end else begin BUFH bufh_mmcm_xn (.I(txpllmmcm_xn), .O(txclk)) ; assign status[5:4] = 2'b10 ; end end else begin assign status[6] = 1'b0 ; // Use a PLL PLLE2_ADV #( .BANDWIDTH ("OPTIMIZED"), .CLKFBOUT_MULT (7*MMCM_MODE), .CLKFBOUT_PHASE (0.0), .CLKIN1_PERIOD (CLKIN_PERIOD), .CLKIN2_PERIOD (CLKIN_PERIOD), .CLKOUT0_DIVIDE (2*MMCM_MODE), .CLKOUT0_DUTY_CYCLE (0.5), .CLKOUT0_PHASE (0.0), .CLKOUT1_DIVIDE (14*MMCM_MODE), .CLKOUT1_DUTY_CYCLE (0.5), .CLKOUT1_PHASE (0.0), .CLKOUT2_DIVIDE (7*MMCM_MODE), .CLKOUT2_DUTY_CYCLE (0.5), .CLKOUT2_PHASE (0.0), .CLKOUT3_DIVIDE (8), .CLKOUT3_DUTY_CYCLE (0.5), .CLKOUT3_PHASE (0.0), .CLKOUT4_DIVIDE (8), .CLKOUT4_DUTY_CYCLE (0.5), .CLKOUT4_PHASE (0.0), .CLKOUT5_DIVIDE (8), .CLKOUT5_DUTY_CYCLE (0.5), .CLKOUT5_PHASE (0.0), .COMPENSATION ("ZHOLD"), .DIVCLK_DIVIDE (1), .REF_JITTER1 (0.100)) tx_mmcme2_adv_inst ( .CLKFBOUT (txpllmmcm_x1), .CLKOUT0 (txpllmmcm_xn), .CLKOUT1 (txpllmmcm_d2), .CLKOUT2 (), .CLKOUT3 (), .CLKOUT4 (), .CLKOUT5 (), .DO (), .DRDY (), .PWRDWN (1'b0), .LOCKED (mmcm_lckd), .CLKFBIN (pixel_clk), .CLKIN1 (clkint), .CLKIN2 (1'b0), .CLKINSEL (1'b1), .DADDR (7'h00), .DCLK (1'b0), .DEN (1'b0), .DI (16'h0000), .DWE (1'b0), .RST (reset)) ; if (PIXEL_CLOCK == "BUF_G") begin // Final clock selection BUFG bufg_mmcm_x1 (.I(txpllmmcm_x1), .O(pixel_clk)) ; assign status[1:0] = 2'b00 ; end else if (PIXEL_CLOCK == "BUF_R") begin BUFR #(.BUFR_DIVIDE("1"),.SIM_DEVICE("7SERIES"))bufr_mmcm_x1 (.I(txpllmmcm_x1),.CE(1'b1),.O(pixel_clk),.CLR(1'b0)) ; assign status[1:0] = 2'b01 ; end else begin BUFH bufh_mmcm_x1 (.I(txpllmmcm_x1), .O(pixel_clk)) ; assign status[1:0] = 2'b10 ; end if (INTER_CLOCK == "BUF_G") begin // Intermediate clock selection BUFG bufg_mmcm_d2 (.I(txpllmmcm_d2), .O(txclk_div)) ; assign status[3:2] = 2'b00 ; end else if (INTER_CLOCK == "BUF_R") begin BUFR #(.BUFR_DIVIDE("1"),.SIM_DEVICE("7SERIES"))bufr_mmcm_d2 (.I(txpllmmcm_d2),.CE(1'b1),.O(txclk_div),.CLR(1'b0)) ; assign status[3:2] = 2'b01 ; end else begin BUFH bufh_mmcm_d2 (.I(txpllmmcm_d2), .O(txclk_div)) ; assign status[3:2] = 2'b10 ; end if (TX_CLOCK == "BUF_G") begin // Sample clock selection BUFG bufg_mmcm_xn (.I(txpllmmcm_xn), .O(txclk)) ; assign status[5:4] = 2'b00 ; end else if (TX_CLOCK == "BUFIO") begin BUFIO bufio_mmcm_xn (.I (txpllmmcm_xn), .O(txclk)) ; assign status[5:4] = 2'b11 ; end else begin BUFH bufh_mmcm_xn (.I(txpllmmcm_xn), .O(txclk)) ; assign status[5:4] = 2'b10 ; end end endgenerate endmodule

两个时钟输出被用于高速和低速时钟从锁相环或MMCM。这两个时钟是相位对齐的,以确保在所有OSERDES都同步并在SR输入上同步复位后,OSERDES中的串行化是正确的。应用的并行数据然后被串行化输出使用高速传输时钟。通过向与时钟线相关的OSERDES发送一个常量值,转发的时钟输出以类似的方式生成。视频7:1应用的转发时钟需要1100001或1100011,以确保转发的时钟和数据关系符合广泛使用的标准。

每个channel配合一个clock,当然也可以配合一个总的clock,这几个clock都是一样的。

在这里插入图片描述 在这里插入图片描述

4.1 OSERDES

在这里插入图片描述

在这里插入图片描述

// OSERDESE2: Output SERial/DESerializer with bitslip // 7 Series // Xilinx HDL Libraries Guide, version 14.7 OSERDESE2 #( .DATA_RATE_OQ("DDR"), // DDR, SDR .DATA_RATE_TQ("DDR"), // DDR, BUF, SDR .DATA_WIDTH(4), // Parallel data width (2-8,10,14) .INIT_OQ(1'b0), // Initial value of OQ output (1'b0,1'b1) .INIT_TQ(1'b0), // Initial value of TQ output (1'b0,1'b1) .SERDES_MODE("MASTER"), // MASTER, SLAVE .SRVAL_OQ(1'b0), // OQ output value when SR is used (1'b0,1'b1) .SRVAL_TQ(1'b0), // TQ output value when SR is used (1'b0,1'b1) .TBYTE_CTL("FALSE"), // Enable tristate byte operation (FALSE, TRUE) .TBYTE_SRC("FALSE"), // Tristate byte source (FALSE, TRUE) .TRISTATE_WIDTH(4) // 3-state converter width (1,4) ) OSERDESE2_inst ( .OFB(OFB), // 1-bit output: Feedback path for data .OQ(OQ), // 1-bit output: Data path output // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each) .SHIFTOUT1(SHIFTOUT1), .SHIFTOUT2(SHIFTOUT2), .TBYTEOUT(TBYTEOUT), // 1-bit output: Byte group tristate .TFB(TFB), // 1-bit output: 3-state control .TQ(TQ), // 1-bit output: 3-state control .CLK(CLK), // 1-bit input: High speed clock .CLKDIV(CLKDIV), // 1-bit input: Divided clock // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each) .D1(D1), .D2(D2), .D3(D3), .D4(D4), .D5(D5), .D6(D6), .D7(D7), .D8(D8), .OCE(OCE), // 1-bit input: Output data clock enable .RST(RST), // 1-bit input: Reset // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each) .SHIFTIN1(SHIFTIN1), .SHIFTIN2(SHIFTIN2), // T1 - T4: 1-bit (each) input: Parallel 3-state inputs .T1(T1), .T2(T2), .T3(T3), .T4(T4), .TBYTEIN(TBYTEIN), // 1-bit input: Byte group tristate .TCE(TCE) // 1-bit input: 3-state clock enable ); // End of OSERDESE2_inst instantiation

首先关注OSEDES2的属性内容,它的重要属性决定的因素如下:

DATA_RATE_OQ:决定OQ端口输出的数据速率,可选SDR或DDR; DATA_RATE_TQ:决定TQ端口输出的数据速率,可选BUF, SDR或DDR; DATA_WIDTH: 根据"DATA_RATE_OQ"确定具体数值;SDR Rate:可设为2,3,4,5,6,7,8;DDR Rate:可设为4,6,8,10,14; SERDES_MODE:确定OSERDES是主模块还是从模块,这跟OSERDES级联使用有关,具体内容请看下面的内容; TRISTATE_WIDTH:这跟"DATA_RATE_TQ"有关,大多情况都设为1,它的具体设置关系如下: 在这里插入图片描述 OSERDES原语的端口定义如上图所示,其中重要的端口设置如下:

OQ:串行数据输出,直接到IOB,也就是直接连接到IOBUF,ODELAY等特殊结构 SHIFTOUT1/2:级联时使用,详见下文 CLK:高速时钟,串行数据时钟输入 CLKDIV:慢速时钟,并行数据时钟输入 D1 to D8:并行数据输入,当并行数据多于8bit不超过14bit,可以使用OSERDES级联,级联的使用方法详见下文 OCE: 串行数据时钟使能信号输出 RST: 高复位信号输入 SHIFTIN1/2: 级联时使用,详见下文 OSERDES的波形如下图:

以最简单的2:1 SDR串化为例: 在这里插入图片描述 Event1时,数据从FPGA其他部分逻辑传到OSERDES2的D1-2端口Event2时,数据在CLKDIV上升沿被OSERDES2采样Event3时,OQ端口产生相应的输出串行数据 DDR: 在这里插入图片描述 和SDR比较,前三个event都是一样的,在第四个event代表传输完成。

OSERDES级联使用:

当并行数据多于8bit不超过14bit时,可以采用两个OSERDES2级联的使用方法,示意图如下, 在这里插入图片描述 在这里插入图片描述

4.2 ODDR

还有一种实现lvds传输的方法就是使用ODDR这个原语,按照惯例,先看端口和波形: 在这里插入图片描述

在这里插入图片描述 在这里插入图片描述 根据波形可以看出,ODDR是把两个数据转换成一个周期的双边沿触发的数据,和IDDR的做法类似,ODDR只适用于DDR模式,不适合SDR模式,同样需要两个数据传一下: 这里可以使用一个counter和buffer来解决。

begin case (outcount) 0: shiftdata buffer[0][2], buffer[0][3] }; 2: shiftdata buffer[0][6], buffer[1][0] }; 4: shiftdata buffer[1][3], buffer[1][4] }; 6: shiftdata


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3