FPGA SCCB

SCCB写操作与IIC写操作一致

SCCB读操作与IIC读操作区别

IIC读操作

SCCB读操作


与IIC代码相比增加了读中点停止状态,当写操作时,SCCB与IIC无异,读操作时在写地址状态后跳转到读中点停止状态,产生上升沿停止位,之后跳转到读开始状态(在此状态中产生起始位)。

module SCCB(Clk                 ,Rst_n               ,Wr                  ,Wr_data             ,Wr_data_vaule       ,Wr_done             ,Word_adrr           ,           //存储单元地址Device_adress       ,           //器件地址Read                ,Rd_data             ,Rd_data_vaule       ,Rd_done             ,Sda                 ,Sccb_clk
);input Clk;input Rst_n;input Wr;input Read;input [7:0] Device_adress; //器件地址input [7:0] Word_adrr; //存储单元地址input [7:0]Wr_data;//写入的数据output reg[7:0]Rd_data;//读出的数据output Wr_data_vaule;//写数据有效标志信号output reg Rd_data_vaule;//读数据有效标志信号inout  Sda;output reg Wr_done;output reg Rd_done;output  Sccb_clk;parameter CLK_FREQUENCY = 50_000_000;parameter Sccb_clk_FREQUENCY = 100_000; //sccb clk时钟频率100KHZlocalparam COUNT_MAX = CLK_FREQUENCY/Sccb_clk_FREQUENCY;//独热码localparam      IDLE      =     10'b0_000_000_001,WR_START  =     10'b0_000_000_010,WR_CTRL   =     10'b0_000_000_100,//写控制 写器件地址WR_ADDRE  =     10'b0_000_001_000,//写地址RDMSTOP   =     10'b0_000_010_000,WR_DATA   =     10'b0_000_100_000,//写数据RD_START  =     10'b0_001_000_000,//读开始RD_CTRL   =     10'b0_010_000_000,//读控制RD_DATA   =     10'b0_100_000_000,//读数据STOP      =     10'b1_000_000_000;reg iic_free_n;//i2c空闲标志位,低电平有效wire [7:0]waddress_data;//器件地址数据写wire [7:0]raddress_data;//器件地址数据读reg [15:0]iic_count; //产生i2C_CLK信号计数寄存器reg clk_high;reg clk_low;reg [7:0]half_clk_cnt;//计数一个状态中高低电平计数器reg [9:0]main_state;//主状态机状态寄存器reg ack;//数据接收方对发送方的响应标志位reg send_en;//控制Sda线输入输出开关reg sda_reg;//sda信号线寄存器reg task_en_n;//任务开始结束控制寄存器reg [7:0]sda_data_out;//sda待输出的数据reg [7:0]sda_data_in;//sda待写入的数据wire be_rd_data_vaule;//读数据有效前寄存器reg w_flag;reg r_flag;reg clk_r;//写/读器件地址8位assign waddress_data = {Device_adress[7:1],1'b0 };assign raddress_data = {Device_adress[7:1],1'b1 };assign  Sccb_clk    =   ((main_state    ==  RD_START)   ||  (main_state ==  RDMSTOP)) ? 1'b1 : clk_r;assign Sda = send_en?sda_reg:1'bz;//iic_free_n状态判断always @(posedge Clk or negedge Rst_n)if(!Rst_n)iic_free_n <= 1'b0;else  if(Wr_done  ||  Rd_done)iic_free_n <= 1'b0;else    if(Wr|Read)iic_free_n <= 1'b1;elseiic_free_n <= iic_free_n;//iic_count计数always @(posedge Clk or negedge Rst_n)if(!Rst_n)iic_count <= 1'b0;else   if(iic_free_n)beginif(iic_count == COUNT_MAX - 1'b1)iic_count <= 16'd0;elseiic_count <= iic_count + 1'b1;endelseiic_count <= 1'b0;//Sccb_clk产生always @(posedge Clk or negedge Rst_n)if(!Rst_n)clk_r <= 1'b1;else if(iic_count == COUNT_MAX >> 1)clk_r <= 1'b0;else if(iic_count == 1'b0)clk_r <= 1'b1;elseclk_r <= clk_r;//标志Sccb_clk高电平 clk_high产生always @(posedge Clk or negedge Rst_n)if(!Rst_n)clk_high <= 1'b0;else if(iic_count == (COUNT_MAX >> 2) )clk_high <= 1'b1;elseclk_high <= 1'b0;//标志Sccb_clk低电平 clk_low产生always @(posedge Clk or negedge Rst_n)if(!Rst_n)clk_low <= 1'b0;else if(iic_count == (COUNT_MAX >> 2 ) + (COUNT_MAX >> 1) )clk_low <= 1'b1;elseclk_low <= 1'b0;//sda串行收发Sccb_clk高低电平计数器always @(posedge Clk or negedge Rst_n)if(!Rst_n)half_clk_cnt <= 1'b0;elseif((main_state == WR_CTRL) || (main_state ==WR_ADDRE)|| (main_state ==WR_DATA) || (main_state ==RD_CTRL) ||(main_state ==RD_DATA))beginif(clk_high | clk_low)beginif(half_clk_cnt == 8'd17)half_clk_cnt <= 8'b0;elsehalf_clk_cnt <= half_clk_cnt + 1'b1;endelsehalf_clk_cnt <= half_clk_cnt;endelsehalf_clk_cnt <= 1'b0;//数据接收方对发送方的响应标志位ACKalways @(posedge Clk or negedge Rst_n)if(!Rst_n)ack <= 1'b0;elseif((half_clk_cnt == 8'd16) && clk_high && (Sda == 1'b0))ack <= 1'b1;elseif((half_clk_cnt == 8'd17 )&& clk_low)ack <= 1'b0;elseack <= ack;//输出串行数据任务task send_eight_data;if(clk_high && (half_clk_cnt == 8'd16))task_en_n <= 1'b1;elseif(half_clk_cnt < 8'd17)beginsda_reg <= sda_data_out[7];if(clk_low)sda_data_out <= {sda_data_out[6:0],1'b0};elsesda_data_out <= sda_data_out;endendtask//输入串行任务task get_eight_data;if(clk_low && (half_clk_cnt == 8'd15))task_en_n <= 1'b1;elseif(half_clk_cnt < 8'd15)beginif(clk_high)sda_data_in <= {sda_data_in[6:0],Sda};elsesda_data_in <= sda_data_in;endendtaskalways @(posedge Clk or negedge Rst_n)if(!Rst_n)beginsda_reg <= 1'b1;Wr_done <= 1'b0;w_flag <= 1'b0;r_flag <= 1'b0;Rd_done <= 1'b0;endelsebegincase(main_state)IDLE :beginsda_reg <= 1'b1;w_flag <= 1'b0;r_flag <= 1'b0;Wr_done <= 1'b0;Rd_done <= 1'b0;if(Wr)beginmain_state <= WR_START;w_flag <= 1'b1;endelse if(Read)beginmain_state <= WR_START;r_flag <= 1'b1;endelsemain_state  <=  IDLE    ;endWR_START:beginif(clk_low)beginmain_state <= WR_CTRL;sda_data_out <= waddress_data;task_en_n <= 1'b0;endelse if(clk_high)beginsda_reg <= 1'b0;main_state <= WR_START;endelsemain_state <= WR_START;endWR_CTRL:beginif(task_en_n == 1'b0)send_eight_data;elseif(ack == 1'b1)beginif(clk_low)beginmain_state <= WR_ADDRE;task_en_n <= 1'b0;sda_data_out <= Word_adrr;endelsemain_state <= WR_CTRL;endelsemain_state <= IDLE;endWR_ADDRE:beginif(task_en_n == 1'b0)send_eight_data;elsebeginif(ack == 1'b1)beginif(clk_low && w_flag)beginmain_state <= WR_DATA;task_en_n <= 1'b0;sda_data_out <= Wr_data;endelseif(clk_low && r_flag)beginmain_state <= RDMSTOP;sda_reg <= 1'b0; //产生上升沿停止位endelsemain_state <= WR_ADDRE;endelsemain_state <= IDLE;endendRDMSTOP:beginif(clk_low)main_state  <=  RD_START    ;elseif(clk_high)beginsda_reg <=  1'b1;           //产生上升沿main_state  <=  RDMSTOP ;endelsemain_state  <=  RDMSTOP ;endWR_DATA: //10_000beginif(task_en_n == 1'b0)send_eight_data;elsebeginif(ack == 1'b1)beginif(clk_low)beginmain_state <= STOP;sda_reg <= 1'b0; //上升沿停止endelsemain_state <= WR_DATA;endelsemain_state <= IDLE;endendRD_START:beginif(clk_low)beginmain_state <= RD_CTRL;task_en_n <= 1'b0;sda_data_out <= raddress_data;endelseif(clk_high)beginmain_state <= RD_START;sda_reg <= 1'b0;//产生下降沿起始位endelsemain_state <= RD_START;endRD_CTRL:beginif(task_en_n == 1'b0)send_eight_data;elsebeginif(ack == 1'b1)beginif(clk_low)beginmain_state <= RD_DATA;task_en_n <= 1'b0;endelsemain_state <= RD_CTRL;endelsemain_state <= IDLE;endendRD_DATA:beginif(task_en_n == 1'b0)get_eight_data;elsebeginsda_reg <= 1'b1; //产生NOack信号表示不读if(clk_low)beginmain_state <= STOP;sda_reg <= 1'b0; //产生上升沿停止位endelsemain_state <= RD_DATA;endendSTOP:beginif(clk_high)beginsda_reg <= 1'b1; //产生上升沿停止态main_state <= IDLE;if(w_flag)Wr_done <=  1'b1;elseif(r_flag)Rd_done <=  1'b1;endelsemain_state <= STOP;enddefault : main_state <= IDLE;endcaseend//控制sda开关闭合关闭always @(*)  //描述组合逻辑电路begincase(main_state)IDLE:send_en = 1'b0;RD_START,WR_START,RDMSTOP,STOP:  //写/读开始 停止位send_en = 1'b1;RD_CTRL,WR_CTRL,WR_ADDRE,WR_DATA:beginif(half_clk_cnt < 8'd16)send_en = 1'b1;elsesend_en = 1'b0;endRD_DATA:beginif(half_clk_cnt < 8'd16)send_en = 1'b0;elsesend_en = 1'b1;enddefault:send_en = 1'b0;endcaseend//写输入有效标志位assign Wr_data_vaule = ((main_state == WR_ADDRE) && (w_flag && clk_low) && (ack == 1'b1));//读数据有效标志位前寄存器assign be_rd_data_vaule = ((main_state == RD_DATA) && (half_clk_cnt == 8'd15) && clk_low);//读数据有效标志位always @(posedge Clk or negedge Rst_n)if(!Rst_n)Rd_data_vaule <= 1'b0;else if(be_rd_data_vaule)Rd_data_vaule <= 1'b1;elseRd_data_vaule <= 1'b0;gai//读出的有效数据always @(posedge Clk or negedge Rst_n)if(!Rst_n)Rd_data <= 8'd0;else if(be_rd_data_vaule)Rd_data <= sda_data_in;elseRd_data <= Rd_data;endmodule

