说明:i2c乔布斯。有这么多的事情在网上参考。

时刻:2014年5一个月6周二星期



1.问题叙述性说明:

正如图。已知的时钟clk为100k,rst为复位信号。上升沿有效,基于Verilog HDL或者VHDL语言,将A器件内的六个8位数据,依照I2C协议规格送入总线sda。并产生对应的串行时钟scl.

要求(1):写出完整代码;

要求(2):给出仿真波形图。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMjM3MzAyMA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

1.1仿真波形图

在波形图中,黄色波形表示sda。红色波形data是为了方便观察sda所传输的数据而设立的。所要传输的6个数据分别为:8’h98, 8’h01, 8’h41, 8’hf0,8’h60, 8’h90。器件地址是自定义的7'b1011010(由于I2C器件的地址是7位。作业给出的地址是8位)。

发送数据的放大波形图例如以下(以发送数据8’h41为例):

1.2完整代码

代码採用Modelsim仿真,编写了Verilog程序和testbench激励文件。

Verilog程序:

modulei2c (scl, sda, clk, rst);
inout scl;
inout sda;
input clk;
input rst; reg i;
reg rscl = 1'bz;
reg rsda = 1'bz;
reg[7:0] temp, data; reg[6:0] slave_addr_reg= 7'b1011010; //slave addr
parameter DATA0 = 8'h98;
parameter DATA1 = 8'h01;
parameter DATA2 = 8'h41;
parameter DATA3 = 8'hF0;
parameter DATA4 = 8'h60;
parameter DATA5 = 8'h80; assign scl = rscl;
assign sda = rsda; task start;
begin
@(posedge clk);
rsda = 1;
rscl = 1;
@(posedge clk);
rsda = 0;
@(posedge clk);
rscl = 0;
end
endtask task stop;
begin
rsda = 0;
@(posedge clk);
rscl = 1;
@(posedge clk);
rsda = 1;
@(posedge clk);
rscl = 1'bz;
@(posedge clk);
@(posedge clk);
rsda = 1'bz;
end
endtask task rw_slave_addr(input[6:0] slave_addr,input rw); begin
repeat(7) begin
@(posedge clk);
rsda = slave_addr[6];
slave_addr={slave_addr[5:0],slave_addr[6]};
temp = temp << 1;
temp[0] = rsda;
@(posedge clk);
rscl = 1;
@(posedge clk);
@(posedge clk);
rscl = 0;
end
data = temp;
@(posedge clk);
rsda = rw;
@(posedge clk);
rscl = 1;
@(posedge clk);
@(posedge clk);
rscl = 0;
@(posedge clk);
rsda = 1'bz;
@(posedge clk);
rscl = 1;
if(sda != 0) $display("ACKerror at time: %t", $time);
@(posedge clk);
@(posedge clk);
rscl = 0;
@(posedge clk);
end
endtask task send_byte(input [7:0] send_byte);begin
repeat(8) begin
rsda = send_byte[7];
send_byte={send_byte[6:0],send_byte[7]};
temp = temp << 1;
temp[0] = rsda;
@(posedge clk);
rscl = 1;
@(posedge clk);
@(posedge clk);
rscl = 0;
@(posedge clk);
end
data = temp;
rsda = 1'bz;
@(posedge clk);
rscl = 1'b1;
if(sda != 0) $display("ACKerror at time: %t", $time);
@(posedge clk);
@(posedge clk);
rscl = 0;
@(posedge clk);
end
endtask always@(posedge clk or negedge rst) begin
if(!rst) begin
rscl = 1'bz;
rsda = 1'bz;
end
else begin
start;
rw_slave_addr(slave_addr_reg,0);
send_byte(DATA0);
send_byte(DATA1);
send_byte(DATA2);
send_byte(DATA3);
send_byte(DATA4);
send_byte(DATA5);
stop;
#20;
$stop;
end
end endmodule

testbench程序:

