0


FPGA实现cameralink接口图像传输

  1. 硬件芯片实现cameralink图像传输

常用的cameralink收发芯片有DS90CR287和288,287发送288接收。只需要向芯片提供像素时钟和cameralink协议中的28位数据信号就可以实现基本的图像数据传输非常方便。关于cameralink协议的常识详见http://t.csdn.cn/XtFud

同样地,接收方可以直接接收28位数据还原位图像数据信号。

发送端代码:

示例是之前做的16位红外相机上使用cameralink发送接收模块,使用的是287、288芯片,base模式

  1. /* Document info
  2. document class : RES
  3. module name : CameraLink_Out
  4. module purpose : video out
  5. version : V1.0
  6. author : mayidianzi
  7. */
  8. ///
  9. `timescale 1ns / 1ps
  10. module Clink(
  11. input I_img_frame,
  12. input I_img_line,
  13. input[15:0] I_img_data,
  14. input I_img_clk,
  15. output O_img_clk,
  16. output[27:0] O_tx_data
  17. );
  18. / parameter set \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  19. internal signal \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  20. //wire S_data_vld ;
  21. //wire S_data_vld_1 ;
  22. //wire S_img_clk ;
  23. //wire S_img_fram ;
  24. //wire S_img_line ;
  25. //wire[15:0] S_img_data ;
  26. //reg[2:0] S_count_t ;
  27. assign O_img_clk = I_img_clk;
  28. //assign S_data_vld = (S_count_t==1) ? 1 : 0;
  29. //assign S_data_vld_1 = S_data_vld & I_img_line;
  30. wire[7:0] S_port_a,S_port_b,S_port_c;
  31. assign S_port_a = I_img_data[7:0];
  32. assign S_port_b = I_img_data[15:8];
  33. assign S_port_c = 8'h0000;
  34. assign O_tx_data[4:0] = S_port_a[4:0];
  35. assign O_tx_data[5] = S_port_a[7];
  36. assign O_tx_data[6] = S_port_a[5];
  37. assign O_tx_data[9:7] = S_port_b[2:0];
  38. assign O_tx_data[11:10] = S_port_b[7:6];
  39. assign O_tx_data[14:12] = S_port_b[5:3];
  40. assign O_tx_data[15] = S_port_c[0];
  41. assign O_tx_data[17:16] = S_port_c[7:6];
  42. assign O_tx_data[22:18] = S_port_c[5:1];
  43. assign O_tx_data[23] = 0; //spare
  44. assign O_tx_data[24] = I_img_line; //LVAL,line valid
  45. assign O_tx_data[25] = I_img_frame; //FVAL,frame valid
  46. assign O_tx_data[26] = 1; //DVAL,data valid
  47. assign O_tx_data[27] = S_port_a[6];
  48. instance \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  49. ila_0 ila_0_i(
  50. .clk(I_img_clk),
  51. .probe0(I_img_data),
  52. .probe1(I_img_line),
  53. .probe2(I_img_frame)
  54. );
  55. main programe \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  56. endmodule

接收端代码

  1. /* Document info
  2. document class : RES
  3. module name : CameraLink_Out
  4. module purpose : video out
  5. version : V1.0
  6. author : mayidianzi
  7. */
  8. ///
  9. `timescale 1ns / 1ps
  10. module Clink_B(
  11. input[27:0] I_tx_data, //
  12. input I_reset,
  13. input I_img_clk,
  14. output reg[15:0] O_img_data, //S_sensor_data
  15. output reg O_img_frame, //S_sensor_FS
  16. output reg O_img_line //S_sensor_LINE
  17. );
  18. / parameter set \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  19. internal signal \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  20. //wire S_data_vld ;
  21. //wire S_data_vld_1 ;
  22. //wire S_img_clk ;
  23. wire S_img_frame ;
  24. wire S_img_line ;
  25. wire[15:0] S_img_data ;
  26. //reg[2:0] S_count_t ;
  27. //assign S_data_vld = (S_count_t==1) ? 1 : 0;
  28. //assign S_data_vld_1 = S_data_vld & I_img_line;
  29. wire[7:0] S_port_a,S_port_b,S_port_c;
  30. assign S_img_data[7:0] = S_port_a ;
  31. assign S_img_data[15:8]= S_port_b ;
  32. assign S_port_a[4:0] = I_tx_data[4:0] ;
  33. assign S_port_a[7] = I_tx_data[5] ;
  34. assign S_port_a[5] = I_tx_data[6] ;
  35. assign S_port_b[2:0] = I_tx_data[9:7] ;
  36. assign S_port_b[7:6] = I_tx_data[11:10] ;
  37. assign S_port_b[5:3] = I_tx_data[14:12] ;
  38. assign S_port_c[0] = I_tx_data[15] ;
  39. assign S_port_c[7:6] = I_tx_data[17:16] ;
  40. assign S_port_c[5:1] = I_tx_data[22:18] ;
  41. assign S_img_line = I_tx_data[24] ; //LVAL,line valid
  42. assign S_img_frame = I_tx_data[25] ; //FVAL,frame valid
  43. assign S_port_a[6] = I_tx_data[27] ;
  44. instance \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  45. ila_4 ila_4_i(
  46. .clk(I_img_clk),
  47. .probe0(O_img_data),
  48. .probe1(O_img_line),
  49. .probe2(O_img_frame),
  50. .probe3(I_img_clk)
  51. );
  52. main programe \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  53. always@(posedge I_img_clk or posedge I_reset)
  54. begin
  55. if(I_reset)
  56. begin
  57. O_img_data <= 0;
  58. O_img_frame <= 0;
  59. O_img_line <= 0;
  60. end
  61. else
  62. begin
  63. O_img_data <= S_img_data;
  64. O_img_frame <= S_img_frame;
  65. O_img_line <= S_img_line;
  66. end
  67. end
  68. endmodule
  1. FPGA编写cameralink接口模块传输

