OpenEdv-开源电子网

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

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

[复制链接]

1070

主题

1081

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4443
金钱
4443
注册时间
2019-5-8
在线时间
1199 小时
发表于 2023-12-25 17:27:02 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2023-12-23 15:43 编辑

第四十四章  MT9V034摄像头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

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

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

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

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

1.4 软件设计
图 44.4.1是根据本章实验任务画出的系统框图。对比“MT9V034摄像头RGB-LCD显示实验”的系统框图可以发现,本次实验只是把LCD顶层模块替换成了HDMI顶层模块,并将图像采集模块中的图片裁剪模块去掉了,其余模块(除时钟模块外)完全相同。之所以本节实验将图片裁剪模块去掉是因为本次实验所用HDMI显示器的分辨率是大于摄像头分辨率的,所以只需要在HDMI驱动模块中稍微改下数据请求即可,改动部分和OV7725摄像头HDMI显示实验一模一样,这里就不再详细讲解了。时钟模块用于为I2C驱动模块、HDMI顶层模块以及DDR3控制模块提供驱动时钟;I2C驱动模块和I2C配置模块用于初始化MT9V034图像传感器;摄像头采集模块负责采集摄像头图像数据,并且把图像数据写入DDR3控制模块中;DDR3控制模块负责将用户数据写入和读出片外DDR3存储器;HDMI顶层模块负责驱动HDMI显示器。本章使用的HDMI显示器其分辨率为1280*720,而MT9V034传感器的本次实验所配置的分辨率为640*480,所以HDMI显示器需要填充黑色的像素点。                           
image001.png
图 44.4.1 顶层系统框图