`timescale1us/1us

modulei2c_test;
wire scl, sda;
reg clk, rst; initial begin
clk=0;
forever #1 clk=~clk;
end initial begin
rst=0;
#20 rst=1;
end i2c u1(scl, sda, clk);
endmodule

2.I2C概述

经常使用的串行扩展总线有:I2C(InterICBUS)总线、单总线(1-WIREBUS)、SPI(SerialPeripheralInterface)总线及Microwire/PLUS等。

I2C总线是PHLIPS公司推出的一种串行总线。是具备多主机系统所需的包含总线裁决和高低速器件同步功能的高性能串行总线。

I2C总线仅仅有两根双向信号线。一根是数据线SDA,还有一根是时钟线SCL。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMjM3MzAyMA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

I2C总线通过上拉电阻接正电源。当总线空暇时,两根线均为高电平。连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系。

每一个接到I2C总线上的器件都有唯一的地址。

主机与其他器件间的数据传送能够是由主机发送数据到其他器件,这时主机即为发送器。由总线上接收数据的器件则为接收器。

3.I2C总线的数据传送

3.1数据位的有效性规定

I2C总线进行数据传送时。时钟信号为高电平期间,数据线上的数据必须保持稳定,仅仅有在时钟线上的信号为低电平期间。数据线上的高电平或低电平状态才同意变化。

3.2起始和终止信号

SCL线为高电平期间。SDA线由高电平向低电平的变化表示起始信号;SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。

起始和终止信号都是由主机发出的,在起始信号产生后,总线就处于被占用的状态;在终止信号产生后,总线就处于空暇状态。

连接到I2C总线上的器件。若具有I2C总线的硬件接口,则非常easy检測到起始和终止信号。对于不具备I2C总线硬件接口的有些单片机来说。为了检測起始和终止信号。必须保证在每一个时钟周期内对数据线SDA採样两次。

接收器件收到一个完整的数据字节后,有可能须要完毕一些其他工作。如处理内部中断服务等。可能无法立马接收下一个字节。这时接收器件能够将SCL线拉成低电平,从而使主机处于等待状态。

直到接收器件准备好接收下一个字节时。再释放SCL线使之为高电平,从而使数据传送能够继续进行。

3.3数据传送格式

(1)字节传送与应答

每个字节必须保证是8位长度。数据传送时。先传送最高位(MSB),每个被传送的字节后面都必须尾随一位应答位(即一帧共同拥有9位)。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMjM3MzAyMA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

因为某种原因从机不正确主机寻址信号应答时(如从机正在进行实时性的处理工作而无法接收总线上的数据),它必须将数据线置于高电平。而由主机产生一个终止信号以结束总线的数据传送。

假设从机对主机进行了应答。但在数据传送一段时间后无法继续接收很多其它的数据时,从机能够通过对无法接收的第一个数据字节的“非应答”通知主机。主机则应发出终止信号以结束数据的继续传送。

当主机接收数据时。它收到最后一个数据字节后。必须向从机发出一个结束传送的信号。这个信号是由对从机的“非应答”来实现的。

然后,从机释放SDA线。以同意主机产生终止信号。

(2)数据帧格式

I2C总线上传送的数据信号是广义的,既包含地址信号,又包含真正的数据信号。

在起始信号后必须传送一个从机的地址(7位),第8位是数据的传送方向位(R/),用“0”表示主机发送数据(T),“1”表示主机接收数据(R)。

每次数据传送总是由主机产生的终止信号结束。

可是。若主机希望继续占用总线进行新的数据传送。则能够不产生终止信号,立即再次发出起始信号对还有一从机进行寻址。

在总线的一次数据传送过程中,能够有下面几种组合方式:

a、主机向从机发送数据,数据传送方向在整个传送过程中不变:

b、主机在第一个字节后,马上由从机读数据

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMjM3MzAyMA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

c、在传送过程中,当须要改变传送方向时,起始信号和从机地址都被反复产生一次,但两次读/写方向位正好反相。

版权声明:本文博主原创文章,博客,未经同意不得转载。

Verilog之i2c合约的更多相关文章

  1. i2c状态机方法设计-verilog

    2010-09-05 21:04:00 verilog语言基础学的差不多了.接着就是看看华为的语言编写规范.状态机设计方法是fpga的重要设计方法.所以我要记上一笔. 只要会FSM方法,用fpga编写 ...

  2. I2C控制器的Verilog建模之三(完结版)

    前言:终于到了测试篇,不过悲剧了一下.按照之前<二>里面的思路,在顶层用一个复用器驱动读写独立模块的I2C总线确实失败.虽然综合过去了,不过警告里已经说明:底层的2个原本是inout三态口 ...

  3. I2C控制器的Verilog建模之二

    前言:接着上一篇的I2C写操作,今天要实现一个I2C的读操作.虽然在ADV7181B配置内部寄存器时没有必要使用到读操作,但是为了进一步确认寄存器是否在I2C写模块下被正确配置,这一步是必不可少的. ...

  4. I2C控制器的Verilog建模之一

    前言:之前申请了ADI公司的一款ADV7181CBSTZ的视频解码芯片,正好原装DE2板子安的是同系列的ADV7181BBSTZ.虽然都是ADV7181的宗出,但是寄存器配置等等还是有些诧异,引脚也不 ...

  5. I2C Verilog的实现(二)

    1. 起始结束信号的判断 //--------------------------------------------- //start,stop condition judgement //---- ...

  6. I2C Verilog的实现(一)

    <span style="font-size:14px;">`timescale 1ns / 1ps module test( sda ); reg scl; inou ...

  7. verilog中24LC04B iic(i2c)读写通信设计步骤,以及程序常见写法错误。

    板子使用的是黑金的是xilinx spartan-6开发板,首先准备一份24LC04B芯片资料,读懂资料后列出关键参数. 如下: 1.空闲状态为SDA和SCL都为高电平 2.开始状态为:保持SCL,S ...

  8. 学习笔记一:I2C协议学习和Verilog实现

    ////////////////////////////////////////////////// //clk = 20 MHz ,一个周期50ns //sck = 100 kHz (scl) ,一 ...

  9. I2C三态门Verilog

    http://www.blogbus.com/uyarotxb-logs/206932748.html     inout作为输出端口时三态门为选通状态,inout作为输入端口时三态门为高阻态,可通过 ...

