37 基于FPGA的LVDS信号环路测试

发布时间 2023-12-29 18:49:32作者: 米联客(milianke)

软件版本:VIVADO2021.1

操作系统:WIN10 64bit

硬件平台:适用XILINX A7/K7/Z7/ZU/KU系列FPGA

登录米联客(MiLianKe)FPGA社区-www.uisrc.com观看免费视频课程、在线答疑解惑!

1 概述

LVDS(Low Voltage Differential Signalin)是一种低振幅差分信号技术。它使用幅度非常低的信号(约350mV)通过一对差分PCB走线或平衡电缆传输数据。大部分高速数据传输中,都会用到LVDS传输。

目前FPGA开发板资料中涉及LVDS通信的方案并不多,但是LVDS实际上有大量的应用,特别是在高速ADC,高分辨率摄像头,液晶屏显示技术等应用领域。所以掌握LVDS通信也是我们FPGA开发者的必备基本技能。本文首先简要介绍一些XILINX FPGA的LVDS解决方案,然后再通过一个简单的环路测试对LVDS通信做一个简单的验证测试。

2 XILINX FPGA差分信号解决方案

2.1 IBUFDS差分输入

对应原语

   IBUFDS #(

      .DIFF_TERM("FALSE"),       // "FALSE"=不使用内部终端电阻,"TRUE"=使用内部终端电阻

      .IBUF_LOW_PWR("TRUE"),     // "TRUE"=高性能,"FALSE" =低功耗

      .IOSTANDARD("DEFAULT")     // 设置输入电平属性

   ) IBUFDS_inst (

      .O(O),  // IO buffer输出

      .I(I),  // 差分输入P端

      .IB(IB) // 差分输入N端

   );

2.2 OBUFDS差分输出

对应原语

   OBUFDS #(

      .IOSTANDARD("DEFAULT"), // IO电平属性

      .SLEW("SLOW")           // IO的压摆率,"SLOW"或者"FAST"

// FAST压摆率可以满足高性能需求,例如高速存储器接口,但是,如果不能恰当设计(端接匹配,传输线阻抗控制和串扰耦合),更高的压摆率输出会导致信号反射或者产生噪声问题。

   ) OBUFDS_inst (

      .O(O),     // 差分输出P端

      .OB(OB),   // 差分输出N端

      .I(I)      // 内部输入信号

   );

2.3 IOBUFDS双向差分IO

对应原语

   IOBUFDS #(

      .DIFF_TERM("FALSE"),     // "FALSE"=不使用内部终端电阻,"TRUE"=使用内部终端电阻

      .IBUF_LOW_PWR("TRUE"),   // "TRUE"=低功耗, "FALSE"=高性能

      .IOSTANDARD("BLVDS_25"), // 设置IP电平属性

      .SLEW("SLOW")            // IO的压摆率,"SLOW"或者"FAST",FAST压摆率可以满足高性能需求,例如高速存储器接口,但是,如果不能恰当设计(端接匹配,传输线阻抗控制和串扰耦合),更高的压摆率输出会导致信号反射或者产生噪声问题。

   ) IOBUFDS_inst (

      .O(O),     // 缓冲输出

      .IO(IO),   // 差分IO P

      .IOB(IOB), // 差分 IO N

      .I(I),     // 缓冲输入

      .T(T)      // 3态使能, high=输入, low=输出

   );

3 LVDS中的终端电阻

如果要使用内部的终端电阻,对于HP的LVDS信号BANK电压必须是1.8V,而对于HR的LVDS25 BANK信号必须是2.5V,否则可以使用外部终端电阻。

4 LVDS电气特性

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

4.2 LVDS

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的差分电气特性是兼容的。

5 LVDS电平兼容

对于HP BANK 即便是BANK电压VCCO不是1.8V,也可以使用LVDS输入,但是LVDS输出或者双向LVDS通信,BANK电压必须是1.8V

对于HR或者HD BANK即便是BANK电压VCCO不是2.5V也可以使用LVDS_25输入,但是LVDS_25输出或者双向LVDS_25通信,BANK电压必须是2.5V

如果电平标准无法满足要求,可以采用外部电路实现差分信号的电平转换,下图就是典型的方案,该电路使用交流耦合,并且对输入信号直流偏置,通过RBIAS的电阻产生VCCO/2的VICM电平。电容的典型值时100nF,电阻的范围为10K~100K

以下两张图来自于XILINX官网,用户在硬件设计的时候可以用于评估LVDS的兼容特性

当和其他LVDS外设通信时,可以通过以上两张表以及本文28.4LVDS电气特性小节,判断电气特性是否兼容。

6 硬件电路分析

硬件接口和子卡模块请阅读"附录 1"

配套工程的 FPGA PIN 脚定义路径为 soc_prj/uisrc/04_pin/ fpga_pin.xdc。

7 测试代码

测试采用PC上通过串口发送数据到开发板,然后经过外部的LVDS环路后把串口数据传回电脑。例子虽然简单,但是可以展示LVDS接口的基本用法。

