差分信号环路测试
1 概述
LVDS(Low Voltage Differential Signalin)是一种低振幅差分信号技术。它使用幅度非常低的信号(约350mV)通过一对差分PCB走线或平衡电缆传输数据。大部分高速数据传输中,都会用到LVDS传输。
目前FPGA开发板资料中涉及LVDS通信的方案并不多,但是LVDS实际上有大量的应用,特别是在高速ADC,
高分辨率摄像头,液晶屏显示技术等应用领域。所以掌握LVDS通信也是我们FPGA开发者的必备基本技能。本文首先简要介绍一些XILINXFPGA的LVDS解决方案,然后再通过一个简单的环路测试对LVDS通信做一个简单的验证测试。
2 XILINX FPGA 差分信号解决方案
2.1 IBUFDS
对应原语:
IBUFDS #(
.DIFF_TERM("FALSE"), // Differential Termination
.IBUF_LOW_PWR("TRUE"), // Low power="TRUE", Highest performance="FALSE"
.IOSTANDARD("DEFAULT")// Specify the input I/O standard
) IBUFDS_inst (
.O(O), // Buffer output
.I(I), // Diff_p buffer input (connect directly to top-level port)
.IB(IB) // Diff_n buffer input (connect directly to top-level port)
);
2.2 OBUFDS
对应原语:
OBUFDS#(
.IOSTANDARD("DEFAULT"), // Specify the output I/O standard
.SLEW("SLOW")// Specify the output slew rate
) OBUFDS_inst (
.O(O), // Diff_p output (connect directly to top-level port)
.OB(OB), // Diff_n output (connect directly to top-level port)
.I(I) // Buffer input
);
2.3 IOBUFDS
对应原语:
IOBUFDS #(
.DIFF_TERM("FALSE"),// Differential Termination ("TRUE"/"FALSE")
.IBUF_LOW_PWR("TRUE"), // Low Power- "TRUE", High Performance = "FALSE"
.IOSTANDARD("BLVDS_25"), // Specify the I/O standard
.SLEW("SLOW") // Specify the output slew rate
) IOBUFDS_inst (
.O(O),// Buffer output
.IO(IO),// Diff_p inout (connect directly to top-level port)
.IOB(IOB), // Diff_n inout (connect directly to top-level port)
.I(I),// Buffer input
.T(T) // 3-state enable input, high=input, low=output
);
2.3 LVDS 中的终端电阻
如果要使用内部的终端电阻,对于HP的LVDS信号BANK电压必须是1.8V,而对于HR的LVDS25BANK
信号必须是2.5V,否则可以使用外部终端电阻。
2.4 LVDS 电气特性
2.4.1 LVDS25
VCCO是2.5V
VOH是高电平最大1.675V
VOL 低电平最小0.7V
VODIFF 差模电压最大600mv,最小247mv,典型值350mv
VOCM 输出共模电压,最小1V最大1.425V,典型值1.25V
VIDIFF 输入差模电压,最大600mv,最小100mv,典型350mv
VICM输入共模电压,最大1.5V,最小0.3V,典型1.2V
2.4.2 LVDS18
VCCO是1.8V
VOH是高电平最大1.675V
VOL 低电平最小0.825V
VODIFF 差模电压最大600mv,最小247mv,典型值350mv
VOCM 输出共模电压,最小1V最大1.425V,典型值1.25V
VIDIFF 输入差模电压,最大600mv,最小100mv,典型350mv
VICM输入共模电压,最大1.5V,最小0.3V,典型1.2V
LVDS器件电气特性是否兼容主要看,VODIF,VOCM,VIDIFF,VICM,可以看到,LVDS25 和LVDS的差分电气特性是兼容的。
5LVDS 电平兼容
对于HPBANK 即便是BANK电压VCCO不是1.8V,也可以使用LVDS输入,但是LVDS输出或者双向LVDS
通信,BANK电压必须是1.8V
对于HR或者HDBANK即便是BANK电压VCCO不是2.5V也可以使用LVDS_25输入,但是LVDS_25输出
或者双向LVDS_25通信,BANK电压必须是2.5V
如果电平标准无法满足要求,可以采用外部电路实现差分信号的电平转换,下图就是典型的方案,该电路使用交流耦合,并且对输入信号直流偏置,通过RBIAS的电阻产生VCCO/2的VICM电平。电容的典型值时100nF,电阻的范围为10K~100K。
以下两张图来自于XILINX官网,用户在硬件设计的时候可以用于评估LVDS的兼容特性
当和其他LVDS外设通信时,可以通过以上两张表以及本文4LVDS电气特性小节,判断电气特性是否兼容。
源码
module lvds_loop(
//sytem clk input
//input clk_i,
input clk_i_p,
input clk_i_n,
output card_en_o,
//uart
input uart_rx_i,
output uart_tx_o,
//lvds loop input
input dclki_p,
input dclki_n,
input din_p,
input din_n,
//lvds loop output
output dclko_p,
output dclko_n,
output dout_p,
output dout_n
);
assign card_en_o = 1'b1;
wire clk50m,clk5m,dclki,din;
reg uart_rx_r=1'b0;
clk_wiz_0 uclk(.clk_out1(clk50m),.clk_out2(clk5m), .clk_in1_p(clk_i_p),.clk_in1_n(clk_i_n));
//clk_wiz_0 uclk(.clk_out1(clk50m),.clk_out2(clk5m), .clk_in1(clk_i));
//lvds out
OBUFDS #(
.IOSTANDARD("DEFAULT"), // Specify the output I/O standard
.SLEW("SLOW")
)
dclko_OBUFDS
(
.O (dclko_p ),
.OB (dclko_n ),
.I (clk50m )
);
OBUFDS #(
.IOSTANDARD("DEFAULT"), // Specify the output I/O standard
.SLEW("SLOW")
)
dout_OBUFDS
(
.O (dout_p ),
.OB (dout_n ),
.I (uart_rx_i)
);
//lvds in
IBUFDS
#(
.DIFF_TERM("TRUE"), // Differential Termination
.IBUF_LOW_PWR("TRUE"), // Low power="TRUE", Highest performance="FALSE"
.IOSTANDARD("DEFAULT") // Specify the input I/O standard
)
dclki_IBUFDS
(
.O(dclki), // 1-bit output: Buffer output
.I(dclki_p), // 1-bit input: Diff_p buffer input (connect directly to top-level port)
.IB(dclki_n) // 1-bit input: Diff_n buffer input (connect directly to top-level port)
);
IBUFDS
#(
.DIFF_TERM("TRUE"), // Differential Termination
.IBUF_LOW_PWR("TRUE"), // Low power="TRUE", Highest performance="FALSE"
.IOSTANDARD("DEFAULT") // Specify the input I/O standard
)
ddatai_IBUFDS
(
.O(din), // 1-bit output: Buffer output
.I(din_p), // 1-bit input: Diff_p buffer input (connect directly to top-level port)
.IB(din_n) // 1-bit input: Diff_n buffer input (connect directly to top-level port)
);
always @(posedge dclki)begin
uart_rx_r <= din;
end
assign uart_tx_o = uart_rx_r;
ila_0 ila_dg (
.clk(clk50m),
.probe0({clk5m,uart_rx_i,din,uart_tx_o})
);
endmodule