大俠好,歡迎來到FPGA技術(shù)江湖,江湖偌大,相見即是緣分。大俠可以關(guān)注FPGA技術(shù)江湖,在“闖蕩江湖”、"行俠仗義"欄里獲取其他感興趣的資源,或者一起煮酒言歡。
今天給大俠帶來 Xilinx ISE14.7 LVDS應(yīng)用,話不多說,上貨。
最近項(xiàng)目需要用到差分信號(hào)傳輸,于是看了一下FPGA上差分信號(hào)的使用。Xilinx FPGA中,主要通過原語實(shí)現(xiàn)差分信號(hào)的收發(fā):OBUFDS(差分輸出BUF),IBUFDS(差分輸入BUF)。
注意在分配引腳時(shí),只需要分配SIGNAL_P的引腳,SIGNAL_N會(huì)自動(dòng)連接到相應(yīng)差分對(duì)引腳上;若沒有使用差分信號(hào)原語,則在引腳電平上沒有LVDS的選項(xiàng)(IO Planning PlanAhead)。
測(cè)試代碼:
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產(chǎn)生,原語的使用可參考:E:XilinxISE14.7ISE_DSISEdocusenglishisehelpspartan6里面提供了所用器件的原語。
同時(shí),Xilinx器件內(nèi)部信號(hào)內(nèi)部還提供了100歐姆電阻匹配,可參考Spartan-6 FPGA?SelectIO Resources(UG381)
補(bǔ)充:
若要實(shí)現(xiàn)高速通信的場(chǎng)合,可以利用FPGA內(nèi)部自帶的SelectIO資源,利用ISERDESE2、 OSERDESE2,實(shí)現(xiàn)串-并,并-串的轉(zhuǎn)換,理論速度可達(dá)到750Mbs,
參考資料:Spartan-6 FPGA Data Sheet: DC and Switching Characteristics(UG162)
通信框圖:
因?yàn)榇修D(zhuǎn)成并行的時(shí)候,輸出的數(shù)據(jù)無法判斷哪個(gè) Bit 是高位,哪個(gè) bit 是低位,因此,對(duì)于 ISERDESE2 可以利用bitslip 信號(hào)來重新對(duì)齊串行數(shù)據(jù)以獲得正確的字節(jié)數(shù)據(jù);代碼實(shí)現(xiàn)時(shí),也需要先進(jìn)行數(shù)據(jù)對(duì)齊,才能進(jìn)行數(shù)據(jù)的正常接收。
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
module lvds_test(
input clk_50m,//全局時(shí)鐘
input rstn, //復(fù)位
input clk_in_from_pin_p, //lvds時(shí)鐘輸出P
input clk_in_from_pin_n, //lvds時(shí)鐘輸入N
input data_in_from_pin_p, //lvds輸入數(shù)據(jù)P
input data_in_from_pin_n, //lvds輸入數(shù)據(jù)N
output clk_out_to_pin_p, //lvds時(shí)鐘輸出P
output clk_out_to_pin_n, //lvds時(shí)鐘輸出N
output data_out_to_pin_p, //lvds輸出數(shù)據(jù)P
output data_out_to_pin_n //lvds輸出數(shù)據(jù)N
);
wire clk_div_out_1; //低速時(shí)鐘1,串行發(fā)送時(shí)鐘的8分頻
wire clk_div_out_2; //低速時(shí)鐘2,串行接收時(shí)鐘的8分頻
wire [7:0] datain; //LVDS輸入的8位并行數(shù)據(jù)
//產(chǎn)生LVDS發(fā)送的測(cè)試數(shù)據(jù),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
//產(chǎn)生BITSLIP信號(hào),用于修改串轉(zhuǎn)并的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) //當(dāng)串轉(zhuǎn)并的輸入的數(shù)據(jù)為0x80的時(shí)候,檢測(cè)開始
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 //如果檢測(cè)到數(shù)據(jù)0x80后面的下一個(gè)時(shí)鐘的數(shù)據(jù)為0x81時(shí)
BITSLIP <= 1'b0; //BITSLIP不為高
equal<=1'b1; //數(shù)據(jù)正確信號(hào)為高
end
else begin
BITSLIP <= 1'b1; //BITSLIP產(chǎn)生一個(gè)高脈沖,改變串轉(zhuǎn)并的數(shù)據(jù)排列
equal<=1'b0; //數(shù)據(jù)正確信號(hào)為低
end
else begin
BITSLIP <= 1'b0;
equal<=equal;
end
end
//并轉(zhuǎn)串,8位數(shù)據(jù)dataout轉(zhuǎn)換成串行數(shù)據(jù),并通過lvds差分信號(hào)輸出
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
);
//串轉(zhuǎn)并,LVDS差分信號(hào)轉(zhuǎn)換成單端信號(hào)再通過串轉(zhuǎn)并,轉(zhuǎn)換為8位數(shù)據(jù)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核實(shí)現(xiàn)),OSERDESE2輸出的LVDS 差分時(shí)鐘可作為ISERDESE2的接收時(shí)鐘。