当前位置:   article > 正文

FPGA ov5640 lcd屏幕显示实验_ov5640 输出帧率

ov5640 输出帧率

1 ov5640简介

OV5640 是由豪威科技生产的一款 500 万像素级的 CMOS 图像传感器。它支持高达 2592x1944 分辨率的图像输出,同时能够以 15fps 的帧率输出 QSXGA 分辨率的图像,或者以 90fps 的帧率输出 VGA 分辨率的图像。OV5640 的感光阵列分辨率为 2624x1964(物理尺寸)。
OV5640 的输出接口支持 DVP 接口,控制接口则采用标准的 SCCB 接口(兼容 IIC)。这款摄像头的内部结构较为复杂,包括图像数据的采集、放大、数字信号转换等过程,最终通过 DVP 端口输出。DVP 接口本身拥有 10 位数据线,可以输出 10 位的 RAW 数据,但在大多数情况下,使用 8 位数据线来输出 RGB888 及 RGB565 等格式。

1.1 SCCB协议

SCCB(Serial Camera Control Bus)是由OmniVision Technologies公司开发的一种串行通信协议,主要用于控制其OV系列的图像传感器

OV5640 使用的是两线式接口总线,该接口总线包括 SIO_C 串行时钟输入线和 SIO_D 串行双向数据线,分别相当于 IIC 协议的 SCL 信号线和 SDA 信号线。
SCCB 的写传输协议如下图所示:

上图中的 ID ADDRESS 是由 7 位器件地址和 1 位读写控制位构成( 0 :写 1 :读); Sub-address 8 位寄存器地址,一般有些寄存器是可改写的,有些是只读的,只有可改写的寄存器才能正确写入;Write Data为 8 位写数据,每一个寄存器地址对应 8 位的配置数据。上图中的第 9 X 表示 Don’t Care (不必关心位),该位是由从机(此处指摄像头)发出应答信号来响应主机表示当前 ID Address Sub-address Write Data 是否传输完成,但是从机有可能不发出应答信号,因此主机(此处指 FPGA )可不用判断此处是否有应答,直接默认当前传输完成即可。
SCCB 的读传输协议如下图所示:

SCCB 读传输协议分为两个部分。第一部分是写器件地址和寄存器地址,即先进行一次虚
写操作,通过这种虚写操作使地址指针指向虚写操作中寄存器地址的位置,当然虚写操作也可以通过前面介绍的写传输协议来完成。第二部分是读器件地址和读数据,此时读取到的数据才是寄存器地址对应的数据。上图中的 NA 位由主机(这里指 FPGA )产生,由于 SCCB 总线不支持连续读写,因此 NA 位必须为高电平。
对于 OV5640 摄像头来说,由于其可配置的寄存器非常多,所以 OV5640 摄像头的寄存器地址位数是16 位(两个字节), OV5640 SCCB 的写传输协议如下图所示:

上图中的 ID ADDRESS 是由 7 位器件地址和 1 位读写控制位构成( 0 :写 1 :读), OV5640 的器件地址为 7’h3c,所以在写传输协议中,ID Address(W)= 8’h78(器件地址左移 1 位,低位补 0);Sub-address(H) 为高 8 位寄存器地址, Sub-address(L) 为低 8 位寄存器地址,在 OV5640 众多寄存器中,有些寄存器是可改写的,有些是只读的,只有可改写的寄存器才能正确写入;Write Data 8 位写数据,每一个寄存器地址对应 8 位的配置数据。

2 实验任务

使用 DFZU4EV MPSoC 开发板及 OV5640 摄像头实现图像采集,并通过 RGB-LCD接口驱动 RGB-LCD 液晶屏 ,并实时显示出图像。

3实验设计

3.1 顶层设计

