MyFPGA Forum

 找回密码
 注册
搜索
查看: 13386|回复: 10
打印 上一主题 下一主题

de2 demo 中I2C_Controller 问题

[复制链接]
跳转到指定楼层
1#
发表于 2009-7-1 20:22:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
de2 demo 中I2C_Controller 问题
最近在看友晶公司的demo,其中里面好几个模块都用到了I2C_Controller.v文件,对其中的一些地方存在疑问。
code
-------------------------------------
module I2C_Controller (
        CLOCK,
        I2C_SCLK,//I2C CLOCK
         I2C_SDAT,//I2C DATA
        I2C_DATA,//DATA:[SLAVE_ADDR,SUB_ADDR,DATA]
        GO,      //GO transfor
        END,     //END transfor
        W_R,     //W_R
        ACK,      //ACK
        RESET,
        //TEST
        SD_COUNTER,
        SDO
);
        input  CLOCK;
        input  [23:0]I2C_DATA;        
        input  GO;
        input  RESET;        
        input  W_R;
         inout  I2C_SDAT;        
        output I2C_SCLK;
        output END;        
        output ACK;

//TEST
        output [5:0] SD_COUNTER;
        output SDO;


reg SDO;
reg SCLK;
reg END;
reg [23:0]SD;
reg [5:0]SD_COUNTER;

wire I2C_SCLK=SCLK | ( ((SD_COUNTER >= 4) & (SD_COUNTER <=30))? ~CLOCK :0 );
wire I2C_SDAT=SDO?1'bz:0 ;

reg ACK1,ACK2,ACK3;
wire ACK=ACK1 | ACK2 |ACK3;

