文章目录
- 问题描述
- 原因分析
- 解决方案
问题描述
OV7670的输出图像异常,怀疑寄存器没有正确配置,在SignalTap中观察到SIO_D在读出阶段一直为高或低
寄存器读出0x00
寄存器读出0xFF
原因分析
在确保电源、时钟和读写时序没有问题的情况下,有可能是OV7670模块中SIO_C与SIO_D的引脚没有接上拉电阻,导致寄存器无法正常读写
解决方案
在FPGA对应引脚上开启上拉电阻,具体过程见 Altera FPGA 开启引脚片上上拉电阻功能
问题解决,寄存器读出0x17
标红的地方需要把SIO_D设置为高阻状态
这里附上SIO_C与SIO_D的时序,可以根据序列号1C7F & 1DA2进行验证
// 配置SCL与SDA
reg scl_reg;
reg sda_reg;
always@(posedge clk or negedge rst_n)begin
if(!rst_n)begin
scl_reg <= 1'b1;
sda_reg <= 1'b1;
dout <= 1'b0;
end
else begin
// 写寄存器
if(mode == 1'b1)begin
case(cnt_step)
// 开始标志
0 :begin scl_reg <= 1'b1; sda_reg <= 1'b1; end
1 :begin scl_reg <= 1'b1; sda_reg <= 1'b0; end
2 :begin scl_reg <= 1'b0; sda_reg <= 1'b0; end
// ID地址
3 :begin scl_reg <= scl_high; sda_reg <= data[23]; end
4 :begin scl_reg <= scl_high; sda_reg <= data[22]; end
5 :begin scl_reg <= scl_high; sda_reg <= data[21]; end
6 :begin scl_reg <= scl_high; sda_reg <= data[20]; end
7 :begin scl_reg <= scl_high; sda_reg <= data[19]; end
8 :begin scl_reg <= scl_high; sda_reg <= data[18]; end
9 :begin scl_reg <= scl_high; sda_reg <= data[17]; end
10:begin scl_reg <= scl_high; sda_reg <= data[16]; end
11:begin scl_reg <= 1'b0; sda_reg <= 1'bz; end
12:begin scl_reg <= scl_high; sda_reg <= 1'bz; end
13:begin scl_reg <= 1'b0; sda_reg <= 1'b0; end
// 子地址
14:begin scl_reg <= scl_high; sda_reg <= data[15]; end
15:begin scl_reg <= scl_high; sda_reg <= data[14]; end
16:begin scl_reg <= scl_high; sda_reg <= data[13]; end
17:begin scl_reg <= scl_high; sda_reg <= data[12]; end
18:begin scl_reg <= scl_high; sda_reg <= data[11]; end
19:begin scl_reg <= scl_high; sda_reg <= data[10]; end
20:begin scl_reg <= scl_high; sda_reg <= data[9]; end
21:begin scl_reg <= scl_high; sda_reg <= data[8]; end
22:begin scl_reg <= 1'b0; sda_reg <= 1'bz; end
23:begin scl_reg <= scl_high; sda_reg <= 1'bz; end
24:begin scl_reg <= 1'b0; sda_reg <= 1'b0; end
// 写入数据
25:begin scl_reg <= scl_high; sda_reg <= data[7]; end
26:begin scl_reg <= scl_high; sda_reg <= data[6]; end
27:begin scl_reg <= scl_high; sda_reg <= data[5]; end
28:begin scl_reg <= scl_high; sda_reg <= data[4]; end
29:begin scl_reg <= scl_high; sda_reg <= data[3]; end
30:begin scl_reg <= scl_high; sda_reg <= data[2]; end
31:begin scl_reg <= scl_high; sda_reg <= data[1]; end
32:begin scl_reg <= scl_high; sda_reg <= data[0]; end
33:begin scl_reg <= 1'b0; sda_reg <= 1'bz; end
34:begin scl_reg <= scl_high; sda_reg <= 1'bz; end
35:begin scl_reg <= 1'b0; sda_reg <= 1'b0; end
// 结束标志
36:begin scl_reg <= 1'b1; sda_reg <= 1'b0; end
37:begin scl_reg <= 1'b1; sda_reg <= 1'b1; end
endcase
end
// 读寄存器
else if(mode == 1'b0)begin
case(cnt_step)
// 开始标志
0 :begin scl_reg <= 1'b1; sda_reg <= 1'b1; end
1 :begin scl_reg <= 1'b1; sda_reg <= 1'b0; end
2 :begin scl_reg <= 1'b0; sda_reg <= 1'b0; end
// ID地址
3 :begin scl_reg <= scl_high; sda_reg <= data[23]; end
4 :begin scl_reg <= scl_high; sda_reg <= data[22]; end
5 :begin scl_reg <= scl_high; sda_reg <= data[21]; end
6 :begin scl_reg <= scl_high; sda_reg <= data[20]; end
7 :begin scl_reg <= scl_high; sda_reg <= data[19]; end
8 :begin scl_reg <= scl_high; sda_reg <= data[18]; end
9 :begin scl_reg <= scl_high; sda_reg <= data[17]; end
10:begin scl_reg <= scl_high; sda_reg <= data[16]; end
11:begin scl_reg <= 1'b0; sda_reg <= 1'bz; end
12:begin scl_reg <= scl_high; sda_reg <= 1'bz; end
13:begin scl_reg <= 1'b0; sda_reg <= 1'b0; end
// 子地址
14:begin scl_reg <= scl_high; sda_reg <= data[15]; end
15:begin scl_reg <= scl_high; sda_reg <= data[14]; end
16:begin scl_reg <= scl_high; sda_reg <= data[13]; end
17:begin scl_reg <= scl_high; sda_reg <= data[12]; end
18:begin scl_reg <= scl_high; sda_reg <= data[11]; end
19:begin scl_reg <= scl_high; sda_reg <= data[10]; end
20:begin scl_reg <= scl_high; sda_reg <= data[9]; end
21:begin scl_reg <= scl_high; sda_reg <= data[8]; end
22:begin scl_reg <= 1'b0; sda_reg <= 1'bz; end
23:begin scl_reg <= scl_high; sda_reg <= 1'bz; end
24:begin scl_reg <= 1'b0; sda_reg <= 1'b0; end
// 结束标志
25:begin scl_reg <= 1'b1; sda_reg <= 1'b0; end
26:begin scl_reg <= 1'b1; sda_reg <= 1'b1; end
// 开始标志
27:begin scl_reg <= 1'b1; sda_reg <= 1'b1; end
28:begin scl_reg <= 1'b1; sda_reg <= 1'b0; end
29:begin scl_reg <= 1'b0; sda_reg <= 1'b0; end
// ID地址
30:begin scl_reg <= scl_high; sda_reg <= data[23]; end
31:begin scl_reg <= scl_high; sda_reg <= data[22]; end
32:begin scl_reg <= scl_high; sda_reg <= data[21]; end
33:begin scl_reg <= scl_high; sda_reg <= data[20]; end
34:begin scl_reg <= scl_high; sda_reg <= data[19]; end
35:begin scl_reg <= scl_high; sda_reg <= data[18]; end
36:begin scl_reg <= scl_high; sda_reg <= data[17]; end
37:begin scl_reg <= scl_high; sda_reg <= 1'b1; end
38:begin scl_reg <= 1'b0; sda_reg <= 1'bz; end
39:begin scl_reg <= scl_high; sda_reg <= 1'bz; end
40:begin scl_reg <= 1'b0; sda_reg <= 1'bz; end
// 读出数据
41:begin scl_reg <= scl_high; sda_reg <= 1'bz; dout[7] <= sdat; end
42:begin scl_reg <= scl_high; sda_reg <= 1'bz; dout[6] <= sdat; end
43:begin scl_reg <= scl_high; sda_reg <= 1'bz; dout[5] <= sdat; end
44:begin scl_reg <= scl_high; sda_reg <= 1'bz; dout[4] <= sdat; end
45:begin scl_reg <= scl_high; sda_reg <= 1'bz; dout[3] <= sdat; end
46:begin scl_reg <= scl_high; sda_reg <= 1'bz; dout[2] <= sdat; end
47:begin scl_reg <= scl_high; sda_reg <= 1'bz; dout[1] <= sdat; end
48:begin scl_reg <= scl_high; sda_reg <= 1'bz; dout[0] <= sdat; end
49:begin scl_reg <= scl_high; sda_reg <= 1'b1; end
// 结束标志
50:begin scl_reg <= 1'b1; sda_reg <= 1'b0; end
51:begin scl_reg <= 1'b1; sda_reg <= 1'b1; end
endcase
end
end
end
assign sclk = scl_reg;
assign sdat = idle ? 1'bz : sda_reg;
简单粗暴的穷举~