gaochy1126 发表于 2022-3-31 22:49

FPGA LVDS

最近项目需要用到差分信号传输,于是看了一下FPGA上差分信号的使用。Xilinx FPGA中,主要通过原语实现差分信号的收发:OBUFDS(差分输出BUF),IBUFDS(差分输入BUF)。注意在分配引脚时,只需要分配SIGNAL_P的引脚,SIGNAL_N会自动连接到相应差分对引脚上;若没有使用差分信号原语,则在引脚电平上没有LVDS的选项(IO Planning PlanAhead)。测试代码:https://www.pianshen.com/images/771/48304ba5e6f9fe08f3fa1abda7d326ab.gif//////////////////////////////////////////////////////////////////////////////////module lvds_test(      sys_clk,    sys_rst,      signal_in_p,    signal_in_n,    signal_out_p,    signal_out_n,      led_signal);inputsys_clk;inputsys_rst;inputsignal_in_p;inputsignal_in_n;output signal_out_p;output signal_out_n;output led_signal;wire signal_out_temp;reg clk_cnt;always @ (posedge sys_clk) begin    if(!sys_rst)         clk_cnt <= 32'd0;    else begin      if(clk_cnt == 32'd10_000_000) clk_cnt <= 32'd0;            else clk_cnt <= clk_cnt+1'b1;    endendassign signal_out=(clk_cnt >= 32'd5_000_000) ? 1 : 0;OBUFDS signal_out_diff(    .O(signal_out_p),    .OB(signal_out_n),    .I(signal_out));IBUFDS signal_in_diff(   .O(led_signal),    .I(signal_in_p),    .IB(signal_in_n));endmodulehttps://www.pianshen.com/images/771/48304ba5e6f9fe08f3fa1abda7d326ab.gif约束文件:https://www.pianshen.com/images/771/48304ba5e6f9fe08f3fa1abda7d326ab.gifNET "signal_out_p" IOSTANDARD = LVDS_33;NET "signal_out_p" LOC = U16;NET "sys_clk" IOSTANDARD = LVCMOS33;NET "sys_rst" IOSTANDARD = LVCMOS33;NET "led_signal" LOC = D18;NET "led_signal" IOSTANDARD = LVCMOS33;#Created by Constraints Editor (xc6slx45t-csg324-3) - 2016/06/06NET "sys_clk" TNM_NET = "sys_clk";TIMESPEC TS_sys_clk = PERIOD "sys_clk" 50 MHz HIGH 50 %;NET "signal_in_p" LOC = T12;NET "signal_in_n" LOC = V12;NET "sys_clk" LOC = G8;NET "sys_rst" LOC = U3;# PlanAhead Generated IO constraints NET "signal_in_p" IOSTANDARD = LVDS_33;https://www.pianshen.com/images/771/48304ba5e6f9fe08f3fa1abda7d326ab.gif约束文件IO Planning PlanAhead产生,原语的使用可参考:E:\Xilinx\ISE\14.7\ISE_DS\ISE\doc\usenglish\isehelp\spartan6里面提供了所用器件的原语。同时,Xilinx器件内部信号内部还提供了100欧姆电阻匹配,可参考Spartan-6 FPGA SelectIO Resources(UG381)若要实现高速通信的场合,可以利用FPGA内部自带的SelectIO资源,利用ISERDESE2、 OSERDESE2,实现串-并,并-串的转换,理论速度可达到750Mbs;参考资料:Spartan-6 FPGA Data Sheet: DC and Switching Characteristics(UG162)https://www.pianshen.com/images/910/cff7e52c620c560266cf9292c6d6e0ee.png通信框图:https://www.pianshen.com/images/660/de49569464b20e940b2a5adda3cac44c.png因为串行转成并行的时候,输出的数据无法判断哪个 Bit 是高位,哪个 bit 是低位,因此,对于 ISERDESE2 可以利用bitslip 信号来重新对齐串行数据以获得正确的字节数据;代码实现时,也需要先进行数据对齐,才能进行数据的正常接收。

gaochy1126 发表于 2022-3-31 22:50



