最近一直在学习各种接口,今天要讲的是I2C 总线。I2C是是一种简单的同步串行总线。 它只需要两根线即可在连接于总线上的器件之间传送信息。

主器件用于启动总线传送数据,并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件.在总线上主和从、发和收的关系不是恒定的,而取决于此时数据传送方向。如果主机要发送数据给从器件,则主机首先寻址从器件,然后主动发送数据至从器件,最后由主机终止数据传送;如果主机要接收从器件的数据,首先由主器件寻址从器件.然后主机接收从器件发送的数据,最后由主机终止接收过程。在这种情况下.主机负责产生定时时钟和终止数据传送。这也就是主器件对于从器件的两种操作,即写操作和读操作。
I2C总线的写时序如下所示:
读时序如下所示:
下面是verilog实现,用状态机实现主器件对从器件的读写,由于主器件的数据是来自于并行总线,所以写期间会涉及到并串转换,用一个任务实现;读期间会涉及到串并转换也用一个任务实现。这两个任务使用一个子状态机实现,具体见下面的代码:
module i2c(clk,rst,rd,wr,w_data,w_addr,sda,scl,ack);
parameter size_addr=8;
parameter size_data=8;
//主状态机的各个状态
parameter idle=4'd0,wr_ready=4'd1,wr_ctrl=4'd2,wr_addr=4'd3,wr_data=4'd4,rd_ctrl=4'd5,rd_data=4'd6,stop=4'd7,ackn=4'd8;
//启动状态机的各个状态
parameter head_begin=2'b00,head_bit=2'b01,head_end=2'b10;
//停止状态及的各个状态
parameter stop_begin=2'b00,stop_bit=2'b01,stop_end=2'b10;
//并串转换状态机的各个状态
parameter sh8out_begin=4'd0,bit6=4'd1,bit5=4'd2,bit4=4'd3,bit3=4'd4,bit2=4'd5,bit1=4'd6,bit0=4'd7,sh8out_end=4'd8;
//串并转换状态机的各个状态
parameter sh8in_begin=4'd0,bit70=4'd1,bit60=4'd2,bit50=4'd3,bit40=4'd4,bit30=4'd5,bit20=4'd6,bit10=4'd7,bit00=4'd8,sh8in_end=4'd9;
input clk,rst;
input rd,wr;input [size_addr-1:0] w_addr;
input [size_data-1:0] w_data;inout sda;
output scl;
output ack;
reg ack;
reg scl;reg link_sda;//开关信号
reg link_write;
reg link_read;
reg link_start;
reg link_stop;reg start_buf;
reg stop_buf;
reg [size_data-1:0]sh8out_buf;
reg [size_data-1:0]sh8in_buf;
wire [size_data-1:0]r_data;//读出的数据
reg FF;//任务完成标志reg [3:0] mstate;//主状态机寄存器
reg [1:0] start_state;//启动状态寄存器
reg [1:0] stop_state;//结束状态寄存器
reg [3:0] sh8out_state;//并串转换状态寄存器
reg [3:0] sh8in_state;//串并转换状态寄存器wire sda1,sda2,sda3,sda4;
assign sda1=(link_start==1)?1'b1:1'b0;
assign sda2=(link_stop==1) ?1'b1:1'b0;
assign sda3=(link_write==1)?sh8out_buf[7]:1'b0;
assign sda4=sda1|sda2|sda3;
assign sda=(link_sda==1)?sda4:1'bz;
assign r_data=(link_read==1)?sh8in_buf:8'hzz;always@(posedge clk)//scl时钟产生逻辑
begin
if(!rst) scl<=0;
else scl<=~scl;
endalways@(posedge clk)
beginif(!rst)beginmstate<=idle;link_read<=0;link_write<=0;link_sda<=0;link_start<=0;ack<=0;link_stop<=0;FF<=0;endelse begincase(mstate)idle: beginmstate<=wr_ready;start_state<=head_begin;link_write<=0;link_start<=1;start_buf<=1;ack<=0;FF<=0;endwr_ready:beginif(FF==0) headstate;elsebeginmstate<=wr_ctrl;FF<=0;sh8out_state<=sh8out_begin;sh8out_buf<=8'b1100_1011;endendwr_ctrl:beginif(FF==0)sh8out;elsebeginmstate<=wr_addr;FF<=0;sh8out_state<=sh8out_begin;sh8out_buf<=w_addr;endendwr_addr:beginif (FF==0)sh8out;elsebeginFF<=0;if(rd)beginlink_read<=1;mstate<=rd_ctrl;sh8out_buf<=8'b1001010;sh8out_state<=sh8out_begin;endif(wr)beginmstate<=wr_data;sh8out_buf<=w_data;sh8out_state<=sh8out_begin;link_write<=1;endendendwr_data:beginif(FF==0)sh8out;elsebeginmstate<=stop;stop_state<=stop_begin;link_stop<=1;stop_buf<=0;FF<=0;endendrd_ctrl:beginif(FF==0)sh8out;elsebeginFF<=0;mstate<=rd_data;sh8in_state<=sh8in_begin;endendrd_data:beginif(FF==0)sh8in;else beginFF<=0;mstate<=stop;stop_buf<=0;link_stop<=1;stop_state<=stop_begin;endendstop:beginif(FF==0)stopstate;elsebeginack<=1;mstate<=ack;FF<=0;endendackn:beginmstate<=idle;ack<=0;enddefault:mstate<=idle;endcaseend
endtask headstate;
begin
case(start_state)head_begin:beginif(!scl)beginlink_sda<=1;start_state<=head_bit;endelse beginstart_state<=head_begin;endendhead_bit:beginif(scl)beginstart_buf<=0;start_state<=head_end;endelse start_state<=head_bit;endhead_end:if(!scl)beginlink_sda<=0;link_start<=0;FF<=1;start_state<=head_begin;endelse start_state<=head_end;
endcase
end
endtasktask stopstate;
begincase(stop_state)stop_begin:if(!scl)beginlink_sda<=1;stop_state<=stop_bit;endelse stop_state<=stop_begin;stop_bit:beginif(scl)beginstop_state<=stop_end;stop_buf<=1;endelse stop_state<=stop_bit;endstop_end:if(!scl)beginlink_sda<=0;link_stop<=0;FF<=1;stop_state<=stop_begin;endelse stop_state<=stop_end;endcase
end
endtasktask sh8out;
begincase(sh8out_state)sh8out_begin:beginlink_sda<=1;link_write<=1;sh8out_state<=bit6;endbit6:beginif(!scl)beginsh8out_buf<=sh8out_buf<<1;sh8out_state<=bit5;endelse sh8out_state<=bit6;endbit5:beginif(!scl)beginsh8out_buf<=sh8out_buf<<1;sh8out_state<=bit4;endelse sh8out_state<=bit5;endbit4:beginif(!scl)beginsh8out_buf<=sh8out_buf<<1;sh8out_state<=bit3;endelse sh8out_state<=bit4;endbit3:beginif(!scl)beginsh8out_buf<=sh8out_buf<<1;sh8out_state<=bit2;endelse sh8out_state<=bit3;endbit2:beginif(!scl)beginsh8out_buf<=sh8out_buf<<1;sh8out_state<=bit1;endelse sh8out_state<=bit2;endbit1:beginif(!scl)beginsh8out_buf<=sh8out_buf<<1;sh8out_state<=bit0;endelse sh8out_state<=bit1;endbit0:beginif(!scl)beginsh8out_buf<=sh8out_buf<<1;sh8out_state<=sh8out_end;endelse sh8out_state<=bit0;endsh8out_end:beginsh8out_state<=sh8out_begin;FF<=1;link_sda<=0;link_write<=0;endendcase
end
endtasktask sh8in;
begin
case (sh8in_state)
sh8in_begin:beginlink_sda<=1;link_read<=0;sh8in_state<=bit70;end
bit70:beginif(scl)beginsh8in_buf[7]<=sda;sh8in_state<=bit60;endelse sh8in_state<=bit70;end
bit60:beginif(scl)beginsh8in_buf[6]<=sda;sh8in_state<=bit50;endelse sh8in_state<=bit60;end
bit50:beginif(scl)beginsh8in_buf[5]<=sda;sh8in_state<=bit40;endelse sh8in_state<=bit50;end
bit40:beginif(scl)beginsh8in_buf[4]<=sda;sh8in_state<=bit30;endelse sh8in_state<=bit40;end
bit30:beginif(scl)beginsh8in_buf[3]<=sda;sh8in_state<=bit20;endelse sh8in_state<=bit30;end
bit20:beginif(scl)beginsh8in_buf[2]<=sda;sh8in_state<=bit10;endelse sh8in_state<=bit20;end
bit10:beginif(scl)beginsh8in_buf[1]<=sda;sh8in_state<=bit00;endelse sh8in_state<=bit10;end
bit00:beginif(scl)beginsh8in_buf[0]<=sda;sh8in_state<=sh8in_end;endelse sh8in_state<=bit00;end
sh8in_end:beginlink_sda<=0;link_read<=1;FF<=1;sh8in_state<=sh8in_begin;end
default:beginlink_read<=0;sh8in_state<=sh8in_begin;end
endcase
end
endtaskendmodule

