OV系列摄像头的模块采用Serial Camera Control Bus (SCCB)总线

写进行配置ov摄像头

1,SCCB有START 和STOP条件,和I2C非常类似。
2,写一寄存器分成三个字节段: 即设备从地址,片内寄存器地址,要写的字节内容。这实际和I2C接口的24C02这个EEPROM写操作是几乎一样的。
3,DON’T-CARE BIT 实际就是接受端的ACK回应,0标示回应。
4,一个写寄存器的操作对应三个DON’T-CARE BIT。我们通过查看这个ACK位就知道摄像头SCCB接口是否已经连接以及写寄存器的操作是否成功完成。
5,数据位在SIOC为0是发生变化,在SOIC为1写入摄像头模块。
6,从设备地址有8位,结合读写位,组成8位作为器件地址。OV7670器件地址是0X42。

可以采用状态机或者定时器周期的方法

`timescale 1ns/1nsmodule SCCB_TEST ;reg clk  = 0 ;always #5 clk = ~clk ;wire siod , sioc , ready ;reg valid ;reg [7:0] id,sub_addr,value ;pullup r1 (siod);SCCB_sender UT(.clk( clk ),.siod( siod ),.sioc( sioc ),.ready( ready ),.valid( valid  ),.id( id  ),.sub_addr( sub_addr ),.value( value  ));task send_cmd ;input [7:0] id_i,sub_addr_i,value_i ;beginid = id_i;sub_addr=sub_addr_i;value=value_i;valid=1;@(posedge clk);while(~ready)begin @(posedge clk);  end ;valid=0;@(posedge clk);endendtaskinitial beginvalid=0;clk=0;@(posedge clk );send_cmd(1,2,3);send_cmd(1,'h55,'haa);endendmodulemodule SCCB_sender(input       clk,inout       siod,output  reg   sioc,output  reg  ready = 0,input        valid,input [7:0] id,sub_addr,value,output reg error);reg [20:0] cntr  = 0 ;always @ (posedge clk) // valid有效时开始if (0==cntr)cntr <= valid ;/// begin if (valid )cntr <=  1 ;end  //valid ;elsebeginif ( 31 == cntr[20:11] ) cntr <= 0 ;  else cntr <= cntr + 1 ;end// 32  *  2 * k =  64 *1024 = 64k always @ (posedge clk) ready <=  (cntr == 0) && (valid ==1) ; //告诉上位机数据已经取走reg [7:0]idr,addr,val;//锁存要发送的数据always @(posedge clk)if ( ( cntr == 0 ) && ( valid == 1 ) ) idr   <=  id ;always @(posedge clk)if ( ( cntr == 0 ) && ( valid == 1 ) ) addr  <=  sub_addr ;always @(posedge clk)if ( ( cntr == 0 ) && ( valid == 1 ) ) val   <=  value ;reg SIOD_EN ; // 发送使能 为0则是输入always @ (posedge clk)case  ( cntr[20:11] )0: sioc <= 1 ;1: case (cntr[10:9])2'b00:  sioc <= 1 ;2'b01:  sioc <= 1 ;2'b10:  sioc <= 1 ;2'b11:  sioc <= 0 ;endcase29:case (cntr[10:9])2'b00:  sioc <= 0 ;2'b01:  sioc <= 1 ;2'b10:  sioc <= 1 ;2'b11:  sioc <= 1 ;endcase30,31: sioc <= 1 ;default case (cntr[10:9])2'b00:  sioc <= 0 ;2'b01:  sioc <= 1 ;2'b10:  sioc <= 1 ;2'b11:  sioc <= 0 ;endcaseendcase//SIOD_ENalways @ (posedge clk) //在三个DONOT-CARE 状态设置为输入状态case  (cntr[20:11])10,19,28 :SIOD_EN <=0 ;default SIOD_EN<=1;endcasereg [31:0] dr ; //采用串行移位方式。always @ (posedge clk)if ( (cntr == 0)&& (valid ==1 ) )dr <= {   2'b10,   id,1'bx,             sub_addr,1'bx,     value, 1'bx,       3'b011    };else if ( cntr[10:0] == 0 ) dr <={dr[30:0],1'b1};assign siod = ( SIOD_EN ) ? dr[31] : 'BZ ;always @ (posedge clk)if (cntr[10:9] == 2'b01  )case(cntr[20:11])1: error<=0;10,19,28 :error <= error | siod ;endcaseendmodule
module module_name(clk    ,rst_n  ,//其他信号,举例doutCam_sclk,Cam_sdata);//参数定义parameter      DELAY_10MS =28'd1000000;parameter      CLK_DIV =10'd500;//100KhZ//输入信号定义input               clk    ;input               rst_n  ;output reg          Cam_sclk;output reg          Cam_sdata;//输出信号定义output[DATA_W-1:0]  Cam_sclk   ;//输出信号reg定义reg   [DATA_W-1:0]  Cam_sdata   ;//中间信号定义reg  [28-1:0]        delay_cnt;reg    [10-1:0]      time_cnt;reg    [10-1:0]      time_cnt;reg    [4-1:0]       bit_cnt;//最大16reg[7:0]    rom_addr;//0-75reg i2c_finish;wire i2c_stop;reg [7:0]    i2c_rddata;//读出来的assign i2c_stop=fsm_cs==WR_STOP;assign i2c_finish=rom_addr==75?1:0;reg       cam_sdata_reg;//串行输出reg       cam_sdata_reg_en;assign  Cam_sdata=(cam_sdata_reg_en)?cam_sdata_reg:1'bz;//cam_sdata_regwire Read_i2c_flag=time_cnt==0;always  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begincam_sdata_reg<=1;endelse begincase(fsm_cs)FSM_IDLE://RD_RAEDY,RD_NACKcam_sdata_reg<=1;WR_START,WR_STOP://RD_START1,RD_START2,RD_STOP1,RD_STOP2cam_sdata_reg<0;WR_DEVADDR: //RD_DEVADDR1,RD_DEVADDR2if(Read_i2c_flag)cam_sdata_reg<=shift_dev_addr[7]:elsecam_sdata_reg<=cam_sdata_reg;WR_REGADDR:// RD_REGADDRif(Read_i2c_flag)cam_sdata_reg<=shift_reg_addr[7]:elsecam_sdata_reg<=cam_sdata_reg;WR_REGDATA :if(Read_i2c_flag)cam_sdata_reg<=shift_regdata[7]:elsecam_sdata_reg<=shift_regdata;default:cam_sdata_reg<=cam_sdata_reg;endcaseendend//cam_sdata_reg_en   ack应答为0,,0表示输入,获取cam_data的发回的应答值//使能1,其他时刻为输出。always  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begincam_sdata_reg_en<=0;endelse begincase(fsm_cs)WR_ACK_DEV ,WR_ACK_REG ,//RD_ACK_DEV1,RD_ACK_DEV2,RD_ACK_REG, RD_DATAWR_ACK_DATA:cam_sdata_reg_en<=0;default:cam_sdata_reg_en<=1;endcaseendendreg[15:0] rom_data;reg[7:0] rom_addr;// rom_addralways  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginrom_addr<=0;endelse (i2c_stop&&i2c_ack&&I2CClk_period)begin//i2c_stop是进入fsm)STOP第一个50MHz时刻改变,在进入idle那一时刻把组合逻辑的值打入寄存器rom_addr<=rom_addr+1;            endelse beginrom_addr<=rom_addr;end//rom_dataalways  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginrom_data<=0;endelse begin//加个条件可以不用工作?case(rom_addr)0:rom_data={8'h1C,8'h7F};1:rom_data={8'h1D,8'hA2};                  endcaseendendreg i2c_ack_dev;reg i2c_ack_reg;reg i2c_ack_data;   //i2c_ack_devalways  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begini2c_ack_dev<=1;endelse if((fsm==WR_ACK_DEV||fsm==RD_ACK_DEV1)&&Write_IICclkhigh_mid)begini2c_ack_dev<=Cam_sdata;            endelse i2c_ack_dev<=i2c_ack_dev;            end//i2c_ack_regalways  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begini2c_ack_reg<=1;endelse if((fsm==WR_ACK_REG||fsm==RD_ACK_DEV2)&&Write_IICclkhigh_mid)begini2c_ack_reg<=Cam_sdata;            endelse i2c_ack_reg<=i2c_ack_reg;            end//i2c_ack_dataalways  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begini2c_ack_data<=1;endelse if((fsm==WR_ACK_DATA&&||fsm==RD_ACK_REG)Write_IICclkhigh_mid)begini2c_ack_data<=Cam_sdata;            endelse i2c_ack_data<=i2c_ack_data;            endwire i2c_ack;assign i2c_ack=(i2c_ack_reg||i2c_ack_data||i2c_ack_dev)?0:1;//低电平为接收//delay_cnt  一直计时wire Delaying_10ms=delay_cnt==DELAY_10MS-1;always@(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begindelay_cnt<=0;endelse if(Delaying_10ms ) begindelay_cnt<=0;endelse begindelay_cnt<=delay_cnt+1;endend//time_cnt  cam_iic_clk计时wire I2CClk_period=(time_cnt==CLK_DIV-1);always@(posedge clk or negedge rst_n)beginif(rst_n==1'b0)begintime_cnt<=0;endelse if(I2CClk_period) begintime_cnt<=0;endelse begintime_cnt<=time_cnt+1;endend//bit_cntalways@(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginbit_cnt<=0;endelse if(fsm_cs!=fsm_ns) beginbit_cnt<=0;endelse  beginbit_cnt<=bit_cnt+1;endend//Cam_sclkalways  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginCam_sclk<=0;endelse begincase(fsm_cs)WR_DEVADDR,  WR_ACK_DEV, WR_REGADDR ,WR_ACK_REG ,WR_REGDATA ,RD_DEVADDR1,RD_ACK_DEV1,RD_REGADDR1,RD_ACK_REG  , RD_START2   ,RD_DEVADDR2 ,RD_ACK_DEV2 ,RD_DATA     ,RD_NACK     ,WR_ACK_DATA:if(time_cnt==CLK_DIV/4&&time_cnt==CLK_DIV*3/4)Cam_sclk<=1;elseCam_sclk<=0;default:Cam_sclk<=1;endcase                         end                                 end                                     parameter FSM_IDLE   =5'd0;parameter WR_START   =5'd1;parameter WR_DEVADDR    =5'd2;parameter WR_ACK_DEV    =5'd3;parameter WR_REGADDR    =5'd4;parameter WR_ACK_REG    =5'd5;    parameter WR_REGDATA    =5'd6;parameter WR_ACK_DATA   =5'd7;    parameter WR_STOP       =5'd8;//rdparameter RD_START1      =5'd9 ;parameter RD_DEVADDR1    =5'd10 ;parameter RD_ACK_DEV1    =5'd11 ;parameter RD_REGADDR1    =5'd12 ;parameter RD_ACK_REG    =5'd13 ;parameter RD_STOP1      =5'd14 ;parameter RD_READY      =5'd15 ;   //2准备 parameter RD_START2     =5'd16 ;parameter RD_DEVADDR2   =5'd17 ;    parameter RD_ACK_DEV2   =5'd18 ;parameter RD_DATA       =5'd19 ;        parameter RD_NACK       =5'd20 ;parameter RD_STOP2      =5'd21 ; //fsmreg[5-1:0] fsm_cs;reg[5-1:0] fsm_ns;always  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginfsm_cs<=0;endelse beginfsm_cs<=fsm_ns;endend//zuhealways  @(*)begincase(fsm_cs) beginFSM_IDLE   :if(!Delaying_10ms&&bit_cnt==0) //fsm_ns=fsm_cs;else if(I2CClk_period&& rom_addr<8'd2)beginfsm_ns=RD_START1;end    else if(I2CClk_period&& rom_addr<8'd75)begin //在时钟沿改变,保证时序fsm_ns=WR_START;endelsefsm_ns=fsm_cs;    WR_START   ://1  1 IICclk  start,IIClk下降开始沿if(I2CClk_period)beginfsm_ns=WR_DEVADDR;   endelse beginfsm_ns=fsm_cs;end//读RD_START1   ://9  1 IICclk  start,IIClk下降开始沿if(I2CClk_period)beginfsm_ns=RD_DEVADDR1;   endelse beginfsm_ns=fsm_cs;endRD_DEVADDR1 ://10 设备地址if(I2CClk_period&&bit_cnt==7 )beginfsm_ns=RD_ACK_DEV1;endelse beginfsm_ns=fsm_cs;end  RD_ACK_DEV1 ://11 设备应答if(I2CClk_period)beginfsm_ns=RD_REGADDR1;endelse beginfsm_ns=fsm_cs;end   RD_REGADDR1 ://12 寄存器地址if(I2CClk_period&&bit_cnt==7)beginfsm_ns=RD_ACK_REG;                    endelse beginfsm_ns=fsm_cs;end                RD_ACK_REG ://13 寄存器应答if(I2CClk_period)beginfsm_ns=RD_STOP1;    endelse beginfsm_ns=fsm_cs;end                  RD_STOP1 ://14if(I2CClk_period)beginfsm_ns=RD_STOP1;    endelse beginfsm_ns=fsm_cs;end  RD_READY ://15if(I2CClk_period)beginfsm_ns=RD_START2;    endelse beginfsm_ns=fsm_cs;end  //2stageRD_START2   ://16if(I2CClk_period)beginfsm_ns=RD_DEVADDR2;   endelse beginfsm_ns=fsm_cs;endRD_DEVADDR2 ://17 设备地址if(I2CClk_period&&bit_cnt==7 )beginfsm_ns=RD_ACK_DEV2;endelse beginfsm_ns=fsm_cs;end  RD_ACK_DEV2 ://18 设备应答if(I2CClk_period)beginfsm_ns=RD_DATA;endelse beginfsm_ns=fsm_cs;end RD_DATA ://19 dataif(I2CClk_period&&bit_cnt==7 )beginfsm_ns=RD_NACK;endelse beginfsm_ns=fsm_cs;end  RD_NACK ://20if(I2CClk_period)beginfsm_ns=RD_STOP2;endelse beginfsm_ns=fsm_cs;end RD_STOP2 ://21if(I2CClk_period)beginfsm_ns=FSM_IDLE;endelse beginfsm_ns=fsm_cs;end //wr                WR_DEVADDR ://2 设备地址if(I2CClk_period&&bit_cnt==7 )beginfsm_ns=WR_ACK_DEV;endelse beginfsm_ns=fsm_cs;end                WR_ACK_DEV ://3 设备应答if(I2CClk_period)beginfsm_ns=WR_REGADDR;endelse beginfsm_ns=fsm_cs;end                WR_REGADDR ://4 寄存器地址if(I2CClk_period&&bit_cnt==7)beginfsm_ns=WR_ACK_REG;                    endelse beginfsm_ns=fsm_cs;end                WR_ACK_REG ://5 寄存器应答if(I2CClk_period)beginfsm_ns=WR_REGDATA;    endelse beginfsm_ns=fsm_cs;end                WR_REGDATA ://6 写寄存器数据if(I2CClk_period&&bit_cnt==7)beginfsm_ns=WR_ACK_DATA;   endelse beginfsm_ns=fsm_cs;end                WR_ACK_DATA://7 写寄存器数据应答if(I2CClk_period)beginfsm_ns=WR_STOP;                       endelse beginfsm_ns=fsm_cs;end                WR_STOP    ://8 写停止if(I2CClk_period)beginfsm_ns=FSM_IDLE;   endelse beginfsm_ns=fsm_cs;end      default:fsm_ns=FSM_IDLE;endcaseend//shift_dev_addr 设备地址的移位寄存器wire Write_IICclkhigh_mid=(time_cnt==(CLK_DIV-1)/2);reg [7:0] shift_dev_addr;always  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginshift_dev_addr<=0;endelse begincase(fsm_cs) beginWR_START:shift_dev_addr<=8'h42;WR_DEVADDR:if(Write_IICclkhigh_mid)shift_dev_addr<={shift_dev_addr[6:0],1'b0};else shift_dev_addr<=shift_dev_addr;default:shift_dev_addr<=shift_dev_addr;                    endcaseendend//reg [7:0] shift_reg_addr;reg [7:0] shift_reg_addr;always  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginshift_reg_addr<=0;endelse begincase(fsm_cs) beginWR_START:shift_reg_addr<=rom_data[15:8];WR_REGADDR:if(Write_IICclkhigh_mid)shift_reg_addr<={shift_reg_addr[6:0],1'b0};else shift_reg_addr<=shift_reg_addr;default:shift_reg_addr<=shift_reg_addr;                    endcaseendend//    reg [7:0] shift_regdata;reg [7:0] shift_regdata ;always  @(posedge clk or negedge rst_n)beginif(rst_n==1'b0)beginshift_regdata<=0;endelse begincase(fsm_cs) beginWR_START:shift_regdata<=rom_data[7:0];WR_REGDATA:if(Write_IICclkhigh_mid)shift_regdata<={shift_regdata[6:0],1'b0};else shift_regdata<=shift_regdata;default:shift_regdata<=shift_regdata;                    endcaseendendendmodule

SCCB协议 verilog状态机定时器相关推荐

  1. OV7725学习之SCCB协议(一)

    OV7725摄像头只能作为从机,通过SCCB协议配置内置的172个寄存器.因此首先要了解的就是SCCB总线 1.SCCB协议简述 SCCB协议有两线也有三线,两线为SIO_C与SIO_D,三线为SIO ...

  2. Verilog状态机常见三种写法

    1.1理论   Verilog状态机又称同步状态机(FSM,Finite State Machine),一般又叫状态机,在Verilog描述电路中大部分是同步执行(并行)的,但是很多时候需要处理明显具 ...

  3. SCCB协议介绍与应用和OV7670摄像头的寄存器配置

    SCCB协议简介: 以OV7670的配置传输为例 OV770中,8'h42是写操作ID,8'h43是读地址 从数据传输时序可以看出,其传输的顺序是: 开始位,数据[7:0] ,X位,其中X位为任意,手 ...

  4. SCCB协议理解及实现

    前记:   众说周知,SCCB协议与IIC协议十分相似,不过IIC是PHILIPS的专利,所以OmnVision在IIC的基础上做了点小改动,然后你懂的.SCCB最主要是阉割了IIC的连续读写的功能, ...

  5. SCCB协议学习笔记

    目录 一.前言 二.SCCB是什么 三.SCCB与IIC 四.OG02B10中的SCCB 一.前言 在配置某项目的主摄像头时,由于暂时没有现成的驱动文件,需要先根据平台其他摄像头的驱动格式进行移植,在 ...

  6. FPGA利用SCCB协议配置OV5640摄像头

    FPGA利用SCCB协议配置OV5640摄像头 为什么要配置摄像头 配置代码 测试代码 总结 为什么要配置摄像头 OV5640摄像头有许多工作模式,如可以工作在1080P,720P,480P分辨率的情 ...

  7. 软件SCCB协议学习笔记

    一.SCCB协议简介 SCCB协议是OV公司公布的摄像头用的串行总线协议,相当于一个简易的I2C协议.本文写作意图在于记录使用软件SCCB驱动OV7670模块的配置方法. 二.SCCB协议时序简介(二 ...

  8. SCCB协议与IIC协议的对比

    SCCB协议与IIC协议对比 SCCB协议的作用 两种协议的不同点 两种协议的相同点 参考文档 结束语 SCCB协议的作用 SCCB协议是摄像头中最常用的协议,该SCCB协议可以使用去配置摄像头的寄存 ...

  9. 基于Sata3.0固态硬盘接口协议verilog驱动代码

    基于Sata3.0固态硬盘接口协议verilog驱动代码 Verilog程序源代码. vivado2017.4开发. 可自适应3.0,2.0速率, 可扩展也磁盘矩阵,支持不同数据包读写 带有测速功能, ...

最新文章

  1. 广义线性模型?链接函数?sigmoid和softmax?Logistic处理多分类问题?logistic回归处理超大数据?使用logistic和randomsearch进行组合获取最优参数组合、优缺点
  2. java 单线程改多线程_帮我把单线程的程序改成多线程JAVA,急!
  3. Android Flow遇见Retrofit网络请求实践
  4. QML中的JavaScript表达式
  5. 征战蓝桥 —— 2014年第五届 —— C/C++A组第1题——猜年龄
  6. 清华姚班毕业生不配自信?张昆玮在豆瓣征女友,却被网友群嘲......
  7. CSAPP:Attack lab
  8. python生成范围内随机数_python在一个范围内取随机数的方法是什么
  9. c语言编程计算平分,用C语言编程平均分数
  10. MaterialDesignInXAML WPF入门教程 目录
  11. Visual Studio 2012下载安装方法
  12. 计算机最早应用于( )领域,计算机最早被应用于()领域。
  13. 40余个超好用的在线影视站点
  14. 学生的认知风格类型有哪些_学生认知方式的类型
  15. python——【1】gzip压缩文件
  16. html设计判断闰年,javascript如何判断是否为闰年?
  17. winform 读取用户控件的变量_VS2005winform程序中获取用户控件的值
  18. [vue-router] Named Route ‘Home‘ has a default child route. When navigating to this named route....
  19. vue标准时间改为时间戳_区块链科普005:什么是时间戳?白话通俗讲解时间戳是什么意思?...
  20. c语言求对应学号的总成绩,c语言 求大神编程。定义一个学生结构体,包括学号、姓名、年龄、成绩。1、要求输入五个学生相应的信息,求学生成绩总和。2、输入一个学生学号,把该学生全部信息输出。...

热门文章

  1. 【将xls批量转为xlsx】
  2. 余世维 - 有效沟通
  3. Qt常用却容易忘的功能记录
  4. Web TOP10漏洞之sql注入
  5. 使用QT实现Mjpeg-streamer的客户端,采用单独的线程进行视频图片的获取
  6. 2022“航天宏图杯”遥感影像耕地变化检测第四名方案简介
  7. 两台电脑直接连接共享资料
  8. MySQL重安装失败
  9. 学生认证免费使用pycharm专业版
  10. 算法精品讲解(2)——DP问题入门(适合零基础者,一看就会)