关于IIC通信协议的从机Verilog实现
亟待解决的问题是,从机代码修改。之前使用的从机主要是有两个问题需要解决:一,时序按照标准IIC主机进行修改。二,之前使用的从机代码用的是自己的晶振clk进行驱动,标准的IIC从机应该是根据主机发送过来的SCL进行数据流的控制,不要自己再加时钟。但是起始信号和终止信号,以及向主机发送应答信号和接受主机发送过来的应答信号该如何用SCL进行数据控制呢?如果是在SCL的上升沿就行数据的读取,SCL的下降沿进行SDA数据总线的数据变化,那么起始信号和结束信号如何用可综合的代码实现呢?
之前也一直遇到这个问题,从机如果只有SCL时钟驱动的话,从机中所有信号肯定也是跟随SCL跳变的,包括SDA信号,这样就很难满足iic的时序要求了。一直不知道这块怎么解决,实际IIC项目中是只有SCL这一个时钟吗?忘大神解答
标准的IIC主机和从机,都不会以SCL所为实际时钟去驱动逻辑。SCL和SDA的逻辑都是在另外的较高频率时钟下产生得到的。
原来如此,现在遇到的问题是i2c协议要求的scl和sda都是线与逻辑,但是这个线与逻辑verilog不好定义啊,我现在想把这个scl和sda定义为wand线型,这种线型可用于前仿真,但是不能综合,实际工程应该怎么做这一块呢?
不论主从设备,SCL/SDA的PAD都做成开漏即可,这样在一个master多个slave的应用中就不会出现总线冲突了,不是你理解的那种线与。
那如果前期写代码的时候我想看看仿真功能对不对,但是nc和modlesim都不能仿真这种开漏的器件啊,我要怎么看波形呢?
If IIC used SCL as clock source only, it must use real gate IP cell and design as full custom way
lsss讲的绝对了点,其实可以用scl作为时钟,但是复位信号要比较特殊,要用sda作为时钟来产生scl,opensource上有参考设计的,暂时找不到链接了, 给你贴部分代码
assign sas_resetn = scl | sda_in;
//I2C start
always @(negedge sda_in or negedge sas_resetn)
begin
if(!sas_resetn) i2c_start <= 1'b0;
else if(scl) i2c_start <= 1'b1;
else i2c_start <= 1'b0;
end
//I2C stop
always @(posedge sda_in or negedge sas_resetn)
begin
if(!sas_resetn) i2c_stop <= 1'b0;
else if(scl) i2c_stop <= 1'b1;
else i2c_stop <= 1'b0;
end
再用start和stop产生复位信号
assign comb_reset = i2c_start | i2c_stop ;
就可以用来复位scl做始终所驱动的逻辑了
非常的感谢,我现在对从机的思路还是很不明显。比如,根据标准的IIC协议,在主机对从机进行read操作的时候,需要有第二次的起始信号的检测,如果是这样的话和第一次的起始信号怎么分别呢?用状态机进行从机的描述还是数据流?状态机的话我从机的状态跳转就有些分不清楚,数据流的话我都算用计数器,对SCL的边沿进行计数,然后根据计数器进行数据的收发, 但是面对的问题是write和read计数器怎么弄?read的前几个字节和write是一样的,就是在第二次启动信号之后开始写入read控制字节,然后进行read从机的数据。这个计数器怎么弄?如果是用状态机的话,状态的跳转是基于scl还是基于sda呢?
买夏宇闻的数字电路设计,有IIC设计的RTL设计验证实例,你看看就明白了。
内部需要记录当前状态,比如读需要两次操作,那你第一步发送地址完成了需要用一个寄存器bit记录下当前状态,第二步就按照读数据的操作来了
