|
摄像头配置模块的功能:根据摄像头配置指令模块ov7670_para的操作,产生对应的写寄存器命令、读寄存器命令给下游模块。具体功能如下:
1. 根据ov7670_para的参数,逐个配置或者读取寄存器; 2. 所有寄存器操作完成后,产生完成指示信号。
通过代码:`include“ov7670_para.v”,可以把边缘检测摄像头配置指令模块ov7670_para包含进本模块。
一、设计架构
摄像头配置模块采用两个计数器的架构:计数器reg_cnt表示的是对要配置的164个寄存器进行计数,计数器rw_cnt表示判断写数据还是读数据的时序。例如,在写时序时,判断参数是否要写寄存器,如果要写寄存器,此时才产生写命令,如果参数是不要写寄存器,此时也不产生写命令。其结构图如下: 计数器rw_cnt:寄存器读写时序计数器。用来区分“向寄存器写数据”还是“从寄存器读数据”这两个状态。当其为0时,表示判断是否写寄存器的时序,当其为1时,表示判断是否读寄存器的时序。不管读写属性参数是什么,每个寄存器都会占有这两个时序。 计数器reg_cnt:寄存器顺序计数器。对摄像头164个寄存器进行排序,按顺序配置各个寄存器。
二、信号意义
信号
| 类型
| 意义
| clk
| 输入信号
| 时钟信号
| rst_n
| 输入信号
| 复位信号,低电平有效。
| config_en
| 输入信号
| 配置开始指示信号。
当接收到该信号为1时,就开始对寄存器进行配置。
| rdy
| 输入信号
| 下游sccb模块准备好指示信号。
0:下游sccb模块正忙,不能向sccb发送配置指令;
1:下游sccb模块空闲,可以向sccb发送配置指令。
| rdata
| 输入信号
| 从 SCCB模块返回的读寄存器数据。
此工程没有用到。
| rdata_vld
| 输入信号
| 从SCCB模块返回的数据有效指示信号。
此工程没有用到。
| wdata
| 输出信号
| 向下游SCCB模块配置寄存器的数据,当写寄存器命令有效时,此数据才有效。
设计逻辑:该数据取自摄像头配置指令的低8位,表示向需要配置的摄像头寄存器中写入的数据。
| addr
| 输出信号
| 配置寄存器的读写地址,当写寄存器命令或者读寄存器命令有效时,此数据才有效。
设计逻辑:无论读还是写寄存器,其值均来自于摄像头配置指令的第9位到第16位,表示需要操作的摄像头寄存器的地址。
| wr_en
| 输出信号
| 写寄存器命令。
设计逻辑:在“判断是否写时序”的时候,如果在配置指令中次高位为1,此时写寄存器命令有效,否则为0。
| rd_en
| 输出信号
| 读寄存器命令。
设计逻辑:在“判断是否读时序”的时候,如果在配置指令中最高位为1,此时读寄存器命令有效,否则为0。
| cmos_en
| 输出信号
| 下游摄像头图像采集cmos_capture模块使能信号。
复位后为0;
设计逻辑:当164个摄像头寄存器配置完成后为1,指示下游cmos_capture模块开始图像采集。
| pwdn
| 输出信号
| 此工程没有用到。
| reg_cnt
| 内部信号
| 寄存器顺序计数器。
表示配置164个寄存器的顺序。
| add_reg_cnt
| 内部信号
| 寄存器顺序计数器加一条件。
每当判断完寄存器读写时序后,开始下一个寄存器的配置。
| end_reg_cnt
| 内部信号
| 寄存器顺序计数器结束条件。
表示按顺序配置完164个寄存器。
| flag_add
| 内部信号
| 摄像头寄存器配置状态指示信号。
0:非配置寄存器状态;
1:配置寄存器状态。
| add_wdata
| 内部信号
| 摄像头寄存器配置指令。
具体参数见摄像头配置指令模块ov7670_para。
| rw_cnt
| 内部信号
| 寄存器读写时序计数器。
用来区分“向寄存器写数据”还是“从寄存器读数据”这两个状态。
0:表示判断是否写寄存器的时序;
1:表示判断是否读寄存器的时序。
| add_rw_cnt
| 内部信号
| 寄存器读写时序加一条件。
当处于寄存器配置状态并且下游sccb模块空闲,开始判断是否写/读寄存器的时序。
| end_rw_cnt
| 内部信号
| 寄存器读写时序结束条件。
表示已经判断完是否写/读寄存器时序。
|
三、参考代码
下面展出本模块的设计,欢迎进一步交流,如果需要项目完整源代码,欢迎联系。 1
| 2
| 3
| 4
| 5
| 6
| 7
| 8
| 9
| 10
| 11
| 12
| 13
| 14
| 15
| 16
| 17
| 18
| 19
| 20
| 21
| 22
| 23
| 24
| 25
| 26
| 27
| 28
| 29
| 30
| 31
| 32
| 33
| 34
| 35
| 36
| 37
| 38
| 39
| 40
| 41
| 42
| 43
| 44
| 45
| 46
| 47
| 48
| 49
| 50
| 51
| 52
| 53
| 54
| 55
| 56
| 57
| 58
| 59
| 60
| 61
| 62
| 63
| 64
| 65
| 66
| 67
| 68
| 69
| 70
| 71
| 72
| 73
| 74
| 75
| 76
| 77
| 78
| 79
| 80
| 81
| 82
| 83
| 84
| 85
| 86
| 87
| 88
| 89
| 90
| 91
| 92
| 93
| 94
| 95
| 96
| 97
| 98
| 99
| 100
| 101
| 102
| 103
| 104
| 105
| 106
| 107
| 108
| 109
| 110
| 111
| 112
| 113
| 114
| 115
| 116
| 117
| 118
| 119
| 120
| 121
| 122
| 123
| 124
| 125
| 126
| 127
| 128
| 129
| 130
| 131
| 132
| 133
| 134
| 135
| 136
| 137
| 138
| 139
| 140
| 141
| 142
| 143
| 144
| 145
| 146
| 147
| 148
| 149
| 150
| 151
| 152
| 153
| 154
| 155
| 156
| 157
| 158
|
| module ov7670_config(
clk ,
rst_n ,
config_en ,
rdy ,
rdata ,
rdata_vld ,
wdata ,
addr ,
wr_en ,
rd_en ,
cmos_en ,
pwdn
);
parameter DATA_W = 8;
parameter RW_NUM = 2;
input clk ; //50Mhz
input rst_n ;
input config_en;
input rdy ;
input [DATA_W-1:0] rdata ;
input rdata_vld;
output[DATA_W-1:0] wdata ;
output[DATA_W-1:0] addr ;
output cmos_en ;
output wr_en ;
output rd_en ;
output pwdn ;
reg [DATA_W-1:0] wdata ;
reg [DATA_W-1:0] addr ;
reg cmos_en ;
reg wr_en ;
reg rd_en ;
reg [8 :0] reg_cnt ;
wire add_reg_cnt/*synthesis keep*/;
wire end_reg_cnt/*synthesis keep*/;
reg flag_add ;
reg [17:0] add_wdata/*synthesis keep*/;
reg [ 1:0] rw_cnt ;
wire add_rw_cnt ;
assign pwdn = 0;
`include "ov7670_para.v"
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
reg_cnt <= 0;
end
else if(add_reg_cnt)begin
if(end_reg_cnt)
reg_cnt <= 0;
else
reg_cnt <= reg_cnt + 1;
end
end
assign add_reg_cnt = end_rw_cnt;
assign end_reg_cnt = add_reg_cnt && reg_cnt==REG_NUM-1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
rw_cnt <= 0;
end
else if(add_rw_cnt) begin
if(end_rw_cnt)
rw_cnt <= 0;
else
rw_cnt <= rw_cnt + 1;
end
end
assign add_rw_cnt = flag_add && rdy;
assign end_rw_cnt = add_rw_cnt && rw_cnt==RW_NUM-1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
flag_add <= 1'b0;
end
else if(config_en)begin
flag_add <= 1'b1;
end
else if(end_reg_cnt)begin
flag_add <= 1'b0;
end
end
//cmos_en
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
cmos_en <= 1'b0;
end
else if(end_reg_cnt)begin
cmos_en <= 1'b1;
end
end
//add_wdata
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
wdata <= 8'b0;
end
else begin
wdata <= add_wdata[7:0];
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
addr <= 8'b0;
end
else begin
addr <= add_wdata[15:8];
end
end
//wr_en
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
wr_en <= 1'b0;
end
else if(add_rw_cnt && rw_cnt==0 && add_wdata[16])begin
wr_en <= 1'b1;
end
else begin
wr_en <= 1'b0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
rd_en <= 1'b0;
end
else if(add_rw_cnt && rw_cnt==1 && add_wdata[17])begin
rd_en <= 1'b1;
end
else begin
rd_en <= 1'b0;
end
end
endmodule
|
|