// Clock Settingparameter CLK_Freq = 50000000; //??? 50 MHzparameter I2C_Freq = 80000; //??? 40 KHz 25Usparameter I2C_Thd = 200000; //??? 5Us 200 KHzalways@(posedge iCLK or negedge iRST_N)begin // 5000 times divide frequence of iCLK if (!iRST_N) begin mI2C_CLK_DIV <= 0; mI2C_CLKO <= 0; mI2C_CTRL_CLK <= 0; end else if( mI2C_CLK_DIV < (CLK_Freq/I2C_Freq)) begin mI2C_CLK_DIV <= mI2C_CLK_DIV+1; if ((!mI2C_CTRL_CLK)&(mI2C_CLK_DIV < ((CLK_Freq/I2C_Freq)- (CLK_Freq/I2C_Thd))) ) mI2C_CLKO <= 0; else mI2C_CLKO <= 1; end else begin mI2C_CLK_DIV <= 0; mI2C_CTRL_CLK <= ~mI2C_CTRL_CLK; endendendmodule[url=][/url]
testbench程序如下:
[url=][/url]
module I2C_Clock_tb ; //parameter I2C_Thd = 200000 ;//parameter I2C_Freq = 80000 ;//parameter CLK_Freq = 50000000 ; wire mI2C_CTRL_CLK ; wire [15:0] mI2C_CLK_DIV ; wire mI2C_CLKO ; reg iRST_N ; reg iCLK ; I2C_Clock //#( I2C_Thd , I2C_Freq , CLK_Freq ) DUT ( .mI2C_CTRL_CLK (mI2C_CTRL_CLK ) , .mI2C_CLK_DIV (mI2C_CLK_DIV ) , .mI2C_CLKO (mI2C_CLKO ) , .iRST_N (iRST_N ) , .iCLK (iCLK ) ); initial begin iRST_N = 0; iCLK = 0; #50 iRST_N = 1;endalwaysbegin #50 iCLK = ~iCLK; endendmodule[url=][/url]
modelsim仿真的波形如下:
图4 IIC内部时钟仿真图
经过计算,IIC内部所用的时钟频率为40KHz。
2、IIC整体仿真 相关程序在附件中。下面是仿真波形。
图5 IIC整体仿真波形图
结合上述仿真波形图和程序可以看出:
起始位:SCLK为高电平时,SDAT由高到低,指示IIC总线传输数据的开始;
之后,传送一个字节的数据,即4A,为从机的地址,随后,跟了一个高电平,为应答位;
之后,传送一个字节的数据,即01,为从机地址的子地址,随后,跟了一个高电平,为应答位;
之后,传送一个字节的数据,即08,为上面子地址寄存器配置的数据,随后,跟了一个高电平,为应答位;
最后,为停止位,SCLK为高电平时,SDAT由低到高,指示该次IIC总线传输数据的结束。
由仿真结果可知,当传送完一个字节后,SDAT为一个脉冲的高电平,而不是从器件先将SDAT拉低再拉高,这样也是可以的。 |