硬件研发网|技术阅读
登录|注册

您现在的位置是:硬件研发网 > 技术阅读 > FPGA | Xilinx ISE14.7 LVDS应用

FPGA | Xilinx ISE14.7 LVDS应用


大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。



今天给大侠带来 Xilinx ISE14.7 LVDS应用,话不多说,上货。



最近项目需要用到差分信号传输,于是看了一下FPGA上差分信号的使用。Xilinx FPGA中,主要通过原语实现差分信号的收发:OBUFDS(差分输出BUF),IBUFDS(差分输入BUF)。


注意在分配引脚时,只需要分配SIGNAL_P的引脚,SIGNAL_N会自动连接到相应差分对引脚上;若没有使用差分信号原语,则在引脚电平上没有LVDS的选项(IO Planning PlanAhead)。


测试代码:

module lvds_test( sys_clk, sys_rst, signal_in_p, signal_in_n, signal_out_p, signal_out_n, led_signal );
input sys_clk,sys_rst; input signal_in_p,signal_in_n; output signal_out_p,signal_out_n; output led_signal;
wire signal_out_temp; reg[31:0] 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; end end assign 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) ); endmodule


约束文件:
NET "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;

约束文件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)



通信框图:


因为串行转成并行的时候,输出的数据无法判断哪个 Bit 是高位,哪个 bit 是低位,因此,对于 ISERDESE2 可以利用bitslip 信号来重新对齐串行数据以获得正确的字节数据;代码实现时,也需要先进行数据对齐,才能进行数据的正常接收。


`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 [7:0] datain; //LVDS输入的8位并行数据
//产生LVDS发送的测试数据,0~FFreg [7:0] 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 [7:0] 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; end
always @(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);
endmodule


其中,clk_div_out_1和clk_div_out_2是8分频得到的(ISERDESE2、 OSERDESE2核实现),OSERDESE2输出的LVDS 差分时钟可作为ISERDESE2的接收时钟。




END
后续会持续更新,带来Vivado、 ISE、Quartus II 、candence等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。
大侠们,江湖偌大,继续闯荡,愿一切安好,有缘再见!


往期精选 

  










FPGA技术江湖广发江湖帖

无广告纯净模式,给技术交流一片净土,从初学小白到行业精英业界大佬等,从军工领域到民用企业等,从通信、图像处理到人工智能等各个方向应有尽有,QQ微信双选,FPGA技术江湖打造最纯净最专业的技术交流学习平台。


FPGA技术江湖微信交流群

加群主微信,备注职业+方向+名字进群


FPGA技术江湖QQ交流群

备注地区+职业+方向+名字进群