Day5-OV5640摄像头

今天任务:了解这个摄像头的传输协议&接通实现在屏幕上接收摄像头采集到的图像

image

 将采集到的数据 通过image array转换成10bit的ADC,再进行一个ISP的寄存器设置,再转换成摄像头可以识别的图像数据

OV5640摄像头主要特性:

1. 支持500W像素

2. 今天玩的这玩意,不是标准的720p,所以会有黑边

3. 是标准的串行SCCB·接口,与IIC接口相同

4. 在720p下能实现60帧60fps


 引脚介绍

Power Down是高有效输入信号(不工作的时候是低电平,工作时候高电平)

Reset 是低有效输入信号

SIOC和SIOD是他的SCCB的时序,两个数据传输的接口,跟IIC的时序差不多

SDA负责传输数据,SCL负责输入时钟

Vsync是场同步信号,HREF是反向行同步信号(hsync取反后的信号)

XVCLK是系统输入时钟,PCLK是像素时钟

D0-D7是摄像头采集数据传输的接口


这个路径里面是有用的引脚信息:

  ZYNQ资料/01_原理图/EBAZ4205_EXBOARD_20200313.pdf

image


 上电时序

上电时序指   硬件芯片从完全断电状态到进入正常工作状态,各个控制信号必须遵循的“先后顺序”和“时间间隔”

如果这个顺序不对(比如复位拉早了,或者掉电没关掉),芯片内部的状态机可能会错乱,导致摄像头不出图、系统不启动,甚至损伤芯片

image

 其中这里D0Y00和AVDD是内部已经配置好了的,无需改动(毕竟也没有这俩的对应接口信息)

所以下面看这个PWDN  RESETB  XVCLK

图片下面文案说明了这几个t1,t2...的要求

相应的,可以直接看总结资料里的中文版时序图

image

 这里明确说明了t2,t3,t4的要求,于是需要三个计数器去计时

实际会让t2为6ms,t3为2ms这样

这里是对应关系,输入时钟是50兆Hz,也就是20纳秒,转到6ms就是30万次

image 


 SCCB时序介绍(也就当是IIC了)

SIO_C是一个时钟,周期性变化,最小周期$t_syc$是10微秒$μs$,即最大频率为100K,所以需要在代码里面要小于100K

SIO_D是传的数据

SCCB的传输阶段介绍

先传ID地址,再传一段子地址/寄存器地址,再写

再传,再写  再传,再写

ID地址是这个摄像头的地址,然后Sub是寄存器的地址

image

下图讲了,

芯片内部0x3100编号的寄存器用来存放 SCCB 总线通信的设备 ID,上电默认值是0x78,这个数值就是 SCCB 时序里的 ID Address。

从级ID是0x78

image

 

 

 

image

 

 

bbbbebb6b2f0178239a946da3d3db1ac_720


 

提示词1用于控制OV5640图像传感器的上电时序

“在FPGA内部产生符合传感器手册要求的硬件控制信号,确保摄像头能正常启动并进入可配置状态。

也就说,让他内部自己有一个时间控制系统,使得满足上电时序要求,并令ov5640_pwdn 和 ov5640_rst_n 这两根线能跑起来,最终实现摄像头的启动

其中,

  ov5640_pwdn:在6ms到的那一刻,从高电平 “掉下来” (拉低),让芯片通电。

  ov5640_rst_n:再过2ms,从低电平 “弹上去” (拉高),让芯片开始复位初始化。

  这两根线在此之后就不再变化了(保持固定电平),直到板子彻底断电。

  注意:这个模块并没有让摄像头直接出图像,它的目标就是 “启动”

----pow ctrl
请用 Verilog-2001 编写可综合的 OV5640 上电时序控制模块。

模块接口必须完全如下:

module power_ctrl(
    input  sclk,
    input  s_rst_n,
    output ov5640_pwdn,
    output ov5640_rst_n,
    output power_done
);

要求:

1. sclk频率为50MHz,周期20ns。
2. AVDD和DOVDD已经由硬件稳定提供,不需要控制。
3. s_rst_n为异步低电平复位。
4. 复位期间:
   ov5640_pwdn=1;
   ov5640_rst_n=0;
   power_done=05. s_rst_n释放后等待6ms,将ov5640_pwdn拉低。