I2C总线协议的verilog实现相关推荐

  1. [I2C]I2C总线协议图解

    转自:http://blog.csdn.net/w89436838/article/details/38660631 1  I2C总线物理拓扑结构       I2C 总线在物理连接上非常简单,分别由 ...

  2. 总线全称_一篇文章讲透I2C总线协议

    最近一段时间工作上比较忙,一直没有抽出空来写文章与大家分享,这两天腾出些时间静下心来沉淀一番.看标题大家已经知道了是来总结I2C总线,我相信大家或多或少的都接触过I2C总线,这篇文章我们就由浅入深的仔 ...

  3. TM1637芯片使用(I2C总线协议学习),含完整程序

    目录 1.TM1637芯片(大自然的搬运工) 芯片介绍 引脚图 时序图 其他关键 管脚功能 命令格式 封装 2. 51单片机程序编写 I2C_START(): I2C_WR(): I2C_ACK(): ...

  4. SPI与I2C总线协议

    目录: 一.SPI总线协议 1.什么是SPI 2.技术性能 3.接口定义与硬件连接 4.内部结构 5.传输时序 6.高速SPI 1)硬件电路   2)1MHz SPI传输问题 二.I2C总线协议 1. ...

  5. i2c总线协议的工作原理详解

    一.概述 1.I2C总线只有两根双向信号线.一根是数据线SDA,另一根是时钟线SCL. SCL:上升沿将数据输入到每个EEPROM器件中:下降沿驱动EEPROM器件输出数据.(边沿触发) SDA:双向 ...

  6. I2C总线协议和控制器解析

    I2C总线协议 1.1 I2C总线知识 1.1.1  I2C总线物理拓扑结构       I2C 总线在物理连接上非常简单,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成.通信原理是通 ...

  7. IIC 总线协议(Verilog)

    IIC (Inter - Integrated Circuit BUS) 集成电路总线,它是一种串行通信总线,多使用主从架构.IIC 接口共有两条总线线路,即 SCL(串行时钟线).SDA(串行数据线 ...

  8. 浅谈 IIC I2C 总线协议

    简介 IIC(也称I2C或I2C)总线是Philips公司开发的一种简单.双向二线制同步串行总线,是Inter-Integrated Circuit的缩写. IIC只用两条双向线,一条SDA(Seri ...

  9. 对I2C总线协议的一些理解

    1.无论读与写,都是在时钟线为低时把数据送到数据总线上,在高时采样数据,把数据锁存到内部,所以读之前先把时钟线拉低,做好准备(数据线为高表示释放数据线),为接下来读数据做好准备.也就是时钟信号为低时, ...

最新文章

  1. python中约瑟夫环程序_Python实现约瑟夫环问题的方法
  2. 基于Java语言构建区块链(一)—— 基本原型
  3. canal能监控多个mysql_learning-mysql-canal
  4. 【springmvc+mybatis项目实战】杰信商贸-6.重点知识回顾
  5. linux smb 启动失败,[已解决]windows能看到smb,但是打不开
  6. 路径中有中文怎么解决_时序路径分析
  7. 【操作系统】常见进程调度算法特点总结比较
  8. 变态的儿童国学教育与孔子真正的教育之道
  9. 在fedora20下面手动为自己的安装程序创建桌面图标
  10. 计蒜客——学生成绩查找系统
  11. Cesium:加载本地高程/地形数据
  12. 最好用的php编程软件_php 编程软件 php编程软件有哪些
  13. VS插件——Javascript parser
  14. 电磁场理论-麦克斯韦方程组
  15. 【DBN预测】基于粒子群算法优化DBN深度置信网络实现数据预测matlab代码
  16. 请不要 “妖魔化” 外包
  17. VBScript运行时错误处理
  18. 华米自有品牌销量过百万,去小米化或进一步加强
  19. MFC实现弹出模态对话框和非模态对话框(基于对话框)
  20. 数据库的升序降序排列

热门文章

  1. OPC读写Kepware(C++)
  2. 部署k8s 1.18版本及图形管理工具kuboard(十四)
  3. 谈谈无穷小微积分对我国微积分教学改革的影响
  4. 基于google pIxel刷机并且获取root教程
  5. 【转载】男性穿衣常识
  6. 博客摘录「 项目启动会ppt_“项目启动会”必须要汇报的18个要素(附PPT模板)| 推荐」2023年5月26日转载自:http://t.csdn.cn/z5xg8
  7. 大数据分析案例-基于随机森林算法构建人口普查分析模型
  8. 【毕业设计/Matlab系列】基于MATLAB语言的实时变声器系统
  9. get和post的差别
  10. 告别Anaconda: Pycharm最简单的通过pip下载python包的方法(没有之一)