sccb协议
2019-07-13 16:54发布
生成海报
1摄像头配置OV7670
摄像头datasheet
:通过 SCCB
总线控制,可以输出整帧、子采样、取窗口等方式的各种分辨率 8 位影响数据。该产品 VGA 图像最高达到 30 帧/秒。 640*480分辨率标准的 SCCB
接口 ,采用RGB565格式图像。采用SCCB
接口(类似于IIC协议):(1
)SCCB简介SCCB
协议有两线也有三线,两线为SIO_C与SIO_D,三线为SIO_E、SIO_C与SIO_D。2
线的SCCB总线只能是一个主器件对一个从器件控制,但3线SCCB接口可以对多个从器件控制,因此当只有一个从机(slave device)时用两线,有多个从机时用三线。其中SIO_C只能由主机配置(FPGA),SIO_D是一个三态门,双向数据线,既可以由主机控制,也可以由从机控制。 ![](https://img-blog.csdn.net/20180420150719238)
(2)数据传输
当写数据到从机被定义为写传输(write transmission),当从机中读数据被定义为读传输 (read transmission),每一个传输都要有开始和结束来释放总线(start + sotp)完整的数据传输包括两个或三个阶段,每一个阶段包含9
位数据,其中高8位为所要传输的数据,最低位根据器件所处情况有不同的取值:总结如下:
每一个阶段组成:8
位数据+don't care/NA如果是主机发送数据,即进行
写操作,第九位就为don't care如果是从机发送数据,即为
读操作,第九位就为NA.
在进行主器件写操作时,全部阶段的最低位均是Don
’t care bit写操作:
三个阶段构成传输的写,每个阶段都为9位ID地址(7位ID地址+1位读写控制+don't care) + 要写的寄存器地址(8位寄存器地址+don't care) +要写入的数据(8位数据+don't care) ![](https://img-blog.csdn.net/20180420150815643)
即写操作有:
start + ID地址(地址位42)+ 寄存器地址 + 数据 + stop读操作:根据SCCB
接口的读操作时序有两个阶段传输组成2
个阶段写传输 + 2个阶段读传输,每一相都是9位,具体如下ID
地址(8位ID地址+1位读写控制+don't care)+ FPGA要向从机写入即将要读的寄存器地址(8位寄存器地址+don't care)ID
地址(8位ID地址+1位读写控制+don't care) +从机向FPGA发送被指定寄存器里面的数据的数据(8位数据+NA)即读操作为:
start1+ ID地址(42)+ 寄存器地址 +stop1+start 2 +ID地址(43)+ 数据 + stop2 ![](https://img-blog.csdn.net/20180420150908124)
(2)数据传输
当写数据到从机被定义为写传输(write transmission),当从机中读数据被定义为读传输 (read transmission),每一个传输都要有开始和结束来释放总线(start + sotp)完整的数据传输包括两个或三个阶段,每一个阶段包含9
位数据,其中高8位为所要传输的数据,最低位根据器件所处情况有不同的取值:总结如下:
每一个阶段组成:8
位数据+don't care/NA如果是主机发送数据,即进行
写操作,第九位就为don't care如果是从机发送数据,即为
读操作,第九位就为NA.
在进行主器件写操作时,全部阶段的最低位均是Don
’t care bitmodule sccb_sender(
clk,rst_n,sio_c,sio_d,
wr_en,rd_en,write_data,read_data
);
input clk,rst_n;//50MH
output sio_c;
inout sio_d;
input wr_en,rd_en;
input[7:0]write_data;
input[7:0]read_data;
reg[7:0]db_r;
reg[8:0]cnt_8us;//建立SCCB需要的时钟8us 50*8=400
always@(posedge clk or negedge rst_n)
if(!rst_n)cnt_8us<=0;
else
if(cnt_8us==9'd399)cnt_8us<=0;
else cnt_8us<=cnt_8us+1'b1;
reg[8:0]cnt;
reg[2:0]cnt_delay;//把每个计数周期分为4段,在低电平中间改变数据,在高电平中间采集数据
always@(posedge clk or negedge rst_n)
if(!rst_n)cnt_delay<=3'd5;
else
begin
case(cnt)
9'd99 :cnt_delay<=3'd1;//高电平数据中间,用于数据采样
9'd199:cnt_delay<=3'd2;//下降沿
9'd299:cnt_delay<=3'd3;//低电平数据中间,用于数据变化
9'd399:cnt_delay<=3'd0;//上升沿
default:cnt_delay<=3'd5;
endcase
end
`define SIO_C_POS (cnt_delay==3'd0) //SCL上升沿
`define SIO_C_HIG (cnt_delay==3'd1) //SCL高电平中间
`define SIO_C_NEG (cnt_delay==3'd2) //SCL下降沿
`define SIO_C_LOW (cnt_delay==3'd3) //SCL低电平中间
//产生时钟sio_c信号;
reg sio_c_r;
always@(posedge clk or negedge rst_n)
if(!rst_n)sio_c_r<=0;
else if(cnt_delay==3'd0)sio_c_r<=1;
else if(cnt_delay==3'd2)sio_c_r<=0;
assign sio_c=sio_c_r;
parameter subaddres=8'h40;
parameter WRITE_ADD=8'h42;//写寄存器地址
parameter READ_ADD=8'h43;//读寄存器地址
parameter IDLE=4'd0;
parameter START1=4'd1;
parameter ADD1=4'd2;//ID addres
parameter DC=4'd3;//don`t care 位
parameter ADD2=4'd4;//Subaddres
parameter NA=4'd5;//not absolutely位
parameter START2=4'd6;
parameter ADD3=4'd7;//WRITE_DATA
parameter WDATA_ACK=4'd8;//写DATA 应答位
parameter ADD4=4'd9;//READ_DATA
parameter DCB=4'd10;//读DATA 应答位
parameter ADD5=4'd11;
parameter RDATA_ACK=4'd12;
parameter STOP1=4'd13;
parameter STOP2=4'd14;
reg[3:0]cstate;
reg[3:0]num;
reg sio_d_link,sio_d_r;
always@(posedge clk or negedge rst_n)
if(!rst_n)begin
sio_d_link<=0;
sio_d_r<=1;
cstate<=IDLE;
num<=0;
end
else
case(cstate)
IDLE:begin
sio_d_link<=1'b1;
sio_d_r<=1'b1;
if(wr_en||rd_en)begin
db_r<=WRITE_ADD;
cstate<=START1;
end
else cstate<=IDLE;
end
START1:begin
if(`SIO_C_HIG)begin
sio_d_r<=0;
sio_d_link<=1'b1;
cstate<=ADD1;
num<=0;
end
else cstate<=START1;
end
ADD1:begin
if(`SIO_C_LOW)begin
if(num==4'd8)begin
sio_d_link<=1'b0;//高阻态
sio_d_r<=1'b1;
num<=0;
cstate<=DC;
end
else begin
num<=num+1'b1;
cstate<=ADD1;
case(num)
4'd0:sio_d_r<=db_r[7];
4'd1:sio_d_r<=db_r[6];
4'd2:sio_d_r<=db_r[5];
4'd3:sio_d_r<=db_r[4];
4'd4:sio_d_r<=db_r[3];
4'd5:sio_d_r<=db_r[2];
4'd6:sio_d_r<=db_r[1];
4'd7:sio_d_r<=db_r[0];
default:;
endcase
end
end
else if(`SIO_C_POS)db_r<={db_r[6:0],1'b0};//时序图 器件地址左移一位
else cstate<=ADD1;
end
DC:begin
if(`SIO_C_NEG)begin
db_r<=subaddres;//寄存器地址;
cstate<=ADD2;
end
else cstate<=DC;
end
ADD2:begin
if(`SIO_C_LOW)begin
if(num==4'd8)begin
sio_d_link<=1'b0;//高阻态
sio_d_r<=0;
num<=4'd0;
cstate<=NA;
end
else begin
sio_d_link<=1'b1;
num<=num+1'b1;
case(cstate)
4'd0:sio_d_r<=db_r[7];
4'd1:sio_d_r<=db_r[6];
4'd2:sio_d_r<=db_r[5];
4'd3:sio_d_r<=db_r[4];
4'd4:sio_d_r<=db_r[3];
4'd5:sio_d_r<=db_r[2];
4'd6:sio_d_r<=db_r[1];
4'd7:sio_d_r<=db_r[0];
default:;
endcase
cstate<=ADD2;
end
end
else if(`SIO_C_POS)db_r<={db_r[6:0],1'b0};
else cstate<=ADD2;
end
NA:begin
if(`SIO_C_NEG)begin
if(wr_en)begin
cstate<=ADD3;
db_r<=write_data;
end
else if(rd_en)begin
cstate<=START2;
db_r<=READ_ADD;
end
end
else cstate<=NA;
end
ADD3:begin
if(`SIO_C_LOW)begin
if(num==4'd8)begin
num<=0;
cstate<=WDATA_ACK;
sio_d_link<=1'b0;
sio_d_r<=1'b1;
end
else begin
num<=num+1'b1;
cstate<=ADD3;
case(num)
4'd0:sio_d_r<=db_r[7];
4'd1:sio_d_r<=db_r[6];
4'd2:sio_d_r<=db_r[5];
4'd3:sio_d_r<=db_r[4];
4'd4:sio_d_r<=db_r[3];
4'd5:sio_d_r<=db_r[2];
4'd6:sio_d_r<=db_r[1];
4'd7:sio_d_r<=db_r[0];
default:;
endcase
end
end
else if(`SIO_C_POS)db_r<={db_r[6:0],1'b0};
else cstate<=ADD3;
end
WDATA_ACK:begin
if(`SIO_C_NEG)begin
cstate<=STOP1;
sio_d_link<=1'b0;
end
else cstate<=WDATA_ACK;
end
STOP1:begin
if(`SIO_C_HIG)begin
cstate<=STOP2;
sio_d_link<=1'b1;
end
else if(`SIO_C_LOW)begin
sio_d_link<=1'b0;
sio_d_r<=1'b0;
cstate<=STOP1;
end
else cstate<=STOP1;
end
START2:begin
if(`SIO_C_HIG)begin
sio_d_link<=1'b1;
sio_d_r<=1'b0;
cstate<=ADD3;
end
else if(`SIO_C_LOW)begin
sio_d_link<=1'b1;
sio_d_r<=1'b1;
cstate<=START2;
end
else cstate<=START2;
end
ADD4:begin
if(`SIO_C_LOW)begin
if(num==4'd8)begin
sio_d_link<=1'b0;//高阻态
sio_d_r<=1'b1;
num<=0;
cstate<=DCB;
end
else begin
num<=num+1'b1;
cstate<=ADD4;
case(num)
4'd0:sio_d_r<=db_r[7];
4'd1:sio_d_r<=db_r[6];
4'd2:sio_d_r<=db_r[5];
4'd3:sio_d_r<=db_r[4];
4'd4:sio_d_r<=db_r[3];
4'd5:sio_d_r<=db_r[2];
4'd6:sio_d_r<=db_r[1];
4'd7:sio_d_r<=db_r[0];
default:;
endcase
end
end
else if(`SIO_C_POS)db_r<={db_r[6:0],1'b0};//时序图 器件地址左移一位
else cstate<=ADD4;
end
DCB:begin
if(`SIO_C_NEG)begin
db_r<=READ_ADD;//寄存器地址;
cstate<=ADD5;
end
else cstate<=DCB;
end
ADD5:begin
if(`SIO_C_LOW)begin
if(num==4'd8)begin
sio_d_link<=1'b0;//高阻态
sio_d_r<=1'b1;
num<=0;
cstate<=RDATA_ACK;
end
else begin
num<=num+1'b1;
cstate<=ADD5;
case(num)
4'd0:sio_d_r<=db_r[7];
4'd1:sio_d_r<=db_r[6];
4'd2:sio_d_r<=db_r[5];
4'd3:sio_d_r<=db_r[4];
4'd4:sio_d_r<=db_r[3];
4'd5:sio_d_r<=db_r[2];
4'd6:sio_d_r<=db_r[1];
4'd7:sio_d_r<=db_r[0];
default:;
endcase
end
end
else if(`SIO_C_POS)db_r<={db_r[6:0],1'b0};//时序图 器件地址左移一位
else cstate<=ADD5;
end
RDATA_ACK:begin
if(`SIO_C_NEG)begin
sio_d_link<=1'b0;
cstate<=STOP2;
end
else cstate<=RDATA_ACK;
end
STOP2:begin
if(`SIO_C_LOW)begin
sio_d_link<=1'b0;
sio_d_r<=1'b1;
end
else if(`SIO_C_HIG)begin
sio_d_link<=1'b1;
end
else cstate<=IDLE;
end
endcase
assign sio_d=sio_d_link?sio_d_r:1'bz;
endmodule
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