6. PWDN拉低后等待2ms,将ov5640_rst_n拉高。
7. RESET释放后等待21ms,将power_done拉高。
8. power_done拉高后保持为1,用于启动后续SCCB配置。
9. 使用三个计数器依次完成时序:
   6ms=300000个时钟;
   2ms=100000个时钟;
   21ms=1050000个时钟。
10. 计数器达到目标后停止计数,避免溢出。
11. 不需要控制XVCLK。
12. 代码必须可综合,时序逻辑使用非阻塞赋值。

只输出完整的Verilog代码。
提示词1

提示词2是 对寄存器进行初始化配置

“利用时钟线SCL的时间控制,完成对寄存器状态的设置与读取,使得后续可以对寄存器进行调控,从而在宏观上体现为对摄像头的调整”

寄存器是一个个小的运行模块,控制存储器“被写”,状态存储器“被读”,通过在微观上对这些存储器的调整,才能在宏观上看到对摄像头的调整

请用 Verilog-2001 编写可综合的 OV5640 SCCB/I²C 控制器。

模块接口必须完全如下:

module ov5640_iic(
    input             sclk,
    input             s_rst_n,
    output reg        iic_scl,
    inout             iic_sda,
    input             start,
    input      [31:0] wdata,
    output reg [7:0]  riic_data,
    output reg        busy
);

重要条件:

1. 输入 sclk 已经由 50MHz 分频得到:
   sclk = 50MHz / 512 = 97.65625kHz。

2. busy期间每个sclk上升沿翻转一次iic_scl,使:
   iic_scl ≈ 48.828kHz。

3. wdata格式:
   [31:24]:设备地址字节,最低位为读写位;
   [23:8]:16位寄存器地址;
   [7:0]:写数据。
   OV5640写地址通常为0x78,读地址为0x79。

4. 写操作:
   START→0x78→ACK→地址高字节→ACK→地址低字节→ACK→数据→ACK→STOP。

5. 读操作必须使用:
   START→0x78→ACK→地址高字节→ACK→地址低字节→ACK
   →STOP→START→0x79→ACK→读取8位数据→NACK→STOP。
   注意这里要求STOP后重新START,不要只使用repeated START。

6. start为单个sclk周期脉冲。仅在busy=0时接受start,并立即锁存wdata;busy期间忽略新的start。

7. 数据MSB优先。SDA只能在SCL低电平时改变,START和STOP除外。

8. ACK和读取数据期间必须释放SDA:
   assign iic_sda = sda_oe ? sda_out : 1'bz;

9. 读取数据时,在SCL高电平稳定阶段采样SDA,最终保存到riic_data。

10. 读取一个字节后,主机发送NACK,再产生STOP。

11. 空闲时:
    iic_scl=1、SDA释放、busy=012. s_rst_n为异步低电平复位。

13. ACK可以暂时不判断是否有效,但ACK周期必须正确释放SDA。请在代码中预留ACK检测位置。

14. 组合逻辑必须有默认赋值,避免锁存器;时序逻辑使用非阻塞赋值。

15. 模块将直接替换现有工程中的同名模块,所以不能修改端口、位宽、信号方向和wdata编码。

请检查状态跳转,确保写操作发送数据后才STOP,读操作发送0x79并收到ACK后才进入数据接收。

只输出完整的Verilog代码。
提示词2

提示词3用于 让ov5640_cfg掌握控制寄存器的权利,作为总指挥,叫下属去控制寄存器

最终实现对寄存器的调控

写一个 Verilog 模块,用于上电后通过 I2C 控制器自动对 OV5640 摄像头传感器进行寄存器初始化配置。

模块名为 ov5640_cfg,接口如下:

输入:
  sclk        - 系统时钟,约 50MHz,驱动状态机和 I2C 时序
  s_rst_n     - 异步复位,低有效
  estart      - 调试用外部启动信号,在自动配置完成后可手动发起 I2C 传输
  ewdata[31:0] - 调试用外部写入数据,格式为 {8bit设备地址, 16bit寄存器地址, 8bit寄存器值}

输出:
  iic_scl     - I2C 时钟线,由内部 I2C 控制器驱动
  iic_sda     - I2C 数据线,双向 inout
  riic_data[7:0] - I2C 读回数据

内部架构:

1. 定义一个 localparam ANUM = 304,表示配置表中寄存器的数量。

2. 用一个 packed 数组 cfg_array[ANUM-1:0],每个元素 32bit 宽,格式为:
   {8'h78, 16'hREG_ADDR, 8'hREG_VAL}
   其中 8'h78 是 OV5640 的 I2C 写地址。用 304 条 assign 语句逐条填充这个数组,
   每行注释 // ID    REG_ADDR  REG_VAL。这些是 OV5640 的初始化寄存器序列,
   包括 PLL 配置、时钟分频、输出格式(RGB565)、分辨率(1024x720)、DSP 参数、
   AWB/AEC 等共约 300 条寄存器写入。

3. 设计一个自动状态机:
   - cfg_index(9bit 寄存器):当前已发送的配置条目计数
   - start(1bit 寄存器):发往 I2C 控制器的启动脉冲
   - cfg_index == 0 时产生第一个 start 脉冲
   - 检测 I2C 控制器的 busy 信号下降沿(busy_neg),表示上一次传输完成,
     此时若 cfg_index < ANUM 则再次产生 start 脉冲,cfg_index 加 1
   - cfg_index 达到 ANUM 后停止,进入延时等待

4. 配置完成后的延时:
   - cnt_200us(16bit 寄存器):在 cfg_index >= ANUM 后开始递增计数
   - localparam DELAY_200US = 10000(对应 sclk 频率下的约 200µs)
   - 当 cnt_200us >= DELAY_200US 时,cfg_done 置 1

5. 双模式切换:
   - cfg_done == 0 时:iic_start = start,iic_wdata = cfg_array[cfg_index](自动模式)
   - cfg_done == 1 时:iic_start = estart,iic_wdata = ewdata(调试模式,允许外部手动读写寄存器)

6. busy_neg 的检测:
   - 用 3bit 移位寄存器 busy_arr 对 busy 信号打两拍
   - busy_neg = busy_arr[2] & ~busy_arr[1](检测下降沿)

7. 例化一个 ov5640_iic 模块,连接 sclk、s_rst_n、iic_scl、iic_sda、
   start(iic_start)、wdata(iic_wdata)、riic_data、busy。
提示词3

提示词4用于

请用 Verilog 编写一个 ov5640_data 模块,用于处理 OV5640 摄像头传感器的输出数据。

模块接口如下:
  input           s_rst_n          // 系统复位(低有效)
  input           ov5640_pclk      // OV5640 像素时钟
  input           ov5640_href      // OV5640 行参考信号
  input           ov5640_vsync     // OV5640 场同步信号
  input   [7:0]   ov5640_data      // OV5640 8位像素数据
  output  wire    m_vsync          // 输出场同步
  output  wire    m_href           // 输出行参考
  output  wire    [15:0] m_data    // 输出16位拼接数据
  output  reg     m_wr_en          // 输出写使能

内部寄存器要求使用以下命名:
  reg             ov5640_vsync_r1  // vsync打一拍
  reg     [3:0]   frame_cnt        // 帧计数器
  reg     [7:0]   ov5640_data_r1   // 上一字节数据
  wire            ov5640_vsync_pos // vsync上升沿检测
  wire            frame_vaild      // 帧有效标志

功能要求:
1. 在 ov5640_pclk 时钟域下,对 ov5640_vsync 和 ov5640_data 各打一拍。
2. 通过 ov5640_vsync 的上升沿检测(ov5640_vsync & ~ov5640_vsync_r1),在系统复位后计数帧数。
3. frame_cnt 在 frame_vaild 为低且 vsync 上升沿到来时加 1,复位清零。
4. frame_vaild 在前 10 帧期间为低(frame_cnt < 10),之后拉高。
5. m_wr_en:当 frame_vaild 且 ov5640_href 有效时,每个 pclk 翻转一次(乒乓写使能);否则为 06. m_data:将上一拍数据 ov5640_data_r1 与当前 ov5640_data 拼接为 16 位输出(先到的字节在高位)。
7. m_vsync / m_href:仅在 frame_vaild 有效时透传 ov5640_vsync / ov5640_href,否则输出 08. 复位为异步复位,低有效。

请按上述要求输出完整模块代码。
提示词4

 

posted @ 2026-07-24 15:26  little_sheep_xiaoen  阅读(23)  评论(0)    收藏  举报