此模块在后续的系統中将会用到,所以在此不做仿真验证。

FPGA SCCB协议相关推荐

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

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

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

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

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

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

  4. SCCB协议学习笔记

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

  5. SCCB协议理解及实现

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

  6. 软件SCCB协议学习笔记

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

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

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

  8. STM32F407--驱动OV2640采集图像数据,通过W5500传输至上位机---第一篇:OV2640简介及SCCB协议

    以下内容皆是个人学习过程中的总结,记录一下整个过程,用于后期复习,如有不对之处,麻烦各位大佬指出~ (喜欢的朋友麻烦点个关注~~~ 后期还会进行持续更新) OV2640概述: OV2640是OV (O ...

  9. 【FPGA】SCCB协议+ov5640摄像头

    以下都引用自原子哥: SCCB(Serial Camera Control Bus,串行摄像头控制总线)是由OV公司定义和发展的三线式串行总线. 该总线控制着OV系列摄像头大部分的功能,包括图像数据格 ...

最新文章

  1. LeetCode:Minimum Depth of Binary Tree,Maximum Depth of Binary Tree
  2. 达梦数据库DM8飞腾版本、芯版本获取地址,最新达梦数据库各国产化版本获取方法,达梦数据库DM8使用手册、产品文档获取
  3. NYOJ 541 最强的战斗力
  4. VTK:创建颜色系列用法实战
  5. [Codevs] 1004 四子连棋
  6. c++突破网关屏蔽_为什么加了屏蔽罩,测试效果反而不好?
  7. 面试官问:来实现一个Promise
  8. 单位矩阵的逆矩阵是它本身吗_矩阵运算、单位矩阵与逆矩阵(二)
  9. 百度SEO万能网页操作编程者 v2.0
  10. [Java] 蓝桥杯 BASIC-6 基础练习 杨辉三角形
  11. 删除oracle 连接进程,如何查看和清除oracle无用的连接进程
  12. des和aes相比较有哪些特点_高精度的交叉滚子轴承与传统轴承相比较,有哪些优点?...
  13. 计算机网络上机指导,计算机网络上机指导书.pdf
  14. MR Shuffle流程 入门
  15. 交叉编译opencv:undefined reference to `png_riffle_palette_neon
  16. 凸优化4:Operations that preserve convexity
  17. 讯飞AIUI语音初体验
  18. 这些设计细节虽小,但俘获了用户的心
  19. Git三板斧【linux环境】
  20. cygwin安装JohnTheRipper 爬坑

热门文章

  1. CentOS是什么服务器系统
  2. Minitab软件下载与培训文档
  3. 医院信息化及计算机知识,医疗行业信息化相关知识
  4. git 开发分支图解
  5. 掌握这些图片无损压缩工具,轻松搞定图片压缩
  6. [附源码]Java计算机毕业设计SSM高校勤工助学管理系统
  7. 浅析深究什么是SOA
  8. Docker搭建ngrok服务器
  9. android textview 楷体,Android自定义控件之自定义Text,画出米字格-FenGKun
  10. spring 不同注解的使用场景