接口协议(1)----在xilinx 7 系列FPGA上配置LVDS

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模式选择是有条件的:

  1. 当所需的比特率小于所选时钟网络在所需设备和速度等级中所支持的最大时钟时,应该使用SDR技术。
  2. 在这个速度以上可以使用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 <= 1'b1 ;
		reset_out[0] <= 1'b1 ;
	end else begin
		local_reset <= 1'b0 ;
		reset_out[0] <= 1'b0 ;
	end
end 

always @ (posedge input_clock) begin				// Gearbox input - 4 bit data at input clock frequency
	if (local_reset == 1'b1) begin
		write_addr <= 4'h0 ;
		read_enable <= 1'b0 ;
	end 
	else begin
		if (write_addr == 4'hD) begin
			write_addr <= 4'h0 ;
		end 
		else begin
			write_addr <= write_addr + 4'h1 ;
		end
		if (write_addr == 4'h3) begin
			read_enable <= 1'b1 ;
		end
	end
end

always @ (posedge output_clock) begin	
	read_enable_dom_ch <= read_enable ;
	local_reset_dom_ch <= local_reset ;
end

always @ (posedge output_clock) begin				// Gearbox output - 10 bit data at output clock frequency
	reset_out[1] <= rst_int ;
	if (local_reset_dom_ch == 1'b1 || read_enable_dom_ch == 1'b0) begin
		rst_int <= 1'b1 ; 
	end
	else begin
		rst_int <= 1'b0 ; 
	end
	if (reset_out[1] == 1'b1) begin
		read_addra <= 4'h0 ;
		read_addrb <= 4'h1 ;
		read_addrc <= 4'h2 ;
		jog_int <= 1'b0 ;
	end
	else begin
		case (jog_int)
		1'b0 : begin
			case (read_addra)
			4'h0    : begin read_addra <= 4'h1 ; read_addrb <= 4'h2 ; read_addrc <= 4'h3 ; mux <= 2'h1 ; end
			4'h1    : begin read_addra <= 4'h3 ; read_addrb <= 4'h4 ; read_addrc <= 4'h5 ; mux <= 2'h2 ; end
			4'h3    : begin read_addra <= 4'h5 ; read_addrb <= 4'h6 ; read_addrc <= 4'h7 ; mux <= 2'h3 ; end
			4'h5    : begin read_addra <= 4'h7 ; read_addrb <= 4'h8 ; read_addrc <= 4'h9 ; mux <= 2'h0 ; end
			4'h7    : begin read_addra <= 4'h8 ; read_addrb <= 4'h9 ; read_addrc <= 4'hA ; mux <= 2'h1 ; end
			4'h8    : begin read_addra <= 4'hA ; read_addrb <= 4'hB ; read_addrc <= 4'hC ; mux <= 2'h2 ; end
			4'hA    : begin read_addra <= 4'hC ; read_addrb <= 4'hD ; read_addrc <= 4'hD ; mux <= 2'h3 ; jog_int <= jog ; end
			default : begin read_addra <= 4'h0 ; read_addrb <= 4'h1 ; read_addrc <= 4'h2 ; mux <= 2'h0 ; end
			endcase 
		end
		1'b1 : begin
			case (read_addra)
			4'h1    : begin read_addra <= 4'h2 ; read_addrb <= 4'h3 ; read_addrc <= 4'h4 ; mux <= 2'h1 ; end
			4'h2    : begin read_addra <= 4'h4 ; read_addrb <= 4'h5 ; read_addrc <= 4'h6 ; mux <= 2'h2 ; end
			4'h4    : begin read_addra <= 4'h6 ; read_addrb <= 4'h7 ; read_addrc <= 4'h8 ; mux <= 2'h3 ; end
			4'h6    : begin read_addra <= 4'h8 ; read_addrb <= 4'h9 ; read_addrc <= 4'hA ; mux <= 2'h0 ; end
			4'h8    : begin read_addra <= 4'h9 ; read_addrb <= 4'hA ; read_addrc <= 4'hB ; mux <= 2'h1 ; end
			4'h9    : begin read_addra <= 4'hB ; read_addrb <= 4'hC ; read_addrc <= 4'hD ; mux <= 2'h2 ; end
			4'hB    : begin read_addra <= 4'hD ; read_addrb <= 4'h0 ; read_addrc <= 4'h1 ; mux <= 2'h3 ; jog_int <= jog ; end
			default : begin read_addra <= 4'h1 ; read_addrb <= 4'h2 ; read_addrc <= 4'h3 ; mux <= 2'h0 ; end
			endcase 
		end
		endcase
	end
end

generate
for (i = 0 ; i <= D-1 ; i = i+1)
begin : loop0

always @ (posedge output_clock) begin
	case (mux)
	2'h0    : dataout[7*i+6:7*i] <= {                      ramoutb[4*i+2:4*i+0], ramouta[4*i+3:4*i+0]} ;
	2'h1    : dataout[7*i+6:7*i] <= {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] <= {ramoutc[4*i+0],       ramoutb[4*i+3:4*i+0], ramouta[4*i+3:4*i+2]} ; 
	default : 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 <= D*2-1 ; i = i+1)
begin : loop2

RAM32M ram_inst ( 
	.DOA	(ramouta[2*i+1:2*i]), 
	.DOB	(ramoutb[2*i+1:2*i]),
	.DOC    (ramoutc[2*i+1:2*i]), 
	.DOD    (dummy[2*i+1:2*i]),
	.ADDRA	({1'b0, read_addra}), 
	.ADDRB	({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串化为例:
    在这里插入图片描述
  1. Event1时,数据从FPGA其他部分逻辑传到OSERDES2的D1-2端口
  2. Event2时,数据在CLKDIV上升沿被OSERDES2采样
  3. 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][0], buffer[0][1] };
					1:	shiftdata <= { buffer[0][2], buffer[0][3] };
					2:	shiftdata <= { buffer[0][4], buffer[0][5] };
					3:	shiftdata <= { buffer[0][6], buffer[1][0] };
					4:	shiftdata <= { buffer[1][1], buffer[1][2] };
					5:	shiftdata <= { buffer[1][3], buffer[1][4] };
					6:	shiftdata <= { buffer[1][5], buffer[1][6] };
				endcase

5.0 视频传输格式

LVDS数据格式有2种:JEIDA标准和VESA标准。
LVDS的每个clock周期内有7bit数据

  1. JEIDA标准,如下图,第一张图是24bit的RGB数据,其中XX表示未定义,一般是0,第二张是18bit的RGB数据,
    24bit:
    在这里插入图片描述
    18bit:
    在这里插入图片描述

  2. VESA标准,同样,如果使用18bit的RGB数据,TxOUT3不使用。
    24bit:
    在这里插入图片描述

6.0 参考文献

《xapp585-lvds-source-synch-serdes-clock-multiplication》
《UG768 Xilinx 7 Series FPGA Libraries Guide for HDL Designs 》
《UG471 7 Series FPGAs SelectIO Resources》

  • 30
    点赞
  • 220
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: Xilinx-lvds输入接口设计主要是实现对高速差分信号传输的支持,其基本构成由lvds输入模块和相关电路组成。由于lvds电平具有高噪声容限、低功耗、高速传输等优点,在高速数据传输领域被广泛应用。在设计xilinx-lvds读写功能时,首先需要开发相应的硬件平台,然后在该平台上构建读写操作的相关逻辑电路。 xilinx-lvds输入接口的设计需要注意以下几点: 1.物理层接口设计。应根据实际应用需求,选择合适的差分信号传输线路,并对线路进行一定的优化设计,以提高传输质量、降低噪声等级。 2.信号解调设计。应该根据lvds信号传输的协议规范,对差分信号进行解调,提取操作所需的有效信号,以满足读写操作的需要。 3.芯片外部器件设计。应根据芯片器件的规格书要求,选用合适的外部器件,如电阻、电容等,以提高信号品质,降低噪声。 4.读写逻辑电路设计。在上述基础上,可以构建读写操作相关的逻辑电路,通过适当的组合与调试,实现对操作信号的读写控制。 最终,执行性能测试,以验证xilinx-lvds输入接口设计的正确性和稳定性。掌握上述关键技术,可以根据不同的应用要求,实现高速、稳定的lvds数据传输与读写功能。 ### 回答2: 在设计LVDS输入接口时,需要考虑多个因素。 首先,需要确定电路中使用的LVDS芯片,以便确定其电气特性。接着,需要对输入信号进行差分和偏置控制。 在使用Xilinx FPGA实现LVDS读写功能时,需要使用FPGA的IO Banks,其中包括LVDS IO。具体步骤为:首先,将LVDS接口通过差分器连接到IO端口上。然后,需要对IO Banks进行正确的布置和引脚映射,以确保LVDS信号能够被正确接收和发送。 接下来,需要使用芯片供应商提供的LVDS驱动器和接收器(例如TI或ADI)来配置芯片。要注意的是,在使用LVDS接口时,时序约束非常重要,尤其是时钟和数据的延迟和对齐问题。 在完成LVDS接口的硬件设计后,需要使用FPGA设计软件实现读写功能。可以使用Xilinx提供的IP核或自己编写Verilog代码来实现。根据芯片的不同,可能需要对接口进行协议转换(例如,从LVDS到DDR3)。 最后,需要进行测试和验证,确保接口能够正常运行并符合时序约束。这可以通过使用示波器等测试工具来完成。 总之,设计LVDS输入接口需要考虑多个因素,并在硬件和软件层面上进行仔细设计和测试。 ### 回答3: 在Xilinx FPGA设计中,设计LVDS输入接口是一项常见的任务。要实现LVDS输入,需要考虑电源和传输线路的噪声,以及时钟精度和稳定性等方面的问题。下面是一些常见的步骤和技巧,用来设计Xilinx LVDS读写功能的实现。 首先,需要使用LVDS接收器芯片来接收传输线路上的LVDS信号。在Xilinx FPGA中,推荐使用ISERDES模块来实现LVDS输入。ISERDES模块可以将LVDS信号转换为FPGA内部的信号。在使用ISERDES模块时,需要注意时钟的相位和时序同步。 其次,需要考虑双差输入和共模抑制的问题。双差输入是指LVDS信号是两个互为反相的信号,需要对两个信号进行差分输入。共模抑制是指尽可能排除共模噪声干扰,提高信号的稳定性和可靠性。 最后,需要仔细设计PCB布局,保证LVDS接收器芯片的电源和地线稳定,以及传输线路的匹配和降噪设计。同时,还需要根据具体的设计要求选择适当的输出接口,例如LVDS输出或TTL输出。 综上所述,实现Xilinx LVDS读写功能的关键是设计合理的接收器电路、时钟同步和匹配,降低噪声干扰,提高信号的可靠性和稳定性。在实际的设计过程中,需要仔细考虑系统要求、布局约束和测试方法等方面的问题,以确保设计的可行性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值