一、 主要内容:对SCCB模块做下简要的说明
二、 SCCB是串行摄像机控制总线协议(Serial Camera Control Bus
)的英文简称 ,它控制着摄像头大部分的功能,包括图像数据格式、分辨率以及图像处理参数等 ,它有两线和三线两种,3线SCCB接口可以对多个从器件控制,两线只能控制一个从机,本次只控制一个OV7670摄像头,用两线的SCCB即可对摄像头进行配置。
三、 下图是两线模式的基本时序图,其中SIO_C是时钟线,本工程设为100KHz,SIO_D为数据线,开始时,SIO_D信号拉低到SIO_C拉低之间的时间间隔要大于100ns;结束时,SIO_D拉高到SIO_C拉高时间间隔要大于100ns。SIO_D的数据在SIO_C低电平开始变化
四、 读写流程
1、字节格式
2. 写 一般在写寄存器的过程中先发送设备的ID地址(ID Address),然后发送写数据的目地寄存器地址(Sub_address),最后发送要写入的数据(Write Data),本次工程使用的是OV7670,其中Address=8’h42,Sub_addr=8’h12,wdata=8’h04,x为都置1.
3.读 读如下图所示,其中Address(W)=8’h42,Sub_addr=8’h12,Address®=8’h43,最后数据FPGA可以从SIO_D中读取到数据
五、下表为此模块的接口信号列表
六、verilog代码
/***********Filename ﹕sccb .v**************
************Author ﹕Wenliang Zhou*********
************Description ﹕SCCB**********
************Revision time﹕2019.08.02**********
************Email [email protected]﹕**********
***********/
module sccb(
clk ,
rst_n ,
ren ,
wen ,
sub_addr ,
rdata ,
rdata_vld ,
wdata ,
rdy ,
sio_c ,
sio_d_r ,
en_sio_d_w,
sio_d_w
);
//锟斤拷锟斤拷锟斤拷锟斤拷
parameter SIO_C = 120 ;
//输入引脚定义
input clk ;//25m
input rst_n ;
input ren ;
input wen ;
input [7:0] sub_addr ;
input [7:0] wdata ;
input sio_d_r ;
//输出引脚定义
output[7:0] rdata ;
output rdata_vld;
output sio_c ;//208kHz
output rdy ;
output en_sio_d_w;
output sio_d_w ;
reg [7:0] rdata ;
reg rdata_vld;
reg sio_c ;
reg rdy ;
reg en_sio_d_w;
reg sio_d_w ;
//定义
reg [7:0] count_sck ;
reg [4:0] count_bit ;
reg [1:0] count_duan ;
reg flag_r ;
reg flag_w ;
reg [4:0] bit_num ;
reg [1:0] duan_num ;
reg [29:0] out_data ;
wire add_count_sck ;
wire end_count_sck ;
wire add_count_bit ;
wire end_count_bit ;
wire add_count_duan;
wire end_count_duan;
wire sio_c_h2l ;
wire sio_c_l2h ;
wire en_sio_d_w_h2l;
wire en_sio_d_w_l2h;
wire out_data_time ;
wire rdata_time ;
wire [7:0] rd_com ;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
count_sck <= 0;
end
else if(add_count_sck)begin
if(end_count_sck)begin
count_sck <= 0;
end
else begin
count_sck <= count_sck + 1;
end
end
end
assign add_count_sck = flag_r || flag_w;
assign end_count_sck = add_count_sck && count_sck == SIO_C-1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
count_bit <= 0;
end
else if(add_count_bit)begin
if(end_count_bit)begin
count_bit <= 0;
end
else begin
count_bit <= count_bit + 1;
end
end
end
assign add_count_bit = end_count_sck;
assign end_count_bit = add_count_bit && count_bit == bit_num+2-1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
count_duan <= 0;
end
else if(add_count_duan)begin
if(end_count_duan)begin
count_duan <= 0;
end
else begin
count_duan <= count_duan + 1;
end
end
end
assign add_count_duan = end_count_bit;
assign end_count_duan = add_count_duan && count_duan == duan_num-1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
flag_r <= 0;
end
else if(ren)begin
flag_r <= 1;
end
else if(end_count_duan)begin
flag_r <= 0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
flag_w <= 0;
end
else if(wen)begin
flag_w <= 1;
end
else if(end_count_duan)begin
flag_w <= 0;
end
end
always @(*)begin
if(flag_r)begin
bit_num = 21;
duan_num = 2;
end
else if(flag_w)begin
bit_num = 30;
duan_num = 1;
end
else begin
bit_num = 1;
duan_num = 1;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
sio_c <= 1;
end
else if(sio_c_h2l)begin
sio_c <= 0;
end
else if(sio_c_l2h)begin
sio_c <= 1;
end
end
assign sio_c_h2l = count_bit >= 0 && count_bit < (bit_num-2) && add_count_sck && count_sck == SIO_C-1;
assign sio_c_l2h = count_bit >= 1 && count_bit < bit_num && add_count_sck && count_sck == SIO_C/2-1;
always @ (*)begin
if(flag_r)begin
out_data <= {1'h0,rd_com,1'h1,sub_addr,1'h1,1'h0,1'h1,9'h0};
end
else if(flag_w)begin
out_data <= {1'h0,8'h42,1'h1,sub_addr,1'h1,wdata,1'h1,1'h0,1'h1};
end
else begin
out_data <= 0;
end
end
assign rd_com = (flag_r && count_duan == 0)? 8'h42 : 8'h43;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
en_sio_d_w <= 0;
end
else if(ren || wen)begin
en_sio_d_w <= 1;
end
else if(end_count_duan)begin
en_sio_d_w <= 0;
end
else if(en_sio_d_w_h2l)begin
en_sio_d_w <= 0;
end
else if(en_sio_d_w_l2h)begin
en_sio_d_w <= 1;
end
end
assign en_sio_d_w_h2l = flag_r && count_duan == 1 && count_bit == 10 && add_count_sck && count_sck == 1-1;
assign en_sio_d_w_l2h = flag_r && count_duan == 1 && count_bit == 18 && add_count_sck && count_sck == 1-1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
sio_d_w <= 1;
end
else if(out_data_time)begin
sio_d_w <= out_data[30-count_bit-1];
end
end
assign out_data_time = count_bit >= 0 && count_bit < bit_num && add_count_sck && count_sck == SIO_C/4-1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
rdata <= 0;
end
else if(rdata_time)begin
rdata[17-count_bit] <= sio_d_r;
end
end
assign rdata_time = flag_r && count_duan==1 && count_bit>=10 && count_bit<18 && add_count_sck && count_sck==SIO_C/4*3-1;
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
rdata_vld <= 0;
end
else if(flag_r && end_count_duan)begin
rdata_vld <= 1;
end
else begin
rdata_vld <= 0;
end
end
always @(*)begin
if(ren || wen || flag_r || flag_w)begin
rdy = 0;
end
else begin
rdy = 1;
end
end
endmodule
六、