利用FPGA对cameralink的数据进行接收解码 不使用DS90CR288芯片,直接在FP...
当年接手这个项目时,客户甩过来一句"别用解码芯片",差点让我把开发板摔了。本人在xilinx(赛灵思)A7,K7,V7,zynq7,ultrascale以及ultrascale+ 系列的FPGA上已经验证通过,相关项目已经交付。本人在xilinx(赛灵思)A7,K7,V7,zynq7,ultrascale以及ultrascale+ 系列的FPGA上已经验证通过,相关项目已经交付。这个滑动窗口检测器
利用FPGA对cameralink的数据进行接收解码 不使用DS90CR288芯片,直接在FPGA内部进行解码。 本人在xilinx(赛灵思)A7,K7,V7,zynq7,ultrascale以及ultrascale+ 系列的FPGA上已经验证通过,相关项目已经交付。
直接手撕CameraLink协议这事,我劝你别随便试——除非你跟我一样经历过被28根差分线逼疯的夜晚。当年接手这个项目时,客户甩过来一句"别用解码芯片",差点让我把开发板摔了。但真啃下来才发现,X家的FPGA确实藏着不少宝贝。
先看CameraLink接口那堆蛇形走线,28对LVDS看着吓人其实结构清晰。重点在于理解它的时钟机制:两条差分时钟线CLK_P/N带着像素时钟,真正的玄机在上升沿和下降沿的双沿采样。这里直接上干货,LVDS接收部分的核心代码长这样:
genvar i;
generate for(i=0; i<28; i=i+1) begin : lvds_inputs
IBUFDS #(
.DIFF_TERM("TRUE"),
.IOSTANDARD("LVDS_25")
) ibufds_inst (
.I (camlink_data_p[i]),
.IB (camlink_data_n[i]),
.O (raw_data[i])
);
end endgenerate
这段代码里藏着两个关键点:DIFF_TERM开启差分终端电阻,这对信号完整性至关重要;IOSTANDARD必须严格匹配硬件设计。有次在UltraScale+板卡上翻车,就是因为忘了查Bank电压。
时钟恢复才是真正的硬仗。X家FPGA的IDDR原语这时候该出场了:
IDDR #(
.DDR_CLK_EDGE("SAME_EDGE_PIPELINED")
) iddr_inst (
.Q1(rx_data_even),
.Q2(rx_data_odd),
.C (pixel_clk),
.CE(1'b1),
.D (raw_data[0]),
.R (1'b0),
.S (1'b0)
);
注意这里的双沿采样策略,配合MMCM生成的相位偏移时钟。调试时用ILA抓波形,发现数据错位就调整CLKOUT0_PHASE参数,每次调0.5ns跟玩扭蛋机似的。
利用FPGA对cameralink的数据进行接收解码 不使用DS90CR288芯片,直接在FPGA内部进行解码。 本人在xilinx(赛灵思)A7,K7,V7,zynq7,ultrascale以及ultrascale+ 系列的FPGA上已经验证通过,相关项目已经交付。
数据对齐的骚操作必须提。CameraLink的传输格式里藏着Frame Valid和Line Valid信号,但某些相机厂商根本不按协议来。这时候得祭出移位寄存器大法:
always @(posedge pixel_clk) begin
shift_reg <= {shift_reg[55:0], aligned_data};
if(shift_reg[63:56] == 8'hF0) begin //自定义同步头
valid_data <= shift_reg[55:0];
data_ready <= 1'b1;
end
end
这个滑动窗口检测器帮我搞定了三家不同厂商的相机,其中一家的同步码居然用0xAA,气得我差点给他们的FAE寄刀片。
最后说点血泪教训:Vivado的Timing Constraints必须把CLKSETUPVIOLATION压到0.2ns以下,否则高温测试准掉链子。在Zynq-7000上跑DMA传输时,AXI总线带宽算错导致数据断流,后来上了双缓冲结构才解决。
现在这套架构在A7上只用不到15%的LUT资源,最狠的一个项目用V7同时接四路CameraLink还能跑满85MHz。别问我为什么不用IP核——自己写的代码,深夜调试时连报错信息都显得眉清目秀。

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)