随机推荐

  1. 【转】Multithreaded Python Tutorial with the “Threadworms” Demo

    The code for this tutorial can be downloaded here: threadworms.py or from GitHub. This code works wi ...

  2. SQL Server 2008 R2 的版本和组件

    SQL Server 2008 R2 的版本和组件 SQL Server 2008 R2   其他版本 SQL Server 2008 SQL Server 2005 SQL Server 2012 ...

  3. C/C++中的++a和a++

    代码: #include <iostream> #include <cstdio> using namespace std; int main(){ ; (++a)+=a; / ...

  4. 【C++学习之路】派生类的构造函数(三)

    三.多层继承的派生类 1.多层继承的派生类只需在构造函数的初始化列表中写出直接基类的构造函数即可 class student { public: student(int n, string nam) ...

  5. showModalDialog-父窗体子窗体

    showModalDialog使用例子,父窗口向子窗口传递值,子窗口设置父窗口的值,子窗口关闭的时候返回值到父窗口. farther.html --------------------------- ...

  6. codevs 1068 乌龟棋

    题目描述 Description 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一 的起点,第N格是终点,游戏要求玩家控制 ...

  7. uva 10032 Problem F: Tug of War

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

  8. Gridview将某列内容和标题隐藏起来

    protected void gvInfo_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.Row.RowType == Dat ...

  9. Activity的四种状态

    Running状态:一个新的Activity启动入栈后,它在屏幕最前端,处于栈的最顶端,此时它处于可见并可和用户交互的激活状态.Paused状态:当Activity被另一个透明或者Dialog样式的A ...

  10. ruby文档

    http://www.ruby-doc.org/http://rubyonrails.org/https://www.ruby-lang.org/zh_cn/downloads/http://ruby ...