最顶层模块 ov5640_lcd.v

  1. `timescale 1ns / 1ps
  2. module ov5640_lcd (
  3. //Differential system clocks
  4. input sys_clk_p,
  5. input sys_clk_n,
  6. input sys_rst_n, //系统复位,低电平有效
  7. //摄像头接口
  8. input cam_pclk, //cmos 数据像素时钟
  9. input cam_vsync, //cmos 场同步信号
  10. input cam_href, //cmos 行同步信号
  11. input [7:0] cam_data, //cmos 数据
  12. output cam_rst_n, //cmos 复位信号,低电平有效
  13. output cam_pwdn, //电源休眠模式选择 0:正常模式 1:电源休眠模式
  14. output cam_scl, //cmos SCCB_SCL线
  15. inout cam_sda, //cmos SCCB_SDA线
  16. // DDR4
  17. output c0_ddr4_act_n, //DDR4激活信号,低电平有效,表示一个内存行被激活。
  18. output [16:0] c0_ddr4_adr,//地址线,用于指定要访问的内存单元的行和列地址。
  19. output [1:0] c0_ddr4_ba, //Bank地址线,用于选择内存的Bank。
  20. output [0:0] c0_ddr4_bg, //Bank组选择,用于选择DDR4内存中的Bank组。
  21. output [0:0] c0_ddr4_cke, //时钟使能信号,用于启动或停止时钟信号以进入或退出自刷新模式。
  22. output [0:0] c0_ddr4_odt, //On Die Termination(片上终止)信号,用于控制内存模块上的终端电阻。
  23. output [0:0] c0_ddr4_cs_n, //片选信号,低电平有效,用于选择哪个内存芯片。
  24. output [0:0] c0_ddr4_ck_t, //DDR4时钟信号,用于同步数据传输。
  25. output [0:0] c0_ddr4_ck_c, //DDR4时钟信号的互补信号。
  26. output c0_ddr4_reset_n, //复位信号,低电平有效,用于重置DDR4内存接口。
  27. inout [1:0] c0_ddr4_dm_dbi_n, //数据掩码/数据总线隔离信号,用于屏蔽写操作的数据位或在读取操作中提供数据总线隔离。
  28. inout [15:0] c0_ddr4_dq, //数据线,用于传输数据。
  29. inout [1:0] c0_ddr4_dqs_c, //数据选通信号(DQS)的互补信号,用于采样数据。
  30. inout [1:0] c0_ddr4_dqs_t, //数据选通信号,用于指示数据线上的数据是有效的。
  31. //lcd接口
  32. output lcd_hs, //LCD 行同步信号
  33. output lcd_vs, //LCD 场同步信号
  34. output lcd_de, //LCD 数据输入使能
  35. output [23:0] lcd_rgb, //LCD 颜色数据
  36. output lcd_bl, //LCD 背光控制信号
  37. output lcd_rst, //LCD 复位信号
  38. output lcd_pclk //LCD 采样时钟
  39. );
  40. //wire define
  41. wire clk_50m; //50mhz时钟,提供给lcd驱动时钟
  42. wire locked; //时钟锁定信号
  43. wire rst_n; //全局复位
  44. wire i2c_exec; //I2C触发执行信号
  45. wire [23:0] i2c_data; //I2C要配置的地址与数据(高8位地址,低8位数据)
  46. wire cam_init_done; //摄像头初始化完成
  47. wire i2c_done; //I2C寄存器配置完成信号
  48. wire i2c_dri_clk; //I2C操作时钟
  49. wire wr_en; //DDR4控制器模块写使能
  50. wire [15:0] wr_data; //DDR4控制器模块写数据
  51. wire rdata_req; //DDR4控制器模块读使能
  52. wire [15:0] rd_data; //DDR4控制器模块读数据
  53. wire cmos_frame_valid; //数据有效使能信号
  54. wire init_calib_complete; //DDR4初始化完成init_calib_complete
  55. wire sys_init_done; //系统初始化完成(DDR初始化+摄像头初始化)
  56. wire cmos_frame_vsync; //输出帧有效场同步信号
  57. wire cmos_frame_href; //输出帧有效行同步信号
  58. wire [27:0] app_addr_rd_min; //读DDR4的起始地址
  59. wire [27:0] app_addr_rd_max; //读DDR4的结束地址
  60. wire [7:0] rd_bust_len; //从DDR4中读数据时的突发长度
  61. wire [27:0] app_addr_wr_min; //写DDR4的起始地址
  62. wire [27:0] app_addr_wr_max; //写DDR4的结束地址
  63. wire [7:0] wr_bust_len; //从DDR4中写数据时的突发长度
  64. wire lcd_clk; //分频产生的LCD 采样时钟
  65. wire i2c_rh_wl; //I2C读写控制信号
  66. wire [7:0] i2c_data_r; //I2C读数据
  67. wire [10:0] h_pixel; //存入ddr4的水平分辨率
  68. wire [10:0] v_pixel; //存入ddr4的屏垂直分辨率
  69. wire [12:0] h_disp = 13'd800; //LCD屏水平分辨率
  70. wire [12:0] v_disp = 13'd480; //LCD屏垂直分辨率
  71. wire [27:0] ddr4_addr_max = 23'd384000; //存入DDR4的最大读写地址
  72. //对HTS及VTS的配置会影响摄像头输出图像的帧率
  73. wire [12:0] total_h_pixel = 13'd1800; //水平总像素大小
  74. wire [12:0] total_v_pixel = 13'd1000; //垂直总像素大小
  75. //*****************************************************
  76. //** main code
  77. //*****************************************************
  78. //系统初始化完成:DDR4初始化完成
  79. assign sys_init_done = init_calib_complete;
  80. assign cam_sda = cam_sda_t ? cam_sda_o : 1'bz;
  81. assign cam_sda_i = cam_sda;
  82. //ov5640 驱动
  83. ov5640_dri u_ov5640_dri (
  84. .clk (clk_50m),
  85. .rst_n(sys_rst_n),
  86. .cam_pclk (cam_pclk), //像素时钟,用于同步数据传输。
  87. .cam_vsync(cam_vsync), //垂直同步信号,表示一帧的开始。
  88. .cam_href (cam_href), //行有效信号,表示当前数据是有效图像数据。
  89. .cam_data (cam_data), //图像数据信号,用于传输图像的像素信息。
  90. .cam_rst_n(cam_rst_n), //OV5640的复位信号,低电平时复位传感器。
  91. .cam_pwdn (cam_pwdn), //电源休眠模式选择 0:正常模式 1:电源休眠模式
  92. .cam_scl (cam_scl), //cmos SCCB_SCL线
  93. .cam_sda_i(cam_sda_i), //cmos SCCB_SDA输入
  94. .cam_sda_o(cam_sda_o), //cmos SCCB_SDA输出
  95. .cam_sda_t(cam_sda_t), //cmos SCCB_SDA使能
  96. .capture_start (init_calib_complete), //开始捕获图像的信号
  97. .cmos_h_pixel (h_disp), //水平方向分辨率
  98. .cmos_v_pixel (v_disp), //垂直方向分辨率
  99. .total_h_pixel (total_h_pixel), //水平总像素大小
  100. .total_v_pixel (total_v_pixel), //垂直总像素大小
  101. .cmos_frame_vsync(cmos_frame_vsync), //帧有效信号
  102. .cmos_frame_href (),
  103. .cmos_frame_valid(cmos_frame_valid), //数据有效使能信号
  104. .cmos_frame_data (wr_data) //有效数据
  105. );
  106. ddr4_top u_ddr4_top (
  107. .sys_rst_n (sys_rst_n), //复位,低有效
  108. .sys_init_done (sys_init_done), //系统初始化完成
  109. .init_calib_complete(init_calib_complete), //ddr4初始化完成信号
  110. //ddr4接口信号
  111. .app_addr_rd_min (28'd0), //读ddr4的起始地址
  112. .app_addr_rd_max (ddr4_addr_max[27:0]), //读ddr4的结束地址
  113. .rd_bust_len (h_disp[10:3]), //从ddr4中读数据时的突发长度
  114. .app_addr_wr_min (28'd0), //写ddr4的起始地址
  115. .app_addr_wr_max (ddr4_addr_max[27:0]), //写ddr4的结束地址
  116. .wr_bust_len (h_disp[10:3]), //从ddr4中写数据时的突发长度
  117. // ddr4 IO接口
  118. .c0_sys_clk_p (sys_clk_p),
  119. .c0_sys_clk_n (sys_clk_n),
  120. .c0_ddr4_act_n (c0_ddr4_act_n),
  121. .c0_ddr4_adr (c0_ddr4_adr),
  122. .c0_ddr4_ba (c0_ddr4_ba),
  123. .c0_ddr4_bg (c0_ddr4_bg),
  124. .c0_ddr4_cke (c0_ddr4_cke),
  125. .c0_ddr4_odt (c0_ddr4_odt),
  126. .c0_ddr4_cs_n (c0_ddr4_cs_n),
  127. .c0_ddr4_ck_t (c0_ddr4_ck_t),
  128. .c0_ddr4_ck_c (c0_ddr4_ck_c),
  129. .c0_ddr4_reset_n (c0_ddr4_reset_n),
  130. .c0_ddr4_dm_dbi_n (c0_ddr4_dm_dbi_n),
  131. .c0_ddr4_dq (c0_ddr4_dq),
  132. .c0_ddr4_dqs_c (c0_ddr4_dqs_c),
  133. .c0_ddr4_dqs_t (c0_ddr4_dqs_t),
  134. //用户
  135. .clk_50m (clk_50m),
  136. .ddr4_read_valid (1'b1), //DDR4 读使能
  137. .ddr4_pingpang_en(1'b1), //DDR4 乒乓操作使能
  138. .wr_clk (cam_pclk), //写时钟
  139. .wr_load (cmos_frame_vsync), //输入源更新信号
  140. .datain_valid (cmos_frame_valid), //数据有效使能信号
  141. .datain (wr_data), //有效数据
  142. .rd_clk (lcd_clk), //读时钟
  143. .rd_load (rd_vsync), //输出源更新信号
  144. .dataout (rd_data), //rfifo输出数据
  145. .rdata_req (rdata_req) //请求数据输入
  146. );
  147. //LCD驱动显示模块
  148. lcd_rgb_top u_lcd_rgb_top (
  149. .sys_clk (clk_50m),
  150. .sys_rst_n (sys_rst_n),
  151. .sys_init_done(sys_init_done),
  152. //lcd接口
  153. .lcd_hs (lcd_hs), //LCD 行同步信号
  154. .lcd_vs (lcd_vs), //LCD 场同步信号
  155. .lcd_de (lcd_de), //LCD 数据输入使能
  156. .lcd_rgb (lcd_rgb), //LCD 颜色数据
  157. .lcd_bl (lcd_bl), //LCD 背光控制信号
  158. .lcd_rst (lcd_rst), //LCD 复位信号
  159. .lcd_pclk(lcd_pclk), //LCD 采样时钟
  160. .lcd_clk (lcd_clk), //LCD 驱动时钟
  161. //用户接口
  162. .out_vsync (rd_vsync), //lcd场信号
  163. .h_disp (), //行分辨率
  164. .v_disp (), //场分辨率
  165. .pixel_xpos(), //像素点横坐标
  166. .pixel_ypos(), //像素点纵坐标
  167. .data_in (rd_data), //rfifo输出数据
  168. .data_req (rdata_req) //请求数据输入
  169. );
  170. endmodule

3.2 DDR及FIFO设计

ddr4_top.v

  1. `timescale 1ns / 1ps
  2. //ddr4顶层模块
  3. module ddr4_top (
  4. input sys_rst_n, //复位,低有效
  5. input sys_init_done, //系统初始化完成
  6. // //DDR4接口信号
  7. input [27:0] app_addr_rd_min, //读DDR4的起始地址
  8. input [27:0] app_addr_rd_max, //读DDR4的结束地址
  9. input [ 7:0] rd_bust_len, //从DDR4中读数据时的突发长度
  10. input [27:0] app_addr_wr_min, //读DDR4的起始地址
  11. input [27:0] app_addr_wr_max, //读DDR4的结束地址
  12. input [ 7:0] wr_bust_len, //从DDR4中读数据时的突发长度
  13. // DDR4 IO接口
  14. input c0_sys_clk_p,
  15. input c0_sys_clk_n,
  16. output c0_ddr4_act_n,
  17. output [16:0] c0_ddr4_adr,
  18. output [ 1:0] c0_ddr4_ba,
  19. output [ 0:0] c0_ddr4_bg,
  20. output [ 0:0] c0_ddr4_cke,
  21. output [ 0:0] c0_ddr4_odt,
  22. output [ 0:0] c0_ddr4_cs_n,
  23. output [ 0:0] c0_ddr4_ck_t,
  24. output [ 0:0] c0_ddr4_ck_c,
  25. output c0_ddr4_reset_n,
  26. inout [ 1:0] c0_ddr4_dm_dbi_n,
  27. inout [15:0] c0_ddr4_dq,
  28. inout [ 1:0] c0_ddr4_dqs_c,
  29. inout [ 1:0] c0_ddr4_dqs_t,
  30. //用户
  31. input ddr4_read_valid, //DDR4 读使能
  32. input ddr4_pingpang_en, //DDR4 乒乓操作使能
  33. input wr_clk, //wfifo时钟
  34. input rd_clk, //rfifo的读时钟
  35. input datain_valid, //数据有效使能信号
  36. input [15:0] datain, //有效数据
  37. input rdata_req, //请求像素点颜色数据输入
  38. input rd_load, //输出源更新信号
  39. input wr_load, //输入源更新信号
  40. output [15:0] dataout, //rfifo输出数据
  41. output clk_50m,
  42. output init_calib_complete //ddr4初始化完成信号
  43. );
  44. //wire define
  45. wire ui_clk; //用户时钟
  46. wire [ 27:0] app_addr; //ddr4 地址
  47. wire [ 2:0] app_cmd; //用户读写命令
  48. wire app_en; //MIG IP核使能
  49. wire app_rdy; //MIG IP核空闲
  50. wire [127:0] app_rd_data; //用户读数据
  51. wire app_rd_data_end; //突发读当前时钟最后一个数据
  52. wire app_rd_data_valid; //读数据有效
  53. wire [127:0] app_wdf_data; //用户写数据
  54. wire app_wdf_end; //突发写当前时钟最后一个数据
  55. wire [ 15:0] app_wdf_mask; //写数据屏蔽
  56. wire app_wdf_rdy; //写空闲
  57. wire app_sr_active; //保留
  58. wire app_ref_ack; //刷新请求
  59. wire app_zq_ack; //ZQ 校准请求
  60. wire app_wdf_wren; //ddr4 写使能
  61. wire clk_ref_i; //ddr4参考时钟
  62. wire sys_clk_i; //MIG IP核输入时钟
  63. wire ui_clk_sync_rst; //用户复位信号
  64. wire [ 20:0] rd_cnt; //实际读地址计数
  65. wire [3 : 0] state_cnt; //状态计数器
  66. wire [ 23:0] rd_addr_cnt; //用户读地址计数器
  67. wire [ 23:0] wr_addr_cnt; //用户写地址计数器
  68. wire rfifo_wren; //从ddr4读出数据的有效使能
  69. wire [ 10:0] wfifo_rcount; //rfifo剩余数据计数
  70. wire [ 10:0] rfifo_wcount; //wfifo写进数据计数
  71. //*****************************************************
  72. //** main code
  73. //*****************************************************
  74. //读写模块
  75. ddr4_rw u_ddr4_rw (
  76. .ui_clk(ui_clk),
  77. .ui_clk_sync_rst(ui_clk_sync_rst),
  78. //MIG 接口
  79. .init_calib_complete (init_calib_complete) , //ddr4初始化完成信号
  80. .app_rdy(app_rdy), //MIG IP核空闲
  81. .app_wdf_rdy(app_wdf_rdy), //写空闲
  82. .app_rd_data_valid(app_rd_data_valid), //读数据有效
  83. .app_addr(app_addr), //ddr4 地址
  84. .app_en(app_en), //MIG IP核使能
  85. .app_wdf_wren(app_wdf_wren), //ddr4 写使能
  86. .app_wdf_end (app_wdf_end) , //突发写当前时钟最后一个数据
  87. .app_cmd (app_cmd) , //用户读写命令
  88. //ddr4 地址参数
  89. .app_addr_rd_min(app_addr_rd_min), //读ddr4的起始地址
  90. .app_addr_rd_max(app_addr_rd_max), //读ddr4的结束地址
  91. .rd_bust_len (rd_bust_len) , //从ddr4中读数据时的突发长度
  92. .app_addr_wr_min(app_addr_wr_min), //写ddr4的起始地址
  93. .app_addr_wr_max(app_addr_wr_max), //写ddr4的结束地址
  94. .wr_bust_len (wr_bust_len) , //从ddr4中写数据时的突发长度
  95. //用户接口
  96. .rfifo_wren(rfifo_wren), //从ddr4读出数据的有效使能
  97. .rd_load(rd_load), //输出源更新信号
  98. .wr_load(wr_load), //输入源更新信号
  99. .ddr4_read_valid(ddr4_read_valid), //ddr4 读使能
  100. .ddr4_pingpang_en(ddr4_pingpang_en), //ddr4 乒乓操作使能
  101. .wfifo_rcount(wfifo_rcount), //rfifo剩余数据计数
  102. .rfifo_wcount(rfifo_wcount) //wfifo写进数据计数
  103. );
  104. ddr4_0 u_ddr4_0 (
  105. .c0_init_calib_complete(init_calib_complete), // output wire c0_init_calib_complete
  106. .dbg_clk(), // output wire dbg_clk
  107. .c0_sys_clk_p(c0_sys_clk_p), // input wire c0_sys_clk_p
  108. .c0_sys_clk_n(c0_sys_clk_n), // input wire c0_sys_clk_n
  109. .dbg_bus(), // output wire [511 : 0] dbg_bus
  110. .c0_ddr4_adr(c0_ddr4_adr), // output wire [16 : 0] c0_ddr4_adr
  111. .c0_ddr4_ba(c0_ddr4_ba), // output wire [1 : 0] c0_ddr4_ba
  112. .c0_ddr4_cke(c0_ddr4_cke), // output wire [0 : 0] c0_ddr4_cke
  113. .c0_ddr4_cs_n(c0_ddr4_cs_n), // output wire [0 : 0] c0_ddr4_cs_n
  114. .c0_ddr4_dm_dbi_n(c0_ddr4_dm_dbi_n), // inout wire [1 : 0] c0_ddr4_dm_dbi_n
  115. .c0_ddr4_dq(c0_ddr4_dq), // inout wire [15 : 0] c0_ddr4_dq
  116. .c0_ddr4_dqs_c(c0_ddr4_dqs_c), // inout wire [1 : 0] c0_ddr4_dqs_c
  117. .c0_ddr4_dqs_t(c0_ddr4_dqs_t), // inout wire [1 : 0] c0_ddr4_dqs_t
  118. .c0_ddr4_odt(c0_ddr4_odt), // output wire [0 : 0] c0_ddr4_odt
  119. .c0_ddr4_bg(c0_ddr4_bg), // output wire [0 : 0] c0_ddr4_bg
  120. .c0_ddr4_reset_n(c0_ddr4_reset_n), // output wire c0_ddr4_reset_n
  121. .c0_ddr4_act_n(c0_ddr4_act_n), // output wire c0_ddr4_act_n
  122. .c0_ddr4_ck_c(c0_ddr4_ck_c), // output wire [0 : 0] c0_ddr4_ck_c
  123. .c0_ddr4_ck_t(c0_ddr4_ck_t), // output wire [0 : 0] c0_ddr4_ck_t
  124. //user interface
  125. .c0_ddr4_ui_clk(ui_clk), // output wire c0_ddr4_ui_clk 用户时钟
  126. .c0_ddr4_ui_clk_sync_rst(ui_clk_sync_rst), // output wire c0_ddr4_ui_clk_sync_rst 用户复位
  127. .c0_ddr4_app_en(app_en), // input wire c0_ddr4_app_en
  128. .c0_ddr4_app_hi_pri(1'b0), // input wire c0_ddr4_app_hi_pri
  129. .c0_ddr4_app_wdf_end(app_wdf_end), // input wire c0_ddr4_app_wdf_end
  130. .c0_ddr4_app_wdf_wren(app_wdf_wren), // input wire c0_ddr4_app_wdf_wren
  131. .c0_ddr4_app_rd_data_end(app_rd_data_end), // output wire c0_ddr4_app_rd_data_end
  132. .c0_ddr4_app_rd_data_valid(app_rd_data_valid), // output wire c0_ddr4_app_rd_data_valid
  133. .c0_ddr4_app_rdy(app_rdy), // output wire c0_ddr4_app_rdy
  134. .c0_ddr4_app_wdf_rdy(app_wdf_rdy), // output wire c0_ddr4_app_wdf_rdy
  135. .c0_ddr4_app_addr(app_addr), // input wire [27 : 0] c0_ddr4_app_addr
  136. .c0_ddr4_app_cmd(app_cmd), // input wire [2 : 0] c0_ddr4_app_cmd
  137. .c0_ddr4_app_wdf_data(app_wdf_data), // input wire [127 : 0] c0_ddr4_app_wdf_data
  138. .c0_ddr4_app_wdf_mask(16'b0), // input wire [15 : 0] c0_ddr4_app_wdf_mask
  139. .c0_ddr4_app_rd_data(app_rd_data), // output wire [127 : 0] c0_ddr4_app_rd_data
  140. .addn_ui_clkout1(clk_50m), // output wire addn_ui_clkout1
  141. .sys_rst(~sys_rst_n) // input wire sys_rst
  142. );
  143. ddr4_fifo_ctrl u_ddr4_fifo_ctrl (
  144. .rst_n (sys_rst_n && sys_init_done),
  145. //输入源接口
  146. .wr_clk (wr_clk),
  147. .rd_clk (rd_clk),
  148. .clk_100 (ui_clk), //用户时钟
  149. .datain_valid(datain_valid), //数据有效使能信号
  150. .datain (datain), //有效数据
  151. .rfifo_din (app_rd_data), //用户读数据
  152. .rdata_req (rdata_req), //请求像素点颜色数据输入
  153. .rfifo_wren (rfifo_wren), //ddr4读出数据的有效使能
  154. .wfifo_rden (app_wdf_wren), //ddr4 写使能
  155. //用户接口
  156. .wfifo_rcount(wfifo_rcount), //rfifo剩余数据计数
  157. .rfifo_wcount(rfifo_wcount), //wfifo写进数据计数
  158. .wfifo_dout (app_wdf_data), //用户写数据
  159. .rd_load (rd_load), //输出源更新信号
  160. .wr_load (wr_load), //输入源更新信号
  161. .pic_data (dataout) //rfifo输出数据
  162. );
  163. endmodule

MIG配置

ddr4_rw.v

  1. `timescale 1ns / 1ps
  2. //ddr3控制器读写模块
  3. module ddr4_rw (
  4. input ui_clk, //用户时钟
  5. input ui_clk_sync_rst, //复位,高有效
  6. input init_calib_complete, //ddr4初始化完成
  7. input app_rdy, //MIG IP核空闲
  8. input app_wdf_rdy, //MIG写FIFO空闲
  9. input app_rd_data_valid, //读数据有效
  10. input [10:0] wfifo_rcount, //写端口FIFO中的数据量
  11. input [10:0] rfifo_wcount, //读端口FIFO中的数据量
  12. input rd_load, //输出源更新信号
  13. input wr_load, //输入源更新信号
  14. input [27:0] app_addr_rd_min, //读ddr4的起始地址
  15. input [27:0] app_addr_rd_max, //读ddr4的结束地址
  16. input [ 7:0] rd_bust_len, //从ddr4中读数据时的突发长度
  17. input [27:0] app_addr_wr_min, //写ddr4的起始地址
  18. input [27:0] app_addr_wr_max, //写ddr4的结束地址
  19. input [ 7:0] wr_bust_len, //从ddr4中写数据时的突发长度
  20. input ddr4_read_valid, //ddr4 读使能
  21. input ddr4_pingpang_en, //ddr4 乒乓操作使能
  22. output rfifo_wren, //从ddr4读出数据的有效使能
  23. output [27:0] app_addr, //ddr4地址
  24. output app_en, //MIG IP核操作使能
  25. output app_wdf_wren, //用户写使能
  26. output app_wdf_end, //突发写当前时钟最后一个数据
  27. output [ 2:0] app_cmd //MIG IP核操作命令,读或者写
  28. );
  29. //localparam
  30. localparam IDLE = 4'b0001; //空闲状态
  31. localparam ddr4_DONE = 4'b0010; //ddr4初始化完成状态
  32. localparam WRITE = 4'b0100; //读FIFO保持状态
  33. localparam READ = 4'b1000; //写FIFO保持状态
  34. //reg define
  35. reg [27:0] app_addr; //ddr4地址
  36. reg [27:0] app_addr_rd; //ddr4读地址
  37. reg [27:0] app_addr_wr; //ddr4写地址
  38. reg [ 3:0] state_cnt; //状态计数器
  39. reg [23:0] rd_addr_cnt; //用户读地址计数
  40. reg [23:0] wr_addr_cnt; //用户写地址计数
  41. reg [ 8:0] burst_rd_cnt; //突发读次数计数器
  42. reg [ 8:0] burst_wr_cnt; //突发写次数计数器
  43. reg [10:0] raddr_rst_h_cnt; //输出源的帧复位脉冲进行计数
  44. reg [27:0] app_addr_rd_min_a; //读ddr4的起始地址
  45. reg [27:0] app_addr_rd_max_a; //读ddr4的结束地址
  46. reg [ 7:0] rd_bust_len_a; //从ddr4中读数据时的突发长度
  47. reg [27:0] app_addr_wr_min_a; //写ddr4的起始地址
  48. reg [27:0] app_addr_wr_max_a; //写ddr4的结束地址
  49. reg [ 7:0] wr_bust_len_a; //从ddr4中写数据时的突发长度
  50. reg star_rd_flag; //复位后写入2帧的标志信号
  51. reg rd_load_d0;
  52. reg rd_load_d1;
  53. reg raddr_rst_h; //输出源的帧复位脉冲
  54. reg wr_load_d0;
  55. reg wr_load_d1;
  56. reg wr_rst; //输入源帧复位标志
  57. reg rd_rst; //输出源帧复位标志
  58. reg raddr_page; //ddr4读地址切换信号
  59. reg waddr_page; //ddr4写地址切换信号
  60. reg burst_done_wr; //一次突发写结束信号
  61. reg burst_done_rd; //一次读发写结束信号
  62. reg wr_end; //一次突发写结束信号
  63. reg rd_end; //一次读发写结束信号
  64. wire rst_n;
  65. //*****************************************************
  66. //** main code
  67. //*****************************************************
  68. //将数据有效信号赋给wfifo写使能
  69. assign rfifo_wren = app_rd_data_valid;
  70. assign rst_n = ~ui_clk_sync_rst;
  71. //在写状态MIG空闲且写有效,或者在读状态MIG空闲,此时使能信号为高,其他情况为低
  72. assign app_en = ((state_cnt == WRITE && (app_rdy && app_wdf_rdy))
  73. ||(state_cnt == READ && app_rdy)) ? 1'b1:1'b0;
  74. //在写状态,MIG空闲且写有效,此时拉高写使能
  75. assign app_wdf_wren = (state_cnt == WRITE && (app_rdy && app_wdf_rdy)) ? 1'b1 : 1'b0;
  76. //由于我们ddr4芯片时钟和用户时钟的分频选择4:1,突发长度为8,故两个信号相同
  77. assign app_wdf_end = app_wdf_wren;
  78. //处于读的时候命令值为1,其他时候命令值为0
  79. assign app_cmd = (state_cnt == READ) ? 3'd1 : 3'd0;
  80. //将数据读写地址赋给ddr地址
  81. always @(*) begin
  82. if (~rst_n) app_addr <= 0;
  83. else if (state_cnt == READ)
  84. if (ddr4_pingpang_en) app_addr <= {2'b0, raddr_page, app_addr_rd[24:0]};
  85. else app_addr <= {3'b0, app_addr_rd[24:0]};
  86. else if (ddr4_pingpang_en) app_addr <= {2'b0, waddr_page, app_addr_wr[24:0]};
  87. else app_addr <= {3'b0, app_addr_wr[24:0]};
  88. end
  89. //对信号进行打拍处理
  90. always @(posedge ui_clk or negedge rst_n) begin
  91. if (~rst_n) begin
  92. rd_load_d0 <= 0;
  93. rd_load_d1 <= 0;
  94. wr_load_d0 <= 0;
  95. wr_load_d1 <= 0;
  96. end else begin
  97. rd_load_d0 <= rd_load;
  98. rd_load_d1 <= rd_load_d0;
  99. wr_load_d0 <= wr_load;
  100. wr_load_d1 <= wr_load_d0;
  101. end
  102. end
  103. //对异步信号进行打拍处理
  104. always @(posedge ui_clk or negedge rst_n) begin
  105. if (~rst_n) begin
  106. app_addr_rd_min_a <= 0;
  107. app_addr_rd_max_a <= 0;
  108. rd_bust_len_a <= 0;
  109. app_addr_wr_min_a <= 0;
  110. app_addr_wr_max_a <= 0;
  111. wr_bust_len_a <= 0;
  112. end else begin
  113. app_addr_rd_min_a <= app_addr_rd_min;
  114. app_addr_rd_max_a <= app_addr_rd_max;
  115. rd_bust_len_a <= rd_bust_len;
  116. app_addr_wr_min_a <= app_addr_wr_min;
  117. app_addr_wr_max_a <= app_addr_wr_max;
  118. wr_bust_len_a <= wr_bust_len;
  119. end
  120. end
  121. //对输入源做个帧复位标志
  122. always @(posedge ui_clk or negedge rst_n) begin
  123. if (~rst_n) wr_rst <= 0;
  124. else if (wr_load_d0 && !wr_load_d1) wr_rst <= 1;
  125. else wr_rst <= 0;
  126. end
  127. //对输出源做个帧复位标志
  128. always @(posedge ui_clk or negedge rst_n) begin
  129. if (~rst_n) rd_rst <= 0;
  130. else if (rd_load_d0 && !rd_load_d1) rd_rst <= 1;
  131. else rd_rst <= 0;
  132. end
  133. //对输出源的读地址做个帧复位脉冲
  134. always @(posedge ui_clk or negedge rst_n) begin
  135. if (~rst_n) raddr_rst_h <= 1'b0;
  136. else if (rd_load_d0 && !rd_load_d1) raddr_rst_h <= 1'b1;
  137. else if (app_addr_rd == app_addr_rd_min_a) raddr_rst_h <= 1'b0;
  138. else raddr_rst_h <= raddr_rst_h;
  139. end
  140. //对输出源的帧复位脉冲进行计数
  141. always @(posedge ui_clk or negedge rst_n) begin
  142. if (~rst_n) raddr_rst_h_cnt <= 11'b0;
  143. else if (raddr_rst_h) raddr_rst_h_cnt <= raddr_rst_h_cnt + 1'b1;
  144. else raddr_rst_h_cnt <= 11'b0;
  145. end
  146. //对输出源帧的读地址高位切换
  147. always @(posedge ui_clk or negedge rst_n) begin
  148. if (~rst_n) raddr_page <= 1'b0;
  149. else if (rd_end) raddr_page <= ~waddr_page;
  150. else raddr_page <= raddr_page;
  151. end
  152. //对输入源帧的写地址高位切换
  153. always @(posedge ui_clk or negedge rst_n) begin
  154. if (~rst_n) waddr_page <= 1'b1;
  155. else if (wr_end) waddr_page <= ~waddr_page;
  156. else waddr_page <= waddr_page;
  157. end
  158. //ddr4读写逻辑实现
  159. always @(posedge ui_clk or negedge rst_n) begin
  160. if (~rst_n) begin
  161. state_cnt <= IDLE;
  162. wr_addr_cnt <= 24'd0;
  163. rd_addr_cnt <= 24'd0;
  164. app_addr_wr <= 28'd0;
  165. app_addr_rd <= 28'd0;
  166. wr_end <= 1'b0;
  167. rd_end <= 1'b0;
  168. end else begin
  169. case (state_cnt)
  170. IDLE: begin
  171. if (init_calib_complete) state_cnt <= ddr4_DONE;
  172. else state_cnt <= IDLE;
  173. end
  174. ddr4_DONE: begin
  175. if (wr_rst) begin //当帧复位到来时,对寄存器进行复位
  176. state_cnt <= ddr4_DONE;
  177. wr_addr_cnt <= 24'd0;
  178. app_addr_wr <= app_addr_wr_min_a;
  179. end //当读到结束地址对寄存器复位
  180. else if(app_addr_rd >= app_addr_rd_max_a - 8)begin
  181. state_cnt <= ddr4_DONE;
  182. rd_addr_cnt <= 24'd0;
  183. app_addr_rd <= app_addr_rd_min_a;
  184. rd_end <= 1'b1;
  185. end //当写到结束地址对寄存器复位
  186. else if(app_addr_wr >= app_addr_wr_max_a - 8)begin
  187. state_cnt <= ddr4_DONE;
  188. rd_addr_cnt <= 24'd0;
  189. app_addr_wr <= app_addr_wr_min_a;
  190. wr_end <= 1'b1;
  191. end else if (wfifo_rcount >= wr_bust_len_a - 2) begin
  192. state_cnt <= WRITE; //跳到写操作
  193. wr_addr_cnt <= 24'd0;
  194. app_addr_wr <= app_addr_wr; //写地址保持不变
  195. end else if (raddr_rst_h) begin //当帧复位到来时,对寄存器进行复位
  196. if (raddr_rst_h_cnt >= 1000 && ddr4_read_valid) begin
  197. state_cnt <= READ; //保证读fifo在复位时不回写入数据
  198. rd_addr_cnt <= 24'd0;
  199. app_addr_rd <= app_addr_rd_min_a;
  200. end else begin
  201. state_cnt <= ddr4_DONE;
  202. rd_addr_cnt <= 24'd0;
  203. app_addr_rd <= app_addr_rd;
  204. end
  205. end //当rfifo存储数据少于一次突发长度时,并且ddr已经写入了1帧数据
  206. else if(rfifo_wcount < rd_bust_len_a && ddr4_read_valid )begin
  207. state_cnt <= READ; //跳到读操作
  208. rd_addr_cnt <= 24'd0;
  209. app_addr_rd <= app_addr_rd; //读地址保持不变
  210. end else begin
  211. state_cnt <= state_cnt;
  212. wr_addr_cnt <= 24'd0;
  213. rd_addr_cnt <= 24'd0;
  214. rd_end <= 1'b0;
  215. wr_end <= 1'b0;
  216. end
  217. end
  218. WRITE: begin
  219. if((wr_addr_cnt == (wr_bust_len_a - 1)) &&
  220. (app_rdy && app_wdf_rdy))begin //写到设定的长度跳到等待状态
  221. state_cnt <= ddr4_DONE; //写到设定的长度跳到等待状态
  222. app_addr_wr <= app_addr_wr + 8; //一次性写进8个数,故加8
  223. end else if (app_rdy && app_wdf_rdy) begin //写条件满足
  224. wr_addr_cnt <= wr_addr_cnt + 1'd1; //写地址计数器自加
  225. app_addr_wr <= app_addr_wr + 8; //一次性写进8个数,故加8
  226. end else begin //写条件不满足,保持当前值
  227. wr_addr_cnt <= wr_addr_cnt;
  228. app_addr_wr <= app_addr_wr;
  229. end
  230. end
  231. READ: begin //读到设定的地址长度
  232. if ((rd_addr_cnt == (rd_bust_len_a - 1)) && app_rdy) begin
  233. state_cnt <= ddr4_DONE; //则跳到空闲状态
  234. app_addr_rd <= app_addr_rd + 8;
  235. end else if (app_rdy) begin //若MIG已经准备好,则开始读
  236. rd_addr_cnt <= rd_addr_cnt + 1'd1; //用户地址计数器每次加一
  237. app_addr_rd <= app_addr_rd + 8; //一次性读出8个数,ddr4地址加8
  238. end else begin //若MIG没准备好,则保持原值
  239. rd_addr_cnt <= rd_addr_cnt;
  240. app_addr_rd <= app_addr_rd;
  241. end
  242. end
  243. default: begin
  244. state_cnt <= IDLE;
  245. wr_addr_cnt <= 24'd0;
  246. rd_addr_cnt <= 24'd0;
  247. end
  248. endcase
  249. end
  250. end
  251. endmodule

读FIFO配置

写FIFO配置

ddr4_fifo_ctrl.v

  1. // ddr控制器fifo控制模块
  2. `timescale 1ns / 1ps
  3. module ddr4_fifo_ctrl (
  4. input rst_n, //复位信号
  5. input wr_clk, //wfifo时钟
  6. input rd_clk, //rfifo时钟
  7. input clk_100, //用户时钟
  8. input datain_valid, //数据有效使能信号
  9. input [ 15:0] datain, //有效数据
  10. input [127:0] rfifo_din, //用户读数据
  11. input rdata_req, //请求像素点颜色数据输入
  12. input rfifo_wren, //从ddr4读出数据的有效使能
  13. input wfifo_rden, //wfifo读使能
  14. input rd_load, //输出源场信号
  15. input wr_load, //输入源场信号
  16. output [127:0] wfifo_dout, //用户写数据
  17. output [ 10:0] wfifo_rcount, //rfifo剩余数据计数
  18. output [ 10:0] rfifo_wcount, //wfifo写进数据计数
  19. output reg [ 15:0] pic_data //有效数据
  20. );
  21. //reg define
  22. reg [127:0] datain_t; //16bit输入源数据移位拼接得到
  23. reg [7:0] cam_data_d0;
  24. reg [4:0] i_d0;
  25. reg [30:0] rd_load_d; //由输出源场信号移位拼接得到
  26. reg [6:0] byte_cnt; //写数据移位计数器
  27. reg [127:0] data; //rfifo输出数据打拍得到
  28. reg [4:0] i; //读数据移位计数器
  29. reg [15:0] wr_load_d; //由输入源场信号移位拼接得到
  30. reg [3:0] cmos_ps_cnt; //等待帧数稳定计数器
  31. reg cam_href_d0;
  32. reg cam_href_d1;
  33. reg wr_load_d0;
  34. reg rd_load_d0;
  35. reg rdfifo_rst_h; //rfifo复位信号,高有效
  36. reg wr_load_d1;
  37. reg wfifo_rst_h; //wfifo复位信号,高有效
  38. reg wfifo_wren; //wfifo写使能信号
  39. //wire define
  40. wire [127:0] rfifo_dout; //rfifo输出数据
  41. wire [127:0] wfifo_din; //wfifo写数据
  42. wire [15:0] dataout[0:15]; //定义输出数据的二维数组
  43. wire rfifo_rden; //rfifo的读使能
  44. //*****************************************************
  45. //** main code
  46. //*****************************************************
  47. //rfifo输出的数据存到二维数组
  48. assign dataout[0] = data[127:112];
  49. assign dataout[1] = data[111:96];
  50. assign dataout[2] = data[95:80];
  51. assign dataout[3] = data[79:64];
  52. assign dataout[4] = data[63:48];
  53. assign dataout[5] = data[47:32];
  54. assign dataout[6] = data[31:16];
  55. assign dataout[7] = data[15:0];
  56. assign wfifo_din = datain_t;
  57. //移位寄存器计满时,从rfifo读出一个数据
  58. assign rfifo_rden = (rdata_req && (i == 7)) ? 1'b1 : 1'b0;
  59. //16位数据转128位RGB565数据
  60. always @(posedge wr_clk or negedge rst_n) begin
  61. if (!rst_n) begin
  62. datain_t <= 0;
  63. byte_cnt <= 0;
  64. end else if (datain_valid) begin
  65. if (byte_cnt == 7) begin
  66. byte_cnt <= 0;
  67. datain_t <= {datain_t[111:0], datain};
  68. end else begin
  69. byte_cnt <= byte_cnt + 1;
  70. datain_t <= {datain_t[111:0], datain};
  71. end
  72. end else begin
  73. byte_cnt <= byte_cnt;
  74. datain_t <= datain_t;
  75. end
  76. end
  77. //wfifo写使能产生
  78. always @(posedge wr_clk or negedge rst_n) begin
  79. if (!rst_n) wfifo_wren <= 0;
  80. else if (wfifo_wren == 1) wfifo_wren <= 0;
  81. else if (byte_cnt == 7 && datain_valid) //输入源数据传输8次,写使能拉高一次
  82. wfifo_wren <= 1;
  83. else wfifo_wren <= 0;
  84. end
  85. always @(posedge rd_clk or negedge rst_n) begin
  86. if (!rst_n) data <= 127'b0;
  87. else data <= rfifo_dout;
  88. end
  89. //对rfifo出来的128bit数据拆解成16个16bit数据
  90. always @(posedge rd_clk or negedge rst_n) begin
  91. if (!rst_n) begin
  92. pic_data <= 16'b0;
  93. i <= 0;
  94. i_d0 <= 0;
  95. end else if (rdata_req) begin
  96. if (i == 7) begin
  97. pic_data <= dataout[i_d0];
  98. i <= 0;
  99. i_d0 <= i;
  100. end else begin
  101. pic_data <= dataout[i_d0];
  102. i <= i + 1;
  103. i_d0 <= i;
  104. end
  105. end else begin
  106. pic_data <= pic_data;
  107. i <= 0;
  108. i_d0 <= 0;
  109. end
  110. end
  111. always @(posedge clk_100 or negedge rst_n) begin
  112. if (!rst_n) rd_load_d0 <= 1'b0;
  113. else rd_load_d0 <= rd_load;
  114. end
  115. //对输出源场信号进行移位寄存
  116. always @(posedge clk_100 or negedge rst_n) begin
  117. if (!rst_n) rd_load_d <= 1'b0;
  118. else rd_load_d <= {rd_load_d[30:0], rd_load_d0};
  119. end
  120. //产生一段复位电平,满足fifo复位时序
  121. always @(posedge clk_100 or negedge rst_n) begin
  122. if (!rst_n) rdfifo_rst_h <= 1'b0;
  123. else if (rd_load_d[0] && !rd_load_d[29]) rdfifo_rst_h <= 1'b1;
  124. else rdfifo_rst_h <= 1'b0;
  125. end
  126. //对输入源场信号进行移位寄存
  127. always @(posedge wr_clk or negedge rst_n) begin
  128. if (!rst_n) begin
  129. wr_load_d0 <= 1'b0;
  130. wr_load_d <= 16'b0;
  131. end else begin
  132. wr_load_d0 <= wr_load;
  133. wr_load_d <= {wr_load_d[14:0], wr_load_d0};
  134. end
  135. end
  136. //产生一段复位电平,满足fifo复位时序
  137. always @(posedge wr_clk or negedge rst_n) begin
  138. if (!rst_n) wfifo_rst_h <= 1'b0;
  139. else if (wr_load_d[0] && !wr_load_d[15]) wfifo_rst_h <= 1'b1;
  140. else wfifo_rst_h <= 1'b0;
  141. end
  142. rd_fifo u_rd_fifo (
  143. .rst (~rst_n | rdfifo_rst_h),
  144. .wr_clk (clk_100),
  145. .rd_clk (rd_clk),
  146. .din (rfifo_din),
  147. .wr_en (rfifo_wren),
  148. .rd_en (rfifo_rden),
  149. .dout (rfifo_dout),
  150. .full (),
  151. .empty (),
  152. .rd_data_count(),
  153. .wr_data_count(rfifo_wcount),
  154. .wr_rst_busy (),
  155. .rd_rst_busy ()
  156. );
  157. wr_fifo u_wr_fifo (
  158. .rst (~rst_n | wfifo_rst_h),
  159. .wr_clk (wr_clk),
  160. .rd_clk (clk_100),
  161. .din (wfifo_din),
  162. .wr_en (wfifo_wren),
  163. .rd_en (wfifo_rden),
  164. .dout (wfifo_dout),
  165. .full (),
  166. .empty (),
  167. .rd_data_count(wfifo_rcount),
  168. .wr_data_count(),
  169. .wr_rst_busy (),
  170. .rd_rst_busy ()
  171. );
  172. endmodule

3.3 ov5640设计

ov5640_dri.v

  1. `timescale 1ns / 1ps
  2. //ov5640驱动顶层模块
  3. module ov5640_dri (
  4. input clk, //50m时钟
  5. input rst_n, //复位信号,低电平有效
  6. //摄像头接口
  7. input cam_pclk, //cmos 数据像素时钟
  8. input cam_vsync, //cmos 场同步信号
  9. input cam_href, //cmos 行同步信号
  10. input [7:0] cam_data, //cmos 数据
  11. output cam_rst_n, //cmos 复位信号,低电平有效
  12. output cam_pwdn, //cmos 电源休眠模式选择信号
  13. output cam_scl, //cmos SCCB_SCL线
  14. input cam_sda_i, //cmos SCCB_SDA输入
  15. output cam_sda_o, //cmos SCCB_SDA输出
  16. output cam_sda_t, //cmos SCCB_SDA使能
  17. //摄像头分辨率配置接口
  18. input [12:0] cmos_h_pixel, //水平方向分辨率
  19. input [12:0] cmos_v_pixel, //垂直方向分辨率
  20. input [12:0] total_h_pixel, //水平总像素大小
  21. input [12:0] total_v_pixel, //垂直总像素大小
  22. input capture_start, //图像采集开始信号
  23. output cam_init_done, //摄像头初始化完成
  24. //用户接口
  25. output cmos_frame_vsync, //帧有效信号
  26. output cmos_frame_href, //行有效信号
  27. output cmos_frame_valid, //数据有效使能信号
  28. output [15:0] cmos_frame_data //有效数据
  29. );
  30. //parameter define
  31. parameter SLAVE_ADDR = 7'h3c; //OV5640的器件地址7'h3c
  32. parameter BIT_CTRL = 1'b1; //OV5640的字节地址为16位 0:8位 1:16位
  33. parameter CLK_FREQ = 27'd50_000_000; //i2c_dri模块的驱动时钟频率
  34. parameter I2C_FREQ = 18'd250_000; //I2C的SCL时钟频率,不超过400KHz
  35. //wire difine
  36. wire i2c_exec; //I2C触发执行信号
  37. wire [23:0] i2c_data; //I2C要配置的地址与数据(高8位地址,低8位数据)
  38. wire i2c_done; //I2C寄存器配置完成信号
  39. wire i2c_dri_clk; //I2C操作时钟
  40. wire [ 7:0] i2c_data_r; //I2C读出的数据
  41. wire i2c_rh_wl; //I2C读写控制信号
  42. //*****************************************************
  43. //** main code
  44. //*****************************************************
  45. //电源休眠模式选择 0:正常模式 1:电源休眠模式
  46. assign cam_pwdn = 1'b0;
  47. assign cam_rst_n = 1'b1;
  48. //I2C配置模块
  49. i2c_ov5640_rgb565_cfg u_i2c_cfg (
  50. .clk (i2c_dri_clk),
  51. .rst_n(rst_n),
  52. .i2c_exec (i2c_exec),
  53. .i2c_data (i2c_data),
  54. .i2c_rh_wl (i2c_rh_wl), //I2C读写控制信号
  55. .i2c_done (i2c_done),
  56. .i2c_data_r(i2c_data_r),
  57. .cmos_h_pixel (cmos_h_pixel), //CMOS水平方向像素个数
  58. .cmos_v_pixel (cmos_v_pixel), //CMOS垂直方向像素个数
  59. .total_h_pixel(total_h_pixel), //水平总像素大小
  60. .total_v_pixel(total_v_pixel), //垂直总像素大小
  61. .init_done(cam_init_done)
  62. );
  63. //I2C驱动模块
  64. i2c_dri #(
  65. .SLAVE_ADDR(SLAVE_ADDR), //参数传递
  66. .CLK_FREQ (CLK_FREQ),
  67. .I2C_FREQ (I2C_FREQ)
  68. ) u_i2c_dr (
  69. .clk (clk),
  70. .rst_n(rst_n),
  71. .i2c_exec (i2c_exec),
  72. .bit_ctrl (BIT_CTRL),
  73. .i2c_rh_wl (i2c_rh_wl), //固定为0,只用到了IIC驱动的写操作
  74. .i2c_addr (i2c_data[23:8]),
  75. .i2c_data_w(i2c_data[7:0]),
  76. .i2c_data_r(i2c_data_r),
  77. .i2c_done (i2c_done),
  78. .scl (cam_scl),
  79. .sda_i (cam_sda_i),
  80. .sda_o (cam_sda_o),
  81. .sda_t (cam_sda_t),
  82. .dri_clk(i2c_dri_clk) //I2C操作时钟
  83. );
  84. //CMOS图像数据采集模块
  85. cmos_capture_data u_cmos_capture_data (
  86. //系统初始化完成之后再开始采集数据
  87. .rst_n(rst_n & capture_start),
  88. .cam_pclk (cam_pclk),
  89. .cam_vsync(cam_vsync),
  90. .cam_href (cam_href),
  91. .cam_data (cam_data),
  92. .cmos_frame_vsync(cmos_frame_vsync),
  93. .cmos_frame_href (cmos_frame_href),
  94. .cmos_frame_valid(cmos_frame_valid), //数据有效使能信号
  95. .cmos_frame_data (cmos_frame_data) //有效数据
  96. );
  97. endmodule

 i2c_ov5640_rgb565_cfg.

  1. `timescale 1ns / 1ps
  2. //ov5640通过IIC配置的寄存器
  3. module i2c_ov5640_rgb565_cfg (
  4. input clk, //时钟信号
  5. input rst_n, //复位信号,低电平有效
  6. input [7:0] i2c_data_r, //I2C读出的数据
  7. input i2c_done, //I2C寄存器配置完成信号
  8. input [12:0] cmos_h_pixel,
  9. input [12:0] cmos_v_pixel,
  10. input [12:0] total_h_pixel, //水平总像素大小
  11. input [12:0] total_v_pixel, //垂直总像素大小
  12. output reg i2c_exec, //I2C触发执行信号,上电等待20ms将信号拉高,表示开始配置寄存器,配置时也一直为高
  13. output reg [23:0] i2c_data, //I2C要配置的地址与数据(高16位地址,低8位数据)
  14. output reg i2c_rh_wl, //I2C读写控制信号
  15. output reg init_done //初始化完成信号,将所有寄存器配置完成后信号拉高
  16. );
  17. //parameter define
  18. localparam REG_NUM = 8'd250; //总共需要配置的寄存器个数
  19. //reg define
  20. reg [14:0] start_init_cnt; //等待延时计数器
  21. reg [ 7:0] init_reg_cnt; //寄存器配置个数计数器
  22. //*****************************************************
  23. //** main code
  24. //*****************************************************
  25. //clk时钟配置成1Mhz,周期为20000*1000ns = 20ms
  26. //OV5640上电到开始配置IIC至少等待20ms
  27. always @(posedge clk or negedge rst_n) begin
  28. if (!rst_n) start_init_cnt <= 15'b0;
  29. else if (start_init_cnt < 15'd20000) begin
  30. start_init_cnt <= start_init_cnt + 1'b1;
  31. end
  32. end
  33. //寄存器配置个数计数
  34. always @(posedge clk or negedge rst_n) begin
  35. if (!rst_n) init_reg_cnt <= 8'd0;
  36. else if (i2c_exec) init_reg_cnt <= init_reg_cnt + 8'b1;
  37. end
  38. //i2c触发执行信号
  39. always @(posedge clk or negedge rst_n) begin
  40. if (!rst_n) i2c_exec <= 1'b0;
  41. else if (start_init_cnt == 15'd19999) i2c_exec <= 1'b1;
  42. else if (i2c_done && (init_reg_cnt < REG_NUM)) i2c_exec <= 1'b1;
  43. else i2c_exec <= 1'b0;
  44. end
  45. //配置I2C读写控制信号
  46. always @(posedge clk or negedge rst_n) begin
  47. if (!rst_n) i2c_rh_wl <= 1'b1;
  48. else if (init_reg_cnt == 8'd2) i2c_rh_wl <= 1'b0;
  49. end
  50. //初始化完成信号
  51. always @(posedge clk or negedge rst_n) begin
  52. if (!rst_n) init_done <= 1'b0;
  53. else if ((init_reg_cnt == REG_NUM) && i2c_done) init_done <= 1'b1;
  54. end
  55. //配置寄存器地址与数据
  56. always @(posedge clk or negedge rst_n) begin
  57. if (!rst_n) i2c_data <= 24'b0;
  58. else begin
  59. case (init_reg_cnt)
  60. //先对寄存器进行软件复位,使寄存器恢复初始值
  61. //寄存器软件复位后,需要延时1ms才能配置其它寄存器
  62. 8'd0: i2c_data <= {16'h300a, 8'h0}; //
  63. 8'd1: i2c_data <= {16'h300b, 8'h0}; //
  64. 8'd2: i2c_data <= {16'h3008, 8'h82}; //Bit[7]:复位 Bit[6]:电源休眠
  65. 8'd3: i2c_data <= {16'h3008, 8'h02}; //正常工作模式
  66. 8'd4: i2c_data <= {16'h3103, 8'h02}; //Bit[1]:1 PLL Clock
  67. //引脚输入/输出控制 FREX/VSYNC/HREF/PCLK/D[9:6]
  68. 8'd5: i2c_data <= {8'h30, 8'h17, 8'hff};
  69. //引脚输入/输出控制 D[5:0]/GPIO1/GPIO0
  70. 8'd6: i2c_data <= {16'h3018, 8'hff};
  71. 8'd7: i2c_data <= {16'h3037, 8'h13}; //PLL分频控制
  72. 8'd8: i2c_data <= {16'h3108, 8'h01}; //系统根分频器
  73. 8'd9: i2c_data <= {16'h3630, 8'h36};
  74. 8'd10: i2c_data <= {16'h3631, 8'h0e};
  75. 8'd11: i2c_data <= {16'h3632, 8'he2};
  76. 8'd12: i2c_data <= {16'h3633, 8'h12};
  77. 8'd13: i2c_data <= {16'h3621, 8'he0};
  78. 8'd14: i2c_data <= {16'h3704, 8'ha0};
  79. 8'd15: i2c_data <= {16'h3703, 8'h5a};
  80. 8'd16: i2c_data <= {16'h3715, 8'h78};
  81. 8'd17: i2c_data <= {16'h3717, 8'h01};
  82. 8'd18: i2c_data <= {16'h370b, 8'h60};
  83. 8'd19: i2c_data <= {16'h3705, 8'h1a};
  84. 8'd20: i2c_data <= {16'h3905, 8'h02};
  85. 8'd21: i2c_data <= {16'h3906, 8'h10};
  86. 8'd22: i2c_data <= {16'h3901, 8'h0a};
  87. 8'd23: i2c_data <= {16'h3731, 8'h12};
  88. 8'd24: i2c_data <= {16'h3600, 8'h08}; //VCM控制,用于自动聚焦
  89. 8'd25: i2c_data <= {16'h3601, 8'h33}; //VCM控制,用于自动聚焦
  90. 8'd26: i2c_data <= {16'h302d, 8'h60}; //系统控制
  91. 8'd27: i2c_data <= {16'h3620, 8'h52};
  92. 8'd28: i2c_data <= {16'h371b, 8'h20};
  93. 8'd29: i2c_data <= {16'h471c, 8'h50};
  94. 8'd30: i2c_data <= {16'h3a13, 8'h43}; //AEC(自动曝光控制)
  95. 8'd31: i2c_data <= {16'h3a18, 8'h00}; //AEC 增益上限
  96. 8'd32: i2c_data <= {16'h3a19, 8'hf8}; //AEC 增益上限
  97. 8'd33: i2c_data <= {16'h3635, 8'h13};
  98. 8'd34: i2c_data <= {16'h3636, 8'h03};
  99. 8'd35: i2c_data <= {16'h3634, 8'h40};
  100. 8'd36: i2c_data <= {16'h3622, 8'h01};
  101. 8'd37: i2c_data <= {16'h3c01, 8'h34};
  102. 8'd38: i2c_data <= {16'h3c04, 8'h28};
  103. 8'd39: i2c_data <= {16'h3c05, 8'h98};
  104. 8'd40: i2c_data <= {16'h3c06, 8'h00}; //light meter 1 阈值[15:8]
  105. 8'd41: i2c_data <= {16'h3c07, 8'h08}; //light meter 1 阈值[7:0]
  106. 8'd42: i2c_data <= {16'h3c08, 8'h00}; //light meter 2 阈值[15:8]
  107. 8'd43: i2c_data <= {16'h3c09, 8'h1c}; //light meter 2 阈值[7:0]
  108. 8'd44: i2c_data <= {16'h3c0a, 8'h9c}; //sample number[15:8]
  109. 8'd45: i2c_data <= {16'h3c0b, 8'h40}; //sample number[7:0]
  110. 8'd46: i2c_data <= {16'h3810, 8'h00}; //Timing Hoffset[11:8]
  111. 8'd47: i2c_data <= {16'h3811, 8'h10}; //Timing Hoffset[7:0]
  112. 8'd48: i2c_data <= {16'h3812, 8'h00}; //Timing Voffset[10:8]
  113. 8'd49: i2c_data <= {16'h3708, 8'h64};
  114. 8'd50: i2c_data <= {16'h4001, 8'h02}; //BLC(黑电平校准)补偿起始行号
  115. 8'd51: i2c_data <= {16'h4005, 8'h1a}; //BLC(黑电平校准)补偿始终更新
  116. 8'd52: i2c_data <= {16'h3000, 8'h00}; //系统块复位控制
  117. 8'd53: i2c_data <= {16'h3004, 8'hff}; //时钟使能控制
  118. 8'd54: i2c_data <= {16'h4300, 8'h61}; //格式控制 RGB565
  119. 8'd55: i2c_data <= {16'h501f, 8'h01}; //ISP RGB
  120. 8'd56: i2c_data <= {16'h440e, 8'h00};
  121. 8'd57: i2c_data <= {16'h5000, 8'ha7}; //ISP控制
  122. 8'd58: i2c_data <= {16'h3a0f, 8'h30}; //AEC控制;stable range in high
  123. 8'd59: i2c_data <= {16'h3a10, 8'h28}; //AEC控制;stable range in low
  124. 8'd60: i2c_data <= {16'h3a1b, 8'h30}; //AEC控制;stable range out high
  125. 8'd61: i2c_data <= {16'h3a1e, 8'h26}; //AEC控制;stable range out low
  126. 8'd62: i2c_data <= {16'h3a11, 8'h60}; //AEC控制; fast zone high
  127. 8'd63: i2c_data <= {16'h3a1f, 8'h14}; //AEC控制; fast zone low
  128. //LENC(镜头校正)控制 16'h5800~16'h583d
  129. 8'd64: i2c_data <= {16'h5800, 8'h23};
  130. 8'd65: i2c_data <= {16'h5801, 8'h14};
  131. 8'd66: i2c_data <= {16'h5802, 8'h0f};
  132. 8'd67: i2c_data <= {16'h5803, 8'h0f};
  133. 8'd68: i2c_data <= {16'h5804, 8'h12};
  134. 8'd69: i2c_data <= {16'h5805, 8'h26};
  135. 8'd70: i2c_data <= {16'h5806, 8'h0c};
  136. 8'd71: i2c_data <= {16'h5807, 8'h08};
  137. 8'd72: i2c_data <= {16'h5808, 8'h05};
  138. 8'd73: i2c_data <= {16'h5809, 8'h05};
  139. 8'd74: i2c_data <= {16'h580a, 8'h08};
  140. 8'd75: i2c_data <= {16'h580b, 8'h0d};
  141. 8'd76: i2c_data <= {16'h580c, 8'h08};
  142. 8'd77: i2c_data <= {16'h580d, 8'h03};
  143. 8'd78: i2c_data <= {16'h580e, 8'h00};
  144. 8'd79: i2c_data <= {16'h580f, 8'h00};
  145. 8'd80: i2c_data <= {16'h5810, 8'h03};
  146. 8'd81: i2c_data <= {16'h5811, 8'h09};
  147. 8'd82: i2c_data <= {16'h5812, 8'h07};
  148. 8'd83: i2c_data <= {16'h5813, 8'h03};
  149. 8'd84: i2c_data <= {16'h5814, 8'h00};
  150. 8'd85: i2c_data <= {16'h5815, 8'h01};
  151. 8'd86: i2c_data <= {16'h5816, 8'h03};
  152. 8'd87: i2c_data <= {16'h5817, 8'h08};
  153. 8'd88: i2c_data <= {16'h5818, 8'h0d};
  154. 8'd89: i2c_data <= {16'h5819, 8'h08};
  155. 8'd90: i2c_data <= {16'h581a, 8'h05};
  156. 8'd91: i2c_data <= {16'h581b, 8'h06};
  157. 8'd92: i2c_data <= {16'h581c, 8'h08};
  158. 8'd93: i2c_data <= {16'h581d, 8'h0e};
  159. 8'd94: i2c_data <= {16'h581e, 8'h29};
  160. 8'd95: i2c_data <= {16'h581f, 8'h17};
  161. 8'd96: i2c_data <= {16'h5820, 8'h11};
  162. 8'd97: i2c_data <= {16'h5821, 8'h11};
  163. 8'd98: i2c_data <= {16'h5822, 8'h15};
  164. 8'd99: i2c_data <= {16'h5823, 8'h28};
  165. 8'd100: i2c_data <= {16'h5824, 8'h46};
  166. 8'd101: i2c_data <= {16'h5825, 8'h26};
  167. 8'd102: i2c_data <= {16'h5826, 8'h08};
  168. 8'd103: i2c_data <= {16'h5827, 8'h26};
  169. 8'd104: i2c_data <= {16'h5828, 8'h64};
  170. 8'd105: i2c_data <= {16'h5829, 8'h26};
  171. 8'd106: i2c_data <= {16'h582a, 8'h24};
  172. 8'd107: i2c_data <= {16'h582b, 8'h22};
  173. 8'd108: i2c_data <= {16'h582c, 8'h24};
  174. 8'd109: i2c_data <= {16'h582d, 8'h24};
  175. 8'd110: i2c_data <= {16'h582e, 8'h06};
  176. 8'd111: i2c_data <= {16'h582f, 8'h22};
  177. 8'd112: i2c_data <= {16'h5830, 8'h40};
  178. 8'd113: i2c_data <= {16'h5831, 8'h42};
  179. 8'd114: i2c_data <= {16'h5832, 8'h24};
  180. 8'd115: i2c_data <= {16'h5833, 8'h26};
  181. 8'd116: i2c_data <= {16'h5834, 8'h24};
  182. 8'd117: i2c_data <= {16'h5835, 8'h22};
  183. 8'd118: i2c_data <= {16'h5836, 8'h22};
  184. 8'd119: i2c_data <= {16'h5837, 8'h26};
  185. 8'd120: i2c_data <= {16'h5838, 8'h44};
  186. 8'd121: i2c_data <= {16'h5839, 8'h24};
  187. 8'd122: i2c_data <= {16'h583a, 8'h26};
  188. 8'd123: i2c_data <= {16'h583b, 8'h28};
  189. 8'd124: i2c_data <= {16'h583c, 8'h42};
  190. 8'd125: i2c_data <= {16'h583d, 8'hce};
  191. //AWB(自动白平衡控制) 16'h5180~16'h519e
  192. 8'd126: i2c_data <= {16'h5180, 8'hff};
  193. 8'd127: i2c_data <= {16'h5181, 8'hf2};
  194. 8'd128: i2c_data <= {16'h5182, 8'h00};
  195. 8'd129: i2c_data <= {16'h5183, 8'h14};
  196. 8'd130: i2c_data <= {16'h5184, 8'h25};
  197. 8'd131: i2c_data <= {16'h5185, 8'h24};
  198. 8'd132: i2c_data <= {16'h5186, 8'h09};
  199. 8'd133: i2c_data <= {16'h5187, 8'h09};
  200. 8'd134: i2c_data <= {16'h5188, 8'h09};
  201. 8'd135: i2c_data <= {16'h5189, 8'h75};
  202. 8'd136: i2c_data <= {16'h518a, 8'h54};
  203. 8'd137: i2c_data <= {16'h518b, 8'he0};
  204. 8'd138: i2c_data <= {16'h518c, 8'hb2};
  205. 8'd139: i2c_data <= {16'h518d, 8'h42};
  206. 8'd140: i2c_data <= {16'h518e, 8'h3d};
  207. 8'd141: i2c_data <= {16'h518f, 8'h56};
  208. 8'd142: i2c_data <= {16'h5190, 8'h46};
  209. 8'd143: i2c_data <= {16'h5191, 8'hf8};
  210. 8'd144: i2c_data <= {16'h5192, 8'h04};
  211. 8'd145: i2c_data <= {16'h5193, 8'h70};
  212. 8'd146: i2c_data <= {16'h5194, 8'hf0};
  213. 8'd147: i2c_data <= {16'h5195, 8'hf0};
  214. 8'd148: i2c_data <= {16'h5196, 8'h03};
  215. 8'd149: i2c_data <= {16'h5197, 8'h01};
  216. 8'd150: i2c_data <= {16'h5198, 8'h04};
  217. 8'd151: i2c_data <= {16'h5199, 8'h12};
  218. 8'd152: i2c_data <= {16'h519a, 8'h04};
  219. 8'd153: i2c_data <= {16'h519b, 8'h00};
  220. 8'd154: i2c_data <= {16'h519c, 8'h06};
  221. 8'd155: i2c_data <= {16'h519d, 8'h82};
  222. 8'd156: i2c_data <= {16'h519e, 8'h38};
  223. //Gamma(伽马)控制 16'h5480~16'h5490
  224. 8'd157: i2c_data <= {16'h5480, 8'h01};
  225. 8'd158: i2c_data <= {16'h5481, 8'h08};
  226. 8'd159: i2c_data <= {16'h5482, 8'h14};
  227. 8'd160: i2c_data <= {16'h5483, 8'h28};
  228. 8'd161: i2c_data <= {16'h5484, 8'h51};
  229. 8'd162: i2c_data <= {16'h5485, 8'h65};
  230. 8'd163: i2c_data <= {16'h5486, 8'h71};
  231. 8'd164: i2c_data <= {16'h5487, 8'h7d};
  232. 8'd165: i2c_data <= {16'h5488, 8'h87};
  233. 8'd166: i2c_data <= {16'h5489, 8'h91};
  234. 8'd167: i2c_data <= {16'h548a, 8'h9a};
  235. 8'd168: i2c_data <= {16'h548b, 8'haa};
  236. 8'd169: i2c_data <= {16'h548c, 8'hb8};
  237. 8'd170: i2c_data <= {16'h548d, 8'hcd};
  238. 8'd171: i2c_data <= {16'h548e, 8'hdd};
  239. 8'd172: i2c_data <= {16'h548f, 8'hea};
  240. 8'd173: i2c_data <= {16'h5490, 8'h1d};
  241. //CMX(彩色矩阵控制) 16'h5381~16'h538b
  242. 8'd174: i2c_data <= {16'h5381, 8'h1e};
  243. 8'd175: i2c_data <= {16'h5382, 8'h5b};
  244. 8'd176: i2c_data <= {16'h5383, 8'h08};
  245. 8'd177: i2c_data <= {16'h5384, 8'h0a};
  246. 8'd178: i2c_data <= {16'h5385, 8'h7e};
  247. 8'd179: i2c_data <= {16'h5386, 8'h88};
  248. 8'd180: i2c_data <= {16'h5387, 8'h7c};
  249. 8'd181: i2c_data <= {16'h5388, 8'h6c};
  250. 8'd182: i2c_data <= {16'h5389, 8'h10};
  251. 8'd183: i2c_data <= {16'h538a, 8'h01};
  252. 8'd184: i2c_data <= {16'h538b, 8'h98};
  253. //SDE(特殊数码效果)控制 16'h5580~16'h558b
  254. 8'd185: i2c_data <= {16'h5580, 8'h06};
  255. 8'd186: i2c_data <= {16'h5583, 8'h40};
  256. 8'd187: i2c_data <= {16'h5584, 8'h10};
  257. 8'd188: i2c_data <= {16'h5589, 8'h10};
  258. 8'd189: i2c_data <= {16'h558a, 8'h00};
  259. 8'd190: i2c_data <= {16'h558b, 8'hf8};
  260. 8'd191: i2c_data <= {16'h501d, 8'h40}; //ISP MISC
  261. //CIP(颜色插值)控制 (16'h5300~16'h530c)
  262. 8'd192: i2c_data <= {16'h5300, 8'h08};
  263. 8'd193: i2c_data <= {16'h5301, 8'h30};
  264. 8'd194: i2c_data <= {16'h5302, 8'h10};
  265. 8'd195: i2c_data <= {16'h5303, 8'h00};
  266. 8'd196: i2c_data <= {16'h5304, 8'h08};
  267. 8'd197: i2c_data <= {16'h5305, 8'h30};
  268. 8'd198: i2c_data <= {16'h5306, 8'h08};
  269. 8'd199: i2c_data <= {16'h5307, 8'h16};
  270. 8'd200: i2c_data <= {16'h5309, 8'h08};
  271. 8'd201: i2c_data <= {16'h530a, 8'h30};
  272. 8'd202: i2c_data <= {16'h530b, 8'h04};
  273. 8'd203: i2c_data <= {16'h530c, 8'h06};
  274. 8'd204: i2c_data <= {16'h5025, 8'h00};
  275. //系统时钟分频 Bit[7:4]:系统时钟分频 input clock =24Mhz, PCLK = 48Mhz
  276. 8'd205: i2c_data <= {16'h3035, 8'h11};
  277. 8'd206: i2c_data <= {16'h3036, 8'h3c}; //PLL倍频
  278. 8'd207: i2c_data <= {16'h3c07, 8'h08};
  279. //时序控制 16'h3800~16'h3821
  280. 8'd208: i2c_data <= {16'h3820, 8'h46};
  281. 8'd209: i2c_data <= {16'h3821, 8'h01};
  282. 8'd210: i2c_data <= {16'h3814, 8'h31};
  283. 8'd211: i2c_data <= {16'h3815, 8'h31};
  284. 8'd212: i2c_data <= {16'h3800, 8'h00};
  285. 8'd213: i2c_data <= {16'h3801, 8'h00};
  286. 8'd214: i2c_data <= {16'h3802, 8'h00};
  287. 8'd215: i2c_data <= {16'h3803, 8'h04};
  288. 8'd216: i2c_data <= {16'h3804, 8'h0a};
  289. 8'd217: i2c_data <= {16'h3805, 8'h3f};
  290. 8'd218: i2c_data <= {16'h3806, 8'h07};
  291. 8'd219: i2c_data <= {16'h3807, 8'h9b};
  292. //设置输出像素个数
  293. //DVP 输出水平像素点数高4
  294. 8'd220: i2c_data <= {16'h3808, {4'd0, cmos_h_pixel[11:8]}};
  295. //DVP 输出水平像素点数低8位
  296. 8'd221: i2c_data <= {16'h3809, cmos_h_pixel[7:0]};
  297. //DVP 输出垂直像素点数高3位
  298. 8'd222: i2c_data <= {16'h380a, {5'd0, cmos_v_pixel[10:8]}};
  299. //DVP 输出垂直像素点数低8
  300. 8'd223: i2c_data <= {16'h380b, cmos_v_pixel[7:0]};
  301. //水平总像素大小高5
  302. 8'd224: i2c_data <= {16'h380c, {3'd0, total_h_pixel[12:8]}};
  303. //水平总像素大小低8位
  304. 8'd225: i2c_data <= {16'h380d, total_h_pixel[7:0]};
  305. //垂直总像素大小高5位
  306. 8'd226: i2c_data <= {16'h380e, {3'd0, total_v_pixel[12:8]}};
  307. //垂直总像素大小低8
  308. 8'd227: i2c_data <= {16'h380f, total_v_pixel[7:0]};
  309. 8'd228: i2c_data <= {16'h3813, 8'h06};
  310. 8'd229: i2c_data <= {16'h3618, 8'h00};
  311. 8'd230: i2c_data <= {16'h3612, 8'h29};
  312. 8'd231: i2c_data <= {16'h3709, 8'h52};
  313. 8'd232: i2c_data <= {16'h370c, 8'h03};
  314. 8'd233: i2c_data <= {16'h3a02, 8'h17}; //60Hz max exposure
  315. 8'd234: i2c_data <= {16'h3a03, 8'h10}; //60Hz max exposure
  316. 8'd235: i2c_data <= {16'h3a14, 8'h17}; //50Hz max exposure
  317. 8'd236: i2c_data <= {16'h3a15, 8'h10}; //50Hz max exposure
  318. 8'd237: i2c_data <= {16'h4004, 8'h02}; //BLC(背光) 2 lines
  319. 8'd238: i2c_data <= {16'h4713, 8'h03}; //JPEG mode 3
  320. 8'd239: i2c_data <= {16'h4407, 8'h04}; //量化标度
  321. 8'd240: i2c_data <= {16'h460c, 8'h22};
  322. 8'd241: i2c_data <= {16'h4837, 8'h22}; //DVP CLK divider
  323. 8'd242: i2c_data <= {16'h3824, 8'h02}; //DVP CLK divider
  324. 8'd243: i2c_data <= {16'h5001, 8'ha3}; //ISP 控制
  325. 8'd244: i2c_data <= {16'h3b07, 8'h0a}; //帧曝光模式
  326. //彩条测试使能
  327. 8'd245: i2c_data <= {16'h503d, 8'h00}; //8'h00:正常模式 8'h80:彩条显示
  328. //测试闪光灯功能
  329. 8'd246: i2c_data <= {16'h3016, 8'h02};
  330. 8'd247: i2c_data <= {16'h301c, 8'h02};
  331. 8'd248: i2c_data <= {16'h3019, 8'h02}; //打开闪光灯
  332. 8'd249: i2c_data <= {16'h3019, 8'h00}; //关闭闪光灯
  333. //只读存储器,防止在case中没有列举的情况,之前的寄存器被重复改写
  334. default: i2c_data <= {16'h300a, 8'h00}; //器件ID高8
  335. endcase
  336. end
  337. end
  338. endmodule

 i2c_dri.v

  1. `timescale 1ns / 1ps
  2. //IIC驱动
  3. module i2c_dri #(
  4. parameter SLAVE_ADDR = 7'h3c, //器件地址
  5. parameter CLK_FREQ = 26'd50_000_000, //模块输入的时钟频率
  6. parameter I2C_FREQ = 18'd250_000 //IIC_SCL的时钟频率
  7. ) (
  8. input clk, //50m时钟
  9. input rst_n,
  10. //i2c interface
  11. input i2c_exec, //I2C触发执行信号
  12. input bit_ctrl, //字地址位控制(16b/8b),在此处固定为16位,一直为1
  13. input i2c_rh_wl, //I2C读写控制信号
  14. input [15:0] i2c_addr, //I2C器件内地址
  15. input [7:0] i2c_data_w, //I2C要写的数据
  16. output reg [7:0] i2c_data_r, //I2C读出的数据
  17. output reg i2c_done, //I2C一次操作完成
  18. output reg i2c_ack, //I2C应答标志 0:应答 1:未应答
  19. output reg scl, //I2C的SCL时钟信号
  20. input sda_i, //SDA输入
  21. output sda_o, //SDA输出
  22. output sda_t, //SDA使能
  23. //user interface
  24. output reg dri_clk //驱动I2C操作的驱动时钟
  25. );
  26. //localparam define
  27. localparam st_idle = 8'b0000_0001; //空闲状态
  28. localparam st_sladdr = 8'b0000_0010; //发送器件地址(slave address)
  29. localparam st_addr16 = 8'b0000_0100; //发送16位字地址
  30. localparam st_addr8 = 8'b0000_1000; //发送8位字地址
  31. localparam st_data_wr = 8'b0001_0000; //写数据(8 bit)
  32. localparam st_addr_rd = 8'b0010_0000; //发送器件地址读
  33. localparam st_data_rd = 8'b0100_0000; //读数据(8 bit)
  34. localparam st_stop = 8'b1000_0000; //结束I2C操作
  35. //reg define
  36. reg sda_dir; //I2C数据(SDA)方向控制
  37. reg sda_out; //SDA输出信号
  38. reg st_done; //状态结束
  39. reg wr_flag; //写标志
  40. reg [ 6:0] cnt; //计数
  41. reg [ 7:0] cur_state; //状态机当前状态
  42. reg [ 7:0] next_state; //状态机下一状态
  43. reg [15:0] addr_t; //地址
  44. reg [ 7:0] data_r; //读取的数据
  45. reg [ 7:0] data_wr_t; //I2C需写的数据的临时寄存
  46. reg [ 9:0] clk_cnt; //分频时钟计数
  47. //wire define
  48. wire sda_in; //SDA输入信号
  49. wire [ 8:0] clk_divide; //模块驱动时钟的分频系数
  50. //*****************************************************
  51. //** main code
  52. //*****************************************************
  53. //SDA控制
  54. assign sda_o = sda_out;
  55. assign sda_in = sda_i;
  56. assign sda_t = sda_dir;
  57. assign clk_divide = (CLK_FREQ / I2C_FREQ) >> 2'd2; //模块驱动时钟的分频系数
  58. //生成I2C的SCL的四倍频率的驱动时钟用于驱动i2c的操作
  59. always @(posedge clk or negedge rst_n) begin
  60. if (!rst_n) begin
  61. dri_clk <= 1'b0;
  62. clk_cnt <= 10'd0;
  63. end else if (clk_cnt == clk_divide[8:1] - 1'd1) begin
  64. clk_cnt <= 10'd0;
  65. dri_clk <= ~dri_clk;
  66. end else clk_cnt <= clk_cnt + 1'b1;
  67. end
  68. //(三段式状态机)同步时序描述状态转移
  69. always @(posedge dri_clk or negedge rst_n) begin
  70. if (!rst_n) cur_state <= st_idle;
  71. else cur_state <= next_state;
  72. end
  73. //组合逻辑判断状态转移条件
  74. always @(*) begin
  75. next_state = st_idle;
  76. case (cur_state)
  77. st_idle: begin //空闲状态
  78. if (i2c_exec) begin
  79. next_state = st_sladdr;
  80. end else next_state = st_idle;
  81. end
  82. st_sladdr: begin
  83. if (st_done) begin
  84. if (bit_ctrl) //判断是16位还是8位字地址
  85. next_state = st_addr16;
  86. else next_state = st_addr8;
  87. end else next_state = st_sladdr;
  88. end
  89. st_addr16: begin //写16位字地址
  90. if (st_done) begin
  91. next_state = st_addr8;
  92. end else begin
  93. next_state = st_addr16;
  94. end
  95. end
  96. st_addr8: begin //8位字地址
  97. if (st_done) begin
  98. if (wr_flag == 1'b0) //读写判断
  99. next_state = st_data_wr;
  100. else next_state = st_addr_rd;
  101. end else begin
  102. next_state = st_addr8;
  103. end
  104. end
  105. st_data_wr: begin //写数据(8 bit)
  106. if (st_done) next_state = st_stop;
  107. else next_state = st_data_wr;
  108. end
  109. st_addr_rd: begin //写地址以进行读数据
  110. if (st_done) begin
  111. next_state = st_data_rd;
  112. end else begin
  113. next_state = st_addr_rd;
  114. end
  115. end
  116. st_data_rd: begin //读取数据(8 bit)
  117. if (st_done) next_state = st_stop;
  118. else next_state = st_data_rd;
  119. end
  120. st_stop: begin //结束I2C操作
  121. if (st_done) next_state = st_idle;
  122. else next_state = st_stop;
  123. end
  124. default: next_state = st_idle;
  125. endcase
  126. end
  127. //时序电路描述状态输出
  128. always @(posedge dri_clk or negedge rst_n) begin
  129. //复位初始化
  130. if (!rst_n) begin
  131. scl <= 1'b1;
  132. sda_out <= 1'b1;
  133. sda_dir <= 1'b1;
  134. i2c_done <= 1'b0;
  135. i2c_ack <= 1'b0;
  136. cnt <= 1'b0;
  137. st_done <= 1'b0;
  138. data_r <= 1'b0;
  139. i2c_data_r <= 1'b0;
  140. wr_flag <= 1'b0;
  141. addr_t <= 1'b0;
  142. data_wr_t <= 1'b0;
  143. end else begin
  144. st_done <= 1'b0;
  145. cnt <= cnt + 1'b1;
  146. case (cur_state)
  147. st_idle: begin //空闲状态
  148. scl <= 1'b1;
  149. sda_out <= 1'b1;
  150. sda_dir <= 1'b1;
  151. i2c_done <= 1'b0;
  152. cnt <= 7'b0;
  153. if (i2c_exec) begin
  154. wr_flag <= i2c_rh_wl ;
  155. addr_t <= i2c_addr ;
  156. data_wr_t <= i2c_data_w;
  157. i2c_ack <= 1'b0;
  158. end
  159. end
  160. st_sladdr: begin //写地址(器件地址和字地址)
  161. case (cnt)
  162. 7'd1: sda_out <= 1'b0; //开始I2C
  163. 7'd3: scl <= 1'b0;
  164. 7'd4: sda_out <= SLAVE_ADDR[6]; //传送器件地址
  165. 7'd5: scl <= 1'b1;
  166. 7'd7: scl <= 1'b0;
  167. 7'd8: sda_out <= SLAVE_ADDR[5];
  168. 7'd9: scl <= 1'b1;
  169. 7'd11: scl <= 1'b0;
  170. 7'd12: sda_out <= SLAVE_ADDR[4];
  171. 7'd13: scl <= 1'b1;
  172. 7'd15: scl <= 1'b0;
  173. 7'd16: sda_out <= SLAVE_ADDR[3];
  174. 7'd17: scl <= 1'b1;
  175. 7'd19: scl <= 1'b0;
  176. 7'd20: sda_out <= SLAVE_ADDR[2];
  177. 7'd21: scl <= 1'b1;
  178. 7'd23: scl <= 1'b0;
  179. 7'd24: sda_out <= SLAVE_ADDR[1];
  180. 7'd25: scl <= 1'b1;
  181. 7'd27: scl <= 1'b0;
  182. 7'd28: sda_out <= SLAVE_ADDR[0];
  183. 7'd29: scl <= 1'b1;
  184. 7'd31: scl <= 1'b0;
  185. 7'd32: sda_out <= 1'b0; //0:写
  186. 7'd33: scl <= 1'b1;
  187. 7'd35: scl <= 1'b0;
  188. 7'd36: begin
  189. sda_dir <= 1'b0;
  190. sda_out <= 1'b1;
  191. end
  192. 7'd37: scl <= 1'b1;
  193. 7'd38: begin //从机应答
  194. st_done <= 1'b1;
  195. if (sda_in == 1'b1) //高电平表示未应答
  196. i2c_ack <= 1'b1; //拉高应答标志位
  197. end
  198. 7'd39: begin
  199. scl <= 1'b0;
  200. cnt <= 1'b0;
  201. end
  202. default: ;
  203. endcase
  204. end
  205. st_addr16: begin
  206. case (cnt)
  207. 7'd0: begin
  208. sda_dir <= 1'b1;
  209. sda_out <= addr_t[15]; //传送字地址
  210. end
  211. 7'd1: scl <= 1'b1;
  212. 7'd3: scl <= 1'b0;
  213. 7'd4: sda_out <= addr_t[14];
  214. 7'd5: scl <= 1'b1;
  215. 7'd7: scl <= 1'b0;
  216. 7'd8: sda_out <= addr_t[13];
  217. 7'd9: scl <= 1'b1;
  218. 7'd11: scl <= 1'b0;
  219. 7'd12: sda_out <= addr_t[12];
  220. 7'd13: scl <= 1'b1;
  221. 7'd15: scl <= 1'b0;
  222. 7'd16: sda_out <= addr_t[11];
  223. 7'd17: scl <= 1'b1;
  224. 7'd19: scl <= 1'b0;
  225. 7'd20: sda_out <= addr_t[10];
  226. 7'd21: scl <= 1'b1;
  227. 7'd23: scl <= 1'b0;
  228. 7'd24: sda_out <= addr_t[9];
  229. 7'd25: scl <= 1'b1;
  230. 7'd27: scl <= 1'b0;
  231. 7'd28: sda_out <= addr_t[8];
  232. 7'd29: scl <= 1'b1;
  233. 7'd31: scl <= 1'b0;
  234. 7'd32: begin
  235. sda_dir <= 1'b0;
  236. sda_out <= 1'b1;
  237. end
  238. 7'd33: scl <= 1'b1;
  239. 7'd34: begin //从机应答
  240. st_done <= 1'b1;
  241. if (sda_in == 1'b1) //高电平表示未应答
  242. i2c_ack <= 1'b1; //拉高应答标志位
  243. end
  244. 7'd35: begin
  245. scl <= 1'b0;
  246. cnt <= 1'b0;
  247. end
  248. default: ;
  249. endcase
  250. end
  251. st_addr8: begin
  252. case (cnt)
  253. 7'd0: begin
  254. sda_dir <= 1'b1;
  255. sda_out <= addr_t[7]; //字地址
  256. end
  257. 7'd1: scl <= 1'b1;
  258. 7'd3: scl <= 1'b0;
  259. 7'd4: sda_out <= addr_t[6];
  260. 7'd5: scl <= 1'b1;
  261. 7'd7: scl <= 1'b0;
  262. 7'd8: sda_out <= addr_t[5];
  263. 7'd9: scl <= 1'b1;
  264. 7'd11: scl <= 1'b0;
  265. 7'd12: sda_out <= addr_t[4];
  266. 7'd13: scl <= 1'b1;
  267. 7'd15: scl <= 1'b0;
  268. 7'd16: sda_out <= addr_t[3];
  269. 7'd17: scl <= 1'b1;
  270. 7'd19: scl <= 1'b0;
  271. 7'd20: sda_out <= addr_t[2];
  272. 7'd21: scl <= 1'b1;
  273. 7'd23: scl <= 1'b0;
  274. 7'd24: sda_out <= addr_t[1];
  275. 7'd25: scl <= 1'b1;
  276. 7'd27: scl <= 1'b0;
  277. 7'd28: sda_out <= addr_t[0];
  278. 7'd29: scl <= 1'b1;
  279. 7'd31: scl <= 1'b0;
  280. 7'd32: begin
  281. sda_dir <= 1'b0;
  282. sda_out <= 1'b1;
  283. end
  284. 7'd33: scl <= 1'b1;
  285. 7'd34: begin //从机应答
  286. st_done <= 1'b1;
  287. if (sda_in == 1'b1) //高电平表示未应答
  288. i2c_ack <= 1'b1; //拉高应答标志位
  289. end
  290. 7'd35: begin
  291. scl <= 1'b0;
  292. cnt <= 1'b0;
  293. end
  294. default: ;
  295. endcase
  296. end
  297. st_data_wr: begin //写数据(8 bit)
  298. case (cnt)
  299. 7'd0: begin
  300. sda_out <= data_wr_t[7]; //I2C写8位数据
  301. sda_dir <= 1'b1;
  302. end
  303. 7'd1: scl <= 1'b1;
  304. 7'd3: scl <= 1'b0;
  305. 7'd4: sda_out <= data_wr_t[6];
  306. 7'd5: scl <= 1'b1;
  307. 7'd7: scl <= 1'b0;
  308. 7'd8: sda_out <= data_wr_t[5];
  309. 7'd9: scl <= 1'b1;
  310. 7'd11: scl <= 1'b0;
  311. 7'd12: sda_out <= data_wr_t[4];
  312. 7'd13: scl <= 1'b1;
  313. 7'd15: scl <= 1'b0;
  314. 7'd16: sda_out <= data_wr_t[3];
  315. 7'd17: scl <= 1'b1;
  316. 7'd19: scl <= 1'b0;
  317. 7'd20: sda_out <= data_wr_t[2];
  318. 7'd21: scl <= 1'b1;
  319. 7'd23: scl <= 1'b0;
  320. 7'd24: sda_out <= data_wr_t[1];
  321. 7'd25: scl <= 1'b1;
  322. 7'd27: scl <= 1'b0;
  323. 7'd28: sda_out <= data_wr_t[0];
  324. 7'd29: scl <= 1'b1;
  325. 7'd31: scl <= 1'b0;
  326. 7'd32: begin
  327. sda_dir <= 1'b0;
  328. sda_out <= 1'b1;
  329. end
  330. 7'd33: scl <= 1'b1;
  331. 7'd34: begin //从机应答
  332. st_done <= 1'b1;
  333. if (sda_in == 1'b1) //高电平表示未应答
  334. i2c_ack <= 1'b1; //拉高应答标志位
  335. end
  336. 7'd35: begin
  337. scl <= 1'b0;
  338. cnt <= 1'b0;
  339. end
  340. default: ;
  341. endcase
  342. end
  343. st_addr_rd: begin //写地址以进行读数据
  344. case (cnt)
  345. 7'd0: begin
  346. sda_dir <= 1'b1;
  347. sda_out <= 1'b1;
  348. end
  349. 7'd1: scl <= 1'b1;
  350. 7'd2: sda_out <= 1'b0; //重新开始
  351. 7'd3: scl <= 1'b0;
  352. 7'd4: sda_out <= SLAVE_ADDR[6]; //传送器件地址
  353. 7'd5: scl <= 1'b1;
  354. 7'd7: scl <= 1'b0;
  355. 7'd8: sda_out <= SLAVE_ADDR[5];
  356. 7'd9: scl <= 1'b1;
  357. 7'd11: scl <= 1'b0;
  358. 7'd12: sda_out <= SLAVE_ADDR[4];
  359. 7'd13: scl <= 1'b1;
  360. 7'd15: scl <= 1'b0;
  361. 7'd16: sda_out <= SLAVE_ADDR[3];
  362. 7'd17: scl <= 1'b1;
  363. 7'd19: scl <= 1'b0;
  364. 7'd20: sda_out <= SLAVE_ADDR[2];
  365. 7'd21: scl <= 1'b1;
  366. 7'd23: scl <= 1'b0;
  367. 7'd24: sda_out <= SLAVE_ADDR[1];
  368. 7'd25: scl <= 1'b1;
  369. 7'd27: scl <= 1'b0;
  370. 7'd28: sda_out <= SLAVE_ADDR[0];
  371. 7'd29: scl <= 1'b1;
  372. 7'd31: scl <= 1'b0;
  373. 7'd32: sda_out <= 1'b1; //1:读
  374. 7'd33: scl <= 1'b1;
  375. 7'd35: scl <= 1'b0;
  376. 7'd36: begin
  377. sda_dir <= 1'b0;
  378. sda_out <= 1'b1;
  379. end
  380. 7'd37: scl <= 1'b1;
  381. 7'd38: begin //从机应答
  382. st_done <= 1'b1;
  383. if (sda_in == 1'b1) //高电平表示未应答
  384. i2c_ack <= 1'b1; //拉高应答标志位
  385. end
  386. 7'd39: begin
  387. scl <= 1'b0;
  388. cnt <= 1'b0;
  389. end
  390. default: ;
  391. endcase
  392. end
  393. st_data_rd: begin //读取数据(8 bit)
  394. case (cnt)
  395. 7'd0: sda_dir <= 1'b0;
  396. 7'd1: begin
  397. data_r[7] <= sda_in;
  398. scl <= 1'b1;
  399. end
  400. 7'd3: scl <= 1'b0;
  401. 7'd5: begin
  402. data_r[6] <= sda_in;
  403. scl <= 1'b1;
  404. end
  405. 7'd7: scl <= 1'b0;
  406. 7'd9: begin
  407. data_r[5] <= sda_in;
  408. scl <= 1'b1;
  409. end
  410. 7'd11: scl <= 1'b0;
  411. 7'd13: begin
  412. data_r[4] <= sda_in;
  413. scl <= 1'b1;
  414. end
  415. 7'd15: scl <= 1'b0;
  416. 7'd17: begin
  417. data_r[3] <= sda_in;
  418. scl <= 1'b1;
  419. end
  420. 7'd19: scl <= 1'b0;
  421. 7'd21: begin
  422. data_r[2] <= sda_in;
  423. scl <= 1'b1;
  424. end
  425. 7'd23: scl <= 1'b0;
  426. 7'd25: begin
  427. data_r[1] <= sda_in;
  428. scl <= 1'b1;
  429. end
  430. 7'd27: scl <= 1'b0;
  431. 7'd29: begin
  432. data_r[0] <= sda_in;
  433. scl <= 1'b1;
  434. end
  435. 7'd31: scl <= 1'b0;
  436. 7'd32: begin
  437. sda_dir <= 1'b1;
  438. sda_out <= 1'b1;
  439. end
  440. 7'd33: scl <= 1'b1;
  441. 7'd34: st_done <= 1'b1; //非应答
  442. 7'd35: begin
  443. scl <= 1'b0;
  444. cnt <= 1'b0;
  445. i2c_data_r <= data_r;
  446. end
  447. default: ;
  448. endcase
  449. end
  450. st_stop: begin //结束I2C操作
  451. case (cnt)
  452. 7'd0: begin
  453. sda_dir <= 1'b1; //结束I2C
  454. sda_out <= 1'b0;
  455. end
  456. 7'd1: scl <= 1'b1;
  457. 7'd3: sda_out <= 1'b1;
  458. 7'd15: st_done <= 1'b1;
  459. 7'd16: begin
  460. cnt <= 1'b0;
  461. i2c_done <= 1'b1; //向上层模块传递I2C结束信号
  462. end
  463. default: ;
  464. endcase
  465. end
  466. endcase
  467. end
  468. end
  469. endmodule

 cmos_capture_data.v

  1. `timescale 1ns / 1ps
  2. //摄像头采集模块
  3. module cmos_capture_data (
  4. input rst_n, //复位信号
  5. //摄像头接口
  6. input cam_pclk, //cmos 数据像素时钟
  7. input cam_vsync, //cmos 场同步信号
  8. input cam_href, //cmos 行同步信号
  9. input [ 7:0] cam_data,
  10. //用户接口
  11. output cmos_frame_vsync, //帧有效信号
  12. output cmos_frame_href, //行有效信号
  13. output cmos_frame_valid, //数据有效使能信号
  14. output [15:0] cmos_frame_data //有效数据
  15. );
  16. //寄存器全部配置完成后,先等待10帧数据
  17. //待寄存器配置生效后再开始采集图像
  18. parameter WAIT_FRAME = 4'd10; //寄存器数据稳定等待的帧个数
  19. //reg define
  20. reg cam_vsync_d0;
  21. reg cam_vsync_d1;
  22. reg cam_href_d0;
  23. reg cam_href_d1;
  24. reg [ 3:0] cmos_ps_cnt; //等待帧数稳定计数器
  25. reg [ 7:0] cam_data_d0;
  26. reg [15:0] cmos_data_t; //用于8位转16位的临时寄存器
  27. reg byte_flag; //16位RGB数据转换完成的标志信号
  28. reg byte_flag_d0;
  29. reg frame_val_flag; //帧有效的标志
  30. wire pos_vsync; //采输入场同步信号的上升沿
  31. //*****************************************************
  32. //** main code
  33. //*****************************************************
  34. //采输入场同步信号的上升沿
  35. assign pos_vsync = (~cam_vsync_d1) & cam_vsync_d0;
  36. //输出帧有效信号
  37. assign cmos_frame_vsync = frame_val_flag ? cam_vsync_d1 : 1'b0;
  38. //输出行有效信号
  39. assign cmos_frame_href = frame_val_flag ? cam_href_d1 : 1'b0;
  40. //输出数据使能有效信号
  41. assign cmos_frame_valid = frame_val_flag ? byte_flag_d0 : 1'b0;
  42. //输出数据
  43. assign cmos_frame_data = frame_val_flag ? cmos_data_t : 1'b0;
  44. always @(posedge cam_pclk or negedge rst_n) begin
  45. if (!rst_n) begin
  46. cam_vsync_d0 <= 1'b0;
  47. cam_vsync_d1 <= 1'b0;
  48. cam_href_d0 <= 1'b0;
  49. cam_href_d1 <= 1'b0;
  50. end else begin
  51. cam_vsync_d0 <= cam_vsync;
  52. cam_vsync_d1 <= cam_vsync_d0;
  53. cam_href_d0 <= cam_href;
  54. cam_href_d1 <= cam_href_d0;
  55. end
  56. end
  57. //对帧数进行计数
  58. always @(posedge cam_pclk or negedge rst_n) begin
  59. if (!rst_n) cmos_ps_cnt <= 4'd0;
  60. else if (pos_vsync && (cmos_ps_cnt < WAIT_FRAME)) cmos_ps_cnt <= cmos_ps_cnt + 4'd1;
  61. end
  62. //帧有效标志
  63. always @(posedge cam_pclk or negedge rst_n) begin
  64. if (!rst_n) frame_val_flag <= 1'b0;
  65. else if ((cmos_ps_cnt == WAIT_FRAME) && pos_vsync) frame_val_flag <= 1'b1;
  66. else;
  67. end
  68. //8位数据转16位RGB565数据
  69. always @(posedge cam_pclk or negedge rst_n) begin
  70. if (!rst_n) begin
  71. cmos_data_t <= 16'd0;
  72. cam_data_d0 <= 8'd0;
  73. byte_flag <= 1'b0;
  74. end else if (cam_href) begin
  75. byte_flag <= ~byte_flag;
  76. cam_data_d0 <= cam_data;
  77. if (byte_flag) cmos_data_t <= {cam_data_d0, cam_data};
  78. else;
  79. end else begin
  80. byte_flag <= 1'b0;
  81. cam_data_d0 <= 8'b0;
  82. cmos_data_t <= 16'd0;
  83. end
  84. end
  85. //产生输出数据有效信号(cmos_frame_valid)
  86. always @(posedge cam_pclk or negedge rst_n) begin
  87. if (!rst_n) byte_flag_d0 <= 1'b0;
  88. else byte_flag_d0 <= byte_flag;
  89. end
  90. endmodule

3.4 lcd屏幕设计

lcd_rgb_top.v

  1. `timescale 1ns / 1ps
  2. //LCD顶层模块
  3. module lcd_rgb_top (
  4. input sys_clk, //系统时钟
  5. input sys_rst_n, //复位信号
  6. input sys_init_done,
  7. //lcd接口
  8. output lcd_clk, //LCD驱动时钟
  9. output lcd_hs, //LCD 行同步信号
  10. output lcd_vs, //LCD 场同步信号
  11. output lcd_de, //LCD 数据输入使能
  12. output [23:0] lcd_rgb, //LCD RGB颜色数据
  13. output lcd_bl, //LCD 背光控制信号
  14. output lcd_rst, //LCD 复位信号
  15. output lcd_pclk, //LCD 采样时钟
  16. output out_vsync, //lcd场信号
  17. output [10:0] pixel_xpos, //像素点横坐标
  18. output [10:0] pixel_ypos, //像素点纵坐标
  19. output [10:0] h_disp, //LCD屏水平分辨率
  20. output [10:0] v_disp, //LCD屏垂直分辨率
  21. input [15:0] data_in, //数据输入
  22. output data_req //请求数据输入
  23. );
  24. //wire define
  25. wire [15:0] lcd_rgb_565; //输出的16位lcd数据
  26. //*****************************************************
  27. //** main code
  28. //*****************************************************
  29. //将摄像头16bit数据转换为24bit的lcd数据
  30. assign lcd_rgb = {lcd_rgb_565[15:11], 3'b000, lcd_rgb_565[10:5], 2'b00, lcd_rgb_565[4:0], 3'b000};
  31. //时钟分频模块
  32. clk_div u_clk_div (
  33. .clk (sys_clk),
  34. .rst_n(sys_rst_n),
  35. .lcd_pclk(lcd_clk)
  36. );
  37. //lcd驱动模块
  38. lcd_driver u_lcd_driver (
  39. .lcd_clk (lcd_clk),
  40. .sys_rst_n(sys_rst_n & sys_init_done),
  41. .lcd_hs (lcd_hs),
  42. .lcd_vs (lcd_vs),
  43. .lcd_de (lcd_de),
  44. .lcd_rgb (lcd_rgb_565),
  45. .lcd_bl (lcd_bl),
  46. .lcd_rst (lcd_rst),
  47. .lcd_pclk(lcd_pclk),
  48. .pixel_data(data_in),
  49. .data_req (data_req),
  50. .out_vsync (out_vsync),
  51. .h_disp (h_disp),
  52. .v_disp (v_disp),
  53. .pixel_xpos(pixel_xpos),
  54. .pixel_ypos(pixel_ypos)
  55. );
  56. endmodule

 clk_div.v

  1. `timescale 1ns / 1ps
  2. //时钟分频模块
  3. module clk_div (
  4. input clk, //50Mhz
  5. input rst_n,
  6. output reg lcd_pclk
  7. );
  8. reg clk_25m;
  9. //时钟2分频 输出25MHz时钟
  10. always @(posedge clk or negedge rst_n) begin
  11. if (!rst_n) clk_25m <= 1'b0;
  12. else clk_25m <= ~clk_25m;
  13. end
  14. always @(*) begin
  15. lcd_pclk = clk_25m;
  16. end
  17. endmodule

lcd_driver.v

  1. `timescale 1ns / 1ps
  2. module lcd_driver (
  3. input lcd_clk, //lcd模块驱动时钟
  4. input sys_rst_n, //复位信号
  5. input [15:0] pixel_data, //像素点数据
  6. output data_req, //请求像素点颜色数据输入
  7. output [10:0] pixel_xpos, //像素点横坐标
  8. output [10:0] pixel_ypos, //像素点纵坐标
  9. output [10:0] h_disp, //LCD屏水平分辨率
  10. output [10:0] v_disp, //LCD屏垂直分辨率
  11. output out_vsync, //帧复位,高有效
  12. //RGB LCD接口
  13. output lcd_hs, //LCD 行同步信号
  14. output lcd_vs, //LCD 场同步信号
  15. output lcd_de, //LCD 数据输入使能
  16. output [15:0] lcd_rgb, //LCD RGB565颜色数据
  17. output lcd_bl, //LCD 背光控制信号
  18. output lcd_rst, //LCD 复位信号
  19. output lcd_pclk //LCD 采样时钟
  20. );
  21. //parameter define
  22. // 7' 800*480
  23. parameter H_SYNC_7084 = 11'd128; //行同步
  24. parameter H_BACK_7084 = 11'd88; //行显示后沿
  25. parameter H_DISP_7084 = 11'd800; //行有效数据
  26. parameter H_FRONT_7084 = 11'd40; //行显示前沿
  27. parameter H_TOTAL_7084 = 11'd1056; //行扫描周期
  28. parameter V_SYNC_7084 = 11'd2; //场同步
  29. parameter V_BACK_7084 = 11'd33; //场显示后沿
  30. parameter V_DISP_7084 = 11'd480; //场有效数据
  31. parameter V_FRONT_7084 = 11'd10; //场显示前沿
  32. parameter V_TOTAL_7084 = 11'd525; //场扫描周期
  33. //reg define
  34. reg [10:0] h_sync;
  35. reg [10:0] h_back;
  36. reg [10:0] h_total;
  37. reg [10:0] v_sync;
  38. reg [10:0] v_back;
  39. reg [10:0] v_total;
  40. reg [10:0] h_cnt;
  41. reg [10:0] v_cnt;
  42. reg [10:0] h_disp; //LCD屏水平分辨率
  43. reg [10:0] v_disp; //LCD屏垂直分辨率
  44. reg lcd_de; //LCD 数据输入使能
  45. reg [15:0] lcd_rgb; //LCD RGB565颜色数据
  46. //wire define
  47. wire lcd_en;
  48. wire out_vsync;
  49. //*****************************************************
  50. //** main code
  51. //*****************************************************
  52. assign lcd_bl = 1'b1; //RGB LCD显示模块背光控制信号
  53. assign lcd_rst = 1'b1; //RGB LCD显示模块系统复位信号
  54. assign lcd_pclk = lcd_clk; //RGB LCD显示模块采样时钟
  55. //RGB LCD 采用数据输入使能信号同步时,行场同步信号需要拉高
  56. assign lcd_hs = 1'b1;
  57. assign lcd_vs = 1'b1;
  58. //使能RGB565数据输出
  59. assign lcd_en = ((h_cnt >= h_sync + h_back) && (h_cnt < h_sync + h_back + h_disp)
  60. && (v_cnt >= v_sync + v_back) && (v_cnt < v_sync + v_back + v_disp))
  61. ? 1'b1 : 1'b0;
  62. //帧复位,高有效
  63. assign out_vsync = ((h_cnt <= 100) && (v_cnt == 1)) ? 1'b1 : 1'b0;
  64. //请求像素点颜色数据输入
  65. assign data_req = ((h_cnt >= h_sync + h_back - 1'b1) && (h_cnt < h_sync + h_back + h_disp - 1'b1)
  66. && (v_cnt >= v_sync + v_back) && (v_cnt < v_sync + v_back + v_disp))
  67. ? 1'b1 : 1'b0;
  68. //像素点坐标
  69. assign pixel_xpos = data_req ? (h_cnt - (h_sync + h_back - 1'b1)) : 11'd0;
  70. assign pixel_ypos = data_req ? (v_cnt - (v_sync + v_back - 1'b1)) : 11'd0;
  71. //LCD输入的颜色数据采用数据输入使能信号同步
  72. always @(posedge lcd_clk or negedge sys_rst_n) begin
  73. if (!sys_rst_n) lcd_de <= 11'd0;
  74. else begin
  75. lcd_de <= lcd_en;
  76. end
  77. end
  78. //RGB565数据输出
  79. always @(posedge lcd_clk or negedge sys_rst_n) begin
  80. if (!sys_rst_n) lcd_rgb <= 16'd0;
  81. else begin
  82. if (lcd_en) lcd_rgb <= pixel_data;
  83. else lcd_rgb <= 16'd0;
  84. end
  85. end
  86. //行场时序参数
  87. always @(*) begin
  88. h_sync = H_SYNC_7084;
  89. h_back = H_BACK_7084;
  90. h_disp = H_DISP_7084;
  91. h_total = H_TOTAL_7084;
  92. v_sync = V_SYNC_7084;
  93. v_back = V_BACK_7084;
  94. v_disp = V_DISP_7084;
  95. v_total = V_TOTAL_7084;
  96. end
  97. //行计数器对像素时钟计数
  98. always @(posedge lcd_pclk or negedge sys_rst_n) begin
  99. if (!sys_rst_n) h_cnt <= 11'd0;
  100. else begin
  101. if (h_cnt == h_total - 1'b1) h_cnt <= 11'd0;
  102. else h_cnt <= h_cnt + 1'b1;
  103. end
  104. end
  105. //场计数器对行计数
  106. always @(posedge lcd_clk or negedge sys_rst_n) begin
  107. if (!sys_rst_n) v_cnt <= 11'd0;
  108. else begin
  109. if (h_cnt == h_total - 1'b1) begin
  110. if (v_cnt == v_total - 1'b1) v_cnt <= 11'd0;
  111. else v_cnt <= v_cnt + 1'b1;
  112. end
  113. end
  114. end
  115. endmodule

 

3.5 引角约束

  1. #IO管脚约束
  2. #时钟周期约束
  3. #create_clock -name sys_clk_p -period 10.000 [get_ports sys_clk_p]
  4. #时钟
  5. set_property IOSTANDARD DIFF_HSTL_I_12 [get_ports sys_clk_p]
  6. set_property IOSTANDARD DIFF_HSTL_I_12 [get_ports sys_clk_n]
  7. set_property PACKAGE_PIN AE5 [get_ports sys_clk_p]
  8. set_property PACKAGE_PIN AF5 [get_ports sys_clk_n]
  9. #复位
  10. set_property -dict {PACKAGE_PIN AH11 IOSTANDARD LVCMOS33} [get_ports sys_rst_n]
  11. #RGB LCD
  12. set_property -dict {PACKAGE_PIN W14 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[0]}]
  13. set_property -dict {PACKAGE_PIN Y14 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[1]}]
  14. set_property -dict {PACKAGE_PIN W13 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[2]}]
  15. set_property -dict {PACKAGE_PIN Y13 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[3]}]
  16. set_property -dict {PACKAGE_PIN W12 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[4]}]
  17. set_property -dict {PACKAGE_PIN Y12 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[5]}]
  18. set_property -dict {PACKAGE_PIN W11 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[6]}]
  19. set_property -dict {PACKAGE_PIN AA12 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[7]}]
  20. set_property -dict {PACKAGE_PIN AC14 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[8]}]
  21. set_property -dict {PACKAGE_PIN AD15 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[9]}]
  22. set_property -dict {PACKAGE_PIN AC13 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[10]}]
  23. set_property -dict {PACKAGE_PIN AD14 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[11]}]
  24. set_property -dict {PACKAGE_PIN AE15 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[12]}]
  25. set_property -dict {PACKAGE_PIN AA13 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[13]}]
  26. set_property -dict {PACKAGE_PIN AE14 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[14]}]
  27. set_property -dict {PACKAGE_PIN AB13 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[15]}]
  28. set_property -dict {PACKAGE_PIN AG14 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[16]}]
  29. set_property -dict {PACKAGE_PIN AB15 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[17]}]
  30. set_property -dict {PACKAGE_PIN AH14 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[18]}]
  31. set_property -dict {PACKAGE_PIN AB14 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[19]}]
  32. set_property -dict {PACKAGE_PIN AG13 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[20]}]
  33. set_property -dict {PACKAGE_PIN AE13 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[21]}]
  34. set_property -dict {PACKAGE_PIN AH13 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[22]}]
  35. set_property -dict {PACKAGE_PIN AF13 IOSTANDARD LVCMOS33} [get_ports {lcd_rgb[23]}]
  36. set_property -dict {PACKAGE_PIN J11 IOSTANDARD LVCMOS33} [get_ports lcd_hs]
  37. set_property -dict {PACKAGE_PIN K12 IOSTANDARD LVCMOS33} [get_ports lcd_vs]
  38. set_property -dict {PACKAGE_PIN J10 IOSTANDARD LVCMOS33} [get_ports lcd_de]
  39. set_property -dict {PACKAGE_PIN J12 IOSTANDARD LVCMOS33} [get_ports lcd_bl]
  40. set_property -dict {PACKAGE_PIN K13 IOSTANDARD LVCMOS33} [get_ports lcd_pclk]
  41. set_property -dict {PACKAGE_PIN F10 IOSTANDARD LVCMOS33} [get_ports lcd_rst]
  42. #CAMERA
  43. #摄像头接口的时钟
  44. create_clock -period 40.000 -name cmos_pclk [get_ports cam_pclk]
  45. set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets cam_pclk_IBUF]
  46. #set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets cam_pclk_IBUF_inst/O]
  47. set_property -dict {PACKAGE_PIN C13 IOSTANDARD LVCMOS33} [get_ports cam_pclk]
  48. set_property -dict {PACKAGE_PIN F13 IOSTANDARD LVCMOS33} [get_ports cam_rst_n]
  49. set_property -dict {PACKAGE_PIN B15 IOSTANDARD LVCMOS33} [get_ports cam_pwdn]
  50. set_property -dict {PACKAGE_PIN E15 IOSTANDARD LVCMOS33 } [get_ports {cam_data[0]}]
  51. set_property -dict {PACKAGE_PIN D15 IOSTANDARD LVCMOS33 } [get_ports {cam_data[1]}]
  52. set_property -dict {PACKAGE_PIN E14 IOSTANDARD LVCMOS33 } [get_ports {cam_data[2]}]
  53. set_property -dict {PACKAGE_PIN D14 IOSTANDARD LVCMOS33 } [get_ports {cam_data[3]}]
  54. set_property -dict {PACKAGE_PIN E13 IOSTANDARD LVCMOS33 } [get_ports {cam_data[4]}]
  55. set_property -dict {PACKAGE_PIN B13 IOSTANDARD LVCMOS33 } [get_ports {cam_data[5]}]
  56. set_property -dict {PACKAGE_PIN C14 IOSTANDARD LVCMOS33 } [get_ports {cam_data[6]}]
  57. set_property -dict {PACKAGE_PIN A13 IOSTANDARD LVCMOS33 } [get_ports {cam_data[7]}]
  58. set_property -dict {PACKAGE_PIN G14 IOSTANDARD LVCMOS33} [get_ports cam_vsync]
  59. set_property -dict {PACKAGE_PIN G13 IOSTANDARD LVCMOS33} [get_ports cam_href]
  60. set_property -dict {PACKAGE_PIN H13 IOSTANDARD LVCMOS33} [get_ports cam_scl]
  61. set_property -dict {PACKAGE_PIN F15 IOSTANDARD LVCMOS33} [get_ports cam_sda]
  62. set_property PULLUP true [get_ports cam_scl]
  63. set_property PULLUP true [get_ports cam_sda]
  64. #DDR4
  65. set_property PACKAGE_PIN AH4 [get_ports {c0_ddr4_odt[0]}]
  66. set_property PACKAGE_PIN AE8 [get_ports {c0_ddr4_bg[0]}]
  67. set_property PACKAGE_PIN AB5 [get_ports {c0_ddr4_adr[16]}]
  68. set_property PACKAGE_PIN AB7 [get_ports {c0_ddr4_adr[15]}]
  69. set_property PACKAGE_PIN AF6 [get_ports {c0_ddr4_adr[14]}]
  70. set_property PACKAGE_PIN AD9 [get_ports {c0_ddr4_adr[13]}]
  71. set_property PACKAGE_PIN AC6 [get_ports {c0_ddr4_adr[12]}]
  72. set_property PACKAGE_PIN AH9 [get_ports {c0_ddr4_adr[11]}]
  73. set_property PACKAGE_PIN AE7 [get_ports {c0_ddr4_adr[10]}]
  74. set_property PACKAGE_PIN AC9 [get_ports {c0_ddr4_adr[9]}]
  75. set_property PACKAGE_PIN AH8 [get_ports {c0_ddr4_adr[8]}]
  76. set_property PACKAGE_PIN AE9 [get_ports {c0_ddr4_adr[7]}]
  77. set_property PACKAGE_PIN AH7 [get_ports {c0_ddr4_adr[6]}]
  78. set_property PACKAGE_PIN AD7 [get_ports {c0_ddr4_adr[5]}]
  79. set_property PACKAGE_PIN AF7 [get_ports {c0_ddr4_adr[4]}]
  80. set_property PACKAGE_PIN AC8 [get_ports {c0_ddr4_adr[3]}]
  81. set_property PACKAGE_PIN AF8 [get_ports {c0_ddr4_adr[2]}]
  82. set_property PACKAGE_PIN AB8 [get_ports {c0_ddr4_adr[1]}]
  83. set_property PACKAGE_PIN AG8 [get_ports {c0_ddr4_adr[0]}]
  84. set_property PACKAGE_PIN AD2 [get_ports {c0_ddr4_dqs_t[1]}]
  85. set_property PACKAGE_PIN AD1 [get_ports {c0_ddr4_dqs_c[1]}]
  86. set_property PACKAGE_PIN AE2 [get_ports {c0_ddr4_dqs_t[0]}]
  87. set_property PACKAGE_PIN AF2 [get_ports {c0_ddr4_dqs_c[0]}]
  88. set_property PACKAGE_PIN AC4 [get_ports {c0_ddr4_dq[15]}]
  89. set_property PACKAGE_PIN AC3 [get_ports {c0_ddr4_dq[14]}]
  90. set_property PACKAGE_PIN AB4 [get_ports {c0_ddr4_dq[13]}]
  91. set_property PACKAGE_PIN AB3 [get_ports {c0_ddr4_dq[12]}]
  92. set_property PACKAGE_PIN AB2 [get_ports {c0_ddr4_dq[11]}]
  93. set_property PACKAGE_PIN AC2 [get_ports {c0_ddr4_dq[10]}]
  94. set_property PACKAGE_PIN AB1 [get_ports {c0_ddr4_dq[9]}]
  95. set_property PACKAGE_PIN AC1 [get_ports {c0_ddr4_dq[8]}]
  96. set_property PACKAGE_PIN AG3 [get_ports {c0_ddr4_dq[7]}]
  97. set_property PACKAGE_PIN AH3 [get_ports {c0_ddr4_dq[6]}]
  98. set_property PACKAGE_PIN AE3 [get_ports {c0_ddr4_dq[5]}]
  99. set_property PACKAGE_PIN AF3 [get_ports {c0_ddr4_dq[4]}]
  100. set_property PACKAGE_PIN AH2 [get_ports {c0_ddr4_dq[3]}]
  101. set_property PACKAGE_PIN AH1 [get_ports {c0_ddr4_dq[2]}]
  102. set_property PACKAGE_PIN AF1 [get_ports {c0_ddr4_dq[1]}]
  103. set_property PACKAGE_PIN AG1 [get_ports {c0_ddr4_dq[0]}]
  104. set_property INTERNAL_VREF 0.6 [get_iobanks 64]
  105. set_property PACKAGE_PIN AB6 [get_ports {c0_ddr4_cs_n[0]}]
  106. set_property PACKAGE_PIN AG6 [get_ports {c0_ddr4_ck_t[0]}]
  107. set_property PACKAGE_PIN AG5 [get_ports {c0_ddr4_ck_c[0]}]
  108. set_property PACKAGE_PIN AE4 [get_ports {c0_ddr4_cke[0]}]
  109. set_property PACKAGE_PIN AG9 [get_ports c0_ddr4_reset_n]
  110. set_property PACKAGE_PIN AD4 [get_ports c0_ddr4_act_n]
  111. set_property PACKAGE_PIN AC7 [get_ports {c0_ddr4_ba[1]}]
  112. set_property PACKAGE_PIN AH6 [get_ports {c0_ddr4_ba[0]}]
  113. set_property PACKAGE_PIN AD5 [get_ports {c0_ddr4_dm_dbi_n[1]}]
  114. set_property PACKAGE_PIN AG4 [get_ports {c0_ddr4_dm_dbi_n[0]}]
  115. set_property DRIVE 12 [get_ports {lcd_rgb[23]}]
  116. set_property DRIVE 12 [get_ports {lcd_rgb[22]}]
  117. set_property DRIVE 12 [get_ports {lcd_rgb[21]}]
  118. set_property DRIVE 12 [get_ports {lcd_rgb[20]}]
  119. set_property DRIVE 12 [get_ports {lcd_rgb[19]}]
  120. set_property DRIVE 12 [get_ports {lcd_rgb[18]}]
  121. set_property DRIVE 12 [get_ports {lcd_rgb[17]}]
  122. set_property DRIVE 12 [get_ports {lcd_rgb[16]}]
  123. set_property DRIVE 12 [get_ports {lcd_rgb[15]}]
  124. set_property DRIVE 12 [get_ports {lcd_rgb[14]}]
  125. set_property DRIVE 12 [get_ports {lcd_rgb[13]}]
  126. set_property DRIVE 12 [get_ports {lcd_rgb[12]}]
  127. set_property DRIVE 12 [get_ports {lcd_rgb[11]}]
  128. set_property DRIVE 12 [get_ports {lcd_rgb[10]}]
  129. set_property DRIVE 12 [get_ports {lcd_rgb[9]}]
  130. set_property DRIVE 12 [get_ports {lcd_rgb[8]}]
  131. set_property DRIVE 12 [get_ports {lcd_rgb[7]}]
  132. set_property DRIVE 12 [get_ports {lcd_rgb[6]}]
  133. set_property DRIVE 12 [get_ports {lcd_rgb[5]}]
  134. set_property DRIVE 12 [get_ports {lcd_rgb[4]}]
  135. set_property DRIVE 12 [get_ports {lcd_rgb[3]}]
  136. set_property DRIVE 12 [get_ports {lcd_rgb[2]}]
  137. set_property DRIVE 12 [get_ports {lcd_rgb[1]}]
  138. set_property DRIVE 12 [get_ports {lcd_rgb[0]}]
  139. set_property DRIVE 12 [get_ports lcd_bl]
  140. set_property DRIVE 12 [get_ports lcd_de]
  141. set_property DRIVE 12 [get_ports lcd_hs]
  142. set_property DRIVE 12 [get_ports lcd_rst]
  143. set_property DRIVE 12 [get_ports lcd_vs]
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/567745
推荐阅读
相关标签
  

闽ICP备14008679号