OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 972|回复: 0

[国产FPGA] 《ATK-DFPGL22G 之FPGA开发指南》第四十章 OV7725摄像头HDMI显示实验

[复制链接]

1118

主题

1129

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4672
金钱
4672
注册时间
2019-5-8
在线时间
1224 小时
发表于 2023-12-20 15:57:28 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2023-12-20 15:57 编辑

第四十章  OV7725摄像头HDMI显示实验


1)实验平台:正点原子 ATK-DFPGL22G开发板

2) 章节摘自【正点原子】ATK-DFPGL22G之FPGA开发指南_V1.0


4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/fpga/zdyz-PGL22G.html

5)正点原子官方B站:https://space.bilibili.com/394620890

6)FPGA技术交流QQ群:435699340

155537c2odj87vz1z9vj6l.jpg

155537nfqovl2gg9faaol9.png

在OV7725摄像头RGB-LCD显示实验中,成功地在LCD屏上实时显示出了摄像头采集的图像。本章将使用FPGA开发板实现对OV7725的数字图像采集并在HDMI显示器上实时显示。
本章包括以下几个部分:        
1.1        简介
1.2        实验任务
1.3        硬件设计
1.4        程序设计
1.5        下载验证

1.1 简介
在“OV7725摄像头RGB-LCD显示实验”中对OV7725的视频传输时序、SCCB协议以及寄存器的配置信息等内容作了详细的介绍,如果大家对这部分内容不是很熟悉的话,请参考“OV7725摄像头RGB-LCD显示实验”中的简介部分。

1.2 实验任务
本节实验任务是使用ATK-DFPGL22G开发板及OV7725摄像头实现图像采集,通过HDMI接口驱动HDMI显示器,并实时显示出图像。

1.3 硬件设计
摄像头扩展接口原理图及OV7725模块说明与“OV7725摄像头RGB-LCD显示实验”完全相同,请参考“OV7725摄像头RGB-LCD显示实验”硬件设计部分。HDMI接口部分的硬件设计请参考“HDMI彩条显示实验”中的硬件设计部分。
由于OV7725、HDMI接口和DDR3引脚数目较多且在前面相应的章节中已经给出它们的管脚列表,这里不再列出管脚分配。

