LVDS(Low Voltage Differential Signalin)是一种低振幅差分信号技术。它使用幅度非常低的信号(约350mV)通过一对差分PCB走线或平衡电缆传输数据。大部分高速数据传输中,都会用到LVDS传输。
目前FPGA开发板资料中涉及LVDS通信的方案并不多,但是LVDS实际上有大量的应用,特别是在高速ADC,
高分辨率摄像头,液晶屏显示技术等应用领域。所以掌握LVDS通信也是我们FPGA开发者的必备基本技能。本文首先简要介绍一些XILINXFPGA的LVDS解决方案,然后再通过一个简单的环路测试对LVDS通信做一个简单的验证测试。
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)
);
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
);
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
);
如果要使用内部的终端电阻,对于HP的LVDS信号BANK电压必须是1.8V,而对于HR的LVDS25BANK
信号必须是2.5V,否则可以使用外部终端电阻。
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
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的差分电气特性是兼容的。
对于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