• 基于FPGA的OV7670摄像头实时检测


    目录

    前言:整体系统框图

    一、OV7670摄像头简介

    二、OV7670 SCCB协议简介

    三、OV7670初始化寄存器配置

    四、OV7670初始化代码编写

     五、什么是DVP?

    六、摄像头写数据请求

    七、顶层文件编写

    八、效果


    前言:整体系统框图

     如图所示,FPGA中主要模块包含:时钟模块、OV7670初始化模块、DVP协议数据流模块、写FIFO模块、写FIFO控制模块、SDRAM控制模块、读FIFO模块、读FIFO控制模块、VGA控制模块。

    其整体流程为:启动时先对摄像头进行初始化设置,初始化完成后,FPGA从摄像头获取一帧一帧的图像数据,根据数据手册将ov7670数据流转换成我们需要的RGB565数据流,随后存入写FIFO模块;(写控制模块)当写FIFO模块中存储的数据大于等于8时,发出SDRAM写请求,SDRAM写请求通过后,读取FIFO数据存储起来;(读FIFO模块)当读FIFO数据小于等于8时,读取SDRAM中的数据经过读FIFO缓存后送入VGA显示模块进行显示。同时写控制模块和读控制模块控制SDRAM读写地址的增加。

    1、时钟模块
         这里使用PLL的IP核,以50MHz时钟生成25MHz和100MHz时钟,其中摄像头初始化模块和VGA控制模块使用的是25MHz,SDRAM控制模块、写FIFO控制模块和读FIFO控制模块使用的是100MHz,写FIFO和读FIFO模块都是异步FIFO,使用25MHz和100MHz时钟。

    一、OV7670摄像头简介

    OV7670/OV7171 图像传感器,体积小、工作电压低,提供单片VGA摄像头和影像处理器的所有功能。通过SCCB 总线控制,可以输出整帧、子采样、取窗口等方式的各种分辨率8位影响数据。该产品VGA图像最高达到30帧/秒。用户可以完全控制图像质量、数据格式和传输方式。所有图像处理功能过程包括伽玛曲线、白平衡、饱和度、色度等都可以通过SCCB接口编程。OmmiVision 图像传感器应用独有的传感器技术,通过减少或消除光学或电子缺陷如固定图案噪声、托尾、浮散等,提高图像质量,得到清晰的稳定的彩色图像。

    主要引出的信号引脚如下:

    3.3V--输入电源电压(推荐使用3.3V,5V也可,但不推荐)

    GND

    SCL(SIOC):SCCB时钟口(注意:部分单片机需要上拉控制,和I2C接口类似)

    SDA(SIOD):SCCB数据口(注意:部分单片机需要上拉控制,和I2C接口类似)

    VSYNC:场同步(帧同步)信号(输出信号)

    HREF:行同步信号(输出信号,一般可以不使用,特殊情况使用)

    PCLK:像素时钟

    XCLK:系统时钟输入

    D0-D7:数据位(输出信号)

    RESET:初始化所有寄存器到默认值 0:RESET 模式 1:一般模式

    PWDN:POWER DOWN模式选择 0:工作 1:POWER DOWN

    其中,对OV7670初始化配置只使用SCL和SDA两个信号线。

    所用模块如图:

    二、OV7670 SCCB协议简介

          对OV7670初始化使用的是SCCB协议,由数据线SDA和时钟线SCL组成,SCCB协议和I2C协议基本一样,是简化的I2C协议,前面博客中已经讲过I2C协议,需要可以去看看。

    SCCB(SeriaI Camera ControlBus)是简化的I2C协议,SIO-l是串行时钟输入线,SIO-O是串行双向数据线,分别相当于I2C协议的SCL和SDA。SCCB的总线时序与I2C基本相同,它的响应信号ACK被称为一个传输单元的第9位,分为Don’t care和NA。Don’t care位由从机产生;NA位由主机产生,由于SCCB不支持多字节的读写,NA位必须为高电平。另外,SCCB没有重复起始的概念,因此在SCCB的读周期中,当主机发送完片内寄存器地址后,必须发送总线停止条件。不然在发送读命令时,从机将不能产生Don’t care响应信号。

    这里采用的是100KHz的SCL。

    三、OV7670初始化寄存器配置

         OV7670摄像头共201个寄存器,需要配置的有一百六十几个,这个具体看数据手册吧,下边代码中会有配置寄存器的数据。

    四、OV7670初始化代码编写

    1. `timescale 1 ns / 1 ns
    2. module system_ctrl
    3. (
    4. input clk, //50MHz
    5. input rst_n, //global reset
    6. output sys_rst_n, //system reset
    7. output clk_c0,
    8. output clk_c1,
    9. output clk_c2, //-75deg
    10. output clk_c3 //-75deg
    11. );
    12. //----------------------------------------------
    13. //rst_n synchronism, is controlled by the input clk
    14. reg rst_nr1,rst_nr2;
    15. always @(posedge clk or negedge rst_n)
    16. begin
    17. if(!rst_n)
    18. begin
    19. rst_nr1 <= 1'b0;
    20. rst_nr2 <= 1'b0;
    21. end
    22. else
    23. begin
    24. rst_nr1 <= 1'b1;
    25. rst_nr2 <= rst_nr1;
    26. end
    27. end
    28. //----------------------------------
    29. //component instantiation for system_delay
    30. wire delay_done;
    31. system_delay u_system_delay
    32. (
    33. .clk (clk),
    34. .rst_n (rst_nr2),
    35. .delay_done (delay_done)
    36. );
    37. wire pll_rst = ~rst_nr2 & ~delay_done; //active High
    38. //----------------------------------------------
    39. //Component instantiation
    40. wire locked;
    41. sdram_pll u_sdram_pll
    42. (
    43. .inclk0 (clk),
    44. .areset (pll_rst),
    45. .locked (locked),
    46. .c0 (clk_c0),
    47. .c1 (clk_c1),
    48. .c2 (clk_c2),
    49. .c3 (clk_c3)
    50. );
    51. //----------------------------------------------
    52. //sys_rst_n synchronism, is control by the highest output clk
    53. wire sysrst_nr0 = rst_nr2 & locked & delay_done;
    54. reg sysrst_nr1, sysrst_nr2;
    55. always @(posedge clk_c1 or negedge sysrst_nr0)
    56. begin
    57. if(!sysrst_nr0)
    58. begin
    59. sysrst_nr1 <= 1'b0;
    60. sysrst_nr2 <= 1'b0;
    61. end
    62. else
    63. begin
    64. sysrst_nr1 <= 1'b1;
    65. sysrst_nr2 <= sysrst_nr1;
    66. end
    67. end
    68. assign sys_rst_n = sysrst_nr2; //active Low
    69. endmodule
    70. //################################################//
    71. //################################################//
    72. module system_delay
    73. (
    74. input clk, //50MHz
    75. input rst_n,
    76. output delay_done
    77. );
    78. //------------------------------------------
    79. // Delay 100ms for steady state
    80. localparam DELAY_CNT = 23'd100_0000; //50ms
    81. reg [22:0] cnt;
    82. always@(posedge clk or negedge rst_n)
    83. begin
    84. if(!rst_n)
    85. cnt <= 0;
    86. else
    87. begin
    88. if(cnt < DELAY_CNT) //1ms
    89. cnt <= cnt + 1'b1;
    90. else
    91. cnt <= cnt;
    92. end
    93. end
    94. //------------------------------------------
    95. //sys_rst_n synchronism
    96. assign delay_done = (cnt == DELAY_CNT)? 1'b1 : 1'b0;
    97. endmodule

    摄像头检测代码

    1. `timescale 1ns/1ns
    2. module CMOS_Capture
    3. (
    4. //Global Clock
    5. input iCLK, //25MHz
    6. input iRST_N,
    7. //I2C Initilize Done
    8. input Init_Done, //Init Done
    9. //Sensor Interface
    10. output CMOS_RST_N, //cmos work state(5ms delay for sccb config)
    11. output CMOS_PWDN, //cmos power on
    12. output CMOS_XCLK, //25MHz
    13. input CMOS_PCLK, //25MHz
    14. input [7:0] CMOS_iDATA, //CMOS Data
    15. input CMOS_VSYNC, //L: Vaild
    16. input CMOS_HREF, //H: Vaild
    17. //Ouput Sensor Data
    18. output reg CMOS_oCLK, //1/2 PCLK
    19. output reg [15:0] CMOS_oDATA, //16Bits RGB
    20. output reg CMOS_VALID, //Data Enable
    21. output reg [7:0] CMOS_FPS_DATA //cmos fps
    22. );
    23. assign CMOS_RST_N = 1'b1; //cmos work state(5ms delay for sccb config)
    24. assign CMOS_PWDN = 1'b0; //cmos power on
    25. assign CMOS_XCLK = iCLK; //25MHz XCLK
    26. //-----------------------------------------------------
    27. //同步输入//Sensor HS & VS Vaild Capture
    28. /**************************************************
    29. ________ ________
    30. VS |_________________________________|
    31. HS _______ _______
    32. _____________| |__...___| |____________
    33. **************************************************/
    34. /*
    35. //----------------------------------------------
    36. reg mCMOS_HREF; //行同步:高电平有效
    37. always@(posedge CMOS_PCLK or negedge iRST_N)
    38. begin
    39. if(!iRST_N)
    40. mCMOS_HREF <= 0;
    41. else
    42. mCMOS_HREF <= CMOS_HREF;
    43. end
    44. wire CMOS_HREF_over = ({mCMOS_HREF,CMOS_HREF} == 2'b10) ? 1'b1 : 1'b0; //HREF 下降沿结束
    45. */
    46. //----------------------------------------------
    47. reg mCMOS_VSYNC;
    48. always@(posedge CMOS_PCLK or negedge iRST_N)
    49. begin
    50. if(!iRST_N)
    51. mCMOS_VSYNC <= 1;
    52. else
    53. mCMOS_VSYNC <= CMOS_VSYNC; //场同步:低电平有效
    54. end
    55. wire CMOS_VSYNC_over = ({mCMOS_VSYNC,CMOS_VSYNC} == 2'b01) ? 1'b1 : 1'b0; //VSYNC上升沿结束
    56. /*
    57. //--------------------------------------------
    58. //Counter the HS & VS Pixel
    59. localparam H_DISP = 12'd640;
    60. localparam V_DISP = 12'd480;
    61. reg [11:0] X_Cont; //640
    62. reg [11:0] Y_Cont; //480
    63. always@(posedge CMOS_PCLK or negedge iRST_N)
    64. begin
    65. if(!iRST_N)
    66. X_Cont <= 0;
    67. else if(~CMOS_VSYNC & CMOS_HREF) //场信号有效
    68. X_Cont <= (byte_state == 1'b1) ? X_Cont + 1'b1 : X_Cont;
    69. else
    70. X_Cont <= 0;
    71. end
    72. always@(posedge CMOS_PCLK or negedge iRST_N)
    73. begin
    74. if(!iRST_N)
    75. Y_Cont <= 0;
    76. else if(CMOS_VSYNC == 1'b0)
    77. begin
    78. if(CMOS_HREF_over == 1'b1) //HREF下降沿 一行结束
    79. Y_Cont <= Y_Cont + 1'b1;
    80. end
    81. else
    82. Y_Cont <= 0;
    83. end
    84. */
    85. //-----------------------------------------------------
    86. //Change the sensor data from 8 bits to 16 bits.
    87. reg byte_state; //byte state count
    88. reg [7:0] Pre_CMOS_iDATA;
    89. always@(posedge CMOS_PCLK or negedge iRST_N)
    90. begin
    91. if(!iRST_N)
    92. begin
    93. byte_state <= 0;
    94. Pre_CMOS_iDATA <= 8'd0;
    95. CMOS_oDATA <= 16'd0;
    96. end
    97. else
    98. begin
    99. if(~CMOS_VSYNC & CMOS_HREF) //行场有效,{first_byte, second_byte}
    100. begin
    101. byte_state <= byte_state + 1'b1; //(RGB565 = {first_byte, second_byte})
    102. case(byte_state)
    103. 1'b0 : Pre_CMOS_iDATA[7:0] <= CMOS_iDATA;
    104. 1'b1 : CMOS_oDATA[15:0] <= {Pre_CMOS_iDATA[7:0], CMOS_iDATA[7:0]};
    105. endcase
    106. end
    107. else
    108. begin
    109. byte_state <= 0;
    110. Pre_CMOS_iDATA <= 8'd0;
    111. CMOS_oDATA <= CMOS_oDATA;
    112. end
    113. end
    114. end
    115. //--------------------------------------------
    116. //Wait for Sensor output Data valid, 10 Franme
    117. reg [3:0] Frame_Cont;
    118. reg Frame_valid;
    119. always@(posedge CMOS_PCLK or negedge iRST_N)
    120. begin
    121. if(!iRST_N)
    122. begin
    123. Frame_Cont <= 0;
    124. Frame_valid <= 0;
    125. end
    126. else if(Init_Done) //CMOS I2C初始化完毕
    127. begin
    128. if(CMOS_VSYNC_over == 1'b1) //VS上升沿,1帧写入完毕
    129. begin
    130. if(Frame_Cont < 12)
    131. begin
    132. Frame_Cont <= Frame_Cont + 1'b1;
    133. Frame_valid <= 1'b0;
    134. end
    135. else
    136. begin
    137. Frame_Cont <= Frame_Cont;
    138. Frame_valid <= 1'b1; //数据输出有效
    139. end
    140. end
    141. end
    142. end
    143. //-----------------------------------------------------
    144. //CMOS_DATA数据同步输出使能时钟
    145. always@(posedge CMOS_PCLK or negedge iRST_N)
    146. begin
    147. if(!iRST_N)
    148. CMOS_oCLK <= 0;
    149. else if(Frame_valid == 1'b1 && byte_state)//(X_Cont >= 12'd1 && X_Cont <= H_DISP))
    150. CMOS_oCLK <= ~CMOS_oCLK;
    151. else
    152. CMOS_oCLK <= 0;
    153. end
    154. //----------------------------------------------------
    155. //数据输出有效CMOS_VALID
    156. always@(posedge CMOS_PCLK or negedge iRST_N)
    157. begin
    158. if(!iRST_N)
    159. CMOS_VALID <= 0;
    160. else if(Frame_valid == 1'b1)
    161. CMOS_VALID <= ~CMOS_VSYNC;
    162. else
    163. CMOS_VALID <= 0;
    164. end
    165. /************************************************************
    166. Caculate Frame Rate per second
    167. *************************************************************/
    168. //-----------------------------------------------------
    169. // 2s 延时函数
    170. reg [25:0] delay_cnt; //25_000000 * 2
    171. always@(posedge iCLK or negedge iRST_N)
    172. begin
    173. if(!iRST_N)
    174. delay_cnt <= 0;
    175. else if(Frame_valid)
    176. begin
    177. if(delay_cnt < 26'd50_000000)
    178. delay_cnt <= delay_cnt + 1'b1;
    179. else
    180. delay_cnt <= 0;
    181. end
    182. else
    183. delay_cnt <= 0;
    184. end
    185. wire delay_2s = (delay_cnt == 26'd50_000000) ? 1'b1 : 1'b0;
    186. //-------------------------------------------
    187. //帧率采样计算
    188. reg fps_state;
    189. reg [7:0] fps_data;
    190. always@(posedge iCLK or negedge iRST_N)
    191. begin
    192. if(!iRST_N)
    193. begin
    194. fps_data <= 0;
    195. fps_state <= 0;
    196. CMOS_FPS_DATA <= 0;
    197. end
    198. else if(Frame_valid)
    199. begin
    200. case(fps_state)
    201. 0: begin
    202. CMOS_FPS_DATA <= CMOS_FPS_DATA;
    203. if(delay_2s == 0)
    204. begin
    205. fps_state <= 0;
    206. if(CMOS_VSYNC_over == 1'b1) //VS上升沿,1帧写入完毕
    207. fps_data <= fps_data + 1'b1;
    208. end
    209. else
    210. fps_state <= 1;
    211. end
    212. 1: begin
    213. fps_state <= 0;
    214. fps_data <= 0;
    215. CMOS_FPS_DATA <= fps_data >>1;
    216. end
    217. endcase
    218. end
    219. else
    220. begin
    221. fps_data <= 0;
    222. fps_state <= 0;
    223. CMOS_FPS_DATA <= 0;
    224. end
    225. end
    226. endmodule

    摄像头开机定时要求

    1. //camera power on timing requirement
    2. module power_on_delay(clk_50M,reset_n,camera_rstn,camera_pwnd,initial_en);
    3. input clk_50M;
    4. input reset_n;
    5. output camera_rstn;
    6. output camera_pwnd;
    7. output initial_en;
    8. reg [18:0]cnt1;
    9. reg [15:0]cnt2;
    10. reg [19:0]cnt3;
    11. reg initial_en;
    12. reg camera_rstn_reg;
    13. reg camera_pwnd_reg;
    14. assign camera_rstn=camera_rstn_reg;
    15. assign camera_pwnd=camera_pwnd_reg;
    16. //5ms, delay from sensor power up stable to Pwdn pull down
    17. always@(posedge clk_50M)
    18. begin
    19. if(reset_n==1'b0) begin
    20. cnt1<=0;
    21. camera_pwnd_reg<=1'b1;
    22. end
    23. else if(cnt1<18'h40000) begin
    24. cnt1<=cnt1+1'b1;
    25. camera_pwnd_reg<=1'b1;
    26. end
    27. else
    28. camera_pwnd_reg<=1'b0;
    29. end
    30. //1.3ms, delay from pwdn low to resetb pull up
    31. always@(posedge clk_50M)
    32. begin
    33. if(camera_pwnd_reg==1) begin
    34. cnt2<=0;
    35. camera_rstn_reg<=1'b0;
    36. end
    37. else if(cnt2<16'hffff) begin
    38. cnt2<=cnt2+1'b1;
    39. camera_rstn_reg<=1'b0;
    40. end
    41. else
    42. camera_rstn_reg<=1'b1;
    43. end
    44. //21ms, delay from resetb pul high to SCCB initialization
    45. always@(posedge clk_50M)
    46. begin
    47. if(camera_rstn_reg==0) begin
    48. cnt3<=0;
    49. initial_en<=1'b0;
    50. end
    51. else if(cnt3<20'hfffff) begin
    52. cnt3<=cnt3+1'b1;
    53. initial_en<=1'b0;
    54. end
    55. else
    56. initial_en<=1'b1;
    57. end
    58. endmodule

    sdram_vga_top 

    1. module sdram_vga_top
    2. (
    3. //global clock
    4. input clk_vga, //vga clock
    5. input clk_ref, //sdram ctrl clock
    6. input clk_refout, //sdram clock output
    7. input rst_n, //global reset
    8. //sdram control
    9. output sdram_clk, //sdram clock
    10. output sdram_cke, //sdram clock enable
    11. output sdram_cs_n, //sdram chip select
    12. output sdram_we_n, //sdram write enable
    13. output sdram_cas_n, //sdram column address strobe
    14. output sdram_ras_n, //sdram row address strobe
    15. output sdram_udqm, //sdram data enable (H:8)
    16. output sdram_ldqm, //sdram data enable (L:8)
    17. output [1:0] sdram_ba, //sdram bank address
    18. output [11:0] sdram_addr, //sdram address
    19. inout [15:0] sdram_data, //sdram data
    20. //lcd port
    21. output lcd_dclk, //lcd pixel clock
    22. output lcd_hs, //lcd horizontal sync
    23. output lcd_vs, //lcd vertical sync
    24. output lcd_sync, //lcd sync
    25. output lcd_blank, //lcd blank(L:blank)
    26. output [4:0] lcd_red, //lcd red data
    27. output [5:0] lcd_green, //lcd green data
    28. output [4:0] lcd_blue, //lcd blue data
    29. //user interface
    30. input clk_write, //fifo write clock
    31. input sys_we, //fifo write enable
    32. input [15:0] sys_data_in, //fifo data input
    33. output sdram_init_done,//sdram init done
    34. input frame_valid //frame valid
    35. );
    36. //----------------------------------------------
    37. wire sys_rd; //fifo read enable
    38. wire [15:0] sys_data_out; //fifo data output
    39. wire lcd_framesync; //lcd frame sync
    40. wire frame_write_done; //sdram write frame done
    41. wire frame_read_done; //sdram read frame done
    42. wire [1:0] wr_bank; //sdram write bank
    43. wire [1:0] rd_bank; //sdram read bank
    44. wire wr_load; //sdram write address reset
    45. wire rd_load; //sdram read address reset
    46. sdram_2fifo_top u_sdram_2fifo_top
    47. (
    48. //global clock
    49. .clk_ref (clk_ref), //sdram reference clock
    50. .clk_refout (clk_refout), //sdram clk input
    51. .clk_write (clk_write), //fifo data write clock
    52. .clk_read (clk_vga), //fifo data read clock
    53. .rst_n (rst_n), //global reset
    54. //sdram interface
    55. .sdram_clk (sdram_clk), //sdram clock
    56. .sdram_cke (sdram_cke), //sdram clock enable
    57. .sdram_cs_n (sdram_cs_n), //sdram chip select
    58. .sdram_we_n (sdram_we_n), //sdram write enable
    59. .sdram_ras_n (sdram_ras_n), //sdram column address strobe
    60. .sdram_cas_n (sdram_cas_n), //sdram row address strobe
    61. .sdram_ba (sdram_ba), //sdram data enable (H:8)
    62. .sdram_addr (sdram_addr), //sdram data enable (L:8)
    63. .sdram_data (sdram_data), //sdram bank address
    64. .sdram_udqm (sdram_udqm), //sdram address
    65. .sdram_ldqm (sdram_ldqm), //sdram data
    66. //user interface
    67. //burst and addr
    68. .wr_length (9'd256), //sdram write burst length
    69. .rd_length (9'd256), //sdram read burst length
    70. .wr_addr ({wr_bank,20'd0}), //sdram start write address
    71. .wr_max_addr ({wr_bank,20'd307200}), //sdram max write address
    72. .wr_load (wr_load), //sdram write address reset
    73. .rd_addr ({rd_bank,20'd0}), //sdram start read address
    74. .rd_max_addr ({rd_bank,20'd307200}), //sdram max read address
    75. .rd_load (rd_load), //sdram read address reset
    76. //dcfifo interface
    77. .sdram_init_done (sdram_init_done), //sdram init done
    78. .frame_write_done (frame_write_done), //sdram write one frame
    79. .frame_read_done (frame_read_done), //sdram read one frame
    80. .sys_we (sys_we), //fifo write enable
    81. .sys_data_in (sys_data_in), //fifo data input
    82. .sys_rd (sys_rd), //fifo read enable
    83. .sys_data_out (sys_data_out), //fifo data output
    84. .data_valid (lcd_framesync) //system data output enable
    85. );
    86. //-----------------------------
    87. sdbank_switch u_sdbank_switch
    88. (
    89. .clk (clk_write),
    90. .rst_n (rst_n),
    91. .bank_valid (frame_valid),
    92. .frame_write_done (frame_write_done),
    93. .frame_read_done (frame_read_done),
    94. .wr_bank (wr_bank),
    95. .rd_bank (rd_bank),
    96. .wr_load (wr_load),
    97. .rd_load (rd_load)
    98. );
    99. //---------------------------------
    100. //display on lcd
    101. wire [10:0] lcd_xpos;
    102. wire [10:0] lcd_ypos;
    103. wire [15:0] lcd_data;
    104. assign lcd_data = sys_data_out;
    105. /*
    106. lcd_display U_lcd_display
    107. (
    108. .clk (clk_vga),
    109. .rst_n (rst_n),
    110. .alpha_data (9'hC8),
    111. .lcd_xpos (lcd_xpos),
    112. .lcd_ypos (lcd_ypos),
    113. .lcd_data_in (sys_data_out),
    114. .lcd_data (lcd_data)
    115. );
    116. */
    117. //-----------------------------
    118. //lcd driver top module
    119. lcd_top u_lcd_top
    120. (
    121. //global clock
    122. .clk (clk_vga),
    123. .rst_n (rst_n),
    124. //lcd interface
    125. .lcd_blank (lcd_blank),
    126. .lcd_sync (lcd_sync),
    127. .lcd_dclk (lcd_dclk),
    128. .lcd_hs (lcd_hs),
    129. .lcd_vs (lcd_vs),
    130. .lcd_en (),
    131. .lcd_rgb ({lcd_red, lcd_green ,lcd_blue}),
    132. //user interface
    133. .lcd_request (sys_rd),
    134. .lcd_framesync (lcd_framesync),
    135. .lcd_data (lcd_data),
    136. .lcd_xpos (lcd_xpos),
    137. .lcd_ypos (lcd_ypos)
    138. );
    139. endmodule

     五、什么是DVP?

           DVP(Digital Video Port) 是传统的sensor输出接口,采用并行输出方式,d数据位宽有8bit、10bit、12bit、16bit,是CMOS电平信号(重点是非差分信号),PCLK最大速率为96MHz,接口如下图:

     DVP协议是摄像头中常用的协议,除了DVP协议摄像头中还有其他常用的协议如:MIPI、LVDS等协议,以实现标准图像数据流转换,其中摄像头8位数据转16位代码如下

    1. module cmos_8_16bit(
    2. input rst,
    3. input pclk,
    4. input [7:0] pdata_i,
    5. input de_i,
    6. output reg[15:0] pdata_o,//转换成16位RGB565图像数据
    7. output reg hblank,
    8. output reg de_o
    9. );
    10. reg[7:0] pdata_i_d0;
    11. reg[11:0] x_cnt;
    12. always@(posedge pclk)
    13. begin
    14. pdata_i_d0 <= pdata_i;
    15. end
    16. always@(posedge pclk or posedge rst)
    17. begin
    18. if(rst)
    19. x_cnt <= 12'd0;
    20. else if(de_i)
    21. x_cnt <= x_cnt + 12'd1;
    22. else
    23. x_cnt <= 12'd0;
    24. end
    25. always@(posedge pclk or posedge rst)
    26. begin
    27. if(rst)
    28. de_o <= 1'b0;
    29. else if(de_i && x_cnt[0])
    30. de_o <= 1'b1;
    31. else
    32. de_o <= 1'b0;
    33. end
    34. always@(posedge pclk or posedge rst)
    35. begin
    36. if(rst)
    37. hblank <= 1'b0;
    38. else
    39. hblank <= de_i;
    40. end
    41. always@(posedge pclk or posedge rst)
    42. begin
    43. if(rst)
    44. pdata_o <= 16'd0;
    45. else if(de_i && x_cnt[0])
    46. pdata_o <= {pdata_i_d0,pdata_i};
    47. else
    48. pdata_o <= 16'd0;
    49. end
    50. endmodule

    六、摄像头写数据请求

    1. module cmos_write_req_gen(
    2. input rst,
    3. input pclk,
    4. input cmos_vsync,
    5. output reg write_req,
    6. output reg[1:0] write_addr_index,
    7. output reg[1:0] read_addr_index,
    8. input write_req_ack
    9. );
    10. reg cmos_vsync_d0;
    11. reg cmos_vsync_d1;
    12. always@(posedge pclk or posedge rst)
    13. begin
    14. if(rst == 1'b1)
    15. begin
    16. cmos_vsync_d0 <= 1'b0;
    17. cmos_vsync_d1 <= 1'b0;
    18. end
    19. else
    20. begin
    21. cmos_vsync_d0 <= cmos_vsync;
    22. cmos_vsync_d1 <= cmos_vsync_d0;
    23. end
    24. end
    25. always@(posedge pclk or posedge rst)
    26. begin
    27. if(rst == 1'b1)
    28. write_req <= 1'b0;
    29. else if(cmos_vsync_d0 == 1'b1 && cmos_vsync_d1 == 1'b0)
    30. write_req <= 1'b1;
    31. else if(write_req_ack == 1'b1)
    32. write_req <= 1'b0;
    33. end
    34. always@(posedge pclk or posedge rst)
    35. begin
    36. if(rst == 1'b1)
    37. write_addr_index <= 2'b0;
    38. else if(cmos_vsync_d0 == 1'b1 && cmos_vsync_d1 == 1'b0)
    39. write_addr_index <= write_addr_index + 2'd1;
    40. end
    41. always@(posedge pclk or posedge rst)
    42. begin
    43. if(rst == 1'b1)
    44. read_addr_index <= 2'b0;
    45. else if(cmos_vsync_d0 == 1'b1 && cmos_vsync_d1 == 1'b0)
    46. read_addr_index <= write_addr_index;
    47. end
    48. endmodule

    七、顶层文件编写

    1. `timescale 1ns / 1ps
    2. module sdram_ov7670_vga
    3. (
    4. //global clock 50MHz
    5. //input clk_27, //27MHz
    6. input CLOCK,
    7. //input rst_n, //global reset
    8. //sdram control
    9. output S_CLK, //sdram clock
    10. output S_CKE, //sdram clock enable
    11. output S_NCS, //sdram chip select
    12. output S_NWE, //sdram write enable
    13. output S_NCAS, //sdram column address strobe
    14. output S_NRAS, //sdram row address strobe
    15. output[1:0] S_DQM, //sdram data enable
    16. output [1:0] S_BA, //sdram bank address
    17. output [12:0] S_A, //sdram address
    18. inout [15:0] S_DB, //sdram data
    19. //VGA port
    20. output VGA_HSYNC, //horizontal sync
    21. output VGA_VSYNC, //vertical sync
    22. output [15:0] VGAD, //VGA data
    23. //cmos interface
    24. output CMOS_SCLK, //cmos i2c clock
    25. inout CMOS_SDAT, //cmos i2c data
    26. input CMOS_VSYNC, //cmos vsync
    27. input CMOS_HREF, //cmos hsync refrence
    28. input CMOS_PCLK, //cmos pxiel clock
    29. output CMOS_XCLK, //cmos externl clock
    30. input [7:0] CMOS_DB, //cmos data
    31. // output cmos_rst_n, //cmos reset
    32. // output cmos_pwdn, //cmos pwer down
    33. output [3:0] LED //led data input
    34. );
    35. assign rst_n = 1'b1;
    36. //---------------------------------------------
    37. wire clk_camera;
    38. wire clk_vga; //vga clock
    39. wire clk_ref; //sdram ctrl clock
    40. wire clk_refout; //sdram clock output
    41. wire sys_rst_n; //global reset
    42. system_ctrl u_system_ctrl
    43. (
    44. .clk (CLOCK), //global clock 50MHZ
    45. .rst_n (rst_n), //external reset
    46. .sys_rst_n (sys_rst_n), //global reset
    47. .clk_c0 (clk_camera), //13MHz
    48. .clk_c1 (clk_vga), //25MHz
    49. .clk_c2 (clk_ref), //100MHz
    50. .clk_c3 (clk_refout) //100MHz
    51. );
    52. //-----------------------------
    53. wire [7:0] I2C_RDATA; //i2c register data
    54. wire [7:0] LUT_INDEX; //lut index
    55. wire Config_Done; //I2C config done
    56. I2C_AV_Config u_I2C_AV_Config
    57. (
    58. //Global clock
    59. .iCLK (clk_vga), //25MHz
    60. .iRST_N (sys_rst_n), //Global Reset
    61. //I2C Side
    62. .I2C_SCLK (CMOS_SCLK), //I2C CLOCK
    63. .I2C_SDAT (CMOS_SDAT), //I2C DATA
    64. //CMOS Signal
    65. .Config_Done (Config_Done), //I2C Config done
    66. .I2C_RDATA (I2C_RDATA), //CMOS ID
    67. .LUT_INDEX ()//(LUT_INDEX) //ID Index
    68. );
    69. assign led_data = I2C_RDATA; //diaplay I2C_RDATA
    70. //-----------------------------------------------
    71. //Seg7_lut u5 ( LUT_INDEX[7:4], oSEG5 );
    72. //Seg7_lut u4 ( LUT_INDEX[3:0], oSEG4 );
    73. //Seg7_lut u1 ( I2C_RDATA[7:4], oSEG1 );
    74. //Seg7_lut u0 ( I2C_RDATA[3:0], oSEG0 );
    75. //-----------------------------------------------
    76. wire frame_valid; //data valid, or address restart
    77. wire [7:0] cmos_fps_data; //cmos frame rate
    78. CMOS_Capture u_CMOS_Capture
    79. (
    80. //Global Clock
    81. .iCLK (clk_camera), //24MHz
    82. .iRST_N (sys_rst_n), //global reset
    83. //I2C Initilize Done
    84. .Init_Done (Config_Done & sdram_init_done), //Init Done
    85. //Sensor Interface
    86. .CMOS_RST_N (),//(cmos_rst_n), //cmos work state
    87. .CMOS_PWDN (),//(cmos_pwdn), //cmos power on
    88. .CMOS_XCLK (CMOS_XCLK), //cmos
    89. .CMOS_PCLK (CMOS_PCLK), //25MHz
    90. .CMOS_iDATA (CMOS_DB), //CMOS Data
    91. .CMOS_VSYNC (CMOS_VSYNC), //L: Vaild
    92. .CMOS_HREF (CMOS_HREF), //H: Vaild
    93. //Ouput Sensor Data
    94. .CMOS_oCLK (sys_we), //Data PCLK
    95. .CMOS_oDATA (sys_data_in), //16Bits RGB
    96. .CMOS_VALID (frame_valid), //Data Enable
    97. .CMOS_FPS_DATA ()//(cmos_fps_data) //cmos frame rate
    98. );
    99. //Seg7_lut u7 ( cmos_fps_data[7:4], oSEG7 ); //fsp rate
    100. //Seg7_lut u6 ( cmos_fps_data[3:0], oSEG6 ); //fps rate
    101. //wire [8:0] alpha_data; //alpha adjust data
    102. //assign led_data = alpha_data; //diaplay alpha data
    103. //alpha_control u_alpha_control
    104. //(
    105. // .clk (clk_vga), //vga clock
    106. // .rst_n (sys_rst_n), //global reset
    107. //
    108. // .key_data (key_data), //key data
    109. // .alpha_data (alpha_data) //aplha adjust data
    110. //);
    111. //-------------------------------------
    112. //sdram vga ctrl system
    113. wire sys_we; //system data write enable
    114. wire [15:0] sys_data_in; //system data input
    115. wire sdram_init_done; //sdram init done
    116. sdram_vga_top u_sdram_vga_top
    117. (
    118. //global clock
    119. .clk_vga (clk_vga), //vga clock
    120. .clk_ref (clk_ref), //sdram ctrl clock
    121. .clk_refout (clk_refout), //sdram clock output
    122. .rst_n (sys_rst_n), //global reset
    123. //sdram control
    124. .sdram_clk (S_CLK), //sdram clock
    125. .sdram_cke (S_CKE), //sdram clock enable
    126. .sdram_cs_n (S_NCS), //sdram chip select
    127. .sdram_we_n (S_NWE), //sdram write enable
    128. .sdram_cas_n (S_NCAS), //sdram column address strobe
    129. .sdram_ras_n (S_NRAS), //sdram row address strobe
    130. .sdram_udqm (S_DQM[1]), //sdram data enable (H:8)
    131. .sdram_ldqm (S_DQM[0]), //sdram data enable (L:8)
    132. .sdram_ba (S_BA), //sdram bank address
    133. .sdram_addr (S_A), //sdram address
    134. .sdram_data (S_DB), //sdram data
    135. //lcd port
    136. .lcd_dclk (), //lcd pixel clock
    137. .lcd_hs (VGA_HSYNC), //lcd horizontal sync
    138. .lcd_vs (VGA_VSYNC), //lcd vertical sync
    139. .lcd_sync (),//(lcd_sync), //lcd sync
    140. .lcd_blank (), //lcd blank(L:blank)
    141. .lcd_red (VGAD[15:11]), //lcd red data
    142. .lcd_green (VGAD[10:5]), //lcd green data
    143. .lcd_blue (VGAD[4:0]), //lcd blue data
    144. //user interface
    145. .clk_write (CMOS_PCLK), //fifo write clock
    146. .sys_we (sys_we), //fifo write enable
    147. .sys_data_in (sys_data_in), //fifo data input
    148. .sdram_init_done (sdram_init_done), //sdram init done
    149. .frame_valid (frame_valid) //frame valid
    150. );
    151. endmodule

    八、效果

  • 相关阅读:
    Python 编程基础 | 第一章-预备知识 | 1.1、Python简介
    【leetcode】【2022/10/19】1700. 无法吃午餐的学生数量
    用c++实现五子棋小游戏
    鸿蒙面试心得
    Python字符串格式化
    【Java 进阶篇】JDBC ResultSet 类详解
    js-map方法中调用服务器接口
    Python数据容器之(元组)
    大学生值得珍藏的实用网站推荐
    git stash 是一个在Git中用于保存当前工作目录和暂存区的临时状态的命令
  • 原文地址:https://blog.csdn.net/mxh3600/article/details/126733682