`timescale 1ns / 1ns

 

module lvds_loop

(

input I_sysclk,//系统时钟信号输入

input I_uart_rx,//UART数据信号接收

output O_uart_tx,//UART数据信号发送

//lvds 差分输入

input I_dclk_p,//差分输入时钟信号p端

input I_dclk_n,//差分输入时钟信号n端

input I_din_p,//差分数据输入信号p端

input I_din_n,//差分数据输入信号n端

//lvds 差分输出

output O_dclk_p,//差分时钟输出信号p端

output O_dclk_n,//差分时钟输出信号n端

output O_dout_p,//差分数据输出信号p端

output O_dout_n//差分数据输出信号n端

);

 

wire clk50m,clk5m,dclki,din;

reg uart_rx_r=1'b0;

 

//使用pll产生50mhz时钟和5mhz时钟

clk_wiz_0 uclk(.clk_out1(clk50m),.clk_out2(clk5m), .clk_in1(I_sysclk));

 

//单端转差分输出部分

//内部单端时钟转为差分信号输出

OBUFDS #(

.IOSTANDARD("DEFAULT"), // IO电平属性

.SLEW("SLOW")           // IO的压摆率,"SLOW"或者"FAST"

                         // FAST压摆率可以满足高性能需求,例如高速存储器接口,但是,如果不能恰当设计(端接匹配,传输线阻抗控制和串扰耦合),更高的压摆率输出会导致信号反射或者产生噪声问题。

)

OBUFDS_DCLK_O_inst (

.O(O_dclk_p),     // 差分输出P端

.OB(O_dclk_n),   // 差分输出N端

.I(clk50m)      // 内部输入信号

);

 

//接收的uart_rx信号转为差分输出

OBUFDS #(

.IOSTANDARD("DEFAULT"), // IO电平属性

.SLEW("SLOW")           // IO的压摆率,"SLOW"或者"FAST"

                         // FAST压摆率可以满足高性能需求,例如高速存储器接口,但是,如果不能恰当设计(端接匹配,传输线阻抗控制和串扰耦合),更高的压摆率输出会导致信号反射或者产生噪声问题。

)

OBUFDS_DOUT_inst (

.O(O_dout_p),     // 差分输出P端

.OB(O_dout_n),    // 差分输出N端

.I(I_uart_rx)   // 内部输入信号

);

 

 

 

//单端转差分输入部分

//差分时钟转为单端内部时钟信号

IBUFDS #(

.DIFF_TERM("FALSE"),       // "FALSE"=不使用内部终端电阻,"TRUE"=使用内部终端电阻

.IBUF_LOW_PWR("TRUE"),     // "TRUE"=低功耗,"FALSE" =高性能

.IOSTANDARD("DEFAULT")    // 设置输入电平属性

)

IBUFDS_DCLK_I_inst (

.O(dclki),   // IO buffer输出到内部信号

.I(I_dclk_p), // 差分输入P端

.IB(I_dclk_n) // 差分输入N端

);

 

 

//接收的差分数据转为内部单端数据信号

IBUFDS #(

.DIFF_TERM("FALSE"),       // "FALSE"=不使用内部终端电阻,"TRUE"=使用内部终端电阻

.IBUF_LOW_PWR("TRUE"),     // "TRUE"=低功耗,"FALSE" =高性能

.IOSTANDARD("DEFAULT")    // 设置输入电平属性

)

IBUFDS_DIN_inst (

.O(din),   // IO buffer输出到内部信号

.I(I_din_p), // 差分输入P端

.IB(I_din_n) // 差分输入N端

);

 

 

//在FPGA内部,把接收的din寄存到uart_rx_r

always @(posedge dclki)begin

    uart_rx_r <= din;

end

 

assign O_uart_tx = uart_rx_r;//通过assign 把接收的环路数据,直接给O_uart_tx

 

 

//通过ila在线逻辑分析仪,下载bit后,在线调试观察内部的数据信号

ila_0 ila_dg (

    .clk(clk50m),

    .probe0({clk5m,I_uart_rx,din,O_uart_tx})

);    

 

endmodule

 

8 仿真结果

仿真中修改前面文章中使用的tb_uart_top.v文件,模拟串口的发送,并且观察经过LVDS之后的环路输出结果是否正确,通过这种简单的办法验证代码功能,对于硬件板卡不支持LVDS的开发板可以如此验证。

9 硬件接线

(该教程为通用型教程,教程中仅展示一款示例开发板的连接方式,具体连接方式以所购买的开发板型号以及结合配套代码管脚约束为准。)

我们使用米联客1.8V的 BASE子卡。请确保下载器和开发板已经正确连接,并且开发板已经上电。(注意JTAG端子不支持热插拔,而USB接口支持,所以在不通电的情况下接通好JTAG后,再插入USB到电脑,之后再上电,以免造成JTAG IO损坏)

10 测试结果

由于串口速度很慢,我们使用lia的capture模式才能抓到更多数据,以下是IP CORE的设置

以下是下载Bit后设置Capture模式的采样信号,这里用了5MHZ的时钟信号 上升沿作为采样信号

I_uart_rx为低电平触发

 

在线仿真抓取的波形

串口助手接收收发测试