Xilinx FPGA 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/06
NET "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~FF
reg [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位數據datain
s_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的接收時鍾。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM