FPGA之OV7725摄像头采集与VGA显示实验--3--摄像头配置模块实现(Verilog代码)

发布于:2022-12-31 ⋅ 阅读:(457) ⋅ 点赞:(0)

        上一节向大家介绍了摄像头配置的SCCB协议发送器的Verilog实现,这一节则向大家介绍配置信息存储模块:ovcfg_info的Verilog实现。

学习目标

  • 配置模块Verilog实现

 系统框图

 

        从图中我们可以看到,ov7725_cfg模块的作用类似一个存储器,根据SCCB模块输出的 i2c_clk 与done,确定输送进SCCB模块地址接口和数据接口的数据。

        因此我们可以有一个思路出现:首先数据的更新要赶在TRAN1状态之前,而恰好在STOP3状态结束的后四分之一周期,done信号发生一个跳变。因此可以用触发器检测done信号对数据进行计数。

代码实现

接口

sys_resetn 复位信号
i2c_clk 触发时钟信号
done 配置完成信号
i2c_addr 地址数据输出
i2c_data 配置参数输出

Verilog代码

/*
 By WWD 2022/9/3
  OV7725 cfg  V1.0

转载请注明出处!
*/
module ovcfg_info(
input wire i2c_clk,
input wire sys_resetn,
input wire done,

output wire [7:0] i2c_addr,
output wire [7:0] i2c_data
);

reg[6:0] info_cnt;

wire[15:0] cfg_data_reg [68:0];

assign  cfg_data_reg[00]  =       {8'h3d,  8'h03};
assign  cfg_data_reg[01]  =       {8'h15,  8'h00};
assign  cfg_data_reg[02]  =       {8'h17,  8'h23};
assign  cfg_data_reg[03]  =       {8'h18,  8'ha0};
assign  cfg_data_reg[04]  =       {8'h19,  8'h07};
assign  cfg_data_reg[05]  =       {8'h1a,  8'hf0};
assign  cfg_data_reg[06]  =       {8'h32,  8'h00};
assign  cfg_data_reg[07]  =       {8'h29,  8'ha0};
assign  cfg_data_reg[08]  =       {8'h2a,  8'h00};
assign  cfg_data_reg[09]  =       {8'h2b,  8'h00};
assign  cfg_data_reg[10]  =       {8'h2c,  8'hf0};
assign  cfg_data_reg[11]  =       {8'h0d,  8'h41};
assign  cfg_data_reg[12]  =       {8'h11,  8'h00};
assign  cfg_data_reg[13]  =       {8'h12,  8'h06};
assign  cfg_data_reg[14]  =       {8'h0c,  8'hd0};
assign  cfg_data_reg[15]  =       {8'h42,  8'h7f};
assign  cfg_data_reg[16]  =       {8'h4d,  8'h09};
assign  cfg_data_reg[17]  =       {8'h63,  8'hf0};
assign  cfg_data_reg[18]  =       {8'h64,  8'hff};
assign  cfg_data_reg[19]  =       {8'h65,  8'h00};
assign  cfg_data_reg[20]  =       {8'h66,  8'h00};
assign  cfg_data_reg[21]  =       {8'h67,  8'h00};
assign  cfg_data_reg[22]  =       {8'h13,  8'hff};
assign  cfg_data_reg[23]  =       {8'h0f,  8'hc5};
assign  cfg_data_reg[24]  =       {8'h14,  8'h11};
assign  cfg_data_reg[25]  =       {8'h22,  8'h98};
assign  cfg_data_reg[26]  =       {8'h23,  8'h03};
assign  cfg_data_reg[27]  =       {8'h24,  8'h40};
assign  cfg_data_reg[28]  =       {8'h25,  8'h30};
assign  cfg_data_reg[29]  =       {8'h26,  8'ha1};
assign  cfg_data_reg[30]  =       {8'h6b,  8'haa};
assign  cfg_data_reg[31]  =       {8'h13,  8'hff};
assign  cfg_data_reg[32]  =       {8'h90,  8'h0a};
assign  cfg_data_reg[33]  =       {8'h91,  8'h01};
assign  cfg_data_reg[34]  =       {8'h92,  8'h01};
assign  cfg_data_reg[35]  =       {8'h93,  8'h01};
assign  cfg_data_reg[36]  =       {8'h94,  8'h5f};
assign  cfg_data_reg[37]  =       {8'h95,  8'h53};
assign  cfg_data_reg[38]  =       {8'h96,  8'h11};
assign  cfg_data_reg[39]  =       {8'h97,  8'h1a};
assign  cfg_data_reg[40]  =       {8'h98,  8'h3d};
assign  cfg_data_reg[41]  =       {8'h99,  8'h5a};
assign  cfg_data_reg[42]  =       {8'h9a,  8'h1e};
assign  cfg_data_reg[43]  =       {8'h9b,  8'h3f};
assign  cfg_data_reg[44]  =       {8'h9c,  8'h25};
assign  cfg_data_reg[45]  =       {8'h9e,  8'h81};
assign  cfg_data_reg[46]  =       {8'ha6,  8'h06};
assign  cfg_data_reg[47]  =       {8'ha7,  8'h65};
assign  cfg_data_reg[48]  =       {8'ha8,  8'h65};
assign  cfg_data_reg[49]  =       {8'ha9,  8'h80};
assign  cfg_data_reg[50]  =       {8'haa,  8'h80};
assign  cfg_data_reg[51]  =       {8'h7e,  8'h0c};
assign  cfg_data_reg[52]  =       {8'h7f,  8'h16};
assign  cfg_data_reg[53]  =       {8'h80,  8'h2a};
assign  cfg_data_reg[54]  =       {8'h81,  8'h4e};
assign  cfg_data_reg[55]  =       {8'h82,  8'h61};
assign  cfg_data_reg[56]  =       {8'h83,  8'h6f};
assign  cfg_data_reg[57]  =       {8'h84,  8'h7b};
assign  cfg_data_reg[58]  =       {8'h85,  8'h86};
assign  cfg_data_reg[59]  =       {8'h86,  8'h8e};
assign  cfg_data_reg[60]  =       {8'h87,  8'h97};
assign  cfg_data_reg[61]  =       {8'h88,  8'ha4};
assign  cfg_data_reg[62]  =       {8'h89,  8'haf};
assign  cfg_data_reg[63]  =       {8'h8a,  8'hc5};
assign  cfg_data_reg[64]  =       {8'h8b,  8'hd7};
assign  cfg_data_reg[65]  =       {8'h8c,  8'he8};
assign  cfg_data_reg[66]  =       {8'h8d,  8'h20};
assign  cfg_data_reg[67]  =       {8'h0e,  8'h65};
assign  cfg_data_reg[68]  =       {8'h09,  8'h00};

always@(posedge i2c_clk or negedge sys_resetn)begin
if(sys_resetn == 1'b0)
    info_cnt <= 7'd0;
else if(info_cnt == 7'd69)
    info_cnt <= 7'd0;
else if(done == 1'b1)
    info_cnt <= info_cnt +7'd1;
end

assign i2c_addr = cfg_data_reg[info_cnt][15:8];
assign i2c_data = cfg_data_reg[info_cnt][7:0];

endmodule

测试验证

TB文件

/*
By WWD 2022/9/3
转载请注明出处
*/
`timescale 1ns/1ns

module tb_topovcfg();

reg sys_reset_n;
reg sys_clk;
reg i2c_start;

wire i2c_clk;
wire done;
wire [7:0] i2c_addr;
wire [7:0] i2c_data;

initial begin

sys_reset_n = 1'b0;
sys_clk = 1'b1;
i2c_start = 1'b0;
#20
 i2c_start = 1'b1;
 sys_reset_n = 1'b1;

 /*#2000
 byte_addr = 8'b1000_1111;
 i2c_data = 8'b1111_0100;*/
end

always #10 sys_clk = ~sys_clk; //50MHz时钟

SCCB u1(
.sys_reset_n(sys_reset_n),
.sys_clk(sys_clk),
.i2c_start(i2c_start),
.byte_addr(i2c_addr),
.i2c_data(i2c_data),
.i2c_clk(i2c_clk),
.done(done),
.SDA(),
.SCL()
); 

ovcfg_info u2(
.i2c_clk(i2c_clk),
.sys_resetn(sys_reset_n),
.done(done),
.i2c_addr(i2c_addr),
.i2c_data(i2c_data)
);

endmodule

Modelsim波形图

 

         我们随意验证第一组数据与第二组数据:

assign  cfg_data_reg[00]  =       {8'h3d,  8'h03};
assign  cfg_data_reg[01]  =       {8'h15,  8'h00};

发现完全符合要求! 

 并且可以看到,当计数到68后,计数器归零,并且对应数据完全正确。

        这里留给大家一个小任务,请大家改造这个模块,使得配置的过程只经历一遍。

下一节,我们将介绍如何设计OV7725的数据采集模块,敬请期待!

本文含有隐藏内容,请 开通VIP 后查看