https://www.pianshen.com/images/771/48304ba5e6f9fe08f3fa1abda7d326ab.gif`timescale 1ns / 1ps//////////////////////////////////////////////////////////////////////////////////module lvds_test(    input clk_50m,//全局时钟    input rstn, //复位      input clk_in_from_pin_p,         //lvds时钟输出P    input clk_in_from_pin_n,         //lvds时钟输入N    input data_in_from_pin_p,      //lvds输入数据P    input data_in_from_pin_n,      //lvds输入数据N      output clk_out_to_pin_p,         //lvds时钟输出P    output clk_out_to_pin_n,         //lvds时钟输出N    output data_out_to_pin_p,      //lvds输出数据P    output data_out_to_pin_n         //lvds输出数据N      );wire clk_div_out_1;   //低速时钟1,串行发送时钟的8分频wire clk_div_out_2;   //低速时钟2,串行接收时钟的8分频wire datain;      //LVDS输入的8位并行数据//产生LVDS发送的测试数据,0~FFreg dataout;always @(posedge clk_div_out_1) begin    if (~rstn)         dataout <= 0;    else if (dataout == 8'hff)      dataout <= 0;    else         dataout <= dataout + 1'b1;   end//产生BITSLIP信号,用于修改串转并的Bit的起始位置wire data_delay;reg      BITSLIP=1'b0;reg      slip_check;reg      equal=1'b0;assign data_delay = datain;always @(posedge clk_div_out_2) begin    if (~rstn)         slip_check <= 1'b0;    else if(data_delay==8'h80)      //当串转并的输入的数据为0x80的时候,检测开始      slip_check <= 1'b1;          else      slip_check <= 1'b0;      endalways @(posedge clk_div_out_2) begin    if (~rstn) begin      BITSLIP <= 1'b0;      equal<=1'b0;            end else if((slip_check==1'b1) && (equal==1'b0))      if (data_delay ==8'h81) begin//如果检测到数据0x80后面的下一个时钟的数据为0x81时            BITSLIP <= 1'b0;         //BITSLIP不为高            equal<=1'b1;               //数据正确信号为高                  end      else begin            BITSLIP <= 1'b1;         //BITSLIP产生一个高脉冲,改变串转并的数据排列            equal<=1'b0;               //数据正确信号为低      end         else begin      BITSLIP <= 1'b0;      equal<=equal;      end            end          //并转串,8位数据dataout转换成串行数据,并通过lvds差分信号输出p_to_s p_to_s_inst (    // From the device out to the system    .DATA_OUT_FROM_DEVICE (dataout), //Input pins    .DATA_OUT_TO_PINS_P   (data_out_to_pin_p), //Output pins    .DATA_OUT_TO_PINS_N   (data_out_to_pin_n), //Output pins    .CLK_TO_PINS_P      (clk_out_to_pin_p),//Output pins    .CLK_TO_PINS_N      (clk_out_to_pin_n),//Output pins    .CLK_IN               (clk_50m),         // Single ended clock from IOB    .CLK_DIV_OUT          (clk_div_out_1),   // Slow clock output    .IO_RESET             (~rstn)//system reset);//串转并,LVDS差分信号转换成单端信号再通过串转并,转换为8位数据datains_to_p s_to_p_inst(    // From the system into the device    .DATA_IN_FROM_PINS_P(data_in_from_pin_p), //Input pins    .DATA_IN_FROM_PINS_N(data_in_from_pin_n), //Input pins    .DATA_IN_TO_DEVICE(datain),               //Output pins    .BITSLIP(BITSLIP), //Input pin    .CLK_IN_P(clk_in_from_pin_p),      // Differential clock from IOB    .CLK_IN_N(clk_in_from_pin_n),      // Differential clock from IOB    .CLK_DIV_OUT(clk_div_out_2),       // Slow clock output    .IO_RESET(~rstn)                   //system reset);endmoduleendmodulehttps://www.pianshen.com/images/771/48304ba5e6f9fe08f3fa1abda7d326ab.gif其中,clk_div_out_1和clk_div_out_2是8分频得到的(ISERDESE2、 OSERDESE2核实现),OSERDESE2输出的LVDS 差分时钟可作为ISERDESE2的接收时钟。
页: [1]
查看完整版本: FPGA LVDS