如果不使用芯片可以用verilog写一个发送接收模块,按照标准时序将28位数通过4条差分线输出,这里需要注意4条数据线的同步时钟是像素同步时钟的7倍,像素时钟不可太高。硬件布线方面注意所有的差分线要做等长。若接收端发现接收数据和采样时钟不同步可通过时钟模块适当调整同步时钟的相位。以上为调试过程的经验。

发送端代码:

同样是以16位红外相机为例,Base模式

  1. `timescale 1ns / 1ps
  2. //
  3. // Company:
  4. // Engineer:
  5. //
  6. // Create Date: 2022/03/22 08:31:08
  7. // Design Name:
  8. // Module Name: Clink
  9. // Project Name:
  10. // Target Devices:
  11. // Tool Versions:
  12. // Description:
  13. //
  14. // Dependencies:
  15. //
  16. // Revision:
  17. // Revision 0.01 - File Created
  18. // Additional Comments:
  19. //
  20. //
  21. module Clink(
  22. input I_336M_CLK,
  23. input I_reset,
  24. input[15:0] I_video_data,
  25. input I_frame_valid,
  26. input I_line_valid,
  27. output reg O_X0,
  28. output reg O_X1,
  29. output reg O_X2,
  30. output reg O_X3,
  31. output reg O_XCLK
  32. );
  33. //
  34. reg[7:0] S_cnt;
  35. reg[1:0] S_cnt0;
  36. reg[27:0] S_tx_data;
  37. reg S_frame_valid, S_line_valid;
  38. reg[15:0] S_video_data;
  39. wire[7:0] S_port_a,S_port_b,S_port_c;
  40. assign S_port_a = S_video_data[7:0];
  41. assign S_port_b = S_video_data[15:8];
  42. assign S_port_c = 8'h0000;
  43. //
  44. /*ila_0 ila_0_i(
  45. .clk(I_336M_CLK),
  46. .probe0(O_XCLK),
  47. .probe1(S_line_valid),
  48. .probe2(S_frame_valid),
  49. .probe3(O_X0),
  50. .probe4(O_X1),
  51. .probe5(O_X2),
  52. .probe6(O_X3),
  53. .probe7(S_cnt),
  54. .probe8(S_video_data)
  55. );*/
  56. //
  57. always @(posedge I_336M_CLK or negedge I_reset)
  58. begin
  59. if(!I_reset)
  60. begin
  61. S_video_data <= 0;
  62. S_frame_valid <= 0;
  63. S_line_valid <= 0;
  64. end
  65. else
  66. begin
  67. S_video_data <= I_video_data;
  68. S_frame_valid <= I_frame_valid;
  69. S_line_valid <= I_line_valid;
  70. end
  71. end
  72. always @(posedge I_336M_CLK or negedge I_reset)
  73. begin
  74. if(!I_reset)
  75. S_tx_data <= 0;
  76. else if(S_cnt == 0 & S_cnt0 == 0)
  77. begin
  78. S_tx_data[4:0] <= S_port_a[4:0];
  79. S_tx_data[5] <= S_port_a[7];
  80. S_tx_data[6] <= S_port_a[5];
  81. S_tx_data[9:7] <= S_port_b[2:0];
  82. S_tx_data[11:10] <= S_port_b[7:6];
  83. S_tx_data[14:12] <= S_port_b[5:3];
  84. S_tx_data[15] <= S_port_c[0];
  85. S_tx_data[17:16] <= S_port_c[7:6];
  86. S_tx_data[22:18] <= S_port_c[5:1];
  87. S_tx_data[23] <= 0; //spare
  88. S_tx_data[24] <= S_line_valid; //LVAL,line valid
  89. S_tx_data[25] <= S_frame_valid; //FVAL,frame valid
  90. S_tx_data[26] <= 1; //DVAL,data valid
  91. S_tx_data[27] <= S_port_a[6];
  92. end
  93. end
  94. always @(posedge I_336M_CLK or negedge I_reset)
  95. begin
  96. if(!I_reset)
  97. begin
  98. S_cnt0 <= 0;
  99. S_cnt <= 0;
  100. end
  101. else
  102. begin
  103. if(S_cnt0 == 1 & S_cnt == 6)
  104. begin
  105. S_cnt0 <= 0;
  106. S_cnt <= 0;
  107. end
  108. else if(S_cnt0 == 1)
  109. begin
  110. S_cnt <= S_cnt + 1;
  111. S_cnt0 <= 0;
  112. end
  113. else
  114. S_cnt0 <= S_cnt0 + 1;
  115. end
  116. end
  117. always @ (posedge I_336M_CLK or negedge I_reset)
  118. begin
  119. if(!I_reset)
  120. O_XCLK <= 0;
  121. else if(S_cnt0 == 1)
  122. begin
  123. if(S_cnt == 5)
  124. O_XCLK <= 1;
  125. if(S_cnt == 2)
  126. O_XCLK <= 0;
  127. end
  128. end
  129. always @ (posedge I_336M_CLK or negedge I_reset)
  130. begin
  131. if(!I_reset)
  132. begin
  133. O_X0 <= 0;
  134. O_X1 <= 0;
  135. O_X2 <= 0;
  136. O_X3 <= 0;
  137. end
  138. else if(S_cnt0 == 1)
  139. begin
  140. case(S_cnt)
  141. 8'd0:
  142. begin
  143. O_X0 <= S_tx_data[7];
  144. O_X1 <= S_tx_data[18];
  145. O_X2 <= S_tx_data[26];
  146. O_X3 <= S_tx_data[23];
  147. end
  148. 8'd1:
  149. begin
  150. O_X0 <= S_tx_data[6];
  151. O_X1 <= S_tx_data[15];
  152. O_X2 <= S_tx_data[25];
  153. O_X3 <= S_tx_data[17];
  154. end
  155. 8'd2:
  156. begin
  157. O_X0 <= S_tx_data[4];
  158. O_X1 <= S_tx_data[14];
  159. O_X2 <= S_tx_data[24];
  160. O_X3 <= S_tx_data[16];
  161. end
  162. 8'd3:
  163. begin
  164. O_X0 <= S_tx_data[3];
  165. O_X1 <= S_tx_data[13];
  166. O_X2 <= S_tx_data[22];
  167. O_X3 <= S_tx_data[11];
  168. end
  169. 8'd4:
  170. begin
  171. O_X0 <= S_tx_data[2];
  172. O_X1 <= S_tx_data[12];
  173. O_X2 <= S_tx_data[21];
  174. O_X3 <= S_tx_data[10];
  175. end
  176. 8'd5:
  177. begin
  178. O_X0 <= S_tx_data[1];
  179. O_X1 <= S_tx_data[9];
  180. O_X2 <= S_tx_data[20];
  181. O_X3 <= S_tx_data[5];
  182. end
  183. 8'd6:
  184. begin
  185. O_X0 <= S_tx_data[0];
  186. O_X1 <= S_tx_data[8];
  187. O_X2 <= S_tx_data[19];
  188. O_X3 <= S_tx_data[27];
  189. end
  190. default
  191. begin
  192. O_X0 <= 0;
  193. O_X1 <= 0;
  194. O_X2 <= 0;
  195. O_X3 <= 0;
  196. end
  197. endcase
  198. end
  199. end
  200. endmodule

接受端

代码中含有图像数据行帧头校验内容,自行忽略

  1. /* Document info
  2. document class : RES
  3. module name : CameraLink_Out
  4. module purpose : video out
  5. version : V1.0
  6. author : mayidianzi
  7. */
  8. ///
  9. `timescale 1ns / 1ps
  10. module Cameralink_in(
  11. input I_CLINK_RxCLK,
  12. input I_CLINK_RxCLKx7,
  13. input I_CLINK_RxCLKx7_n,
  14. input I_RESET,
  15. input I_X0,
  16. input I_X1,
  17. input I_X2,
  18. input I_X3,
  19. output O_img_clk,
  20. output O_img_frame,
  21. output reg O_img_line,
  22. output O_img_vblank,
  23. output O_img_hblank,
  24. output[15:0] O_img_data
  25. );
  26. / parameter set \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  27. reg [27:0] S_Rx_data;
  28. reg [27:0] S_data, S_data_d0;
  29. reg S_RxCLK_d0, S_RxCLK_d1, S_RxCLK_d2;
  30. wire [15:0] S_img_data;
  31. wire S_img_line, S_img_frame;
  32. reg[15:0] S_imgdata_d0, S_imgdata_d1, S_imgdata_d2, S_imgdata_d3, S_cnt;
  33. reg S_img_frame_d0, S_img_frame_d1, S_img_frame_d2, S_img_frame_d3, S_false;
  34. reg[3:0] S_state;
  35. parameter C_idle = 0,
  36. C_valid = 1;
  37. internal signal \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  38. ila_4 ila_4_i(
  39. .clk (I_CLINK_RxCLK),
  40. .probe0(O_img_frame),
  41. .probe1(O_img_line),
  42. .probe2(S_RxCLK_d1),
  43. .probe3(S_RxCLK_d2),
  44. .probe4(O_img_data),
  45. .probe5(I_X0),
  46. .probe6(I_X1),
  47. .probe7(I_X2),
  48. .probe8(S_false),
  49. .probe9(S_Rx_data),
  50. .probe10(S_img_data)
  51. );
  52. internal signal \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  53. assign O_img_vblank = ~O_img_frame;
  54. assign O_img_hblank = O_img_frame & (~O_img_line);
  55. wire[7:0] S_port_a, S_port_b, S_port_c;
  56. assign S_img_data[7:0] = S_port_a;
  57. assign S_img_data[15:8] = S_port_b;
  58. assign S_port_a[4:0] = S_data_d0[4:0];
  59. assign S_port_a[7] = S_data_d0[5];
  60. assign S_port_a[5] = S_data_d0[6];
  61. assign S_port_b[2:0] = S_data_d0[9:7];
  62. assign S_port_b[7:6] = S_data_d0[11:10];
  63. assign S_port_b[5:3] = S_data_d0[14:12];
  64. //assign S_port_c[0] = S_data[15];
  65. //assign S_port_c[7:6] = S_data[17:16];
  66. //assign S_port_c[5:1] = S_data[22:18];
  67. assign S_img_line = S_data_d0[24]; //LVAL,line valid
  68. assign S_img_frame = S_data_d0[25]; //FVAL,frame valid
  69. assign S_port_a[6] = S_data_d0[27];
  70. assign O_img_frame = S_img_frame_d3;
  71. //assign O_img_line = S_img_line;
  72. assign O_img_data = S_imgdata_d3;
  73. //assign O_img_clk = S_RxCLK_d2;
  74. assign O_img_clk = I_CLINK_RxCLK;
  75. internal signal \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  76. always @(posedge I_CLINK_RxCLKx7 or posedge I_RESET)//
  77. begin
  78. if(I_RESET)
  79. begin
  80. S_RxCLK_d0 <= 0;
  81. S_RxCLK_d1 <= 0;
  82. S_RxCLK_d2 <= 0;
  83. end
  84. else
  85. begin
  86. S_RxCLK_d0 <= I_CLINK_RxCLK;
  87. S_RxCLK_d1 <= S_RxCLK_d0;
  88. S_RxCLK_d2 <= S_RxCLK_d1;
  89. end
  90. end
  91. always @(posedge S_RxCLK_d2 or posedge I_RESET)//
  92. begin
  93. if(I_RESET)
  94. S_data <= 0;
  95. else
  96. S_data[27:0] <= {S_Rx_data[21:18],S_Rx_data[27],S_Rx_data[17:13],S_Rx_data[26:25],
  97. S_Rx_data[12:9],S_Rx_data[24:23],S_Rx_data[8:5],S_Rx_data[22],S_Rx_data[4:0]};
  98. end
  99. always @(posedge I_CLINK_RxCLKx7_n or posedge I_RESET)//
  100. begin
  101. if(I_RESET)
  102. S_Rx_data <= 0;
  103. else
  104. begin
  105. S_Rx_data[27:21] <= {S_Rx_data[26:21],I_X3};
  106. S_Rx_data[20:14] <= {S_Rx_data[19:14],I_X2};
  107. S_Rx_data[13:7] <= {S_Rx_data[12:7],I_X1};
  108. S_Rx_data[6:0] <= {S_Rx_data[5:0],I_X0};
  109. end
  110. end
  111. always @(posedge I_CLINK_RxCLK or posedge I_RESET)//
  112. begin
  113. if(I_RESET)
  114. S_data_d0 <= 0;
  115. else
  116. S_data_d0[27:0] <= S_data;
  117. end
  118. always @(posedge I_CLINK_RxCLK or posedge I_RESET)//
  119. begin
  120. if(I_RESET)
  121. begin
  122. S_imgdata_d0 <= 0;
  123. S_imgdata_d1 <= 0;
  124. S_imgdata_d2 <= 0;
  125. S_imgdata_d3 <= 0;
  126. S_img_frame_d0 <= 0;
  127. S_img_frame_d1 <= 0;
  128. S_img_frame_d2 <= 0;
  129. S_img_frame_d3 <= 0;
  130. end
  131. else
  132. begin
  133. S_imgdata_d0 <= S_img_data;
  134. S_imgdata_d1 <= S_imgdata_d0;
  135. S_imgdata_d2 <= S_imgdata_d1;
  136. S_imgdata_d3 <= S_imgdata_d2;
  137. S_img_frame_d0 <= S_img_frame;
  138. S_img_frame_d1 <= S_img_frame_d0;
  139. S_img_frame_d2 <= S_img_frame_d1;
  140. S_img_frame_d3 <= S_img_frame_d2;
  141. end
  142. end
  143. always @(posedge I_CLINK_RxCLK or posedge I_RESET)//
  144. begin
  145. if(I_RESET)
  146. begin
  147. S_state <= C_idle;
  148. S_cnt <= 0;
  149. end
  150. else
  151. begin
  152. case(S_state)
  153. C_idle:
  154. if(S_imgdata_d0 == 16'haa || S_imgdata_d1 == 16'hbb)
  155. begin
  156. S_state <= C_valid;
  157. S_cnt <= 0;
  158. end
  159. else
  160. S_cnt <= S_cnt + 1;
  161. C_valid:
  162. if(S_cnt >= 645)
  163. begin
  164. S_cnt <= 0;
  165. S_state <= C_idle;
  166. end
  167. else
  168. S_cnt <= S_cnt + 1;
  169. endcase
  170. end
  171. end
  172. always @(posedge I_CLINK_RxCLK or posedge I_RESET)//
  173. begin
  174. if(I_RESET)
  175. begin
  176. O_img_line <= 0;
  177. S_false <= 0;
  178. end
  179. else
  180. begin
  181. case(S_state)
  182. C_idle:
  183. begin
  184. O_img_line <= 0;
  185. if(S_cnt > 2500)
  186. S_false <= 1;
  187. end
  188. C_valid:
  189. O_img_line <= 1;
  190. endcase
  191. end
  192. end
  193. endmodule

之前的领导脑子不好,天天催,代码写的很随意,将就看吧。

写的很累,给个关注可以不。


本文转载自: https://blog.csdn.net/weixin_43498765/article/details/129428668
版权归原作者 mayidianzi 所有, 如有侵权,请联系我们删除。

“FPGA实现cameralink接口图像传输”的评论:

还没有评论