找回密码
 注册
关于网站域名变更的通知
查看: 344|回复: 0
打印 上一主题 下一主题

边缘检测项目: 摄像头配置模块ov7670_config代码解析

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2019-12-17 11:35 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
边缘检测项目: 摄像头配置模块ov7670_config代码解析
* o+ U! b! ~4 P0 Z1 e9 f
作者:肖肖肖
. d, p. B" u6 j% L
本文为明德扬原创文章,转载请注明出处!
% k% B& R  D6 {( h! J

0 P" `) a/ B6 ^, H  Z6 g
      摄像头配置模块的功能:根据摄像头配置指令模块ov7670_para的操作,产生对应的写寄存器命令、读寄存器命令给下游模块。具体功能如下:

* T  v, y2 L0 S  B
1. 根据ov7670_para的参数,逐个配置或者读取寄存器;
2. 所有寄存器操作完成后,产生完成指示信号。
- [7 I/ x6 j7 P. `; l8 {* J. N
通过代码:`include“ov7670_para.v”,可以把边缘检测摄像头配置指令模块ov7670_para包含进本模块。

* O- K7 o, G* F$ S+ j4 ]
一、设计架构

" `* r' T% f1 ], v  r% Z" t( A6 e0 A
摄像头配置模块采用两个计数器的架构:计数器reg_cnt表示的是对要配置的164个寄存器进行计数,计数器rw_cnt表示判断写数据还是读数据的时序。例如,在写时序时,判断参数是否要写寄存器,如果要写寄存器,此时才产生写命令,如果参数是不要写寄存器,此时也不产生写命令。其结构图如下:
计数器rw_cnt:寄存器读写时序计数器。用来区分“向寄存器写数据”还是“从寄存器读数据”这两个状态。当其为0时,表示判断是否写寄存器的时序,当其为1时,表示判断是否读寄存器的时序。不管读写属性参数是什么,每个寄存器都会占有这两个时序。
计数器reg_cnt:寄存器顺序计数器。对摄像头164个寄存器进行排序,按顺序配置各个寄存器。
2 y, C2 R# ^% N. \" [
$ y2 v5 X- U6 ~5 F( }% M4 K
二、信号意义

5 {4 D+ V+ V5 g+ v' M
信号
类型
意义
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:表示判断是否读寄存器的时序。
: W3 W! s6 R; M+ k+ W1 e
add_rw_cnt
内部信号
寄存器读写时序加一条件。
当处于寄存器配置状态并且下游sccb模块空闲,开始判断是否写/读寄存器的时序。
end_rw_cnt
内部信号
寄存器读写时序结束条件。
表示已经判断完是否写/读寄存器时序。
- L1 `# i1 I2 o: r0 a, i" C. I2 z
# Y3 t' z6 c5 ]+ w  m
三、参考代码
) v9 w, M. D& v8 y' @1 [
下面展出本模块的设计,欢迎进一步交流,如果需要项目完整源代码,欢迎联系。
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
% ~" \' N0 G) M1 o
module ov7670_config(
     clk        ,
     rst_n      ,
     config_en  ,
     rdy        ,
     rdata      ,
     rdata_vld  ,
     wdata      ,
     addr       ,
     wr_en         ,
        rd_en      ,
     cmos_en    ,
     pwdn        
     );
2 }* l8 t, f, u# Y/ _
     parameter      DATA_W  =          8;
     parameter      RW_NUM  =          2;
7 {- I+ x2 M& {$ l1 T

' l3 c- \. z& ]! s
     input               clk      ;    //50Mhz
     input               rst_n    ;
     input               config_en;
     input               rdy      ;
     input [DATA_W-1:0]  rdata    ;
     input               rdata_vld;
4 `; X$ _( l* p, _
     output[DATA_W-1:0]  wdata    ;
     output[DATA_W-1:0]  addr     ;
6 ]% t' f+ Q1 M: N: a* k
     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    ;
/ F& e5 q6 S: q" ?
     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*/;
9 _/ n" L: A8 g9 P/ o9 [( j1 I1 u
     reg   [ 1:0]        rw_cnt     ;
     wire                add_rw_cnt ;
8 P, r8 l' f4 H. Q% i& X
     assign              pwdn = 0;

! J/ {+ I8 C8 H: f  Z/ [/ v; h) h8 Q+ k- @! d
     `include "ov7670_para.v"

) ?# d; W& B7 |, ]- l2 y2 ]
5 p* U9 N* H2 B4 G
     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
* R4 b. _7 w! M& ^
     assign add_reg_cnt = end_rw_cnt;   
     assign end_reg_cnt = add_reg_cnt && reg_cnt==REG_NUM-1;

8 r( H+ d- q  g4 _
     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

9 O% J5 d( S2 H: s) u
     assign  add_rw_cnt = flag_add  && rdy;
     assign  end_rw_cnt = add_rw_cnt  && rw_cnt==RW_NUM-1;

" `( ^$ @% f  I) u! M6 ~3 b- U6 ?$ i
9 d) v" y3 h" {' q) a+ V+ b+ Q+ t& H3 }) {- ]2 O. q9 ]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
" _. {3 I  B/ W
     //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
* J& x) e9 d* O

. ]1 k4 u! ?8 f- m
     //add_wdata

& U& r$ R6 u8 x" n" ^7 Z
     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
/ t; p- M0 U+ E: @3 M# S
     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
, k' e! D3 q( B. b' {7 {* ~6 b
; {0 _5 X/ A% B" o3 Q; a
     //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
4 b) _% m# f6 `9 i3 A+ \' R
) U# G2 l: b2 R) H! b
     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

9 u9 i% ?5 R2 t# j
/ c# @$ B2 r5 e' k: ^) k4 Y
endmodule
- w- U+ i' D. F6 D. b  x+ e9 C3 `0 W

; z- s9 Z( ]2 a9 j+ {* Q5 C
' a6 A- S: ~( H! f# R
4 w5 h+ U, L" e  }7 f
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-7-22 05:09 , Processed in 0.140625 second(s), 27 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表