文章目录
- 问题描述
- 原因分析
- 解决方案
问题描述
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)beginif(!rst_n)beginscl_reg <= 1'b1;sda_reg <= 1'b1;dout <= 1'b0;endelse begin// 写寄存器if(mode == 1'b1)begincase(cnt_step)// 开始标志 0 :begin scl_reg <= 1'b1; sda_reg <= 1'b1; end1 :begin scl_reg <= 1'b1; sda_reg <= 1'b0; end2 :begin scl_reg <= 1'b0; sda_reg <= 1'b0; end// ID地址3 :begin scl_reg <= scl_high; sda_reg <= data[23]; end4 :begin scl_reg <= scl_high; sda_reg <= data[22]; end5 :begin scl_reg <= scl_high; sda_reg <= data[21]; end6 :begin scl_reg <= scl_high; sda_reg <= data[20]; end7 :begin scl_reg <= scl_high; sda_reg <= data[19]; end8 :begin scl_reg <= scl_high; sda_reg <= data[18]; end9 :begin scl_reg <= scl_high; sda_reg <= data[17]; end10:begin scl_reg <= scl_high; sda_reg <= data[16]; end11:begin scl_reg <= 1'b0; sda_reg <= 1'bz; end12:begin scl_reg <= scl_high; sda_reg <= 1'bz; end13:begin scl_reg <= 1'b0; sda_reg <= 1'b0; end// 子地址14:begin scl_reg <= scl_high; sda_reg <= data[15]; end15:begin scl_reg <= scl_high; sda_reg <= data[14]; end16:begin scl_reg <= scl_high; sda_reg <= data[13]; end17:begin scl_reg <= scl_high; sda_reg <= data[12]; end18:begin scl_reg <= scl_high; sda_reg <= data[11]; end19:begin scl_reg <= scl_high; sda_reg <= data[10]; end20:begin scl_reg <= scl_high; sda_reg <= data[9]; end21:begin scl_reg <= scl_high; sda_reg <= data[8]; end22:begin scl_reg <= 1'b0; sda_reg <= 1'bz; end23:begin scl_reg <= scl_high; sda_reg <= 1'bz; end24:begin scl_reg <= 1'b0; sda_reg <= 1'b0; end// 写入数据25:begin scl_reg <= scl_high; sda_reg <= data[7]; end26:begin scl_reg <= scl_high; sda_reg <= data[6]; end27:begin scl_reg <= scl_high; sda_reg <= data[5]; end28:begin scl_reg <= scl_high; sda_reg <= data[4]; end29:begin scl_reg <= scl_high; sda_reg <= data[3]; end30:begin scl_reg <= scl_high; sda_reg <= data[2]; end31:begin scl_reg <= scl_high; sda_reg <= data[1]; end32:begin scl_reg <= scl_high; sda_reg <= data[0]; end33:begin scl_reg <= 1'b0; sda_reg <= 1'bz; end34:begin scl_reg <= scl_high; sda_reg <= 1'bz; end35:begin scl_reg <= 1'b0; sda_reg <= 1'b0; end // 结束标志36:begin scl_reg <= 1'b1; sda_reg <= 1'b0; end37:begin scl_reg <= 1'b1; sda_reg <= 1'b1; endendcaseend// 读寄存器else if(mode == 1'b0)begincase(cnt_step)// 开始标志 0 :begin scl_reg <= 1'b1; sda_reg <= 1'b1; end1 :begin scl_reg <= 1'b1; sda_reg <= 1'b0; end2 :begin scl_reg <= 1'b0; sda_reg <= 1'b0; end// ID地址3 :begin scl_reg <= scl_high; sda_reg <= data[23]; end4 :begin scl_reg <= scl_high; sda_reg <= data[22]; end5 :begin scl_reg <= scl_high; sda_reg <= data[21]; end6 :begin scl_reg <= scl_high; sda_reg <= data[20]; end7 :begin scl_reg <= scl_high; sda_reg <= data[19]; end8 :begin scl_reg <= scl_high; sda_reg <= data[18]; end9 :begin scl_reg <= scl_high; sda_reg <= data[17]; end10:begin scl_reg <= scl_high; sda_reg <= data[16]; end11:begin scl_reg <= 1'b0; sda_reg <= 1'bz; end12:begin scl_reg <= scl_high; sda_reg <= 1'bz; end13:begin scl_reg <= 1'b0; sda_reg <= 1'b0; end// 子地址14:begin scl_reg <= scl_high; sda_reg <= data[15]; end15:begin scl_reg <= scl_high; sda_reg <= data[14]; end16:begin scl_reg <= scl_high; sda_reg <= data[13]; end17:begin scl_reg <= scl_high; sda_reg <= data[12]; end18:begin scl_reg <= scl_high; sda_reg <= data[11]; end19:begin scl_reg <= scl_high; sda_reg <= data[10]; end20:begin scl_reg <= scl_high; sda_reg <= data[9]; end21:begin scl_reg <= scl_high; sda_reg <= data[8]; end22:begin scl_reg <= 1'b0; sda_reg <= 1'bz; end23:begin scl_reg <= scl_high; sda_reg <= 1'bz; end24:begin scl_reg <= 1'b0; sda_reg <= 1'b0; end// 结束标志25:begin scl_reg <= 1'b1; sda_reg <= 1'b0; end26:begin scl_reg <= 1'b1; sda_reg <= 1'b1; end// 开始标志27:begin scl_reg <= 1'b1; sda_reg <= 1'b1; end28:begin scl_reg <= 1'b1; sda_reg <= 1'b0; end29:begin scl_reg <= 1'b0; sda_reg <= 1'b0; end // ID地址30:begin scl_reg <= scl_high; sda_reg <= data[23]; end31:begin scl_reg <= scl_high; sda_reg <= data[22]; end32:begin scl_reg <= scl_high; sda_reg <= data[21]; end33:begin scl_reg <= scl_high; sda_reg <= data[20]; end34:begin scl_reg <= scl_high; sda_reg <= data[19]; end35:begin scl_reg <= scl_high; sda_reg <= data[18]; end36:begin scl_reg <= scl_high; sda_reg <= data[17]; end37:begin scl_reg <= scl_high; sda_reg <= 1'b1; end38:begin scl_reg <= 1'b0; sda_reg <= 1'bz; end39:begin scl_reg <= scl_high; sda_reg <= 1'bz; end40:begin scl_reg <= 1'b0; sda_reg <= 1'bz; end// 读出数据41:begin scl_reg <= scl_high; sda_reg <= 1'bz; dout[7] <= sdat; end42:begin scl_reg <= scl_high; sda_reg <= 1'bz; dout[6] <= sdat; end43:begin scl_reg <= scl_high; sda_reg <= 1'bz; dout[5] <= sdat; end44:begin scl_reg <= scl_high; sda_reg <= 1'bz; dout[4] <= sdat; end45:begin scl_reg <= scl_high; sda_reg <= 1'bz; dout[3] <= sdat; end46:begin scl_reg <= scl_high; sda_reg <= 1'bz; dout[2] <= sdat; end47:begin scl_reg <= scl_high; sda_reg <= 1'bz; dout[1] <= sdat; end48:begin scl_reg <= scl_high; sda_reg <= 1'bz; dout[0] <= sdat; end49:begin scl_reg <= scl_high; sda_reg <= 1'b1; end// 结束标志50:begin scl_reg <= 1'b1; sda_reg <= 1'b0; end51:begin scl_reg <= 1'b1; sda_reg <= 1'b1; endendcaseendend
endassign sclk = scl_reg;
assign sdat = idle ? 1'bz : sda_reg;
简单粗暴的穷举~