//--I2C COUNTER
always @(negedge RESET or posedge CLOCK ) begin
if (!RESET) SD_COUNTER=6'b111111;
else begin
if (GO==0)
        SD_COUNTER=0;
        else
        if (SD_COUNTER < 6'b111111) SD_COUNTER=SD_COUNTER+1;        
end
end
//----

always @(negedge RESET or  posedge CLOCK ) begin
if (!RESET) begin SCLK=1;SDO=1; ACK1=0;ACK2=0;ACK3=0; END=1; end
else
case (SD_COUNTER)
        6'd0  : begin ACK1=0 ;ACK2=0 ;ACK3=0 ; END=0; SDO=1; SCLK=1;end
        //start
        6'd1  : begin SD=I2C_DATA;SDO=0;end
        6'd2  : SCLK=0;
        //SLAVE ADDR
        6'd3  : SDO=SD[23];
        6'd4  : SDO=SD[22];
        6'd5  : SDO=SD[21];
        6'd6  : SDO=SD[20];
        6'd7  : SDO=SD[19];
        6'd8  : SDO=SD[18];
        6'd9  : SDO=SD[17];
        6'd10 : SDO=SD[16];        
        6'd11 : SDO=1'b1;//ACK

        //SUB ADDR
        6'd12  : begin SDO=SD[15]; ACK1=I2C_SDAT; end
        6'd13  : SDO=SD[14];
        6'd14  : SDO=SD[13];
        6'd15  : SDO=SD[12];
        6'd16  : SDO=SD[11];
        6'd17  : SDO=SD[10];
        6'd18  : SDO=SD[9];
        6'd19  : SDO=SD[8];
        6'd20  : SDO=1'b1;//ACK

        //DATA
        6'd21  : begin SDO=SD[7]; ACK2=I2C_SDAT; end
        6'd22  : SDO=SD[6];
        6'd23  : SDO=SD[5];
        6'd24  : SDO=SD[4];
        6'd25  : SDO=SD[3];
        6'd26  : SDO=SD[2];
        6'd27  : SDO=SD[1];
        6'd28  : SDO=SD[0];
        6'd29  : SDO=1'b1;//ACK

        
        //stop
    6'd30 : begin SDO=1'b0;        SCLK=1'b0; ACK3=I2C_SDAT; end        
    6'd31 : SCLK=1'b1;
    6'd32 : begin SDO=1'b1; END=1; end

endcase
end



endmodule
---------------------------------------------
其中wire I2C_SDAT=SDO?1'bz:0 ; 为什么SDO为1的时候要将I2C_SDAT置为高阻?
2#
发表于 2009-7-6 15:37:47 | 只看该作者
I2C_DATA為inout port, 一般為了怕in和out相衝, 外面都會有保護電路的設計,
在 I2C 這邊是沒有用到的訊號都會 pull high來保護電路不相衝.
所以當I2C_DATA沒有用到時會用high impedence外,
要 output 為1時也可以送high impedence, 讓外部電路決定值(因為外部電路會 pull high),
只有 output 為0時才需要特別指定...
希望這樣簡單的解釋可以幫助您
3#
 楼主| 发表于 2009-7-10 14:50:46 | 只看该作者
2# Pocahontas

感谢您的热心帮助。
4#
发表于 2009-7-11 16:38:19 | 只看该作者
de2 demo 中I2C_Controller 问题
最近在看友晶公司的demo,其中里面好几个模块都用到了_Controller.v文件,对其中的一些地方存在疑问。
code
-------------------------------- ...
pkuzz 发表于 2009-7-1 20:22

你好,我也打算用I2C通讯,请问可以把你有关程序和资料发给我学习一下吗,我的邮箱是acguokailin@163.com,谢谢
5#
发表于 2009-7-14 15:45:10 | 只看该作者
建議您用I2C當關鍵字去任何搜尋引擎查一下,當中就會有許多I2C的資料以及規範,至於如何運用就要看個別IC的datasheet對於各個參數的定義。
6#
发表于 2010-10-9 11:36:46 | 只看该作者
这个历程中还有两个地方不懂
一、状态机只到32,为什么计数是SD_COUNTER < 6'b111111 (十进制63)。。
二、ACK问题。为什么每次传输8位数据后有一个SDO=1'b1;//ACK。。。datasheet上的协议似乎没说啊。。还有这一句 6'd12  : begin SDO=SD[15]; ACK1=I2C_SDAT; end       ACK1,ACK2取的是哪个数呢,这个时序没搞清楚。。。

困扰小弟很久,请高手指教!!
7#
发表于 2010-10-13 10:32:17 | 只看该作者
对于你的第一个问题,我也还没看明白,先回答第二个问题吧。







首先,从代码上看这个代码应该是i2c主机模式的代码。你再认真看一下datasheet,i2c中,主机向从机发送任何数据(包括地址),从机在接受到之后都要有响应,而这个响应就是在数据最后一位结束后产生的。







现在解释一下响应的作用,主机在向从机发送数据后,如果从机没有返回任何信息的话,主机是不知道从机有没有接受到刚才发送的这个数据,因此为了让主机知道从机到底有没有接收到,就用这个响应信号来通知主机。即当主机发送完地址,从机在接收到这个地址(并且确认是自己的从机地址之后),从机就要发送一个响应信号来通知主机让主机知道从机已经接收到了(如果没有接收到,从机就不会发送这个响应信号)。同样的,主机发送完一个8位数据,从机在接收到之后也会有响应信号。







接下来再看这段代码,wire I2C_SDAT=SDO?1'bz:0 ;在结合源程序中,每次传输8位数据后有一个SDO=1'b1;可以知道当sdo等于一时,i2c_sdat为高阻态,这个时候i2c_sdat的值就等于输入值(因为i2c-sdat是I/O口,当i2c-sdat为高阻态时,它就是一个输入口),也就是从机发送过来的数值。然后再结合这句 6'd12  : begin SDO=SD[15]; ACK1=I2C_SDAT; end   ,于是ack1就等于之前一个周期的i2c_sdat的输入值,也就是状态‘ 11’6'd11 : SDO=1'b1;时从机发送过来的值,而这个从机发送过来的值是在主机发送完地址后发送的,也就是从机对地址的一个响应信号。于是ack2,ack3可以以此类推。
8#
发表于 2010-10-13 10:32:53 | 只看该作者
这个历程中还有两个地方不懂
一、状态机只到32,为什么计数是SD_COUNTER < 6'b111111 (十进制63)。。
二 ...
shinexqq 发表于 2010-10-9 11:36


对于你的第一个问题,我也还没看明白,先回答第二个问题吧。

首先,从代码上看这个代码应该是i2c主机模式的代码。你再认真看一下datasheet,i2c中,主机向从机发送任何数据(包括地址),从机在接受到之后都要有响应,而这个响应就是在数据最后一位结束后产生的。

现在解释一下响应的作用,主机在向从机发送数据后,如果从机没有返回任何信息的话,主机是不知道从机有没有接受到刚才发送的这个数据,因此为了让主机知道从机到底有没有接收到,就用这个响应信号来通知主机。即当主机发送完地址,从机在接收到这个地址(并且确认是自己的从机地址之后),从机就要发送一个响应信号来通知主机让主机知道从机已经接收到了(如果没有接收到,从机就不会发送这个响应信号)。同样的,主机发送完一个8位数据,从机在接收到之后也会有响应信号。

接下来再看这段代码,wire I2C_SDAT=SDO?1'bz:0 ;在结合源程序中,每次传输8位数据后有一个SDO=1'b1;可以知道当sdo等于一时,i2c_sdat为高阻态,这个时候i2c_sdat的值就等于输入值(因为i2c-sdat是I/O口,当i2c-sdat为高阻态时,它就是一个输入口),也就是从机发送过来的数值。然后再结合这句 6'd12  : begin SDO=SD[15]; ACK1=I2C_SDAT; end   ,于是ack1就等于之前一个周期的i2c_sdat的输入值,也就是状态‘ 11’6'd11 : SDO=1'b1;时从机发送过来的值,而这个从机发送过来的值是在主机发送完地址后发送的,也就是从机对地址的一个响应信号。于是ack2,ack3可以以此类推。
9#
发表于 2011-1-11 15:27:42 | 只看该作者
第一个问题是不是可以这样理解:
stop信号:需要I2C_SDAT和I2C_SCLK满足stop信号的要求,锁存它们为高。
然后在配置下一个寄存器时,再重新start.
10#
发表于 2011-4-19 10:26:44 | 只看该作者
因为在板子的电路这个端口是有上拉电阻的,在高阻态,器件感受的就是高电平。
11#
发表于 2011-5-25 01:52:41 | 只看该作者
借鉴借鉴~
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|MyFPGA

GMT+8, 2024-4-20 08:05 , Processed in 0.054276 second(s), 15 queries .

Powered by Discuz! X3

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表