由上图可知,时钟模块为HDMI顶层模块、DDR3控制模块以及I2C驱动模块提供驱动时钟。I2C配置模块和I2C驱动模块控制着传感器初始化的开始与结束,传感器初始化完成后图像采集模块将采集到的数据写入DDR3控制模块,HDMI顶层模块从DDR3控制模块中读出数据并驱动显示器显示,这时整个系统才完成了数据的采集、缓存与显示。需要注意的是图像数据采集模块是在DDR3和传感器都初始化完成之后才开始输出数据的,避免了在DDR3初始化过程中向里面写入数据。
顶层代码如下所示:
  1. 1   module mt9v034_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_stb          ,  //cmos pwer down
  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'b1001_000   ;//mt9v034的器件地址7'h90
  42. 42  parameter BIT_CTRL   =1'b0          ; //mt9v034的字节地址为8位  0:8位 1:16位
  43. 43  parameter DATA_CTRL  = 1'b1          ;  //mt9v034的数据为8位 0:8位 1:16位
  44. 44  parameter CLK_FREQ   =27'd50_000_000; //i2c_dri模块的驱动时钟频率
  45. 45  parameter I2C_FREQ   =18'd250_000   ;//I2C的SCL时钟频率,不超过400KHz
  46. 46  parameter APP_ADDR_MIN = 28'd0       ; //ddr3读写起始地址,以一个16bit的数据为一个单位
  47. 47  parameter APP_ADDR_MAX = 28'd307200  ; //ddr3读写结束地址,以一个16bit的数据为一个单位
  48. 48  parameter BURST_LENGTH = 8'd80       ; //ddr3读写突发长度,80个128bit的数据
  49. 49  
  50. 50  //wire define
  51. 51  //PLL
  52. 52  wire        pixel_clk       ;  //像素时钟75M
  53. 53  wire        pixel_clk_5x    ;  //5倍像素时钟375M
  54. 54  wire        clk_50m         ;  //output 50M
  55. 55  wire        clk_locked      ;
  56. 56  //MT9V034
  57. 57  wire        i2c_dri_clk     ;  //I2C操作时钟
  58. 58  wire        i2c_done        ;  //I2C寄存器配置完成信号
  59. 59  wire        i2c_exec        ;  //I2C触发执行信号
  60. 60  wire [7:0  i2c_addr       ;  //I2C要配置的地址
  61. 61  wire [15:0 i2c_wr_data    ;  //I2C要配置的数据
  62. 62  wire        cam_init_done   ;  //摄像头初始化完成
  63. 63  
  64. 64  wire        cmos_frame_vsync;  //帧有效信号
  65. 65  wire        cmos_frame_href ;  //行有效信号
  66. 66  wire        cmos_frame_valid;  //数据有效使能信号
  67. 67  wire [15:0 wr_data        ;  //OV7725写入DDR3控制器模块的数据
  68. 68  //HDMI
  69. 69  wire        video_vs        ;  //场同步信号
  70. 70  wire [15:0 rd_data        ;  //DDR3控制器模块读数据给HDMI
  71. 71  wire        rdata_req       ;  //DDR3控制器模块读使能
  72. 72  //DDR3
  73. 73  wire        fram_done       ; //DDR中已经存入一帧画面标志
  74. 74  wire        ddr_init_done   ;//ddr3初始化完成
  75. 75  
  76. 76  //*****************************************************
  77. 77  //**                    main code
  78. 78  //*****************************************************
  79. 79  assign  cam_stb  = 1'b0;
  80. 80  assign  cam_rst_n = 1'b1;
  81. 81  
  82. 82  //例化PLL IP核
  83. 83  pll_clk  u_pll_clk(
  84. 84       .pll_rst        (~sys_rst_n  ),
  85. 85       .clkin1         (sys_clk     ),
  86. 86       .clkout0        (pixel_clk   ), //像素时钟75M
  87. 87       .clkout1        (pixel_clk_5x), //5倍像素时钟375M
  88. 88       .clkout2        (clk_50m     ), //output50M
  89. 89       .pll_lock       (clk_locked  )
  90. 90  );
  91. 91  
  92. 92  //I2C驱配置模块
  93. 93  i2c_cfg  u_i2c_cfg(
  94. 94       .clk          (i2c_dri_clk  ),
  95. 95       .rst_n        (sys_rst_n    ),
  96. 96       .i2c_done     (i2c_done     ),
  97. 97       .i2c_exec     (i2c_exec     ),
  98. 98       .i2c_addr     (i2c_addr     ),
  99. 99       .i2c_wr_data  (i2c_wr_data  ),
  100. 100      .cfg_done     (cam_init_done)
  101. 101 );
  102. 102
  103. 103 //I2C驱动模块
  104. 104 i2c_dri
  105. 105   #(
  106. 106      .SLAVE_ADDR         (SLAVE_ADDR),    //参数传递
  107. 107      .CLK_FREQ           (CLK_FREQ  ),              
  108. 108      .I2C_FREQ           (I2C_FREQ  )
  109. 109      )
  110. 110   u_i2c_dr(
  111. 111      .clk                (clk_50m        ),
  112. 112      .rst_n              (sys_rst_n      ),
  113. 113      .i2c_exec           (i2c_exec       ),
  114. 114      .bit_ctrl           (BIT_CTRL       ),
  115. 115      .data_ctrl          (DATA_CTRL      ),
  116. 116      .i2c_rh_wl          (0              ), //固定为0,只用到了IIC驱动的写操作   
  117. 117      .i2c_addr           ({8'b0,i2c_addr}),
  118. 118      .i2c_data_w         (i2c_wr_data    ),
  119. 119      .i2c_data_r         (               ),
  120. 120      .i2c_done           (i2c_done       ),
  121. 121      .scl                (cam_scl        ),
  122. 122      .sda                (cam_sda        ),
  123. 123      .dri_clk            (i2c_dri_clk    )  //I2C操作时钟
  124. 124 );
  125. 125
  126. 126 //图像采集模块
  127. 127  cmos_capture_raw_gray
  128. 128 #(
  129. 129      .CMOS_FRAME_WAITCNT  (4'd10)  //Wait n fps for steady(OmniVision need 10Frame)
  130. 130 )
  131. 131 u_cmos_capture_raw_gray
  132. 132 (
  133. 133      //global clock
  134. 134      .clk_cmos          (1'b0                     ), //24MHzCMOS Driver clock input
  135. 135      .rst_n             (sys_rst_n & ddr_init_done), //global reset
  136. 136      //CMOS Sensor Interface
  137. 137      .cmos_pclk         (cam_pclk                 ), //24MHz CMOS Pixelclock input
  138. 138     .cmos_xclk         (                         ), //24MHzdrive clock
  139. 139      .cmos_data         (cam_data                 ), //8 bits cmos datainput
  140. 140      .cmos_vsync        (cam_vsync                ), //L: vaild, H: invalid
  141. 141      .cmos_href         (cam_href                 ), //H:vaild, L: invalid   
  142. 142      //CMOS SYNC Data output
  143. 143      .cmos_frame_vsync  (cmos_frame_vsync         ), //cmos frame datavsync valid signal
  144. 144      .cmos_frame_href   (cmos_frame_href          ), //cmos frame data hrefvaild  signal
  145. 145      .wr_data           (wr_data                  ), //cmos frame grayoutput
  146. 146      .cmos_frame_clken  (cmos_frame_valid         ), //cmos frame dataoutput/capture enable clock   
  147. 147      //user interface
  148. 148      .cmos_fps_rate     (                         )  //cmos image output rate
  149. 149 );
  150. 150
  151. 151 //ddr3
  152. 152 ddr3_top u_ddr3_top(
  153. 153      .refclk_in             (clk_50m        ),
  154. 154      .rst_n                 (sys_rst_n       ),
  155. 155      .app_addr_rd_min       (APP_ADDR_MIN   ),
  156. 156      .app_addr_rd_max       (APP_ADDR_MAX   ),
  157. 157      .rd_bust_len           (BURST_LENGTH   ),
  158. 158      .app_addr_wr_min       (APP_ADDR_MIN   ),
  159. 159      .app_addr_wr_max       (APP_ADDR_MAX   ),
  160. 160      .wr_bust_len           (BURST_LENGTH   ),
  161. 161      .ddr3_read_valid       (1'b1            ),
  162. 162      .ddr3_pingpang_en      (1'b1            ),
  163. 163      .wr_clk                (cam_pclk       ),
  164. 164     .rd_clk                (pixel_clk      ),
  165. 165      .datain_valid          (cmos_frame_valid),
  166. 166      .datain                (wr_data        ),
  167. 167      .rdata_req             (rdata_req      ),
  168. 168      .rd_load               (video_vs       ),
  169. 169      .wr_load               (cmos_frame_vsync),
  170. 170      .fram_done             (fram_done      ),
  171. 171      .dataout               (rd_data        ),
  172. 172      .pll_lock              (pll_lock       ),
  173. 173      .ddr_init_done         (ddr_init_done   ),
  174. 174      .ddrphy_rst_done       (               ),
  175. 175      .pad_loop_in           (pad_loop_in    ),
  176. 176      .pad_loop_in_h         (pad_loop_in_h  ),
  177. 177      .pad_rstn_ch0          (pad_rstn_ch0   ),
  178. 178      .pad_ddr_clk_w         (pad_ddr_clk_w  ),
  179. 179      .pad_ddr_clkn_w        (pad_ddr_clkn_w ),
  180. 180      .pad_csn_ch0           (pad_csn_ch0    ),
  181. 181      .pad_addr_ch0          (pad_addr_ch0   ),
  182. 182      .pad_dq_ch0            (pad_dq_ch0     ),
  183. 183     .pad_dqs_ch0           (pad_dqs_ch0    ),
  184. 184      .pad_dqsn_ch0          (pad_dqsn_ch0   ),
  185. 185      .pad_dm_rdqs_ch0       (pad_dm_rdqs_ch0 ),
  186. 186      .pad_cke_ch0           (pad_cke_ch0    ),
  187. 187      .pad_odt_ch0           (pad_odt_ch0    ),
  188. 188      .pad_rasn_ch0          (pad_rasn_ch0   ),
  189. 189      .pad_casn_ch0          (pad_casn_ch0   ),
  190. 190      .pad_wen_ch0           (pad_wen_ch0    ),
  191. 191      .pad_ba_ch0            (pad_ba_ch0     ),
  192. 192      .pad_loop_out          (pad_loop_out   ),
  193. 193      .pad_loop_out_h        (pad_loop_out_h )
  194. 194      
  195. 195      );
  196. 196
  197. 197 //HDMI顶层模块
  198. 198 hdmi_top u_hdmi_top(
  199. 199      .hdmi_clk       (pixel_clk    ),
  200. 200      .hdmi_clk_5     (pixel_clk_5x ),
  201. 201      .sys_rst_n      (sys_rst_n    ),
  202. 202      .fram_done      (fram_done    ),
  203. 203      .clk_locked     (clk_locked   ),
  204. 204      .rd_data        (rd_data      ),
  205. 205      .rd_en          (rdata_req    ),
  206. 206      .video_vs       (video_vs     ),
  207. 207      .h_disp         (             ),
  208. 208      .v_disp         (             ),
  209. 209      .pixel_xpos     (             ),
  210. 210      .pixel_ypos     (             ),
  211. 211      .tmds_clk_p     (tmds_clk_p   ),
  212. 212      .tmds_clk_n     (tmds_clk_n   ),
  213. 213      .tmds_data_p    (tmds_data_p  ),
  214. 214      .tmds_data_n    (tmds_data_n  )
  215. 215      );
  216. 216
  217. 217 endmodule
复制代码
FPGA顶层模块(mt9v034_hdmi)例化了以下6个模块:时钟模块(pll_clk)、I2C驱动模块(i2c_dri)、I2C配置模块(i2c_cfg)、图像采集模块(cmos_capture_raw_gray)、DDR3控制模块(ddr3_top)和HDMI顶层模块(hdmi_top)。
时钟模块(pll_clk):时钟模块通过调用PLL IP核实现,为DDR3控制模块以及I2C驱动模块提供驱动时钟,为HDMI模块提供像素时钟和5倍像素时钟(频率分别是75Mhz和375Mhz)。
I2C驱动模块(i2c_dri):I2C驱动模块负责驱动MT9V034的两线式接口总线,用户根据该模块提供的用户接口可以很方便的对MT9V034的寄存器进行配置,该模块和“EEPROM读写实验”章节中用到的I2C驱动模块为同一个模块,有关该模块的详细介绍请大家参考“EEPROM读写实验”章节;其中代码改动部分的详细介绍请大家参考“MT9V034摄像头RGB-LCD显示实验”章节。
I2C配置模块(i2c_cfg):I2C配置模块的驱动时钟是由I2C驱动模块输出的时钟提供的,这样方便了I2C驱动模块和I2C配置模块之间的数据交互。该模块寄存需要配置的寄存器地址和数据,同时该模块输出MT9V034的寄存器地址和数据以及控制I2C驱动模块开始执行的控制信号,直接连接到I2C驱动模块的用户接口,从而完成对MT9V034传感器的配置。
图像采集模块(cmos_capture_raw_gray):在摄像头像素时钟的驱动下将传感器输出的场同步信号、行同步信号以及8位数据信号进行采集,在摄像头数据稳定后输出场同步信号、行同步信号以及8位数据信号,以提供给DDR3控制模块所使用。
DDR3控制模块(ddr3_top):DDR3读写控制器模块负责驱动DDR3片外存储器,缓存图像传感器输出的图像数据。该模块将DDR3复杂的读写操作封装成类似FIFO的用户接口,非常方便用户的使用。有关DDR3控制模块的详细介绍请大家参考“DDR3读写测试实验”章节。
HDMI顶层模块(hdmi_top):HDMI顶层模块负责驱动HDMI显示器的驱动信号的输出,同时为其他模块提供场同步信号和数据请求信号。HDMI顶层模块例化了HDMI视频显示模块(video_display)、HDMI视频显示驱动模块(video_driver)和HDMI驱动模块(dvi_transmitter_top)。
HDMI视频显示驱动模块负责产生行场信号和数据有效使能信号和像素点的横纵坐标。HDMI视频显示模块负责产生显示的像素点数据,并将内部信号data_req(数据请求信号)输出至端口,方便从DD3控制器中读取数据。HDMI驱动模块负责将RGB565格式的视频图像转换成TMDS数据输出。有关HDMI视频显示驱动模块、HDMI驱动模块的详细介绍请大家参考“HDMI彩条显示实验”章节,HDMI视频显示模块详细介绍请大家参考“OV7725摄像头HDMI显示实验”章节。

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

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-6-8 02:06

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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