1.4 程序设计
图 40.4.1是根据本章实验任务画出的系统框图。对比“OV7725摄像头RGB-LCD显示实验”的系统框图可以发现,本次实验只是把LCD顶层模块替换成了HDMI顶层模块,将图像采集顶层模块中的图像裁剪模块去掉了,其余模块(除时钟模块外)完全相同。之所以在本节实验中把裁剪模块去掉,是因为本次实验所用的HDMI显示器的分辨率大于摄像头的分辨率,所以只需要在HDMI视频显示模块稍微改一下读数据请求即可,改动部分下文会给大家讲解。时钟模块用于为I2C驱动模块、HDMI顶层模块以及DDR3控制模块提供驱动时钟;I2C驱动模块和I2C配置模块用于初始化OV7725图像传感器;摄像头采集模块负责采集摄像头图像数据,并把图像数据写入DDR3控制模块中;DDR3控制模块负责将用户数据写入和读出片外DDR3存储器;HDMI顶层模块负责驱动HDMI显示器。本章使用的HDMI显示器分辨率为1280*720,而OV7725传感器的最大分辨率为640*480,所以HDMI显示器需要填充黑色的像素点。                           
image001.png
图 40.4.1顶层系统框图
由上图可知,本节实验中时钟模块pll_clk为DDR3控制模块、I2C驱动模块提供驱动时钟以及为HDMI模块提供像素时钟和5倍像素时钟。I2C配置模块和I2C驱动模块控制着传感器初始化的开始与结束,传感器初始化完成后图像采集模块将采集到的数据写入DDR3控制模块,HDMI顶层模块从DDR3控制模块中读出数据并驱动显示器显示,这时整个系统才完成了数据的采集、缓存与显示。需要注意的是图像数据采集模块是在DDR3和传感器都初始化完成之后才开始输出数据的,避免了在DDR3初始化过程中向里面写入数据。
顶层模块代码如下所示:
  1. 1    module ov7725_hdmi(
  2. 2        input             sys_clk          ,
  3. 3        input             sys_rst_n        ,
  4. 4                                          
  5. 5        output            tmds_clk_p       ,  // TMDS 时钟通道
  6. 6        output            tmds_clk_n       ,
  7. 7        output [2:0     tmds_data_p      ,  // TMDS 数据通道
  8. 8        output [2:0     tmds_data_n      ,
  9. 9        //摄像头接口                       
  10. 10       input             cam_pclk         ,  //cmos 数据像素时钟
  11. 11       input             cam_vsync        ,  //cmos 场同步信号
  12. 12       input             cam_href         ,  //cmos 行同步信号
  13. 13       input [7:0      cam_data         ,  //cmos 数据
  14. 14       output            cam_rst_n        ,  //cmos 复位信号,低电平有效
  15. 15       output            cam_sgm_ctrl     ,  //cmos 时钟选择信号, 1:使用摄像头自带的晶振
  16. 16       output            cam_scl          ,  //cmos SCCB_SCL线
  17. 17       inout            cam_sda          ,  //cmos SCCB_SDA线
  18. 18       //DDR3接口
  19. 19       input             pad_loop_in      ,  //低位温度补偿输入
  20. 20       input             pad_loop_in_h    ,  //高位温度补偿输入
  21. 21       output            pad_rstn_ch0     ,  //Memory复位
  22. 22       output            pad_ddr_clk_w    ,  //Memory差分时钟正
  23. 23       output            pad_ddr_clkn_w   ,  //Memory差分时钟负
  24. 24       output            pad_csn_ch0      ,  //Memory片选
  25. 25       output [15:0     pad_addr_ch0     ,  //Memory地址总线
  26. 26       inout [16-1:0  pad_dq_ch0       ,  //数据总线
  27. 27       inout [16/8-1:0 pad_dqs_ch0     ,  //数据时钟正端
  28. 28       inout [16/8-1:0 pad_dqsn_ch0    ,  //数据时钟负端
  29. 29       output [16/8-1:0 pad_dm_rdqs_ch0 ,  //数据Mask
  30. 30       output            pad_cke_ch0      ,  //Memory差分时钟使
  31. 31       output            pad_odt_ch0      ,  //On Die Terminati
  32. 32       output            pad_rasn_ch0     ,  //行地址strobe
  33. 33       output            pad_casn_ch0     ,  //列地址strobe
  34. 34       output            pad_wen_ch0      ,  //写使能
  35. 35       output [2:0     pad_ba_ch0       ,  //Bank地址总线
  36. 36       output            pad_loop_out     ,  //低位温度补偿输出
  37. 37       output            pad_loop_out_h      //高位温度补偿输出
  38. 38      );
  39. 39   
  40. 40   //parameter define
  41. 41   parameter SLAVE_ADDR = 7'h21         ; //OV7725的器件地址7'h21
  42. 42   parameter BIT_CTRL   =1'b0          ; //OV7725的字节地址为8位  0:8位 1:16位
  43. 43   parameter CLK_FREQ   =27'd50_000_000; //i2c_dri模块的驱动时钟频率
  44. 44   parameter I2C_FREQ   =18'd250_000   ;//I2C的SCL时钟频率,不超过400KHz
  45. 45   parameter APP_ADDR_MIN = 28'd0      ; //ddr3读写起始地址,以一个16bit的数据为一个单位
  46. 46   parameter APP_ADDR_MAX = 28'd307200 ; //ddr3读写结束地址,以一个16bit的数据为一个单位
  47. 47   parameter BURST_LENGTH = 8'd80      ; //ddr3读写突发长度,80个128bit的数据
  48. 48   
  49. 49   //wire define
  50. 50   //PLL
  51. 51   wire       pixel_clk       ;  //像素时钟75M
  52. 52   wire       pixel_clk_5x    ;  //5倍像素时钟375M
  53. 53   wire       clk_50m         ;  //output 50M
  54. 54   wire       clk_locked      ;
  55. 55   //OV7725
  56. 56   wire       i2c_dri_clk     ;  //I2C操作时钟
  57. 57   wire       i2c_done        ;  //I2C寄存器配置完成信号
  58. 58   wire       i2c_exec        ;  //I2C触发执行信号
  59. 59   wire [15:0 i2c_data       ;  //I2C要配置的地址与数据(高8位地址,低8位数据)
  60. 60   wire       cam_init_done   ;  //摄像头初始化完成
  61. 61   wire       cmos_frame_vsync;  //帧有效信号
  62. 62   wire       cmos_frame_href ;  //行有效信号
  63. 63   wire       cmos_frame_valid;  //数据有效使能信号
  64. 64   wire [15:0 wr_data        ;  //OV7725写入DDR3控制器模块的数据
  65. 65   //HDMI
  66. 66   wire       video_vs        ;  //场同步信号
  67. 67   wire [15:0 rd_data        ;  //DDR3控制器模块读数据给HDMI
  68. 68   wire       rdata_req       ;  //DDR3控制器模块读使能
  69. 69   //DDR3
  70. 70   wire       fram_done       ; //DDR中已经存入一帧画面标志
  71. 71   wire       ddr_init_done   ; //ddr3初始化完成
  72. 72   
  73. 73   //*****************************************************
  74. 74   //**                   main code
  75. 75   //*****************************************************
  76. 76   assign cam_sgm_ctrl = 1'b1;
  77. 77   assign cam_rst_n    = 1'b1;
  78. 78
复制代码
第76行代码是选择使用摄像头自带的晶振,第77行代码是不复位摄像头。
  1. 79   //例化PLLIP核
  2. 80   pll_clk  u_pll_clk(
  3. 81       .pll_rst        (~sys_rst_n  ),
  4. 82       .clkin1         (sys_clk     ),
  5. 83       .clkout0        (pixel_clk   ), //像素时钟75M
  6. 84       .clkout1        (pixel_clk_5x), //5倍像素时钟375M
  7. 85       .clkout2        (clk_50m     ), //output50M
  8. 86       .pll_lock       (clk_locked  )
  9. 87   );
  10. 88   
  11. 89   //I2C配置模块   
  12. 90   i2c_ov7725_rgb565_cfg  u_i2c_cfg(
  13. 91       .clk            (i2c_dri_clk  ), //in
  14. 92       .rst_n          (sys_rst_n    ), //in
  15. 93       .i2c_done       (i2c_done     ), //in
  16. 94       .i2c_exec       (i2c_exec     ), //out
  17. 95       .i2c_data       (i2c_data     ), //out
  18. 96       .init_done      (cam_init_done)  //out
  19. 97       );
  20. 98   
  21. 99   //I2C驱动模块
  22. 100  i2c_dri
  23. 101     #(
  24. 102      .SLAVE_ADDR     (SLAVE_ADDR),  //参数传递
  25. 103      .CLK_FREQ       (CLK_FREQ  ),
  26. 104      .I2C_FREQ       (I2C_FREQ  )
  27. 105      )
  28. 106     u_i2c_dri(
  29. 107      .clk            (clk_50m       ),
  30. 108      .rst_n          (sys_rst_n     ),
  31. 109      //i2c interface
  32. 110      .i2c_exec       (i2c_exec      ),
  33. 111      .bit_ctrl       (BIT_CTRL      ),
  34. 112      .i2c_rh_wl      (1'b0          ), //固定为0,只用到了IIC驱动的写操作
  35. 113      .i2c_addr       (i2c_data[15:8]),
  36. 114      .i2c_data_w     (i2c_data[7:0 ),
  37. 115      .i2c_data_r     (              ), //out
  38. 116      .i2c_done       (i2c_done      ), //out
  39. 117      .i2c_ack        (              ), //out
  40. 118      .scl            (cam_scl       ), //out
  41. 119      .sda            (cam_sda       ), //inout
  42. 120      //user interface
  43. 121      .dri_clk        (i2c_dri_clk)     //I2C操作时钟//out
  44. 122  );
  45. 123  
  46. 124  //摄像头数据采集模块
  47. 125  cmos_capture_datau_cmos_capture_data(
  48. 126      .rst_n                (sys_rst_n & ddr_init_done),
  49. 127      .cam_pclk             (cam_pclk                 ),
  50. 128      .cam_vsync            (cam_vsync                ),
  51. 129      .cam_href             (cam_href                 ),
  52. 130      .cam_data             (cam_data                 ),
  53. 131      .cmos_frame_vsync     (cmos_frame_vsync         ),//out
  54. 132      .cmos_frame_href      (cmos_frame_href          ),//out
  55. 133      .cmos_frame_valid     (cmos_frame_valid         ),//out
  56. 134      .cmos_frame_data      (wr_data                  ) //out
  57. 135      );
  58. 136  
  59. 137  //ddr3
  60. 138  ddr3_top u_ddr3_top(
  61. 139      .refclk_in            (clk_50m         ),
  62. 140      .rst_n                (sys_rst_n       ),
  63. 141      .app_addr_rd_min      (APP_ADDR_MIN    ),
  64. 142      .app_addr_rd_max      (APP_ADDR_MAX    ),
  65. 143      .rd_bust_len          (BURST_LENGTH    ),
  66. 144      .app_addr_wr_min      (APP_ADDR_MIN    ),
  67. 145      .app_addr_wr_max       (APP_ADDR_MAX    ),
  68. 146      .wr_bust_len          (BURST_LENGTH    ),
  69. 147      .ddr3_read_valid      (1'b1            ),
  70. 148      .ddr3_pingpang_en     (1'b1            ),
  71. 149      .wr_clk               (cam_pclk        ),
  72. 150      .rd_clk               (pixel_clk       ),
  73. 151      .datain_valid         (cmos_frame_valid),
  74. 152      .datain               (wr_data         ),
  75. 153      .rdata_req            (rdata_req       ),
  76. 154      .rd_load              (video_vs        ),
  77. 155      .wr_load              (cmos_frame_vsync),
  78. 156      .fram_done            (fram_done       ),
  79. 157      .dataout              (rd_data         ),
  80. 158      .pll_lock             (pll_lock        ),
  81. 159      .ddr_init_done        (ddr_init_done   ),
  82. 160      .ddrphy_rst_done      (                ),
  83. 161      .pad_loop_in          (pad_loop_in     ),
  84. 162      .pad_loop_in_h        (pad_loop_in_h   ),
  85. 163      .pad_rstn_ch0         (pad_rstn_ch0    ),
  86. 164      .pad_ddr_clk_w         (pad_ddr_clk_w   ),
  87. 165      .pad_ddr_clkn_w       (pad_ddr_clkn_w  ),
  88. 166      .pad_csn_ch0          (pad_csn_ch0     ),
  89. 167      .pad_addr_ch0         (pad_addr_ch0    ),
  90. 168      .pad_dq_ch0           (pad_dq_ch0      ),
  91. 169      .pad_dqs_ch0          (pad_dqs_ch0     ),
  92. 170      .pad_dqsn_ch0         (pad_dqsn_ch0    ),
  93. 171      .pad_dm_rdqs_ch0      (pad_dm_rdqs_ch0 ),
  94. 172      .pad_cke_ch0          (pad_cke_ch0     ),
  95. 173      .pad_odt_ch0          (pad_odt_ch0     ),
  96. 174      .pad_rasn_ch0         (pad_rasn_ch0    ),
  97. 175      .pad_casn_ch0         (pad_casn_ch0    ),
  98. 176      .pad_wen_ch0          (pad_wen_ch0     ),
  99. 177      .pad_ba_ch0           (pad_ba_ch0      ),
  100. 178      .pad_loop_out         (pad_loop_out    ),
  101. 179      .pad_loop_out_h       (pad_loop_out_h  )
  102. 180      );
  103. 181  
  104. 182  //HDMI顶层模块
  105. 183  hdmi_top u_hdmi_top(
  106. 184      .hdmi_clk       (pixel_clk    ),
  107. 185      .hdmi_clk_5     (pixel_clk_5x ),
  108. 186      .sys_rst_n      (sys_rst_n    ),
  109. 187      .fram_done      (fram_done    ),
  110. 188      .clk_locked     (clk_locked   ),
  111. 189      .rd_data        (rd_data      ),
  112. 190      .rd_en          (rdata_req    ),
  113. 191      .video_vs       (video_vs     ),
  114. 192      .h_disp         (             ),
  115. 193      .v_disp         (             ),
  116. 194      .pixel_xpos     (             ),
  117. 195      .pixel_ypos     (             ),
  118. 196      .tmds_clk_p     (tmds_clk_p   ),
  119. 197      .tmds_clk_n     (tmds_clk_n   ),
  120. 198      .tmds_data_p    (tmds_data_p  ),
  121. 199      .tmds_data_n    (tmds_data_n  )
  122. 200      );
  123. 201  
  124. 202  endmodule
复制代码
从上面顶层模块代码中可以看出本节实验就是在原本的“OV7725摄像头RGB-LCD显示实验”的基础上修改过来的,这里主要就是将原本的LCD顶层模块替换成了HDMI顶层模块,时钟模块为DDR3控制模块、I2C驱动模块提供驱动时钟以及为HDMI模块提供像素时钟和5倍像素时钟。
HDMI顶层模块代码如下:
  1. 1   module hdmi_top(
  2. 2       input          hdmi_clk     ,
  3. 3       input          hdmi_clk_5   ,
  4. 4       input          sys_rst_n    ,
  5. 5       input          fram_done    ,
  6. 6       input          clk_locked   ,
  7. 7      
  8. 8       input [15:0  rd_data      ,
  9. 9       output         rd_en        ,
  10. 10      output         video_vs     ,  //场同步信号
  11. 11      output [10:0  pixel_xpos   ,  //像素点横坐标
  12. 12      output [10:0  pixel_ypos   ,  //像素点纵坐标
  13. 13      output [12:0  h_disp       ,  //HDMI屏水平分辨率
  14. 14      output [12:0  v_disp       ,  //HDMI屏垂直分辨率
  15. 15      //HDMI接口
  16. 16      output         tmds_clk_p   ,  //TMDS 时钟通道
  17. 17      output         tmds_clk_n   ,
  18. 18      output [2:0   tmds_data_p  ,  //TMDS 数据通道
  19. 19      output [2:0   tmds_data_n
  20. 20  
  21. 21  );
  22. 22  
  23. 23  //wire define
  24. 24  wire       video_hs        ;  //行同步信号
  25. 25  wire       video_de        ;  //数据使能
  26. 26  wire [15:0 video_rgb_565  ;  //RGB565颜色数据
  27. 27  wire [15:0 pixel_data_w   ;  //像素点数据
  28. 28  wire [23:0 video_rgb      ;  ////RGB888颜色数据
  29. 29  
  30. 30  //reg define
  31. 31  reg   fram_done_t0    ;
  32. 32  reg   fram_done_t1    ;
  33. 33  reg   fram_done_t2    ;
  34. 34  
  35. 35  //*****************************************************
  36. 36  //**                   main code
  37. 37  //*****************************************************
  38. 38  
  39. 39  assign video_rgb = {video_rgb_565[15:11],3'b000,video_rgb_565[10:5],2'b00,
  40. 40                      video_rgb_565[4:0],3'b000};
  41. 41  
  42. 第39~40行代码是将采集到的RGB565格式的数据转换为HDMI显示的RGB888格式的数据。
  43. 42  always @(posedge hdmi_clk) begin
  44. 43      fram_done_t0 <= fram_done    ;
  45. 44      fram_done_t1 <= fram_done_t0 ;
  46. 45      fram_done_t2 <= fram_done_t1 ;
  47. 46  end
  48. 47  
  49. 48  //例化视频显示驱动模块
  50. 49  video_driver  u_video_driver(
  51. 50      .pixel_clk            (hdmi_clk               ),
  52. 51      .sys_rst_n            (sys_rst_n&&fram_done_t2),
  53. 52      .video_hs             (video_hs               ),
  54. 53      .video_vs             (video_vs               ),
  55. 54      .video_de             (video_de               ),
  56. 55      .video_rgb            (video_rgb_565          ),
  57. 56      .data_req             (                       ),
  58. 57      .h_disp               (h_disp                 ),
  59. 58      .v_disp               (v_disp                 ),
  60. 59      .pixel_xpos           (pixel_xpos             ),
  61. 60      .pixel_ypos           (pixel_ypos             ),
  62. 61      .pixel_data           (pixel_data_w           )
  63. 62      );
  64. 63  
  65. 64  //例化视频显示模块
  66. 65  video_display  u_video_display(
  67. 66      .pixel_clk            (hdmi_clk               ),
  68. 67      .sys_rst_n            (sys_rst_n&&fram_done_t2),
  69. 68      .pixel_xpos           (pixel_xpos             ),
  70. 69      .pixel_ypos           (pixel_ypos             ),
  71. 70      .h_disp               (h_disp                 ),
  72. 71      .v_disp               (v_disp                 ),
  73. 72      .cmos_data            (rd_data                ),
  74. 73      .video_data           (pixel_data_w           ),
  75. 74      .data_req             (rd_en                  )
  76. 75      );
  77. 76   
  78. 77  //例化HDMI驱动模块
  79. 78  dvi_transmitter_top  u_rgb2dvi_0(
  80. 79      .pclk                 (hdmi_clk            ),
  81. 80      .pclk_x5              (hdmi_clk_5          ),
  82. 81      .reset_n              (sys_rst_n&clk_locked),
  83. 82      .video_din            (video_rgb           ),
  84. 83      .video_hsync          (video_hs            ),
  85. 84      .video_vsync          (video_vs            ),
  86. 85      .video_de             (video_de            ),
  87. 86      .tmds_clk_p           (tmds_clk_p          ),
  88. 87      .tmds_clk_n           (tmds_clk_n          ),
  89. 88      .tmds_data_p          (tmds_data_p         ),
  90. 89      .tmds_data_n          (tmds_data_n         )
  91. 90      );
  92. 91      
  93. 92  endmodule
复制代码
HDMI顶层模块例化了三个模块,分别是视频显示驱动模块(video_driver)、视频显示模块(video_display)和HDMI驱动模块(dvi_transmitter_top)。
HDMI驱动模块(dvi_transmitter_top):HDMI驱动模块主要就是进行串并转换和TMDS编码,这部分内容在前面的HDMI彩条实验中已经给大家讲解过了,这里不再重复赘述了。
视频显示驱动模块(video_driver):显示驱动模块的作用就是生成HDMI显示器的驱动时序,用来驱动HDMI显示器,其中包括行场同步信号和DE像素有效信号。这里的显示驱动模块(video_driver)跟HDMI彩条显示实验的驱动模块几乎是一模一样的,唯一的区别就是将HDMI的分辨率信息也作为了模块的输出,代码是没有改动的,详细的讲解可以查看前面的HDMI彩条实验,这里不再重复赘述了。
视频显示模块(video_display):该模块用于控制HDMI显示器显示的像素值,即摄像头采集的图像及黑边填充。因为OV7725摄像头的分辨率小于显示器的分辨率,所以我们需要配合当前的像素点坐标来进行判断是否向DDR3控制器发出读数据请求信号。在摄像头有效显示范围内,将摄像头采集的数据赋值给hdmi像素点数据,否则将黑色所对应的数据赋值给hdmi像素点数据(即填充黑边),其代码如下:
  1. 1   module video_display(
  2. 2       input             pixel_clk , //驱动时钟
  3. 3       input             sys_rst_n , //复位信号
  4. 4   
  5. 5       input      [10:0 pixel_xpos, //像素点横坐标
  6. 6       input      [10:0 pixel_ypos, //像素点纵坐标
  7. 7       input      [15:0 cmos_data , //CMOS传感器像素点数据
  8. 8       input      [10:0 h_disp    , //水平分辨率
  9. 9       input      [10:0 v_disp    , //垂直分辨率
  10. 10      
  11. 11      output     [15:0 video_data, //像素点数据
  12. 12      output            data_req    //请求像素点颜色数据输入
  13. 13      );   
  14. 14  
  15. 15  //parameter define  
  16. 16  parameter  V_CMOS_DISP = 11'd480;               //CMOS分辨率——行
  17. 17  parameter  H_CMOS_DISP = 11'd640;               //CMOS分辨率——列
  18. 18  localparam BLACK  = 16'b00000_000000_00000;      //RGB565 黑色
  19. 19  
  20. 20  //reg define   
  21. 21  reg            data_val            ;            //数据有效信号
  22. 22  
  23. 23  //wire define
  24. 24  wire    [10:0 display_border_pos_l;            //左侧边界的横坐标
  25. 25  wire    [10:0 display_border_pos_r;            //右侧边界的横坐标
  26. 26  wire    [10:0 display_border_pos_t;            //上端边界的纵坐标
  27. 27  wire    [10:0 display_border_pos_b;            //下端边界的纵坐标
  28. 28  
  29. 29  //*****************************************************
  30. 30  //**                   main code
  31. 31  //*****************************************************
  32. 32  
  33. 33  //左侧边界的横坐标计算
  34. 34  assign display_border_pos_l = (h_disp - H_CMOS_DISP)/2-1;
  35. 35  //右侧边界的横坐标计算
  36. 36  assign display_border_pos_r = H_CMOS_DISP + (h_disp - H_CMOS_DISP)/2-1;
  37. 37  
  38. 38  //上端边界的纵坐标计算
  39. 39  assign display_border_pos_t = (v_disp - V_CMOS_DISP)/2;
  40. 40  
  41. 41  //下端边界的纵坐标计算
  42. 42  assign display_border_pos_b = V_CMOS_DISP + (v_disp - V_CMOS_DISP)/2;
  43. 43  
  44. 44  //请求像素点颜色数据输入 范围:79~718,共640个时钟周期
  45. 45  assign data_req = ((pixel_xpos >= display_border_pos_l ) &&
  46. 46                    (pixel_xpos < display_border_pos_r) &&
  47. 47                    (pixel_ypos > display_border_pos_t) &&
  48. 48                    (pixel_ypos <= display_border_pos_b)
  49. 49                    ) ? 1'b1 : 1'b0;
  50. 50  
  51. 51  //在数据有效范围内,将摄像头采集的数据赋值给hdmi像素点数据
  52. 52  assign video_data = data_val ? cmos_data : BLACK;
  53. 53  
  54. 54  //有效数据滞后于请求信号一个时钟周期,所以数据有效信号在此延时一拍
  55. 55  always @(posedge pixel_clk or negedge sys_rst_n) begin
  56. 56      if(!sys_rst_n)
  57. 57          data_val <= 1'b0;
  58. 58      else
  59. 59          data_val <= data_req;
  60. 60  end
  61. 61  
  62. 62  endmodule
复制代码
在代码的第33至42行,计算了摄像头存入DDR3的边界坐标,上边界坐标(display_border_pos_t)是HDMI屏幕的场分辨率(720)减去摄像头的场分辨率(480)再除以2得到的,其他的边界也是以类似的计算方法得到,裁剪原理与lcd屏裁剪相同(可参考图 39.4.5)。
这里还有一点需要提醒大家注意的是我们读数据请求发送给DDR3控制器后实际上是发送给读FIFO,而读FIFO接收到数据请求到数据出来是需要一个时钟周期的延迟的,也就是说有效数据实际上比读数据请求晚了一个时钟(如果FIFO用的是另外一种数据提前模式则有效数据和读数据请求是同步的,本节实验采用的是普通模式),因此代码的55~60行对读数据请求作了一个打拍处理,生成数据有效使能信号(data_val)。如代码第52行所示,当data_val信号拉高代表数据有效,data_val信号为低时代表数据无效,此时给HDMI显示屏填充黑边,到这里OV7725 HDMI显示实验的代码就讲完了。
因为本节实验例程的所有代码在“DDR3读写实验”、“ov7725_lcd显示实验”和“HDMI彩条显示实验”都有过详细的讲解,我们在本节实验只不过是将这些模块拿过来重新拼接一下,所以就不再重复的去详细讲解代码了,大家有不懂的地方可以翻看前面的例程。

1.5 下载验证
编译完工程之后就可以开始下载程序了。将OV7725摄像头模块插在ATK-DFPGL22G开发板的“OLED/CAMERA”插座上,并将HDMI电缆一端连接到开发板上的HDMI插座、另一端连接到显示器。将下载器一端连电脑,另一端与开发板上的JTAG端口连接,连接电源线并打开电源开关。接下来我们下载程序,验证OV7725 HDMI实时显示功能。下载完成后观察HDMI显示器显示的图案如下图所示,说明OV7725 HDMI实时显示程序下载验证成功。
QQ截图20231220155654.png
图 40.5.1 HDMI实时显示图像
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 20:09

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表