一.應用情景概述
在以往的Cameralink相機采集中,通常會有協定解碼晶片,但如今,在不使用解碼晶片的情況下,直接由相機直接用Cameralink标準協定過LVDS直接把資料傳輸至FPGA。
二.協定介紹
一根時鐘線,其餘四根為資料線。均采用差分方式LVDS标準輸出至FPGA。
時鐘頻率固定為25MHZ并不是(175MHZ),每7個資料共用一個時鐘周期。具體資料位如圖所示:
點号定義如下:
三.解碼方式
由于沒有解碼晶片,是以需要在FPGA子產品設計時,在采集子產品之前設計一個并轉串的子產品。區分出行場同步信号以及資料信号即一個時鐘對應相應的資料位和相應的同步信号。以下為解碼部分的具體實作。
1>差分信号變單端信号:
由于是5對LVDS差分信号對直接與FPGA直接相連,是以需要使用原語(xilinx K7)将差分信号轉化為單端信号。
IBUFDS #(
.DIFF_TERM("true"), // Differential Termination
.IBUF_LOW_PWR("FALSE"), // Low power="TRUE", Highest performance="FALSE"
.IOSTANDARD("LVDS") // Specify the input I/O standard
) IBUFDS_inst0 (
.O(data_in_to_device[0]), // Buffer output
.I(data_in_from_pins_p[0]), // Diff_p buffer input (connect directly to top-level port)
.IB(data_in_from_pins_n[0]) // Diff_n buffer input (connect directly to top-level port)
);
IBUFDS #(
.DIFF_TERM("true"), // Differential Termination
.IBUF_LOW_PWR("FALSE"), // Low power="TRUE", Highest performance="FALSE"
.IOSTANDARD("LVDS") // Specify the input I/O standard
) IBUFDS_inst1 (
.O(data_in_to_device[1]), // Buffer output
.I(data_in_from_pins_p[1]), // Diff_p buffer input (connect directly to top-level port)
.IB(data_in_from_pins_n[1]) // Diff_n buffer input (connect directly to top-level port)
);
IBUFDS #(
.DIFF_TERM("true"), // Differential Termination
.IBUF_LOW_PWR("FALSE"), // Low power="TRUE", Highest performance="FALSE"
.IOSTANDARD("LVDS") // Specify the input I/O standard
) IBUFDS_inst2 (
.O(data_in_to_device[2]), // Buffer output
.I(data_in_from_pins_p[2]), // Diff_p buffer input (connect directly to top-level port)
.IB(data_in_from_pins_n[2]) // Diff_n buffer input (connect directly to top-level port)
);
IBUFDS #(
.DIFF_TERM("true"), // Differential Termination
.IBUF_LOW_PWR("FALSE"), // Low power="TRUE", Highest performance="FALSE"
.IOSTANDARD("LVDS") // Specify the input I/O standard
) IBUFDS_inst3 (
.O(data_in_to_device[3]), // Buffer output
.I(data_in_from_pins_p[3]), // Diff_p buffer input (connect directly to top-level port)
.IB(data_in_from_pins_n[3]) // Diff_n buffer input (connect directly to top-level port)
);
IBUFDS #(
.DIFF_TERM("true"), // Differential Termination
.IBUF_LOW_PWR("FALSE"), // Low power="TRUE", Highest performance="FALSE"
.IOSTANDARD("LVDS") // Specify the input I/O standard
) IBUFDS_inst4 (
.O(clk_out), // Buffer output
.I(clk_in_p), // Diff_p buffer input (connect directly to top-level port)
.IB(clk_in_n) // Diff_n buffer input (connect directly to top-level port)
);
由此就變成了五根單端信号線,然後再對這五根信号線進行操作。
2>串轉并
再看一遍時序圖:
五根單端信号如上圖所示,由于7個bit公用一個時鐘,是以我們要用175M= 25M*7 的時鐘來采集25M時鐘線的上升沿。具體verliog代碼如下:
always @(posedge inClk175M)
begin
if(~inRstn)begin
regState <= cIDLE;
regFifo_Din28 <= 0;
regRiseCnt16 <= 0;
end else begin
case(regState)
cIDLE:begin
if(regClkSyncRise[1]==1)begin
regRiseCnt16 <= regRiseCnt16 + 1;
regFifo_Din28[23] <= regDataSync[3];
regFifo_Din28[26] <= regDataSync[2];
regFifo_Din28[18] <= regDataSync[1];
regFifo_Din28[7] <= regDataSync[0];
if(regRiseCnt16==16'hFFFF)
regState <= cS1;
end
end
cS1:begin
regFifo_Din28[17] <= regDataSync[3];
regFifo_Din28[25] <= regDataSync[2];
regFifo_Din28[15] <= regDataSync[1];
regFifo_Din28[6] <= regDataSync[0];
regState <= cS2;
end
cS2:begin
regFifo_Din28[16] <= regDataSync[3];
regFifo_Din28[24] <= regDataSync[2];
regFifo_Din28[14] <= regDataSync[1];
regFifo_Din28[4] <= regDataSync[0];
regState <= cS3;
end
cS3:begin
regFifo_Din28[11] <= regDataSync[3];
regFifo_Din28[22] <= regDataSync[2];
regFifo_Din28[13] <= regDataSync[1];
regFifo_Din28[3] <= regDataSync[0];
regState <= cS4;
end
cS4:begin
regFifo_Din28[10] <= regDataSync[3];
regFifo_Din28[21] <= regDataSync[2];
regFifo_Din28[12] <= regDataSync[1];
regFifo_Din28[2] <= regDataSync[0];
regState <= cS5;
end
cS5:begin
regFifo_Din28[5] <= regDataSync[3];
regFifo_Din28[20] <= regDataSync[2];
regFifo_Din28[9] <= regDataSync[1];
regFifo_Din28[1] <= regDataSync[0];
regState <= cS6;
end
cS6:begin
regFifo_Din28[27] <= regDataSync[3];
regFifo_Din28[19] <= regDataSync[2];
regFifo_Din28[8] <= regDataSync[1];
regFifo_Din28[0] <= regDataSync[0];
regState <= cS7;
regFifo_WrEn <= 1;
end
cS7:begin
regFifo_Din28[23] <= regDataSync[3];
regFifo_Din28[26] <= regDataSync[2];
regFifo_Din28[18] <= regDataSync[1];
regFifo_Din28[7] <= regDataSync[0];
regFifo_WrEn <= 0;
regState <= cS1;
end
endcase
end
end
由于有跨時鐘域操作,是以需要将這些資料寫入異步FIFO。在判斷好第一個上升沿之後,将資料每七個時鐘(175M)寫入一次,采集到一次上升沿之後一直循環不再判斷25M的上升沿。